summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Madden <jamadden@gmail.com>2020-10-23 15:32:46 -0500
committerJason Madden <jamadden@gmail.com>2020-10-23 15:32:46 -0500
commit34085388b34738c094b30a65c7d0abbcd05ee421 (patch)
tree570a9303b5fba27d036a81dc8d9e62ef8ede3871
parent2ae267b9101efef4913d4875b8fd2c3ffa74beb8 (diff)
downloadzope-interface-doc_persistency_equality#218.tar.gz
Add more persistence examples.doc_persistency_equality#218
-rw-r--r--docs/README.rst56
1 files changed, 56 insertions, 0 deletions
diff --git a/docs/README.rst b/docs/README.rst
index 42576bc..bfb7712 100644
--- a/docs/README.rst
+++ b/docs/README.rst
@@ -1135,6 +1135,22 @@ old one?
...
_pickle.PicklingError: Can't pickle <class 'Foo'>: it's not the same object as builtins.Foo
+A consequence of this is that only one object of the given name can be
+defined and pickled at a time. If we were to try to define a new ``Foo``
+class (remembering that normally the ``sys.modules[__name__].Foo =``
+line is automatic), we still cannot pickle the old one:
+
+.. doctest::
+
+ >>> orig_Foo = Foo
+ >>> class Foo(object):
+ ... pass
+ >>> sys.modules[__name__].Foo = Foo # XXX, see below
+ >>> pickle.dumps(orig_Foo)
+ Traceback (most recent call last):
+ ...
+ _pickle.PicklingError: Can't pickle <class 'Foo'>: it's not the same object as builtins.Foo
+
Or what if there simply is no global object?
.. doctest::
@@ -1187,6 +1203,46 @@ the same principle as persistence. Interfaces are treated like "global
objects" and sort and hash using the same information a *reference* to
them would: their ``__name__`` and ``__module__``.
+In this way, hashing, equality and sorting are consistent with each
+other, and consistent with pickling:
+
+.. doctest::
+
+ >>> class IFoo(zope.interface.Interface):
+ ... pass
+ >>> sys.modules[__name__].IFoo = IFoo
+ >>> f1 = IFoo
+ >>> pickled_f1 = pickle.dumps(f1)
+ >>> class IFoo(zope.interface.Interface):
+ ... pass
+ >>> sys.modules[__name__].IFoo = IFoo
+ >>> IFoo == f1
+ True
+ >>> unpickled_f1 = pickle.loads(pickled_f1)
+ >>> unpickled_f1 == IFoo == f1
+ True
+
+This isn't quite the case for classes; note how ``f1`` wasn't equal to
+``Foo`` before pickling, but the unpickled value is:
+
+.. doctest::
+
+ >>> class Foo(object):
+ ... pass
+ >>> sys.modules[__name__].Foo = Foo
+ >>> f1 = Foo
+ >>> pickled_f1 = pickle.dumps(Foo)
+ >>> class Foo(object):
+ ... pass
+ >>> sys.modules[__name__].Foo = Foo
+ >>> f1 == Foo
+ False
+ >>> unpickled_f1 = pickle.loads(pickled_f1)
+ >>> unpickled_f1 == Foo # Surprise!
+ True
+ >>> unpickled_f1 == f1
+ False
+
For more information, and some rare potential pitfalls, see
:ref:`spec_eq_hash`.