[Python-modules-commits] [toolz] 01/06: Import toolz_0.8.2.orig.tar.gz

Diane Trout diane at moszumanska.debian.org
Thu Dec 22 04:55:23 UTC 2016


This is an automated email from the git hooks/post-receive script.

diane pushed a commit to branch master
in repository toolz.

commit 08b9e40c113500d4a0d287ff5f093daefe61f923
Author: Diane Trout <diane at ghic.org>
Date:   Wed Dec 21 11:05:14 2016 -0800

    Import toolz_0.8.2.orig.tar.gz
---
 conda.recipe/meta.yaml            |   2 +-
 toolz/__init__.py                 |   2 +-
 toolz/functoolz.py                |  46 +++++++++----
 toolz/tests/test_functoolz.py     |  12 +++-
 toolz/tests/test_serialization.py | 138 ++++++++++++++++++++++++++++++++++++++
 5 files changed, 183 insertions(+), 17 deletions(-)

diff --git a/conda.recipe/meta.yaml b/conda.recipe/meta.yaml
index 96e4208..c94d3b1 100644
--- a/conda.recipe/meta.yaml
+++ b/conda.recipe/meta.yaml
@@ -1,6 +1,6 @@
 package:
     name: toolz
-    version: "0.8.1"
+    version: "0.8.2"
 
 build:
     number: {{environ.get('BINSTAR_BUILD', 1)}}
diff --git a/toolz/__init__.py b/toolz/__init__.py
index 1f4342c..86dd490 100644
--- a/toolz/__init__.py
+++ b/toolz/__init__.py
@@ -19,4 +19,4 @@ comp = compose
 
 functoolz._sigs.create_signature_registry()
 
-__version__ = '0.8.1'
+__version__ = '0.8.2'
diff --git a/toolz/functoolz.py b/toolz/functoolz.py
index ed37c0a..2bd80a4 100644
--- a/toolz/functoolz.py
+++ b/toolz/functoolz.py
@@ -200,6 +200,8 @@ class curry(object):
 
         self.__doc__ = getattr(func, '__doc__', None)
         self.__name__ = getattr(func, '__name__', '<curry>')
+        self.__module__ = getattr(func, '__module__', None)
+        self.__qualname__ = getattr(func, '__qualname__', None)
         self._sigspec = None
         self._has_unknown_args = None
 
@@ -324,27 +326,43 @@ class curry(object):
     def __reduce__(self):
         func = self.func
         modname = getattr(func, '__module__', None)
-        funcname = getattr(func, '__name__', None)
-        if modname and funcname:
-            module = import_module(modname)
-            obj = getattr(module, funcname, None)
-            if obj is self:
-                return funcname
-            elif isinstance(obj, curry) and obj.func is func:
-                func = '%s.%s' % (modname, funcname)
+        qualname = getattr(func, '__qualname__', None)
+        if qualname is None:  # pragma: py3 no cover
+            qualname = getattr(func, '__name__', None)
+        is_decorated = None
+        if modname and qualname:
+            attrs = []
+            obj = import_module(modname)
+            for attr in qualname.split('.'):
+                if isinstance(obj, curry):  # pragma: py2 no cover
+                    attrs.append('func')
+                    obj = obj.func
+                obj = getattr(obj, attr, None)
+                if obj is None:
+                    break
+                attrs.append(attr)
+            if isinstance(obj, curry) and obj.func is func:
+                is_decorated = obj is self
+                qualname = '.'.join(attrs)
+                func = '%s:%s' % (modname, qualname)
 
         # functools.partial objects can't be pickled
         userdict = tuple((k, v) for k, v in self.__dict__.items()
-                         if k != '_partial')
-        state = (type(self), func, self.args, self.keywords, userdict)
+                         if k not in ('_partial', '_sigspec'))
+        state = (type(self), func, self.args, self.keywords, userdict,
+                 is_decorated)
         return (_restore_curry, state)
 
 
