[Python-checkins] r66050 - in python/branches/tlee-ast-optimize: Doc/c-api/object.rst Doc/whatsnew/2.6.rst Include/abstract.h Include/object.h Lib/test/test_abc.py Lib/test/test_exceptions.py Lib/test/test_typechecks.py Misc/NEWS Objects/abstract.c Objects/typeobject.c Python/errors.c

thomas.lee python-checkins at python.org
Wed Aug 27 11:15:25 CEST 2008


Author: thomas.lee
Date: Wed Aug 27 11:15:24 2008
New Revision: 66050

Log:
Merged revisions 66030-66049 via svnmerge from 
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r66039 | benjamin.peterson | 2008-08-27 03:08:40 +1000 (Wed, 27 Aug 2008) | 1 line
  
  sort of backport 66038 by aliasing PyObject_Bytes to PyObject_Str
........
  r66043 | antoine.pitrou | 2008-08-27 08:42:08 +1000 (Wed, 27 Aug 2008) | 11 lines
  
  Issue #2534: speed up isinstance() and issubclass() by 50-70%, so as to 
  match Python 2.5 speed despite the __instancecheck__ / __subclasscheck__  
  mechanism. In the process, fix a bug where isinstance() and issubclass(),  
  when given a tuple of classes as second argument, were looking up  
  __instancecheck__ / __subclasscheck__ on the tuple rather than on each  
  type object.  
  
  Reviewed by Benjamin Peterson and Raymond Hettinger.
........
  r66045 | andrew.kuchling | 2008-08-27 10:27:18 +1000 (Wed, 27 Aug 2008) | 1 line
  
  Trim whitespace; add a few updates
........
  r66048 | andrew.kuchling | 2008-08-27 10:45:02 +1000 (Wed, 27 Aug 2008) | 1 line
  
  Add an item and a note
........
  r66049 | andrew.kuchling | 2008-08-27 12:12:18 +1000 (Wed, 27 Aug 2008) | 1 line
  
  Add various items
........


Modified:
   python/branches/tlee-ast-optimize/   (props changed)
   python/branches/tlee-ast-optimize/Doc/c-api/object.rst
   python/branches/tlee-ast-optimize/Doc/whatsnew/2.6.rst
   python/branches/tlee-ast-optimize/Include/abstract.h
   python/branches/tlee-ast-optimize/Include/object.h
   python/branches/tlee-ast-optimize/Lib/test/test_abc.py
   python/branches/tlee-ast-optimize/Lib/test/test_exceptions.py
   python/branches/tlee-ast-optimize/Lib/test/test_typechecks.py
   python/branches/tlee-ast-optimize/Misc/NEWS
   python/branches/tlee-ast-optimize/Objects/abstract.c
   python/branches/tlee-ast-optimize/Objects/typeobject.c
   python/branches/tlee-ast-optimize/Python/errors.c

Modified: python/branches/tlee-ast-optimize/Doc/c-api/object.rst
==============================================================================
--- python/branches/tlee-ast-optimize/Doc/c-api/object.rst	(original)
+++ python/branches/tlee-ast-optimize/Doc/c-api/object.rst	Wed Aug 27 11:15:24 2008
@@ -130,6 +130,14 @@
    by the :keyword:`print` statement.
 
 
+.. cfunction:: PyObject* PyObject_Bytes(PyObject *o)
+
+   .. index:: builtin: bytes
+
+   Compute a bytes representation of object *o*.  In 2.x, this is just a alias
+   for :cfunc:`PyObject_Str`.
+
+
 .. cfunction:: PyObject* PyObject_Unicode(PyObject *o)
 
    .. index:: builtin: unicode

Modified: python/branches/tlee-ast-optimize/Doc/whatsnew/2.6.rst
==============================================================================
--- python/branches/tlee-ast-optimize/Doc/whatsnew/2.6.rst	(original)
+++ python/branches/tlee-ast-optimize/Doc/whatsnew/2.6.rst	Wed Aug 27 11:15:24 2008
@@ -529,15 +529,15 @@
 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.  
+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 
+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.
@@ -668,10 +668,10 @@
    The documentation for the :mod:`multiprocessing` module.
 
    :pep:`371` - Addition of the multiprocessing package
-     PEP written by Jesse Noller and Richard Oudkerk; 
+     PEP written by Jesse Noller and Richard Oudkerk;
      implemented by Richard Oudkerk and Jesse Noller.
 
-    
+
 .. ======================================================================
 
 .. _pep-3101:
@@ -918,15 +918,15 @@
 
     print len(s)               # 12 Unicode characters
 
-At the C level, Python 3.0 will rename the existing 8-bit 
-string type, called :ctype:`PyStringObject` in Python 2.x, 
+At the C level, Python 3.0 will rename the existing 8-bit
+string type, called :ctype:`PyStringObject` in Python 2.x,
 to :ctype:`PyBytesObject`.  Python 2.6 uses ``#define``
-to support using the names :cfunc:`PyBytesObject`, 
+to support using the names :cfunc:`PyBytesObject`,
 :cfunc:`PyBytes_Check`, :cfunc:`PyBytes_FromStringAndSize`,
 and all the other functions and macros used with strings.
 
-Instances of the :class:`bytes` type are immutable just 
-as strings are.  A new :class:`bytearray` type stores a mutable 
+Instances of the :class:`bytes` type are immutable just
+as strings are.  A new :class:`bytearray` type stores a mutable
 sequence of bytes::
 
     >>> bytearray([65, 66, 67])
@@ -940,9 +940,9 @@
     >>> unicode(str(b), 'utf-8')
     u'\u31ef \u3244'
 
-Byte arrays support most of the methods of string types, such as 
+Byte arrays support most of the methods of string types, such as
 :meth:`startswith`/:meth:`endswith`, :meth:`find`/:meth:`rfind`,
