/usr/lib/python2.7/dist-packages/apptools/sweet_pickle/__init__.py is in python-apptools 4.3.0-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 | #-----------------------------------------------------------------------------
#
# Copyright (c) 2006 by Enthought, Inc.
# All rights reserved.
#
# Author: Dave Peterson <dpeterson@enthought.com>
#
#-----------------------------------------------------------------------------
""" A pickle framework that supports unpickling of refactored versions of
old classes. Part of the AppTools project of the Enthought Tool Suite.
Beyond refactoring support, there are additional useful capabilities of
this package:
- HasTraits objects are fully pickled when sweet_pickle.dump() or
sweet_pickle.dumps() are called. This means every trait's value
is pickled explicitly. This allows improved self-consistency as
values within unpickled objects correspond to the default trait
values of the instance that was pickled rather than the default
values of the current class definition.
- Multiple updaters can be registered to update state for any version
of a class. This is extremely useful when an instance being
pickled and unpickled is the result of an addition of one or more
Trait Categories to a class. In that case, the Category contributor
can also register a state function to update the Category's traits
through versioning.
We have duplicated the API of the Python 'pickle' module within this
package. Thus, users can simply import sweet_pickle in places where
they previously used pickle or cPickle. For example::
import cPickle ---> import apptools.sweet_pickle as pickle
s = pickle.dumps(obj) s = pickle.dumps(obj)
pickle.loads(s) pickle.loads(s)
Pickles generated by this package *can be* unpickled by standard pickle
or cPickle, though you lose the benefit of the refactoring support during
unpickling.
As a result of the above, this package is a drop-in replacement for the
Python 'pickle' module or 'cPickle' module and should be safe to use even
if you never version or refactor your own classes. In fact, we STRONGLY
RECOMMEND that you use this framework for all of your pickle needs because
you never know when one of the classes you encounter during unpickling has
been versioned or otherwise refactored by someone else.
See module 'pickle' for more basic information about pickling.
The most common way to benefit from the versioning capabilities of this
framework is to register class mappings and state modification functions
with the global updater registry (more detail is below.) However, you may
also choose to explicitly instantiate an Unpickler and provide it with your
own explicit definition of class mappings and state modification functions.
We do not provide any help on the latter at this time.
You can register class mappings and state modification functions with the
global updater registry using the methods provided on the Updater instance
that is the global registry. You can get this instance by calling the
'get_global_registry' function exposed through this package's namespace.
This framework has been designed so that you can register your class
mappings and state modification functions during the import of the module
or package that contained the original class. However, you may also
register your mappings and functions at any point such that the they are
known to the framework prior to, or become known during the attempt to,
unpickle the class they modify.
The framework will call a __setstate__ method on the final target class
of any unpickled instance. It will not call __setstate__ methods on any
beginning or intermediate classes within a chain of class mappings.
A class mapping is used to redirect the unpickling of one class to return
an instantiation of another class. The classes can be in different
modules, and the modules in different packages. Mappings can be chained.
For example, given the mappings::
foo.bar.Bar --> foo.baz.Baz
foo.baz.Baz --> foo.Foo
An attempt to unpickle a foo.bar.Bar would actually generate a foo.Foo
instance.
A state modification function is called during the execution of the
__setstate__ method during unpickling of an object of the type and version
for which it was registered for. The function must accept a single
argument which is a state dictionary and must then return the modified
state dictionary. Additionally, the function should change the version
variable within the state to represent the version the new state
represents. (The framework will assume an increment of one if this is
not done.) The framework ensures that state modification functions
are chained appropriately to convert through multiple versions and/or class
mappings.
Note that refactorings that cause classes to be completed removed from
the source code can be supported, without breaking unpickling of object
hierarchies that include an instace of that class, by adding a mapping
to the Placeholder class in the placeholder module.
"""
##############################################################################
# Implement the Python pickle package API
##############################################################################
# Expose our custom pickler as the standard Unpickler
from versioned_unpickler import VersionedUnpickler as Unpickler
# Use our custom unpickler to load from files
def load(file, max_pass=-1):
return Unpickler(file).load(max_pass)
# Use our custom unpickler to load from strings
def loads(str, max_pass=-1):
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
file = StringIO(str)
return Unpickler(file).load(max_pass)
# We don't customize the Python pickler, though we do use the cPickle module
# for improved performance.
from cPickle import Pickler
# Implement the dump and dumps methods so that all traits in a HasTraits object
# get included in the pickle.
def dump(obj, file, protocol=2):
_flush_traits(obj)
from cPickle import dump as d
return d(obj, file, protocol)
def dumps(obj, protocol=2):
_flush_traits(obj)
from cPickle import dumps as ds
return ds(obj, protocol)
# We don't customize exceptions so just map to the Python pickle package
from pickle import PickleError, PicklingError, UnpicklingError
##############################################################################
# Allow retrieval of the global registry
##############################################################################
from global_registry import get_global_registry
##############################################################################
# Expose our Updater class so users can explicitly create their own.
##############################################################################
from updater import Updater
##############################################################################
# Method to ensure that all traits on a has traits object are included in a
# pickle.
##############################################################################
def _flush_traits(obj):
if hasattr(obj, 'trait_names'):
for name, value in obj.traits().items():
if value.type == 'trait':
try:
getattr(obj, name)
except AttributeError:
pass
### EOF ######################################################################
|