Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

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""" 

15Support functions for dealing with differences in platforms, including Python 

16versions and implementations. 

17 

18This file should have no imports from the rest of zope.interface because it is 

19used during early bootstrapping. 

20""" 

21import os 

22import sys 

23import types 

24 

25if sys.version_info[0] < 3: 

26 

27 def _normalize_name(name): 

28 if isinstance(name, basestring): 

29 return unicode(name) 

30 raise TypeError("name must be a regular or unicode string") 

31 

32 CLASS_TYPES = (type, types.ClassType) 

33 STRING_TYPES = (basestring,) 

34 

35 _BUILTINS = '__builtin__' 

36 

37 PYTHON3 = False 

38 PYTHON2 = True 

39 

40else: 

41 

42 def _normalize_name(name): 

43 if isinstance(name, bytes): 

44 name = str(name, 'ascii') 

45 if isinstance(name, str): 

46 return name 

47 raise TypeError("name must be a string or ASCII-only bytes") 

48 

49 CLASS_TYPES = (type,) 

50 STRING_TYPES = (str,) 

51 

52 _BUILTINS = 'builtins' 

53 

54 PYTHON3 = True 

55 PYTHON2 = False 

56 

57PYPY = hasattr(sys, 'pypy_version_info') 

58PYPY2 = PYTHON2 and PYPY 

59 

60def _skip_under_py3k(test_method): 

61 import unittest 

62 return unittest.skipIf(sys.version_info[0] >= 3, "Only on Python 2")(test_method) 

63 

64 

65def _skip_under_py2(test_method): 

66 import unittest 

67 return unittest.skipIf(sys.version_info[0] < 3, "Only on Python 3")(test_method) 

68 

69 

70def _c_optimizations_required(): 

71 """ 

72 Return a true value if the C optimizations are required. 

73 

74 This uses the ``PURE_PYTHON`` variable as documented in `_use_c_impl`. 

75 """ 

76 pure_env = os.environ.get('PURE_PYTHON') 

77 require_c = pure_env == "0" 

78 return require_c 

79 

80 

81def _c_optimizations_available(): 

82 """ 

83 Return the C optimization module, if available, otherwise 

84 a false value. 

85 

86 If the optimizations are required but not available, this 

87 raises the ImportError. 

88 

89 This does not say whether they should be used or not. 

90 """ 

91 catch = () if _c_optimizations_required() else (ImportError,) 

92 try: 

93 from zope.interface import _zope_interface_coptimizations as c_opt 

94 return c_opt 

95 except catch: # pragma: no cover (only Jython doesn't build extensions) 

96 return False 

97 

98 

99def _c_optimizations_ignored(): 

100 """ 

101 The opposite of `_c_optimizations_required`. 

102 """ 

103 pure_env = os.environ.get('PURE_PYTHON') 

104 return pure_env is not None and pure_env != "0" 

105 

106 

107def _should_attempt_c_optimizations(): 

108 """ 

109 Return a true value if we should attempt to use the C optimizations. 

110 

111 This takes into account whether we're on PyPy and the value of the 

112 ``PURE_PYTHON`` environment variable, as defined in `_use_c_impl`. 

113 """ 

114 is_pypy = hasattr(sys, 'pypy_version_info') 

115 

116 if _c_optimizations_required(): 

117 return True 

118 if is_pypy: 

119 return False 

120 return not _c_optimizations_ignored() 

121 

122 

123def _use_c_impl(py_impl, name=None, globs=None): 

124 """ 

125 Decorator. Given an object implemented in Python, with a name like 

126 ``Foo``, import the corresponding C implementation from 

127 ``zope.interface._zope_interface_coptimizations`` with the name 

128 ``Foo`` and use it instead. 

129 

130 If the ``PURE_PYTHON`` environment variable is set to any value 

131 other than ``"0"``, or we're on PyPy, ignore the C implementation 

132 and return the Python version. If the C implementation cannot be 

133 imported, return the Python version. If ``PURE_PYTHON`` is set to 

134 0, *require* the C implementation (let the ImportError propagate); 

135 note that PyPy can import the C implementation in this case (and all 

136 tests pass). 

137 

138 In all cases, the Python version is kept available. in the module 

139 globals with the name ``FooPy`` and the name ``FooFallback`` (both 

140 conventions have been used; the C implementation of some functions 

141 looks for the ``Fallback`` version, as do some of the Sphinx 

142 documents). 

143 

144 Example:: 

145 

146 @_use_c_impl 

147 class Foo(object): 

148 ... 

149 """ 

150 name = name or py_impl.__name__ 

151 globs = globs or sys._getframe(1).f_globals 

152 

153 def find_impl(): 

154 if not _should_attempt_c_optimizations(): 

155 return py_impl 

156 

157 c_opt = _c_optimizations_available() 

158 if not c_opt: # pragma: no cover (only Jython doesn't build extensions) 

159 return py_impl 

160 

161 __traceback_info__ = c_opt 

162 return getattr(c_opt, name) 

163 

164 c_impl = find_impl() 

165 # Always make available by the FooPy name and FooFallback 

166 # name (for testing and documentation) 

167 globs[name + 'Py'] = py_impl 

168 globs[name + 'Fallback'] = py_impl 

169 

170 return c_impl