|
102 | 102 | PY2 = False |
103 | 103 | from importlib._bootstrap import _find_spec |
104 | 104 |
|
105 | | -# XXX: This cache cannot be a WeakKeyDictionary, because sometimes, cloudpickle |
106 | | -# misclassifies a builtin pypy function as dynamic, and thus tries to extract |
107 | | -# the globals of its underlying builtin-code. However, builtin-code objects |
108 | | -# cannot be weak-referenced (hence the if-else clause below). |
109 | | -# Note that the root cause of cloudpickle misclassification of builtin |
110 | | -# functions is PyPy flaky support of __qualname__ attributes in v3.5. This |
111 | | -# guard can be removed by either spotting more proactively builtin pypy |
112 | | -# functions before trying to save them as dynamic, or simply after support for |
113 | | -# pypy3.5 is dropped. |
114 | | -_extract_code_globals_cache = ( |
115 | | - weakref.WeakKeyDictionary() |
116 | | - if not hasattr(sys, "pypy_version_info") |
117 | | - else {}) |
118 | | - |
| 105 | +_extract_code_globals_cache = weakref.WeakKeyDictionary() |
119 | 106 |
|
120 | 107 |
|
121 | 108 | def _ensure_tracking(class_def): |
@@ -216,24 +203,19 @@ def _extract_code_globals(co): |
216 | 203 | """ |
217 | 204 | out_names = _extract_code_globals_cache.get(co) |
218 | 205 | if out_names is None: |
219 | | - try: |
220 | | - names = co.co_names |
221 | | - except AttributeError: |
222 | | - # PyPy "builtin-code" object |
223 | | - out_names = set() |
224 | | - else: |
225 | | - out_names = {names[oparg] for _, oparg in _walk_global_ops(co)} |
226 | | - |
227 | | - # Declaring a function inside another one using the "def ..." |
228 | | - # syntax generates a constant code object corresonding to the one |
229 | | - # of the nested function's As the nested function may itself need |
230 | | - # global variables, we need to introspect its code, extract its |
231 | | - # globals, (look for code object in it's co_consts attribute..) and |
232 | | - # add the result to code_globals |
233 | | - if co.co_consts: |
234 | | - for const in co.co_consts: |
235 | | - if isinstance(const, types.CodeType): |
236 | | - out_names |= _extract_code_globals(const) |
| 206 | + names = co.co_names |
| 207 | + out_names = {names[oparg] for _, oparg in _walk_global_ops(co)} |
| 208 | + |
| 209 | + # Declaring a function inside another one using the "def ..." |
| 210 | + # syntax generates a constant code object corresonding to the one |
| 211 | + # of the nested function's As the nested function may itself need |
| 212 | + # global variables, we need to introspect its code, extract its |
| 213 | + # globals, (look for code object in it's co_consts attribute..) and |
| 214 | + # add the result to code_globals |
| 215 | + if co.co_consts: |
| 216 | + for const in co.co_consts: |
| 217 | + if isinstance(const, types.CodeType): |
| 218 | + out_names |= _extract_code_globals(const) |
237 | 219 |
|
238 | 220 | _extract_code_globals_cache[co] = out_names |
239 | 221 |
|
@@ -803,28 +785,6 @@ def save_function_tuple(self, func): |
803 | 785 | write(pickle.TUPLE) |
804 | 786 | write(pickle.REDUCE) # applies _fill_function on the tuple |
805 | 787 |
|
806 | | - _extract_code_globals_cache = weakref.WeakKeyDictionary() |
807 | | - |
808 | | - @classmethod |
809 | | - def extract_code_globals(cls, co): |
810 | | - """ |
811 | | - Find all globals names read or written to by codeblock co |
812 | | - """ |
813 | | - out_names = cls._extract_code_globals_cache.get(co) |
814 | | - if out_names is None: |
815 | | - names = co.co_names |
816 | | - out_names = {names[oparg] for _, oparg in _walk_global_ops(co)} |
817 | | - |
818 | | - # see if nested function have any global refs |
819 | | - if co.co_consts: |
820 | | - for const in co.co_consts: |
821 | | - if isinstance(const, types.CodeType): |
822 | | - out_names |= cls.extract_code_globals(const) |
823 | | - |
824 | | - cls._extract_code_globals_cache[co] = out_names |
825 | | - |
826 | | - return out_names |
827 | | - |
828 | 788 | def extract_func_data(self, func): |
829 | 789 | """ |
830 | 790 | Turn the function into a tuple of data necessary to recreate it: |
|
0 commit comments