| 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
|
|
|