Skip to content

Commit 0a907cc

Browse files
authored
More post-Python 2 cleanups (#345)
1 parent b867f0e commit 0a907cc

File tree

3 files changed

+29
-95
lines changed

3 files changed

+29
-95
lines changed

cloudpickle/cloudpickle.py

Lines changed: 23 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -60,18 +60,14 @@
6060
import weakref
6161
import uuid
6262
import threading
63+
from enum import Enum
6364

6465
from pickle import _Pickler as Pickler
6566
from pickle import _getattribute
6667
from io import BytesIO
6768
from importlib._bootstrap import _find_spec
6869

6970

70-
try:
71-
from enum import Enum
72-
except ImportError:
73-
Enum = None
74-
7571
# cloudpickle is meant for inter process communication: we expect all
7672
# communicating processes to run the same Python version hence we favor
7773
# communication speed over compatibility:
@@ -580,6 +576,7 @@ def save_dynamic_class(self, obj):
580576

581577
# If type overrides __dict__ as a property, include it in the type
582578
# kwargs. In Python 2, we can't set this attribute after construction.
579+
# XXX: can this ever happen in Python 3? If so add a test.
583580
__dict__ = clsdict.pop('__dict__', None)
584581
if isinstance(__dict__, property):
585582
type_kwargs['__dict__'] = __dict__
@@ -786,51 +783,6 @@ def save_instancemethod(self, obj):
786783

787784
dispatch[types.MethodType] = save_instancemethod
788785

789-
def save_inst(self, obj):
790-
"""Inner logic to save instance. Based off pickle.save_inst"""
791-
cls = obj.__class__
792-
793-
# Try the dispatch table (pickle module doesn't do it)
794-
f = self.dispatch.get(cls)
795-
if f:
796-
f(self, obj) # Call unbound method with explicit self
797-
return
798-
799-
memo = self.memo
800-
write = self.write
801-
save = self.save
802-
803-
if hasattr(obj, '__getinitargs__'):
804-
args = obj.__getinitargs__()
805-
len(args) # XXX Assert it's a sequence
806-
pickle._keep_alive(args, memo)
807-
else:
808-
args = ()
809-
810-
write(pickle.MARK)
811-
812-
if self.bin:
813-
save(cls)
814-
for arg in args:
815-
save(arg)
816-
write(pickle.OBJ)
817-
else:
818-
for arg in args:
819-
save(arg)
820-
write(pickle.INST + cls.__module__ + '\n' + cls.__name__ + '\n')
821-
822-
self.memoize(obj)
823-
824-
try:
825-
getstate = obj.__getstate__
826-
except AttributeError:
827-
stuff = obj.__dict__
828-
else:
829-
stuff = getstate()
830-
pickle._keep_alive(stuff, memo)
831-
save(stuff)
832-
write(pickle.BUILD)
833-
834786
def save_property(self, obj):
835787
# properties not correctly saved in python
836788
self.save_reduce(property, (obj.fget, obj.fset, obj.fdel, obj.__doc__),
@@ -924,11 +876,7 @@ def save_ellipsis(self, obj):
924876
def save_not_implemented(self, obj):
925877
self.save_reduce(_gen_not_implemented, ())
926878

927-
try: # Python 2
928-
dispatch[file] = save_file
929-
except NameError: # Python 3 # pragma: no branch
930-
dispatch[io.TextIOWrapper] = save_file
931-
879+
dispatch[io.TextIOWrapper] = save_file
932880
dispatch[type(Ellipsis)] = save_ellipsis
933881
dispatch[type(NotImplemented)] = save_not_implemented
934882

@@ -1241,41 +1189,25 @@ def _is_dynamic(module):
12411189
if hasattr(module, '__file__'):
12421190
return False
12431191

1244-
if hasattr(module, '__spec__'):
1245-
if module.__spec__ is not None:
1246-
return False
1247-
1248-
# In PyPy, Some built-in modules such as _codecs can have their
1249-
# __spec__ attribute set to None despite being imported. For such
1250-
# modules, the ``_find_spec`` utility of the standard library is used.
1251-
parent_name = module.__name__.rpartition('.')[0]
1252-
if parent_name: # pragma: no cover
1253-
# This code handles the case where an imported package (and not
1254-
# module) remains with __spec__ set to None. It is however untested
1255-
# as no package in the PyPy stdlib has __spec__ set to None after
1256-
# it is imported.
1257-
try:
1258-
parent = sys.modules[parent_name]
1259-
except KeyError:
1260-
msg = "parent {!r} not in sys.modules"
1261-
raise ImportError(msg.format(parent_name))
1262-
else:
1263-
pkgpath = parent.__path__
1264-
else:
1265-
pkgpath = None
1266-
return _find_spec(module.__name__, pkgpath, module) is None
1192+
if module.__spec__ is not None:
1193+
return False
12671194

1268-
else:
1269-
# Backward compat for Python 2
1270-
import imp
1195+
# In PyPy, Some built-in modules such as _codecs can have their
1196+
# __spec__ attribute set to None despite being imported. For such
1197+
# modules, the ``_find_spec`` utility of the standard library is used.
1198+
parent_name = module.__name__.rpartition('.')[0]
1199+
if parent_name: # pragma: no cover
1200+
# This code handles the case where an imported package (and not
1201+
# module) remains with __spec__ set to None. It is however untested
1202+
# as no package in the PyPy stdlib has __spec__ set to None after
1203+
# it is imported.
12711204
try:
1272-
path = None
1273-
for part in module.__name__.split('.'):
1274-
if path is not None:
1275-
path = [path]
1276-
f, path, description = imp.find_module(part, path)
1277-
if f is not None:
1278-
f.close()
1279-
except ImportError:
1280-
return True
1281-
return False
1205+
parent = sys.modules[parent_name]
1206+
except KeyError:
1207+
msg = "parent {!r} not in sys.modules"
1208+
raise ImportError(msg.format(parent_name))
1209+
else:
1210+
pkgpath = parent.__path__
1211+
else:
1212+
pkgpath = None
1213+
return _find_spec(module.__name__, pkgpath, module) is None

dev-requirements.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ flake8
33
pytest
44
pytest-cov
55
psutil
6+
# To be able to test tornado coroutines
7+
tornado
8+
# To be able to test numpy specific things
9+
# but do not build numpy from source on Python nightly
10+
numpy; python_version <= '3.8'
611
# Code coverage uploader for Travis:
712
codecov
813
coverage

tests/cloudpickle_test.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import unittest
2222
import weakref
2323
import os
24+
import enum
2425

2526
import pytest
2627

@@ -1855,8 +1856,6 @@ def test_dataclass(self):
18551856
assert data.x == pickle_depickle(data, protocol=self.protocol).x == 42
18561857

18571858
def test_locally_defined_enum(self):
1858-
enum = pytest.importorskip("enum")
1859-
18601859
class StringEnum(str, enum.Enum):
18611860
"""Enum when all members are also (and must be) strings"""
18621861

@@ -1886,7 +1885,6 @@ def is_green(self):
18861885
assert green3 is Color.GREEN
18871886

18881887
def test_locally_defined_intenum(self):
1889-
enum = pytest.importorskip("enum")
18901888
# Try again with a IntEnum defined with the functional API
18911889
DynamicColor = enum.IntEnum("Color", {"RED": 1, "GREEN": 2, "BLUE": 3})
18921890

@@ -1900,7 +1898,6 @@ def test_locally_defined_intenum(self):
19001898
assert ClonedDynamicColor is DynamicColor
19011899

19021900
def test_interactively_defined_enum(self):
1903-
pytest.importorskip("enum")
19041901
code = """if __name__ == "__main__":
19051902
from enum import Enum
19061903
from testutils import subprocess_worker

0 commit comments

Comments
 (0)