123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- ##############################################################################
- #
- # Copyright (c) 2006 Zope Foundation and Contributors.
- # All Rights Reserved.
- #
- # This software is subject to the provisions of the Zope Public License,
- # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
- # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
- # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
- # FOR A PARTICULAR PURPOSE.
- #
- ##############################################################################
- """
- Support functions for dealing with differences in platforms, including Python
- versions and implementations.
-
- This file should have no imports from the rest of zope.interface because it is
- used during early bootstrapping.
- """
- import os
- import sys
-
-
- def _normalize_name(name):
- if isinstance(name, bytes):
- name = str(name, 'ascii')
- if isinstance(name, str):
- return name
- raise TypeError("name must be a string or ASCII-only bytes")
-
- PYPY = hasattr(sys, 'pypy_version_info')
-
-
- def _c_optimizations_required():
- """
- Return a true value if the C optimizations are required.
-
- This uses the ``PURE_PYTHON`` variable as documented in `_use_c_impl`.
- """
- pure_env = os.environ.get('PURE_PYTHON')
- require_c = pure_env == "0"
- return require_c
-
-
- def _c_optimizations_available():
- """
- Return the C optimization module, if available, otherwise
- a false value.
-
- If the optimizations are required but not available, this
- raises the ImportError.
-
- This does not say whether they should be used or not.
- """
- catch = () if _c_optimizations_required() else (ImportError,)
- try:
- from zope.interface import _zope_interface_coptimizations as c_opt
- return c_opt
- except catch: # pragma: no cover (only Jython doesn't build extensions)
- return False
-
-
- def _c_optimizations_ignored():
- """
- The opposite of `_c_optimizations_required`.
- """
- pure_env = os.environ.get('PURE_PYTHON')
- return pure_env is not None and pure_env != "0"
-
-
- def _should_attempt_c_optimizations():
- """
- Return a true value if we should attempt to use the C optimizations.
-
- This takes into account whether we're on PyPy and the value of the
- ``PURE_PYTHON`` environment variable, as defined in `_use_c_impl`.
- """
- is_pypy = hasattr(sys, 'pypy_version_info')
-
- if _c_optimizations_required():
- return True
- if is_pypy:
- return False
- return not _c_optimizations_ignored()
-
-
- def _use_c_impl(py_impl, name=None, globs=None):
- """
- Decorator. Given an object implemented in Python, with a name like
- ``Foo``, import the corresponding C implementation from
- ``zope.interface._zope_interface_coptimizations`` with the name
- ``Foo`` and use it instead.
-
- If the ``PURE_PYTHON`` environment variable is set to any value
- other than ``"0"``, or we're on PyPy, ignore the C implementation
- and return the Python version. If the C implementation cannot be
- imported, return the Python version. If ``PURE_PYTHON`` is set to
- 0, *require* the C implementation (let the ImportError propagate);
- note that PyPy can import the C implementation in this case (and all
- tests pass).
-
- In all cases, the Python version is kept available. in the module
- globals with the name ``FooPy`` and the name ``FooFallback`` (both
- conventions have been used; the C implementation of some functions
- looks for the ``Fallback`` version, as do some of the Sphinx
- documents).
-
- Example::
-
- @_use_c_impl
- class Foo(object):
- ...
- """
- name = name or py_impl.__name__
- globs = globs or sys._getframe(1).f_globals
-
- def find_impl():
- if not _should_attempt_c_optimizations():
- return py_impl
-
- c_opt = _c_optimizations_available()
- if not c_opt: # pragma: no cover (only Jython doesn't build extensions)
- return py_impl
-
- __traceback_info__ = c_opt
- return getattr(c_opt, name)
-
- c_impl = find_impl()
- # Always make available by the FooPy name and FooFallback
- # name (for testing and documentation)
- globs[name + 'Py'] = py_impl
- globs[name + 'Fallback'] = py_impl
-
- return c_impl
|