-and some of the methods of lists, such as :meth:`append`, 
+and some of the methods of lists, such as :meth:`append`,
 :meth:`pop`,  and :meth:`reverse`.
 
     >>> b = bytearray('ABC')
@@ -951,6 +951,11 @@
     >>> b
     bytearray(b'ABCde')
 
+There's also a corresponding C API, with
+:cfunc:`PyByteArray_FromObject`,
+:cfunc:`PyByteArray_FromStringAndSize`,
+and various other functions.
+
 .. seealso::
 
    :pep:`3112` - Bytes literals in Python 3000
@@ -993,14 +998,14 @@
   It supports all of the methods of :class:`RawIOBase`,
   and adds a :attr:`raw` attribute holding the underlying raw object.
 
-  There are four concrete classes implementing this ABC:
-  :class:`BufferedWriter` and
-  :class:`BufferedReader` for objects that only support
-  writing or reading and don't support random access,
-  :class:`BufferedRandom` for objects that support the :meth:`seek` method
-  for random access,
-  and :class:`BufferedRWPair` for objects such as TTYs that have
-  both read and write operations that act upon unconnected streams of data.
+  There are five concrete classes implementing this ABC.
+  :class:`BufferedWriter` and :class:`BufferedReader` are for objects
+  that only support writing or reading and don't support random
+  access.  :class:`BufferedRandom` adds the :meth:`seek` method for
+  random access, and :class:`BufferedRWPair` is for objects such as
+  TTYs that have both read and write operations that act upon
+  unconnected streams of data.  The :class:`BytesIO`
+  class supports reading, writing, and seeking over an in-memory buffer.
 
 * :class:`TextIOBase`: Provides functions for reading and writing
   strings (remember, strings will be Unicode in Python 3.0),
@@ -1053,8 +1058,7 @@
 of arrays so that callers can write data directly into an array instead
 of going through a slower API.  This PEP updates the buffer protocol in light of experience
 from NumPy development, adding a number of new features
-such as indicating the shape of an array,
-locking memory .
+such as indicating the shape of an array or locking a memory region.
 
 The most important new C API function is
 ``PyObject_GetBuffer(PyObject *obj, Py_buffer *view, int flags)``, which
@@ -1063,10 +1067,11 @@
 about the object's memory representation.  Objects
 can use this operation to lock memory in place
 while an external caller could be modifying the contents,
-so there's a corresponding
-``PyBuffer_Release(Py_buffer *view)`` to
+so there's a corresponding ``PyBuffer_Release(Py_buffer *view)`` to
 indicate that the external caller is done.
 
+.. XXX PyObject_GetBuffer not documented in c-api
+
 The **flags** argument to :cfunc:`PyObject_GetBuffer` specifies
 constraints upon the memory returned.  Some examples are:
 
@@ -1078,7 +1083,8 @@
    requests a C-contiguous (last dimension varies the fastest) or
    Fortran-contiguous (first dimension varies the fastest) layout.
 
-.. XXX this feature is not in 2.6 docs yet
+Two new argument codes for :cfunc:`PyArg_ParseTuple`,
+``s*`` and ``z*``, return locked buffer objects for a parameter.
 
 .. seealso::
 
@@ -1436,6 +1442,18 @@
 
   (Contributed by Alexander Belopolsky; :issue:`1686487`.)
 