-def _restore_curry(cls, func, args, kwargs, userdict):
+def _restore_curry(cls, func, args, kwargs, userdict, is_decorated):
     if isinstance(func, str):
-        modname, funcname = func.rsplit('.', 1)
-        module = import_module(modname)
-        func = getattr(module, funcname).func
+        modname, qualname = func.rsplit(':', 1)
+        obj = import_module(modname)
+        for attr in qualname.split('.'):
+            obj = getattr(obj, attr)
+        if is_decorated:
+            return obj
+        func = obj.func
     obj = cls(func, *args, **(kwargs or {}))
     obj.__dict__.update(userdict)
     return obj
diff --git a/toolz/tests/test_functoolz.py b/toolz/tests/test_functoolz.py
index 6c7cb0e..deda606 100644
--- a/toolz/tests/test_functoolz.py
+++ b/toolz/tests/test_functoolz.py
@@ -285,16 +285,26 @@ def test_curry_attributes_readonly():
 def test_curry_attributes_writable():
     def foo(a, b, c=1):
         return a + b + c
-
+    foo.__qualname__ = 'this.is.foo'
     f = curry(foo, 1, c=2)
+    assert f.__qualname__ == 'this.is.foo'
     f.__name__ = 'newname'
     f.__doc__ = 'newdoc'
+    f.__module__ = 'newmodule'
+    f.__qualname__ = 'newqualname'
     assert f.__name__ == 'newname'
     assert f.__doc__ == 'newdoc'
+    assert f.__module__ == 'newmodule'
+    assert f.__qualname__ == 'newqualname'
     if hasattr(f, 'func_name'):
         assert f.__name__ == f.func_name
 
 
+def test_curry_module():
+    from toolz.curried.exceptions import merge
+    assert merge.__module__ == 'toolz.curried.exceptions'
+
+
 def test_curry_comparable():
     def foo(a, b, c=1):
         return a + b + c
diff --git a/toolz/tests/test_serialization.py b/toolz/tests/test_serialization.py
index a49f7a8..afee159 100644
--- a/toolz/tests/test_serialization.py
+++ b/toolz/tests/test_serialization.py
@@ -1,6 +1,9 @@
 from toolz import *
 import toolz
+import toolz.curried.exceptions
 import pickle
+from toolz.compatibility import PY3, PY33, PY34
+from toolz.utils import raises
 
 
 def test_compose():
@@ -55,3 +58,138 @@ def test_flip():
     g1 = flip(f)(1)
     g2 = pickle.loads(pickle.dumps(g1))
     assert g1(2) == g2(2) == f(2, 1)
