• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

zopefoundation / zope.interface / 16098775349

04 Mar 2025 10:16PM UTC coverage: 99.073% (+0.05%) from 99.022%
16098775349

push

github

web-flow
Merge pull request #338 from zopefoundation/config-with-c-code-template-3c1c588c

Apply latest meta templates, drop support for Python 3.8

2436 of 2464 branches covered (98.86%)

Branch coverage included in aggregate %.

12209 of 12318 relevant lines covered (99.12%)

6.93 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.55
/src/zope/interface/_compat.py
1
##############################################################################
2
#
3
# Copyright (c) 2006 Zope Foundation and Contributors.
4
# All Rights Reserved.
5
#
6
# This software is subject to the provisions of the Zope Public License,
7
# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
8
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11
# FOR A PARTICULAR PURPOSE.
12
#
13
##############################################################################
14
"""
7✔
15
Support functions for dealing with differences in platforms, including Python
16
versions and implementations.
17

18
This file should have no imports from the rest of zope.interface because it is
19
used during early bootstrapping.
20
"""
21
import os
7✔
22
import sys
7✔
23

24

25
PY313_OR_OLDER = sys.version_info < (3, 14)
7✔
26

27

28
def _normalize_name(name):
7✔
29
    if isinstance(name, bytes):
7✔
30
        name = str(name, 'ascii')
7✔
31
    if isinstance(name, str):
7✔
32
        return name
7✔
33
    raise TypeError("name must be a string or ASCII-only bytes")
7✔
34

35

36
PYPY = hasattr(sys, 'pypy_version_info')
7✔
37

38

39
def _c_optimizations_required():
7✔
40
    """
41
    Return a true value if the C optimizations are required.
42

43
    This uses the ``PURE_PYTHON`` variable as documented in `_use_c_impl`.
44
    """
45
    pure_env = os.environ.get('PURE_PYTHON')
7✔
46
    require_c = pure_env == "0"
7✔
47
    return require_c
7✔
48

49

50
def _c_optimizations_available():
7✔
51
    """
52
    Return the C optimization module, if available, otherwise
53
    a false value.
54

55
    If the optimizations are required but not available, this
56
    raises the ImportError.
57

58
    This does not say whether they should be used or not.
59
    """
60
    catch = () if _c_optimizations_required() else (ImportError,)
6✔
61
    try:
6✔
62
        from zope.interface import _zope_interface_coptimizations as c_opt
6✔
63
        return c_opt
6✔
64
    except catch:  # pragma: no cover (only Jython doesn't build extensions)
65
        return False
66

67

68
def _c_optimizations_ignored():
7✔
69
    """
70
    The opposite of `_c_optimizations_required`.
71
    """
72
    pure_env = os.environ.get('PURE_PYTHON')
6✔
73
    return pure_env is not None and pure_env != "0"
6✔
74

75

76
def _should_attempt_c_optimizations():
7✔
77
    """
78
    Return a true value if we should attempt to use the C optimizations.
79

80
    This takes into account whether we're on PyPy and the value of the
81
    ``PURE_PYTHON`` environment variable, as defined in `_use_c_impl`.
82
    """
83
    is_pypy = hasattr(sys, 'pypy_version_info')
7✔
84

85
    if _c_optimizations_required():
7!
86
        return True
×
87
    if is_pypy:
7✔
88
        return False
1✔
89
    return not _c_optimizations_ignored()
6✔
90

91

92
def _use_c_impl(py_impl, name=None, globs=None):
7✔
93
    """
94
    Decorator. Given an object implemented in Python, with a name like
95
    ``Foo``, import the corresponding C implementation from
96
    ``zope.interface._zope_interface_coptimizations`` with the name
97
    ``Foo`` and use it instead.
98

99
    If the ``PURE_PYTHON`` environment variable is set to any value
100
    other than ``"0"``, or we're on PyPy, ignore the C implementation
101
    and return the Python version. If the C implementation cannot be
102
    imported, return the Python version. If ``PURE_PYTHON`` is set to
103
    0, *require* the C implementation (let the ImportError propagate);
104
    note that PyPy can import the C implementation in this case (and all
105
    tests pass).
106

107
    In all cases, the Python version is kept available. in the module
108
    globals with the name ``FooPy`` and the name ``FooFallback`` (both
109
    conventions have been used; the C implementation of some functions
110
    looks for the ``Fallback`` version, as do some of the Sphinx
111
    documents).
112

113
    Example::
114

115
        @_use_c_impl
116
        class Foo(object):
117
            ...
118
    """
119
    name = name or py_impl.__name__
7✔
120
    globs = globs or sys._getframe(1).f_globals
7✔
121

122
    def find_impl():
7✔
123
        if not _should_attempt_c_optimizations():
7✔
124
            return py_impl
7✔
125

126
        c_opt = _c_optimizations_available()
6✔
127
        if not c_opt:  # pragma: no cover (Jython doesn't build extensions)
128
            return py_impl
129

130
        __traceback_info__ = c_opt
6✔
131
        return getattr(c_opt, name)
6✔
132

133
    c_impl = find_impl()
7✔
134
    # Always make available by the FooPy name and FooFallback
135
    # name (for testing and documentation)
136
    globs[name + 'Py'] = py_impl
7✔
137
    globs[name + 'Fallback'] = py_impl
7✔
138

139
    return c_impl
7✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc