Skip to content
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
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
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,25 @@ Running the tests
PYTHONPATH='.:tests' py.test


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

Note that because of design issues `Python`'s `typing` module, `cloudpickle`
supports pickling type annotations of dynamic functions for `Python` 3.7 and
later. On `Python` 3.4, 3.5 and 3.6, those type annotations will be dropped
silently during pickling (example below):

```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
16 changes: 13 additions & 3 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),
"""This syntax won't work on py2 and pickling annotations
isn't supported for py34 and below.""")
@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_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