+
+
+def test_curried_exceptions():
+    # This tests a global curried object that isn't defined in toolz.functoolz
+    merge = pickle.loads(pickle.dumps(toolz.curried.exceptions.merge))
+    assert merge is toolz.curried.exceptions.merge
+
+
+ at toolz.curry
+class GlobalCurried(object):
+    def __init__(self, x, y):
+        self.x = x
+        self.y = y
+
+    @toolz.curry
+    def f1(self, a, b):
+        return self.x + self.y + a + b
+
+    def g1(self):
+        pass
+
+    def __reduce__(self):
+        """Allow us to serialize instances of GlobalCurried"""
+        return (GlobalCurried, (self.x, self.y))
+
+    @toolz.curry
+    class NestedCurried(object):
+        def __init__(self, x, y):
+            self.x = x
+            self.y = y
+
+        @toolz.curry
+        def f2(self, a, b):
+            return self.x + self.y + a + b
+
+        def g2(self):
+            pass
+
+        def __reduce__(self):
+            """Allow us to serialize instances of NestedCurried"""
+            return (GlobalCurried.NestedCurried, (self.x, self.y))
+
+    class Nested(object):
+        def __init__(self, x, y):
+            self.x = x
+            self.y = y
+
+        @toolz.curry
+        def f3(self, a, b):
+            return self.x + self.y + a + b
+
+        def g3(self):
+            pass
+
+
+def test_curried_qualname():
+    if not PY3:
+        return
+
+    def preserves_identity(obj):
+        return pickle.loads(pickle.dumps(obj)) is obj
+
+    assert preserves_identity(GlobalCurried)
+    assert preserves_identity(GlobalCurried.func.f1)
+    assert preserves_identity(GlobalCurried.func.NestedCurried)
+    assert preserves_identity(GlobalCurried.func.NestedCurried.func.f2)
+    assert preserves_identity(GlobalCurried.func.Nested.f3)
+
+    global_curried1 = GlobalCurried(1)
+    global_curried2 = pickle.loads(pickle.dumps(global_curried1))
+    assert global_curried1 is not global_curried2
+    assert global_curried1(2).f1(3, 4) == global_curried2(2).f1(3, 4) == 10
+
+    global_curried3 = global_curried1(2)
+    global_curried4 = pickle.loads(pickle.dumps(global_curried3))
+    assert global_curried3 is not global_curried4
+    assert global_curried3.f1(3, 4) == global_curried4.f1(3, 4) == 10
+
+    func1 = global_curried1(2).f1(3)
+    func2 = pickle.loads(pickle.dumps(func1))
+    assert func1 is not func2
+    assert func1(4) == func2(4) == 10
+
+    nested_curried1 = GlobalCurried.func.NestedCurried(1)
+    nested_curried2 = pickle.loads(pickle.dumps(nested_curried1))
+    assert nested_curried1 is not nested_curried2
+    assert nested_curried1(2).f2(3, 4) == nested_curried2(2).f2(3, 4) == 10
+
+    # If we add `curry.__getattr__` forwarding, the following tests will pass
+
+    # if not PY33 and not PY34:
+    #     assert preserves_identity(GlobalCurried.func.g1)
+    #     assert preserves_identity(GlobalCurried.func.NestedCurried.func.g2)
+    #     assert preserves_identity(GlobalCurried.func.Nested)
+    #     assert preserves_identity(GlobalCurried.func.Nested.g3)
+    #
+    # # Rely on curry.__getattr__
+    # assert preserves_identity(GlobalCurried.f1)
+    # assert preserves_identity(GlobalCurried.NestedCurried)
+    # assert preserves_identity(GlobalCurried.NestedCurried.f2)
+    # assert preserves_identity(GlobalCurried.Nested.f3)
+    # if not PY33 and not PY34:
+    #     assert preserves_identity(GlobalCurried.g1)
+    #     assert preserves_identity(GlobalCurried.NestedCurried.g2)
+    #     assert preserves_identity(GlobalCurried.Nested)
+    #     assert preserves_identity(GlobalCurried.Nested.g3)
+    #
+    # nested_curried3 = nested_curried1(2)
+    # nested_curried4 = pickle.loads(pickle.dumps(nested_curried3))
+    # assert nested_curried3 is not nested_curried4
+    # assert nested_curried3.f2(3, 4) == nested_curried4.f2(3, 4) == 10
+    #
+    # func1 = nested_curried1(2).f2(3)
+    # func2 = pickle.loads(pickle.dumps(func1))
+    # assert func1 is not func2
+    # assert func1(4) == func2(4) == 10
+    #
+    # if not PY33 and not PY34:
+    #     nested3 = GlobalCurried.func.Nested(1, 2)
+    #     nested4 = pickle.loads(pickle.dumps(nested3))
+    #     assert nested3 is not nested4
+    #     assert nested3.f3(3, 4) == nested4.f3(3, 4) == 10
+    #
+    #     func1 = nested3.f3(3)
+    #     func2 = pickle.loads(pickle.dumps(func1))
+    #     assert func1 is not func2
+    #     assert func1(4) == func2(4) == 10
+
+
+def test_curried_bad_qualname():
+    @toolz.curry
+    class Bad(object):
+        __qualname__ = 'toolz.functoolz.not.a.valid.path'
+
+    assert raises(pickle.PicklingError, lambda: pickle.dumps(Bad))

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/toolz.git



More information about the Python-modules-commits mailing list