Python-checkins
Threads by month
- ----- 2024 -----
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
March 2010
- 19 participants
- 1077 discussions
Author: tarek.ziade
Date: Thu Mar 25 11:00:07 2010
New Revision: 79416
Log:
fixed the example
Modified:
peps/trunk/pep-0376.txt
Modified: peps/trunk/pep-0376.txt
==============================================================================
--- peps/trunk/pep-0376.txt (original)
+++ peps/trunk/pep-0376.txt Thu Mar 25 11:00:07 2010
@@ -181,7 +181,7 @@
- docutils/
- roman.py
- - docutils-0.5-py2.6.egg-info/
+ - docutils-0.5.egg-info/
PKG-INFO
The syntax of the egg-info directory name is as follows::
1
0
Author: tarek.ziade
Date: Thu Mar 25 10:43:50 2010
New Revision: 79415
Log:
removed trailing spaces and added more examples on the RECORD file
Modified:
peps/trunk/pep-0376.txt
Modified: peps/trunk/pep-0376.txt
==============================================================================
--- peps/trunk/pep-0376.txt (original)
+++ peps/trunk/pep-0376.txt Thu Mar 25 10:43:50 2010
@@ -85,7 +85,7 @@
Some executable scripts, such as `rst2html.py`, are also be added in the
`bin` directory of the Python installation.
-Another project called `setuptools` [#setuptools]_ has two other formats
+Another project called `setuptools` [#setuptools]_ has two other formats
to install distributions, called `EggFormats` [#eggformats]_:
- a self-contained `.egg` directory, that contains all the distribution files
@@ -100,19 +100,19 @@
uses the ``setuptools.setup`` function in its setup.py file, instead of
the ``distutils.core.setup`` one.
-The `setuptools` project also provides an executable script called
-`easy_install` [#easyinstall]_ that installs all distributions, including
+The `setuptools` project also provides an executable script called
+`easy_install` [#easyinstall]_ that installs all distributions, including
distutils-based ones in self-contained `.egg` directories.
-If you want to have a standalone `.egg.info` directory distributions, e.g.
+If you want to have a standalone `.egg.info` directory distributions, e.g.
the second `setuptools` format, you have to force it when you work
with a setuptools-based distribution or with the `easy_install` script.
-You can force it by using the `-–single-version-externally-managed` option
+You can force it by using the `-–single-version-externally-managed` option
**or** the `--root` option.
This option is used by :
-- the `pip` [#pip]_ installer
+- the `pip` [#pip]_ installer
- the Fedora packagers [#fedora]_.
- the Debian packagers [#debian]_.
@@ -152,21 +152,21 @@
.egg-info becomes a directory
=============================
-As explained earlier, the `EggFormats` standard from `setuptools` proposes two
+As explained earlier, the `EggFormats` standard from `setuptools` proposes two
formats to install the metadata information of a distribution:
- A self-contained directory that can be zipped or left unzipped and contains
- the distribution files *and* an `.egg-info` directory containing the
+ the distribution files *and* an `.egg-info` directory containing the
metadata.
- A distinct `.egg-info` directory located in the site-packages directory,
with the metadata inside.
This PEP proposes to keep just one format and make it the standard way to
-install the metadata of a distribution : a distinct `.egg-info` directory
+install the metadata of a distribution : a distinct `.egg-info` directory
located in the site-packages directory, containing the metadata.
-This `.egg-info` directory contains a `PKG-INFO` file built by the
+This `.egg-info` directory contains a `PKG-INFO` file built by the
`write_pkg_file` method of the `Distribution` class in Distutils.
This change does not impact Python itself because the metadata files are not
@@ -176,7 +176,7 @@
they already work with a directory that contains a `PKG-INFO` file, the change
will have no deep consequences.
-Let's take an example of the new format with the `docutils` distribution.
+Let's take an example of the new format with the `docutils` distribution.
The elements installed in `site-packages` are::
- docutils/
@@ -196,7 +196,7 @@
non-alphanumeric characters (except dots) become dashes, with runs of
multiple dashes condensed to a single dash. Both attributes are then
converted into their filename-escaped form, i.e. any '-' characters are
-replaced with '_' other than the one in 'egg-info' and the one
+replaced with '_' other than the one in 'egg-info' and the one
separating the name from the version number.
Examples::
@@ -215,15 +215,15 @@
A `RECORD` file is added inside the `.egg-info` directory at installation
time when installing a source distribution using the `install` command.
-Notice that when installing a binary distribution created with `bdist` command
+Notice that when installing a binary distribution created with `bdist` command
or a `bdist`-based command, the `RECORD` file will be installed as well since
these commands use the `install` command to create a binary distributions.
The `RECORD` file holds the list of installed files. These correspond
to the files listed by the `record` option of the `install` command, and will
be generated by default. This allows the implementation of an uninstallation
-feature, as explained later in this PEP. The `install` command also provides
-an option to prevent the `RECORD` file from being written and this option
+feature, as explained later in this PEP. The `install` command also provides
+an option to prevent the `RECORD` file from being written and this option
should be used when creating system packages.
Third-party installation tools also should not overwrite or delete files
@@ -251,11 +251,11 @@
path, no matter what the target system is. This makes this information
cross-compatible and allows simple installations to be relocatable.
- - if the installed file is located under ``sys.prefix`` or
+ - if the installed file is located under ``sys.prefix`` or
`sys.exec_prefix``, it's a it's a '/'-separated relative path prefixed
by the `$PREFIX` or the `$EXEC_PREFIX` string. The `install` command
decides which prefix to use depending on the files. For instance if
- it's an executable script defined in the `scripts` option of the
+ it's an executable script defined in the `scripts` option of the
setup script, `$EXEC_PREFIX` will be used. If `install` doesn't know
which prefix to use, `$PREFIX` is preferred.
@@ -301,6 +301,21 @@
- `docutils` and `docutils-0.5-py2.6.egg-info` are located in `site-packages` so the file
paths are relative to it.
+Example 2
+---------
+
+If a project has files installed elswhere than under the Python installation
+root, they are added in the RECORD file as full paths. For example a project
+that installs a `config.ini` file in `/etc/myapp` will be added like this::
+
+ /etc/myapp/config.ini,b690274f621402dda63bf11ba5373bf2,9544
+
+For a windows platform, the drive letter is added for the absolute paths,
+so a file that is copied in `c:\MyApp\` will be::
+
+ c:\etc\myapp\config.ini,b690274f621402dda63bf11ba5373bf2,9544
+
+
Adding an INSTALLER file in the .egg-info directory
===================================================
@@ -356,15 +371,15 @@
- ``get_distributions()`` -> iterator of ``Distribution`` instances.
- Provides an iterator that looks for ``.egg-info`` directories in
+ Provides an iterator that looks for ``.egg-info`` directories in
``sys.path`` and returns ``Distribution`` instances for
each one of them.
- ``get_distribution(name)`` -> ``Distribution`` or None.
Scans all elements in ``sys.path`` and looks for all directories ending with
- ``.egg-info``. Returns a ``Distribution`` corresponding to the
- ``.egg-info`` directory that contains a PKG-INFO that matches `name`
+ ``.egg-info``. Returns a ``Distribution`` corresponding to the
+ ``.egg-info`` directory that contains a PKG-INFO that matches `name`
for the `name` metadata.
Notice that there should be at most one result. The first result founded
@@ -438,9 +453,9 @@
local absolute path. Otherwise the raw value from `RECORD` is returned.
-Notice that the API is organized in five classes that work with directories
+Notice that the API is organized in five classes that work with directories
and Zip files (so it works with files included in Zip files, see PEP 273 for
-more details [#pep273]_). These classes are described in the documentation
+more details [#pep273]_). These classes are described in the documentation
of the prototype implementation for interested readers [#prototype]_.
Usage example
@@ -490,11 +505,11 @@
Since the APIs proposed in the current PEP provide everything needed to meet
-this requirement, PEP 376 replaces PEP 262 and becomes the official
+this requirement, PEP 376 replaces PEP 262 and becomes the official
`installation database` standard.
The new version of PEP 345 (XXX work in progress) extends the Metadata
-standard and fullfills the requirements described in PEP 262, like the
+standard and fullfills the requirements described in PEP 262, like the
`REQUIRES` section.
Adding an Uninstall function
@@ -507,7 +522,7 @@
Distutils will provide a very basic ``uninstall`` function, that is added
in ``distutils.util`` and takes the name of the distribution to uninstall
as its argument. ``uninstall`` uses the APIs described earlier and remove all
-unique files, as long as their hash didn't change. Then it removes empty
+unique files, as long as their hash didn't change. Then it removes empty
directories left behind.
``uninstall`` returns a list of uninstalled files::
@@ -524,7 +539,7 @@
---------
To make it a reference API for third-party projects that wish to control
-how `uninstall` works, a second callable argument can be used. It's
+how `uninstall` works, a second callable argument can be used. It's
called for each file that is removed. If the callable returns `True`, the
file is removed. If it returns False, it's left alone.
@@ -639,7 +654,7 @@
http://wiki.debian.org/DebianPython/NewPolicy
.. [#prototype]
- http://bitbucket.org/tarek/pep376/
+ http://bitbucket.org/tarek/pep376/
Acknowledgements
================
1
0
Author: larry.hastings
Date: Thu Mar 25 01:54:54 2010
New Revision: 79397
Log:
Backported PyCapsule from 3.1, and converted most uses of
CObject to PyCapsule.
Added:
python/trunk/Doc/c-api/capsule.rst
python/trunk/Include/pycapsule.h
python/trunk/Objects/capsule.c
Modified:
python/trunk/Doc/c-api/cobject.rst
python/trunk/Doc/c-api/concrete.rst
python/trunk/Doc/data/refcounts.dat
python/trunk/Doc/extending/extending.rst
python/trunk/Include/Python.h
python/trunk/Include/cStringIO.h
python/trunk/Include/cobject.h
python/trunk/Include/datetime.h
python/trunk/Include/py_curses.h
python/trunk/Include/pyexpat.h
python/trunk/Include/ucnhash.h
python/trunk/Lib/test/test_sys.py
python/trunk/Makefile.pre.in
python/trunk/Misc/NEWS
python/trunk/Modules/_ctypes/callproc.c
python/trunk/Modules/_ctypes/cfield.c
python/trunk/Modules/_ctypes/ctypes.h
python/trunk/Modules/_cursesmodule.c
python/trunk/Modules/_elementtree.c
python/trunk/Modules/_testcapimodule.c
python/trunk/Modules/cStringIO.c
python/trunk/Modules/cjkcodecs/cjkcodecs.h
python/trunk/Modules/cjkcodecs/multibytecodec.c
python/trunk/Modules/cjkcodecs/multibytecodec.h
python/trunk/Modules/datetimemodule.c
python/trunk/Modules/pyexpat.c
python/trunk/Modules/socketmodule.c
python/trunk/Modules/socketmodule.h
python/trunk/Modules/unicodedata.c
python/trunk/Objects/object.c
python/trunk/Objects/unicodeobject.c
python/trunk/PC/VS7.1/pythoncore.vcproj
python/trunk/PC/VS8.0/pythoncore.vcproj
python/trunk/PC/os2emx/python27.def
python/trunk/PC/os2vacpp/python.def
python/trunk/Python/compile.c
python/trunk/Python/getargs.c
Added: python/trunk/Doc/c-api/capsule.rst
==============================================================================
--- (empty file)
+++ python/trunk/Doc/c-api/capsule.rst Thu Mar 25 01:54:54 2010
@@ -0,0 +1,150 @@
+.. highlightlang:: c
+
+.. _capsules:
+
+Capsules
+--------
+
+.. index:: object: Capsule
+
+Refer to :ref:`using-capsules` for more information on using these objects.
+
+
+.. ctype:: PyCapsule
+
+ This subtype of :ctype:`PyObject` represents an opaque value, useful for C
+ extension modules who need to pass an opaque value (as a :ctype:`void\*`
+ pointer) through Python code to other C code. It is often used to make a C
+ function pointer defined in one module available to other modules, so the
+ regular import mechanism can be used to access C APIs defined in dynamically
+ loaded modules.
+
+.. ctype:: PyCapsule_Destructor
+
+ The type of a destructor callback for a capsule. Defined as::
+
+ typedef void (*PyCapsule_Destructor)(PyObject *);
+
+ See :cfunc:`PyCapsule_New` for the semantics of PyCapsule_Destructor
+ callbacks.
+
+
+.. cfunction:: int PyCapsule_CheckExact(PyObject *p)
+
+ Return true if its argument is a :ctype:`PyCapsule`.
+
+
+.. cfunction:: PyObject* PyCapsule_New(void *pointer, const char *name, PyCapsule_Destructor destructor)
+
+ Create a :ctype:`PyCapsule` encapsulating the *pointer*. The *pointer*
+ argument may not be *NULL*.
+
+ On failure, set an exception and return *NULL*.
+
+ The *name* string may either be *NULL* or a pointer to a valid C string. If
+ non-*NULL*, this string must outlive the capsule. (Though it is permitted to
+ free it inside the *destructor*.)
+
+ If the *destructor* argument is not *NULL*, it will be called with the
+ capsule as its argument when it is destroyed.
+
+ If this capsule will be stored as an attribute of a module, the *name* should
+ be specified as ``modulename.attributename``. This will enable other modules
+ to import the capsule using :cfunc:`PyCapsule_Import`.
+
+
+.. cfunction:: void* PyCapsule_GetPointer(PyObject *capsule, const char *name)
+
+ Retrieve the *pointer* stored in the capsule. On failure, set an exception
+ and return *NULL*.
+
+ The *name* parameter must compare exactly to the name stored in the capsule.
+ If the name stored in the capsule is *NULL*, the *name* passed in must also
+ be *NULL*. Python uses the C function :cfunc:`strcmp` to compare capsule
+ names.
+
+
+.. cfunction:: PyCapsule_Destructor PyCapsule_GetDestructor(PyObject *capsule)
+
+ Return the current destructor stored in the capsule. On failure, set an
+ exception and return *NULL*.
+
+ It is legal for a capsule to have a *NULL* destructor. This makes a *NULL*
+ return code somewhat ambiguous; use :cfunc:`PyCapsule_IsValid` or
+ :cfunc:`PyErr_Occurred` to disambiguate.
+
+
+.. cfunction:: void* PyCapsule_GetContext(PyObject *capsule)
+
+ Return the current context stored in the capsule. On failure, set an
+ exception and return *NULL*.
+
+ It is legal for a capsule to have a *NULL* context. This makes a *NULL*
+ return code somewhat ambiguous; use :cfunc:`PyCapsule_IsValid` or
+ :cfunc:`PyErr_Occurred` to disambiguate.
+
+
+.. cfunction:: const char* PyCapsule_GetName(PyObject *capsule)
+
+ Return the current name stored in the capsule. On failure, set an exception
+ and return *NULL*.
+
+ It is legal for a capsule to have a *NULL* name. This makes a *NULL* return
+ code somewhat ambiguous; use :cfunc:`PyCapsule_IsValid` or
+ :cfunc:`PyErr_Occurred` to disambiguate.
+
+
+.. cfunction:: void* PyCapsule_Import(const char *name, int no_block)
+
+ Import a pointer to a C object from a capsule attribute in a module. The
+ *name* parameter should specify the full name to the attribute, as in
+ ``module.attribute``. The *name* stored in the capsule must match this
+ string exactly. If *no_block* is true, import the module without blocking
+ (using :cfunc:`PyImport_ImportModuleNoBlock`). If *no_block* is false,
+ import the module conventionally (using :cfunc:`PyImport_ImportModule`).
+
+ Return the capsule's internal *pointer* on success. On failure, set an
+ exception and return *NULL*. However, if :cfunc:`PyCapsule_Import` failed to
+ import the module, and *no_block* was true, no exception is set.
+
+.. cfunction:: int PyCapsule_IsValid(PyObject *capsule, const char *name)
+
+ Determines whether or not *capsule* is a valid capsule. A valid capsule is
+ non-*NULL*, passes :cfunc:`PyCapsule_CheckExact`, has a non-*NULL* pointer
+ stored in it, and its internal name matches the *name* parameter. (See
+ :cfunc:`PyCapsule_GetPointer` for information on how capsule names are
+ compared.)
+
+ In other words, if :cfunc:`PyCapsule_IsValid` returns a true value, calls to
+ any of the accessors (any function starting with :cfunc:`PyCapsule_Get`) are
+ guaranteed to succeed.
+
+ Return a nonzero value if the object is valid and matches the name passed in.
+ Return 0 otherwise. This function will not fail.
+
+.. cfunction:: int PyCapsule_SetContext(PyObject *capsule, void *context)
+
+ Set the context pointer inside *capsule* to *context*.
+
+ Return 0 on success. Return nonzero and set an exception on failure.
+
+.. cfunction:: int PyCapsule_SetDestructor(PyObject *capsule, PyCapsule_Destructor destructor)
+
+ Set the destructor inside *capsule* to *destructor*.
+
+ Return 0 on success. Return nonzero and set an exception on failure.
+
+.. cfunction:: int PyCapsule_SetName(PyObject *capsule, const char *name)
+
+ Set the name inside *capsule* to *name*. If non-*NULL*, the name must
+ outlive the capsule. If the previous *name* stored in the capsule was not
+ *NULL*, no attempt is made to free it.
+
+ Return 0 on success. Return nonzero and set an exception on failure.
+
+.. cfunction:: int PyCapsule_SetPointer(PyObject *capsule, void *pointer)
+
+ Set the void pointer inside *capsule* to *pointer*. The pointer may not be
+ *NULL*.
+
+ Return 0 on success. Return nonzero and set an exception on failure.
Modified: python/trunk/Doc/c-api/cobject.rst
==============================================================================
--- python/trunk/Doc/c-api/cobject.rst (original)
+++ python/trunk/Doc/c-api/cobject.rst Thu Mar 25 01:54:54 2010
@@ -7,8 +7,11 @@
.. index:: object: CObject
-Refer to :ref:`using-cobjects` for more information on using these objects.
+.. warning::
+
+ The CObject API is deprecated as of Python 2.7. Please switch to the new
+ :ref:`capsules` API.
.. ctype:: PyCObject
Modified: python/trunk/Doc/c-api/concrete.rst
==============================================================================
--- python/trunk/Doc/c-api/concrete.rst (original)
+++ python/trunk/Doc/c-api/concrete.rst Thu Mar 25 01:54:54 2010
@@ -100,6 +100,7 @@
descriptor.rst
slice.rst
weakref.rst
+ capsule.rst
cobject.rst
cell.rst
gen.rst
Modified: python/trunk/Doc/data/refcounts.dat
==============================================================================
--- python/trunk/Doc/data/refcounts.dat (original)
+++ python/trunk/Doc/data/refcounts.dat Thu Mar 25 01:54:54 2010
@@ -55,6 +55,45 @@
PyBuffer_New:PyObject*::+1:
PyBuffer_New:int:size::
+PyCapsule_GetContext:void *:::
+PyCapsule_GetContext:PyObject*:self:0:
+
+PyCapsule_GetDestructor:void (*)(PyObject *):::
+PyCapsule_GetDestructor:PyObject*:self:0:
+
+PyCapsule_GetName:const char *:::
+PyCapsule_GetName:PyObject*:self:0:
+
+PyCapsule_GetPointer:void*:::
+PyCapsule_GetPointer:PyObject*:self:0:
+PyCapsule_GetPointer:const char *:name::
+
+PyCapsule_Import:void *:::
+PyCapsule_Import:const char *:name::
+PyCapsule_Import:int:no_block::
+
+PyCapsule_New:PyObject*::+1:
+PyCapsule_New:void*:pointer::
+PyCapsule_New:const char *:name::
+PyCapsule_New::void (* destructor)(PyObject* )::
+
+PyCapsule_SetContext:int:::
+PyCapsule_SetContext:PyObject*:self:0:
+PyCapsule_SetContext:void *:context::
+
+PyCapsule_SetDestructor:int:::
+PyCapsule_SetDestructor:PyObject*:self:0:
+PyCapsule_SetDestructor:void (*)(PyObject *):destructor::
+
+PyCapsule_SetName:int:::
+PyCapsule_SetName:PyObject*:self:0:
+PyCapsule_SetName:const char *:name::
+
+PyCapsule_SetPointer:int:::
+PyCapsule_SetPointer:PyObject*:self:0:
+PyCapsule_SetPointer:void*:pointer::
+
+
PyCObject_AsVoidPtr:void*:::
PyCObject_AsVoidPtr:PyObject*:self:0:
Modified: python/trunk/Doc/extending/extending.rst
==============================================================================
--- python/trunk/Doc/extending/extending.rst (original)
+++ python/trunk/Doc/extending/extending.rst Thu Mar 25 01:54:54 2010
@@ -1060,7 +1060,7 @@
define this symbol).
-.. _using-cobjects:
+.. _using-capsules:
Providing a C API for an Extension Module
=========================================
@@ -1096,23 +1096,40 @@
other extension modules must be exported in a different way.
Python provides a special mechanism to pass C-level information (pointers) from
-one extension module to another one: CObjects. A CObject is a Python data type
-which stores a pointer (:ctype:`void \*`). CObjects can only be created and
+one extension module to another one: Capsules. A Capsule is a Python data type
+which stores a pointer (:ctype:`void \*`). Capsules can only be created and
accessed via their C API, but they can be passed around like any other Python
object. In particular, they can be assigned to a name in an extension module's
namespace. Other extension modules can then import this module, retrieve the
-value of this name, and then retrieve the pointer from the CObject.
+value of this name, and then retrieve the pointer from the Capsule.
-There are many ways in which CObjects can be used to export the C API of an
-extension module. Each name could get its own CObject, or all C API pointers
-could be stored in an array whose address is published in a CObject. And the
+There are many ways in which Capsules can be used to export the C API of an
+extension module. Each function could get its own Capsule, or all C API pointers
+could be stored in an array whose address is published in a Capsule. And the
various tasks of storing and retrieving the pointers can be distributed in
different ways between the module providing the code and the client modules.
+Whichever method you choose, it's important to name your Capsules properly.
+The function :cfunc:`PyCapsule_New` takes a name parameter
+(:ctype:`const char \*`); you're permitted to pass in a *NULL* name, but
+we strongly encourage you to specify a name. Properly named Capsules provide
+a degree of runtime type-safety; there is no feasible way to tell one unnamed
+Capsule from another.
+
+In particular, Capsules used to expose C APIs should be given a name following
+this convention::
+
+ modulename.attributename
+
+The convenience function :cfunc:`PyCapsule_Import` makes it easy to
+load a C API provided via a Capsule, but only if the Capsule's name
+matches this convention. This behavior gives C API users a high degree
+of certainty that the Capsule they load contains the correct C API.
+
The following example demonstrates an approach that puts most of the burden on
the writer of the exporting module, which is appropriate for commonly used
library modules. It stores all C API pointers (just one in the example!) in an
-array of :ctype:`void` pointers which becomes the value of a CObject. The header
+array of :ctype:`void` pointers which becomes the value of a Capsule. The header
file corresponding to the module provides a macro that takes care of importing
the module and retrieving its C API pointers; client modules only have to call
this macro before accessing the C API.
@@ -1174,8 +1191,8 @@
/* Initialize the C API pointer array */
PySpam_API[PySpam_System_NUM] = (void *)PySpam_System;
- /* Create a CObject containing the API pointer array's address */
- c_api_object = PyCObject_FromVoidPtr((void *)PySpam_API, NULL);
+ /* Create a Capsule containing the API pointer array's address */
+ c_api_object = PyCapsule_New((void *)PySpam_API, "spam._C_API", NULL);
if (c_api_object != NULL)
PyModule_AddObject(m, "_C_API", c_api_object);
@@ -1217,28 +1234,14 @@
#define PySpam_System \
(*(PySpam_System_RETURN (*)PySpam_System_PROTO) PySpam_API[PySpam_System_NUM])
- /* Return -1 and set exception on error, 0 on success. */
+ /* Return -1 on error, 0 on success.
+ * PyCapsule_Import will set an exception if there's an error.
+ */
static int
import_spam(void)
{
- PyObject *c_api_object;
- PyObject *module;
-
- module = PyImport_ImportModule("spam");
- if (module == NULL)
- return -1;
-
- c_api_object = PyObject_GetAttrString(module, "_C_API");
- if (c_api_object == NULL) {
- Py_DECREF(module);
- return -1;
- }
- if (PyCObject_Check(c_api_object))
- PySpam_API = (void **)PyCObject_AsVoidPtr(c_api_object);
-
- Py_DECREF(c_api_object);
- Py_DECREF(module);
- return 0;
+ PySpam_API = (void **)PyCapsule_Import("spam._C_API", 0);
+ return (PySpam_API != NULL) ? 0 : -1;
}
#endif
@@ -1270,11 +1273,11 @@
rather complicated. However, the basic structure is the same for each function
that is exported, so it has to be learned only once.
-Finally it should be mentioned that CObjects offer additional functionality,
+Finally it should be mentioned that Capsules offer additional functionality,
which is especially useful for memory allocation and deallocation of the pointer
-stored in a CObject. The details are described in the Python/C API Reference
-Manual in the section :ref:`cobjects` and in the implementation of CObjects (files
-:file:`Include/cobject.h` and :file:`Objects/cobject.c` in the Python source
+stored in a Capsule. The details are described in the Python/C API Reference
+Manual in the section :ref:`capsules` and in the implementation of Capsules (files
+:file:`Include/pycapsule.h` and :file:`Objects/pycapsule.c` in the Python source
code distribution).
.. rubric:: Footnotes
Modified: python/trunk/Include/Python.h
==============================================================================
--- python/trunk/Include/Python.h (original)
+++ python/trunk/Include/Python.h Thu Mar 25 01:54:54 2010
@@ -107,6 +107,7 @@
#include "classobject.h"
#include "fileobject.h"
#include "cobject.h"
+#include "pycapsule.h"
#include "traceback.h"
#include "sliceobject.h"
#include "cellobject.h"
Modified: python/trunk/Include/cStringIO.h
==============================================================================
--- python/trunk/Include/cStringIO.h (original)
+++ python/trunk/Include/cStringIO.h Thu Mar 25 01:54:54 2010
@@ -18,9 +18,12 @@
This would typically be done in your init function.
*/
+
+#define PycStringIO_CAPSULE_NAME "cStringIO.cStringIO_CAPI"
+
#define PycString_IMPORT \
- PycStringIO = (struct PycStringIO_CAPI*)PyCObject_Import("cStringIO", \
- "cStringIO_CAPI")
+ PycStringIO = ((struct PycStringIO_CAPI*)PyCapsule_Import(\
+ PycStringIO_CAPSULE_NAME, 0))
/* Basic functions to manipulate cStringIO objects from C */
Modified: python/trunk/Include/cobject.h
==============================================================================
--- python/trunk/Include/cobject.h (original)
+++ python/trunk/Include/cobject.h Thu Mar 25 01:54:54 2010
@@ -6,6 +6,8 @@
to other extension modules, so that extension modules can use the
Python import mechanism to link to one another.
+ DEPRECATED - Use PyCapsule objects instead.
+ CObject will be removed in 2.8 (if there is one).
*/
#ifndef Py_COBJECT_H
Modified: python/trunk/Include/datetime.h
==============================================================================
--- python/trunk/Include/datetime.h (original)
+++ python/trunk/Include/datetime.h Thu Mar 25 01:54:54 2010
@@ -158,6 +158,8 @@
} PyDateTime_CAPI;
+#define PyDateTime_CAPSULE_NAME "datetime.datetime_CAPI"
+
/* "magic" constant used to partially protect against developer mistakes. */
#define DATETIME_API_MAGIC 0x414548d5
@@ -186,15 +188,7 @@
static PyDateTime_CAPI *PyDateTimeAPI = NULL;
#define PyDateTime_IMPORT \
- PyDateTimeAPI = (PyDateTime_CAPI*) PyCObject_Import("datetime", \
- "datetime_CAPI")
-
-/* This macro would be used if PyCObject_ImportEx() was created.
-#define PyDateTime_IMPORT \
- PyDateTimeAPI = (PyDateTime_CAPI*) PyCObject_ImportEx("datetime", \
- "datetime_CAPI", \
- DATETIME_API_MAGIC)
-*/
+ PyDateTimeAPI = (PyDateTime_CAPI *)PyCapsule_Import(PyDateTime_CAPSULE_NAME, 0)
/* Macros for type checking when not building the Python core. */
#define PyDate_Check(op) PyObject_TypeCheck(op, PyDateTimeAPI->DateType)
Modified: python/trunk/Include/py_curses.h
==============================================================================
--- python/trunk/Include/py_curses.h (original)
+++ python/trunk/Include/py_curses.h Thu Mar 25 01:54:54 2010
@@ -80,6 +80,9 @@
#define PyCursesWindow_Check(v) (Py_TYPE(v) == &PyCursesWindow_Type)
+#define PyCurses_CAPSULE_NAME "_curses._C_API"
+
+
#ifdef CURSES_MODULE
/* This section is used when compiling _cursesmodule.c */
@@ -94,16 +97,8 @@
#define PyCursesInitialisedColor {if (! ((int (*)(void))PyCurses_API[3]) () ) return NULL;}
#define import_curses() \
-{ \
- PyObject *module = PyImport_ImportModuleNoBlock("_curses"); \
- if (module != NULL) { \
- PyObject *module_dict = PyModule_GetDict(module); \
- PyObject *c_api_object = PyDict_GetItemString(module_dict, "_C_API"); \
- if (PyCObject_Check(c_api_object)) { \
- PyCurses_API = (void **)PyCObject_AsVoidPtr(c_api_object); \
- } \
- } \
-}
+ PyCurses_API = (void **)PyCapsule_Import(PyCurses_CAPSULE_NAME, 1);
+
#endif
/* general error messages */
Added: python/trunk/Include/pycapsule.h
==============================================================================
--- (empty file)
+++ python/trunk/Include/pycapsule.h Thu Mar 25 01:54:54 2010
@@ -0,0 +1,148 @@
+
+/* Capsule objects let you wrap a C "void *" pointer in a Python
+ object. They're a way of passing data through the Python interpreter
+ without creating your own custom type.
+
+ Capsules are used for communication between extension modules.
+ They provide a way for an extension module to export a C interface
+ to other extension modules, so that extension modules can use the
+ Python import mechanism to link to one another.
+
+ For more information, please see "c-api/capsule.html" in the
+ documentation.
+*/
+
+#ifndef Py_CAPSULE_H
+#define Py_CAPSULE_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+PyAPI_DATA(PyTypeObject) PyCapsule_Type;
+
+typedef void (*PyCapsule_Destructor)(PyObject *);
+
+#define PyCapsule_CheckExact(op) (Py_TYPE(op) == &PyCapsule_Type)
+
+
+PyAPI_FUNC(PyObject *) PyCapsule_New(
+ void *pointer,
+ const char *name,
+ PyCapsule_Destructor destructor);
+
+PyAPI_FUNC(void *) PyCapsule_GetPointer(PyObject *capsule, const char *name);
+
+PyAPI_FUNC(PyCapsule_Destructor) PyCapsule_GetDestructor(PyObject *capsule);
+
+PyAPI_FUNC(const char *) PyCapsule_GetName(PyObject *capsule);
+
+PyAPI_FUNC(void *) PyCapsule_GetContext(PyObject *capsule);
+
+PyAPI_FUNC(int) PyCapsule_IsValid(PyObject *capsule, const char *name);
+
+PyAPI_FUNC(int) PyCapsule_SetPointer(PyObject *capsule, void *pointer);
+
+PyAPI_FUNC(int) PyCapsule_SetDestructor(PyObject *capsule, PyCapsule_Destructor destructor);
+
+PyAPI_FUNC(int) PyCapsule_SetName(PyObject *capsule, const char *name);
+
+PyAPI_FUNC(int) PyCapsule_SetContext(PyObject *capsule, void *context);
+
+PyAPI_FUNC(void *) PyCapsule_Import(const char *name, int no_block);
+
+
+#define PYTHON_USING_CAPSULE
+
+#define PYCAPSULE_INSTANTIATE_DESTRUCTOR(name, destructor) \
+static void pycapsule_destructor_ ## name(PyObject *ptr) \
+{ \
+ void *p = PyCapsule_GetPointer(ptr, name); \
+ if (p) { \
+ destructor(p); \
+ } \
+} \
+
+#define PYCAPSULE_NEW(pointer, name) \
+ (PyCapsule_New(pointer, name, capsule_destructor_ ## name))
+
+#define PYCAPSULE_ISVALID(capsule, name) \
+ (PyCapsule_IsValid(capsule, name))
+
+#define PYCAPSULE_DEREFERENCE(capsule, name) \
+ (PyCapsule_GetPointer(capsule, name))
+
+#define PYCAPSULE_SET(capsule, name, value) \
+ (PyCapsule_IsValid(capsule, name) && PyCapsule_SetPointer(capsule, value))
+
+/* module and attribute should be specified as string constants */
+#define PYCAPSULE_IMPORT(module, attribute) \
+ (PyCapsule_Import(module "." attribute, 0))
+
+
+/* begin public-domain code */
+/*
+** This code was written by Larry Hastings,
+** and is dedicated to the public domain.
+** It's designed to make it easy to switch
+** from CObject to Capsule objects without losing
+** backwards compatibility with prior versions
+** of CPython. You're encouraged to copy this code
+** (including this documentation) into your
+** Python C extension.
+**
+** To use:
+** * #define a name for the pointer you store in
+** the CObject. If you make the CObject available
+** as part of your module's API, this name should
+** be "modulename.attributename", and it should be
+** considered part of your API (so put it in your
+** header file).
+** * Specify a PYCAPSULE_INSTANTIATE_DESTRUCTOR(), in
+** every C file that creates these CObjects. This
+** is where you specify your object's destructor.
+** * Change all calls to CObject_FromVoidPtr()
+** and CObject_FromVoidPointerAndDesc() into
+** PYCAPSULE_NEW() calls.
+** * Change all calls to PyCObject_AsVoidPtr()
+** into PYCAPSULE_DEREFERENCE() calls.
+** * Change all calls to PyCObject_SetVoidPtr()
+** into PYCAPSULE_SET() calls.
+** * Change all calls to PyCObject_Import()
+** into PYCAPSULE_IMPORT() calls. Note that
+** the two arguments to PYCAPSULE_IMPORT()
+** should both be string constants; that is,
+** you should call
+** PYCAPSULE_IMPORT("modulename", "attributename"),
+** not PYCAPSULE_IMPORT(charstar1, charstar2).
+*/
+#ifndef PYTHON_USING_CAPSULE
+
+#define PYCAPSULE_INSTANTIATE_DESTRUCTOR(name, destructor) \
+static void pycapsule_destructor_ ## name(void *ptr) \
+{ \
+ destructor(p); \
+} \
+
+#define PYCAPSULE_NEW(pointer, name) \
+ (PyCObject_FromVoidPtr(pointer, pycapsule_destructor_ ## name))
+
+#define PYCAPSULE_ISVALID(capsule, name) \
+ (PyCObject_Check(capsule))
+
+#define PYCAPSULE_DEREFERENCE(capsule, name) \
+ (PyCObject_AsVoidPtr(capsule))
+
+#define PYCAPSULE_SET(capsule, name, value) \
+ (PyCObject_SetVoidPtr(capsule, value))
+
+/* module and attribute should be specified as string constants */
+#define PYCAPSULE_IMPORT(module, attribute) \
+ (PyCObject_Import(module, attribute))
+
+#endif /* PYTHON_USING_CAPSULE */
+/* end public-domain code */
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_CAPSULE_H */
Modified: python/trunk/Include/pyexpat.h
==============================================================================
--- python/trunk/Include/pyexpat.h (original)
+++ python/trunk/Include/pyexpat.h Thu Mar 25 01:54:54 2010
@@ -4,6 +4,7 @@
/* note: you must import expat.h before importing this module! */
#define PyExpat_CAPI_MAGIC "pyexpat.expat_CAPI 1.0"
+#define PyExpat_CAPSULE_NAME "pyexpat.expat_CAPI"
struct PyExpat_CAPI
{
Modified: python/trunk/Include/ucnhash.h
==============================================================================
--- python/trunk/Include/ucnhash.h (original)
+++ python/trunk/Include/ucnhash.h Thu Mar 25 01:54:54 2010
@@ -6,7 +6,9 @@
extern "C" {
#endif
-/* revised ucnhash CAPI interface (exported through a PyCObject) */
+/* revised ucnhash CAPI interface (exported through a "wrapper") */
+
+#define PyUnicodeData_CAPSULE_NAME "unicodedata.ucnhash_CAPI"
typedef struct {
Modified: python/trunk/Lib/test/test_sys.py
==============================================================================
--- python/trunk/Lib/test/test_sys.py (original)
+++ python/trunk/Lib/test/test_sys.py Thu Mar 25 01:54:54 2010
@@ -670,6 +670,7 @@
x = property(getx, setx, delx, "")
check(x, size(h + '4Pi'))
# PyCObject
+ # PyCapsule
# XXX
# rangeiterator
check(iter(xrange(1)), size(h + '4l'))
Modified: python/trunk/Makefile.pre.in
==============================================================================
--- python/trunk/Makefile.pre.in (original)
+++ python/trunk/Makefile.pre.in Thu Mar 25 01:54:54 2010
@@ -309,6 +309,7 @@
Objects/bufferobject.o \
Objects/bytes_methods.o \
Objects/bytearrayobject.o \
+ Objects/capsule.o \
Objects/cellobject.o \
Objects/classobject.o \
Objects/cobject.o \
@@ -642,6 +643,7 @@
Include/pgen.h \
Include/pgenheaders.h \
Include/pyarena.h \
+ Include/pycapsule.h \
Include/pyctype.h \
Include/pydebug.h \
Include/pyerrors.h \
Modified: python/trunk/Misc/NEWS
==============================================================================
--- python/trunk/Misc/NEWS (original)
+++ python/trunk/Misc/NEWS Thu Mar 25 01:54:54 2010
@@ -138,6 +138,12 @@
- Issue #7705: Fix linking on FreeBSD.
+C-API
+-----
+
+- Issue #7992: A replacement PyCObject API, PyCapsule, has been backported
+ from Python 3.1.
+
Tests
-----
Modified: python/trunk/Modules/_ctypes/callproc.c
==============================================================================
--- python/trunk/Modules/_ctypes/callproc.c (original)
+++ python/trunk/Modules/_ctypes/callproc.c Thu Mar 25 01:54:54 2010
@@ -83,6 +83,13 @@
#define DONT_USE_SEH
#endif
+
+#define CTYPES_CAPSULE_ERROROBJ "_ctypes/callproc.c error object"
+CTYPES_CAPSULE_INSTANTIATE_DESTRUCTOR(CTYPES_CAPSULE_ERROROBJ)
+
+#define CTYPES_CAPSULE_WCHAR_T "_ctypes/callproc.c wchar_t buffer from unicode"
+CTYPES_CAPSULE_INSTANTIATE_DESTRUCTOR(CTYPES_CAPSULE_WCHAR_T)
+
/*
ctypes maintains thread-local storage that has space for two error numbers:
private copies of the system 'errno' value and, on Windows, the system error code
@@ -134,14 +141,22 @@
return NULL;
}
errobj = PyDict_GetItem(dict, error_object_name);
- if (errobj)
+ if (errobj) {
+#ifdef CTYPES_USING_CAPSULE
+ if (!PyCapsule_IsValid(errobj, CTYPES_CAPSULE_ERROROBJ)) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "ctypes.error_object is an invalid capsule");
+ return NULL;
+ }
+#endif /* CTYPES_USING_CAPSULE */
Py_INCREF(errobj);
+ }
else {
void *space = PyMem_Malloc(sizeof(int) * 2);
if (space == NULL)
return NULL;
memset(space, 0, sizeof(int) * 2);
- errobj = PyCObject_FromVoidPtr(space, PyMem_Free);
+ errobj = CAPSULE_NEW(space, CTYPES_CAPSULE_ERROROBJ);
if (errobj == NULL)
return NULL;
if (-1 == PyDict_SetItem(dict, error_object_name,
@@ -150,7 +165,7 @@
return NULL;
}
}
- *pspace = (int *)PyCObject_AsVoidPtr(errobj);
+ *pspace = (int *)CAPSULE_DEREFERENCE(errobj, CTYPES_CAPSULE_ERROROBJ);
return errobj;
}
@@ -670,7 +685,7 @@
return -1;
}
memset(pa->value.p, 0, size);
- pa->keep = PyCObject_FromVoidPtr(pa->value.p, PyMem_Free);
+ pa->keep = CAPSULE_NEW(pa->value.p, CTYPES_CAPSULE_WCHAR_T);
if (!pa->keep) {
PyMem_Free(pa->value.p);
return -1;
Modified: python/trunk/Modules/_ctypes/cfield.c
==============================================================================
--- python/trunk/Modules/_ctypes/cfield.c (original)
+++ python/trunk/Modules/_ctypes/cfield.c Thu Mar 25 01:54:54 2010
@@ -10,6 +10,11 @@
#endif
#include "ctypes.h"
+
+#define CTYPES_CAPSULE_WCHAR_T "_ctypes/cfield.c wchar_t buffer from unicode"
+CTYPES_CAPSULE_INSTANTIATE_DESTRUCTOR(CTYPES_CAPSULE_WCHAR_T)
+
+
/******************************************************************/
/*
PyCField_Type
@@ -1457,7 +1462,7 @@
return PyErr_NoMemory();
}
memset(buffer, 0, size);
- keep = PyCObject_FromVoidPtr(buffer, PyMem_Free);
+ keep = CAPSULE_NEW(buffer, CTYPES_CAPSULE_WCHAR_T);
if (!keep) {
Py_DECREF(value);
PyMem_Free(buffer);
Modified: python/trunk/Modules/_ctypes/ctypes.h
==============================================================================
--- python/trunk/Modules/_ctypes/ctypes.h (original)
+++ python/trunk/Modules/_ctypes/ctypes.h Thu Mar 25 01:54:54 2010
@@ -445,6 +445,40 @@
extern PyObject *ComError;
#endif
+#if PY_VERSION_HEX >= 0x020700A4
+/* Use PyCapsule for 2.7 */
+
+#define CTYPES_USING_CAPSULE
+
+#define CTYPES_CAPSULE_INSTANTIATE_DESTRUCTOR(name) \
+static void capsule_destructor_ ## name(PyObject *ptr) \
+{ \
+ void *p = PyCapsule_GetPointer(ptr, name); \
+ if (p) { \
+ PyMem_Free(p); \
+ } \
+} \
+
+#define CAPSULE_NEW(pointer, name) \
+ (PyCapsule_New(pointer, name, capsule_destructor_ ## name))
+
+#define CAPSULE_DEREFERENCE(capsule, name) \
+ (PyCapsule_GetPointer(capsule, name))
+
+#else /* PY_VERSION_HEX >= 0x020700A4 */
+/* Use CObject for 2.6 and before */
+
+#define CTYPES_CAPSULE_INSTANTIATE_DESTRUCTOR(name)
+
+#define CAPSULE_NEW(pointer, name) \
+ (PyCObject_FromVoidPtr(pointer, PyMem_Free))
+
+#define CAPSULE_DEREFERENCE(capsule, name) \
+ (PyCObject_AsVoidPtr(capsule))
+
+#endif /* PY_VERSION_HEX >= 0x020700A4 */
+
+
/*
Local Variables:
compile-command: "python setup.py -q build install --home ~"
Modified: python/trunk/Modules/_cursesmodule.c
==============================================================================
--- python/trunk/Modules/_cursesmodule.c (original)
+++ python/trunk/Modules/_cursesmodule.c Thu Mar 25 01:54:54 2010
@@ -172,7 +172,7 @@
/*
* Check the return code from a curses function and return None
* or raise an exception as appropriate. These are exported using the
- * CObject API.
+ * capsule API.
*/
static PyObject *
@@ -2745,8 +2745,8 @@
return;
ModDict = d; /* For PyCurses_InitScr to use later */
- /* Add a CObject for the C API */
- c_api_object = PyCObject_FromVoidPtr((void *)PyCurses_API, NULL);
+ /* Add a capsule for the C API */
+ c_api_object = PyCapsule_New(PyCurses_API, PyCurses_CAPSULE_NAME, NULL);
PyDict_SetItemString(d, "_C_API", c_api_object);
Py_DECREF(c_api_object);
Modified: python/trunk/Modules/_elementtree.c
==============================================================================
--- python/trunk/Modules/_elementtree.c (original)
+++ python/trunk/Modules/_elementtree.c Thu Mar 25 01:54:54 2010
@@ -3059,7 +3059,7 @@
#if defined(USE_PYEXPAT_CAPI)
/* link against pyexpat, if possible */
- expat_capi = PyCObject_Import("pyexpat", "expat_CAPI");
+ expat_capi = PyCapsule_Import(PyExpat_CAPSULE_NAME, 0);
if (expat_capi) {
/* check that it's usable */
if (strcmp(expat_capi->magic, PyExpat_CAPI_MAGIC) != 0 ||
Modified: python/trunk/Modules/_testcapimodule.c
==============================================================================
--- python/trunk/Modules/_testcapimodule.c (original)
+++ python/trunk/Modules/_testcapimodule.c Thu Mar 25 01:54:54 2010
@@ -1428,6 +1428,157 @@
#undef CHECK_1_FORMAT
}
+/* Coverage testing of capsule objects. */
+
+static const char *capsule_name = "capsule name";
+static char *capsule_pointer = "capsule pointer";
+static char *capsule_context = "capsule context";
+static const char *capsule_error = NULL;
+static int
+capsule_destructor_call_count = 0;
+
+static void
+capsule_destructor(PyObject *o) {
+ capsule_destructor_call_count++;
+ if (PyCapsule_GetContext(o) != capsule_context) {
+ capsule_error = "context did not match in destructor!";
+ } else if (PyCapsule_GetDestructor(o) != capsule_destructor) {
+ capsule_error = "destructor did not match in destructor! (woah!)";
+ } else if (PyCapsule_GetName(o) != capsule_name) {
+ capsule_error = "name did not match in destructor!";
+ } else if (PyCapsule_GetPointer(o, capsule_name) != capsule_pointer) {
+ capsule_error = "pointer did not match in destructor!";
+ }
+}
+
+typedef struct {
+ char *name;
+ char *module;
+ char *attribute;
+} known_capsule;
+
+static PyObject *
+test_capsule(PyObject *self, PyObject *args)
+{
+ PyObject *object;
+ const char *error = NULL;
+ void *pointer;
+ void *pointer2;
+ known_capsule known_capsules[] = {
+ #define KNOWN_CAPSULE(module, name) { module "." name, module, name }
+ KNOWN_CAPSULE("_socket", "CAPI"),
+ KNOWN_CAPSULE("_curses", "_C_API"),
+ KNOWN_CAPSULE("datetime", "datetime_CAPI"),
+ { NULL, NULL },
+ };
+ known_capsule *known = &known_capsules[0];
+
+#define FAIL(x) { error = (x); goto exit; }
+
+#define CHECK_DESTRUCTOR \
+ if (capsule_error) { \
+ FAIL(capsule_error); \
+ } \
+ else if (!capsule_destructor_call_count) { \
+ FAIL("destructor not called!"); \
+ } \
+ capsule_destructor_call_count = 0; \
+
+ object = PyCapsule_New(capsule_pointer, capsule_name, capsule_destructor);
+ PyCapsule_SetContext(object, capsule_context);
+ capsule_destructor(object);
+ CHECK_DESTRUCTOR;
+ Py_DECREF(object);
+ CHECK_DESTRUCTOR;
+
+ object = PyCapsule_New(known, "ignored", NULL);
+ PyCapsule_SetPointer(object, capsule_pointer);
+ PyCapsule_SetName(object, capsule_name);
+ PyCapsule_SetDestructor(object, capsule_destructor);
+ PyCapsule_SetContext(object, capsule_context);
+ capsule_destructor(object);
+ CHECK_DESTRUCTOR;
+ /* intentionally access using the wrong name */
+ pointer2 = PyCapsule_GetPointer(object, "the wrong name");
+ if (!PyErr_Occurred()) {
+ FAIL("PyCapsule_GetPointer should have failed but did not!");
+ }
+ PyErr_Clear();
+ if (pointer2) {
+ if (pointer2 == capsule_pointer) {
+ FAIL("PyCapsule_GetPointer should not have"
+ " returned the internal pointer!");
+ } else {
+ FAIL("PyCapsule_GetPointer should have "
+ "returned NULL pointer but did not!");
+ }
+ }
+ PyCapsule_SetDestructor(object, NULL);
+ Py_DECREF(object);
+ if (capsule_destructor_call_count) {
+ FAIL("destructor called when it should not have been!");
+ }
+
+ for (known = &known_capsules[0]; known->module != NULL; known++) {
+ /* yeah, ordinarily I wouldn't do this either,
+ but it's fine for this test harness.
+ */
+ static char buffer[256];
+#undef FAIL
+#define FAIL(x) \
+ { \
+ sprintf(buffer, "%s module: \"%s\" attribute: \"%s\"", \
+ x, known->module, known->attribute); \
+ error = buffer; \
+ goto exit; \
+ } \
+
+ PyObject *module = PyImport_ImportModule(known->module);
+ if (module) {
+ pointer = PyCapsule_Import(known->name, 0);
+ if (!pointer) {
+ Py_DECREF(module);
+ FAIL("PyCapsule_GetPointer returned NULL unexpectedly!");
+ }
+ object = PyObject_GetAttrString(module, known->attribute);
+ if (!object) {
+ Py_DECREF(module);
+ return NULL;
+ }
+ pointer2 = PyCapsule_GetPointer(object,
+ "weebles wobble but they don't fall down");
+ if (!PyErr_Occurred()) {
+ Py_DECREF(object);
+ Py_DECREF(module);
+ FAIL("PyCapsule_GetPointer should have failed but did not!");
+ }
+ PyErr_Clear();
+ if (pointer2) {
+ Py_DECREF(module);
+ Py_DECREF(object);
+ if (pointer2 == pointer) {
+ FAIL("PyCapsule_GetPointer should not have"
+ " returned its internal pointer!");
+ } else {
+ FAIL("PyCapsule_GetPointer should have"
+ " returned NULL pointer but did not!");
+ }
+ }
+ Py_DECREF(object);
+ Py_DECREF(module);
+ }
+ else
+ PyErr_Clear();
+ }
+
+ exit:
+ if (error) {
+ return raiseTestError("test_capsule", error);
+ }
+ Py_RETURN_NONE;
+#undef FAIL
+}
+
/* This is here to provide a docstring for test_descr. */
static PyObject *
test_with_docstring(PyObject *self)
@@ -1539,6 +1690,7 @@
{"_test_thread_state", test_thread_state, METH_VARARGS},
{"_pending_threadfunc", pending_threadfunc, METH_VARARGS},
#endif
+ {"test_capsule", (PyCFunction)test_capsule, METH_NOARGS},
{"traceback_print", traceback_print, METH_VARARGS},
{"code_newempty", code_newempty, METH_VARARGS},
{"make_exception_with_doc", (PyCFunction)make_exception_with_doc,
Modified: python/trunk/Modules/cStringIO.c
==============================================================================
--- python/trunk/Modules/cStringIO.c (original)
+++ python/trunk/Modules/cStringIO.c Thu Mar 25 01:54:54 2010
@@ -761,8 +761,8 @@
Py_TYPE(&Otype)=&PyType_Type;
if (PyType_Ready(&Otype) < 0) return;
if (PyType_Ready(&Itype) < 0) return;
- PyDict_SetItemString(d,"cStringIO_CAPI",
- v = PyCObject_FromVoidPtr(&CAPI,NULL));
+ v = PyCapsule_New(&CAPI, PycStringIO_CAPSULE_NAME, NULL);
+ PyDict_SetItemString(d,"cStringIO_CAPI", v);
Py_XDECREF(v);
/* Export Types */
Modified: python/trunk/Modules/cjkcodecs/cjkcodecs.h
==============================================================================
--- python/trunk/Modules/cjkcodecs/cjkcodecs.h (original)
+++ python/trunk/Modules/cjkcodecs/cjkcodecs.h Thu Mar 25 01:54:54 2010
@@ -282,7 +282,7 @@
return NULL;
}
- codecobj = PyCObject_FromVoidPtr((void *)codec, NULL);
+ codecobj = PyCapsule_New((void *)codec, PyMultibyteCodec_CAPSULE_NAME, NULL);
if (codecobj == NULL)
return NULL;
@@ -307,7 +307,7 @@
int r;
strcpy(mhname + sizeof("__map_") - 1, h->charset);
r = PyModule_AddObject(module, mhname,
- PyCObject_FromVoidPtr((void *)h, NULL));
+ PyCapsule_New((void *)h, PyMultibyteCodec_CAPSULE_NAME, NULL));
if (r == -1)
return -1;
}
@@ -362,14 +362,14 @@
o = PyObject_GetAttrString(mod, (char*)symbol);
if (o == NULL)
goto errorexit;
- else if (!PyCObject_Check(o)) {
+ else if (!PyCapsule_IsValid(o, PyMultibyteCodec_CAPSULE_NAME)) {
PyErr_SetString(PyExc_ValueError,
- "map data must be a CObject.");
+ "map data must be a Capsule.");
goto errorexit;
}
else {
struct dbcs_map *map;
- map = PyCObject_AsVoidPtr(o);
+ map = PyCapsule_GetPointer(o, PyMultibyteCodec_CAPSULE_NAME);
if (encmap != NULL)
*encmap = map->encmap;
if (decmap != NULL)
Modified: python/trunk/Modules/cjkcodecs/multibytecodec.c
==============================================================================
--- python/trunk/Modules/cjkcodecs/multibytecodec.c (original)
+++ python/trunk/Modules/cjkcodecs/multibytecodec.c Thu Mar 25 01:54:54 2010
@@ -1774,12 +1774,12 @@
MultibyteCodecObject *self;
MultibyteCodec *codec;
- if (!PyCObject_Check(arg)) {
+ if (!PyCapsule_IsValid(arg, PyMultibyteCodec_CAPSULE_NAME)) {
PyErr_SetString(PyExc_ValueError, "argument type invalid");
return NULL;
}
- codec = PyCObject_AsVoidPtr(arg);
+ codec = PyCapsule_GetPointer(arg, PyMultibyteCodec_CAPSULE_NAME);
if (codec->codecinit != NULL && codec->codecinit(codec->config) != 0)
return NULL;
Modified: python/trunk/Modules/cjkcodecs/multibytecodec.h
==============================================================================
--- python/trunk/Modules/cjkcodecs/multibytecodec.h (original)
+++ python/trunk/Modules/cjkcodecs/multibytecodec.h Thu Mar 25 01:54:54 2010
@@ -132,6 +132,9 @@
#define MBENC_FLUSH 0x0001 /* encode all characters encodable */
#define MBENC_MAX MBENC_FLUSH
+#define PyMultibyteCodec_CAPSULE_NAME "multibytecodec.__map_*"
+
+
#ifdef __cplusplus
}
#endif
Modified: python/trunk/Modules/datetimemodule.c
==============================================================================
--- python/trunk/Modules/datetimemodule.c (original)
+++ python/trunk/Modules/datetimemodule.c Thu Mar 25 01:54:54 2010
@@ -4856,11 +4856,10 @@
Py_INCREF(&PyDateTime_TZInfoType);
PyModule_AddObject(m, "tzinfo", (PyObject *) &PyDateTime_TZInfoType);
- x = PyCObject_FromVoidPtrAndDesc(&CAPI, (void*) DATETIME_API_MAGIC,
- NULL);
- if (x == NULL)
- return;
- PyModule_AddObject(m, "datetime_CAPI", x);
+ x = PyCapsule_New(&CAPI, PyDateTime_CAPSULE_NAME, NULL);
+ if (x == NULL)
+ return NULL;
+ PyModule_AddObject(m, "datetime_CAPI", x);
/* A 4-year cycle has an extra leap day over what we'd get from
* pasting together 4 single years.
Modified: python/trunk/Modules/pyexpat.c
==============================================================================
--- python/trunk/Modules/pyexpat.c (original)
+++ python/trunk/Modules/pyexpat.c Thu Mar 25 01:54:54 2010
@@ -2053,8 +2053,8 @@
capi.SetUnknownEncodingHandler = XML_SetUnknownEncodingHandler;
capi.SetUserData = XML_SetUserData;
- /* export as cobject */
- capi_object = PyCObject_FromVoidPtr(&capi, NULL);
+ /* export using capsule */
+ capi_object = PyCapsule_New(&capi, PyExpat_CAPSULE_NAME, NULL);
if (capi_object)
PyModule_AddObject(m, "expat_CAPI", capi_object);
}
Modified: python/trunk/Modules/socketmodule.c
==============================================================================
--- python/trunk/Modules/socketmodule.c (original)
+++ python/trunk/Modules/socketmodule.c Thu Mar 25 01:54:54 2010
@@ -4496,7 +4496,7 @@
/* Export C API */
if (PyModule_AddObject(m, PySocket_CAPI_NAME,
- PyCObject_FromVoidPtr((void *)&PySocketModuleAPI, NULL)
+ PyCapsule_New(&PySocketModuleAPI, PySocket_CAPSULE_NAME, NULL)
) != 0)
return;
Modified: python/trunk/Modules/socketmodule.h
==============================================================================
--- python/trunk/Modules/socketmodule.h (original)
+++ python/trunk/Modules/socketmodule.h Thu Mar 25 01:54:54 2010
@@ -78,6 +78,7 @@
/* Python module and C API name */
#define PySocket_MODULE_NAME "_socket"
#define PySocket_CAPI_NAME "CAPI"
+#define PySocket_CAPSULE_NAME (PySocket_MODULE_NAME "." PySocket_CAPI_NAME)
/* Abstract the socket file descriptor type */
#ifdef MS_WINDOWS
@@ -142,12 +143,12 @@
the _socket module. Since cross-DLL linking introduces a lot of
problems on many platforms, the "trick" is to wrap the
C API of a module in a struct which then gets exported to
- other modules via a PyCObject.
+ other modules via a PyCapsule.
The code in socketmodule.c defines this struct (which currently
only contains the type object reference, but could very
well also include other C APIs needed by other modules)
- and exports it as PyCObject via the module dictionary
+ and exports it as PyCapsule via the module dictionary
under the name "CAPI".
Other modules can now include the socketmodule.h file
@@ -226,33 +227,18 @@
static
int PySocketModule_ImportModuleAndAPI(void)
{
- PyObject *mod = 0, *v = 0;
- char *apimodule = PySocket_MODULE_NAME;
- char *apiname = PySocket_CAPI_NAME;
void *api;
- DPRINTF("Importing the %s C API...\n", apimodule);
- mod = PyImport_ImportModuleNoBlock(apimodule);
- if (mod == NULL)
- goto onError;
- DPRINTF(" %s package found\n", apimodule);
- v = PyObject_GetAttrString(mod, apiname);
- if (v == NULL)
- goto onError;
- Py_DECREF(mod);
- DPRINTF(" API object %s found\n", apiname);
- api = PyCObject_AsVoidPtr(v);
+ DPRINTF(" Loading capsule %s\n", PySocket_CAPSULE_NAME);
+ api = PyCapsule_Import(PySocket_CAPSULE_NAME, 1);
if (api == NULL)
goto onError;
- Py_DECREF(v);
memcpy(&PySocketModule, api, sizeof(PySocketModule));
DPRINTF(" API object loaded and initialized.\n");
return 0;
onError:
DPRINTF(" not found.\n");
- Py_XDECREF(mod);
- Py_XDECREF(v);
return -1;
}
Modified: python/trunk/Modules/unicodedata.c
==============================================================================
--- python/trunk/Modules/unicodedata.c (original)
+++ python/trunk/Modules/unicodedata.c Thu Mar 25 01:54:54 2010
@@ -1261,7 +1261,7 @@
PyModule_AddObject(m, "ucd_3_2_0", v);
/* Export C API */
- v = PyCObject_FromVoidPtr((void *) &hashAPI, NULL);
+ v = PyCapsule_New((void *)&hashAPI, PyUnicodeData_CAPSULE_NAME, NULL);
if (v != NULL)
PyModule_AddObject(m, "ucnhash_CAPI", v);
}
Added: python/trunk/Objects/capsule.c
==============================================================================
--- (empty file)
+++ python/trunk/Objects/capsule.c Thu Mar 25 01:54:54 2010
@@ -0,0 +1,324 @@
+/* Wrap void * pointers to be passed between C modules */
+
+#include "Python.h"
+
+/* Internal structure of PyCapsule */
+typedef struct {
+ PyObject_HEAD
+ void *pointer;
+ const char *name;
+ void *context;
+ PyCapsule_Destructor destructor;
+} PyCapsule;
+
+
+
+static int
+_is_legal_capsule(PyCapsule *capsule, const char *invalid_capsule)
+{
+ if (!capsule || !PyCapsule_CheckExact(capsule) || capsule->pointer == NULL) {
+ PyErr_SetString(PyExc_ValueError, invalid_capsule);
+ return 0;
+ }
+ return 1;
+}
+
+#define is_legal_capsule(capsule, name) \
+ (_is_legal_capsule(capsule, \
+ name " called with invalid PyCapsule object"))
+
+
+static int
+name_matches(const char *name1, const char *name2) {
+ /* if either is NULL, */
+ if (!name1 || !name2) {
+ /* they're only the same if they're both NULL. */
+ return name1 == name2;
+ }
+ return !strcmp(name1, name2);
+}
+
+
+
+PyObject *
+PyCapsule_New(void *pointer, const char *name, PyCapsule_Destructor destructor)
+{
+ PyCapsule *capsule;
+
+ if (!pointer) {
+ PyErr_SetString(PyExc_ValueError, "PyCapsule_New called with null pointer");
+ return NULL;
+ }
+
+ capsule = PyObject_NEW(PyCapsule, &PyCapsule_Type);
+ if (capsule == NULL) {
+ return NULL;
+ }
+
+ capsule->pointer = pointer;
+ capsule->name = name;
+ capsule->context = NULL;
+ capsule->destructor = destructor;
+
+ return (PyObject *)capsule;
+}
+
+
+int
+PyCapsule_IsValid(PyObject *o, const char *name)
+{
+ PyCapsule *capsule = (PyCapsule *)o;
+
+ return (capsule != NULL &&
+ PyCapsule_CheckExact(capsule) &&
+ capsule->pointer != NULL &&
+ name_matches(capsule->name, name));
+}
+
+
+void *
+PyCapsule_GetPointer(PyObject *o, const char *name)
+{
+ PyCapsule *capsule = (PyCapsule *)o;
+
+ if (!is_legal_capsule(capsule, "PyCapsule_GetPointer")) {
+ return NULL;
+ }
+
+ if (!name_matches(name, capsule->name)) {
+ PyErr_SetString(PyExc_ValueError, "PyCapsule_GetPointer called with incorrect name");
+ return NULL;
+ }
+
+ return capsule->pointer;
+}
+
+
+const char *
+PyCapsule_GetName(PyObject *o)
+{
+ PyCapsule *capsule = (PyCapsule *)o;
+
+ if (!is_legal_capsule(capsule, "PyCapsule_GetName")) {
+ return NULL;
+ }
+ return capsule->name;
+}
+
+
+PyCapsule_Destructor
+PyCapsule_GetDestructor(PyObject *o)
+{
+ PyCapsule *capsule = (PyCapsule *)o;
+
+ if (!is_legal_capsule(capsule, "PyCapsule_GetDestructor")) {
+ return NULL;
+ }
+ return capsule->destructor;
+}
+
+
+void *
+PyCapsule_GetContext(PyObject *o)
+{
+ PyCapsule *capsule = (PyCapsule *)o;
+
+ if (!is_legal_capsule(capsule, "PyCapsule_GetContext")) {
+ return NULL;
+ }
+ return capsule->context;
+}
+
+
+int
+PyCapsule_SetPointer(PyObject *o, void *pointer)
+{
+ PyCapsule *capsule = (PyCapsule *)o;
+
+ if (!pointer) {
+ PyErr_SetString(PyExc_ValueError, "PyCapsule_SetPointer called with null pointer");
+ return -1;
+ }
+
+ if (!is_legal_capsule(capsule, "PyCapsule_SetPointer")) {
+ return -1;
+ }
+
+ capsule->pointer = pointer;
+ return 0;
+}
+
+
+int
+PyCapsule_SetName(PyObject *o, const char *name)
+{
+ PyCapsule *capsule = (PyCapsule *)o;
+
+ if (!is_legal_capsule(capsule, "PyCapsule_SetName")) {
+ return -1;
+ }
+
+ capsule->name = name;
+ return 0;
+}
+
+
+int
+PyCapsule_SetDestructor(PyObject *o, PyCapsule_Destructor destructor)
+{
+ PyCapsule *capsule = (PyCapsule *)o;
+
+ if (!is_legal_capsule(capsule, "PyCapsule_SetDestructor")) {
+ return -1;
+ }
+
+ capsule->destructor = destructor;
+ return 0;
+}
+
+
+int
+PyCapsule_SetContext(PyObject *o, void *context)
+{
+ PyCapsule *capsule = (PyCapsule *)o;
+
+ if (!is_legal_capsule(capsule, "PyCapsule_SetContext")) {
+ return -1;
+ }
+
+ capsule->context = context;
+ return 0;
+}
+
+
+void *
+PyCapsule_Import(const char *name, int no_block)
+{
+ PyObject *object = NULL;
+ void *return_value = NULL;
+ char *trace;
+ size_t name_length = (strlen(name) + 1) * sizeof(char);
+ char *name_dup = (char *)PyMem_MALLOC(name_length);
+
+ if (!name_dup) {
+ return NULL;
+ }
+
+ memcpy(name_dup, name, name_length);
+
+ trace = name_dup;
+ while (trace) {
+ char *dot = strchr(trace, '.');
+ if (dot) {
+ *dot++ = '\0';
+ }
+
+ if (object == NULL) {
+ if (no_block) {
+ object = PyImport_ImportModuleNoBlock(trace);
+ } else {
+ object = PyImport_ImportModule(trace);
+ if (!object) {
+ PyErr_Format(PyExc_ImportError, "PyCapsule_Import could not import module \"%s\"", trace);
+ }
+ }
+ } else {
+ PyObject *object2 = PyObject_GetAttrString(object, trace);
+ Py_DECREF(object);
+ object = object2;
+ }
+ if (!object) {
+ goto EXIT;
+ }
+
+ trace = dot;
+ }
+
+ /* compare attribute name to module.name by hand */
+ if (PyCapsule_IsValid(object, name)) {
+ PyCapsule *capsule = (PyCapsule *)object;
+ return_value = capsule->pointer;
+ } else {
+ PyErr_Format(PyExc_AttributeError,
+ "PyCapsule_Import \"%s\" is not valid",
+ name);
+ }
+
+EXIT:
+ Py_XDECREF(object);
+ if (name_dup) {
+ PyMem_FREE(name_dup);
+ }
+ return return_value;
+}
+
+
+static void
+capsule_dealloc(PyObject *o)
+{
+ PyCapsule *capsule = (PyCapsule *)o;
+ if (capsule->destructor) {
+ capsule->destructor(o);
+ }
+ PyObject_DEL(o);
+}
+
+
+static PyObject *
+capsule_repr(PyObject *o)
+{
+ PyCapsule *capsule = (PyCapsule *)o;
+ const char *name;
+ const char *quote;
+
+ if (capsule->name) {
+ quote = "\"";
+ name = capsule->name;
+ } else {
+ quote = "";
+ name = "NULL";
+ }
+
+ return PyString_FromFormat("<capsule object %s%s%s at %p>",
+ quote, name, quote, capsule);
+}
+
+
+
+PyDoc_STRVAR(PyCapsule_Type__doc__,
+"Capsule objects let you wrap a C \"void *\" pointer in a Python\n\
+object. They're a way of passing data through the Python interpreter\n\
+without creating your own custom type.\n\
+\n\
+Capsules are used for communication between extension modules.\n\
+They provide a way for an extension module to export a C interface\n\
+to other extension modules, so that extension modules can use the\n\
+Python import mechanism to link to one another.\n\
+");
+
+PyTypeObject PyCapsule_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "PyCapsule", /*tp_name*/
+ sizeof(PyCapsule), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ capsule_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_reserved*/
+ capsule_repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash*/
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ 0, /*tp_flags*/
+ PyCapsule_Type__doc__ /*tp_doc*/
+};
+
+
Modified: python/trunk/Objects/object.c
==============================================================================
--- python/trunk/Objects/object.c (original)
+++ python/trunk/Objects/object.c Thu Mar 25 01:54:54 2010
@@ -2269,6 +2269,10 @@
#endif
+/* Hack to force loading of capsule.o */
+PyTypeObject *_Py_capsule_hack = &PyCapsule_Type;
+
+
/* Hack to force loading of cobject.o */
PyTypeObject *_Py_cobject_hack = &PyCObject_Type;
Modified: python/trunk/Objects/unicodeobject.c
==============================================================================
--- python/trunk/Objects/unicodeobject.c (original)
+++ python/trunk/Objects/unicodeobject.c Thu Mar 25 01:54:54 2010
@@ -2889,16 +2889,7 @@
message = "malformed \\N character escape";
if (ucnhash_CAPI == NULL) {
/* load the unicode data module */
- PyObject *m, *api;
- m = PyImport_ImportModuleNoBlock("unicodedata");
- if (m == NULL)
- goto ucnhashError;
- api = PyObject_GetAttrString(m, "ucnhash_CAPI");
- Py_DECREF(m);
- if (api == NULL)
- goto ucnhashError;
- ucnhash_CAPI = (_PyUnicode_Name_CAPI *)PyCObject_AsVoidPtr(api);
- Py_DECREF(api);
+ ucnhash_CAPI = (_PyUnicode_Name_CAPI *)PyCapsule_Import(PyUnicodeData_CAPSULE_NAME, 1);
if (ucnhash_CAPI == NULL)
goto ucnhashError;
}
Modified: python/trunk/PC/VS7.1/pythoncore.vcproj
==============================================================================
--- python/trunk/PC/VS7.1/pythoncore.vcproj (original)
+++ python/trunk/PC/VS7.1/pythoncore.vcproj Thu Mar 25 01:54:54 2010
@@ -461,6 +461,9 @@
RelativePath="..\..\Objects\bytes_methods.c">
</File>
<File
+ RelativePath="..\..\Objects\capsule.c">
+ </File>
+ <File
RelativePath="..\..\Objects\cellobject.c">
</File>
<File
Modified: python/trunk/PC/VS8.0/pythoncore.vcproj
==============================================================================
--- python/trunk/PC/VS8.0/pythoncore.vcproj (original)
+++ python/trunk/PC/VS8.0/pythoncore.vcproj Thu Mar 25 01:54:54 2010
@@ -855,6 +855,10 @@
>
</File>
<File
+ RelativePath="..\..\Include\pycapsule.h"
+ >
+ </File>
+ <File
RelativePath="..\..\Include\pyctype.h"
>
</File>
@@ -1419,6 +1423,10 @@
>
</File>
<File
+ RelativePath="..\..\Objects\capsule.c"
+ >
+ </File>
+ <File
RelativePath="..\..\Objects\cellobject.c"
>
</File>
Modified: python/trunk/PC/os2emx/python27.def
==============================================================================
--- python/trunk/PC/os2emx/python27.def (original)
+++ python/trunk/PC/os2emx/python27.def Thu Mar 25 01:54:54 2010
@@ -210,6 +210,19 @@
"PyInstance_Type"
"PyMethod_Type"
+; From python27_s.lib(capsule)
+ "PyCapsule_GetContext"
+ "PyCapsule_GetDestructor"
+ "PyCapsule_GetName"
+ "PyCapsule_GetPointer"
+ "PyCapsule_Import"
+ "PyCapsule_IsValid"
+ "PyCapsule_New"
+ "PyCapsule_SetContext"
+ "PyCapsule_SetDestructor"
+ "PyCapsule_SetName"
+ "PyCapsule_SetPointer"
+
; From python27_s.lib(cobject)
"PyCObject_FromVoidPtr"
"PyCObject_FromVoidPtrAndDesc"
Modified: python/trunk/PC/os2vacpp/python.def
==============================================================================
--- python/trunk/PC/os2vacpp/python.def (original)
+++ python/trunk/PC/os2vacpp/python.def Thu Mar 25 01:54:54 2010
@@ -6,6 +6,7 @@
EXPORTS
; Data
PyCFunction_Type
+ PyCapsule_Type
PyCObject_Type
PyClass_Type
PyCode_Type
@@ -75,6 +76,7 @@
_Py_TrueStruct
_Py_ZeroStruct
_Py_abstract_hack
+ _Py_capsule_hack
_Py_cobject_hack
_Py_re_syntax
_Py_re_syntax_table
@@ -89,6 +91,17 @@
PyCFunction_GetFunction
PyCFunction_GetSelf
PyCFunction_New
+ PyCapsule_GetContext
+ PyCapsule_GetDestructor
+ PyCapsule_GetName
+ PyCapsule_GetPointer
+ PyCapsule_Import
+ PyCapsule_IsValid
+ PyCapsule_New
+ PyCapsule_SetContext
+ PyCapsule_SetDestructor
+ PyCapsule_SetName
+ PyCapsule_SetPointer
PyCObject_AsVoidPtr
PyCObject_FromVoidPtrAndDesc
PyCObject_FromVoidPtr
Modified: python/trunk/Python/compile.c
==============================================================================
--- python/trunk/Python/compile.c (original)
+++ python/trunk/Python/compile.c Thu Mar 25 01:54:54 2010
@@ -181,6 +181,8 @@
static PyCodeObject *assemble(struct compiler *, int addNone);
static PyObject *__doc__;
+#define COMPILER_CAPSULE_NAME_COMPILER_UNIT "compile.c compiler unit"
+
PyObject *
_Py_Mangle(PyObject *privateobj, PyObject *ident)
{
@@ -490,13 +492,13 @@
/* Push the old compiler_unit on the stack. */
if (c->u) {
- PyObject *wrapper = PyCObject_FromVoidPtr(c->u, NULL);
- if (!wrapper || PyList_Append(c->c_stack, wrapper) < 0) {
- Py_XDECREF(wrapper);
+ PyObject *capsule = PyCapsule_New(c->u, COMPILER_CAPSULE_NAME_COMPILER_UNIT, NULL);
+ if (!capsule || PyList_Append(c->c_stack, capsule) < 0) {
+ Py_XDECREF(capsule);
compiler_unit_free(u);
return 0;
}
- Py_DECREF(wrapper);
+ Py_DECREF(capsule);
u->u_private = c->u->u_private;
Py_XINCREF(u->u_private);
}
@@ -513,15 +515,15 @@
compiler_exit_scope(struct compiler *c)
{
int n;
- PyObject *wrapper;
+ PyObject *capsule;
c->c_nestlevel--;
compiler_unit_free(c->u);
/* Restore c->u to the parent unit. */
n = PyList_GET_SIZE(c->c_stack) - 1;
if (n >= 0) {
- wrapper = PyList_GET_ITEM(c->c_stack, n);
- c->u = (struct compiler_unit *)PyCObject_AsVoidPtr(wrapper);
+ capsule = PyList_GET_ITEM(c->c_stack, n);
+ c->u = (struct compiler_unit *)PyCapsule_GetPointer(capsule, COMPILER_CAPSULE_NAME_COMPILER_UNIT);
assert(c->u);
/* we are deleting from a list so this really shouldn't fail */
if (PySequence_DelItem(c->c_stack, n) < 0)
Modified: python/trunk/Python/getargs.c
==============================================================================
--- python/trunk/Python/getargs.c (original)
+++ python/trunk/Python/getargs.c Thu Mar 25 01:54:54 2010
@@ -139,22 +139,33 @@
/* Handle cleanup of allocated memory in case of exception */
+#define GETARGS_CAPSULE_NAME_CLEANUP_PTR "getargs.cleanup_ptr"
+#define GETARGS_CAPSULE_NAME_CLEANUP_BUFFER "getargs.cleanup_buffer"
+
static void
-cleanup_ptr(void *ptr)
+cleanup_ptr(PyObject *self)
{
- PyMem_FREE(ptr);
+ void *ptr = PyCapsule_GetPointer(self, GETARGS_CAPSULE_NAME_CLEANUP_PTR);
+ if (ptr) {
+ PyMem_FREE(ptr);
+ }
}
static void
-cleanup_buffer(void *ptr)
+cleanup_buffer(PyObject *self)
{
- PyBuffer_Release((Py_buffer *) ptr);
+ Py_buffer *ptr = (Py_buffer *)PyCapsule_GetPointer(self, GETARGS_CAPSULE_NAME_CLEANUP_BUFFER);
+ if (ptr) {
+ PyBuffer_Release(ptr);
+ }
}
static int
-addcleanup(void *ptr, PyObject **freelist, void (*destr)(void *))
+addcleanup(void *ptr, PyObject **freelist, PyCapsule_Destructor destr)
{
PyObject *cobj;
+ const char *name;
+
if (!*freelist) {
*freelist = PyList_New(0);
if (!*freelist) {
@@ -162,7 +173,15 @@
return -1;
}
}
- cobj = PyCObject_FromVoidPtr(ptr, destr);
+
+ if (destr == cleanup_ptr) {
+ name = GETARGS_CAPSULE_NAME_CLEANUP_PTR;
+ } else if (destr == cleanup_buffer) {
+ name = GETARGS_CAPSULE_NAME_CLEANUP_BUFFER;
+ } else {
+ return -1;
+ }
+ cobj = PyCapsule_New(ptr, name, destr);
if (!cobj) {
destr(ptr);
return -1;
@@ -183,8 +202,7 @@
don't get called. */
Py_ssize_t len = PyList_GET_SIZE(freelist), i;
for (i = 0; i < len; i++)
- ((PyCObject *) PyList_GET_ITEM(freelist, i))
- ->destructor = NULL;
+ PyCapsule_SetDestructor(PyList_GET_ITEM(freelist, i), NULL);
}
Py_XDECREF(freelist);
return retval;
2
2
Author: benjamin.peterson
Date: Thu Mar 25 04:46:05 2010
New Revision: 79414
Log:
Blocked revisions 79413 via svnmerge
........
r79413 | benjamin.peterson | 2010-03-24 22:44:24 -0500 (Wed, 24 Mar 2010) | 1 line
make an attempt to add capsule to the Windows build
........
Modified:
python/branches/py3k/ (props changed)
1
0
Author: benjamin.peterson
Date: Thu Mar 25 04:44:24 2010
New Revision: 79413
Log:
make an attempt to add capsule to the Windows build
Modified:
python/trunk/PCbuild/pythoncore.vcproj
Modified: python/trunk/PCbuild/pythoncore.vcproj
==============================================================================
--- python/trunk/PCbuild/pythoncore.vcproj (original)
+++ python/trunk/PCbuild/pythoncore.vcproj Thu Mar 25 04:44:24 2010
@@ -683,6 +683,10 @@
>
</File>
<File
+ RelativePath="..\Include\pycapsule.h"
+ >
+ </File>
+ <File
RelativePath="..\Include\code.h"
>
</File>
@@ -1431,6 +1435,10 @@
>
</File>
<File
+ RelativePath="..\Objects\capsule.c"
+ >
+ </File>
+ <File
RelativePath="..\Objects\codeobject.c"
>
</File>
1
0
Author: andrew.kuchling
Date: Thu Mar 25 02:35:51 2010
New Revision: 79412
Log:
Add various items
Modified:
python/trunk/Doc/whatsnew/2.7.rst
Modified: python/trunk/Doc/whatsnew/2.7.rst
==============================================================================
--- python/trunk/Doc/whatsnew/2.7.rst (original)
+++ python/trunk/Doc/whatsnew/2.7.rst Thu Mar 25 02:35:51 2010
@@ -8,6 +8,9 @@
.. Fix accents on Kristjan Valur Jonsson, Fuerstenau
+.. Big jobs: argparse, ElementTree 1.3, pep 391, 3106, sysconfig
+.. unittest test discovery
+
.. $Id$
Rules for maintenance:
@@ -237,6 +240,20 @@
XXX write this section.
+Two smaller enhancements to the logging module are:
+
+.. rev79293
+
+* :class:`Logger` instances gained a :meth:`getChild` that retrieves a
+ descendant logger using a relative path. For example,
+ once you retrieve a logger by doing ``log = getLogger('app')``,
+ calling ``log.getChild('network.listen')`` is equivalent to
+ ``getLogger('app.network.listen')``.
+
+* The :class:`LoggerAdapter` class gained a :meth:`isEnabledFor` method
+ that takes a *level* and returns whether the underlying logger would
+ process a message of that level of importance.
+
.. seealso::
:pep:`391` - Dictionary-Based Configuration For Logging
@@ -351,11 +368,12 @@
of them -- but you can mix auto-numbering and named fields, as in the second
example above. (Contributed by Eric Smith; :issue:`5237`.)
- Complex numbers now correctly support usage with :func:`format`.
+ Complex numbers now correctly support usage with :func:`format`,
+ and default to being right-aligned.
Specifying a precision or comma-separation applies to both the real
and imaginary parts of the number, but a specified field width and
alignment is applied to the whole of the resulting ``1.5+3j``
- output. (Contributed by Eric Smith; :issue:`1588`.)
+ output. (Contributed by Eric Smith; :issue:`1588` and :issue:`7988`.)
The 'F' format code now always formats its output using uppercase characters,
so it will now produce 'INF' and 'NAN'.
@@ -406,6 +424,10 @@
Integer division is also more accurate in its rounding behaviours. (Also
implemented by Mark Dickinson; :issue:`1811`.)
+* It's now possible for a subclass of the built-in :class:`unicode` type
+ to override the :meth:`__unicode__` method. (Implemented by
+ Victor Stinner; :issue:`1583863`.)
+
* The :class:`bytearray` type's :meth:`translate` method now accepts
``None`` as its first argument. (Fixed by Georg Brandl;
:issue:`4759`.)
@@ -568,6 +590,14 @@
used with :class:`memoryview` instances and other similar buffer objects.
(Backported from 3.x by Florent Xicluna; :issue:`7703`.)
+* Updated module: the :mod:`bsddb` module has been updated from 4.7.2devel9
+ to version 4.8.4 of
+ `the pybsddb package <http://www.jcea.es/programacion/pybsddb.htm>`__.
+ The new version features better Python 3.x compatibility, various bug fixes,
+ and adds several new BerkeleyDB flags and methods.
+ (Updated by Jesús Cea Avion; :issue:`8156`. The pybsddb
+ changelog can be browsed at http://hg.jcea.es/pybsddb/file/tip/ChangeLog.)
+
* The :mod:`bz2` module's :class:`BZ2File` now supports the context
management protocol, so you can write ``with bz2.BZ2File(...) as f: ...``.
(Contributed by Hagen Fuerstenau; :issue:`3860`.)
@@ -656,6 +686,11 @@
``Decimal('0.1000000000000000055511151231257827021181583404541015625')``.
(Implemented by Raymond Hettinger; :issue:`4796`.)
+ Most of the methods of the :class:`Context` class now accept integers
+ as well as :class:`Decimal` instances; the only exceptions are the
+ :meth:`canonical` and :meth:`is_canonical` methods. (Patch by
+ Juan José Conti; :issue:`7633`.)
+
The constructor for :class:`Decimal` now accepts non-European
Unicode characters, such as Arabic-Indic digits. (Contributed by
Mark Dickinson; :issue:`6595`.)
@@ -697,6 +732,12 @@
:mod:`gzip` module will now consume these trailing bytes. (Fixed by
Tadek Pietraszek and Brian Curtin; :issue:`2846`.)
+* New attribute: the :mod:`hashlib` module now has an :attr:`algorithms`
+ attribute containing a tuple naming the supported algorithms.
+ In Python 2.7, ``hashlib.algorithms`` contains
+ ``('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512')``
+ (Contributed by Carl Chenet; :issue:`7418`.)
+
* The default :class:`HTTPResponse` class used by the :mod:`httplib` module now
supports buffering, resulting in much faster reading of HTTP responses.
(Contributed by Kristjan Valur Jonsson; :issue:`4879`.)
@@ -803,9 +844,11 @@
the child process; this fixes problems on Solaris when :func:`fork`
is called from a thread. (Fixed by Zsolt Cserna; :issue:`7242`.)
- The :func:`normpath` function now preserves Unicode; if its input path
+* In the :mod:`os.path` module, the :func:`normpath` and
+ :func:`abspath` functions now preserve Unicode; if their input path
is a Unicode string, the return value is also a Unicode string.
- (Fixed by Matt Giuca; :issue:`5827`.)
+ (:meth:`normpath` fixed by Matt Giuca in :issue:`5827`;
+ :meth:`abspath` fixed by Ezio Melotti in :issue:`3426`.)
* The :mod:`pydoc` module now has help for the various symbols that Python
uses. You can now do ``help('<<')`` or ``help('@')``, for example.
@@ -940,14 +983,13 @@
a timeout was provided and the operation timed out.
(Contributed by Tim Lesher; :issue:`1674032`.)
-* The Unicode database has been updated to the version 5.2.0.
- (Updated by Florent Xicluna; :issue:`8024`.)
-
-* The Unicode database provided by the :mod:`unicodedata` is used
- internally to determine which characters are numeric, whitespace,
- or represent line breaks. The database also now includes information
- from the :file:`Unihan.txt` data file. (Patch by Anders Chrigström
- and Amaury Forgeot d'Arc; :issue:`1571184`.)
+* The Unicode database provided by the :mod:`unicodedata` module is
+ now used internally to determine which characters are numeric,
+ whitespace, or represent line breaks. The database also
+ includes information from the :file:`Unihan.txt` data file (patch
+ by Anders Chrigström and Amaury Forgeot d'Arc; :issue:`1571184`)
+ and has been updated to version 5.2.0 (updated by
+ Florent Xicluna; :issue:`8024`).
* The :class:`UserDict` class is now a new-style class. (Changed by
Benjamin Peterson.)
@@ -1074,12 +1116,22 @@
(Implemented by Antoine Pitrou; :issue:`4444`.)
+.. rev 78774
+
+Module- and class-level setup and teardown fixtures are now supported.
+Modules can contain :func:`setUpModule` and :func:`tearDownModule`
+functions. Classes can have :meth:`setUpClass` and
+:meth:`tearDownClass` methods that must be defined as class methods
+(using ``@classmethod`` or the equivalent). These functions and
+methods are invoked when the test runner switches to a test case in a
+different module or class.
+
The methods :meth:`addCleanup` and :meth:`doCleanups` were added.
:meth:`addCleanup` allows you to add cleanup functions that
will be called unconditionally (after :meth:`setUp` if
:meth:`setUp` fails, otherwise after :meth:`tearDown`). This allows
-for much simpler resource allocation and deallocation during tests.
-:issue:`5679`
+for much simpler resource allocation and deallocation during tests
+(:issue:`5679`).
A number of new methods were added that provide more specialized
tests. Many of these methods were written by Google engineers
1
0
Author: larry.hastings
Date: Thu Mar 25 02:25:31 2010
New Revision: 79411
Log:
Blocked revisions 79410 via svnmerge
........
r79410 | larry.hastings | 2010-03-24 18:23:27 -0700 (Wed, 24 Mar 2010) | 2 lines
Remove extraneous experimental code checked in by accident.
........
Modified:
python/branches/py3k/ (props changed)
1
0
Author: larry.hastings
Date: Thu Mar 25 02:23:27 2010
New Revision: 79410
Log:
Remove extraneous experimental code checked in by accident.
Modified:
python/trunk/Include/pycapsule.h
Modified: python/trunk/Include/pycapsule.h
==============================================================================
--- python/trunk/Include/pycapsule.h (original)
+++ python/trunk/Include/pycapsule.h Thu Mar 25 02:23:27 2010
@@ -50,98 +50,6 @@
PyAPI_FUNC(void *) PyCapsule_Import(const char *name, int no_block);
-
-#define PYTHON_USING_CAPSULE
-
-#define PYCAPSULE_INSTANTIATE_DESTRUCTOR(name, destructor) \
-static void pycapsule_destructor_ ## name(PyObject *ptr) \
-{ \
- void *p = PyCapsule_GetPointer(ptr, name); \
- if (p) { \
- destructor(p); \
- } \
-} \
-
-#define PYCAPSULE_NEW(pointer, name) \
- (PyCapsule_New(pointer, name, capsule_destructor_ ## name))
-
-#define PYCAPSULE_ISVALID(capsule, name) \
- (PyCapsule_IsValid(capsule, name))
-
-#define PYCAPSULE_DEREFERENCE(capsule, name) \
- (PyCapsule_GetPointer(capsule, name))
-
-#define PYCAPSULE_SET(capsule, name, value) \
- (PyCapsule_IsValid(capsule, name) && PyCapsule_SetPointer(capsule, value))
-
-/* module and attribute should be specified as string constants */
-#define PYCAPSULE_IMPORT(module, attribute) \
- (PyCapsule_Import(module "." attribute, 0))
-
-
-/* begin public-domain code */
-/*
-** This code was written by Larry Hastings,
-** and is dedicated to the public domain.
-** It's designed to make it easy to switch
-** from CObject to Capsule objects without losing
-** backwards compatibility with prior versions
-** of CPython. You're encouraged to copy this code
-** (including this documentation) into your
-** Python C extension.
-**
-** To use:
-** * #define a name for the pointer you store in
-** the CObject. If you make the CObject available
-** as part of your module's API, this name should
-** be "modulename.attributename", and it should be
-** considered part of your API (so put it in your
-** header file).
-** * Specify a PYCAPSULE_INSTANTIATE_DESTRUCTOR(), in
-** every C file that creates these CObjects. This
-** is where you specify your object's destructor.
-** * Change all calls to CObject_FromVoidPtr()
-** and CObject_FromVoidPointerAndDesc() into
-** PYCAPSULE_NEW() calls.
-** * Change all calls to PyCObject_AsVoidPtr()
-** into PYCAPSULE_DEREFERENCE() calls.
-** * Change all calls to PyCObject_SetVoidPtr()
-** into PYCAPSULE_SET() calls.
-** * Change all calls to PyCObject_Import()
-** into PYCAPSULE_IMPORT() calls. Note that
-** the two arguments to PYCAPSULE_IMPORT()
-** should both be string constants; that is,
-** you should call
-** PYCAPSULE_IMPORT("modulename", "attributename"),
-** not PYCAPSULE_IMPORT(charstar1, charstar2).
-*/
-#ifndef PYTHON_USING_CAPSULE
-
-#define PYCAPSULE_INSTANTIATE_DESTRUCTOR(name, destructor) \
-static void pycapsule_destructor_ ## name(void *ptr) \
-{ \
- destructor(p); \
-} \
-
-#define PYCAPSULE_NEW(pointer, name) \
- (PyCObject_FromVoidPtr(pointer, pycapsule_destructor_ ## name))
-
-#define PYCAPSULE_ISVALID(capsule, name) \
- (PyCObject_Check(capsule))
-
-#define PYCAPSULE_DEREFERENCE(capsule, name) \
- (PyCObject_AsVoidPtr(capsule))
-
-#define PYCAPSULE_SET(capsule, name, value) \
- (PyCObject_SetVoidPtr(capsule, value))
-
-/* module and attribute should be specified as string constants */
-#define PYCAPSULE_IMPORT(module, attribute) \
- (PyCObject_Import(module, attribute))
-
-#endif /* PYTHON_USING_CAPSULE */
-/* end public-domain code */
-
#ifdef __cplusplus
}
#endif
1
0
24 Mar '10
Author: benjamin.peterson
Date: Thu Mar 25 02:21:09 2010
New Revision: 79409
Log:
Merged revisions 79403 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r79403 | benjamin.peterson | 2010-03-24 20:04:58 -0500 (Wed, 24 Mar 2010) | 1 line
set eol on email example
........
Modified:
python/branches/py3k/ (props changed)
python/branches/py3k/Doc/includes/email-headers.py (props changed)
1
0
Author: victor.stinner
Date: Thu Mar 25 02:18:38 2010
New Revision: 79408
Log:
Fix a gcc warning introduced by r79397.
Modified:
python/trunk/Modules/datetimemodule.c
Modified: python/trunk/Modules/datetimemodule.c
==============================================================================
--- python/trunk/Modules/datetimemodule.c (original)
+++ python/trunk/Modules/datetimemodule.c Thu Mar 25 02:18:38 2010
@@ -4858,7 +4858,7 @@
x = PyCapsule_New(&CAPI, PyDateTime_CAPSULE_NAME, NULL);
if (x == NULL)
- return NULL;
+ return;
PyModule_AddObject(m, "datetime_CAPI", x);
/* A 4-year cycle has an extra leap day over what we'd get from
1
0