diff -r befd56673c80 -r 65c3af0d283b Doc/c-api/import.rst
--- a/Doc/c-api/import.rst Sun May 20 02:34:13 2012 +1000
+++ b/Doc/c-api/import.rst Sat May 19 17:01:25 2012 -0400
@@ -30,13 +30,13 @@
.. c:function:: PyObject* PyImport_ImportModuleNoBlock(const char *name)
- This function is a deprecated alias of :c:func:`PyImport_ImportModule`.
-
- .. versionchanged:: 3.3
- This function used to fail immediately when the import lock was held
- by another thread. In Python 3.3 though, the locking scheme switched
- to per-module locks for most purposes, so this function's special
- behaviour isn't needed anymore.
+ This version of :c:func:`PyImport_ImportModule` does not block. It's intended
+ to be used in C functions that import other modules to execute a function.
+ The import may block if another thread holds the import lock. The function
+ :c:func:`PyImport_ImportModuleNoBlock` never blocks. It first tries to fetch
+ the module from sys.modules and falls back to :c:func:`PyImport_ImportModule`
+ unless the lock is held, in which case the function will raise an
+ :exc:`ImportError`.
.. c:function:: PyObject* PyImport_ImportModuleEx(char *name, PyObject *globals, PyObject *locals, PyObject *fromlist)
diff -r befd56673c80 -r 65c3af0d283b Doc/library/__future__.rst
--- a/Doc/library/__future__.rst Sun May 20 02:34:13 2012 +1000
+++ b/Doc/library/__future__.rst Sat May 19 17:01:25 2012 -0400
@@ -75,7 +75,7 @@
| division | 2.2.0a2 | 3.0 | :pep:`238`: |
| | | | *Changing the Division Operator* |
+------------------+-------------+--------------+---------------------------------------------+
-| absolute_import | 2.5.0a1 | 3.0 | :pep:`328`: |
+| absolute_import | 2.5.0a1 | 2.7 | :pep:`328`: |
| | | | *Imports: Multi-Line and Absolute/Relative* |
+------------------+-------------+--------------+---------------------------------------------+
| with_statement | 2.5.0a1 | 2.6 | :pep:`343`: |
diff -r befd56673c80 -r 65c3af0d283b Doc/library/functions.rst
--- a/Doc/library/functions.rst Sun May 20 02:34:13 2012 +1000
+++ b/Doc/library/functions.rst Sat May 19 17:01:25 2012 -0400
@@ -1324,12 +1324,10 @@
Accordingly, :func:`super` is undefined for implicit lookups using statements or
operators such as ``super()[name]``.
- Also note that, aside from the zero argument form, :func:`super` is not
- limited to use inside methods. The two argument form specifies the
- arguments exactly and makes the appropriate references. The zero
- argument form only works inside a class definition, as the compiler fills
- in the necessary details to correctly retrieve the class being defined,
- as well as accessing the current instance for ordinary methods.
+ Also note that :func:`super` is not limited to use inside methods. The two
+ argument form specifies the arguments exactly and makes the appropriate
+ references. The zero argument form automatically searches the stack frame
+ for the class (``__class__``) and the first argument.
For practical suggestions on how to design cooperative classes using
:func:`super`, see `guide to using super()
diff -r befd56673c80 -r 65c3af0d283b Doc/library/imp.rst
--- a/Doc/library/imp.rst Sun May 20 02:34:13 2012 +1000
+++ b/Doc/library/imp.rst Sat May 19 17:01:25 2012 -0400
@@ -107,6 +107,37 @@
in ``sys.modules``.
+.. function:: lock_held()
+
+ Return ``True`` if the import lock is currently held, else ``False``. On
+ platforms without threads, always return ``False``.
+
+ On platforms with threads, a thread executing an import holds an internal lock
+ until the import is complete. This lock blocks other threads from doing an
+ import until the original import completes, which in turn prevents other threads
+ from seeing incomplete module objects constructed by the original thread while
+ in the process of completing its import (and the imports, if any, triggered by
+ that).
+
+
+.. function:: acquire_lock()
+
+ Acquire the interpreter's import lock for the current thread. This lock should
+ be used by import hooks to ensure thread-safety when importing modules.
+
+ Once a thread has acquired the import lock, the same thread may acquire it
+ again without blocking; the thread must release it once for each time it has
+ acquired it.
+
+ On platforms without threads, this function does nothing.
+
+
+.. function:: release_lock()
+
+ Release the interpreter's import lock. On platforms without threads, this
+ function does nothing.
+
+
.. function:: reload(module)
Reload a previously imported *module*. The argument must be a module object, so
@@ -204,49 +235,6 @@
magic number, as returned by :func:`get_magic`.
-The following functions help interact with the import system's internal
-locking mechanism. Locking semantics of imports are an implementation
-detail which may vary from release to release. However, Python ensures
-that circular imports work without any deadlocks.
-
-.. versionchanged:: 3.3
- In Python 3.3, the locking scheme has changed to per-module locks for
- the most part. A global import lock is kept for some critical tasks,
- such as initializing the per-module locks.
-
-
-.. function:: lock_held()
-
- Return ``True`` if the global import lock is currently held, else
- ``False``. On platforms without threads, always return ``False``.
-
- On platforms with threads, a thread executing an import first holds a
- global import lock, then sets up a per-module lock for the rest of the
- import. This blocks other threads from importing the same module until
- the original import completes, preventing other threads from seeing
- incomplete module objects constructed by the original thread. An
- exception is made for circular imports, which by construction have to
- expose an incomplete module object at some point.
-
-.. function:: acquire_lock()
-
- Acquire the interpreter's global import lock for the current thread.
- This lock should be used by import hooks to ensure thread-safety when
- importing modules.
-
- Once a thread has acquired the import lock, the same thread may acquire it
- again without blocking; the thread must release it once for each time it has
- acquired it.
-
- On platforms without threads, this function does nothing.
-
-
-.. function:: release_lock()
-
- Release the interpreter's global import lock. On platforms without
- threads, this function does nothing.
-
-
The following constants with integer values, defined in this module, are used
to indicate the search result of :func:`find_module`.
diff -r befd56673c80 -r 65c3af0d283b Doc/library/multiprocessing.rst
--- a/Doc/library/multiprocessing.rst Sun May 20 02:34:13 2012 +1000
+++ b/Doc/library/multiprocessing.rst Sat May 19 17:01:25 2012 -0400
@@ -120,7 +120,9 @@
print(q.get()) # prints "[42, None, 'hello']"
p.join()
- Queues are thread and process safe.
+ Queues are thread and process safe, but note that they must never
+ be instantiated as a side effect of importing a module: this can lead
+ to a deadlock! (see :ref:`threaded-imports`)
**Pipes**
diff -r befd56673c80 -r 65c3af0d283b Doc/library/textwrap.rst
--- a/Doc/library/textwrap.rst Sun May 20 02:34:13 2012 +1000
+++ b/Doc/library/textwrap.rst Sat May 19 17:01:25 2012 -0400
@@ -107,15 +107,6 @@
expanded to spaces using the :meth:`expandtabs` method of *text*.
- .. attribute:: tabsize
-
- (default: ``8``) If :attr:`expand_tabs` is true, then all tab characters
- in *text* will be expanded to zero or more spaces, depending on the
- current column and the given tab size.
-
- .. versionadded:: 3.3
-
-
.. attribute:: replace_whitespace
(default: ``True``) If true, each whitespace character (as defined by
diff -r befd56673c80 -r 65c3af0d283b Doc/library/threading.rst
--- a/Doc/library/threading.rst Sun May 20 02:34:13 2012 +1000
+++ b/Doc/library/threading.rst Sat May 19 17:01:25 2012 -0400
@@ -426,12 +426,15 @@
Acquire a lock, blocking or non-blocking.
- When invoked with the *blocking* argument set to ``True`` (the default),
- block until the lock is unlocked, then set it to locked and return ``True``.
+ When invoked without arguments, block until the lock is unlocked, then set it to
+ locked, and return true.
- When invoked with the *blocking* argument set to ``False``, do not block.
- If a call with *blocking* set to ``True`` would block, return ``False``
- immediately; otherwise, set the lock to locked and return ``True``.
+ When invoked with the *blocking* argument set to true, do the same thing as when
+ called without arguments, and return true.
+
+ When invoked with the *blocking* argument set to false, do not block. If a call
+ without an argument would block, return false immediately; otherwise, do the
+ same thing as when called without arguments, and return true.
When invoked with the floating-point *timeout* argument set to a positive
value, block for at most the number of seconds specified by *timeout*
@@ -996,3 +999,27 @@
Currently, :class:`Lock`, :class:`RLock`, :class:`Condition`,
:class:`Semaphore`, and :class:`BoundedSemaphore` objects may be used as
:keyword:`with` statement context managers.
+
+
+.. _threaded-imports:
+
+Importing in threaded code
+--------------------------
+
+While the import machinery is thread-safe, there are two key restrictions on
+threaded imports due to inherent limitations in the way that thread-safety is
+provided:
+
+* Firstly, other than in the main module, an import should not have the
+ side effect of spawning a new thread and then waiting for that thread in
+ any way. Failing to abide by this restriction can lead to a deadlock if
+ the spawned thread directly or indirectly attempts to import a module.
+* Secondly, all import attempts must be completed before the interpreter
+ starts shutting itself down. This can be most easily achieved by only
+ performing imports from non-daemon threads created through the threading
+ module. Daemon threads and threads created directly with the thread
+ module will require some other form of synchronization to ensure they do
+ not attempt imports after system shutdown has commenced. Failure to
+ abide by this restriction will lead to intermittent exceptions and
+ crashes during interpreter shutdown (as the late imports attempt to
+ access machinery which is no longer in a valid state).
diff -r befd56673c80 -r 65c3af0d283b Doc/library/time.rst
--- a/Doc/library/time.rst Sun May 20 02:34:13 2012 +1000
+++ b/Doc/library/time.rst Sat May 19 17:01:25 2012 -0400
@@ -62,9 +62,9 @@
the units in which their value or argument is expressed. E.g. on most Unix
systems, the clock "ticks" only 50 or 100 times a second.
-* On the other hand, the precision of :func:`.time` and :func:`sleep` is better
+* On the other hand, the precision of :func:`time` and :func:`sleep` is better
than their Unix equivalents: times are expressed as floating point numbers,
- :func:`.time` returns the most accurate time available (using Unix
+ :func:`time` returns the most accurate time available (using Unix
:c:func:`gettimeofday` where available), and :func:`sleep` will accept a time
with a nonzero fraction (Unix :c:func:`select` is used to implement this, where
available).
@@ -256,7 +256,7 @@
Convert a time expressed in seconds since the epoch to a string representing
local time. If *secs* is not provided or :const:`None`, the current time as
- returned by :func:`.time` is used. ``ctime(secs)`` is equivalent to
+ returned by :func:`time` is used. ``ctime(secs)`` is equivalent to
``asctime(localtime(secs))``. Locale information is not used by :func:`ctime`.
@@ -284,7 +284,7 @@
Convert a time expressed in seconds since the epoch to a :class:`struct_time` in
UTC in which the dst flag is always zero. If *secs* is not provided or
- :const:`None`, the current time as returned by :func:`.time` is used. Fractions
+ :const:`None`, the current time as returned by :func:`time` is used. Fractions
of a second are ignored. See above for a description of the
:class:`struct_time` object. See :func:`calendar.timegm` for the inverse of this
function.
@@ -293,7 +293,7 @@
.. function:: localtime([secs])
Like :func:`gmtime` but converts to local time. If *secs* is not provided or
- :const:`None`, the current time as returned by :func:`.time` is used. The dst
+ :const:`None`, the current time as returned by :func:`time` is used. The dst
flag is set to ``1`` when DST applies to the given time.
@@ -302,7 +302,7 @@
This is the inverse function of :func:`localtime`. Its argument is the
:class:`struct_time` or full 9-tuple (since the dst flag is needed; use ``-1``
as the dst flag if it is unknown) which expresses the time in *local* time, not
- UTC. It returns a floating point number, for compatibility with :func:`.time`.
+ UTC. It returns a floating point number, for compatibility with :func:`time`.
If the input value cannot be represented as a valid time, either
:exc:`OverflowError` or :exc:`ValueError` will be raised (which depends on
whether the invalid value is caught by Python or the underlying C libraries).
diff -r befd56673c80 -r 65c3af0d283b Doc/library/types.rst
--- a/Doc/library/types.rst Sun May 20 02:34:13 2012 +1000
+++ b/Doc/library/types.rst Sat May 19 17:01:25 2012 -0400
@@ -1,5 +1,5 @@
-:mod:`types` --- Dynamic type creation and names for built-in types
-===================================================================
+:mod:`types` --- Names for built-in types
+=========================================
.. module:: types
:synopsis: Names for built-in types.
@@ -8,69 +8,20 @@
--------------
-This module defines utility function to assist in dynamic creation of
-new types.
+This module defines names for some object types that are used by the standard
+Python interpreter, but not exposed as builtins like :class:`int` or
+:class:`str` are. Also, it does not include some of the types that arise
+transparently during processing such as the ``listiterator`` type.
-It also defines names for some object types that are used by the standard
-Python interpreter, but not exposed as builtins like :class:`int` or
-:class:`str` are.
+Typical use is for :func:`isinstance` or :func:`issubclass` checks.
-
-Dynamic Type Creation
----------------------
-
-.. function:: new_class(name, bases=(), kwds=None, exec_body=None)
-
- Creates a class object dynamically using the appropriate metaclass.
-
- The arguments are the components that make up a class definition: the
- class name, the base classes (in order), the keyword arguments (such as
- ``metaclass``) and the callback function to populate the class namespace.
-
- The *exec_body* callback should accept the class namespace as its sole
- argument and update the namespace directly with the class contents.
-
-.. function:: prepare_class(name, bases=(), kwds=None)
-
- Calculates the appropriate metaclass and creates the class namespace.
-
- The arguments are the components that make up a class definition: the
- class name, the base classes (in order) and the keyword arguments (such as
- ``metaclass``).
-
- The return value is a 3-tuple: ``metaclass, namespace, kwds``
-
- *metaclass* is the appropriate metaclass
- *namespace* is the prepared class namespace
- *kwds* is an updated copy of the passed in *kwds* argument with any
- ``'metaclass'`` entry removed. If no *kwds* argument is passed in, this
- will be an empty dict.
-
-
-.. seealso::
-
- :pep:`3115` - Metaclasses in Python 3000
- Introduced the ``__prepare__`` namespace hook
-
-
-Standard Interpreter Types
---------------------------
-
-This module provides names for many of the types that are required to
-implement a Python interpreter. It deliberately avoids including some of
-the types that arise only incidentally during processing such as the
-``listiterator`` type.
-
-Typical use is of these names is for :func:`isinstance` or
-:func:`issubclass` checks.
-
-Standard names are defined for the following types:
+The module defines the following names:
.. data:: FunctionType
LambdaType
- The type of user-defined functions and functions created by
- :keyword:`lambda` expressions.
+ The type of user-defined functions and functions created by :keyword:`lambda`
+ expressions.
.. data:: GeneratorType
diff -r befd56673c80 -r 65c3af0d283b Doc/reference/datamodel.rst
--- a/Doc/reference/datamodel.rst Sun May 20 02:34:13 2012 +1000
+++ b/Doc/reference/datamodel.rst Sat May 19 17:01:25 2012 -0400
@@ -1550,115 +1550,53 @@
Customizing class creation
--------------------------
-By default, classes are constructed using :func:`type`. The class body is
-executed in a new namespace and the class name is bound locally to the
-result of ``type(name, bases, namespace)``.
+By default, classes are constructed using :func:`type`. A class definition is
+read into a separate namespace and the value of class name is bound to the
+result of ``type(name, bases, dict)``.
-The class creation process can be customised by passing the ``metaclass``
-keyword argument in the class definition line, or by inheriting from an
-existing class that included such an argument. In the following example,
-both ``MyClass`` and ``MySubclass`` are instances of ``Meta``::
+When the class definition is read, if a callable ``metaclass`` keyword argument
+is passed after the bases in the class definition, the callable given will be
+called instead of :func:`type`. If other keyword arguments are passed, they
+will also be passed to the metaclass. This allows classes or functions to be
+written which monitor or alter the class creation process:
- class Meta(type):
- pass
+* Modifying the class dictionary prior to the class being created.
- class MyClass(metaclass=Meta):
- pass
+* Returning an instance of another class -- essentially performing the role of a
+ factory function.
- class MySubclass(MyClass):
- pass
+These steps will have to be performed in the metaclass's :meth:`__new__` method
+-- :meth:`type.__new__` can then be called from this method to create a class
+with different properties. This example adds a new element to the class
+dictionary before creating the class::
-Any other keyword arguments that are specified in the class definition are
-passed through to all metaclass operations described below.
+ class metacls(type):
+ def __new__(mcs, name, bases, dict):
+ dict['foo'] = 'metacls was here'
+ return type.__new__(mcs, name, bases, dict)
-When a class definition is executed, the following steps occur:
+You can of course also override other class methods (or add new methods); for
+example defining a custom :meth:`__call__` method in the metaclass allows custom
+behavior when the class is called, e.g. not always creating a new instance.
-* the appropriate metaclass is determined
-* the class namespace is prepared
-* the class body is executed
-* the class object is created
+If the metaclass has a :meth:`__prepare__` attribute (usually implemented as a
+class or static method), it is called before the class body is evaluated with
+the name of the class and a tuple of its bases for arguments. It should return
+an object that supports the mapping interface that will be used to store the
+namespace of the class. The default is a plain dictionary. This could be used,
+for example, to keep track of the order that class attributes are declared in by
+returning an ordered dictionary.
-Determining the appropriate metaclass
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+The appropriate metaclass is determined by the following precedence rules:
-The appropriate metaclass for a class definition is determined as follows:
+* If the ``metaclass`` keyword argument is passed with the bases, it is used.
-* if no bases and no explicit metaclass are given, then :func:`type` is used
-* if an explicit metaclass is given and it is *not* an instance of
- :func:`type`, then it is used directly as the metaclass
-* if an instance of :func:`type` is given as the explicit metaclass, or
- bases are defined, then the most derived metaclass is used
+* Otherwise, if there is at least one base class, its metaclass is used.
-The most derived metaclass is selected from the explicitly specified
-metaclass (if any) and the metaclasses (i.e. ``type(cls)``) of all specified
-base classes. The most derived metaclass is one which is a subtype of *all*
-of these candidate metaclasses. If none of the candidate metaclasses meets
-that criterion, then the class definition will fail with ``TypeError``.
-
-
-Preparing the class namespace
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Once the appropriate metaclass has been identified, then the class namespace
-is prepared. If the metaclass has a ``__prepare__`` attribute, it is called
-as ``namespace = metaclass.__prepare__(name, bases, **kwds)`` (where the
-additional keyword arguments, if any, come from the class definition).
-
-If the metaclass has no ``__prepare__`` attribute, then the class namespace
-is initialised as an empty :func:`dict` instance.
-
-.. seealso::
-
- :pep:`3115` - Metaclasses in Python 3000
- Introduced the ``__prepare__`` namespace hook
-
-
-Executing the class body
-^^^^^^^^^^^^^^^^^^^^^^^^
-
-The class body is executed (approximately) as
-``exec(body, globals(), namespace)``. The key difference from a normal
-call to :func:`exec` is that lexical scoping allows the class body (including
-any methods) to reference names from the current and outer scopes when the
-class definition occurs inside a function.
-
-However, even when the class definition occurs inside the function, methods
-defined inside the class still cannot see names defined at the class scope.
-Class variables must be accessed through the first parameter of instance or
-class methods, and cannot be accessed at all from static methods.
-
-
-Creating the class object
-^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Once the class namespace has been populated by executing the class body,
-the class object is created by calling
-``metaclass(name, bases, namespace, **kwds)`` (the additional keywords
-passed here are the same as those passed to ``__prepate__``).
-
-This class object is the one that will be referenced by the zero-argument
-form of :func:`super`. ``__class__`` is an implicit closure reference
-created by the compiler if any methods in a class body refer to either
-``__class__`` or ``super``. This allows the zero argument form of
-:func:`super` to correctly identify the class being defined based on
-lexical scoping, while the class or instance that was used to make the
-current call is identified based on the first argument passed to the method.
-
-After the class object is created, any class decorators included in the
-function definition are invoked and the resulting object is bound in the
-local namespace to the name of the class.
-
-.. seealso::
-
- :pep:`3135` - New super
- Describes the implicit ``__class__`` closure reference
-
-
-Metaclass example
-^^^^^^^^^^^^^^^^^
+* Otherwise, the default metaclass (:class:`type`) is used.
The potential uses for metaclasses are boundless. Some ideas that have been
-explored include logging, interface checking, automatic delegation, automatic
+explored including logging, interface checking, automatic delegation, automatic
property creation, proxies, frameworks, and automatic resource
locking/synchronization.
@@ -1671,9 +1609,9 @@
def __prepare__(metacls, name, bases, **kwds):
return collections.OrderedDict()
- def __new__(cls, name, bases, namespace, **kwds):
- result = type.__new__(cls, name, bases, dict(namespace))
- result.members = tuple(namespace)
+ def __new__(cls, name, bases, classdict):
+ result = type.__new__(cls, name, bases, dict(classdict))
+ result.members = tuple(classdict)
return result
class A(metaclass=OrderedClass):
diff -r befd56673c80 -r 65c3af0d283b Doc/whatsnew/3.3.rst
--- a/Doc/whatsnew/3.3.rst Sun May 20 02:34:13 2012 +1000
+++ b/Doc/whatsnew/3.3.rst Sat May 19 17:01:25 2012 -0400
@@ -573,23 +573,6 @@
.. XXX mention new error messages for passing wrong number of arguments to functions
-A Finer-Grained Import Lock
-===========================
-
-Previous versions of CPython have always relied on a global import lock.
-This led to unexpected annoyances, such as deadlocks when importing a module
-would trigger code execution in a different thread as a side-effect.
-Clumsy workarounds were sometimes employed, such as the
-:c:func:`PyImport_ImportModuleNoBlock` C API function.
-
-In Python 3.3, importing a module takes a per-module lock. This correctly
-serializes importation of a given module from multiple threads (preventing
-the exposure of incompletely initialized modules), while eliminating the
-aforementioned annoyances.
-
-(contributed by Antoine Pitrou in :issue:`9260`.)
-
-
New and Improved Modules
========================
@@ -1239,10 +1222,6 @@
(:issue:`14386`)
-The new functions `types.new_class` and `types.prepare_class` provide support
-for PEP 3115 compliant dynamic type creation. (:issue:`14588`)
-
-
urllib
------
@@ -1281,10 +1260,6 @@
* repeating a single ASCII letter and getting a substring of a ASCII strings
is 4 times faster
-* UTF-8 and UTF-16 decoding is now 2x to 4x faster.
-
- (contributed by Serhiy Storchaka, :issue:`14624` and :issue:`14738`.)
-
Build and C API Changes
=======================
diff -r befd56673c80 -r 65c3af0d283b Lib/__future__.py
--- a/Lib/__future__.py Sun May 20 02:34:13 2012 +1000
+++ b/Lib/__future__.py Sat May 19 17:01:25 2012 -0400
@@ -114,7 +114,7 @@
CO_FUTURE_DIVISION)
absolute_import = _Feature((2, 5, 0, "alpha", 1),
- (3, 0, 0, "alpha", 0),
+ (2, 7, 0, "alpha", 0),
CO_FUTURE_ABSOLUTE_IMPORT)
with_statement = _Feature((2, 5, 0, "alpha", 1),
diff -r befd56673c80 -r 65c3af0d283b Lib/http/client.py
--- a/Lib/http/client.py Sun May 20 02:34:13 2012 +1000
+++ b/Lib/http/client.py Sat May 19 17:01:25 2012 -0400
@@ -1076,7 +1076,7 @@
self.putrequest(method, url, **skips)
- if body is not None and ('content-length' not in header_names):
+ if body and ('content-length' not in header_names):
self._set_content_length(body)
for hdr, value in headers.items():
self.putheader(hdr, value)
diff -r befd56673c80 -r 65c3af0d283b Lib/importlib/_bootstrap.py
--- a/Lib/importlib/_bootstrap.py Sun May 20 02:34:13 2012 +1000
+++ b/Lib/importlib/_bootstrap.py Sat May 19 17:01:25 2012 -0400
@@ -159,145 +159,6 @@
return type(_io)(name)
-# Module-level locking ########################################################
-
-# A dict mapping module names to weakrefs of _ModuleLock instances
-_module_locks = {}
-# A dict mapping thread ids to _ModuleLock instances
-_blocking_on = {}
-
-
-class _DeadlockError(RuntimeError):
- pass
-
-
-class _ModuleLock:
- """A recursive lock implementation which is able to detect deadlocks
- (e.g. thread 1 trying to take locks A then B, and thread 2 trying to
- take locks B then A).
- """
-
- def __init__(self, name):
- self.lock = _thread.allocate_lock()
- self.wakeup = _thread.allocate_lock()
- self.name = name
- self.owner = None
- self.count = 0
- self.waiters = 0
-
- def has_deadlock(self):
- # Deadlock avoidance for concurrent circular imports.
- me = _thread.get_ident()
- tid = self.owner
- while True:
- lock = _blocking_on.get(tid)
- if lock is None:
- return False
- tid = lock.owner
- if tid == me:
- return True
-
- def acquire(self):
- """
- Acquire the module lock. If a potential deadlock is detected,
- a _DeadlockError is raised.
- Otherwise, the lock is always acquired and True is returned.
- """
- tid = _thread.get_ident()
- _blocking_on[tid] = self
- try:
- while True:
- with self.lock:
- if self.count == 0 or self.owner == tid:
- self.owner = tid
- self.count += 1
- return True
- if self.has_deadlock():
- raise _DeadlockError("deadlock detected by %r" % self)
- if self.wakeup.acquire(False):
- self.waiters += 1
- # Wait for a release() call
- self.wakeup.acquire()
- self.wakeup.release()
- finally:
- del _blocking_on[tid]
-
- def release(self):
- tid = _thread.get_ident()
- with self.lock:
- if self.owner != tid:
- raise RuntimeError("cannot release un-acquired lock")
- assert self.count > 0
- self.count -= 1
- if self.count == 0:
- self.owner = None
- if self.waiters:
- self.waiters -= 1
- self.wakeup.release()
-
- def __repr__(self):
- return "_ModuleLock(%r) at %d" % (self.name, id(self))
-
-
-class _DummyModuleLock:
- """A simple _ModuleLock equivalent for Python builds without
- multi-threading support."""
-
- def __init__(self, name):
- self.name = name
- self.count = 0
-
- def acquire(self):
- self.count += 1
- return True
-
- def release(self):
- if self.count == 0:
- raise RuntimeError("cannot release un-acquired lock")
- self.count -= 1
-
- def __repr__(self):
- return "_DummyModuleLock(%r) at %d" % (self.name, id(self))
-
-
-# The following two functions are for consumption by Python/import.c.
-
-def _get_module_lock(name):
- """Get or create the module lock for a given module name.
-
- Should only be called with the import lock taken."""
- lock = None
- if name in _module_locks:
- lock = _module_locks[name]()
- if lock is None:
- if _thread is None:
- lock = _DummyModuleLock(name)
- else:
- lock = _ModuleLock(name)
- def cb(_):
- del _module_locks[name]
- _module_locks[name] = _weakref.ref(lock, cb)
- return lock
-
-def _lock_unlock_module(name):
- """Release the global import lock, and acquires then release the
- module lock for a given module name.
- This is used to ensure a module is completely initialized, in the
- event it is being imported by another thread.
-
- Should only be called with the import lock taken."""
- lock = _get_module_lock(name)
- _imp.release_lock()
- try:
- lock.acquire()
- except _DeadlockError:
- # Concurrent circular import, we'll accept a partially initialized
- # module object.
- pass
- else:
- lock.release()
-
-
# Finder/loader utility code ##################################################
_PYCACHE = '__pycache__'
@@ -403,15 +264,12 @@
else:
module.__package__ = fullname.rpartition('.')[0]
try:
- module.__initializing__ = True
# If __package__ was not set above, __import__() will do it later.
return fxn(self, module, *args, **kwargs)
except:
if not is_reload:
del sys.modules[fullname]
raise
- finally:
- module.__initializing__ = False
_wrap(module_for_loader_wrapper, fxn)
return module_for_loader_wrapper
@@ -1074,8 +932,7 @@
if not sys.meta_path:
_warnings.warn('sys.meta_path is empty', ImportWarning)
for finder in sys.meta_path:
- with _ImportLockContext():
- loader = finder.find_module(name, path)
+ loader = finder.find_module(name, path)
if loader is not None:
# The parent import may have already imported this module.
if name not in sys.modules:
@@ -1105,7 +962,8 @@
_ERR_MSG = 'No module named {!r}'
-def _find_and_load_unlocked(name, import_):
+def _find_and_load(name, import_):
+ """Find and load the module."""
path = None
parent = name.rpartition('.')[0]
if parent:
@@ -1151,19 +1009,6 @@
return module
-def _find_and_load(name, import_):
- """Find and load the module, and release the import lock."""
- try:
- lock = _get_module_lock(name)
- finally:
- _imp.release_lock()
- lock.acquire()
- try:
- return _find_and_load_unlocked(name, import_)
- finally:
- lock.release()
-
-
def _gcd_import(name, package=None, level=0):
"""Import and return the module based on its name, the package the call is
being made from, and the level adjustment.
@@ -1176,17 +1021,17 @@
_sanity_check(name, package, level)
if level > 0:
name = _resolve_name(name, package, level)
- _imp.acquire_lock()
- if name not in sys.modules:
+ with _ImportLockContext():
+ try:
+ module = sys.modules[name]
+ if module is None:
+ message = ("import of {} halted; "
+ "None in sys.modules".format(name))
+ raise ImportError(message, name=name)
+ return module
+ except KeyError:
+ pass # Don't want to chain the exception
return _find_and_load(name, _gcd_import)
- module = sys.modules[name]
- if module is None:
- _imp.release_lock()
- message = ("import of {} halted; "
- "None in sys.modules".format(name))
- raise ImportError(message, name=name)
- _lock_unlock_module(name)
- return module
def _handle_fromlist(module, fromlist, import_):
@@ -1304,17 +1149,7 @@
continue
else:
raise ImportError('importlib requires posix or nt')
-
- try:
- thread_module = BuiltinImporter.load_module('_thread')
- except ImportError:
- # Python was built without threads
- thread_module = None
- weakref_module = BuiltinImporter.load_module('_weakref')
-
setattr(self_module, '_os', os_module)
- setattr(self_module, '_thread', thread_module)
- setattr(self_module, '_weakref', weakref_module)
setattr(self_module, 'path_sep', path_sep)
setattr(self_module, 'path_separators', set(path_separators))
# Constants
diff -r befd56673c80 -r 65c3af0d283b Lib/importlib/test/test_locks.py
--- a/Lib/importlib/test/test_locks.py Sun May 20 02:34:13 2012 +1000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-from importlib import _bootstrap
-import time
-import unittest
-import weakref
-
-from test import support
-
-try:
- import threading
-except ImportError:
- threading = None
-else:
- from test import lock_tests
-
-
-LockType = _bootstrap._ModuleLock
-DeadlockError = _bootstrap._DeadlockError
-
-
-if threading is not None:
- class ModuleLockAsRLockTests(lock_tests.RLockTests):
- locktype = staticmethod(lambda: LockType("some_lock"))
-
- # _is_owned() unsupported
- test__is_owned = None
- # acquire(blocking=False) unsupported
- test_try_acquire = None
- test_try_acquire_contended = None
- # `with` unsupported
- test_with = None
- # acquire(timeout=...) unsupported
- test_timeout = None
- # _release_save() unsupported
- test_release_save_unacquired = None
-
-else:
- class ModuleLockAsRLockTests(unittest.TestCase):
- pass
-
-
-@unittest.skipUnless(threading, "threads needed for this test")
-class DeadlockAvoidanceTests(unittest.TestCase):
-
- def run_deadlock_avoidance_test(self, create_deadlock):
- NLOCKS = 10
- locks = [LockType(str(i)) for i in range(NLOCKS)]
- pairs = [(locks[i], locks[(i+1)%NLOCKS]) for i in range(NLOCKS)]
- if create_deadlock:
- NTHREADS = NLOCKS
- else:
- NTHREADS = NLOCKS - 1
- barrier = threading.Barrier(NTHREADS)
- results = []
- def _acquire(lock):
- """Try to acquire the lock. Return True on success, False on deadlock."""
- try:
- lock.acquire()
- except DeadlockError:
- return False
- else:
- return True
- def f():
- a, b = pairs.pop()
- ra = _acquire(a)
- barrier.wait()
- rb = _acquire(b)
- results.append((ra, rb))
- if rb:
- b.release()
- if ra:
- a.release()
- lock_tests.Bunch(f, NTHREADS).wait_for_finished()
- self.assertEqual(len(results), NTHREADS)
- return results
-
- def test_deadlock(self):
- results = self.run_deadlock_avoidance_test(True)
- # One of the threads detected a potential deadlock on its second
- # acquire() call.
- self.assertEqual(results.count((True, False)), 1)
- self.assertEqual(results.count((True, True)), len(results) - 1)
-
- def test_no_deadlock(self):
- results = self.run_deadlock_avoidance_test(False)
- self.assertEqual(results.count((True, False)), 0)
- self.assertEqual(results.count((True, True)), len(results))
-
-
-class LifetimeTests(unittest.TestCase):
-
- def test_lock_lifetime(self):
- name = "xyzzy"
- self.assertNotIn(name, _bootstrap._module_locks)
- lock = _bootstrap._get_module_lock(name)
- self.assertIn(name, _bootstrap._module_locks)
- wr = weakref.ref(lock)
- del lock
- support.gc_collect()
- self.assertNotIn(name, _bootstrap._module_locks)
- self.assertIs(wr(), None)
-
- def test_all_locks(self):
- support.gc_collect()
- self.assertEqual(0, len(_bootstrap._module_locks))
-
-
-@support.reap_threads
-def test_main():
- support.run_unittest(ModuleLockAsRLockTests,
- DeadlockAvoidanceTests,
- LifetimeTests)
-
-
-if __name__ == '__main__':
- test_main()
diff -r befd56673c80 -r 65c3af0d283b Lib/multiprocessing/forking.py
--- a/Lib/multiprocessing/forking.py Sun May 20 02:34:13 2012 +1000
+++ b/Lib/multiprocessing/forking.py Sat May 19 17:01:25 2012 -0400
@@ -324,8 +324,7 @@
return [sys.executable, '--multiprocessing-fork']
else:
prog = 'from multiprocessing.forking import main; main()'
- opts = util._args_from_interpreter_flags()
- return [_python_exe] + opts + ['-c', prog, '--multiprocessing-fork']
+ return [_python_exe, '-c', prog, '--multiprocessing-fork']
def main():
diff -r befd56673c80 -r 65c3af0d283b Lib/multiprocessing/util.py
--- a/Lib/multiprocessing/util.py Sun May 20 02:34:13 2012 +1000
+++ b/Lib/multiprocessing/util.py Sat May 19 17:01:25 2012 -0400
@@ -7,14 +7,12 @@
# Licensed to PSF under a Contributor Agreement.
#
-import sys
import functools
import itertools
import weakref
import atexit
import threading # we want threading to install it's
# cleanup function before multiprocessing does
-from subprocess import _args_from_interpreter_flags
from multiprocessing.process import current_process, active_children
diff -r befd56673c80 -r 65c3af0d283b Lib/packaging/command/build_ext.py
--- a/Lib/packaging/command/build_ext.py Sun May 20 02:34:13 2012 +1000
+++ b/Lib/packaging/command/build_ext.py Sat May 19 17:01:25 2012 -0400
@@ -375,10 +375,6 @@
# Next, compile the source code to object files.
- # XXX not honouring 'define_macros' or 'undef_macros' -- the
- # CCompiler API needs to change to accommodate this, and I
- # want to do one thing at a time!
-
# Two possible sources for extra compiler arguments:
# - 'extra_compile_args' in Extension object
# - CFLAGS environment variable (not particularly
@@ -389,7 +385,7 @@
# command-line args. Hence we combine them in order:
extra_args = ext.extra_compile_args or []
- macros = ext.define_macros[:]
+ macros = [(macro, '1') for macro in ext.define_macros]
for undef in ext.undef_macros:
macros.append((undef,))
diff -r befd56673c80 -r 65c3af0d283b Lib/packaging/command/install_data.py
--- a/Lib/packaging/command/install_data.py Sun May 20 02:34:13 2012 +1000
+++ b/Lib/packaging/command/install_data.py Sat May 19 17:01:25 2012 -0400
@@ -3,6 +3,7 @@
# Contributed by Bastian Kleineidam
import os
+from functools import partial
from shutil import Error
from sysconfig import get_paths, format_value
from packaging import logger
@@ -27,24 +28,24 @@
def initialize_options(self):
self.install_dir = None
+ self.distinfo_dir = None
self.outfiles = []
self.data_files_out = []
self.root = None
self.force = False
self.data_files = self.distribution.data_files
self.warn_dir = True
+ self.extra_dist_info = []
def finalize_options(self):
self.set_undefined_options('install_dist',
('install_data', 'install_dir'),
'root', 'force')
+ self.set_undefined_options('install_distinfo',
+ 'distinfo_dir')
def run(self):
- self.mkpath(self.install_dir)
- for _file in self.data_files.items():
- destination = convert_path(self.expand_categories(_file[1]))
- dir_dest = os.path.abspath(os.path.dirname(destination))
-
+ def do_copy(_file, dir_dest, destination):
self.mkpath(dir_dest)
try:
out = self.copy_file(_file[0], dir_dest)[0]
@@ -55,9 +56,20 @@
self.outfiles.append(out)
self.data_files_out.append((_file[0], destination))
+ self.mkpath(self.install_dir)
+ for _file in self.data_files.items():
+ destination = convert_path(self.expand_categories(_file[1]))
+ dir_dest = os.path.abspath(os.path.dirname(destination))
+ copy = partial(do_copy, _file, dir_dest, destination)
+ if destination.startswith(self.distinfo_dir):
+ self.extra_dist_info.append(copy)
+ else:
+ copy()
+
def expand_categories(self, path_with_categories):
local_vars = get_paths()
local_vars['distribution.name'] = self.distribution.metadata['Name']
+ local_vars['dist-info'] = self.distinfo_dir
expanded_path = format_value(path_with_categories, local_vars)
expanded_path = format_value(expanded_path, local_vars)
if '{' in expanded_path and '}' in expanded_path:
diff -r befd56673c80 -r 65c3af0d283b Lib/packaging/command/install_distinfo.py
--- a/Lib/packaging/command/install_distinfo.py Sun May 20 02:34:13 2012 +1000
+++ b/Lib/packaging/command/install_distinfo.py Sat May 19 17:01:25 2012 -0400
@@ -36,6 +36,7 @@
def initialize_options(self):
self.install_dir = None
+ self.install_base = None
self.installer = None
self.requested = None
self.no_record = None
@@ -44,7 +45,7 @@
def finalize_options(self):
self.set_undefined_options('install_dist',
- 'installer', 'requested', 'no_record')
+ 'installer', 'requested', 'no_record', 'install_base')
self.set_undefined_options('install_lib', 'install_dir')
@@ -63,26 +64,46 @@
basename = metadata.get_fullname(filesafe=True) + ".dist-info"
- self.install_dir = os.path.join(self.install_dir, basename)
-
+ self.distinfo_dir = os.path.join(self.install_dir, basename)
+
+ @staticmethod
+ def pep376path(fpath, install_base, install_dir):
+ """Return PEP-376 path (but always with platform path separators)"""
+ # install_base is 'prefix' from PEP-376
+ install_base = install_base.rstrip(os.path.sep) + os.path.sep
+ # install_dir is 'base location' from PEP-376
+ install_dir = install_dir.rstrip(os.path.sep) + os.path.sep
+ install_dir_in_base = install_dir.startswith(install_base)
+ if fpath.startswith(install_dir) or \
+ fpath.startswith(install_base) and install_dir_in_base:
+ rpath = os.path.relpath(fpath, install_dir)
+ else:
+ rpath = os.path.abspath(fpath)
+ return rpath
+
def run(self):
- target = self.install_dir
+ target = self.distinfo_dir
if os.path.isdir(target) and not os.path.islink(target):
if not self.dry_run:
rmtree(target)
elif os.path.exists(target):
- self.execute(os.unlink, (self.install_dir,),
+ self.execute(os.unlink, (self.distinfo_dir,),
"removing " + target)
self.execute(os.makedirs, (target,), "creating " + target)
+
+ if not self.dry_run:
+ install_data = self.get_finalized_command('install_data')
+ while install_data.extra_dist_info:
+ install_data.extra_dist_info.pop()()
- metadata_path = os.path.join(self.install_dir, 'METADATA')
+ metadata_path = os.path.join(self.distinfo_dir, 'METADATA')
self.execute(self.distribution.metadata.write, (metadata_path,),
"creating " + metadata_path)
self.outfiles.append(metadata_path)
- installer_path = os.path.join(self.install_dir, 'INSTALLER')
+ installer_path = os.path.join(self.distinfo_dir, 'INSTALLER')
logger.info('creating %s', installer_path)
if not self.dry_run:
with open(installer_path, 'w') as f:
@@ -90,7 +111,7 @@
self.outfiles.append(installer_path)
if self.requested:
- requested_path = os.path.join(self.install_dir, 'REQUESTED')
+ requested_path = os.path.join(self.distinfo_dir, 'REQUESTED')
logger.info('creating %s', requested_path)
if not self.dry_run:
open(requested_path, 'wb').close()
@@ -99,7 +120,7 @@
if not self.no_resources:
install_data = self.get_finalized_command('install_data')
if install_data.get_resources_out() != []:
- resources_path = os.path.join(self.install_dir,
+ resources_path = os.path.join(self.distinfo_dir,
'RESOURCES')
logger.info('creating %s', resources_path)
if not self.dry_run:
@@ -113,7 +134,7 @@
self.outfiles.append(resources_path)
if not self.no_record:
- record_path = os.path.join(self.install_dir, 'RECORD')
+ record_path = os.path.join(self.distinfo_dir, 'RECORD')
logger.info('creating %s', record_path)
if not self.dry_run:
with open(record_path, 'w', encoding='utf-8') as f:
@@ -121,22 +142,23 @@
lineterminator='\n',
quotechar='"')
- install = self.get_finalized_command('install_dist')
+ install = self.get_finalized_command('install_dist')
for fpath in install.get_outputs():
+ rpath = self.pep376path(fpath, self.install_base, self.install_dir)
if fpath.endswith('.pyc') or fpath.endswith('.pyo'):
# do not put size and md5 hash, as in PEP-376
- writer.writerow((fpath, '', ''))
+ writer.writerow((rpath, '', ''))
else:
size = os.path.getsize(fpath)
with open(fpath, 'rb') as fp:
hash = hashlib.md5()
hash.update(fp.read())
md5sum = hash.hexdigest()
- writer.writerow((fpath, md5sum, size))
+ writer.writerow((rpath, md5sum, size))
# add the RECORD file itself
- writer.writerow((record_path, '', ''))
+ writer.writerow((self.pep376path(record_path, self.install_base, self.install_dir), '', ''))
self.outfiles.append(record_path)
def get_outputs(self):
diff -r befd56673c80 -r 65c3af0d283b Lib/packaging/database.py
--- a/Lib/packaging/database.py Sun May 20 02:34:13 2012 +1000
+++ b/Lib/packaging/database.py Sat May 19 17:01:25 2012 -0400
@@ -244,11 +244,6 @@
'dist-info file %r does not belong to the %r %s '
'distribution' % (path, self.name, self.version))
- # The file must be relative
- if path not in DIST_FILES:
- raise PackagingError('invalid path for a dist-info file: %r' %
- path)
-
path = os.path.join(self.path, path)
return open(path, open_flags)
diff -r befd56673c80 -r 65c3af0d283b Lib/packaging/tests/test_command_install_data.py
--- a/Lib/packaging/tests/test_command_install_data.py Sun May 20 02:34:13 2012 +1000
+++ b/Lib/packaging/tests/test_command_install_data.py Sat May 19 17:01:25 2012 -0400
@@ -95,10 +95,12 @@
scripts_dir = self.mkdtemp()
project_dir, dist = self.create_dist(
name='Spamlib', version='0.1',
- data_files={'spamd': '{scripts}/spamd'})
+ data_files={'spamd': '{scripts}/spamd',
+ 'entry_points.txt': '{dist-info}/entry_points.txt'})
os.chdir(project_dir)
self.write_file('spamd', '# Python script')
+ self.write_file('entry_points.txt', '[entry_points]\nham = eggs:cheese')
sysconfig._SCHEMES.set(_get_default_scheme(), 'scripts', scripts_dir)
sys.path.insert(0, install_dir)
packaging.database.disable_cache()
@@ -119,18 +121,21 @@
cmd = install_distinfo(dist)
cmd.ensure_finalized()
dist.command_obj['install_distinfo'] = cmd
- cmd.run()
+ cmd.run()
# first a few sanity checks
self.assertEqual(os.listdir(scripts_dir), ['spamd'])
- self.assertEqual(os.listdir(install_dir), ['Spamlib-0.1.dist-info'])
+ self.assertEqual(os.listdir(install_dir), ['Spamlib-0.1.dist-info'])
# now the real test
fn = os.path.join(install_dir, 'Spamlib-0.1.dist-info', 'RESOURCES')
with open(fn, encoding='utf-8') as fp:
content = fp.read().strip()
- expected = 'spamd,%s' % os.path.join(scripts_dir, 'spamd')
+ expected = 'spamd,%s\nentry_points.txt,%s' % (os.path.join(scripts_dir, 'spamd'),
+ os.path.join(install_dir,
+ 'Spamlib-0.1.dist-info',
+ 'entry_points.txt'))
self.assertEqual(content, expected)
# just to be sure, we also test that get_file works here, even though
diff -r befd56673c80 -r 65c3af0d283b Lib/pyclbr.py
--- a/Lib/pyclbr.py Sun May 20 02:34:13 2012 +1000
+++ b/Lib/pyclbr.py Sat May 19 17:01:25 2012 -0400
@@ -130,8 +130,6 @@
parent = _readmodule(package, path, inpackage)
if inpackage is not None:
package = "%s.%s" % (inpackage, package)
- if not '__path__' in parent:
- raise ImportError('No package named {}'.format(package))
return _readmodule(submodule, parent['__path__'], package)
# Search the path for the module
diff -r befd56673c80 -r 65c3af0d283b Lib/pydoc.py
--- a/Lib/pydoc.py Sun May 20 02:34:13 2012 +1000
+++ b/Lib/pydoc.py Sat May 19 17:01:25 2012 -0400
@@ -167,7 +167,7 @@
if name in {'__builtins__', '__doc__', '__file__', '__path__',
'__module__', '__name__', '__slots__', '__package__',
'__cached__', '__author__', '__credits__', '__date__',
- '__version__', '__qualname__', '__initializing__'}:
+ '__version__', '__qualname__'}:
return 0
# Private names are hidden, but special names are displayed.
if name.startswith('__') and name.endswith('__'): return 1
diff -r befd56673c80 -r 65c3af0d283b Lib/subprocess.py
--- a/Lib/subprocess.py Sun May 20 02:34:13 2012 +1000
+++ b/Lib/subprocess.py Sat May 19 17:01:25 2012 -0400
@@ -475,37 +475,6 @@
continue
-# XXX This function is only used by multiprocessing and the test suite,
-# but it's here so that it can be imported when Python is compiled without
-# threads.
-
-def _args_from_interpreter_flags():
- """Return a list of command-line arguments reproducing the current
- settings in sys.flags and sys.warnoptions."""
- flag_opt_map = {
- 'debug': 'd',
- # 'inspect': 'i',
- # 'interactive': 'i',
- 'optimize': 'O',
- 'dont_write_bytecode': 'B',
- 'no_user_site': 's',
- 'no_site': 'S',
- 'ignore_environment': 'E',
- 'verbose': 'v',
- 'bytes_warning': 'b',
- 'quiet': 'q',
- 'hash_randomization': 'R',
- }
- args = []
- for flag, opt in flag_opt_map.items():
- v = getattr(sys.flags, flag)
- if v > 0:
- args.append('-' + opt * v)
- for opt in sys.warnoptions:
- args.append('-W' + opt)
- return args
-
-
def call(*popenargs, timeout=None, **kwargs):
"""Run command with arguments. Wait for command to complete or
timeout, then return the returncode attribute.
diff -r befd56673c80 -r 65c3af0d283b Lib/tarfile.py
--- a/Lib/tarfile.py Sun May 20 02:34:13 2012 +1000
+++ b/Lib/tarfile.py Sat May 19 17:01:25 2012 -0400
@@ -245,8 +245,8 @@
the high bit set. So we calculate two checksums, unsigned and
signed.
"""
- unsigned_chksum = 256 + sum(struct.unpack_from("148B8x356B", buf))
- signed_chksum = 256 + sum(struct.unpack_from("148b8x356b", buf))
+ unsigned_chksum = 256 + sum(struct.unpack("148B", buf[:148]) + struct.unpack("356B", buf[156:512]))
+ signed_chksum = 256 + sum(struct.unpack("148b", buf[:148]) + struct.unpack("356b", buf[156:512]))
return unsigned_chksum, signed_chksum
def copyfileobj(src, dst, length=None):
diff -r befd56673c80 -r 65c3af0d283b Lib/test/lock_tests.py
--- a/Lib/test/lock_tests.py Sun May 20 02:34:13 2012 +1000
+++ b/Lib/test/lock_tests.py Sat May 19 17:01:25 2012 -0400
@@ -247,6 +247,7 @@
# Cannot release an unacquired lock
lock = self.locktype()
self.assertRaises(RuntimeError, lock.release)
+ self.assertRaises(RuntimeError, lock._release_save)
lock.acquire()
lock.acquire()
lock.release()
@@ -254,17 +255,6 @@
lock.release()
lock.release()
self.assertRaises(RuntimeError, lock.release)
-
- def test_release_save_unacquired(self):
- # Cannot _release_save an unacquired lock
- lock = self.locktype()
- self.assertRaises(RuntimeError, lock._release_save)
- lock.acquire()
- lock.acquire()
- lock.release()
- lock.acquire()
- lock.release()
- lock.release()
self.assertRaises(RuntimeError, lock._release_save)
def test_different_thread(self):
diff -r befd56673c80 -r 65c3af0d283b Lib/test/support.py
--- a/Lib/test/support.py Sun May 20 02:34:13 2012 +1000
+++ b/Lib/test/support.py Sat May 19 17:01:25 2012 -0400
@@ -1596,7 +1596,24 @@
def args_from_interpreter_flags():
"""Return a list of command-line arguments reproducing the current
settings in sys.flags and sys.warnoptions."""
- return subprocess._args_from_interpreter_flags()
+ flag_opt_map = {
+ 'bytes_warning': 'b',
+ 'dont_write_bytecode': 'B',
+ 'hash_randomization': 'R',
+ 'ignore_environment': 'E',
+ 'no_user_site': 's',
+ 'no_site': 'S',
+ 'optimize': 'O',
+ 'verbose': 'v',
+ }
+ args = []
+ for flag, opt in flag_opt_map.items():
+ v = getattr(sys.flags, flag)
+ if v > 0:
+ args.append('-' + opt * v)
+ for opt in sys.warnoptions:
+ args.append('-W' + opt)
+ return args
#============================================================
# Support for assertions about logging.
diff -r befd56673c80 -r 65c3af0d283b Lib/test/test_httplib.py
--- a/Lib/test/test_httplib.py Sun May 20 02:34:13 2012 +1000
+++ b/Lib/test/test_httplib.py Sat May 19 17:01:25 2012 -0400
@@ -99,34 +99,6 @@
conn.request('POST', '/', body, headers)
self.assertEqual(conn._buffer.count[header.lower()], 1)
- def test_content_length_0(self):
-
- class ContentLengthChecker(list):
- def __init__(self):
- list.__init__(self)
- self.content_length = None
- def append(self, item):
- kv = item.split(b':', 1)
- if len(kv) > 1 and kv[0].lower() == b'content-length':
- self.content_length = kv[1].strip()
- list.append(self, item)
-
- # POST with empty body
- conn = client.HTTPConnection('example.com')
- conn.sock = FakeSocket(None)
- conn._buffer = ContentLengthChecker()
- conn.request('POST', '/', '')
- self.assertEqual(conn._buffer.content_length, b'0',
- 'Header Content-Length not set')
-
- # PUT request with empty body
- conn = client.HTTPConnection('example.com')
- conn.sock = FakeSocket(None)
- conn._buffer = ContentLengthChecker()
- conn.request('PUT', '/', '')
- self.assertEqual(conn._buffer.content_length, b'0',
- 'Header Content-Length not set')
-
def test_putheader(self):
conn = client.HTTPConnection('example.com')
conn.sock = FakeSocket(None)
diff -r befd56673c80 -r 65c3af0d283b Lib/test/test_multiprocessing.py
--- a/Lib/test/test_multiprocessing.py Sun May 20 02:34:13 2012 +1000
+++ b/Lib/test/test_multiprocessing.py Sat May 19 17:01:25 2012 -0400
@@ -2814,41 +2814,8 @@
with self.assertRaises(ValueError):
multiprocessing.connection.Listener('/var/test.pipe')
-#
-# Issue 12098: check sys.flags of child matches that for parent
-#
-
-class TestFlags(unittest.TestCase):
- @classmethod
- def run_in_grandchild(cls, conn):
- conn.send(tuple(sys.flags))
-
- @classmethod
- def run_in_child(cls):
- import json
- r, w = multiprocessing.Pipe(duplex=False)
- p = multiprocessing.Process(target=cls.run_in_grandchild, args=(w,))
- p.start()
- grandchild_flags = r.recv()
- p.join()
- r.close()
- w.close()
- flags = (tuple(sys.flags), grandchild_flags)
- print(json.dumps(flags))
-
- def test_flags(self):
- import json, subprocess
- # start child process using unusual flags
- prog = ('from test.test_multiprocessing import TestFlags; ' +
- 'TestFlags.run_in_child()')
- data = subprocess.check_output(
- [sys.executable, '-E', '-S', '-O', '-c', prog])
- child_flags, grandchild_flags = json.loads(data.decode('ascii'))
- self.assertEqual(child_flags, grandchild_flags)
-
testcases_other = [OtherTest, TestInvalidHandle, TestInitializers,
- TestStdinBadfiledescriptor, TestWait, TestInvalidFamily,
- TestFlags]
+ TestStdinBadfiledescriptor, TestWait, TestInvalidFamily]
#
#
diff -r befd56673c80 -r 65c3af0d283b Lib/test/test_pkg.py
--- a/Lib/test/test_pkg.py Sun May 20 02:34:13 2012 +1000
+++ b/Lib/test/test_pkg.py Sat May 19 17:01:25 2012 -0400
@@ -23,8 +23,6 @@
def fixdir(lst):
if "__builtins__" in lst:
lst.remove("__builtins__")
- if "__initializing__" in lst:
- lst.remove("__initializing__")
return lst
diff -r befd56673c80 -r 65c3af0d283b Lib/test/test_pyclbr.py
--- a/Lib/test/test_pyclbr.py Sun May 20 02:34:13 2012 +1000
+++ b/Lib/test/test_pyclbr.py Sat May 19 17:01:25 2012 -0400
@@ -167,11 +167,6 @@
cm('email.parser')
cm('test.test_pyclbr')
- def test_issue_14798(self):
- # test ImportError is raised when the first part of a dotted name is
- # not a package
- self.assertRaises(ImportError, pyclbr.readmodule_ex, 'asyncore.foo')
-
def test_main():
run_unittest(PyclbrTest)
diff -r befd56673c80 -r 65c3af0d283b Lib/test/test_textwrap.py
--- a/Lib/test/test_textwrap.py Sun May 20 02:34:13 2012 +1000
+++ b/Lib/test/test_textwrap.py Sat May 19 17:01:25 2012 -0400
@@ -91,14 +91,6 @@
result = wrapper.fill(text)
self.check(result, '\n'.join(expect))
- text = "\tTest\tdefault\t\ttabsize."
- expect = [" Test default tabsize."]
- self.check_wrap(text, 80, expect)
-
- text = "\tTest\tcustom\t\ttabsize."
- expect = [" Test custom tabsize."]
- self.check_wrap(text, 80, expect, tabsize=4)
-
def test_fix_sentence_endings(self):
wrapper = TextWrapper(60, fix_sentence_endings=True)
diff -r befd56673c80 -r 65c3af0d283b Lib/test/test_threaded_import.py
--- a/Lib/test/test_threaded_import.py Sun May 20 02:34:13 2012 +1000
+++ b/Lib/test/test_threaded_import.py Sat May 19 17:01:25 2012 -0400
@@ -12,7 +12,7 @@
import shutil
import unittest
from test.support import (
- verbose, import_module, run_unittest, TESTFN, reap_threads, forget, unlink)
+ verbose, import_module, run_unittest, TESTFN, reap_threads)
threading = import_module('threading')
def task(N, done, done_tasks, errors):
@@ -187,7 +187,7 @@
contents = contents % {'delay': delay}
with open(os.path.join(TESTFN, name + ".py"), "wb") as f:
f.write(contents.encode('utf-8'))
- self.addCleanup(forget, name)
+ self.addCleanup(sys.modules.pop, name, None)
results = []
def import_ab():
@@ -204,23 +204,6 @@
t2.join()
self.assertEqual(set(results), {'a', 'b'})
- def test_side_effect_import(self):
- code = """if 1:
- import threading
- def target():
- import random
- t = threading.Thread(target=target)
- t.start()
- t.join()"""
- sys.path.insert(0, os.curdir)
- self.addCleanup(sys.path.remove, os.curdir)
- filename = TESTFN + ".py"
- with open(filename, "wb") as f:
- f.write(code.encode('utf-8'))
- self.addCleanup(unlink, filename)
- self.addCleanup(forget, TESTFN)
- __import__(TESTFN)
-
@reap_threads
def test_main():
diff -r befd56673c80 -r 65c3af0d283b Lib/test/test_types.py
--- a/Lib/test/test_types.py Sun May 20 02:34:13 2012 +1000
+++ b/Lib/test/test_types.py Sat May 19 17:01:25 2012 -0400
@@ -747,257 +747,8 @@
self.assertEqual(copy['key1'], 27)
-class ClassCreationTests(unittest.TestCase):
-
- class Meta(type):
- def __init__(cls, name, bases, ns, **kw):
- super().__init__(name, bases, ns)
- @staticmethod
- def __new__(mcls, name, bases, ns, **kw):
- return super().__new__(mcls, name, bases, ns)
- @classmethod
- def __prepare__(mcls, name, bases, **kw):
- ns = super().__prepare__(name, bases)
- ns["y"] = 1
- ns.update(kw)
- return ns
-
- def test_new_class_basics(self):
- C = types.new_class("C")
- self.assertEqual(C.__name__, "C")
- self.assertEqual(C.__bases__, (object,))
-
- def test_new_class_subclass(self):
- C = types.new_class("C", (int,))
- self.assertTrue(issubclass(C, int))
-
- def test_new_class_meta(self):
- Meta = self.Meta
- settings = {"metaclass": Meta, "z": 2}
- # We do this twice to make sure the passed in dict isn't mutated
- for i in range(2):
- C = types.new_class("C" + str(i), (), settings)
- self.assertIsInstance(C, Meta)
- self.assertEqual(C.y, 1)
- self.assertEqual(C.z, 2)
-
- def test_new_class_exec_body(self):
- Meta = self.Meta
- def func(ns):
- ns["x"] = 0
- C = types.new_class("C", (), {"metaclass": Meta, "z": 2}, func)
- self.assertIsInstance(C, Meta)
- self.assertEqual(C.x, 0)
- self.assertEqual(C.y, 1)
- self.assertEqual(C.z, 2)
-
- def test_new_class_exec_body(self):
- #Test that keywords are passed to the metaclass:
- def meta_func(name, bases, ns, **kw):
- return name, bases, ns, kw
- res = types.new_class("X",
- (int, object),
- dict(metaclass=meta_func, x=0))
- self.assertEqual(res, ("X", (int, object), {}, {"x": 0}))
-
- def test_new_class_defaults(self):
- # Test defaults/keywords:
- C = types.new_class("C", (), {}, None)
- self.assertEqual(C.__name__, "C")
- self.assertEqual(C.__bases__, (object,))
-
- def test_new_class_meta_with_base(self):
- Meta = self.Meta
- def func(ns):
- ns["x"] = 0
- C = types.new_class(name="C",
- bases=(int,),
- kwds=dict(metaclass=Meta, z=2),
- exec_body=func)
- self.assertTrue(issubclass(C, int))
- self.assertIsInstance(C, Meta)
- self.assertEqual(C.x, 0)
- self.assertEqual(C.y, 1)
- self.assertEqual(C.z, 2)
-
- # Many of the following tests are derived from test_descr.py
- def test_prepare_class(self):
- # Basic test of metaclass derivation
- expected_ns = {}
- class A(type):
- def __new__(*args, **kwargs):
- return type.__new__(*args, **kwargs)
-
- def __prepare__(*args):
- return expected_ns
-
- B = types.new_class("B", (object,))
- C = types.new_class("C", (object,), {"metaclass": A})
-
- # The most derived metaclass of D is A rather than type.
- meta, ns, kwds = types.prepare_class("D", (B, C), {"metaclass": type})
- self.assertIs(meta, A)
- self.assertIs(ns, expected_ns)
- self.assertEqual(len(kwds), 0)
-
- def test_metaclass_derivation(self):
- # issue1294232: correct metaclass calculation
- new_calls = [] # to check the order of __new__ calls
- class AMeta(type):
- def __new__(mcls, name, bases, ns):
- new_calls.append('AMeta')
- return super().__new__(mcls, name, bases, ns)
- @classmethod
- def __prepare__(mcls, name, bases):
- return {}
-
- class BMeta(AMeta):
- def __new__(mcls, name, bases, ns):
- new_calls.append('BMeta')
- return super().__new__(mcls, name, bases, ns)
- @classmethod
- def __prepare__(mcls, name, bases):
- ns = super().__prepare__(name, bases)
- ns['BMeta_was_here'] = True
- return ns
-
- A = types.new_class("A", (), {"metaclass": AMeta})
- self.assertEqual(new_calls, ['AMeta'])
- new_calls.clear()
-
- B = types.new_class("B", (), {"metaclass": BMeta})
- # BMeta.__new__ calls AMeta.__new__ with super:
- self.assertEqual(new_calls, ['BMeta', 'AMeta'])
- new_calls.clear()
-
- C = types.new_class("C", (A, B))
- # The most derived metaclass is BMeta:
- self.assertEqual(new_calls, ['BMeta', 'AMeta'])
- new_calls.clear()
- # BMeta.__prepare__ should've been called:
- self.assertIn('BMeta_was_here', C.__dict__)
-
- # The order of the bases shouldn't matter:
- C2 = types.new_class("C2", (B, A))
- self.assertEqual(new_calls, ['BMeta', 'AMeta'])
- new_calls.clear()
- self.assertIn('BMeta_was_here', C2.__dict__)
-
- # Check correct metaclass calculation when a metaclass is declared:
- D = types.new_class("D", (C,), {"metaclass": type})
- self.assertEqual(new_calls, ['BMeta', 'AMeta'])
- new_calls.clear()
- self.assertIn('BMeta_was_here', D.__dict__)
-
- E = types.new_class("E", (C,), {"metaclass": AMeta})
- self.assertEqual(new_calls, ['BMeta', 'AMeta'])
- new_calls.clear()
- self.assertIn('BMeta_was_here', E.__dict__)
-
- def test_metaclass_override_function(self):
- # Special case: the given metaclass isn't a class,
- # so there is no metaclass calculation.
- class A(metaclass=self.Meta):
- pass
-
- marker = object()
- def func(*args, **kwargs):
- return marker
-
- X = types.new_class("X", (), {"metaclass": func})
- Y = types.new_class("Y", (object,), {"metaclass": func})
- Z = types.new_class("Z", (A,), {"metaclass": func})
- self.assertIs(marker, X)
- self.assertIs(marker, Y)
- self.assertIs(marker, Z)
-
- def test_metaclass_override_callable(self):
- # The given metaclass is a class,
- # but not a descendant of type.
- new_calls = [] # to check the order of __new__ calls
- prepare_calls = [] # to track __prepare__ calls
- class ANotMeta:
- def __new__(mcls, *args, **kwargs):
- new_calls.append('ANotMeta')
- return super().__new__(mcls)
- @classmethod
- def __prepare__(mcls, name, bases):
- prepare_calls.append('ANotMeta')
- return {}
-
- class BNotMeta(ANotMeta):
- def __new__(mcls, *args, **kwargs):
- new_calls.append('BNotMeta')
- return super().__new__(mcls)
- @classmethod
- def __prepare__(mcls, name, bases):
- prepare_calls.append('BNotMeta')
- return super().__prepare__(name, bases)
-
- A = types.new_class("A", (), {"metaclass": ANotMeta})
- self.assertIs(ANotMeta, type(A))
- self.assertEqual(prepare_calls, ['ANotMeta'])
- prepare_calls.clear()
- self.assertEqual(new_calls, ['ANotMeta'])
- new_calls.clear()
-
- B = types.new_class("B", (), {"metaclass": BNotMeta})
- self.assertIs(BNotMeta, type(B))
- self.assertEqual(prepare_calls, ['BNotMeta', 'ANotMeta'])
- prepare_calls.clear()
- self.assertEqual(new_calls, ['BNotMeta', 'ANotMeta'])
- new_calls.clear()
-
- C = types.new_class("C", (A, B))
- self.assertIs(BNotMeta, type(C))
- self.assertEqual(prepare_calls, ['BNotMeta', 'ANotMeta'])
- prepare_calls.clear()
- self.assertEqual(new_calls, ['BNotMeta', 'ANotMeta'])
- new_calls.clear()
-
- C2 = types.new_class("C2", (B, A))
- self.assertIs(BNotMeta, type(C2))
- self.assertEqual(prepare_calls, ['BNotMeta', 'ANotMeta'])
- prepare_calls.clear()
- self.assertEqual(new_calls, ['BNotMeta', 'ANotMeta'])
- new_calls.clear()
-
- # This is a TypeError, because of a metaclass conflict:
- # BNotMeta is neither a subclass, nor a superclass of type
- with self.assertRaises(TypeError):
- D = types.new_class("D", (C,), {"metaclass": type})
-
- E = types.new_class("E", (C,), {"metaclass": ANotMeta})
- self.assertIs(BNotMeta, type(E))
- self.assertEqual(prepare_calls, ['BNotMeta', 'ANotMeta'])
- prepare_calls.clear()
- self.assertEqual(new_calls, ['BNotMeta', 'ANotMeta'])
- new_calls.clear()
-
- F = types.new_class("F", (object(), C))
- self.assertIs(BNotMeta, type(F))
- self.assertEqual(prepare_calls, ['BNotMeta', 'ANotMeta'])
- prepare_calls.clear()
- self.assertEqual(new_calls, ['BNotMeta', 'ANotMeta'])
- new_calls.clear()
-
- F2 = types.new_class("F2", (C, object()))
- self.assertIs(BNotMeta, type(F2))
- self.assertEqual(prepare_calls, ['BNotMeta', 'ANotMeta'])
- prepare_calls.clear()
- self.assertEqual(new_calls, ['BNotMeta', 'ANotMeta'])
- new_calls.clear()
-
- # TypeError: BNotMeta is neither a
- # subclass, nor a superclass of int
- with self.assertRaises(TypeError):
- X = types.new_class("X", (C, int()))
- with self.assertRaises(TypeError):
- X = types.new_class("X", (int(), C))
-
-
def test_main():
- run_unittest(TypesTests, MappingProxyTests, ClassCreationTests)
+ run_unittest(TypesTests, MappingProxyTests)
if __name__ == '__main__':
test_main()
diff -r befd56673c80 -r 65c3af0d283b Lib/test/test_urlparse.py
--- a/Lib/test/test_urlparse.py Sun May 20 02:34:13 2012 +1000
+++ b/Lib/test/test_urlparse.py Sat May 19 17:01:25 2012 -0400
@@ -636,20 +636,11 @@
('s3', 'foo.com', '/stuff', '', '', ''))
self.assertEqual(urllib.parse.urlparse("x-newscheme://foo.com/stuff"),
('x-newscheme', 'foo.com', '/stuff', '', '', ''))
- self.assertEqual(urllib.parse.urlparse("x-newscheme://foo.com/stuff?query#fragment"),
- ('x-newscheme', 'foo.com', '/stuff', '', 'query', 'fragment'))
- self.assertEqual(urllib.parse.urlparse("x-newscheme://foo.com/stuff?query"),
- ('x-newscheme', 'foo.com', '/stuff', '', 'query', ''))
-
# And for bytes...
self.assertEqual(urllib.parse.urlparse(b"s3://foo.com/stuff"),
(b's3', b'foo.com', b'/stuff', b'', b'', b''))
self.assertEqual(urllib.parse.urlparse(b"x-newscheme://foo.com/stuff"),
(b'x-newscheme', b'foo.com', b'/stuff', b'', b'', b''))
- self.assertEqual(urllib.parse.urlparse(b"x-newscheme://foo.com/stuff?query#fragment"),
- (b'x-newscheme', b'foo.com', b'/stuff', b'', b'query', b'fragment'))
- self.assertEqual(urllib.parse.urlparse(b"x-newscheme://foo.com/stuff?query"),
- (b'x-newscheme', b'foo.com', b'/stuff', b'', b'query', b''))
def test_mixed_types_rejected(self):
# Several functions that process either strings or ASCII encoded bytes
@@ -806,13 +797,6 @@
encoding='utf-8')
self.assertRaises(TypeError, urllib.parse.quote, b'foo', errors='strict')
- def test_issue14072(self):
- p1 = urllib.parse.urlsplit('tel:+31-641044153')
- self.assertEqual(p1.scheme, 'tel')
- self.assertEqual(p1.path, '+31-641044153')
- p2 = urllib.parse.urlsplit('tel:+31641044153')
- self.assertEqual(p2.scheme, 'tel')
- self.assertEqual(p2.path, '+31641044153')
def test_main():
support.run_unittest(UrlParseTestCase)
diff -r befd56673c80 -r 65c3af0d283b Lib/textwrap.py
--- a/Lib/textwrap.py Sun May 20 02:34:13 2012 +1000
+++ b/Lib/textwrap.py Sat May 19 17:01:25 2012 -0400
@@ -39,11 +39,8 @@
of wrapped output; also counts towards each line's width.
expand_tabs (default: true)
Expand tabs in input text to spaces before further processing.
- Each tab will become 0 .. 'tabsize' spaces, depending on its position
- in its line. If false, each tab is treated as a single character.
- tabsize (default: 8)
- Expand tabs in input text to 0 .. 'tabsize' spaces, unless
- 'expand_tabs' is false.
+ Each tab will become 1 .. 8 spaces, depending on its position in
+ its line. If false, each tab is treated as a single character.
replace_whitespace (default: true)
Replace all whitespace characters in the input text by spaces
after tab expansion. Note that if expand_tabs is false and
@@ -103,8 +100,7 @@
fix_sentence_endings=False,
break_long_words=True,
drop_whitespace=True,
- break_on_hyphens=True,
- tabsize=8):
+ break_on_hyphens=True):
self.width = width
self.initial_indent = initial_indent
self.subsequent_indent = subsequent_indent
@@ -114,7 +110,6 @@
self.break_long_words = break_long_words
self.drop_whitespace = drop_whitespace
self.break_on_hyphens = break_on_hyphens
- self.tabsize = tabsize
# -- Private methods -----------------------------------------------
@@ -128,7 +123,7 @@
becomes " foo bar baz".
"""
if self.expand_tabs:
- text = text.expandtabs(self.tabsize)
+ text = text.expandtabs()
if self.replace_whitespace:
text = text.translate(self.unicode_whitespace_trans)
return text
diff -r befd56673c80 -r 65c3af0d283b Lib/token.py
--- a/Lib/token.py Sun May 20 02:34:13 2012 +1000
+++ b/Lib/token.py Sat May 19 17:01:25 2012 -0400
@@ -70,7 +70,7 @@
tok_name = {value: name
for name, value in globals().items()
- if isinstance(value, int) and not name.startswith('_')}
+ if isinstance(value, int)}
__all__.extend(tok_name.values())
def ISTERMINAL(x):
diff -r befd56673c80 -r 65c3af0d283b Lib/types.py
--- a/Lib/types.py Sun May 20 02:34:13 2012 +1000
+++ b/Lib/types.py Sat May 19 17:01:25 2012 -0400
@@ -40,61 +40,3 @@
MemberDescriptorType = type(FunctionType.__globals__)
del sys, _f, _g, _C, # Not for export
-
-
-# Provide a PEP 3115 compliant mechanism for class creation
-def new_class(name, bases=(), kwds=None, exec_body=None):
- """Create a class object dynamically using the appropriate metaclass."""
- meta, ns, kwds = prepare_class(name, bases, kwds)
- if exec_body is not None:
- exec_body(ns)
- return meta(name, bases, ns, **kwds)
-
-def prepare_class(name, bases=(), kwds=None):
- """Call the __prepare__ method of the appropriate metaclass.
-
- Returns (metaclass, namespace, kwds) as a 3-tuple
-
- *metaclass* is the appropriate metaclass
- *namespace* is the prepared class namespace
- *kwds* is an updated copy of the passed in kwds argument with any
- 'metaclass' entry removed. If no kwds argument is passed in, this will
- be an empty dict.
- """
- if kwds is None:
- kwds = {}
- else:
- kwds = dict(kwds) # Don't alter the provided mapping
- if 'metaclass' in kwds:
- meta = kwds.pop('metaclass')
- else:
- if bases:
- meta = type(bases[0])
- else:
- meta = type
- if isinstance(meta, type):
- # when meta is a type, we first determine the most-derived metaclass
- # instead of invoking the initial candidate directly
- meta = _calculate_meta(meta, bases)
- if hasattr(meta, '__prepare__'):
- ns = meta.__prepare__(name, bases, **kwds)
- else:
- ns = {}
- return meta, ns, kwds
-
-def _calculate_meta(meta, bases):
- """Calculate the most derived metaclass."""
- winner = meta
- for base in bases:
- base_meta = type(base)
- if issubclass(winner, base_meta):
- continue
- if issubclass(base_meta, winner):
- winner = base_meta
- continue
- # else:
- raise TypeError("metaclass conflict: "
- "the metaclass of a derived class "
- "must be a (non-strict) subclass "
- "of the metaclasses of all its bases")
- return winner
diff -r befd56673c80 -r 65c3af0d283b Lib/urllib/parse.py
--- a/Lib/urllib/parse.py Sun May 20 02:34:13 2012 +1000
+++ b/Lib/urllib/parse.py Sat May 19 17:01:25 2012 -0400
@@ -44,9 +44,16 @@
'imap', 'wais', 'file', 'mms', 'https', 'shttp',
'snews', 'prospero', 'rtsp', 'rtspu', 'rsync', '',
'svn', 'svn+ssh', 'sftp', 'nfs', 'git', 'git+ssh']
+non_hierarchical = ['gopher', 'hdl', 'mailto', 'news',
+ 'telnet', 'wais', 'imap', 'snews', 'sip', 'sips']
uses_params = ['ftp', 'hdl', 'prospero', 'http', 'imap',
'https', 'shttp', 'rtsp', 'rtspu', 'sip', 'sips',
'mms', '', 'sftp']
+uses_query = ['http', 'wais', 'imap', 'https', 'shttp', 'mms',
+ 'gopher', 'rtsp', 'rtspu', 'sip', 'sips', '']
+uses_fragment = ['ftp', 'hdl', 'http', 'gopher', 'news',
+ 'nntp', 'wais', 'https', 'shttp', 'snews',
+ 'file', 'prospero', '']
# Characters valid in scheme names
scheme_chars = ('abcdefghijklmnopqrstuvwxyz'
@@ -338,21 +345,21 @@
if c not in scheme_chars:
break
else:
- # make sure "url" is not actually a port number (in which case
- # "scheme" is really part of the path)
- rest = url[i+1:]
- if not rest or any(c not in '0123456789' for c in rest):
- # not a port number
- scheme, url = url[:i].lower(), rest
+ try:
+ # make sure "url" is not actually a port number (in which case
+ # "scheme" is really part of the path
+ _testportnum = int(url[i+1:])
+ except ValueError:
+ scheme, url = url[:i].lower(), url[i+1:]
if url[:2] == '//':
netloc, url = _splitnetloc(url, 2)
if (('[' in netloc and ']' not in netloc) or
(']' in netloc and '[' not in netloc)):
raise ValueError("Invalid IPv6 URL")
- if allow_fragments and '#' in url:
+ if allow_fragments and scheme in uses_fragment and '#' in url:
url, fragment = url.split('#', 1)
- if '?' in url:
+ if scheme in uses_query and '?' in url:
url, query = url.split('?', 1)
v = SplitResult(scheme, netloc, url, query, fragment)
_parse_cache[key] = v
diff -r befd56673c80 -r 65c3af0d283b Misc/ACKS
--- a/Misc/ACKS Sun May 20 02:34:13 2012 +1000
+++ b/Misc/ACKS Sat May 19 17:01:25 2012 -0400
@@ -361,7 +361,6 @@
Dan Gass
Andrew Gaul
Stephen M. Gava
-Xavier de Gaye
Harry Henry Gebel
Marius Gedminas
Thomas Gellekum
@@ -777,7 +776,6 @@
Joe Peterson
Randy Pausch
Samuele Pedroni
-Justin Peel
Marcel van der Peijl
Berker Peksag
Steven Pemberton
diff -r befd56673c80 -r 65c3af0d283b Misc/NEWS
--- a/Misc/NEWS Sun May 20 02:34:13 2012 +1000
+++ b/Misc/NEWS Sat May 19 17:01:25 2012 -0400
@@ -10,14 +10,6 @@
Core and Builtins
-----------------
-- Issue #14494: Fix __future__.py and its documentation to note that
- absolute imports are the default behavior in 3.0 instead of 2.7.
- Patch by Sven Marnach.
-
-- Issue #9260: A finer-grained import lock. Most of the import sequence
- now uses per-module locks rather than the global import lock, eliminating
- well-known issues with threads and imports.
-
- Issue #14624: UTF-16 decoding is now 3x to 4x faster on various inputs.
Patch by Serhiy Storchaka.
@@ -42,33 +34,6 @@
Library
-------
-- Issue #14588: The types module now provide new_class() and prepare_class()
- functions to support PEP 3115 compliant dynamic class creation. Patch by
- Daniel Urban and Nick Coghlan.
-
-- Issue #13152: Allow to specify a custom tabsize for expanding tabs in
- textwrap. Patch by John Feuerstein.
-
-- Issue #14721: Send the correct 'Content-length: 0' header when the body is an
- empty string ''. Initial Patch contributed by Arve Knudsen.
-
-- Issue #14072: Fix parsing of 'tel' URIs in urlparse by making the check for
- ports stricter.
-
-- Issue #9374: Generic parsing of query and fragment portions of url for any
- scheme. Supported both by RFC3986 and RFC2396.
-
-- Issue #14798: Fix the functions in pyclbr to raise an ImportError
- when the first part of a dotted name is not a package. Patch by
- Xavier de Gaye.
-
-- Issue #12098: multiprocessing on Windows now starts child processes
- using the same sys.flags as the current process. Initial patch by
- Sergey Mezentsev.
-
-- Issue #13031: Small speed-up for tarfile when unzipping tarfiles.
- Patch by Justin Peel.
-
- Issue #14780: urllib.request.urlopen() now has a ``cadefault`` argument
to use the default certificate store. Initial patch by James Oakley.
@@ -163,20 +128,11 @@
Build
-----
-- Upgrade Windows library versions: bzip 1.0.6, OpenSSL 1.0.1c.
-
- Issue #14693: Under non-Windows platforms, hashlib's fallback modules are
always compiled, even if OpenSSL is present at build time.
- Issue #13210: Windows build now uses VS2010, ported from VS2008.
-Documentation
--------------
-
-- Issue #14588: The language reference now accurately documents the Python 3
- class definition process. Patch by Nick Coghlan.
-
-
What's New in Python 3.3.0 Alpha 3?
===================================
diff -r befd56673c80 -r 65c3af0d283b PC/VC6/readme.txt
--- a/PC/VC6/readme.txt Sun May 20 02:34:13 2012 +1000
+++ b/PC/VC6/readme.txt Sat May 19 17:01:25 2012 -0400
@@ -153,9 +153,10 @@
Unpack into the "dist" directory, retaining the folder name from
the archive - for example, the latest stable OpenSSL will install as
- dist/openssl-1.0.1c
+ dist/openssl-1.0.0a
- You need to use version 1.0.1c of OpenSSL.
+ You can (theoretically) use any version of OpenSSL you like - the
+ build process will automatically select the latest version.
You can install the NASM assembler from
http://www.nasm.us/
diff -r befd56673c80 -r 65c3af0d283b PC/VS8.0/pyproject.vsprops
--- a/PC/VS8.0/pyproject.vsprops Sun May 20 02:34:13 2012 +1000
+++ b/PC/VS8.0/pyproject.vsprops Sat May 19 17:01:25 2012 -0400
@@ -58,7 +58,7 @@
/>
= 4:
+ continue
+ if parts > best_parts:
+ best_parts = parts
+ best_name = c
+ if best_name is not None:
+ print("Found an SSL directory at '%s'" % (best_name,))
+ else:
+ print("Could not find an SSL directory in '%s'" % (sources,))
+ sys.stdout.flush()
+ return best_name
def create_makefile64(makefile, m32):
"""Create and fix makefile for 64bit
@@ -178,7 +202,7 @@
print("No Perl installation was found. Existing Makefiles are used.")
sys.stdout.flush()
# Look for SSL 2 levels up from pcbuild - ie, same place zlib etc all live.
- ssl_dir = get_ssl_dir()
+ ssl_dir = find_best_ssl_dir(("..\\..",))
if ssl_dir is None:
sys.exit(1)
@@ -228,9 +252,9 @@
# Now run make.
if arch == "amd64":
- rc = os.system("nasm -f win64 -DNEAR -Ox -g ms\\uptable.asm")
+ rc = os.system("ml64 -c -Foms\\uptable.obj ms\\uptable.asm")
if rc:
- print("nasm assembler has failed.")
+ print("ml64 assembler has failed.")
sys.exit(rc)
copy(r"crypto\buildinf_%s.h" % arch, r"crypto\buildinf.h")
diff -r befd56673c80 -r 65c3af0d283b PCbuild/pyproject.props
--- a/PCbuild/pyproject.props Sun May 20 02:34:13 2012 +1000
+++ b/PCbuild/pyproject.props Sat May 19 17:01:25 2012 -0400
@@ -7,7 +7,7 @@
$(externalsDir)\sqlite-3.7.12
$(externalsDir)\bzip2-1.0.6
$(externalsDir)\xz-5.0.3
- $(externalsDir)\openssl-1.0.1c
+ $(externalsDir)\openssl-1.0.0a
$(externalsDir)\tcltk
$(externalsDir)\tcltk64
$(tcltkDir)\lib\tcl85.lib;$(tcltkDir)\lib\tk85.lib
diff -r befd56673c80 -r 65c3af0d283b PCbuild/readme.txt
--- a/PCbuild/readme.txt Sun May 20 02:34:13 2012 +1000
+++ b/PCbuild/readme.txt Sat May 19 17:01:25 2012 -0400
@@ -148,7 +148,7 @@
Get the source code through
- svn export http://svn.python.org/projects/external/openssl-1.0.1c
+ svn export http://svn.python.org/projects/external/openssl-1.0.0a
** NOTE: if you use the Tools\buildbot\external(-amd64).bat approach for
obtaining external sources then you don't need to manually get the source
diff -r befd56673c80 -r 65c3af0d283b Python/import.c
--- a/Python/import.c Sun May 20 02:34:13 2012 +1000
+++ b/Python/import.c Sat May 19 17:01:25 2012 -0400
@@ -1370,7 +1370,47 @@
PyObject *
PyImport_ImportModuleNoBlock(const char *name)
{
- return PyImport_ImportModule(name);
+ PyObject *nameobj, *modules, *result;
+#ifdef WITH_THREAD
+ long me;
+#endif
+
+ /* Try to get the module from sys.modules[name] */
+ modules = PyImport_GetModuleDict();
+ if (modules == NULL)
+ return NULL;
+
+ nameobj = PyUnicode_FromString(name);
+ if (nameobj == NULL)
+ return NULL;
+ result = PyDict_GetItem(modules, nameobj);
+ if (result != NULL) {
+ Py_DECREF(nameobj);
+ Py_INCREF(result);
+ return result;
+ }
+ PyErr_Clear();
+#ifdef WITH_THREAD
+ /* check the import lock
+ * me might be -1 but I ignore the error here, the lock function
+ * takes care of the problem */
+ me = PyThread_get_thread_ident();
+ if (import_lock_thread == -1 || import_lock_thread == me) {
+ /* no thread or me is holding the lock */
+ result = PyImport_Import(nameobj);
+ }
+ else {
+ PyErr_Format(PyExc_ImportError,
+ "Failed to import %R because the import lock"
+ "is held by another thread.",
+ nameobj);
+ result = NULL;
+ }
+#else
+ result = PyImport_Import(nameobj);
+#endif
+ Py_DECREF(nameobj);
+ return result;
}
@@ -1380,13 +1420,11 @@
int level)
{
_Py_IDENTIFIER(__import__);
- _Py_IDENTIFIER(__initializing__);
_Py_IDENTIFIER(__package__);
_Py_IDENTIFIER(__path__);
_Py_IDENTIFIER(__name__);
_Py_IDENTIFIER(_find_and_load);
_Py_IDENTIFIER(_handle_fromlist);
- _Py_IDENTIFIER(_lock_unlock_module);
_Py_static_string(single_dot, ".");
PyObject *abs_name = NULL;
PyObject *builtins_import = NULL;
@@ -1569,48 +1607,16 @@
goto error_with_unlock;
}
else if (mod != NULL) {
- PyObject *value;
- int initializing = 0;
-
Py_INCREF(mod);
- /* Only call _bootstrap._lock_unlock_module() if __initializing__ is true. */
- value = _PyObject_GetAttrId(mod, &PyId___initializing__);
- if (value == NULL)
- PyErr_Clear();
- else {
- initializing = PyObject_IsTrue(value);
- Py_DECREF(value);
- if (initializing == -1)
- PyErr_Clear();
- }
- if (initializing > 0) {
- /* _bootstrap._lock_unlock_module() releases the import lock */
- value = _PyObject_CallMethodObjIdArgs(interp->importlib,
- &PyId__lock_unlock_module, abs_name,
- NULL);
- if (value == NULL)
- goto error;
- Py_DECREF(value);
- }
- else {
-#ifdef WITH_THREAD
- if (_PyImport_ReleaseLock() < 0) {
- PyErr_SetString(PyExc_RuntimeError, "not holding the import lock");
- goto error;
- }
-#endif
- }
}
else {
- /* _bootstrap._find_and_load() releases the import lock */
mod = _PyObject_CallMethodObjIdArgs(interp->importlib,
&PyId__find_and_load, abs_name,
builtins_import, NULL);
if (mod == NULL) {
- goto error;
+ goto error_with_unlock;
}
}
- /* From now on we don't hold the import lock anymore. */
if (PyObject_Not(fromlist)) {
if (level == 0 || PyUnicode_GET_LENGTH(name) > 0) {
@@ -1619,12 +1625,12 @@
PyObject *borrowed_dot = _PyUnicode_FromId(&single_dot);
if (borrowed_dot == NULL) {
- goto error;
+ goto error_with_unlock;
}
partition = PyUnicode_Partition(name, borrowed_dot);
if (partition == NULL) {
- goto error;
+ goto error_with_unlock;
}
if (PyUnicode_GET_LENGTH(PyTuple_GET_ITEM(partition, 1)) == 0) {
@@ -1632,7 +1638,7 @@
Py_DECREF(partition);
final_mod = mod;
Py_INCREF(mod);
- goto error;
+ goto exit_with_unlock;
}
front = PyTuple_GET_ITEM(partition, 0);
@@ -1651,7 +1657,7 @@
abs_name_len - cut_off);
Py_DECREF(front);
if (to_return == NULL) {
- goto error;
+ goto error_with_unlock;
}
final_mod = PyDict_GetItem(interp->modules, to_return);
@@ -1677,8 +1683,8 @@
fromlist, builtins_import,
NULL);
}
- goto error;
+ exit_with_unlock:
error_with_unlock:
#ifdef WITH_THREAD
if (_PyImport_ReleaseLock() < 0) {
diff -r befd56673c80 -r 65c3af0d283b Python/importlib.h
Binary file Python/importlib.h has changed
diff -r befd56673c80 -r 65c3af0d283b Tools/buildbot/external-common.bat
--- a/Tools/buildbot/external-common.bat Sun May 20 02:34:13 2012 +1000
+++ b/Tools/buildbot/external-common.bat Sat May 19 17:01:25 2012 -0400
@@ -14,7 +14,7 @@
@rem if exist tk8.4.16 rd /s/q tk8.4.16
@rem if exist tk-8.4.18.1 rd /s/q tk-8.4.18.1
@rem if exist db-4.4.20 rd /s/q db-4.4.20
-@rem if exist openssl-1.0.1c rd /s/q openssl-1.0.1c
+@rem if exist openssl-1.0.0a rd /s/q openssl-1.0.0a
@rem if exist sqlite-3.7.12 rd /s/q sqlite-3.7.12
@rem bzip
@@ -24,10 +24,7 @@
)
@rem OpenSSL
-if not exist openssl-1.0.1c (
- rd /s/q openssl-1.0.0j
- svn export http://svn.python.org/projects/external/openssl-1.0.1c
-)
+if not exist openssl-1.0.0a svn export http://svn.python.org/projects/external/openssl-1.0.0a
@rem tcl/tk
if not exist tcl-8.5.11.0 (
diff -r befd56673c80 -r 65c3af0d283b Tools/scripts/run_tests.py
--- a/Tools/scripts/run_tests.py Sun May 20 02:34:13 2012 +1000
+++ b/Tools/scripts/run_tests.py Sat May 19 17:01:25 2012 -0400
@@ -10,10 +10,6 @@
import os
import sys
import test.support
-try:
- import threading
-except ImportError:
- threading = None
def is_multiprocess_flag(arg):
@@ -38,7 +34,7 @@
])
if sys.platform == 'win32':
args.append('-n') # Silence alerts under Windows
- if threading and not any(is_multiprocess_flag(arg) for arg in regrtest_args):
+ if not any(is_multiprocess_flag(arg) for arg in regrtest_args):
args.extend(['-j', '0']) # Use all CPU cores
if not any(is_resource_use_flag(arg) for arg in regrtest_args):
args.extend(['-u', 'all,-largefile,-audio,-gui'])