Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
6 changes: 6 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
1.2.2
=====

- Revert the change introduced in
([issue #276](https://github.com/cloudpipe/cloudpickle/pull/276))
attempting to pickle functions annotations for Python 3.4 to 3.6. It is not
possible to pickle complex typing constructs for those versions (see
[issue #193]( https://github.com/cloudpipe/cloudpickle/issues/193))

- Fix a bug affecting bound classmethod saving on Python 2.
([issue #288](https://github.com/cloudpipe/cloudpickle/issues/288))

Expand Down
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,23 @@ Running the tests
PYTHONPATH='.:tests' py.test


Note about function Annotations
-------------------------------

Note that because of design issues `Python`'s `typing` module, `cloudpickle` will
not pickle dynamic function annotations on `Python` 3.4, 3.5 and 3.6:

```python
>>> import typing
>>> import cloudpickle
>>> def f(x: typing.Union[list, int]):
... return x
>>> f
<function __main__.f(x:Union[list, int])>
>>> cloudpickle.loads(cloudpickle.dumps(f)) # drops f's annotations
<function __main__.f(x)>
```

History
-------

Expand Down
4 changes: 3 additions & 1 deletion cloudpickle/cloudpickle.py
Original file line number Diff line number Diff line change
Expand Up @@ -747,7 +747,9 @@ def save_function_tuple(self, func):
'doc': func.__doc__,
'_cloudpickle_submodules': submodules
}
if hasattr(func, '__annotations__') and sys.version_info >= (3, 4):
if hasattr(func, '__annotations__') and sys.version_info >= (3, 7):
# Although annotations were added in Python3.4, It is not possible
# to properly pickle them until Python3.7. (See #193)
state['annotations'] = func.__annotations__
if hasattr(func, '__qualname__'):
state['qualname'] = func.__qualname__
Expand Down
14 changes: 12 additions & 2 deletions tests/cloudpickle_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1621,9 +1621,9 @@ def g():

self.assertEqual(f2.__doc__, f.__doc__)

@unittest.skipIf(sys.version_info < (3, 4),
@unittest.skipIf(sys.version_info < (3, 7),
"""This syntax won't work on py2 and pickling annotations
isn't supported for py34 and below.""")
isn't supported for py37 and below.""")
def test_wraps_preserves_function_annotations(self):
from functools import wraps

Expand All @@ -1640,6 +1640,16 @@ def g(x):

self.assertEqual(f2.__annotations__, f.__annotations__)

@unittest.skipIf(sys.version_info < (3, 7),
"""This syntax won't work on py2 and pickling annotations
isn't supported for py37 and below.""")
def test_type_hint(self):
# Try to pickle compound typing constructs. This would typically fail
# on Python < 3.7 (See #193)
import typing
t = typing.Union[list, int]
assert pickle_depickle(t) == t

def test_instance_with_slots(self):
for slots in [["registered_attribute"], "registered_attribute"]:
class ClassWithSlots(object):
Expand Down