Part of twisted.spread View Source
It does something very much like Pickle
;
however, pickle's main goal seems to be efficiency (both in space and
time); jelly's main goals are security, human readability, and portability
to other environments.
This is how Jelly converts various objects to s-expressions.
Boolean:
True --> ['boolean', 'true']
Integer:
1 --> 1
List:
[1, 2] --> ['list', 1, 2]
String:
"hello" --> "hello"
Float:
2.3 --> 2.3
Dictionary:
{'a': 1, 'b': 'c'} --> ['dictionary', ['b', 'c'], ['a', 1]]
Module:
UserString --> ['module', 'UserString']
Class:
UserString.UserString --> ['class', ['module', 'UserString'], 'UserString']
Function:
string.join --> ['function', 'join', ['module', 'string']]
Instance: s is an instance of UserString.UserString, with a __dict__ {'data': 'hello'}:
["UserString.UserString", ['dictionary', ['data', 'hello']]]
Class Method: UserString.UserString.center:
['method', 'center', ['None'], ['class', ['module', 'UserString'], 'UserString']]
Instance Method: s.center, where s is an instance of UserString.UserString:
['method', 'center', ['instance', ['reference', 1, ['class', ['module', 'UserString'], 'UserString']], ['dictionary', ['data', 'd']]], ['dereference', 1]]
The set
builtin and the sets.Set
class are
serialized to the same thing, and unserialized to set
if
available, else to sets.Set
. It means that there's a
possibility of type switching in the serialization process. The solution is
to always use set
.
The same rule applies for frozenset
and
sets.ImmutableSet
.
Author | Glyph Lefkowitz |
Function | setUnjellyableForClass | Set which local class will represent a remote type. |
Function | setUnjellyableFactoryForClass | Set the factory to construct a remote instance of a type: |
Function | setUnjellyableForClassTree | Set all classes in a module derived from baseClass as
copiers for a corresponding remote class. |
Function | getInstanceState | Utility method to default to 'normal' state rules in serialization. |
Function | setInstanceState | Utility method to default to 'normal' state rules in unserialization. |
Class | Unpersistable | This is an instance of a class that comes back when something couldn't be unpersisted. |
Class | Jellyable | Inherit from me to Jelly yourself directly with the `getStateFor' convenience method. |
Class | Unjellyable | Inherit from me to Unjelly yourself directly with the
setStateFor convenience method. |
Class | InsecureJelly | This exception will be raised when a jelly is deemed `insecure'; e.g. it contains a type, class, or module disallowed by the specified `taster' |
Class | DummySecurityOptions | DummySecurityOptions() -> insecure security options Dummy security options -- this class will allow anything. |
Class | SecurityOptions | This will by default disallow everything, except for 'none'. |
Function | jelly | Serialize to s-expression. |
Function | unjelly | Unserialize from s-expression. |
Function | _newInstance | Make a new instance of a class without calling its __init__ method. Supports both new- and old-style classes. |
Function | _maybeClass | Undocumented |
Class | _Jellier | (Internal) This class manages state for a call to jelly() |
Class | _Unjellier | No class docstring; 5/27 methods documented |
Class | _Dummy | (Internal) Dummy class, used for unserializing instances. |
Class | _DummyNewStyle | (Internal) Dummy class, used for unserializing instances of new-style classes. |
Function | _newDummyLike | Create a new instance like instance . |
Parameters | state | A dict used to update inst.__dict__ or
_NO_STATE to skip this part of initialization. |
Returns | A new instance of cls . |
If you have written a Copyable class that you expect your client to be receiving, write a local "copy" class to represent it, then call:
jellier.setUnjellyableForClass('module.package.Class', MyCopier).
Call this at the module level immediately after its class definition. MyCopier should be a subclass of RemoteCopy.
The classname may be a special tag returned by 'Copyable.getTypeToCopyFor' rather than an actual classname.
This call is also for cached classes, since there will be no overlap. The rules are the same.
jellier.setUnjellyableFactoryForClass('module.package.Class', MyFactory)
Call this at the module level immediately after its class definition.
copyFactory
should return an instance or subclass of RemoteCopy
.
Similar to setUnjellyableForClass
except it uses a factory instead of creating an instance.
baseClass
as
copiers for a corresponding remote class.
When you have a heirarchy of Copyable (or Cacheable) classes on one side, and a mirror structure of Copied (or RemoteCache) classes on the other, use this to setUnjellyableForClass all your Copieds for the Copyables.
Each copyTag (the "classname" argument to getTypeToCopyFor, and what the Copyable's getTypeToCopyFor returns) is formed from adding a prefix to the Copied's class name. The prefix defaults to module.__name__. If you wish the copy tag to consist of solely the classname, pass the empty string ''.
Parameters | module | a module object from which to pull the Copied classes. (passing sys.modules[__name__] might be useful) |
baseClass | the base class from which all your Copied classes derive. | |
prefix | the string prefixed to classnames to form the unjellyableRegistry. |
instance
.
The new instance has the same class and instance dictionary as the given instance.
Returns | The new instance. |
Returns a list which is the serialized representation of an object. An optional 'taster' argument takes a SecurityOptions and will mark any insecure objects as unpersistable rather than serializing them.
Takes an list that was the result from a call to jelly() and unserializes an arbitrary object from it. The optional 'taster' argument, an instance of SecurityOptions, will cause an InsecureJelly exception to be raised if a disallowed type, module, or class attempted to unserialize.