2011-04-04 19:37:07 -04:00
|
|
|
PEP: 399
|
2011-04-04 19:47:09 -04:00
|
|
|
Title: Pure Python/C Accelerator Module Compatibility Requirements
|
2011-04-04 19:37:07 -04:00
|
|
|
Version: $Revision: 88219 $
|
|
|
|
Last-Modified: $Date: 2011-01-27 13:47:00 -0800 (Thu, 27 Jan 2011) $
|
|
|
|
Author: Brett Cannon <brett@python.org>
|
2011-08-20 00:00:37 -04:00
|
|
|
Status: Final
|
2011-04-04 19:37:07 -04:00
|
|
|
Type: Informational
|
|
|
|
Content-Type: text/x-rst
|
|
|
|
Created: 04-Apr-2011
|
|
|
|
Python-Version: 3.3
|
2013-01-04 15:23:50 -05:00
|
|
|
Post-History: 04-Apr-2011, 12-Apr-2011, 17-Jul-2011, 15-Aug-2011, 01-Jan-2013
|
2011-04-04 19:37:07 -04:00
|
|
|
|
|
|
|
Abstract
|
|
|
|
========
|
|
|
|
|
|
|
|
The Python standard library under CPython contains various instances
|
2011-04-06 13:05:50 -04:00
|
|
|
of modules implemented in both pure Python and C (either entirely or
|
2011-04-12 17:59:45 -04:00
|
|
|
partially). This PEP requires that in these instances that the
|
2012-12-09 13:31:24 -05:00
|
|
|
C code **must** pass the test suite used for the pure Python code
|
2011-07-17 20:18:06 -04:00
|
|
|
so as to act as much as a drop-in replacement as reasonably possible
|
2011-04-12 17:59:45 -04:00
|
|
|
(C- and VM-specific tests are exempt). It is also required that new
|
|
|
|
C-based modules lacking a pure Python equivalent implementation get
|
2011-07-17 20:18:06 -04:00
|
|
|
special permission to be added to the standard library.
|
2011-04-04 19:37:07 -04:00
|
|
|
|
|
|
|
|
|
|
|
Rationale
|
|
|
|
=========
|
|
|
|
|
|
|
|
Python has grown beyond the CPython virtual machine (VM). IronPython_,
|
2011-07-17 20:18:06 -04:00
|
|
|
Jython_, and PyPy_ are all currently viable alternatives to the
|
|
|
|
CPython VM. The VM ecosystem that has sprung up around the Python
|
2011-04-04 19:37:07 -04:00
|
|
|
programming language has led to Python being used in many different
|
|
|
|
areas where CPython cannot be used, e.g., Jython allowing Python to be
|
|
|
|
used in Java applications.
|
|
|
|
|
|
|
|
A problem all of the VMs other than CPython face is handling modules
|
2011-04-06 13:05:50 -04:00
|
|
|
from the standard library that are implemented (to some extent) in C.
|
2011-07-17 20:18:06 -04:00
|
|
|
Since other VMs do not typically support the entire `C API of CPython`_
|
2016-07-11 11:14:08 -04:00
|
|
|
they are unable to use the code used to create the module. Oftentimes
|
2011-04-16 16:47:30 -04:00
|
|
|
this leads these other VMs to either re-implement the modules in pure
|
2011-07-17 20:18:06 -04:00
|
|
|
Python or in the programming language used to implement the VM itself
|
2011-04-06 13:05:50 -04:00
|
|
|
(e.g., in C# for IronPython). This duplication of effort between
|
|
|
|
CPython, PyPy, Jython, and IronPython is extremely unfortunate as
|
2012-12-09 13:31:24 -05:00
|
|
|
implementing a module **at least** in pure Python would help mitigate
|
2011-04-06 13:05:50 -04:00
|
|
|
this duplicate effort.
|
2011-04-04 19:37:07 -04:00
|
|
|
|
|
|
|
The purpose of this PEP is to minimize this duplicate effort by
|
|
|
|
mandating that all new modules added to Python's standard library
|
2012-12-09 13:31:24 -05:00
|
|
|
**must** have a pure Python implementation *unless* special dispensation
|
2011-04-04 19:37:07 -04:00
|
|
|
is given. This makes sure that a module in the stdlib is available to
|
2011-04-12 17:59:45 -04:00
|
|
|
all VMs and not just to CPython (pre-existing modules that do not meet
|
|
|
|
this requirement are exempt, although there is nothing preventing
|
|
|
|
someone from adding in a pure Python implementation retroactively).
|
2011-04-04 19:37:07 -04:00
|
|
|
|
|
|
|
Re-implementing parts (or all) of a module in C (in the case
|
|
|
|
of CPython) is still allowed for performance reasons, but any such
|
2011-04-12 17:59:45 -04:00
|
|
|
accelerated code must pass the same test suite (sans VM- or C-specific
|
|
|
|
tests) to verify semantics and prevent divergence. To accomplish this,
|
2011-07-17 20:18:06 -04:00
|
|
|
the test suite for the module must have comprehensive coverage of the
|
2011-04-12 17:59:45 -04:00
|
|
|
pure Python implementation before the acceleration code may be added.
|
2011-04-04 19:37:07 -04:00
|
|
|
|
|
|
|
|
|
|
|
Details
|
|
|
|
=======
|
|
|
|
|
|
|
|
Starting in Python 3.3, any modules added to the standard library must
|
|
|
|
have a pure Python implementation. This rule can only be ignored if
|
|
|
|
the Python development team grants a special exemption for the module.
|
2011-04-12 17:59:45 -04:00
|
|
|
Typically the exemption will be granted only when a module wraps a
|
2011-04-04 19:37:07 -04:00
|
|
|
specific C-based library (e.g., sqlite3_). In granting an exemption it
|
2011-04-12 17:59:45 -04:00
|
|
|
will be recognized that the module will be considered exclusive to
|
|
|
|
CPython and not part of Python's standard library that other VMs are
|
|
|
|
expected to support. Usage of ``ctypes`` to provide an
|
2011-04-04 19:37:07 -04:00
|
|
|
API for a C library will continue to be frowned upon as ``ctypes``
|
|
|
|
lacks compiler guarantees that C code typically relies upon to prevent
|
|
|
|
certain errors from occurring (e.g., API changes).
|
|
|
|
|
|
|
|
Even though a pure Python implementation is mandated by this PEP, it
|
|
|
|
does not preclude the use of a companion acceleration module. If an
|
|
|
|
acceleration module is provided it is to be named the same as the
|
|
|
|
module it is accelerating with an underscore attached as a prefix,
|
|
|
|
e.g., ``_warnings`` for ``warnings``. The common pattern to access
|
|
|
|
the accelerated code from the pure Python implementation is to import
|
|
|
|
it with an ``import *``, e.g., ``from _warnings import *``. This is
|
|
|
|
typically done at the end of the module to allow it to overwrite
|
|
|
|
specific Python objects with their accelerated equivalents. This kind
|
|
|
|
of import can also be done before the end of the module when needed,
|
|
|
|
e.g., an accelerated base class is provided but is then subclassed by
|
|
|
|
Python code. This PEP does not mandate that pre-existing modules in
|
|
|
|
the stdlib that lack a pure Python equivalent gain such a module. But
|
|
|
|
if people do volunteer to provide and maintain a pure Python
|
|
|
|
equivalent (e.g., the PyPy team volunteering their pure Python
|
|
|
|
implementation of the ``csv`` module and maintaining it) then such
|
2011-07-17 20:18:06 -04:00
|
|
|
code will be accepted. In those instances the C version is considered
|
|
|
|
the reference implementation in terms of expected semantics.
|
2011-04-12 17:59:45 -04:00
|
|
|
|
|
|
|
Any new accelerated code must act as a drop-in replacement as close
|
|
|
|
to the pure Python implementation as reasonable. Technical details of
|
|
|
|
the VM providing the accelerated code are allowed to differ as
|
|
|
|
necessary, e.g., a class being a ``type`` when implemented in C. To
|
|
|
|
verify that the Python and equivalent C code operate as similarly as
|
|
|
|
possible, both code bases must be tested using the same tests which
|
|
|
|
apply to the pure Python code (tests specific to the C code or any VM
|
2011-07-17 20:18:06 -04:00
|
|
|
do not follow under this requirement). The test suite is expected to
|
|
|
|
be extensive in order to verify expected semantics.
|
2011-04-12 17:59:45 -04:00
|
|
|
|
|
|
|
Acting as a drop-in replacement also dictates that no public API be
|
|
|
|
provided in accelerated code that does not exist in the pure Python
|
|
|
|
code. Without this requirement people could accidentally come to rely
|
|
|
|
on a detail in the accelerated code which is not made available to
|
|
|
|
other VMs that use the pure Python implementation. To help verify
|
|
|
|
that the contract of semantic equivalence is being met, a module must
|
|
|
|
be tested both with and without its accelerated code as thoroughly as
|
|
|
|
possible.
|
2011-04-04 19:37:07 -04:00
|
|
|
|
|
|
|
As an example, to write tests which exercise both the pure Python and
|
2011-04-06 12:38:21 -04:00
|
|
|
C accelerated versions of a module, a basic idiom can be followed::
|
2011-04-04 19:37:07 -04:00
|
|
|
|
2013-01-27 13:24:31 -05:00
|
|
|
from test.support import import_fresh_module
|
2011-04-04 19:37:07 -04:00
|
|
|
import unittest
|
|
|
|
|
|
|
|
c_heapq = import_fresh_module('heapq', fresh=['_heapq'])
|
|
|
|
py_heapq = import_fresh_module('heapq', blocked=['_heapq'])
|
|
|
|
|
|
|
|
|
2013-01-04 15:23:50 -05:00
|
|
|
class ExampleTest:
|
2011-04-04 19:37:07 -04:00
|
|
|
|
2013-01-27 13:24:31 -05:00
|
|
|
def test_example(self):
|
|
|
|
self.assertTrue(hasattr(self.module, 'heapify'))
|
2011-04-04 19:37:07 -04:00
|
|
|
|
|
|
|
|
2013-01-04 15:23:50 -05:00
|
|
|
class PyExampleTest(ExampleTest, unittest.TestCase):
|
2013-01-27 13:24:31 -05:00
|
|
|
module = py_heapq
|
2011-04-04 19:37:07 -04:00
|
|
|
|
|
|
|
|
2013-01-04 15:23:50 -05:00
|
|
|
@unittest.skipUnless(c_heapq, 'requires the C _heapq module')
|
|
|
|
class CExampleTest(ExampleTest, unittest.TestCase):
|
2013-01-27 13:24:31 -05:00
|
|
|
module = c_heapq
|
2011-04-04 19:37:07 -04:00
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
2013-01-04 15:23:50 -05:00
|
|
|
unittest.main()
|
|
|
|
|
2011-04-04 19:37:07 -04:00
|
|
|
|
2013-01-04 15:23:50 -05:00
|
|
|
The test module defines a base class (``ExampleTest``) with test methods
|
|
|
|
that access the ``heapq`` module through a ``self.heapq`` class attribute,
|
|
|
|
and two subclasses that set this attribute to either the Python or the C
|
|
|
|
version of the module. Note that only the two subclasses inherit from
|
|
|
|
``unittest.TestCase`` -- this prevents the ``ExampleTest`` class from
|
|
|
|
being detected as a ``TestCase`` subclass by ``unittest`` test discovery.
|
|
|
|
A ``skipUnless`` decorator can be added to the class that tests the C code
|
|
|
|
in order to have these tests skipped when the C module is not available.
|
2011-04-12 17:59:45 -04:00
|
|
|
|
2011-07-17 20:18:06 -04:00
|
|
|
If this test were to provide extensive coverage for
|
2011-04-12 17:59:45 -04:00
|
|
|
``heapq.heappop()`` in the pure Python implementation then the
|
|
|
|
accelerated C code would be allowed to be added to CPython's standard
|
|
|
|
library. If it did not, then the test suite would need to be updated
|
2011-07-17 20:18:06 -04:00
|
|
|
until proper coverage was provided before the accelerated C code
|
2011-04-12 17:59:45 -04:00
|
|
|
could be added.
|
2011-04-04 19:37:07 -04:00
|
|
|
|
2011-07-17 20:18:06 -04:00
|
|
|
To also help with compatibility, C code should use abstract APIs on
|
|
|
|
objects to prevent accidental dependence on specific types. For
|
|
|
|
instance, if a function accepts a sequence then the C code should
|
|
|
|
default to using `PyObject_GetItem()` instead of something like
|
|
|
|
`PyList_GetItem()`. C code is allowed to have a fast path if the
|
2011-08-20 00:00:37 -04:00
|
|
|
proper `PyList_CheckExact()` is used, but otherwise APIs should work
|
|
|
|
with any object that duck types to the proper interface instead of a
|
2011-07-17 20:18:06 -04:00
|
|
|
specific type.
|
|
|
|
|
2011-04-04 19:37:07 -04:00
|
|
|
|
|
|
|
Copyright
|
|
|
|
=========
|
|
|
|
|
|
|
|
This document has been placed in the public domain.
|
|
|
|
|
|
|
|
|
|
|
|
.. _IronPython: http://ironpython.net/
|
|
|
|
.. _Jython: http://www.jython.org/
|
|
|
|
.. _PyPy: http://pypy.org/
|
2011-04-16 16:47:30 -04:00
|
|
|
.. _C API of CPython: http://docs.python.org/py3k/c-api/index.html
|
2011-04-04 19:37:07 -04:00
|
|
|
.. _sqlite3: http://docs.python.org/py3k/library/sqlite3.html
|