+  It's also now legal to provide keyword arguments after a ``*args`` argument
+  to a function call.
+
+    >>> def f(*args, **kw):
+    ...     print args, kw
+    ...
+    >>> f(1,2,3, *(4,5,6), keyword=13)
+    (1, 2, 3, 4, 5, 6) {'keyword': 13}
+
+  Previously this would have been a syntax error.
+  (Contributed by Amaury Forgeot d'Arc; :issue:`3473`.)
+
 * A new built-in, ``next(*iterator*, [*default*])`` returns the next item
   from the specified iterator.  If the *default* argument is supplied,
   it will be returned if *iterator* has been exhausted; otherwise,
@@ -1485,8 +1503,8 @@
             self._x = value / 2
 
 * Several methods of the built-in set types now accept multiple iterables:
-  :meth:`intersection`, 
-  :meth:`intersection_update`, 
+  :meth:`intersection`,
+  :meth:`intersection_update`,
   :meth:`union`, :meth:`update`,
   :meth:`difference` and :meth:`difference_update`.
 
@@ -1645,10 +1663,21 @@
   (Original optimization implemented by Armin Rigo, updated for
   Python 2.6 by Kevin Jacobs; :issue:`1700288`.)
 
+  By default, this change is only applied to types that are included with
+  the Python core.  Extension modules may not necessarily be compatible with
+  this cache,
+  so they must explicitly add :cmacro:`Py_TPFLAGS_HAVE_VERSION_TAG`
+  to the module's ``tp_flags`` field to enable the method cache.
+  (To be compatible with the method cache, the extension module's code
+  must not directly access and modify the ``tp_dict`` member of
+  any of the types it implements.  Most modules don't do this,
+  but it's impossible for the Python interpreter to determine that.
+  See :issue:`1878` for some discussion.)
+
 * Function calls that use keyword arguments
   are significantly faster thanks to a patch that does a quick pointer
   comparison, usually saving the time of a full string comparison.
-  (Contributed by Raymond Hettinger, after an initial implementation by 
+  (Contributed by Raymond Hettinger, after an initial implementation by
   Antoine Pitrou; :issue:`1819`.)
 
 * All of the functions in the :mod:`struct` module have been rewritten in
@@ -1701,10 +1730,10 @@
 
 The encoding used for standard input, output, and standard error can
 be specified by setting the :envvar:`PYTHONIOENCODING` environment
-variable before running the interpreter.  The value should be a string 
-in the form ``**encoding**`` or ``**encoding**:**errorhandler**``.  
+variable before running the interpreter.  The value should be a string
+in the form ``**encoding**`` or ``**encoding**:**errorhandler**``.
 The **encoding** part specifies the encoding's name, e.g. ``utf-8`` or
-``latin-1``; the optional **errorhandler** part specifies 
+``latin-1``; the optional **errorhandler** part specifies
 what to do with characters that can't be handled by the encoding,
 and  should be one of "error", "ignore", or "replace".   (Contributed
 by Martin von Loewis.)
@@ -1814,18 +1843,18 @@
   :mod:`videoreader`,
   :mod:`WAIT`.
 
-* The :mod:`asyncore` and :mod:`asynchat` modules are 
-  being actively maintained again, and a number of patches and bugfixes 
-  were applied.  (Maintained by Josiah Carlson; see :issue:`1736190` for 
+* The :mod:`asyncore` and :mod:`asynchat` modules are
+  being actively maintained again, and a number of patches and bugfixes
+  were applied.  (Maintained by Josiah Carlson; see :issue:`1736190` for
   one patch.)
 
 * The :mod:`bsddb.dbshelve` module now uses the highest pickling protocol
   available, instead of restricting itself to protocol 1.
   (Contributed by W. Barnes; :issue:`1551443`.)
 
-* The :mod:`cgi` module will now read variables from the query string of an 
-  HTTP POST request.  This makes it possible to use form actions with 
-  URLs such as "/cgi-bin/add.py?category=1".  (Contributed by 
+* The :mod:`cgi` module will now read variables from the query string of an
+  HTTP POST request.  This makes it possible to use form actions with
+  URLs such as "/cgi-bin/add.py?category=1".  (Contributed by
   Alexandre Fiori and Nubis; :issue:`1817`.)
 
 * The :mod:`cmath` module underwent an extensive set of revisions,
@@ -1973,7 +2002,7 @@
 * When possible, the :mod:`getpass` module will now use
   :file:`/dev/tty` (when available) to print
   a prompting message and read the password, falling back to using
-  standard error and standard input.    If the password may be echoed to 
+  standard error and standard input.    If the password may be echoed to
   the terminal, a warning is printed before the prompt is displayed.
   (Contributed by Gregory P. Smith.)
 
@@ -1998,7 +2027,7 @@
 
   :mod:`heapq` is now implemented to only use less-than comparison,
   instead of the less-than-or-equal comparison it previously used.
-  This makes :mod:`heapq`'s usage of a type match that of the 
+  This makes :mod:`heapq`'s usage of a type match that of the
   :meth:`list.sort` method.
   (Contributed by Raymond Hettinger.)
 
@@ -2094,8 +2123,8 @@
   is true, opening of the log file is deferred until the first
   :meth:`emit` call is made.  (Contributed by Vinay Sajip.)
 
-  :class:`TimedRotatingFileHandler` also has a *utc* constructor 
-  parameter.  If the argument is true, UTC time will be used 
+  :class:`TimedRotatingFileHandler` also has a *utc* constructor
+  parameter.  If the argument is true, UTC time will be used
   in determining when midnight occurs and in generating filenames;
   otherwise local time will be used.
 
@@ -2246,6 +2275,13 @@
   time-consuming searches can now be interrupted.
   (Contributed by Josh Hoyt and Ralf Schmitt; :issue:`846388`.)
 
+  The regular expression module is implemented by compiling bytecodes
+  for a tiny regex-specific virtual machine.  Untrusted code
+  could create malicious strings of bytecode directly and cause crashes,
+  so Python 2.6 includes a verifier for the regex bytecode.
+  (Contributed by Guido van Rossum from work for Google App Engine;
+  :issue:`3487`.)
+
 * The :mod:`rgbimg` module has been removed.
 
 * The :mod:`rlcompleter` module's :meth:`Completer.complete()` method
@@ -2272,17 +2308,17 @@
 * The :func:`shutil.copytree` function now has an optional **ignore** argument
   that takes a callable object.  This callable will receive each directory path
   and a list of the directory's contents, and returns a list of names that
-  will be ignored, not copied.  
+  will be ignored, not copied.
 
   The :mod:`shutil` module also provides an :func:`ignore_patterns`
   function for use with this new parameter.
   :func:`ignore_patterns` takes an arbitrary number of glob-style patterns
   and will ignore any files and directories that match this pattern.
   The following example copies a directory tree, but skip both SVN's internal
-  :file:`.svn` directories and Emacs backup 
+  :file:`.svn` directories and Emacs backup
   files, which have names ending with '~'::
 
-      shutil.copytree('Doc/library', '/tmp/library', 
+      shutil.copytree('Doc/library', '/tmp/library',
                       ignore=shutil.ignore_patterns('*~', '.svn'))
 
   (Contributed by Tarek Ziadé; :issue:`2663`.)
@@ -2395,10 +2431,10 @@
   These attributes are all read-only.
   (Contributed by Christian Heimes.)
 
-  A new function, :func:`getsizeof`, takes a Python object and returns 
+  A new function, :func:`getsizeof`, takes a Python object and returns
   the amount of memory used by the object, measured in bytes.  Built-in
   objects return correct results; third-party extensions may not,
-  but can define a :meth:`__sizeof__` method to return the 
+  but can define a :meth:`__sizeof__` method to return the
   object's size.
   (Contributed by Robert Schuppenies; :issue:`2898`.)
 
@@ -2487,9 +2523,18 @@
 
   (Contributed by Dwayne Bailey; :issue:`1581073`.)
 
-* The :mod:`threading` module's :class:`Thread` objects 
-  gained a :meth:`getIdent` method that returns the thread's 
-  identifier, a nonzero integer.  (Contributed by Gregory P. Smith; 
+* The :mod:`threading` module API is being changed for Python 3.0, to
+  use properties such as :attr:`daemon` instead of :meth:`setDaemon`
+  and :meth:`isDaemon` methods, and some methods have been renamed to
+  use underscores instead of camel-case; for example, the
+  :meth:`activeCount` method is renamed to :meth:`active_count`.  The
+  2.6 version of the module supports the same properties and renamed
+  methods, but doesn't remove the old methods.  (Carried out by
+  various people, most notably Benjamin Peterson.)
+
+  The :mod:`threading` module's :class:`Thread` objects
+  gained an :attr:`ident` property that returns the thread's
+  identifier, a nonzero integer.  (Contributed by Gregory P. Smith;
   :issue:`2871`.)
 
 * The :mod:`timeit` module now accepts callables as well as strings
@@ -2502,7 +2547,7 @@
   :issue:`1533909`.)
 
 * The :mod:`Tkinter` module now accepts lists and tuples for options,
-  separating the elements by spaces before passing the resulting value to 
+  separating the elements by spaces before passing the resulting value to
   Tcl/Tk.
   (Contributed by Guilherme Polo; :issue:`2906`.)
 
@@ -2510,18 +2555,18 @@
   Gregor Lingl.  New features in the module include:
 
   * Better animation of turtle movement and rotation.
-  * Control over turtle movement using the new delay(), 
+  * Control over turtle movement using the new delay(),
     tracer(), and speed() methods.
-  * The ability to set new shapes for the turtle, and to 
+  * The ability to set new shapes for the turtle, and to
     define a new coordinate system.
   * Turtles now have an undo() method that can roll back actions.
   * Simple support for reacting to input events such as mouse and keyboard
     activity, making it possible to write simple games.
-  * A :file:`turtle.cfg` file can be used to customize the starting appearance 
+  * A :file:`turtle.cfg` file can be used to customize the starting appearance
     of the turtle's screen.
   * The module's docstrings can be replaced by new docstrings that have been
     translated into another language.
-  
+
   (:issue:`1513695`)
 
 * An optional ``timeout`` parameter was added to the
@@ -2569,7 +2614,7 @@
   dates before 1900 (contributed by Ralf Schmitt; :issue:`2014`)
   and 64-bit integers represented by using ``<i8>`` in XML-RPC responses
   (contributed by Riku Lindblad; :issue:`2985`).
-  
+
 * The :mod:`zipfile` module's :class:`ZipFile` class now has
   :meth:`extract` and :meth:`extractall` methods that will unpack
   a single file or all the files in the archive to the current directory, or
@@ -2585,14 +2630,14 @@
 
   (Contributed by Alan McIntyre; :issue:`467924`.)
 
-  The :meth:`open`, :meth:`read` and :meth:`extract` methods can now 
+  The :meth:`open`, :meth:`read` and :meth:`extract` methods can now
   take either a filename or a :class:`ZipInfo` object.  This is useful when an
   archive accidentally contains a duplicated filename.
   (Contributed by Graham Horler; :issue:`1775025`.)
 
   Finally, :mod:`zipfile` now supports using Unicode filenames
   for archived files.  (Contributed by Alexey Borzenkov; :issue:`1734346`.)
-  
+
 .. ======================================================================
 .. whole new modules get described in subsections here
 
@@ -2603,7 +2648,7 @@
 of Python code.  For Python 2.6, Armin Ronacher contributed a set of
 helper functions that perform various common tasks.  These will be useful
 for HTML templating packages, code analyzers, and similar tools that
-process Python code. 
+process Python code.
 
 The :func:`parse` function takes an expression and returns an AST.
 The :func:`dump` function outputs a representation of a tree, suitable
@@ -2638,7 +2683,7 @@
 representing a literal expression, one that contains a Python
 expression containing only strings, numbers, dictionaries, etc. but no
 statements or function calls, and returns the resulting value.  If you
-need to unserialize an expression but need to worry about security 
+need to unserialize an expression but need to worry about security
 and can't risk using an :func:`eval` call, :func:`literal_eval` will
 handle it safely::
 
@@ -2663,22 +2708,22 @@
 Python 3.0 makes various changes to the repertoire of built-in
 functions, and most of the changes can't be introduced in the Python
 2.x series because they would break compatibility.
-The :mod:`future_builtins` module provides versions 
-of these built-in functions that can be imported when writing 
+The :mod:`future_builtins` module provides versions
+of these built-in functions that can be imported when writing
 3.0-compatible code.
 
 The functions in this module currently include:
 
-* ``ascii(**obj**)``: equivalent to :func:`repr`.  In Python 3.0, 
-  :func:`repr` will return a Unicode string, while :func:`ascii` will 
+* ``ascii(**obj**)``: equivalent to :func:`repr`.  In Python 3.0,
+  :func:`repr` will return a Unicode string, while :func:`ascii` will
   return a pure ASCII bytestring.
 
-* ``filter(**predicate**, **iterable**)``, 
-  ``map(**func**, **iterable1**, ...)``: the 3.0 versions 
+* ``filter(**predicate**, **iterable**)``,
+  ``map(**func**, **iterable1**, ...)``: the 3.0 versions
   return iterators, differing from the 2.x built-ins that return lists.
 
-* ``hex(**value**)``, ``oct(**value**)``: instead of calling the 
-  :meth:`__hex__` or :meth:`__oct__` methods, these versions will 
+* ``hex(**value**)``, ``oct(**value**)``: instead of calling the
+  :meth:`__hex__` or :meth:`__oct__` methods, these versions will
   call the :meth:`__index__` method and convert the result to hexadecimal
   or octal.
 
@@ -2753,8 +2798,8 @@
 ctypes Enhancements
 --------------------------------------------------
 
-Thomas Heller continued to maintain and enhance the 
-:mod:`ctypes` module.  
+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;
@@ -2767,6 +2812,13 @@
 
 .. Revision 57769
 
+All :mod:`ctypes` data types now support
+:meth:`from_buffer` and :meth:`from_buffer_copy`
+methods that create a ctypes instance based on a
+provided buffer object.  :meth:`from_buffer_copy` copies
+the contents of the object,
+while :meth:`from_buffer` will share the same memory area.
+
 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`.)
@@ -2775,13 +2827,13 @@
 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.  
+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`.  
+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
@@ -2823,7 +2875,7 @@
   (Implemented by Christian Heimes.)
 
 * On MacOS X, Python 2.6 can be compiled as a 4-way universal build.
-  The :program:`configure` script 
+  The :program:`configure` script
   can take a :option:`--with-universal-archs=[32-bit|64-bit|all]`
   switch, controlling whether the binaries are built for 32-bit
   architectures (x86, PowerPC), 64-bit (x86-64 and PPC-64), or both.
@@ -2964,9 +3016,9 @@
   registry reflection for 32-bit processes running on 64-bit systems.
   (:issue:`1753245`)
 
-* The :mod:`msilib` module's :class:`Record` object 
-  gained :meth:`GetInteger` and :meth:`GetString` methods that 
-  return field values as an integer or a string.  
+* The :mod:`msilib` module's :class:`Record` object
+  gained :meth:`GetInteger` and :meth:`GetString` methods that
+  return field values as an integer or a string.
   (Contributed by Floris Bruynooghe; :issue:`2125`.)
 
 * The new default compiler on Windows is Visual Studio 2008 (VS 9.0). The
@@ -2982,9 +3034,9 @@
 Port-Specific Changes: MacOS X
 -----------------------------------
 
-* When compiling a framework build of Python, you can now specify the 
-  framework name to be used by providing the 
-  :option:`--with-framework-name=` option to the 
+* When compiling a framework build of Python, you can now specify the
+  framework name to be used by providing the
+  :option:`--with-framework-name=` option to the
   :program:`configure` script.
 
 .. ======================================================================

Modified: python/branches/tlee-ast-optimize/Include/abstract.h
==============================================================================
--- python/branches/tlee-ast-optimize/Include/abstract.h	(original)
+++ python/branches/tlee-ast-optimize/Include/abstract.h	Wed Aug 27 11:15:24 2008
@@ -1377,6 +1377,11 @@
       /* issubclass(object, typeorclass) */
 
 
+PyAPI_FUNC(int) _PyObject_RealIsInstance(PyObject *inst, PyObject *cls);
+
+PyAPI_FUNC(int) _PyObject_RealIsSubclass(PyObject *derived, PyObject *cls);
+
+
 #ifdef __cplusplus
 }
 #endif

Modified: python/branches/tlee-ast-optimize/Include/object.h
==============================================================================
--- python/branches/tlee-ast-optimize/Include/object.h	(original)
+++ python/branches/tlee-ast-optimize/Include/object.h	Wed Aug 27 11:15:24 2008
@@ -458,6 +458,7 @@
 PyAPI_FUNC(PyObject *) PyObject_Repr(PyObject *);
 PyAPI_FUNC(PyObject *) _PyObject_Str(PyObject *);
 PyAPI_FUNC(PyObject *) PyObject_Str(PyObject *);
+#define PyObject_Bytes PyObject_Str
 #ifdef Py_USING_UNICODE
 PyAPI_FUNC(PyObject *) PyObject_Unicode(PyObject *);
 #endif

Modified: python/branches/tlee-ast-optimize/Lib/test/test_abc.py
==============================================================================
--- python/branches/tlee-ast-optimize/Lib/test/test_abc.py	(original)
+++ python/branches/tlee-ast-optimize/Lib/test/test_abc.py	Wed Aug 27 11:15:24 2008
@@ -88,15 +88,21 @@
             pass
         b = B()
         self.assertEqual(issubclass(B, A), False)
+        self.assertEqual(issubclass(B, (A,)), False)
         self.assertEqual(isinstance(b, A), False)
+        self.assertEqual(isinstance(b, (A,)), False)
         A.register(B)
         self.assertEqual(issubclass(B, A), True)
+        self.assertEqual(issubclass(B, (A,)), True)
         self.assertEqual(isinstance(b, A), True)
+        self.assertEqual(isinstance(b, (A,)), True)
         class C(B):
             pass
         c = C()
         self.assertEqual(issubclass(C, A), True)
+        self.assertEqual(issubclass(C, (A,)), True)
         self.assertEqual(isinstance(c, A), True)
+        self.assertEqual(isinstance(c, (A,)), True)
 
     def test_isinstance_invalidation(self):
         class A:
@@ -105,20 +111,26 @@
             pass
         b = B()
         self.assertEqual(isinstance(b, A), False)
+        self.assertEqual(isinstance(b, (A,)), False)
         A.register(B)
         self.assertEqual(isinstance(b, A), True)
+        self.assertEqual(isinstance(b, (A,)), True)
 
     def test_registration_builtins(self):
         class A:
             __metaclass__ = abc.ABCMeta
         A.register(int)
         self.assertEqual(isinstance(42, A), True)
+        self.assertEqual(isinstance(42, (A,)), True)
         self.assertEqual(issubclass(int, A), True)
+        self.assertEqual(issubclass(int, (A,)), True)
         class B(A):
             pass
         B.register(basestring)
         self.assertEqual(isinstance("", A), True)
+        self.assertEqual(isinstance("", (A,)), True)
         self.assertEqual(issubclass(str, A), True)
+        self.assertEqual(issubclass(str, (A,)), True)
 
     def test_registration_edge_cases(self):
         class A:
@@ -141,29 +153,40 @@
         class A:
             __metaclass__ = abc.ABCMeta
         self.failUnless(issubclass(A, A))
+        self.failUnless(issubclass(A, (A,)))
         class B:
             __metaclass__ = abc.ABCMeta
         self.failIf(issubclass(A, B))
+        self.failIf(issubclass(A, (B,)))
         self.failIf(issubclass(B, A))
+        self.failIf(issubclass(B, (A,)))
         class C:
             __metaclass__ = abc.ABCMeta
         A.register(B)
         class B1(B):
             pass
         self.failUnless(issubclass(B1, A))
+        self.failUnless(issubclass(B1, (A,)))
         class C1(C):
             pass
         B1.register(C1)
         self.failIf(issubclass(C, B))
+        self.failIf(issubclass(C, (B,)))
         self.failIf(issubclass(C, B1))
+        self.failIf(issubclass(C, (B1,)))
         self.failUnless(issubclass(C1, A))
+        self.failUnless(issubclass(C1, (A,)))
         self.failUnless(issubclass(C1, B))
+        self.failUnless(issubclass(C1, (B,)))
         self.failUnless(issubclass(C1, B1))
+        self.failUnless(issubclass(C1, (B1,)))
         C1.register(int)
         class MyInt(int):
             pass
         self.failUnless(issubclass(MyInt, A))
+        self.failUnless(issubclass(MyInt, (A,)))
         self.failUnless(isinstance(42, A))
+        self.failUnless(isinstance(42, (A,)))
 
     def test_all_new_methods_are_called(self):
         class A:

Modified: python/branches/tlee-ast-optimize/Lib/test/test_exceptions.py
==============================================================================
--- python/branches/tlee-ast-optimize/Lib/test/test_exceptions.py	(original)
+++ python/branches/tlee-ast-optimize/Lib/test/test_exceptions.py	Wed Aug 27 11:15:24 2008
@@ -333,7 +333,19 @@
                 return g()
             except ValueError:
                 return -1
-        self.assertRaises(RuntimeError, g)
+
+        # The test prints an unraisable recursion error when
+        # doing "except ValueError", this is because subclass
+        # checking has recursion checking too.
+        with captured_output("stderr"):
+            try:
+                g()
+            except RuntimeError:
+                pass
+            except:
+                self.fail("Should have raised KeyError")
+            else:
+                self.fail("Should have raised KeyError")
 
     def testUnicodeStrUsage(self):
         # Make sure both instances and classes have a str and unicode
@@ -363,12 +375,20 @@
             except KeyError:
                 pass
             except:
-                self.fail("Should have raised TypeError")
+                self.fail("Should have raised KeyError")
             else:
-                self.fail("Should have raised TypeError")
-        self.assertEqual(stderr.getvalue(),
-                         "Exception ValueError: ValueError() in "
-                         "<type 'exceptions.KeyError'> ignored\n")
+                self.fail("Should have raised KeyError")
+
+        with captured_output("stderr") as stderr:
+            def g():
+                try:
+                    return g()
+                except RuntimeError:
+                    return sys.exc_info()
+            e, v, tb = g()
+            self.assert_(e is RuntimeError, e)
+            self.assert_("maximum recursion depth exceeded" in str(v), v)
+
 
 def test_main():
     run_unittest(ExceptionTests)

Modified: python/branches/tlee-ast-optimize/Lib/test/test_typechecks.py
==============================================================================
--- python/branches/tlee-ast-optimize/Lib/test/test_typechecks.py	(original)
+++ python/branches/tlee-ast-optimize/Lib/test/test_typechecks.py	Wed Aug 27 11:15:24 2008
@@ -41,26 +41,39 @@
 
     def testIsSubclassBuiltin(self):
         self.assertEqual(issubclass(int, Integer), True)
+        self.assertEqual(issubclass(int, (Integer,)), True)
         self.assertEqual(issubclass(float, Integer), False)
+        self.assertEqual(issubclass(float, (Integer,)), False)
 
     def testIsInstanceBuiltin(self):
         self.assertEqual(isinstance(42, Integer), True)
+        self.assertEqual(isinstance(42, (Integer,)), True)
         self.assertEqual(isinstance(3.14, Integer), False)
+        self.assertEqual(isinstance(3.14, (Integer,)), False)
 
     def testIsInstanceActual(self):
         self.assertEqual(isinstance(Integer(), Integer), True)
+        self.assertEqual(isinstance(Integer(), (Integer,)), True)
 
     def testIsSubclassActual(self):
         self.assertEqual(issubclass(Integer, Integer), True)
+        self.assertEqual(issubclass(Integer, (Integer,)), True)
 
     def testSubclassBehavior(self):
         self.assertEqual(issubclass(SubInt, Integer), True)
+        self.assertEqual(issubclass(SubInt, (Integer,)), True)
         self.assertEqual(issubclass(SubInt, SubInt), True)
+        self.assertEqual(issubclass(SubInt, (SubInt,)), True)
         self.assertEqual(issubclass(Integer, SubInt), False)
+        self.assertEqual(issubclass(Integer, (SubInt,)), False)
         self.assertEqual(issubclass(int, SubInt), False)
+        self.assertEqual(issubclass(int, (SubInt,)), False)
         self.assertEqual(isinstance(SubInt(), Integer), True)
+        self.assertEqual(isinstance(SubInt(), (Integer,)), True)
         self.assertEqual(isinstance(SubInt(), SubInt), True)
+        self.assertEqual(isinstance(SubInt(), (SubInt,)), True)
         self.assertEqual(isinstance(42, SubInt), False)
+        self.assertEqual(isinstance(42, (SubInt,)), False)
 
     def testInfiniteRecursionCaughtProperly(self):
         e = Evil()

Modified: python/branches/tlee-ast-optimize/Misc/NEWS
==============================================================================
--- python/branches/tlee-ast-optimize/Misc/NEWS	(original)
+++ python/branches/tlee-ast-optimize/Misc/NEWS	Wed Aug 27 11:15:24 2008
@@ -12,6 +12,13 @@
 Core and Builtins
 -----------------
 
+- Issue #2534: speed up isinstance() and issubclass() by 50-70%, so as to 
+  match Python 2.5 speed despite the __instancecheck__ / __subclasscheck__
+  mechanism. In the process, fix a bug where isinstance() and issubclass(),
+  when given a tuple of classes as second argument, were looking up
+  __instancecheck__ / __subclasscheck__ on the tuple rather than on each
+  type object.
+
 - Fix crashes on memory allocation failure found with failmalloc.
 
 - Fix memory leaks found with valgrind and update suppressions file.
@@ -29,6 +36,11 @@
 - Added warnings on the use of ``__getslice__``, ``__setslice__``, or
   ``__delslice__``.
 
+C-API
+-----
+
+- Aliased PyObject_Bytes to PyObject_Str.
+
 Library
 -------
 

Modified: python/branches/tlee-ast-optimize/Objects/abstract.c
==============================================================================
--- python/branches/tlee-ast-optimize/Objects/abstract.c	(original)
+++ python/branches/tlee-ast-optimize/Objects/abstract.c	Wed Aug 27 11:15:24 2008
@@ -2778,39 +2778,38 @@
 static int
 abstract_issubclass(PyObject *derived, PyObject *cls)
 {
-	PyObject *bases;
+	PyObject *bases = NULL;
 	Py_ssize_t i, n;
 	int r = 0;
 
-
-	if (derived == cls)
-		return 1;
-
-	if (PyTuple_Check(cls)) {
-		/* Not a general sequence -- that opens up the road to
-		   recursion and stack overflow. */
-		n = PyTuple_GET_SIZE(cls);
+	while (1) {
+		if (derived == cls)
+			return 1;
+		bases = abstract_get_bases(derived);
+		if (bases == NULL) {
+			if (PyErr_Occurred())
+				return -1;
+			return 0;
+		}
+		n = PyTuple_GET_SIZE(bases);
+		if (n == 0) {
+			Py_DECREF(bases);
+			return 0;
+		}
+		/* Avoid recursivity in the single inheritance case */
+		if (n == 1) {
+			derived = PyTuple_GET_ITEM(bases, 0);
+			Py_DECREF(bases);
+			continue;
+		}
 		for (i = 0; i < n; i++) {
-			if (derived == PyTuple_GET_ITEM(cls, i))
-				return 1;
+			r = abstract_issubclass(PyTuple_GET_ITEM(bases, i), cls);
+			if (r != 0)
+				break;
 		}
+		Py_DECREF(bases);
+		return r;
 	}
-	bases = abstract_get_bases(derived);
-	if (bases == NULL) {
-		if (PyErr_Occurred())
-			return -1;
-		return 0;
-	}
-	n = PyTuple_GET_SIZE(bases);
-	for (i = 0; i < n; i++) {
-		r = abstract_issubclass(PyTuple_GET_ITEM(bases, i), cls);
-		if (r != 0)
-			break;
-	}
-
-	Py_DECREF(bases);
-
-	return r;
 }
 
 static int
@@ -2828,7 +2827,7 @@
 }
 
 static int
-recursive_isinstance(PyObject *inst, PyObject *cls, int recursion_depth)
+recursive_isinstance(PyObject *inst, PyObject *cls)
 {
 	PyObject *icls;
 	static PyObject *__class__ = NULL;
@@ -2862,25 +2861,6 @@
 			}
 		}
 	}
-	else if (PyTuple_Check(cls)) {
-		Py_ssize_t i, n;
-
-                if (!recursion_depth) {
-                    PyErr_SetString(PyExc_RuntimeError,
-                                    "nest level of tuple too deep");
-                    return -1;
-                }
-
-		n = PyTuple_GET_SIZE(cls);
-		for (i = 0; i < n; i++) {
-			retval = recursive_isinstance(
-                                    inst,
-                                    PyTuple_GET_ITEM(cls, i),
-                                    recursion_depth-1);
-			if (retval != 0)
-				break;
-		}
-	}
 	else {
 		if (!check_class(cls,
 			"isinstance() arg 2 must be a class, type,"
@@ -2910,6 +2890,24 @@
 	if (Py_TYPE(inst) == (PyTypeObject *)cls)
 		return 1;
 
+	if (PyTuple_Check(cls)) {
+		Py_ssize_t i;
+		Py_ssize_t n;
+		int r = 0;
+
+		if (Py_EnterRecursiveCall(" in __instancecheck__"))
+			return -1;
+		n = PyTuple_GET_SIZE(cls);
+		for (i = 0; i < n; ++i) {
+			PyObject *item = PyTuple_GET_ITEM(cls, i);
+			r = PyObject_IsInstance(inst, item);
+			if (r != 0)
+				/* either found it, or got an error */
+				break;
+		}
+		Py_LeaveRecursiveCall();
+		return r;
+	}
 	if (name == NULL) {
 		name = PyString_InternFromString("__instancecheck__");
 		if (name == NULL)
@@ -2934,47 +2932,28 @@
 		}
 		return ok;
 	}
-	return recursive_isinstance(inst, cls, Py_GetRecursionLimit());
+	return recursive_isinstance(inst, cls);
 }
 
 static  int
-recursive_issubclass(PyObject *derived, PyObject *cls, int recursion_depth)
+recursive_issubclass(PyObject *derived, PyObject *cls)
 {
 	int retval;
 
+ 	if (PyType_Check(cls) && PyType_Check(derived)) {
+ 		/* Fast path (non-recursive) */
+ 		return PyType_IsSubtype(
+			(PyTypeObject *)derived, (PyTypeObject *)cls);
+ 	}
 	if (!PyClass_Check(derived) || !PyClass_Check(cls)) {
 		if (!check_class(derived,
 				 "issubclass() arg 1 must be a class"))
 			return -1;
 
-		if (PyTuple_Check(cls)) {
-			Py_ssize_t i;
-			Py_ssize_t n = PyTuple_GET_SIZE(cls);
-
-                        if (!recursion_depth) {
-                            PyErr_SetString(PyExc_RuntimeError,
-                                            "nest level of tuple too deep");
-                            return -1;
-                        }
-			for (i = 0; i < n; ++i) {
-				retval = recursive_issubclass(
-                                            derived,
-                                            PyTuple_GET_ITEM(cls, i),
-                                            recursion_depth-1);
-				if (retval != 0) {
-					/* either found it, or got an error */
-					return retval;
-				}
-			}
-			return 0;
-		}
-		else {
-			if (!check_class(cls,
-					"issubclass() arg 2 must be a class"
-					" or tuple of classes"))
-				return -1;
-		}
-
+		if (!check_class(cls,
+				"issubclass() arg 2 must be a class"
+				" or tuple of classes"))
+			return -1;
 		retval = abstract_issubclass(derived, cls);
 	}
 	else {
@@ -2992,20 +2971,40 @@
 	static PyObject *name = NULL;
 	PyObject *t, *v, *tb;
 	PyObject *checker;
-	PyErr_Fetch(&t, &v, &tb);
 	
+ 	if (PyTuple_Check(cls)) {
+ 		Py_ssize_t i;
+ 		Py_ssize_t n;
+ 		int r = 0;
+ 
+ 		if (Py_EnterRecursiveCall(" in __subclasscheck__"))
+ 			return -1;
+ 		n = PyTuple_GET_SIZE(cls);
+ 		for (i = 0; i < n; ++i) {
+ 			PyObject *item = PyTuple_GET_ITEM(cls, i);
+ 			r = PyObject_IsSubclass(derived, item);
+ 			if (r != 0)
+ 				/* either found it, or got an error */
+ 				break;
+ 		}
+ 		Py_LeaveRecursiveCall();
+ 		return r;
+ 	}
 	if (name == NULL) {
 		name = PyString_InternFromString("__subclasscheck__");
 		if (name == NULL)
 			return -1;
 	}
+	PyErr_Fetch(&t, &v, &tb);
 	checker = PyObject_GetAttr(cls, name);
 	PyErr_Restore(t, v, tb);
 	if (checker != NULL) {
 		PyObject *res;
 		int ok = -1;
-		if (Py_EnterRecursiveCall(" in __subclasscheck__"))
+		if (Py_EnterRecursiveCall(" in __subclasscheck__")) {
+			Py_DECREF(checker);
 			return ok;
+		}
 		res = PyObject_CallFunctionObjArgs(checker, derived, NULL);
 		Py_LeaveRecursiveCall();
 		Py_DECREF(checker);
@@ -3015,7 +3014,19 @@
 		}
 		return ok;
 	}
-	return recursive_issubclass(derived, cls, Py_GetRecursionLimit());
+	return recursive_issubclass(derived, cls);
+}
+
+int
+_PyObject_RealIsInstance(PyObject *inst, PyObject *cls)
+{
+	return recursive_isinstance(inst, cls);
+}
+
+int
+_PyObject_RealIsSubclass(PyObject *derived, PyObject *cls)
+{
+	return recursive_issubclass(derived, cls);
 }
 
 

Modified: python/branches/tlee-ast-optimize/Objects/typeobject.c
==============================================================================
--- python/branches/tlee-ast-optimize/Objects/typeobject.c	(original)
+++ python/branches/tlee-ast-optimize/Objects/typeobject.c	Wed Aug 27 11:15:24 2008
@@ -571,6 +571,49 @@
 	return result;
 }
 
+static PyObject *
+type___instancecheck__(PyObject *type, PyObject *inst)
+{
+	switch (_PyObject_RealIsInstance(inst, type)) {
+	case -1:
+		return NULL;
+	case 0:
+		Py_RETURN_FALSE;
+	default:
+		Py_RETURN_TRUE;
+	}
+}
+
+
+static PyObject *
+type_get_instancecheck(PyObject *type, void *context)
+{
+	static PyMethodDef ml = {"__instancecheck__",
+				 type___instancecheck__, METH_O };
+	return PyCFunction_New(&ml, type);
+}
+
+static PyObject *
+type___subclasscheck__(PyObject *type, PyObject *inst)
+{
+	switch (_PyObject_RealIsSubclass(inst, type)) {
+	case -1:
+		return NULL;
+	case 0:
+		Py_RETURN_FALSE;
+	default:
+		Py_RETURN_TRUE;
+	}
+}
+
+static PyObject *
+type_get_subclasscheck(PyObject *type, void *context)
+{
+	static PyMethodDef ml = {"__subclasscheck__",
+				 type___subclasscheck__, METH_O };
+	return PyCFunction_New(&ml, type);
+}
+
 static PyGetSetDef type_getsets[] = {
 	{"__name__", (getter)type_name, (setter)type_set_name, NULL},
 	{"__bases__", (getter)type_get_bases, (setter)type_set_bases, NULL},
@@ -579,6 +622,8 @@
 	 (setter)type_set_abstractmethods, NULL},
 	{"__dict__",  (getter)type_dict,  NULL, NULL},
 	{"__doc__", (getter)type_get_doc, NULL, NULL},
+	{"__instancecheck__", (getter)type_get_instancecheck, NULL, NULL},
+	{"__subclasscheck__", (getter)type_get_subclasscheck, NULL, NULL},
 	{0}
 };
 

Modified: python/branches/tlee-ast-optimize/Python/errors.c
==============================================================================
--- python/branches/tlee-ast-optimize/Python/errors.c	(original)
+++ python/branches/tlee-ast-optimize/Python/errors.c	Wed Aug 27 11:15:24 2008
@@ -113,7 +113,6 @@
 		/* This function must not fail, so print the error here */
 		if (res == -1) {
 			PyErr_WriteUnraisable(err);
-			/* issubclass did not succeed */
 			res = 0;
 		}
 		PyErr_Restore(exception, value, tb);


More information about the Python-checkins mailing list