Index: third_party/twisted_8_1/twisted/persisted/aot.py |
diff --git a/third_party/twisted_8_1/twisted/persisted/aot.py b/third_party/twisted_8_1/twisted/persisted/aot.py |
deleted file mode 100644 |
index 90e0e3732e7a98e60ba835c17facde85e6d01fc8..0000000000000000000000000000000000000000 |
--- a/third_party/twisted_8_1/twisted/persisted/aot.py |
+++ /dev/null |
@@ -1,560 +0,0 @@ |
-# -*- test-case-name: twisted.test.test_persisted -*- |
- |
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories. |
-# See LICENSE for details. |
- |
- |
- |
-""" |
-AOT: Abstract Object Trees |
-The source-code-marshallin'est abstract-object-serializin'est persister |
-this side of Marmalade! |
-""" |
- |
-import types, new, string, copy_reg, tokenize, re |
- |
-from twisted.python import reflect, log |
-from twisted.persisted import crefutil |
- |
-########################### |
-# Abstract Object Classes # |
-########################### |
- |
-#"\0" in a getSource means "insert variable-width indention here". |
-#see `indentify'. |
- |
-class Named: |
- def __init__(self, name): |
- self.name = name |
- |
-class Class(Named): |
- def getSource(self): |
- return "Class(%r)" % self.name |
- |
-class Function(Named): |
- def getSource(self): |
- return "Function(%r)" % self.name |
- |
-class Module(Named): |
- def getSource(self): |
- return "Module(%r)" % self.name |
- |
- |
-class InstanceMethod: |
- def __init__(self, name, klass, inst): |
- if not (isinstance(inst, Ref) or isinstance(inst, Instance) or isinstance(inst, Deref)): |
- raise TypeError("%s isn't an Instance, Ref, or Deref!" % inst) |
- self.name = name |
- self.klass = klass |
- self.instance = inst |
- |
- def getSource(self): |
- return "InstanceMethod(%r, %r, \n\0%s)" % (self.name, self.klass, prettify(self.instance)) |
- |
- |
-class _NoStateObj: |
- pass |
-NoStateObj = _NoStateObj() |
- |
-_SIMPLE_BUILTINS = [ |
- types.StringType, types.UnicodeType, types.IntType, types.FloatType, |
- types.ComplexType, types.LongType, types.NoneType, types.SliceType, |
- types.EllipsisType] |
- |
-try: |
- _SIMPLE_BUILTINS.append(types.BooleanType) |
-except AttributeError: |
- pass |
- |
-class Instance: |
- def __init__(self, className, __stateObj__=NoStateObj, **state): |
- if not isinstance(className, types.StringType): |
- raise TypeError("%s isn't a string!" % className) |
- self.klass = className |
- if __stateObj__ is not NoStateObj: |
- self.state = __stateObj__ |
- self.stateIsDict = 0 |
- else: |
- self.state = state |
- self.stateIsDict = 1 |
- |
- def getSource(self): |
- #XXX make state be foo=bar instead of a dict. |
- if self.stateIsDict: |
- stateDict = self.state |
- elif isinstance(self.state, Ref) and isinstance(self.state.obj, types.DictType): |
- stateDict = self.state.obj |
- else: |
- stateDict = None |
- if stateDict is not None: |
- try: |
- return "Instance(%r, %s)" % (self.klass, dictToKW(stateDict)) |
- except NonFormattableDict: |
- return "Instance(%r, %s)" % (self.klass, prettify(stateDict)) |
- return "Instance(%r, %s)" % (self.klass, prettify(self.state)) |
- |
-class Ref: |
- |
- def __init__(self, *args): |
- #blargh, lame. |
- if len(args) == 2: |
- self.refnum = args[0] |
- self.obj = args[1] |
- elif not args: |
- self.refnum = None |
- self.obj = None |
- |
- def setRef(self, num): |
- if self.refnum: |
- raise ValueError("Error setting id %s, I already have %s" % (num, self.refnum)) |
- self.refnum = num |
- |
- def setObj(self, obj): |
- if self.obj: |
- raise ValueError("Error setting obj %s, I already have %s" % (obj, self.obj)) |
- self.obj = obj |
- |
- def getSource(self): |
- if self.obj is None: |
- raise RuntimeError("Don't try to display me before setting an object on me!") |
- if self.refnum: |
- return "Ref(%d, \n\0%s)" % (self.refnum, prettify(self.obj)) |
- return prettify(self.obj) |
- |
- |
-class Deref: |
- def __init__(self, num): |
- self.refnum = num |
- |
- def getSource(self): |
- return "Deref(%d)" % self.refnum |
- |
- __repr__ = getSource |
- |
- |
-class Copyreg: |
- def __init__(self, loadfunc, state): |
- self.loadfunc = loadfunc |
- self.state = state |
- |
- def getSource(self): |
- return "Copyreg(%r, %s)" % (self.loadfunc, prettify(self.state)) |
- |
- |
- |
-############### |
-# Marshalling # |
-############### |
- |
- |
-def getSource(ao): |
- """Pass me an AO, I'll return a nicely-formatted source representation.""" |
- return indentify("app = " + prettify(ao)) |
- |
- |
-class NonFormattableDict(Exception): |
- """A dictionary was not formattable. |
- """ |
- |
-r = re.compile('[a-zA-Z_][a-zA-Z0-9_]*$') |
- |
-def dictToKW(d): |
- out = [] |
- items = d.items() |
- items.sort() |
- for k,v in items: |
- if not isinstance(k, types.StringType): |
- raise NonFormattableDict("%r ain't a string" % k) |
- if not r.match(k): |
- raise NonFormattableDict("%r ain't an identifier" % k) |
- out.append( |
- "\n\0%s=%s," % (k, prettify(v)) |
- ) |
- return string.join(out, '') |
- |
- |
-def prettify(obj): |
- if hasattr(obj, 'getSource'): |
- return obj.getSource() |
- else: |
- #basic type |
- t = type(obj) |
- |
- if t in _SIMPLE_BUILTINS: |
- return repr(obj) |
- |
- elif t is types.DictType: |
- out = ['{'] |
- for k,v in obj.items(): |
- out.append('\n\0%s: %s,' % (prettify(k), prettify(v))) |
- out.append(len(obj) and '\n\0}' or '}') |
- return string.join(out, '') |
- |
- elif t is types.ListType: |
- out = ["["] |
- for x in obj: |
- out.append('\n\0%s,' % prettify(x)) |
- out.append(len(obj) and '\n\0]' or ']') |
- return string.join(out, '') |
- |
- elif t is types.TupleType: |
- out = ["("] |
- for x in obj: |
- out.append('\n\0%s,' % prettify(x)) |
- out.append(len(obj) and '\n\0)' or ')') |
- return string.join(out, '') |
- else: |
- raise TypeError("Unsupported type %s when trying to prettify %s." % (t, obj)) |
- |
-def indentify(s): |
- out = [] |
- stack = [] |
- def eater(type, val, r, c, l, out=out, stack=stack): |
- #import sys |
- #sys.stdout.write(val) |
- if val in ['[', '(', '{']: |
- stack.append(val) |
- elif val in [']', ')', '}']: |
- stack.pop() |
- if val == '\0': |
- out.append(' '*len(stack)) |
- else: |
- out.append(val) |
- l = ['', s] |
- tokenize.tokenize(l.pop, eater) |
- return string.join(out, '') |
- |
- |
- |
- |
- |
-########### |
-# Unjelly # |
-########### |
- |
-def unjellyFromAOT(aot): |
- """ |
- Pass me an Abstract Object Tree, and I'll unjelly it for you. |
- """ |
- return AOTUnjellier().unjelly(aot) |
- |
-def unjellyFromSource(stringOrFile): |
- """ |
- Pass me a string of code or a filename that defines an 'app' variable (in |
- terms of Abstract Objects!), and I'll execute it and unjelly the resulting |
- AOT for you, returning a newly unpersisted Application object! |
- """ |
- |
- ns = {"Instance": Instance, |
- "InstanceMethod": InstanceMethod, |
- "Class": Class, |
- "Function": Function, |
- "Module": Module, |
- "Ref": Ref, |
- "Deref": Deref, |
- "Copyreg": Copyreg, |
- } |
- |
- if hasattr(stringOrFile, "read"): |
- exec stringOrFile.read() in ns |
- else: |
- exec stringOrFile in ns |
- |
- if ns.has_key('app'): |
- return unjellyFromAOT(ns['app']) |
- else: |
- raise ValueError("%s needs to define an 'app', it didn't!" % stringOrFile) |
- |
- |
-class AOTUnjellier: |
- """I handle the unjellying of an Abstract Object Tree. |
- See AOTUnjellier.unjellyAO |
- """ |
- def __init__(self): |
- self.references = {} |
- self.stack = [] |
- self.afterUnjelly = [] |
- |
- ## |
- # unjelly helpers (copied pretty much directly from marmalade XXX refactor) |
- ## |
- def unjellyLater(self, node): |
- """Unjelly a node, later. |
- """ |
- d = crefutil._Defer() |
- self.unjellyInto(d, 0, node) |
- return d |
- |
- def unjellyInto(self, obj, loc, ao): |
- """Utility method for unjellying one object into another. |
- This automates the handling of backreferences. |
- """ |
- o = self.unjellyAO(ao) |
- obj[loc] = o |
- if isinstance(o, crefutil.NotKnown): |
- o.addDependant(obj, loc) |
- return o |
- |
- def callAfter(self, callable, result): |
- if isinstance(result, crefutil.NotKnown): |
- l = [None] |
- result.addDependant(l, 1) |
- else: |
- l = [result] |
- self.afterUnjelly.append((callable, l)) |
- |
- def unjellyAttribute(self, instance, attrName, ao): |
- #XXX this is unused???? |
- """Utility method for unjellying into instances of attributes. |
- |
- Use this rather than unjellyAO unless you like surprising bugs! |
- Alternatively, you can use unjellyInto on your instance's __dict__. |
- """ |
- self.unjellyInto(instance.__dict__, attrName, ao) |
- |
- def unjellyAO(self, ao): |
- """Unjelly an Abstract Object and everything it contains. |
- I return the real object. |
- """ |
- self.stack.append(ao) |
- t = type(ao) |
- if t is types.InstanceType: |
- #Abstract Objects |
- c = ao.__class__ |
- if c is Module: |
- return reflect.namedModule(ao.name) |
- |
- elif c in [Class, Function] or issubclass(c, type): |
- return reflect.namedObject(ao.name) |
- |
- elif c is InstanceMethod: |
- im_name = ao.name |
- im_class = reflect.namedObject(ao.klass) |
- im_self = self.unjellyAO(ao.instance) |
- if im_name in im_class.__dict__: |
- if im_self is None: |
- return getattr(im_class, im_name) |
- elif isinstance(im_self, crefutil.NotKnown): |
- return crefutil._InstanceMethod(im_name, im_self, im_class) |
- else: |
- return new.instancemethod(im_class.__dict__[im_name], |
- im_self, |
- im_class) |
- else: |
- raise TypeError("instance method changed") |
- |
- elif c is Instance: |
- klass = reflect.namedObject(ao.klass) |
- state = self.unjellyAO(ao.state) |
- if hasattr(klass, "__setstate__"): |
- inst = new.instance(klass, {}) |
- self.callAfter(inst.__setstate__, state) |
- else: |
- inst = new.instance(klass, state) |
- return inst |
- |
- elif c is Ref: |
- o = self.unjellyAO(ao.obj) #THIS IS CHANGING THE REF OMG |
- refkey = ao.refnum |
- ref = self.references.get(refkey) |
- if ref is None: |
- self.references[refkey] = o |
- elif isinstance(ref, crefutil.NotKnown): |
- ref.resolveDependants(o) |
- self.references[refkey] = o |
- elif refkey is None: |
- # This happens when you're unjellying from an AOT not read from source |
- pass |
- else: |
- raise ValueError("Multiple references with the same ID: %s, %s, %s!" % (ref, refkey, ao)) |
- return o |
- |
- elif c is Deref: |
- num = ao.refnum |
- ref = self.references.get(num) |
- if ref is None: |
- der = crefutil._Dereference(num) |
- self.references[num] = der |
- return der |
- return ref |
- |
- elif c is Copyreg: |
- loadfunc = reflect.namedObject(ao.loadfunc) |
- d = self.unjellyLater(ao.state).addCallback( |
- lambda result, _l: apply(_l, result), loadfunc) |
- return d |
- |
- #Types |
- |
- elif t in _SIMPLE_BUILTINS: |
- return ao |
- |
- elif t is types.ListType: |
- l = [] |
- for x in ao: |
- l.append(None) |
- self.unjellyInto(l, len(l)-1, x) |
- return l |
- |
- elif t is types.TupleType: |
- l = [] |
- tuple_ = tuple |
- for x in ao: |
- l.append(None) |
- if isinstance(self.unjellyInto(l, len(l)-1, x), crefutil.NotKnown): |
- tuple_ = crefutil._Tuple |
- return tuple_(l) |
- |
- elif t is types.DictType: |
- d = {} |
- for k,v in ao.items(): |
- kvd = crefutil._DictKeyAndValue(d) |
- self.unjellyInto(kvd, 0, k) |
- self.unjellyInto(kvd, 1, v) |
- return d |
- |
- else: |
- raise TypeError("Unsupported AOT type: %s" % t) |
- |
- del self.stack[-1] |
- |
- |
- def unjelly(self, ao): |
- try: |
- l = [None] |
- self.unjellyInto(l, 0, ao) |
- for callable, v in self.afterUnjelly: |
- callable(v[0]) |
- return l[0] |
- except: |
- log.msg("Error jellying object! Stacktrace follows::") |
- log.msg(string.join(map(repr, self.stack), "\n")) |
- raise |
-######### |
-# Jelly # |
-######### |
- |
- |
-def jellyToAOT(obj): |
- """Convert an object to an Abstract Object Tree.""" |
- return AOTJellier().jelly(obj) |
- |
-def jellyToSource(obj, file=None): |
- """ |
- Pass me an object and, optionally, a file object. |
- I'll convert the object to an AOT either return it (if no file was |
- specified) or write it to the file. |
- """ |
- |
- aot = jellyToAOT(obj) |
- if file: |
- file.write(getSource(aot)) |
- else: |
- return getSource(aot) |
- |
- |
-class AOTJellier: |
- def __init__(self): |
- # dict of {id(obj): (obj, node)} |
- self.prepared = {} |
- self._ref_id = 0 |
- self.stack = [] |
- |
- def prepareForRef(self, aoref, object): |
- """I prepare an object for later referencing, by storing its id() |
- and its _AORef in a cache.""" |
- self.prepared[id(object)] = aoref |
- |
- def jellyToAO(self, obj): |
- """I turn an object into an AOT and return it.""" |
- objType = type(obj) |
- self.stack.append(repr(obj)) |
- |
- #immutable: We don't care if these have multiple refs! |
- if objType in _SIMPLE_BUILTINS: |
- retval = obj |
- |
- elif objType is types.MethodType: |
- # TODO: make methods 'prefer' not to jelly the object internally, |
- # so that the object will show up where it's referenced first NOT |
- # by a method. |
- retval = InstanceMethod(obj.im_func.__name__, reflect.qual(obj.im_class), |
- self.jellyToAO(obj.im_self)) |
- |
- elif objType is types.ModuleType: |
- retval = Module(obj.__name__) |
- |
- elif objType is types.ClassType: |
- retval = Class(reflect.qual(obj)) |
- |
- elif issubclass(objType, type): |
- retval = Class(reflect.qual(obj)) |
- |
- elif objType is types.FunctionType: |
- retval = Function(reflect.fullFuncName(obj)) |
- |
- else: #mutable! gotta watch for refs. |
- |
-#Marmalade had the nicety of being able to just stick a 'reference' attribute |
-#on any Node object that was referenced, but in AOT, the referenced object |
-#is *inside* of a Ref call (Ref(num, obj) instead of |
-#<objtype ... reference="1">). The problem is, especially for built-in types, |
-#I can't just assign some attribute to them to give them a refnum. So, I have |
-#to "wrap" a Ref(..) around them later -- that's why I put *everything* that's |
-#mutable inside one. The Ref() class will only print the "Ref(..)" around an |
-#object if it has a Reference explicitly attached. |
- |
- if self.prepared.has_key(id(obj)): |
- oldRef = self.prepared[id(obj)] |
- if oldRef.refnum: |
- # it's been referenced already |
- key = oldRef.refnum |
- else: |
- # it hasn't been referenced yet |
- self._ref_id = self._ref_id + 1 |
- key = self._ref_id |
- oldRef.setRef(key) |
- return Deref(key) |
- |
- retval = Ref() |
- self.prepareForRef(retval, obj) |
- |
- if objType is types.ListType: |
- retval.setObj(map(self.jellyToAO, obj)) #hah! |
- |
- elif objType is types.TupleType: |
- retval.setObj(tuple(map(self.jellyToAO, obj))) |
- |
- elif objType is types.DictionaryType: |
- d = {} |
- for k,v in obj.items(): |
- d[self.jellyToAO(k)] = self.jellyToAO(v) |
- retval.setObj(d) |
- |
- elif objType is types.InstanceType: |
- if hasattr(obj, "__getstate__"): |
- state = self.jellyToAO(obj.__getstate__()) |
- else: |
- state = self.jellyToAO(obj.__dict__) |
- retval.setObj(Instance(reflect.qual(obj.__class__), state)) |
- |
- elif copy_reg.dispatch_table.has_key(objType): |
- unpickleFunc, state = copy_reg.dispatch_table[objType](obj) |
- |
- retval.setObj(Copyreg( reflect.fullFuncName(unpickleFunc), |
- self.jellyToAO(state))) |
- |
- else: |
- raise TypeError("Unsupported type: %s" % objType.__name__) |
- |
- del self.stack[-1] |
- return retval |
- |
- def jelly(self, obj): |
- try: |
- ao = self.jellyToAO(obj) |
- return ao |
- except: |
- log.msg("Error jellying object! Stacktrace follows::") |
- log.msg(string.join(self.stack, '\n')) |
- raise |