Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FIX pickling for ABC in python3.7 #189

Merged
merged 7 commits into from
Aug 23, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
language: python
sudo: false
python:
- "2.7"
- "3.4"
- "3.5"
- "3.6"
- "pypy"

matrix:
include:
- python: 2.7
- python: 3.5
- python: 3.6
- python: 3.7
sudo: required
dist: xenial
- python: "pypy"


# This disables sudo, but makes builds start much faster
# See http://blog.travis-ci.com/2014-12-17-faster-builds-with-container-based-infrastructure/
sudo: false
before_install: bash ./ci/before_install.sh
install:
- if [[ $TRAVIS_PYTHON_VERSION != 'pypy'* ]]; then source activate testenv; fi
Expand Down
5 changes: 3 additions & 2 deletions ci/before_install.sh
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
#!/bin/bash

# if python version is not PyPY, then install miniconda
if [[ $TRAVIS_PYTHON_VERSION != 'pypy'* ]]
if [[ $TRAVIS_PYTHON_VERSION != 'pypy'* && $TRAVIS_PYTHON_VERSION != "3.7" ]]
then

# Escape standard Travis virtualenv
deactivate
# See: http://conda.pydata.org/docs/travis.html
Expand All @@ -14,4 +15,4 @@ then
conda update -q conda
conda info -a
conda create -q -n testenv python=$TRAVIS_PYTHON_VERSION numpy scipy pip
fi
fi
19 changes: 18 additions & 1 deletion cloudpickle/cloudpickle.py
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,15 @@ def save_dynamic_class(self, obj):
clsdict = dict(obj.__dict__) # copy dict proxy to a dict
clsdict.pop('__weakref__', None)

# For ABCMeta in python3.7+, remove _abc_impl as it is not picklable.
# This is a fix which breaks the cache but this only makes the first
# calls to issubclass slower.
if "_abc_impl" in clsdict:
import abc
(registry, _, _, _) = abc._get_dump(obj)
clsdict["_abc_impl"] = [subclass_weakref()
for subclass_weakref in registry]

# On PyPy, __doc__ is a readonly attribute, so we need to include it in
# the initial skeleton class. This is safe because we know that the
# doc can't participate in a cycle with the original class.
Expand Down Expand Up @@ -1082,8 +1091,16 @@ def _rehydrate_skeleton_class(skeleton_class, class_dict):

See CloudPickler.save_dynamic_class for more info.
"""
registry = None
for attrname, attr in class_dict.items():
setattr(skeleton_class, attrname, attr)
if attrname == "_abc_impl":
registry = attr
else:
setattr(skeleton_class, attrname, attr)
if registry is not None:
for subclass in registry:
skeleton_class.register(subclass)

return skeleton_class


Expand Down
7 changes: 7 additions & 0 deletions tests/cloudpickle_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -655,11 +655,18 @@ class ConcreteClass(AbstractClass):
def foo(self):
return 'it works!'

# This class is local so we can safely register tuple in it to verify
# the unpickled class also register tuple.
AbstractClass.register(tuple)

depickled_base = pickle_depickle(AbstractClass, protocol=self.protocol)
depickled_class = pickle_depickle(ConcreteClass,
protocol=self.protocol)
depickled_instance = pickle_depickle(ConcreteClass())

assert issubclass(tuple, AbstractClass)
assert issubclass(tuple, depickled_base)

self.assertEqual(depickled_class().foo(), 'it works!')
self.assertEqual(depickled_instance.foo(), 'it works!')

Expand Down
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[tox]
envlist = py27, py34, py35, py36, pypy, pypy3
envlist = py27, py34, py35, py36, py37, pypy, pypy3

[testenv]
deps = -rdev-requirements.txt
Expand Down