diff options
46 files changed, 498 insertions, 209 deletions
diff --git a/Doc/c-api/conversion.rst b/Doc/c-api/conversion.rst index f926094..b71283b 100644 --- a/Doc/c-api/conversion.rst +++ b/Doc/c-api/conversion.rst @@ -83,11 +83,11 @@ The following functions provide locale-independent string to number conversions. .. cfunction:: char * PyOS_stricmp(char *s1, char *s2) - Case insensitive comparison of strings. The functions works almost - identical to :cfunc:`strcmp` except that it ignores the case. + Case insensitive comparison of strings. The function works almost + identically to :cfunc:`strcmp` except that it ignores the case. .. cfunction:: char * PyOS_strnicmp(char *s1, char *s2, Py_ssize_t size) - Case insensitive comparison of strings. The functions works almost - identical to :cfunc:`strncmp` except that it ignores the case. + Case insensitive comparison of strings. The function works almost + identically to :cfunc:`strncmp` except that it ignores the case. diff --git a/Doc/c-api/float.rst b/Doc/c-api/float.rst index 8fff0d0..77a8b83 100644 --- a/Doc/c-api/float.rst +++ b/Doc/c-api/float.rst @@ -73,8 +73,7 @@ Floating Point Objects Return the minimum normalized positive float *DBL_MIN* as C :ctype:`double`. -.. cfunction:: void PyFloat_CompactFreeList(size_t *bc, size_t *bf, size_t *sum) +.. cfunction:: int PyFloat_ClearFreeList(void) - Compact the float free list. *bc* is the number of allocated blocks before - blocks are freed, *bf* is the number of freed blocks and *sum* is the number - of remaining objects in the blocks. + Clear the float free list. Return the number of items that could not + be freed. diff --git a/Doc/c-api/sequence.rst b/Doc/c-api/sequence.rst index 6d3ef71..0ebc0f3 100644 --- a/Doc/c-api/sequence.rst +++ b/Doc/c-api/sequence.rst @@ -143,6 +143,10 @@ Sequence Protocol Return the underlying array of PyObject pointers. Assumes that *o* was returned by :cfunc:`PySequence_Fast` and *o* is not *NULL*. + + Note, if a list gets resized, the reallocation may relocate the items array. + So, only use the underlying array pointer in contexts where the sequence + cannot change. .. cfunction:: PyObject* PySequence_ITEM(PyObject *o, Py_ssize_t i) diff --git a/Doc/extending/windows.rst b/Doc/extending/windows.rst index a0782a7..1811277 100644 --- a/Doc/extending/windows.rst +++ b/Doc/extending/windows.rst @@ -23,7 +23,7 @@ C++. This chapter mentions a number of filenames that include an encoded Python version number. These filenames are represented with the version number shown - as ``XY``; in practive, ``'X'`` will be the major version number and ``'Y'`` + as ``XY``; in practice, ``'X'`` will be the major version number and ``'Y'`` will be the minor version number of the Python release you're working with. For example, if you are using Python 2.2.1, ``XY`` will actually be ``22``. diff --git a/Doc/library/__future__.rst b/Doc/library/__future__.rst index e2349cc..d6f82a3 100644 --- a/Doc/library/__future__.rst +++ b/Doc/library/__future__.rst @@ -16,7 +16,7 @@ * To document when incompatible changes were introduced, and when they will be --- or were --- made mandatory. This is a form of executable documentation, and - can be inspected programatically via importing :mod:`__future__` and examining + can be inspected programmatically via importing :mod:`__future__` and examining its contents. Each statement in :file:`__future__.py` is of the form:: diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst index 939bf8f..f422bf3 100644 --- a/Doc/library/ctypes.rst +++ b/Doc/library/ctypes.rst @@ -1781,8 +1781,8 @@ Utility functions .. function:: byref(obj[, offset]) Returns a light-weight pointer to ``obj``, which must be an - instance of a ctypes type. ``offset`` defaults to zero, it must be - an integer which is added to the internal pointer value. + instance of a ctypes type. ``offset`` defaults to zero, and must be + an integer that will be added to the internal pointer value. ``byref(obj, offset)`` corresponds to this C code:: diff --git a/Doc/library/ftplib.rst b/Doc/library/ftplib.rst index f360c60..d4f8888 100644 --- a/Doc/library/ftplib.rst +++ b/Doc/library/ftplib.rst @@ -300,7 +300,7 @@ followed by ``lines`` for the text version or ``binary`` for the binary version. Send a ``QUIT`` command to the server and close the connection. This is the "polite" way to close a connection, but it may raise an exception of the server - reponds with an error to the ``QUIT`` command. This implies a call to the + responds with an error to the ``QUIT`` command. This implies a call to the :meth:`close` method which renders the :class:`FTP` instance useless for subsequent calls (see below). diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 4b1cbc6..ac40ce7 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -1186,6 +1186,7 @@ are always available. They are listed here in alphabetical order. care about trailing, unmatched values from the longer iterables. If those values are important, use :func:`itertools.zip_longest` instead. + .. rubric:: Footnotes .. [#] Specifying a buffer size currently has no effect on systems that don't have diff --git a/Doc/library/gc.rst b/Doc/library/gc.rst index 99504c6..7c425e3 100644 --- a/Doc/library/gc.rst +++ b/Doc/library/gc.rst @@ -44,6 +44,11 @@ The :mod:`gc` module provides the following functions: :exc:`ValueError` is raised if the generation number is invalid. The number of unreachable objects found is returned. + The free lists maintained for a number of builtin types are cleared + whenever a full collection or collection of the highest generation (2) + is run. Not all items in some free lists may be freed due to the + particular implementation, in particular :class:`float`. + .. function:: set_debug(flags) diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst index be87775..10ccb17 100644 --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -158,7 +158,7 @@ However, if you really do need to use some shared data then The ``'d'`` and ``'i'`` arguments used when creating ``num`` and ``arr`` are typecodes of the kind used by the :mod:`array` module: ``'d'`` indicates a - double precision float and ``'i'`` inidicates a signed integer. These shared + double precision float and ``'i'`` indicates a signed integer. These shared objects will be process and thread safe. For more flexibility in using shared memory one can use the @@ -168,7 +168,7 @@ However, if you really do need to use some shared data then **Server process** A manager object returned by :func:`Manager` controls a server process which - holds python objects and allows other processes to manipulate them using + holds Python objects and allows other processes to manipulate them using proxies. A manager returned by :func:`Manager` will support types :class:`list`, @@ -451,7 +451,7 @@ Note that one can also create a shared queue by using a manager object -- see This means that if you try joining that process you may get a deadlock unless you are sure that all items which have been put on the queue have been consumed. Similarly, if the child process is non-daemonic then the parent - process may hang on exit when it tries to join all it non-daemonic children. + process may hang on exit when it tries to join all its non-daemonic children. Note that a queue created using a manager does not have this issue. See :ref:`multiprocessing-programming`. @@ -532,7 +532,8 @@ For an example of the usage of queues for interprocess communication see Equivalent to ``get(False)``. :class:`multiprocessing.Queue` has a few additional methods not found in - :class:`queue.Queue` which are usually unnecessary: + :class:`queue.Queue`. These methods are usually unnecessary for most + code: .. method:: close() @@ -772,7 +773,7 @@ Synchronization primitives ~~~~~~~~~~~~~~~~~~~~~~~~~~ Generally synchronization primitives are not as necessary in a multiprocess -program as they are in a mulithreaded program. See the documentation for +program as they are in a multithreaded program. See the documentation for :mod:`threading` module. Note that one can also create synchronization primitives by using a manager @@ -782,7 +783,7 @@ object -- see :ref:`multiprocessing-managers`. A bounded semaphore object: a clone of :class:`threading.BoundedSemaphore`. - (On Mac OSX this is indistiguishable from :class:`Semaphore` because + (On Mac OSX this is indistinguishable from :class:`Semaphore` because ``sem_getvalue()`` is not implemented on that platform). .. class:: Condition([lock]) @@ -891,8 +892,8 @@ processes. .. note:: - Although it is posible to store a pointer in shared memory remember that this - will refer to a location in the address space of a specific process. + Although it is possible to store a pointer in shared memory remember that + this will refer to a location in the address space of a specific process. However, the pointer is quite likely to be invalid in the context of a second process and trying to dereference the pointer from the second process may cause a crash. @@ -1081,7 +1082,7 @@ their parent process exits. The manager classes are defined in the Start a subprocess to start the manager. - .. method:: server_forever() + .. method:: serve_forever() Run the server in the current process. @@ -1774,7 +1775,7 @@ handler type) for messages from different processes to get mixed up. handler which sends output to :data:`sys.stderr` using format ``'[%(levelname)s/%(processName)s] %(message)s'``. (The logger allows use of the non-standard ``'%(processName)s'`` format.) Message sent to this logger - will not by default propogate to the root logger. + will not by default propagate to the root logger. Note that on Windows child processes will only inherit the level of the parent process's logger -- any other customization of the logger will not be diff --git a/Doc/library/operator.rst b/Doc/library/operator.rst index 37996e0..a67c6d8 100644 --- a/Doc/library/operator.rst +++ b/Doc/library/operator.rst @@ -513,7 +513,7 @@ Python syntax and the functions in the :mod:`operator` module. +-----------------------+-------------------------+---------------------------------+ | Right Shift | ``a >> b`` | ``rshift(a, b)`` | +-----------------------+-------------------------+---------------------------------+ -| Sequence Repitition | ``seq * i`` | ``repeat(seq, i)`` | +| Sequence Repetition | ``seq * i`` | ``repeat(seq, i)`` | +-----------------------+-------------------------+---------------------------------+ | String Formatting | ``s % obj`` | ``mod(s, obj)`` | +-----------------------+-------------------------+---------------------------------+ diff --git a/Doc/library/select.rst b/Doc/library/select.rst index 102d3ea..f64d6dd 100644 --- a/Doc/library/select.rst +++ b/Doc/library/select.rst @@ -330,7 +330,7 @@ http://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2 +---------------------------+---------------------------------------------+ | :const:`KQ_EV_DISABLE` | Disablesevent | +---------------------------+---------------------------------------------+ - | :const:`KQ_EV_ONESHOT` | Removes event after first occurence | + | :const:`KQ_EV_ONESHOT` | Removes event after first occurrence | +---------------------------+---------------------------------------------+ | :const:`KQ_EV_CLEAR` | Reset the state after an event is retrieved | +---------------------------+---------------------------------------------+ @@ -365,7 +365,7 @@ http://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2 +============================+============================================+ | :const:`KQ_NOTE_DELETE` | *unlink()* was called | +----------------------------+--------------------------------------------+ - | :const:`KQ_NOTE_WRITE` | a write occured | + | :const:`KQ_NOTE_WRITE` | a write occurred | +----------------------------+--------------------------------------------+ | :const:`KQ_NOTE_EXTEND` | the file was extended | +----------------------------+--------------------------------------------+ diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 586770a..40417d8 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -1565,7 +1565,7 @@ The constructors for both classes work the same: .. method:: isdisjoint(other) Return True if the set has no elements in common with *other*. Sets are - disjoint if and only if their interesection is the empty set. + disjoint if and only if their intersection is the empty set. .. method:: issubset(other) set <= other diff --git a/Doc/library/string.rst b/Doc/library/string.rst index 662541e..07a2c4b 100644 --- a/Doc/library/string.rst +++ b/Doc/library/string.rst @@ -266,7 +266,7 @@ Then the outer replacement field would be evaluated, producing:: "noses " -Which is subsitituted into the string, yielding:: +Which is substituted into the string, yielding:: "A man with two noses " diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst index f92b1e4..3f73ec2 100644 --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -54,19 +54,6 @@ always available. A string containing the copyright pertaining to the Python interpreter. -.. function:: _compact_freelists() - - Compact the free list of floats by deallocating unused blocks. - It can reduce the memory usage of the Python process several tenth of - thousands of integers or floats have been allocated at once. - - The return value is a tuple of tuples each containing three elements, - amount of used objects, total block count before the blocks are deallocated - and amount of freed blocks. - - This function should be used for specialized purposes only. - - .. function:: _clear_type_cache() Clear the internal type cache. The type cache is used to speed up attribute diff --git a/Doc/library/tkinter.tix.rst b/Doc/library/tkinter.tix.rst index a85aeb1..b555376 100644 --- a/Doc/library/tkinter.tix.rst +++ b/Doc/library/tkinter.tix.rst @@ -305,8 +305,8 @@ File Selectors .. \ulink{FileEntry}{http://tix.sourceforge.net/dist/current/demos/samples/FileEnt.tcl} -Hierachical ListBox -^^^^^^^^^^^^^^^^^^^ +Hierarchical ListBox +^^^^^^^^^^^^^^^^^^^^ .. class:: HList() diff --git a/Doc/library/tkinter.turtle.rst b/Doc/library/tkinter.turtle.rst index 575c2fc..6bf9c10 100644 --- a/Doc/library/tkinter.turtle.rst +++ b/Doc/library/tkinter.turtle.rst @@ -2,6 +2,10 @@ :mod:`turtle` --- Turtle graphics for Tk ======================================== +.. module:: tkinter.turtle + :synopsis: Turtle graphics for Tk +.. sectionauthor:: Gregor Lingl <gregor.lingl@aon.at> + Introduction ============ @@ -1251,7 +1255,7 @@ Window control ... left(10) ... >>> for _ in range(8): - ... left(45); fd(2) # a regular octogon + ... left(45); fd(2) # a regular octagon Animation control @@ -1262,7 +1266,7 @@ Animation control :param delay: positive integer Set or return the drawing *delay* in milliseconds. (This is approximately - the time interval between two consecutived canvas updates.) The longer the + the time interval between two consecutive canvas updates.) The longer the drawing delay, the slower the animation. Optional argument: diff --git a/Doc/library/urllib.request.rst b/Doc/library/urllib.request.rst index c506829..3038588 100644 --- a/Doc/library/urllib.request.rst +++ b/Doc/library/urllib.request.rst @@ -1062,7 +1062,7 @@ involved. For example, the :envvar:`http_proxy` environment variable is read to obtain the HTTP proxy's URL. This example replaces the default :class:`ProxyHandler` with one that uses -programatically-supplied proxy URLs, and adds proxy authorization support with +programmatically-supplied proxy URLs, and adds proxy authorization support with :class:`ProxyBasicAuthHandler`. :: proxy_handler = urllib.request.ProxyHandler({'http': 'http://www.example.com:3128/'}) diff --git a/Doc/library/wsgiref.rst b/Doc/library/wsgiref.rst index 70064fc..fcfe769 100644 --- a/Doc/library/wsgiref.rst +++ b/Doc/library/wsgiref.rst @@ -413,7 +413,7 @@ Paste" library. from wsgiref.validate import validator from wsgiref.simple_server import make_server - # Our callable object which is intentionally not compilant to the + # Our callable object which is intentionally not compliant to the # standard, so the validator is going to break def simple_app(environ, start_response): status = '200 OK' # HTTP Status diff --git a/Doc/library/xmlrpc.client.rst b/Doc/library/xmlrpc.client.rst index e249b12..1f18810 100644 --- a/Doc/library/xmlrpc.client.rst +++ b/Doc/library/xmlrpc.client.rst @@ -344,7 +344,7 @@ The client code for the preceding server:: try: proxy.add(2, 5) except xmlrpc.client.Fault, err: - print("A fault occured") + print("A fault occurred") print("Fault code: %d" % err.faultCode) print("Fault string: %s" % err.faultString) @@ -391,7 +391,7 @@ by providing an invalid URI:: try: proxy.some_method() except xmlrpc.client.ProtocolError, err: - print("A protocol error occured") + print("A protocol error occurred") print("URL: %s" % err.url) print("HTTP/HTTPS headers: %s" % err.headers) print("Error code: %d" % err.errcode) diff --git a/Doc/tutorial/stdlib2.rst b/Doc/tutorial/stdlib2.rst index 7d76363..84dfb61 100644 --- a/Doc/tutorial/stdlib2.rst +++ b/Doc/tutorial/stdlib2.rst @@ -286,7 +286,7 @@ sometimes there is a need for alternative implementations with different performance trade-offs. The :mod:`array` module provides an :class:`array()` object that is like a list -that stores only homogenous data and stores it more compactly. The following +that stores only homogeneous data and stores it more compactly. The following example shows an array of numbers stored as two byte unsigned binary numbers (typecode ``"H"``) rather than the usual 16 bytes per entry for regular lists of python int objects:: diff --git a/Doc/using/windows.rst b/Doc/using/windows.rst index 4064fa1..2dd236f 100644 --- a/Doc/using/windows.rst +++ b/Doc/using/windows.rst @@ -186,7 +186,7 @@ of your Python installation directory). This suppresses the terminal window on startup. You can also make all ``.py`` scripts execute with :program:`pythonw.exe`, -setting this through the usual facilites, for example (might require +setting this through the usual facilities, for example (might require administrative rights): #. Launch a command prompt. @@ -215,7 +215,7 @@ PyWin32 The `PyWin32 <http://python.net/crew/mhammond/win32/>`_ module by Mark Hammond is a collection of modules for advanced Windows-specific support. This includes -utilites for: +utilities for: * `Component Object Model <http://www.microsoft.com/com/>`_ (COM) * Win32 API calls diff --git a/Doc/whatsnew/2.6.rst b/Doc/whatsnew/2.6.rst index 264ec2e..5cf29cb 100644 --- a/Doc/whatsnew/2.6.rst +++ b/Doc/whatsnew/2.6.rst @@ -51,7 +51,7 @@ This article explains the new features in Python 2.6. The release schedule is described in :pep:`361`; currently the final release is -scheduled for September 3 2008. +scheduled for October 1 2008. This article doesn't attempt to provide a complete specification of the new features, but instead provides a convenient overview. For @@ -526,28 +526,152 @@ environment variable. PEP 371: The ``multiprocessing`` Package ===================================================== -.. XXX I think this still needs help +The new :mod:`multiprocessing` package lets Python programs create new +processes that will perform a computation and return a result to the +parent. The parent and child processes can communicate using queues +and pipes, synchronize their operations using locks and semaphores, +and can share simple arrays of data. + +The :mod:`multiprocessing` module started out as an exact emulation of +the :mod:`threading` module using processes instead of threads. That +goal was discarded along the path to Python 2.6, but the general +approach of the module is still similar. The fundamental class +is the :class:`Process`, which is passed a callable object and +a collection of arguments. The :meth:`start` method +sets the callable running in a subprocess, after which you can call +the :meth:`is_alive` method to check whether the subprocess is still running +and the :meth:`join` method to wait for the process to exit. + +Here's a simple example where the subprocess will calculate a +factorial. The function doing the calculation is a bit strange; it's +written to take significantly longer when the input argument is a +multiple of 4. + +:: + + import time + from multiprocessing import Process, Queue + + + def factorial(queue, N): + "Compute a factorial." + # If N is a multiple of 4, this function will take much longer. + if (N % 4) == 0: + time.sleep(.05 * N/4) + + # Calculate the result + fact = 1L + for i in range(1, N+1): + fact = fact * i + + # Put the result on the queue + queue.put(fact) + + if __name__ == '__main__': + queue = Queue() + + N = 5 + + p = Process(target=factorial, args=(queue, N)) + p.start() + p.join() + + result = queue.get() + print 'Factorial', N, '=', result + +A :class:`Queue` object is created and stored as a global. The child +process will use the value of the variable when the child was created; +because it's a :class:`Queue`, parent and child can use the object to +communicate. (If the parent were to change the value of the global +variable, the child's value would be unaffected, and vice versa.) + +Two other classes, :class:`Pool` and :class:`Manager`, provide +higher-level interfaces. :class:`Pool` will create a fixed number of +worker processes, and requests can then be distributed to the workers +by calling :meth:`apply` or `apply_async`, adding a single request, +and :meth:`map` or :meth:`map_async` to distribute a number of +requests. The following code uses a :class:`Pool` to spread requests +across 5 worker processes, receiving a list of results back. + +:: + + from multiprocessing import Pool + + p = Pool(5) + result = p.map(factorial, range(1, 1000, 10)) + for v in result: + print v + +This produces the following output:: + + 1 + 39916800 + 51090942171709440000 + 8222838654177922817725562880000000 + 33452526613163807108170062053440751665152000000000 + ... + +The :class:`Manager` class creates a separate server process that can +hold master copies of Python data structures. Other processes can +then access and modify these data structures by using proxy objects. +The following example creates a shared dictionary by calling the +:meth:`dict` method; the worker processes then insert values into the +dictionary. (No locking is done automatically, which doesn't matter +in this example. :class:`Manager`'s methods also include +:meth:`Lock`, :meth:`RLock`, and :meth:`Semaphore` to create shared locks. + +:: + + import time + from multiprocessing import Pool, Manager + + def factorial(N, dictionary): + "Compute a factorial." + # Calculate the result + fact = 1L + for i in range(1, N+1): + fact = fact * i + + # Store result in dictionary + dictionary[N] = fact + + if __name__ == '__main__': + p = Pool(5) + mgr = Manager() + d = mgr.dict() # Create shared dictionary -:mod:`multiprocessing` makes it easy to distribute work over multiple processes. -Its API is similiar to that of :mod:`threading`. For example:: + # Run tasks using the pool + for N in range(1, 1000, 10): + p.apply_async(factorial, (N, d)) - from multiprocessing import Process + # Mark pool as closed -- no more tasks can be added. + p.close() - def long_hard_task(n): - print n * 43 + # Wait for tasks to exit + p.join() - for i in range(10): - Process(target=long_hard_task, args=(i)).start() + # Output results + for k, v in sorted(d.items()): + print k, v -will multiply the numbers between 0 and 10 times 43 and print out the result -concurrently. +This will produce the output:: + + 1 1 + 11 39916800 + 21 51090942171709440000 + 31 8222838654177922817725562880000000 + 41 33452526613163807108170062053440751665152000000000 + 51 1551118753287382280224243016469303211063259720016986112000000000000 .. seealso:: + The documentation for the :mod:`multiprocessing` module. + :pep:`371` - Addition of the multiprocessing package PEP written by Jesse Noller and Richard Oudkerk; implemented by Richard Oudkerk and Jesse Noller. + .. ====================================================================== .. _pep-3101: @@ -1775,21 +1899,6 @@ details. (Contributed by Raymond Hettinger.) -* XXX Describe the new ctypes calling convention that allows safe - access to errno. - (Implemented by Thomas Heller; :issue:`1798`.) - -* The :mod:`ctypes` module now supports a :class:`c_bool` datatype - that represents the C99 ``bool`` type. (Contributed by David Remahl; - :issue:`1649190`.) - - The :mod:`ctypes` string, buffer and array types also have improved - support for extended slicing syntax, - where various combinations of ``(start, stop, step)`` are supplied. - (Implemented by Thomas Wouters.) - - .. Revision 57769 - * A new method in the :mod:`curses` module: for a window, :meth:`chgat` changes the display characters for a certain number of characters on a single line. (Contributed by Fabian Kreutz.) @@ -2628,6 +2737,45 @@ Using the module is simple:: .. ====================================================================== +ctypes Enhancements +-------------------------------------------------- + +Thomas Heller continued to maintain and enhance the +:mod:`ctypes` module. + +:mod:`ctypes` now supports a :class:`c_bool` datatype +that represents the C99 ``bool`` type. (Contributed by David Remahl; +:issue:`1649190`.) + +The :mod:`ctypes` string, buffer and array types have improved +support for extended slicing syntax, +where various combinations of ``(start, stop, step)`` are supplied. +(Implemented by Thomas Wouters.) + +.. Revision 57769 + +A new calling convention tells :mod:`ctypes` to clear the ``errno`` or +Win32 LastError variables at the outset of each wrapped call. +(Implemented by Thomas Heller; :issue:`1798`.) + +For the Unix ``errno`` variable: when creating a wrapped function, +you can supply ``use_errno=True`` as a keyword parameter +to the :func:`DLL` function +and then call the module-level methods :meth:`set_errno` +and :meth:`get_errno` to set and retrieve the error value. + +The Win32 LastError variable is supported similarly by +the :func:`DLL`, :func:`OleDLL`, and :func:`WinDLL` functions. +You supply ``use_last_error=True`` as a keyword parameter +and then call the module-level methods :meth:`set_last_error` +and :meth:`get_last_error`. + +The :func:`byref` function, used to retrieve a pointer to a ctypes +instance, now has an optional **offset** parameter that is a byte +count that will be added to the returned pointer. + +.. ====================================================================== + Improved SSL Support -------------------------------------------------- diff --git a/Include/floatobject.h b/Include/floatobject.h index 650d544..364b913 100644 --- a/Include/floatobject.h +++ b/Include/floatobject.h @@ -103,7 +103,7 @@ PyAPI_FUNC(double) _PyFloat_Unpack4(const unsigned char *p, int le); PyAPI_FUNC(double) _PyFloat_Unpack8(const unsigned char *p, int le); /* free list api */ -PyAPI_FUNC(void) PyFloat_CompactFreeList(size_t *, size_t *, size_t *); +PyAPI_FUNC(int) PyFloat_ClearFreeList(void); /* Format the object based on the format_spec, as defined in PEP 3101 (Advanced String Formatting). */ diff --git a/Include/object.h b/Include/object.h index 7f0e24a..07a4b2c 100644 --- a/Include/object.h +++ b/Include/object.h @@ -695,9 +695,9 @@ PyAPI_FUNC(void) _Py_AddToAllObjects(PyObject *, int force); #define Py_CLEAR(op) \ do { \ if (op) { \ - PyObject *tmp = (PyObject *)(op); \ + PyObject *_py_tmp = (PyObject *)(op); \ (op) = NULL; \ - Py_DECREF(tmp); \ + Py_DECREF(_py_tmp); \ } \ } while (0) diff --git a/Include/traceback.h b/Include/traceback.h index 0be3ad5..e7943da 100644 --- a/Include/traceback.h +++ b/Include/traceback.h @@ -19,7 +19,7 @@ typedef struct _traceback { PyAPI_FUNC(int) PyTraceBack_Here(struct _frame *); PyAPI_FUNC(int) PyTraceBack_Print(PyObject *, PyObject *); -PyAPI_FUNC(int) Py_DisplaySourceLine(PyObject *, const char *, int, int); +PyAPI_FUNC(int) _Py_DisplaySourceLine(PyObject *, const char *, int, int); /* Reveal traceback type so we can typecheck traceback objects */ PyAPI_DATA(PyTypeObject) PyTraceBack_Type; diff --git a/Lib/bisect.py b/Lib/bisect.py index e4a2133..fe84255 100644 --- a/Lib/bisect.py +++ b/Lib/bisect.py @@ -9,6 +9,8 @@ def insort_right(a, x, lo=0, hi=None): slice of a to be searched. """ + if lo < 0: + raise ValueError('lo must be non-negative') if hi is None: hi = len(a) while lo < hi: @@ -30,6 +32,8 @@ def bisect_right(a, x, lo=0, hi=None): slice of a to be searched. """ + if lo < 0: + raise ValueError('lo must be non-negative') if hi is None: hi = len(a) while lo < hi: @@ -49,6 +53,8 @@ def insort_left(a, x, lo=0, hi=None): slice of a to be searched. """ + if lo < 0: + raise ValueError('lo must be non-negative') if hi is None: hi = len(a) while lo < hi: @@ -69,6 +75,8 @@ def bisect_left(a, x, lo=0, hi=None): slice of a to be searched. """ + if lo < 0: + raise ValueError('lo must be non-negative') if hi is None: hi = len(a) while lo < hi: diff --git a/Lib/fractions.py b/Lib/fractions.py index 3df628a..bc06524 100755 --- a/Lib/fractions.py +++ b/Lib/fractions.py @@ -108,7 +108,9 @@ class Fraction(numbers.Rational): Beware that Fraction.from_float(0.3) != Fraction(3, 10). """ - if not isinstance(f, float): + if isinstance(f, numbers.Integral): + f = float(f) + elif not isinstance(f, float): raise TypeError("%s.from_float() only takes floats, not %r (%s)" % (cls.__name__, f, type(f).__name__)) if math.isnan(f) or math.isinf(f): @@ -119,7 +121,9 @@ class Fraction(numbers.Rational): def from_decimal(cls, dec): """Converts a finite Decimal instance to a rational number, exactly.""" from decimal import Decimal - if not isinstance(dec, Decimal): + if isinstance(dec, numbers.Integral): + dec = Decimal(int(dec)) + elif not isinstance(dec, Decimal): raise TypeError( "%s.from_decimal() only takes Decimals, not %r (%s)" % (cls.__name__, dec, type(dec).__name__)) diff --git a/Lib/multiprocessing/connection.py b/Lib/multiprocessing/connection.py index 8493ac0..717e14e 100644 --- a/Lib/multiprocessing/connection.py +++ b/Lib/multiprocessing/connection.py @@ -222,11 +222,9 @@ class SocketListener(object): self._family = family self._last_accepted = None - sub_debug('listener bound to address %r', self._address) - if family == 'AF_UNIX': self._unlink = Finalize( - self, os.unlink, args=(self._address,), exitpriority=0 + self, os.unlink, args=(address,), exitpriority=0 ) else: self._unlink = None diff --git a/Lib/shutil.py b/Lib/shutil.py index e9cebae..56ea7ec 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -8,6 +8,7 @@ import os import sys import stat from os.path import abspath +import fnmatch __all__ = ["copyfileobj","copyfile","copymode","copystat","copy","copy2", "copytree","move","rmtree","Error"] @@ -93,8 +94,19 @@ def copy2(src, dst): copyfile(src, dst) copystat(src, dst) +def ignore_patterns(*patterns): + """Function that can be used as copytree() ignore parameter. -def copytree(src, dst, symlinks=False): + Patterns is a sequence of glob-style patterns + that are used to exclude files""" + def _ignore_patterns(path, names): + ignored_names = [] + for pattern in patterns: + ignored_names.extend(fnmatch.filter(names, pattern)) + return set(ignored_names) + return _ignore_patterns + +def copytree(src, dst, symlinks=False, ignore=None): """Recursively copy a directory tree using copy2(). The destination directory must not already exist. @@ -105,13 +117,32 @@ def copytree(src, dst, symlinks=False): it is false, the contents of the files pointed to by symbolic links are copied. + The optional ignore argument is a callable. If given, it + is called with the `src` parameter, which is the directory + being visited by copytree(), and `names` which is the list of + `src` contents, as returned by os.listdir(): + + callable(src, names) -> ignored_names + + Since copytree() is called recursively, the callable will be + called once for each directory that is copied. It returns a + list of names relative to the `src` directory that should + not be copied. + XXX Consider this example code rather than the ultimate tool. """ names = os.listdir(src) + if ignore is not None: + ignored_names = ignore(src, names) + else: + ignored_names = set() + os.makedirs(dst) errors = [] for name in names: + if name in ignored_names: + continue srcname = os.path.join(src, name) dstname = os.path.join(dst, name) try: @@ -119,7 +150,7 @@ def copytree(src, dst, symlinks=False): linkto = os.readlink(srcname) os.symlink(linkto, dstname) elif os.path.isdir(srcname): - copytree(srcname, dstname, symlinks) + copytree(srcname, dstname, symlinks, ignore) else: copy2(srcname, dstname) # XXX What about devices, sockets etc.? diff --git a/Lib/test/test_bisect.py b/Lib/test/test_bisect.py index af9f1f7..987f33c 100644 --- a/Lib/test/test_bisect.py +++ b/Lib/test/test_bisect.py @@ -114,6 +114,14 @@ class TestBisect(unittest.TestCase): self.assertEqual(func(data, elem), expected) self.assertEqual(func(UserList(data), elem), expected) + def test_negative_lo(self): + # Issue 3301 + mod = self.module + self.assertRaises(ValueError, mod.bisect_left, [1, 2, 3], 5, -1, 3), + self.assertRaises(ValueError, mod.bisect_right, [1, 2, 3], 5, -1, 3), + self.assertRaises(ValueError, mod.insort_left, [1, 2, 3], 5, -1, 3), + self.assertRaises(ValueError, mod.insort_right, [1, 2, 3], 5, -1, 3), + def test_random(self, n=25): from random import randrange for i in range(n): diff --git a/Lib/test/test_float.py b/Lib/test/test_float.py index 7de5320..db91e5e 100644 --- a/Lib/test/test_float.py +++ b/Lib/test/test_float.py @@ -284,24 +284,36 @@ class ReprTestCase(unittest.TestCase): floats_file.close() # Beginning with Python 2.6 float has cross platform compatible -# ways to create and representate inf and nan +# ways to create and represent inf and nan class InfNanTest(unittest.TestCase): def test_inf_from_str(self): self.assert_(isinf(float("inf"))) self.assert_(isinf(float("+inf"))) self.assert_(isinf(float("-inf"))) + self.assert_(isinf(float("infinity"))) + self.assert_(isinf(float("+infinity"))) + self.assert_(isinf(float("-infinity"))) self.assertEqual(repr(float("inf")), "inf") self.assertEqual(repr(float("+inf")), "inf") self.assertEqual(repr(float("-inf")), "-inf") + self.assertEqual(repr(float("infinity")), "inf") + self.assertEqual(repr(float("+infinity")), "inf") + self.assertEqual(repr(float("-infinity")), "-inf") self.assertEqual(repr(float("INF")), "inf") self.assertEqual(repr(float("+Inf")), "inf") self.assertEqual(repr(float("-iNF")), "-inf") + self.assertEqual(repr(float("Infinity")), "inf") + self.assertEqual(repr(float("+iNfInItY")), "inf") + self.assertEqual(repr(float("-INFINITY")), "-inf") self.assertEqual(str(float("inf")), "inf") self.assertEqual(str(float("+inf")), "inf") self.assertEqual(str(float("-inf")), "-inf") + self.assertEqual(str(float("infinity")), "inf") + self.assertEqual(str(float("+infinity")), "inf") + self.assertEqual(str(float("-infinity")), "-inf") self.assertRaises(ValueError, float, "info") self.assertRaises(ValueError, float, "+info") @@ -309,6 +321,10 @@ class InfNanTest(unittest.TestCase): self.assertRaises(ValueError, float, "in") self.assertRaises(ValueError, float, "+in") self.assertRaises(ValueError, float, "-in") + self.assertRaises(ValueError, float, "infinit") + self.assertRaises(ValueError, float, "+Infin") + self.assertRaises(ValueError, float, "-INFI") + self.assertRaises(ValueError, float, "infinitys") def test_inf_as_str(self): self.assertEqual(repr(1e300 * 1e300), "inf") diff --git a/Lib/test/test_fractions.py b/Lib/test/test_fractions.py index 4f8defb..4fadf6c 100644 --- a/Lib/test/test_fractions.py +++ b/Lib/test/test_fractions.py @@ -134,10 +134,8 @@ class FractionTest(unittest.TestCase): self.assertNotEquals(F(4, 2), r) def testFromFloat(self): - self.assertRaisesMessage( - TypeError, "Fraction.from_float() only takes floats, not 3 (int)", - F.from_float, 3) - + self.assertRaises(TypeError, F.from_float, 3+4j) + self.assertEquals((10, 1), _components(F.from_float(10))) self.assertEquals((0, 1), _components(F.from_float(-0.0))) self.assertEquals((10, 1), _components(F.from_float(10.0))) self.assertEquals((-5, 2), _components(F.from_float(-2.5))) @@ -161,10 +159,8 @@ class FractionTest(unittest.TestCase): F.from_float, nan) def testFromDecimal(self): - self.assertRaisesMessage( - TypeError, - "Fraction.from_decimal() only takes Decimals, not 3 (int)", - F.from_decimal, 3) + self.assertRaises(TypeError, F.from_decimal, 3+4j) + self.assertEquals(F(10, 1), F.from_decimal(10)) self.assertEquals(F(0), F.from_decimal(Decimal("-0"))) self.assertEquals(F(5, 10), F.from_decimal(Decimal("0.5"))) self.assertEquals(F(5, 1000), F.from_decimal(Decimal("5e-3"))) diff --git a/Lib/test/test_import.py b/Lib/test/test_import.py index 81e221d..aa65c7a 100644 --- a/Lib/test/test_import.py +++ b/Lib/test/test_import.py @@ -1,5 +1,3 @@ -from test.support import TESTFN, run_unittest, catch_warning - import unittest import os import random @@ -8,7 +6,7 @@ import sys import py_compile import warnings import imp -from test.support import unlink, TESTFN, unload +from test.support import unlink, TESTFN, unload, run_unittest, catch_warning def remove_files(name): @@ -267,6 +265,25 @@ class RelativeImport(unittest.TestCase): from . import relimport self.assertTrue(hasattr(relimport, "RelativeImport")) + def test_issue3221(self): + def check_relative(): + exec("from . import relimport", ns) + # Check both OK with __package__ and __name__ correct + ns = dict(__package__='test', __name__='test.notarealmodule') + check_relative() + # Check both OK with only __name__ wrong + ns = dict(__package__='test', __name__='notarealpkg.notarealmodule') + check_relative() + # Check relative fails with only __package__ wrong + ns = dict(__package__='foo', __name__='test.notarealmodule') + self.assertRaises(SystemError, check_relative) + # Check relative fails with __package__ and __name__ wrong + ns = dict(__package__='foo', __name__='notarealpkg.notarealmodule') + self.assertRaises(SystemError, check_relative) + # Check both fail with package set to a non-string + ns = dict(__package__=object()) + self.assertRaises(ValueError, check_relative) + def test_main(verbose=None): run_unittest(ImportTest, PathsTests, RelativeImport) diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py index 2e680a9..ad60a44 100644 --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -108,6 +108,82 @@ class TestShutil(unittest.TestCase): if os.path.exists(path): shutil.rmtree(path) + def test_copytree_with_exclude(self): + + def write_data(path, data): + f = open(path, "w") + f.write(data) + f.close() + + def read_data(path): + f = open(path) + data = f.read() + f.close() + return data + + # creating data + join = os.path.join + exists = os.path.exists + src_dir = tempfile.mkdtemp() + dst_dir = join(tempfile.mkdtemp(), 'destination') + write_data(join(src_dir, 'test.txt'), '123') + write_data(join(src_dir, 'test.tmp'), '123') + os.mkdir(join(src_dir, 'test_dir')) + write_data(join(src_dir, 'test_dir', 'test.txt'), '456') + os.mkdir(join(src_dir, 'test_dir2')) + write_data(join(src_dir, 'test_dir2', 'test.txt'), '456') + os.mkdir(join(src_dir, 'test_dir2', 'subdir')) + os.mkdir(join(src_dir, 'test_dir2', 'subdir2')) + write_data(join(src_dir, 'test_dir2', 'subdir', 'test.txt'), '456') + write_data(join(src_dir, 'test_dir2', 'subdir2', 'test.py'), '456') + + + # testing glob-like patterns + try: + patterns = shutil.ignore_patterns('*.tmp', 'test_dir2') + shutil.copytree(src_dir, dst_dir, ignore=patterns) + # checking the result: some elements should not be copied + self.assert_(exists(join(dst_dir, 'test.txt'))) + self.assert_(not exists(join(dst_dir, 'test.tmp'))) + self.assert_(not exists(join(dst_dir, 'test_dir2'))) + finally: + if os.path.exists(dst_dir): + shutil.rmtree(dst_dir) + try: + patterns = shutil.ignore_patterns('*.tmp', 'subdir*') + shutil.copytree(src_dir, dst_dir, ignore=patterns) + # checking the result: some elements should not be copied + self.assert_(not exists(join(dst_dir, 'test.tmp'))) + self.assert_(not exists(join(dst_dir, 'test_dir2', 'subdir2'))) + self.assert_(not exists(join(dst_dir, 'test_dir2', 'subdir'))) + finally: + if os.path.exists(dst_dir): + shutil.rmtree(dst_dir) + + # testing callable-style + try: + def _filter(src, names): + res = [] + for name in names: + path = os.path.join(src, name) + + if (os.path.isdir(path) and + path.split()[-1] == 'subdir'): + res.append(name) + elif os.path.splitext(path)[-1] in ('.py'): + res.append(name) + return res + + shutil.copytree(src_dir, dst_dir, ignore=_filter) + + # checking the result: some elements should not be copied + self.assert_(not exists(join(dst_dir, 'test_dir2', 'subdir2', + 'test.py'))) + self.assert_(not exists(join(dst_dir, 'test_dir2', 'subdir'))) + + finally: + if os.path.exists(dst_dir): + shutil.rmtree(dst_dir) if hasattr(os, "symlink"): def test_dont_copy_file_onto_link_to_itself(self): diff --git a/Lib/zipfile.py b/Lib/zipfile.py index 59a86e2..fda9903 100644 --- a/Lib/zipfile.py +++ b/Lib/zipfile.py @@ -45,9 +45,9 @@ ZIP_DEFLATED = 8 # The "end of central directory" structure, magic number, size, and indices # (section V.I in the format document) -structEndCentDir = b"<4s4H2LH" -magicEndCentDir = b"PK\005\006" -sizeEndCentDir = struct.calcsize(structEndCentDir) +structEndArchive = b"<4s4H2LH" +stringEndArchive = b"PK\005\006" +sizeEndCentDir = struct.calcsize(structEndArchive) _ECD_SIGNATURE = 0 _ECD_DISK_NUMBER = 1 @@ -65,37 +65,9 @@ _ECD_LOCATION = 9 # The "central directory" structure, magic number, size, and indices # of entries in the structure (section V.F in the format document) structCentralDir = "<4s4B4HL2L5H2L" -magicCentralDir = b"PK\001\002" +stringCentralDir = b"PK\001\002" sizeCentralDir = struct.calcsize(structCentralDir) -# The "local file header" structure, magic number, size, and indices -# (section V.A in the format document) -structFileHeader = "<4s2B4HL2L2H" -magicFileHeader = b"PK\003\004" -sizeFileHeader = struct.calcsize(structFileHeader) - -# The "Zip64 end of central directory locator" structure, magic number, and size -structEndCentDir64Locator = "<4sLQL" -magicEndCentDir64Locator = b"PK\x06\x07" -sizeEndCentDir64Locator = struct.calcsize(structEndCentDir64Locator) - -# The "Zip64 end of central directory" record, magic number, size, and indices -# (section V.G in the format document) -structEndCentDir64 = "<4sQ2H2L4Q" -magicEndCentDir64 = b"PK\x06\x06" -sizeEndCentDir64 = struct.calcsize(structEndCentDir64) - -_CD64_SIGNATURE = 0 -_CD64_DIRECTORY_RECSIZE = 1 -_CD64_CREATE_VERSION = 2 -_CD64_EXTRACT_VERSION = 3 -_CD64_DISK_NUMBER = 4 -_CD64_DISK_NUMBER_START = 5 -_CD64_NUMBER_ENTRIES_THIS_DISK = 6 -_CD64_NUMBER_ENTRIES_TOTAL = 7 -_CD64_DIRECTORY_SIZE = 8 -_CD64_OFFSET_START_CENTDIR = 9 - # indexes of entries in the central directory structure _CD_SIGNATURE = 0 _CD_CREATE_VERSION = 1 @@ -120,7 +92,7 @@ _CD_LOCAL_HEADER_OFFSET = 18 # The "local file header" structure, magic number, size, and indices # (section V.A in the format document) structFileHeader = "<4s2B4HL2L2H" -magicFileHeader = b"PK\003\004" +stringFileHeader = b"PK\003\004" sizeFileHeader = struct.calcsize(structFileHeader) _FH_SIGNATURE = 0 @@ -137,15 +109,15 @@ _FH_FILENAME_LENGTH = 10 _FH_EXTRA_FIELD_LENGTH = 11 # The "Zip64 end of central directory locator" structure, magic number, and size -structEndCentDir64Locator = "<4sLQL" -magicEndCentDir64Locator = b"PK\x06\x07" -sizeEndCentDir64Locator = struct.calcsize(structEndCentDir64Locator) +structEndArchive64Locator = "<4sLQL" +stringEndArchive64Locator = b"PK\x06\x07" +sizeEndCentDir64Locator = struct.calcsize(structEndArchive64Locator) # The "Zip64 end of central directory" record, magic number, size, and indices # (section V.G in the format document) -structEndCentDir64 = "<4sQ2H2L4Q" -magicEndCentDir64 = b"PK\x06\x06" -sizeEndCentDir64 = struct.calcsize(structEndCentDir64) +structEndArchive64 = "<4sQ2H2L4Q" +stringEndArchive64 = b"PK\x06\x06" +sizeEndCentDir64 = struct.calcsize(structEndArchive64) _CD64_SIGNATURE = 0 _CD64_DIRECTORY_RECSIZE = 1 @@ -176,8 +148,8 @@ def _EndRecData64(fpin, offset, endrec): """ fpin.seek(offset - sizeEndCentDir64Locator, 2) data = fpin.read(sizeEndCentDir64Locator) - sig, diskno, reloff, disks = struct.unpack(structEndCentDir64Locator, data) - if sig != magicEndCentDir64Locator: + sig, diskno, reloff, disks = struct.unpack(structEndArchive64Locator, data) + if sig != stringEndArchive64Locator: return endrec if diskno != 0 or disks != 1: @@ -188,8 +160,8 @@ def _EndRecData64(fpin, offset, endrec): data = fpin.read(sizeEndCentDir64) sig, sz, create_version, read_version, disk_num, disk_dir, \ dircount, dircount2, dirsize, diroffset = \ - struct.unpack(structEndCentDir64, data) - if sig != magicEndCentDir64: + struct.unpack(structEndArchive64, data) + if sig != stringEndArchive64: return endrec # Update the original endrec using data from the ZIP64 record @@ -217,9 +189,9 @@ def _EndRecData(fpin): # file if this is the case). fpin.seek(-sizeEndCentDir, 2) data = fpin.read() - if data[0:4] == magicEndCentDir and data[-2:] == b"\000\000": + if data[0:4] == stringEndArchive and data[-2:] == b"\000\000": # the signature is correct and there's no comment, unpack structure - endrec = struct.unpack(structEndCentDir, data) + endrec = struct.unpack(structEndArchive, data) endrec=list(endrec) # Append a blank comment and record start offset @@ -241,11 +213,11 @@ def _EndRecData(fpin): maxCommentStart = max(filesize - (1 << 16) - sizeEndCentDir, 0) fpin.seek(maxCommentStart, 0) data = fpin.read() - start = data.rfind(magicEndCentDir) + start = data.rfind(stringEndArchive) if start >= 0: # found the magic number; attempt to unpack and interpret recData = data[start:start+sizeEndCentDir] - endrec = list(struct.unpack(structEndCentDir, recData)) + endrec = list(struct.unpack(structEndArchive, recData)) comment = data[start+sizeEndCentDir:] # check that comment length is correct if endrec[_ECD_COMMENT_SIZE] == len(comment): @@ -352,7 +324,7 @@ class ZipInfo (object): self.create_version = max(45, self.extract_version) filename, flag_bits = self._encodeFilenameFlags() - header = struct.pack(structFileHeader, magicFileHeader, + header = struct.pack(structFileHeader, stringFileHeader, self.extract_version, self.reserved, flag_bits, self.compress_type, dostime, dosdate, CRC, compress_size, file_size, @@ -777,7 +749,7 @@ class ZipFile: total = 0 while total < size_cd: centdir = fp.read(sizeCentralDir) - if centdir[0:4] != magicCentralDir: + if centdir[0:4] != stringCentralDir: raise BadZipfile("Bad magic number for central directory") centdir = struct.unpack(structCentralDir, centdir) if self.debug > 2: @@ -892,7 +864,7 @@ class ZipFile: # Skip the file header: fheader = zef_file.read(sizeFileHeader) - if fheader[0:4] != magicFileHeader: + if fheader[0:4] != stringFileHeader: raise BadZipfile("Bad magic number for file header") fheader = struct.unpack(structFileHeader, fheader) @@ -1184,7 +1156,7 @@ class ZipFile: try: filename, flag_bits = zinfo._encodeFilenameFlags() centdir = struct.pack(structCentralDir, - magicCentralDir, create_version, + stringCentralDir, create_version, zinfo.create_system, extract_version, zinfo.reserved, flag_bits, zinfo.compress_type, dostime, dosdate, zinfo.CRC, compress_size, file_size, @@ -1212,13 +1184,13 @@ class ZipFile: if pos1 > ZIP64_LIMIT: # Need to write the ZIP64 end-of-archive records zip64endrec = struct.pack( - structEndCentDir64, magicEndCentDir64, + structEndArchive64, stringEndArchive64, 44, 45, 45, 0, 0, count, count, pos2 - pos1, pos1) self.fp.write(zip64endrec) zip64locrec = struct.pack( - structEndCentDir64Locator, - magicEndCentDir64Locator, 0, pos2, 1) + structEndArchive64Locator, + stringEndArchive64Locator, 0, pos2, 1) self.fp.write(zip64locrec) centDirOffset = 0xFFFFFFFF @@ -1229,7 +1201,7 @@ class ZipFile: % ZIP_MAX_COMMENT self.comment = self.comment[:ZIP_MAX_COMMENT] - endrec = struct.pack(structEndCentDir, magicEndCentDir, + endrec = struct.pack(structEndArchive, stringEndArchive, 0, 0, count % ZIP_FILECOUNT_LIMIT, count % ZIP_FILECOUNT_LIMIT, pos2 - pos1, centDirOffset, len(self.comment)) @@ -460,6 +460,7 @@ Luke Mewburn Mike Meyer Steven Miale Trent Mick +Aristotelis Mikropoulos Damien Miller Chad Miller Jay T. Miller diff --git a/Modules/_bisectmodule.c b/Modules/_bisectmodule.c index 1280b04..bf47feb 100644 --- a/Modules/_bisectmodule.c +++ b/Modules/_bisectmodule.c @@ -11,6 +11,10 @@ internal_bisect_right(PyObject *list, PyObject *item, Py_ssize_t lo, Py_ssize_t PyObject *litem; Py_ssize_t mid, res; + if (lo < 0) { + PyErr_SetString(PyExc_ValueError, "lo must be non-negative"); + return -1; + } if (hi == -1) { hi = PySequence_Size(list); if (hi < 0) @@ -108,6 +112,10 @@ internal_bisect_left(PyObject *list, PyObject *item, int lo, int hi) PyObject *litem; int mid, res; + if (lo < 0) { + PyErr_SetString(PyExc_ValueError, "lo must be non-negative"); + return -1; + } if (hi == -1) { hi = PySequence_Size(list); if (hi < 0) diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index 8b505c8..51bcd79f 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -706,6 +706,7 @@ clear_freelists(void) (void)PyCFunction_ClearFreeList(); (void)PyTuple_ClearFreeList(); (void)PyUnicode_ClearFreeList(); + (void)PyFloat_ClearFreeList(); } /* This is the main function. Read this to understand how the diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 8282134..a6a19c1 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -3638,7 +3638,8 @@ posix_fork1(PyObject *self, PyObject *noargs) pid_t pid = fork1(); if (pid == -1) return posix_error(); - PyOS_AfterFork(); + if (pid == 0) + PyOS_AfterFork(); return PyLong_FromLong(pid); } #endif diff --git a/Objects/floatobject.c b/Objects/floatobject.c index f18e7dd..daf7ee8 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -225,6 +225,9 @@ PyFloat_FromString(PyObject *v) if (PyOS_strnicmp(p, "inf", 4) == 0) { Py_RETURN_INF(sign); } + if (PyOS_strnicmp(p, "infinity", 9) == 0) { + Py_RETURN_INF(sign); + } #ifdef Py_NAN if(PyOS_strnicmp(p, "nan", 4) == 0) { Py_RETURN_NAN; @@ -1903,30 +1906,28 @@ _PyFloat_Init(void) PyStructSequence_InitType(&FloatInfoType, &floatinfo_desc); } -void -PyFloat_CompactFreeList(size_t *pbc, size_t *pbf, size_t *bsum) +int +PyFloat_ClearFreeList(void) { PyFloatObject *p; PyFloatBlock *list, *next; - unsigned i; - size_t bc = 0, bf = 0; /* block count, number of freed blocks */ - size_t fsum = 0; /* total unfreed ints */ - int frem; /* remaining unfreed ints per block */ + int i; + int u; /* remaining unfreed ints per block */ + int freelist_size = 0; list = block_list; block_list = NULL; free_list = NULL; while (list != NULL) { - bc++; - frem = 0; + u = 0; for (i = 0, p = &list->objects[0]; i < N_FLOATOBJECTS; i++, p++) { if (PyFloat_CheckExact(p) && Py_REFCNT(p) != 0) - frem++; + u++; } next = list->next; - if (frem) { + if (u) { list->next = block_list; block_list = list; for (i = 0, p = &list->objects[0]; @@ -1941,15 +1942,12 @@ PyFloat_CompactFreeList(size_t *pbc, size_t *pbf, size_t *bsum) } } else { - PyMem_FREE(list); /* XXX PyObject_FREE ??? */ - bf++; + PyMem_FREE(list); } - fsum += frem; + freelist_size += u; list = next; } - *pbc = bc; - *pbf = bf; - *bsum = fsum; + return freelist_size; } void @@ -1957,25 +1955,21 @@ PyFloat_Fini(void) { PyFloatObject *p; PyFloatBlock *list; - unsigned i; - size_t bc, bf; /* block count, number of freed blocks */ - size_t fsum; /* total unfreed floats per block */ + int i; + int u; /* total unfreed floats per block */ - PyFloat_CompactFreeList(&bc, &bf, &fsum); + u = PyFloat_ClearFreeList(); if (!Py_VerboseFlag) return; fprintf(stderr, "# cleanup floats"); - if (!fsum) { + if (!u) { fprintf(stderr, "\n"); } else { fprintf(stderr, - ": %" PY_FORMAT_SIZE_T "d unfreed float%s in %" - PY_FORMAT_SIZE_T "d out of %" - PY_FORMAT_SIZE_T "d block%s\n", - fsum, fsum == 1 ? "" : "s", - bc - bf, bc, bc == 1 ? "" : "s"); + ": %d unfreed float%s\n", + u, u == 1 ? "" : "s"); } if (Py_VerboseFlag > 1) { list = block_list; diff --git a/Python/_warnings.c b/Python/_warnings.c index e9384ca..cb81b07 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -266,7 +266,8 @@ show_warning(PyObject *filename, int lineno, PyObject *text, PyObject PyFile_WriteString("\n", f_stderr); } else - Py_DisplaySourceLine(f_stderr, PyUnicode_AsString(filename), lineno, 2); + _Py_DisplaySourceLine(f_stderr, PyUnicode_AsString(filename), + lineno, 2); PyErr_Clear(); } diff --git a/Python/import.c b/Python/import.c index 14cda6e..7ad3bf9 100644 --- a/Python/import.c +++ b/Python/import.c @@ -2162,6 +2162,7 @@ get_parent(PyObject *globals, char *buf, Py_ssize_t *p_buflen, int level) static PyObject *pathstr = NULL; static PyObject *pkgstr = NULL; PyObject *pkgname, *modname, *modpath, *modules, *parent; + int orig_level = level; if (globals == NULL || !PyDict_Check(globals) || !level) return Py_None; @@ -2292,9 +2293,27 @@ get_parent(PyObject *globals, char *buf, Py_ssize_t *p_buflen, int level) modules = PyImport_GetModuleDict(); parent = PyDict_GetItemString(modules, buf); - if (parent == NULL) - PyErr_Format(PyExc_SystemError, - "Parent module '%.200s' not loaded", buf); + if (parent == NULL) { + if (orig_level < 1) { + PyObject *err_msg = PyBytes_FromFormat( + "Parent module '%.200s' not found " + "while handling absolute import", buf); + if (err_msg == NULL) { + return NULL; + } + if (!PyErr_WarnEx(PyExc_RuntimeWarning, + PyBytes_AsString(err_msg), 1)) { + *buf = '\0'; + *p_buflen = 0; + parent = Py_None; + } + Py_DECREF(err_msg); + } else { + PyErr_Format(PyExc_SystemError, + "Parent module '%.200s' not loaded, " + "cannot perform relative import", buf); + } + } return parent; /* We expect, but can't guarantee, if parent != None, that: - parent.__name__ == buf diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 4017ac2..f4118d6 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -824,29 +824,12 @@ PyDoc_STRVAR(sys_clear_type_cache__doc__, Clear the internal type lookup cache."); -static PyObject * -sys_compact_freelists(PyObject* self, PyObject* args) -{ - size_t fsum, fbc, fbf; - - PyFloat_CompactFreeList(&fbc, &fbf, &fsum); - - return Py_BuildValue("((kkk))", fsum, fbc, fbf); - -} - -PyDoc_STRVAR(sys_compact_freelists__doc__, -"_compact_freelists() -> ((remaing_objects, total_blocks, freed_blocks),)\n\ -Compact the free lists of floats."); - static PyMethodDef sys_methods[] = { /* Might as well keep this in alphabetic order */ {"callstats", (PyCFunction)PyEval_GetCallStats, METH_NOARGS, callstats_doc}, {"_clear_type_cache", sys_clear_type_cache, METH_NOARGS, sys_clear_type_cache__doc__}, - {"_compact_freelists", sys_compact_freelists, METH_NOARGS, - sys_compact_freelists__doc__}, {"_current_frames", sys_current_frames, METH_NOARGS, current_frames_doc}, {"displayhook", sys_displayhook, METH_O, displayhook_doc}, diff --git a/Python/traceback.c b/Python/traceback.c index 55300fc..d569a18 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -129,7 +129,7 @@ PyTraceBack_Here(PyFrameObject *frame) } int -Py_DisplaySourceLine(PyObject *f, const char *filename, int lineno, int indent) +_Py_DisplaySourceLine(PyObject *f, const char *filename, int lineno, int indent) { int err = 0; FILE *xfp = NULL; @@ -241,7 +241,7 @@ tb_displayline(PyObject *f, const char *filename, int lineno, const char *name) err = PyFile_WriteString(linebuf, f); if (err != 0) return err; - return Py_DisplaySourceLine(f, filename, lineno, 4); + return _Py_DisplaySourceLine(f, filename, lineno, 4); } static int diff --git a/Tools/faqwiz/move-faqwiz.sh b/Tools/faqwiz/move-faqwiz.sh index 6a708aa..b3bcc92 100755 --- a/Tools/faqwiz/move-faqwiz.sh +++ b/Tools/faqwiz/move-faqwiz.sh @@ -9,7 +9,7 @@ # blackjesus:~> ./move-faqwiz.sh 2\.1 3\.2 # Moving FAQ question 02.001 to 03.002 -if [ x$2 == x ]; then +if [ x$2 = x ]; then echo "Need 2 args: original_version final_version." exit 2 fi @@ -19,7 +19,7 @@ if [ ! -d data -o ! -d data/RCS ]; then exit 2 fi -function cut_n_pad() { +cut_n_pad() { t=`echo $1 | cut -d. -f $2` export $3=`echo $t | awk "{ tmp = \\$0; l = length(tmp); for (i = 0; i < $2-l+1; i++) { tmp = "0".tmp } print tmp }"` } @@ -28,7 +28,13 @@ cut_n_pad $1 1 prefix1 cut_n_pad $1 2 suffix1 cut_n_pad $2 1 prefix2 cut_n_pad $2 2 suffix2 -tmpfile=tmp$RANDOM.tmp +if which tempfile >/dev/null; then + tmpfile=$(tempfile -d .) +elif [ -n "$RANDOM" ]; then + tmpfile=tmp$RANDOM.tmp +else + tmpfile=tmp$$.tmp +fi file1=faq$prefix1.$suffix1.htp file2=faq$prefix2.$suffix2.htp |