Skip to content

Commit 5f6defe

Browse files
committed
CLN rebase with cloudpipe#278
1 parent a712557 commit 5f6defe

File tree

3 files changed

+20
-57
lines changed

3 files changed

+20
-57
lines changed

cloudpickle/cloudpickle.py

Lines changed: 14 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -102,20 +102,7 @@
102102
PY2 = False
103103
from importlib._bootstrap import _find_spec
104104

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()
119106

120107

121108
def _ensure_tracking(class_def):
@@ -216,24 +203,19 @@ def _extract_code_globals(co):
216203
"""
217204
out_names = _extract_code_globals_cache.get(co)
218205
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)
237219

238220
_extract_code_globals_cache[co] = out_names
239221

@@ -803,28 +785,6 @@ def save_function_tuple(self, func):
803785
write(pickle.TUPLE)
804786
write(pickle.REDUCE) # applies _fill_function on the tuple
805787

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-
828788
def extract_func_data(self, func):
829789
"""
830790
Turn the function into a tuple of data necessary to recreate it:

cloudpickle/cloudpickle_fast.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -485,9 +485,12 @@ def _function_reduce(self, obj):
485485
obj from an attribute lookup of a file-backed module. If this check
486486
fails, then a custom reducer is called.
487487
"""
488-
if not _is_global(obj):
488+
# There no special handling for builtin pypy functions like in
489+
# cloudpickle.py because cloudpickle_fast is CPython-specific.
490+
if _is_global(obj):
491+
return NotImplemented
492+
else:
489493
return self._dynamic_function_reduce(obj)
490-
return NotImplemented
491494

492495
def _function_getnewargs(self, func):
493496
code = func.__code__

tests/cloudpickle_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1829,7 +1829,7 @@ def inner_function():
18291829
return _TEST_GLOBAL_VARIABLE
18301830
return inner_function
18311831

1832-
globals_ = cloudpickle.CloudPickler.extract_code_globals(
1832+
globals_ = cloudpickle.cloudpickle._extract_code_globals(
18331833
function_factory.__code__)
18341834
assert globals_ == {'_TEST_GLOBAL_VARIABLE'}
18351835

0 commit comments

Comments
 (0)