diff options
35 files changed, 438 insertions, 110 deletions
diff --git a/Doc/c-api/arg.rst b/Doc/c-api/arg.rst index 5dc28af..144a365 100644 --- a/Doc/c-api/arg.rst +++ b/Doc/c-api/arg.rst @@ -136,8 +136,9 @@ variable(s) whose address should be passed. them. Instead, the implementation assumes that the string object uses the encoding passed in as parameter. -``b`` (integer) [char] - Convert a Python integer to a tiny int, stored in a C :ctype:`char`. +``b`` (integer) [unsigned char] + Convert a nonnegative Python integer to an unsigned tiny int, stored in a C + :ctype:`unsigned char`. ``B`` (integer) [unsigned char] Convert a Python integer to a tiny int without overflow checking, stored in a C @@ -533,3 +534,8 @@ and the following format units are left untouched. If there is an error in the format string, the :exc:`SystemError` exception is set and *NULL* returned. + +.. cfunction:: PyObject* Py_VaBuildValue(const char *format, va_list vargs) + + Identical to :cfunc:`Py_BuildValue`, except that it accepts a va_list + rather than a variable number of arguments. diff --git a/Doc/c-api/exceptions.rst b/Doc/c-api/exceptions.rst index 2998521..536b123 100644 --- a/Doc/c-api/exceptions.rst +++ b/Doc/c-api/exceptions.rst @@ -73,11 +73,10 @@ is a separate error indicator for each thread. .. cfunction:: int PyErr_GivenExceptionMatches(PyObject *given, PyObject *exc) - Return true if the *given* exception matches the exception in *exc*. If *exc* - is a class object, this also returns true when *given* is an instance of a - subclass. If *exc* is a tuple, all exceptions in the tuple (and recursively in - subtuples) are searched for a match. If *given* is *NULL*, a memory access - violation will occur. + Return true if the *given* exception matches the exception in *exc*. If + *exc* is a class object, this also returns true when *given* is an instance + of a subclass. If *exc* is a tuple, all exceptions in the tuple (and + recursively in subtuples) are searched for a match. .. cfunction:: void PyErr_NormalizeException(PyObject**exc, PyObject**val, PyObject**tb) diff --git a/Doc/distutils/apiref.rst b/Doc/distutils/apiref.rst index a8f7461..4a0d354 100644 --- a/Doc/distutils/apiref.rst +++ b/Doc/distutils/apiref.rst @@ -88,9 +88,9 @@ setup script). Indirectly provides the :class:`distutils.dist.Distribution` and | *options* | default options for the setup | a string | | | script | | +--------------------+--------------------------------+-------------------------------------------------------------+ - | *license* | The license for the package | | + | *license* | The license for the package | a string | +--------------------+--------------------------------+-------------------------------------------------------------+ - | *keywords* | Descriptive meta-data. See | | + | *keywords* | Descriptive meta-data, see | | | | :pep:`314` | | +--------------------+--------------------------------+-------------------------------------------------------------+ | *platforms* | | | @@ -98,6 +98,13 @@ setup script). Indirectly provides the :class:`distutils.dist.Distribution` and | *cmdclass* | A mapping of command names to | a dictionary | | | :class:`Command` subclasses | | +--------------------+--------------------------------+-------------------------------------------------------------+ + | *data_files* | A list of data files to | a list | + | | install | | + +--------------------+--------------------------------+-------------------------------------------------------------+ + | *package_dir* | A mapping of package to | a dictionary | + | | directory names | | + +--------------------+--------------------------------+-------------------------------------------------------------+ + .. function:: run_setup(script_name[, script_args=None, stop_after='run']) @@ -1100,6 +1107,24 @@ other utility module. For non-POSIX platforms, currently just returns ``sys.platform``. + For MacOS X systems the OS version reflects the minimal version on which + binaries will run (that is, the value of ``MACOSX_DEPLOYMENT_TARGET`` + during the build of Python), not the OS version of the current system. + + For universal binary builds on MacOS X the architecture value reflects + the univeral binary status instead of the architecture of the current + processor. For 32-bit universal binaries the architecture is ``fat``, + for 64-bit universal binaries the architecture is ``fat64``, and + for 4-way universal binaries the architecture is ``universal``. + + Examples of returned values on MacOS X: + + * ``macosx-10.3-ppc`` + + * ``macosx-10.3-fat`` + + * ``macosx-10.5-universal`` + .. % XXX isn't this also provided by some other non-distutils module? diff --git a/Doc/howto/unicode.rst b/Doc/howto/unicode.rst index 561ce29..d5dec63 100644 --- a/Doc/howto/unicode.rst +++ b/Doc/howto/unicode.rst @@ -30,7 +30,7 @@ For a while people just wrote programs that didn't display accents. I remember looking at Apple ][ BASIC programs, published in French-language publications in the mid-1980s, that had lines like these:: - PRINT "FICHER EST COMPLETE." + PRINT "FICHIER EST COMPLETE." PRINT "CARACTERE NON ACCEPTE." Those messages should contain accents, and they just look wrong to someone who diff --git a/Doc/library/email.mime.rst b/Doc/library/email.mime.rst index 6f1b0ae..415a682 100644 --- a/Doc/library/email.mime.rst +++ b/Doc/library/email.mime.rst @@ -19,6 +19,7 @@ things easier. Here are the classes: +.. currentmodule:: email.mime.base .. class:: MIMEBase(_maintype, _subtype, **_params) @@ -39,6 +40,8 @@ Here are the classes: :mailheader:`MIME-Version` header (always set to ``1.0``). +.. currentmodule:: email.mime.nonmultipart + .. class:: MIMENonMultipart() Module: :mod:`email.mime.nonmultipart` @@ -52,6 +55,8 @@ Here are the classes: .. versionadded:: 2.2.2 +.. currentmodule:: email.mime.multipart + .. class:: MIMEMultipart([subtype[, boundary[, _subparts[, _params]]]]) Module: :mod:`email.mime.multipart` @@ -77,6 +82,8 @@ Here are the classes: .. versionadded:: 2.2.2 +.. currentmodule:: email.mime.application + .. class:: MIMEApplication(_data[, _subtype[, _encoder[, **_params]]]) Module: :mod:`email.mime.application` @@ -99,6 +106,8 @@ Here are the classes: .. versionadded:: 2.5 +.. currentmodule:: email.mime.audio + .. class:: MIMEAudio(_audiodata[, _subtype[, _encoder[, **_params]]]) Module: :mod:`email.mime.audio` @@ -122,6 +131,8 @@ Here are the classes: *_params* are passed straight through to the base class constructor. +.. currentmodule:: email.mime.image + .. class:: MIMEImage(_imagedata[, _subtype[, _encoder[, **_params]]]) Module: :mod:`email.mime.image` @@ -145,6 +156,8 @@ Here are the classes: *_params* are passed straight through to the :class:`MIMEBase` constructor. +.. currentmodule:: email.mime.message + .. class:: MIMEMessage(_msg[, _subtype]) Module: :mod:`email.mime.message` @@ -158,6 +171,8 @@ Here are the classes: :mimetype:`rfc822`. +.. currentmodule:: email.mime.text + .. class:: MIMEText(_text[, _subtype[, _charset]]) Module: :mod:`email.mime.text` diff --git a/Doc/library/json.rst b/Doc/library/json.rst index bff779b..cf6138e 100644 --- a/Doc/library/json.rst +++ b/Doc/library/json.rst @@ -166,7 +166,7 @@ Basic Usage :func:`dump`. -.. function load(fp[, encoding[, cls[, object_hook[, parse_float[, parse_int[, parse_constant[, **kw]]]]]]]) +.. function:: load(fp[, encoding[, cls[, object_hook[, parse_float[, parse_int[, parse_constant[, **kw]]]]]]]) Deserialize *fp* (a ``.read()``-supporting file-like object containing a JSON document) to a Python object. @@ -202,7 +202,7 @@ Basic Usage class. -.. function loads(s[, encoding[, cls[, object_hook[, parse_float[, parse_int[, parse_constant[, **kw]]]]]]]) +.. function:: loads(s[, encoding[, cls[, object_hook[, parse_float[, parse_int[, parse_constant[, **kw]]]]]]]) Deserialize *s* (a :class:`str` or :class:`unicode` instance containing a JSON document) to a Python object. diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst index dac6aeb1..3e54422 100644 --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -553,10 +553,10 @@ provided: #. :class:`HTTPHandler` instances send error messages to an HTTP server using either ``GET`` or ``POST`` semantics. -The :class:`StreamHandler` and :class:`FileHandler` classes are defined in the -core logging package. The other handlers are defined in a sub- module, -:mod:`logging.handlers`. (There is also another sub-module, -:mod:`logging.config`, for configuration functionality.) +The :class:`NullHandler`, :class:`StreamHandler` and :class:`FileHandler` +classes are defined in the core logging package. The other handlers are +defined in a sub- module, :mod:`logging.handlers`. (There is also another +sub-module, :mod:`logging.config`, for configuration functionality.) Logged messages are formatted for presentation through instances of the :class:`Formatter` class. They are initialized with a format string suitable for @@ -1544,6 +1544,8 @@ subclasses. However, the :meth:`__init__` method in subclasses needs to call StreamHandler ^^^^^^^^^^^^^ +.. module:: logging.handlers + The :class:`StreamHandler` class, located in the core :mod:`logging` package, sends logging output to streams such as *sys.stdout*, *sys.stderr* or any file-like object (or, more precisely, any object which supports :meth:`write` @@ -2050,6 +2052,8 @@ supports sending logging messages to a Web server, using either ``GET`` or Formatter Objects ----------------- +.. currentmodule:: logging + :class:`Formatter`\ s have the following attributes and methods. They are responsible for converting a :class:`LogRecord` to (usually) a string which can be interpreted by either a human or an external system. The base diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst index 8297e9f..6f4a3f1 100644 --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -358,7 +358,7 @@ The :mod:`multiprocessing` package mostly replicates the API of the .. attribute:: daemon - The process's daemon flag, a Boolean value. This must be called before + The process's daemon flag, a Boolean value. This must be set before :meth:`start` is called. The initial value is inherited from the creating process. @@ -1810,9 +1810,9 @@ Address Formats filesystem. * An ``'AF_PIPE'`` address is a string of the form - ``r'\\\\.\\pipe\\PipeName'``. To use :func:`Client` to connect to a named + :samp:`r'\\\\.\\pipe\\{PipeName}'`. To use :func:`Client` to connect to a named pipe on a remote computer called ServerName* one should use an address of the - form ``r'\\\\ServerName\\pipe\\PipeName'`` instead. + form :samp:`r'\\\\{ServerName}\\pipe\\{PipeName}'`` instead. Note that any string beginning with two backslashes is assumed by default to be an ``'AF_PIPE'`` address rather than an ``'AF_UNIX'`` address. diff --git a/Doc/library/new.rst b/Doc/library/new.rst index d8e455c..670d3d7 100644 --- a/Doc/library/new.rst +++ b/Doc/library/new.rst @@ -1,4 +1,3 @@ - :mod:`new` --- Creation of runtime internal objects =================================================== @@ -7,7 +6,8 @@ :deprecated: .. deprecated:: 2.6 - The :mod:`new` module has been removed in Python 3.0. + The :mod:`new` module has been removed in Python 3.0. Use the :mod:`types` + module's classes instead. .. sectionauthor:: Moshe Zadka <moshez@zadka.site.co.il> diff --git a/Doc/library/pydoc.rst b/Doc/library/pydoc.rst index 6d4986e..3784515 100644 --- a/Doc/library/pydoc.rst +++ b/Doc/library/pydoc.rst @@ -36,6 +36,13 @@ it contains the path separator for your operating system, such as a slash in Unix), and refers to an existing Python source file, then documentation is produced for that file. +.. note:: + + In order to find objects and their documentation, :mod:`pydoc` imports the + module(s) to be documented. Therefore, any code on module level will be + executed on that occasion. Use an ``if __name__ == '__main__':`` guard to + only execute code when a file is invoked as a script and not just imported. + Specifying a :option:`-w` flag before the argument will cause HTML documentation to be written out to a file in the current directory, instead of displaying text on the console. diff --git a/Doc/library/socketserver.rst b/Doc/library/socketserver.rst index 7f4daad..786632e 100644 --- a/Doc/library/socketserver.rst +++ b/Doc/library/socketserver.rst @@ -448,7 +448,7 @@ This is the server side:: if __name__ == "__main__": HOST, PORT = "localhost", 9999 - server = SocketServer.UDPServer((HOST, PORT), BaseUDPRequestHandler) + server = SocketServer.UDPServer((HOST, PORT), MyUDPHandler) server.serve_forever() This is the client side:: diff --git a/Doc/library/urllib2.rst b/Doc/library/urllib2.rst index 18f5af7..4c7c582 100644 --- a/Doc/library/urllib2.rst +++ b/Doc/library/urllib2.rst @@ -391,23 +391,23 @@ OpenerDirector Objects .. method:: OpenerDirector.add_handler(handler) - *handler* should be an instance of :class:`BaseHandler`. The following methods - are searched, and added to the possible chains (note that HTTP errors are a - special case). + *handler* should be an instance of :class:`BaseHandler`. The following + methods are searched, and added to the possible chains (note that HTTP errors + are a special case). - * :meth:`protocol_open` --- signal that the handler knows how to open *protocol* - URLs. + * :samp:`{protocol}_open` --- signal that the handler knows how to open + *protocol* URLs. - * :meth:`http_error_type` --- signal that the handler knows how to handle HTTP - errors with HTTP error code *type*. + * :samp:`http_error_{type}` --- signal that the handler knows how to handle + HTTP errors with HTTP error code *type*. - * :meth:`protocol_error` --- signal that the handler knows how to handle errors - from (non-\ ``http``) *protocol*. + * :samp:`{protocol}_error` --- signal that the handler knows how to handle + errors from (non-\ ``http``) *protocol*. - * :meth:`protocol_request` --- signal that the handler knows how to pre-process - *protocol* requests. + * :samp:`{protocol}_request` --- signal that the handler knows how to + pre-process *protocol* requests. - * :meth:`protocol_response` --- signal that the handler knows how to + * :samp:`{protocol}_response` --- signal that the handler knows how to post-process *protocol* responses. @@ -441,24 +441,24 @@ OpenerDirector objects open URLs in three stages: The order in which these methods are called within each stage is determined by sorting the handler instances. -#. Every handler with a method named like :meth:`protocol_request` has that +#. Every handler with a method named like :samp:`{protocol}_request` has that method called to pre-process the request. -#. Handlers with a method named like :meth:`protocol_open` are called to handle +#. Handlers with a method named like :samp:`{protocol}_open` are called to handle the request. This stage ends when a handler either returns a non-\ :const:`None` value (ie. a response), or raises an exception (usually :exc:`URLError`). Exceptions are allowed to propagate. In fact, the above algorithm is first tried for methods named - :meth:`default_open`. If all such methods return :const:`None`, the algorithm - is repeated for methods named like :meth:`protocol_open`. If all such methods - return :const:`None`, the algorithm is repeated for methods named - :meth:`unknown_open`. + :meth:`default_open`. If all such methods return :const:`None`, the + algorithm is repeated for methods named like :samp:`{protocol}_open`. If all + such methods return :const:`None`, the algorithm is repeated for methods + named :meth:`unknown_open`. Note that the implementation of these methods may involve calls of the parent :class:`OpenerDirector` instance's :meth:`.open` and :meth:`.error` methods. -#. Every handler with a method named like :meth:`protocol_response` has that +#. Every handler with a method named like :samp:`{protocol}_response` has that method called to post-process the response. @@ -514,8 +514,10 @@ The following members and methods should only be used by classes derived from .. method:: BaseHandler.protocol_open(req) :noindex: + ("protocol" is to be replaced by the protocol name.) + This method is *not* defined in :class:`BaseHandler`, but subclasses should - define it if they want to handle URLs with the given protocol. + define it if they want to handle URLs with the given *protocol*. This method, if defined, will be called by the parent :class:`OpenerDirector`. Return values should be the same as for :meth:`default_open`. @@ -563,8 +565,10 @@ The following members and methods should only be used by classes derived from .. method:: BaseHandler.protocol_request(req) :noindex: + ("protocol" is to be replaced by the protocol name.) + This method is *not* defined in :class:`BaseHandler`, but subclasses should - define it if they want to pre-process requests of the given protocol. + define it if they want to pre-process requests of the given *protocol*. This method, if defined, will be called by the parent :class:`OpenerDirector`. *req* will be a :class:`Request` object. The return value should be a @@ -574,8 +578,10 @@ The following members and methods should only be used by classes derived from .. method:: BaseHandler.protocol_response(req, response) :noindex: + ("protocol" is to be replaced by the protocol name.) + This method is *not* defined in :class:`BaseHandler`, but subclasses should - define it if they want to post-process responses of the given protocol. + define it if they want to post-process responses of the given *protocol*. This method, if defined, will be called by the parent :class:`OpenerDirector`. *req* will be a :class:`Request` object. *response* will be an object @@ -660,7 +666,9 @@ ProxyHandler Objects .. method:: ProxyHandler.protocol_open(request) :noindex: - The :class:`ProxyHandler` will have a method :meth:`protocol_open` for every + ("protocol" is to be replaced by the protocol name.) + + The :class:`ProxyHandler` will have a method :samp:`{protocol}_open` for every *protocol* which has a proxy in the *proxies* dictionary given in the constructor. The method will modify requests to go through the proxy, by calling ``request.set_proxy()``, and call the next handler in the chain to @@ -865,9 +873,10 @@ HTTPErrorProcessor Objects For 200 error codes, the response object is returned immediately. For non-200 error codes, this simply passes the job on to the - :meth:`protocol_error_code` handler methods, via :meth:`OpenerDirector.error`. - Eventually, :class:`urllib2.HTTPDefaultErrorHandler` will raise an - :exc:`HTTPError` if no other handler handles the error. + :samp:`{protocol}_error_code` handler methods, via + :meth:`OpenerDirector.error`. Eventually, + :class:`urllib2.HTTPDefaultErrorHandler` will raise an :exc:`HTTPError` if no + other handler handles the error. .. _urllib2-examples: diff --git a/Doc/library/webbrowser.rst b/Doc/library/webbrowser.rst index 13cd8c7..d340b8a 100644 --- a/Doc/library/webbrowser.rst +++ b/Doc/library/webbrowser.rst @@ -172,7 +172,7 @@ Here are some simple examples:: Browser Controller Objects -------------------------- -Browser controllers provide two methods which parallel two of the module-level +Browser controllers provide these methods which parallel two of the module-level convenience functions: diff --git a/Doc/library/winsound.rst b/Doc/library/winsound.rst index f9709fe..b4a3391 100644 --- a/Doc/library/winsound.rst +++ b/Doc/library/winsound.rst @@ -30,8 +30,9 @@ provided by Windows platforms. It includes functions and several constants. Call the underlying :cfunc:`PlaySound` function from the Platform API. The *sound* parameter may be a filename, audio data as a string, or ``None``. Its interpretation depends on the value of *flags*, which can be a bitwise ORed - combination of the constants described below. If the system indicates an error, - :exc:`RuntimeError` is raised. + combination of the constants described below. If the *sound* parameter is + ``None``, any currently playing waveform sound is stopped. If the system + indicates an error, :exc:`RuntimeError` is raised. .. function:: MessageBeep([type=MB_OK]) @@ -108,6 +109,10 @@ provided by Windows platforms. It includes functions and several constants. Stop playing all instances of the specified sound. + .. note:: + + This flag is not supported on modern Windows platforms. + .. data:: SND_ASYNC diff --git a/Doc/library/xml.etree.elementtree.rst b/Doc/library/xml.etree.elementtree.rst index cdc774e..b17d510 100644 --- a/Doc/library/xml.etree.elementtree.rst +++ b/Doc/library/xml.etree.elementtree.rst @@ -94,6 +94,16 @@ Functions *events* is a list of events to report back. If omitted, only "end" events are reported. Returns an :term:`iterator` providing ``(event, elem)`` pairs. + .. note:: + + :func:`iterparse` only guarantees that it has seen the ">" + character of a starting tag when it emits a "start" event, so the + attributes are defined, but the contents of the text and tail attributes + are undefined at that point. The same applies to the element children; + they may or may not be present. + + If you need a fully populated element, look for "end" events instead. + .. function:: parse(source[, parser]) diff --git a/Include/unicodeobject.h b/Include/unicodeobject.h index ee9fec1..cff0ac3 100644 --- a/Include/unicodeobject.h +++ b/Include/unicodeobject.h @@ -153,6 +153,7 @@ typedef PY_UNICODE_TYPE Py_UNICODE; # define PyUnicode_AsUnicode PyUnicodeUCS2_AsUnicode # define PyUnicode_AsUnicodeEscapeString PyUnicodeUCS2_AsUnicodeEscapeString # define PyUnicode_AsWideChar PyUnicodeUCS2_AsWideChar +# define PyUnicode_ClearFreeList PyUnicodeUCS2_ClearFreelist # define PyUnicode_Compare PyUnicodeUCS2_Compare # define PyUnicode_Concat PyUnicodeUCS2_Concat # define PyUnicode_Contains PyUnicodeUCS2_Contains @@ -182,13 +183,13 @@ typedef PY_UNICODE_TYPE Py_UNICODE; # define PyUnicode_Find PyUnicodeUCS2_Find # define PyUnicode_Format PyUnicodeUCS2_Format # define PyUnicode_FromEncodedObject PyUnicodeUCS2_FromEncodedObject +# define PyUnicode_FromFormat PyUnicodeUCS2_FromFormat +# define PyUnicode_FromFormatV PyUnicodeUCS2_FromFormatV # define PyUnicode_FromObject PyUnicodeUCS2_FromObject # define PyUnicode_FromOrdinal PyUnicodeUCS2_FromOrdinal -# define PyUnicode_FromUnicode PyUnicodeUCS2_FromUnicode # define PyUnicode_FromString PyUnicodeUCS2_FromString # define PyUnicode_FromStringAndSize PyUnicodeUCS2_FromStringAndSize -# define PyUnicode_FromFormatV PyUnicodeUCS2_FromFormatV -# define PyUnicode_FromFormat PyUnicodeUCS2_FromFormat +# define PyUnicode_FromUnicode PyUnicodeUCS2_FromUnicode # define PyUnicode_FromWideChar PyUnicodeUCS2_FromWideChar # define PyUnicode_GetDefaultEncoding PyUnicodeUCS2_GetDefaultEncoding # define PyUnicode_GetMax PyUnicodeUCS2_GetMax @@ -209,7 +210,6 @@ typedef PY_UNICODE_TYPE Py_UNICODE; # define _PyUnicode_AsDefaultEncodedString _PyUnicodeUCS2_AsDefaultEncodedString # define _PyUnicode_Fini _PyUnicodeUCS2_Fini # define _PyUnicode_Init _PyUnicodeUCS2_Init -# define PyUnicode_ClearFreeList PyUnicodeUCS2_ClearFreelist # define _PyUnicode_IsAlpha _PyUnicodeUCS2_IsAlpha # define _PyUnicode_IsDecimalDigit _PyUnicodeUCS2_IsDecimalDigit # define _PyUnicode_IsDigit _PyUnicodeUCS2_IsDigit @@ -240,6 +240,7 @@ typedef PY_UNICODE_TYPE Py_UNICODE; # define PyUnicode_AsUnicode PyUnicodeUCS4_AsUnicode # define PyUnicode_AsUnicodeEscapeString PyUnicodeUCS4_AsUnicodeEscapeString # define PyUnicode_AsWideChar PyUnicodeUCS4_AsWideChar +# define PyUnicode_ClearFreeList PyUnicodeUCS4_ClearFreelist # define PyUnicode_Compare PyUnicodeUCS4_Compare # define PyUnicode_Concat PyUnicodeUCS4_Concat # define PyUnicode_Contains PyUnicodeUCS4_Contains @@ -269,13 +270,13 @@ typedef PY_UNICODE_TYPE Py_UNICODE; # define PyUnicode_Find PyUnicodeUCS4_Find # define PyUnicode_Format PyUnicodeUCS4_Format # define PyUnicode_FromEncodedObject PyUnicodeUCS4_FromEncodedObject +# define PyUnicode_FromFormat PyUnicodeUCS4_FromFormat +# define PyUnicode_FromFormatV PyUnicodeUCS4_FromFormatV # define PyUnicode_FromObject PyUnicodeUCS4_FromObject # define PyUnicode_FromOrdinal PyUnicodeUCS4_FromOrdinal -# define PyUnicode_FromUnicode PyUnicodeUCS4_FromUnicode # define PyUnicode_FromString PyUnicodeUCS4_FromString # define PyUnicode_FromStringAndSize PyUnicodeUCS4_FromStringAndSize -# define PyUnicode_FromFormatV PyUnicodeUCS4_FromFormatV -# define PyUnicode_FromFormat PyUnicodeUCS4_FromFormat +# define PyUnicode_FromUnicode PyUnicodeUCS4_FromUnicode # define PyUnicode_FromWideChar PyUnicodeUCS4_FromWideChar # define PyUnicode_GetDefaultEncoding PyUnicodeUCS4_GetDefaultEncoding # define PyUnicode_GetMax PyUnicodeUCS4_GetMax @@ -296,7 +297,6 @@ typedef PY_UNICODE_TYPE Py_UNICODE; # define _PyUnicode_AsDefaultEncodedString _PyUnicodeUCS4_AsDefaultEncodedString # define _PyUnicode_Fini _PyUnicodeUCS4_Fini # define _PyUnicode_Init _PyUnicodeUCS4_Init -# define PyUnicode_ClearFreeList PyUnicodeUCS2_ClearFreelist # define _PyUnicode_IsAlpha _PyUnicodeUCS4_IsAlpha # define _PyUnicode_IsDecimalDigit _PyUnicodeUCS4_IsDecimalDigit # define _PyUnicode_IsDigit _PyUnicodeUCS4_IsDigit diff --git a/Lib/distutils/util.py b/Lib/distutils/util.py index 48cc17f..e9d29ff 100644 --- a/Lib/distutils/util.py +++ b/Lib/distutils/util.py @@ -140,9 +140,13 @@ def get_platform (): # 'universal' instead of 'fat'. machine = 'fat' + cflags = get_config_vars().get('CFLAGS') - if '-arch x86_64' in get_config_vars().get('CFLAGS'): - machine = 'universal' + if '-arch x86_64' in cflags: + if '-arch i386' in cflags: + machine = 'universal' + else: + machine = 'fat64' elif machine in ('PowerPC', 'Power_Macintosh'): # Pick a sane name for the PPC architecture. diff --git a/Lib/inspect.py b/Lib/inspect.py index d3d946d..1685bfc 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -158,9 +158,8 @@ def isgeneratorfunction(object): Generator function objects provides same attributes as functions. See isfunction.__doc__ for attributes listing.""" - if (isfunction(object) or ismethod(object)) and \ - object.func_code.co_flags & CO_GENERATOR: - return True + return bool((isfunction(object) or ismethod(object)) and + object.func_code.co_flags & CO_GENERATOR) def isgenerator(object): """Return true if the object is a generator. diff --git a/Lib/pydoc.py b/Lib/pydoc.py index 179026b..dda0208 100755 --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -1574,6 +1574,42 @@ class Helper: 'with': ('with', 'CONTEXTMANAGERS EXCEPTIONS yield'), 'yield': ('yield', ''), } + # Either add symbols to this dictionary or to the symbols dictionary + # directly: Whichever is easier. They are merged later. + _symbols_inverse = { + 'STRINGS' : ("'", "'''", "r'", "u'", '"""', '"', 'r"', 'u"'), + 'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&', + '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'), + 'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'), + 'UNARY' : ('-', '~'), + 'AUGMENTEDASSIGNMENT' : ('+=', '-=', '*=', '/=', '%=', '&=', '|=', + '^=', '<<=', '>>=', '**=', '//='), + 'BITWISE' : ('<<', '>>', '&', '|', '^', '~'), + 'COMPLEX' : ('j', 'J') + } + symbols = { + '%': 'OPERATORS FORMATTING', + '**': 'POWER', + ',': 'TUPLES LISTS FUNCTIONS', + '.': 'ATTRIBUTES FLOAT MODULES OBJECTS', + '...': 'ELLIPSIS', + ':': 'SLICINGS DICTIONARYLITERALS', + '@': 'def class', + '\\': 'STRINGS', + '_': 'PRIVATENAMES', + '__': 'PRIVATENAMES SPECIALMETHODS', + '`': 'BACKQUOTES', + '(': 'TUPLES FUNCTIONS CALLS', + ')': 'TUPLES FUNCTIONS CALLS', + '[': 'LISTS SUBSCRIPTS SLICINGS', + ']': 'LISTS SUBSCRIPTS SLICINGS' + } + for topic, symbols_ in _symbols_inverse.iteritems(): + for symbol in symbols_: + topics = symbols.get(symbol, topic) + if topic not in topics: + topics = topics + ' ' + topic + symbols[symbol] = topics topics = { 'TYPES': ('types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS ' @@ -1717,10 +1753,12 @@ has the same effect as typing a particular string at the help> prompt. if type(request) is type(''): if request == 'help': self.intro() elif request == 'keywords': self.listkeywords() + elif request == 'symbols': self.listsymbols() elif request == 'topics': self.listtopics() elif request == 'modules': self.listmodules() elif request[:8] == 'modules ': self.listmodules(split(request)[1]) + elif request in self.symbols: self.showsymbol(request) elif request in self.keywords: self.showtopic(request) elif request in self.topics: self.showtopic(request) elif request: doc(request, 'Help on %s:') @@ -1766,6 +1804,14 @@ Here is a list of the Python keywords. Enter any keyword to get more help. ''') self.list(self.keywords.keys()) + def listsymbols(self): + self.output.write(''' +Here is a list of the punctuation symbols which Python assigns special meaning +to. Enter any symbol to get more help. + +''') + self.list(self.symbols.keys()) + def listtopics(self): self.output.write(''' Here is a list of available topics. Enter any topic name to get more help. @@ -1773,7 +1819,7 @@ Here is a list of available topics. Enter any topic name to get more help. ''') self.list(self.topics.keys()) - def showtopic(self, topic): + def showtopic(self, topic, more_xrefs=''): try: import pydoc_topics except ImportError: @@ -1787,7 +1833,7 @@ module "pydoc_topics" could not be found. self.output.write('no documentation found for %s\n' % repr(topic)) return if type(target) is type(''): - return self.showtopic(target) + return self.showtopic(target, more_xrefs) label, xrefs = target try: @@ -1796,6 +1842,8 @@ module "pydoc_topics" could not be found. self.output.write('no documentation found for %s\n' % repr(topic)) return pager(strip(doc) + '\n') + if more_xrefs: + xrefs = (xrefs or '') + ' ' + more_xrefs if xrefs: import StringIO, formatter buffer = StringIO.StringIO() @@ -1803,6 +1851,11 @@ module "pydoc_topics" could not be found. 'Related help topics: ' + join(split(xrefs), ', ') + '\n') self.output.write('\n%s\n' % buffer.getvalue()) + def showsymbol(self, symbol): + target = self.symbols[symbol] + topic, _, xrefs = target.partition(' ') + self.showtopic(topic, xrefs) + def listmodules(self, key=''): if key: self.output.write(''' @@ -145,7 +145,8 @@ def sub(pattern, repl, string, count=0): """Return the string obtained by replacing the leftmost non-overlapping occurrences of the pattern in string by the replacement repl. repl can be either a string or a callable; - if a callable, it's passed the match object and must return + if a string, backslash escapes in it are processed. If it is + a callable, it's passed the match object and must return a replacement string to be used.""" return _compile(pattern, 0).sub(repl, string, count) @@ -155,7 +156,8 @@ def subn(pattern, repl, string, count=0): non-overlapping occurrences of the pattern in the source string by the replacement repl. number is the number of substitutions that were made. repl can be either a string or a - callable; if a callable, it's passed the match object and must + callable; if a string, backslash escapes in it are processed. + If it is a callable, it's passed the match object and must return a replacement string to be used.""" return _compile(pattern, 0).subn(repl, string, count) diff --git a/Lib/test/test_deque.py b/Lib/test/test_deque.py index 0f0d098..4e2de3d 100644 --- a/Lib/test/test_deque.py +++ b/Lib/test/test_deque.py @@ -1,7 +1,8 @@ from collections import deque import unittest from test import test_support, seq_tests -from weakref import proxy +import gc +import weakref import copy import cPickle as pickle import random @@ -418,6 +419,22 @@ class TestBasic(unittest.TestCase): d.append(1) gc.collect() + def test_container_iterator(self): + # Bug # XXX: tp_traverse was not implemented for deque iterator objects + class C(object): + pass + for i in range(2): + obj = C() + ref = weakref.ref(obj) + if i == 0: + container = deque([obj, 1]) + else: + container = reversed(deque([obj, 1])) + obj.x = iter(container) + del obj, container + gc.collect() + self.assert_(ref() is None, "Cycle was not collected") + class TestVariousIteratorArgs(unittest.TestCase): def test_constructor(self): @@ -528,7 +545,7 @@ class TestSubclass(unittest.TestCase): def test_weakref(self): d = deque('gallahad') - p = proxy(d) + p = weakref.proxy(d) self.assertEqual(str(p), str(d)) d = None self.assertRaises(ReferenceError, str, p) diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py index f715657..14d62f5 100644 --- a/Lib/test/test_dict.py +++ b/Lib/test/test_dict.py @@ -2,6 +2,7 @@ import unittest from test import test_support import UserDict, random, string +import gc, weakref class DictTest(unittest.TestCase): @@ -554,6 +555,19 @@ class DictTest(unittest.TestCase): pass d = {} + def test_container_iterator(self): + # Bug # XXX: tp_traverse was not implemented for dictiter objects + class C(object): + pass + iterators = (dict.iteritems, dict.itervalues, dict.iterkeys) + for i in iterators: + obj = C() + ref = weakref.ref(obj) + container = {obj: 1} + obj.x = i(container) + del obj, container + gc.collect() + self.assert_(ref() is None, "Cycle was not collected") from test import mapping_tests diff --git a/Lib/test/test_file.py b/Lib/test/test_file.py index 96f6da2..b4f494b 100644 --- a/Lib/test/test_file.py +++ b/Lib/test/test_file.py @@ -125,6 +125,19 @@ class AutoFileTests(unittest.TestCase): class OtherFileTests(unittest.TestCase): + def testOpenDir(self): + this_dir = os.path.dirname(__file__) + for mode in (None, "w"): + try: + if mode: + f = open(this_dir, mode) + else: + f = open(this_dir) + except IOError as e: + self.assertEqual(e.filename, this_dir) + else: + self.fail("opening a directory didn't raise an IOError") + def testModeStrings(self): # check invalid mode strings for mode in ("", "aU", "wU+"): diff --git a/Lib/test/test_fileio.py b/Lib/test/test_fileio.py index c978779..d8cf415 100644 --- a/Lib/test/test_fileio.py +++ b/Lib/test/test_fileio.py @@ -109,6 +109,7 @@ class AutoFileTests(unittest.TestCase): _fileio._FileIO('.', 'r') except IOError as e: self.assertNotEqual(e.errno, 0) + self.assertEqual(e.filename, ".") else: self.fail("Should have raised IOError") diff --git a/Lib/test/test_set.py b/Lib/test/test_set.py index d38a675..8d05712 100644 --- a/Lib/test/test_set.py +++ b/Lib/test/test_set.py @@ -1,6 +1,7 @@ import unittest from test import test_support -from weakref import proxy +import gc +import weakref import operator import copy import pickle @@ -322,6 +323,18 @@ class TestJointOps(unittest.TestCase): self.assertEqual(sum(elem.hash_count for elem in d), n) self.assertEqual(d3, dict.fromkeys(d, 123)) + def test_container_iterator(self): + # Bug # XXX: tp_traverse was not implemented for set iterator object + class C(object): + pass + obj = C() + ref = weakref.ref(obj) + container = set([obj, 1]) + obj.x = iter(container) + del obj, container + gc.collect() + self.assert_(ref() is None, "Cycle was not collected") + class TestSet(TestJointOps): thetype = set @@ -538,7 +551,7 @@ class TestSet(TestJointOps): def test_weakref(self): s = self.thetype('gallahad') - p = proxy(s) + p = weakref.proxy(s) self.assertEqual(str(p), str(s)) s = None self.assertRaises(ReferenceError, str, p) diff --git a/Lib/test/test_struct.py b/Lib/test/test_struct.py index 232bffc..7f5f08b 100644 --- a/Lib/test/test_struct.py +++ b/Lib/test/test_struct.py @@ -2,6 +2,8 @@ import array import unittest import struct import warnings +warnings.filterwarnings("ignore", "struct integer overflow masking is deprecated", + DeprecationWarning) from functools import wraps from test.test_support import TestFailed, verbose, run_unittest @@ -461,6 +463,11 @@ class StructTest(unittest.TestCase): self.check_float_coerce(endian + fmt, 1.0) self.check_float_coerce(endian + fmt, 1.5) + def test_issue4228(self): + # Packing a long may yield either 32 or 64 bits + x = struct.pack('L', -1)[:4] + self.assertEqual(x, '\xff'*4) + def test_unpack_from(self): test_string = 'abcd01234' fmt = '4s' diff --git a/Lib/textwrap.py b/Lib/textwrap.py index 192b43b..64a5b97 100644 --- a/Lib/textwrap.py +++ b/Lib/textwrap.py @@ -84,7 +84,7 @@ class TextWrapper: # splits into # Hello/ /there/ /--/ /you/ /goof-/ball,/ /use/ /the/ /-b/ /option! # (after stripping out empty strings). - wordsep_re = ( + wordsep_re = re.compile( r'(\s+|' # any whitespace r'[^\s\w]*\w+[^0-9\W]-(?=\w+[^0-9\W])|' # hyphenated words r'(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w))') # em-dash @@ -93,7 +93,7 @@ class TextWrapper: # "Hello there -- you goof-ball, use the -b option!" # splits into # Hello/ /there/ /--/ /you/ /goof-ball,/ /use/ /the/ /-b/ /option!/ - wordsep_simple_re = r'(\s+)' + wordsep_simple_re = re.compile(r'(\s+)') # XXX this is not locale- or charset-aware -- string.lowercase # is US-ASCII only (and therefore English-only) @@ -124,6 +124,13 @@ class TextWrapper: self.drop_whitespace = drop_whitespace self.break_on_hyphens = break_on_hyphens + # recompile the regexes for Unicode mode -- done in this clumsy way for + # backwards compatibility because it's rather common to monkey-patch + # the TextWrapper class' wordsep_re attribute. + self.wordsep_re_uni = re.compile(self.wordsep_re.pattern, re.U) + self.wordsep_simple_re_uni = re.compile( + self.wordsep_simple_re.pattern, re.U) + # -- Private methods ----------------------------------------------- # (possibly useful for subclasses to override) @@ -160,12 +167,17 @@ class TextWrapper: 'use', ' ', 'the', ' ', '-b', ' ', option!' otherwise. """ - flags = re.UNICODE if isinstance(text, unicode) else 0 - if self.break_on_hyphens: - pat = self.wordsep_re + if isinstance(text, unicode): + if self.break_on_hyphens: + pat = self.wordsep_re_uni + else: + pat = self.wordsep_simple_re_uni else: - pat = self.wordsep_simple_re - chunks = re.compile(pat, flags).split(text) + if self.break_on_hyphens: + pat = self.wordsep_re + else: + pat = self.wordsep_simple_re + chunks = pat.split(text) chunks = filter(None, chunks) # remove empty chunks return chunks @@ -12,9 +12,21 @@ What's New in Python 2.6.2 Core and Builtins ----------------- +- Issue #3680: Reference cycles created through a dict, set or deque iterator + did not get collected. + - Issue #4701: PyObject_Hash now implicitly calls PyType_Ready on types where the tp_hash and tp_dict slots are both NULL. +- Issue #4764: With io.open, IOError.filename is set when trying to open a + directory on POSIX systems. + +- Issue #4764: IOError.filename is set when trying to open a directory on POSIX + systems. + +- Issue #4759: None is now allowed as the first argument of + bytearray.translate(). It was always allowed for bytes.translate(). + - Issue #4759: fix a segfault for bytearray.translate(x, None). - Added test case to ensure attempts to read from a file opened for writing @@ -138,9 +150,18 @@ Core and Builtins Library ------- +- Issue #4795: inspect.isgeneratorfunction() returns False instead of None when + the function is not a generator. + - Issue #4702: Throwing a DistutilsPlatformError instead of IOError in case no MSVC compiler is found under Windows. Original patch by Philip Jenvey. + - Issue #4739: Add pydoc help topics for symbols, so that e.g. help('@') + works as expected in the interactive environment. + +- Issue #4756: zipfile.is_zipfile() now supports file-like objects. Patch by + Gabriel Genellina. + - Issue #4646: distutils was choking on empty options arg in the setup function. Original patch by Thomas Heller. @@ -206,9 +227,16 @@ Library - Issue #4730: Fixed the cPickle module to handle correctly astral characters when protocol 0 is used. +Tools/Demos +----------- + +- Issue #4677: add two list comprehension tests to pybench. + Build ----- +- Issues #4728 and #4060: WORDS_BIGEDIAN is now correct in Universal builds. + - Issue #4389: Add icon to the uninstall entry in "add-and-remove-programs". - Issue #4289: Remove Cancel button from AdvancedDlg. @@ -239,6 +267,10 @@ C-API Extension Modules ----------------- +- Issue #4228: Pack negative values the same way as 2.4 in struct's L format. + +- Issue #1040026: Fix os.times result on systems where HZ is incorrect. + - Issues #3167, #3682: Fix test_math failures for log, log10 on Solaris, OpenBSD. diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index da000d0..37633d2 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -958,7 +958,7 @@ deque_iter(dequeobject *deque) { dequeiterobject *it; - it = PyObject_New(dequeiterobject, &dequeiter_type); + it = PyObject_GC_New(dequeiterobject, &dequeiter_type); if (it == NULL) return NULL; it->b = deque->leftblock; @@ -967,14 +967,22 @@ deque_iter(dequeobject *deque) it->deque = deque; it->state = deque->state; it->counter = deque->len; + _PyObject_GC_TRACK(it); return (PyObject *)it; } +static int +dequeiter_traverse(dequeiterobject *dio, visitproc visit, void *arg) +{ + Py_VISIT(dio->deque); + return 0; +} + static void dequeiter_dealloc(dequeiterobject *dio) { Py_XDECREF(dio->deque); - Py_TYPE(dio)->tp_free(dio); + PyObject_GC_Del(dio); } static PyObject * @@ -1039,9 +1047,9 @@ static PyTypeObject dequeiter_type = { PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ 0, /* tp_doc */ - 0, /* tp_traverse */ + (traverseproc)dequeiter_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ @@ -1060,7 +1068,7 @@ deque_reviter(dequeobject *deque) { dequeiterobject *it; - it = PyObject_New(dequeiterobject, &dequereviter_type); + it = PyObject_GC_New(dequeiterobject, &dequereviter_type); if (it == NULL) return NULL; it->b = deque->rightblock; @@ -1069,6 +1077,7 @@ deque_reviter(dequeobject *deque) it->deque = deque; it->state = deque->state; it->counter = deque->len; + _PyObject_GC_TRACK(it); return (PyObject *)it; } @@ -1121,9 +1130,9 @@ static PyTypeObject dequereviter_type = { PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ 0, /* tp_doc */ - 0, /* tp_traverse */ + (traverseproc)dequeiter_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ diff --git a/Modules/_fileio.c b/Modules/_fileio.c index 65cc99d..ca12822 100644 --- a/Modules/_fileio.c +++ b/Modules/_fileio.c @@ -98,7 +98,7 @@ fileio_new(PyTypeObject *type, PyObject *args, PyObject *kews) directories, so we need a check. */ static int -dircheck(PyFileIOObject* self) +dircheck(PyFileIOObject* self, char *name) { #if defined(HAVE_FSTAT) && defined(S_IFDIR) && defined(EISDIR) struct stat buf; @@ -109,8 +109,8 @@ dircheck(PyFileIOObject* self) PyObject *exc; internal_close(self); - exc = PyObject_CallFunction(PyExc_IOError, "(is)", - EISDIR, msg); + exc = PyObject_CallFunction(PyExc_IOError, "(iss)", + EISDIR, msg, name); PyErr_SetObject(PyExc_IOError, exc); Py_XDECREF(exc); return -1; @@ -271,7 +271,7 @@ fileio_init(PyObject *oself, PyObject *args, PyObject *kwds) #endif goto error; } - if(dircheck(self) < 0) + if(dircheck(self, name) < 0) goto error; } diff --git a/Modules/_struct.c b/Modules/_struct.c index 30feaa6..b8f1525 100644 --- a/Modules/_struct.c +++ b/Modules/_struct.c @@ -663,7 +663,7 @@ np_int(char *p, PyObject *v, const formatdef *f) return -1; #if (SIZEOF_LONG > SIZEOF_INT) if ((x < ((long)INT_MIN)) || (x > ((long)INT_MAX))) - return _range_error(f, 0); + RANGE_ERROR(x, f, 0, -1); #endif y = (int)x; memcpy(p, (char *)&y, sizeof y); @@ -675,12 +675,12 @@ np_uint(char *p, PyObject *v, const formatdef *f) { unsigned long x; unsigned int y; - if (get_ulong(v, &x) < 0) - return _range_error(f, 1); + if (get_wrapped_ulong(v, &x) < 0) + return -1; y = (unsigned int)x; #if (SIZEOF_LONG > SIZEOF_INT) if (x > ((unsigned long)UINT_MAX)) - return _range_error(f, 1); + RANGE_ERROR(y, f, 1, -1); #endif memcpy(p, (char *)&y, sizeof y); return 0; @@ -700,8 +700,8 @@ static int np_ulong(char *p, PyObject *v, const formatdef *f) { unsigned long x; - if (get_ulong(v, &x) < 0) - return _range_error(f, 1); + if (get_wrapped_ulong(v, &x) < 0) + return -1; memcpy(p, (char *)&x, sizeof x); return 0; } diff --git a/Objects/dictobject.c b/Objects/dictobject.c index f2ef4b0..f4d8683 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -2331,7 +2331,7 @@ static PyObject * dictiter_new(PyDictObject *dict, PyTypeObject *itertype) { dictiterobject *di; - di = PyObject_New(dictiterobject, itertype); + di = PyObject_GC_New(dictiterobject, itertype); if (di == NULL) return NULL; Py_INCREF(dict); @@ -2348,6 +2348,7 @@ dictiter_new(PyDictObject *dict, PyTypeObject *itertype) } else di->di_result = NULL; + _PyObject_GC_TRACK(di); return (PyObject *)di; } @@ -2356,7 +2357,15 @@ dictiter_dealloc(dictiterobject *di) { Py_XDECREF(di->di_dict); Py_XDECREF(di->di_result); - PyObject_Del(di); + PyObject_GC_Del(di); +} + +static int +dictiter_traverse(dictiterobject *di, visitproc visit, void *arg) +{ + Py_VISIT(di->di_dict); + Py_VISIT(di->di_result); + return 0; } static PyObject * @@ -2435,9 +2444,9 @@ PyTypeObject PyDictIterKey_Type = { PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ 0, /* tp_doc */ - 0, /* tp_traverse */ + (traverseproc)dictiter_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ @@ -2507,9 +2516,9 @@ PyTypeObject PyDictIterValue_Type = { PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ 0, /* tp_doc */ - 0, /* tp_traverse */ + (traverseproc)dictiter_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ @@ -2593,9 +2602,9 @@ PyTypeObject PyDictIterItem_Type = { PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ 0, /* tp_doc */ - 0, /* tp_traverse */ + (traverseproc)dictiter_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ diff --git a/Objects/fileobject.c b/Objects/fileobject.c index b2051d7..e01f38e 100644 --- a/Objects/fileobject.c +++ b/Objects/fileobject.c @@ -132,8 +132,8 @@ dircheck(PyFileObject* f) if (fstat(fileno(f->f_fp), &buf) == 0 && S_ISDIR(buf.st_mode)) { char *msg = strerror(EISDIR); - PyObject *exc = PyObject_CallFunction(PyExc_IOError, "(is)", - EISDIR, msg); + PyObject *exc = PyObject_CallFunction(PyExc_IOError, "(isO)", + EISDIR, msg, f->f_name); PyErr_SetObject(PyExc_IOError, exc); Py_XDECREF(exc); return NULL; diff --git a/Objects/setobject.c b/Objects/setobject.c index ea3970e..a55bbb7 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -810,7 +810,14 @@ static void setiter_dealloc(setiterobject *si) { Py_XDECREF(si->si_set); - PyObject_Del(si); + PyObject_GC_Del(si); +} + +static int +setiter_traverse(setiterobject *si, visitproc visit, void *arg) +{ + Py_VISIT(si->si_set); + return 0; } static PyObject * @@ -888,9 +895,9 @@ static PyTypeObject PySetIter_Type = { PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ 0, /* tp_doc */ - 0, /* tp_traverse */ + (traverseproc)setiter_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ @@ -903,7 +910,7 @@ static PyTypeObject PySetIter_Type = { static PyObject * set_iter(PySetObject *so) { - setiterobject *si = PyObject_New(setiterobject, &PySetIter_Type); + setiterobject *si = PyObject_GC_New(setiterobject, &PySetIter_Type); if (si == NULL) return NULL; Py_INCREF(so); @@ -911,6 +918,7 @@ set_iter(PySetObject *so) si->si_used = so->used; si->si_pos = 0; si->len = so->used; + _PyObject_GC_TRACK(si); return (PyObject *)si; } diff --git a/Tools/pybench/Lists.py b/Tools/pybench/Lists.py index 67760db..6c297a3 100644 --- a/Tools/pybench/Lists.py +++ b/Tools/pybench/Lists.py @@ -293,3 +293,58 @@ class SmallLists(Test): for i in xrange(self.rounds): pass + +class SimpleListComprehensions(Test): + + version = 2.0 + operations = 6 + rounds = 20000 + + def test(self): + + n = range(10) * 10 + + for i in xrange(self.rounds): + l = [x for x in n] + l = [x for x in n if x] + l = [x for x in n if not x] + + l = [x for x in n] + l = [x for x in n if x] + l = [x for x in n if not x] + + def calibrate(self): + + n = range(10) * 10 + + for i in xrange(self.rounds): + pass + +class NestedListComprehensions(Test): + + version = 2.0 + operations = 6 + rounds = 20000 + + def test(self): + + m = range(10) + n = range(10) + + for i in xrange(self.rounds): + l = [x for x in n for y in m] + l = [y for x in n for y in m] + + l = [x for x in n for y in m if y] + l = [y for x in n for y in m if x] + + l = [x for x in n for y in m if not y] + l = [y for x in n for y in m if not x] + + def calibrate(self): + + m = range(10) + n = range(10) + + for i in xrange(self.rounds): + pass |