diff options
Diffstat (limited to 'lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread')
13 files changed, 0 insertions, 5222 deletions
diff --git a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/__init__.py b/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/__init__.py deleted file mode 100755 index e38b149a..00000000 --- a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ - -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - - -""" -Twisted Spread: Spreadable (Distributed) Computing. - -Future Plans: PB, Jelly and Banana need to be optimized. - -@author: Glyph Lefkowitz -""" diff --git a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/banana.py b/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/banana.py deleted file mode 100755 index edae9c61..00000000 --- a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/banana.py +++ /dev/null @@ -1,358 +0,0 @@ -# -*- test-case-name: twisted.test.test_banana -*- -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - -""" -Banana -- s-exp based protocol. - -Future Plans: This module is almost entirely stable. The same caveat applies -to it as applies to L{twisted.spread.jelly}, however. Read its future plans -for more details. - -@author: Glyph Lefkowitz -""" - -import copy, cStringIO, struct - -from twisted.internet import protocol -from twisted.persisted import styles -from twisted.python import log - -class BananaError(Exception): - pass - -def int2b128(integer, stream): - if integer == 0: - stream(chr(0)) - return - assert integer > 0, "can only encode positive integers" - while integer: - stream(chr(integer & 0x7f)) - integer = integer >> 7 - - -def b1282int(st): - """ - Convert an integer represented as a base 128 string into an C{int} or - C{long}. - - @param st: The integer encoded in a string. - @type st: C{str} - - @return: The integer value extracted from the string. - @rtype: C{int} or C{long} - """ - e = 1 - i = 0 - for char in st: - n = ord(char) - i += (n * e) - e <<= 7 - return i - - -# delimiter characters. -LIST = chr(0x80) -INT = chr(0x81) -STRING = chr(0x82) -NEG = chr(0x83) -FLOAT = chr(0x84) -# "optional" -- these might be refused by a low-level implementation. -LONGINT = chr(0x85) -LONGNEG = chr(0x86) -# really optional; this is is part of the 'pb' vocabulary -VOCAB = chr(0x87) - -HIGH_BIT_SET = chr(0x80) - -def setPrefixLimit(limit): - """ - Set the limit on the prefix length for all Banana connections - established after this call. - - The prefix length limit determines how many bytes of prefix a banana - decoder will allow before rejecting a potential object as too large. - - @type limit: C{int} - @param limit: The number of bytes of prefix for banana to allow when - decoding. - """ - global _PREFIX_LIMIT - _PREFIX_LIMIT = limit -setPrefixLimit(64) - -SIZE_LIMIT = 640 * 1024 # 640k is all you'll ever need :-) - -class Banana(protocol.Protocol, styles.Ephemeral): - knownDialects = ["pb", "none"] - - prefixLimit = None - sizeLimit = SIZE_LIMIT - - def setPrefixLimit(self, limit): - """ - Set the prefix limit for decoding done by this protocol instance. - - @see: L{setPrefixLimit} - """ - self.prefixLimit = limit - self._smallestLongInt = -2 ** (limit * 7) + 1 - self._smallestInt = -2 ** 31 - self._largestInt = 2 ** 31 - 1 - self._largestLongInt = 2 ** (limit * 7) - 1 - - - def connectionReady(self): - """Surrogate for connectionMade - Called after protocol negotiation. - """ - - def _selectDialect(self, dialect): - self.currentDialect = dialect - self.connectionReady() - - def callExpressionReceived(self, obj): - if self.currentDialect: - self.expressionReceived(obj) - else: - # this is the first message we've received - if self.isClient: - # if I'm a client I have to respond - for serverVer in obj: - if serverVer in self.knownDialects: - self.sendEncoded(serverVer) - self._selectDialect(serverVer) - break - else: - # I can't speak any of those dialects. - log.msg("The client doesn't speak any of the protocols " - "offered by the server: disconnecting.") - self.transport.loseConnection() - else: - if obj in self.knownDialects: - self._selectDialect(obj) - else: - # the client just selected a protocol that I did not suggest. - log.msg("The client selected a protocol the server didn't " - "suggest and doesn't know: disconnecting.") - self.transport.loseConnection() - - - def connectionMade(self): - self.setPrefixLimit(_PREFIX_LIMIT) - self.currentDialect = None - if not self.isClient: - self.sendEncoded(self.knownDialects) - - - def gotItem(self, item): - l = self.listStack - if l: - l[-1][1].append(item) - else: - self.callExpressionReceived(item) - - buffer = '' - - def dataReceived(self, chunk): - buffer = self.buffer + chunk - listStack = self.listStack - gotItem = self.gotItem - while buffer: - assert self.buffer != buffer, "This ain't right: %s %s" % (repr(self.buffer), repr(buffer)) - self.buffer = buffer - pos = 0 - for ch in buffer: - if ch >= HIGH_BIT_SET: - break - pos = pos + 1 - else: - if pos > self.prefixLimit: - raise BananaError("Security precaution: more than %d bytes of prefix" % (self.prefixLimit,)) - return - num = buffer[:pos] - typebyte = buffer[pos] - rest = buffer[pos+1:] - if len(num) > self.prefixLimit: - raise BananaError("Security precaution: longer than %d bytes worth of prefix" % (self.prefixLimit,)) - if typebyte == LIST: - num = b1282int(num) - if num > SIZE_LIMIT: - raise BananaError("Security precaution: List too long.") - listStack.append((num, [])) - buffer = rest - elif typebyte == STRING: - num = b1282int(num) - if num > SIZE_LIMIT: - raise BananaError("Security precaution: String too long.") - if len(rest) >= num: - buffer = rest[num:] - gotItem(rest[:num]) - else: - return - elif typebyte == INT: - buffer = rest - num = b1282int(num) - gotItem(num) - elif typebyte == LONGINT: - buffer = rest - num = b1282int(num) - gotItem(num) - elif typebyte == LONGNEG: - buffer = rest - num = b1282int(num) - gotItem(-num) - elif typebyte == NEG: - buffer = rest - num = -b1282int(num) - gotItem(num) - elif typebyte == VOCAB: - buffer = rest - num = b1282int(num) - gotItem(self.incomingVocabulary[num]) - elif typebyte == FLOAT: - if len(rest) >= 8: - buffer = rest[8:] - gotItem(struct.unpack("!d", rest[:8])[0]) - else: - return - else: - raise NotImplementedError(("Invalid Type Byte %r" % (typebyte,))) - while listStack and (len(listStack[-1][1]) == listStack[-1][0]): - item = listStack.pop()[1] - gotItem(item) - self.buffer = '' - - - def expressionReceived(self, lst): - """Called when an expression (list, string, or int) is received. - """ - raise NotImplementedError() - - - outgoingVocabulary = { - # Jelly Data Types - 'None' : 1, - 'class' : 2, - 'dereference' : 3, - 'reference' : 4, - 'dictionary' : 5, - 'function' : 6, - 'instance' : 7, - 'list' : 8, - 'module' : 9, - 'persistent' : 10, - 'tuple' : 11, - 'unpersistable' : 12, - - # PB Data Types - 'copy' : 13, - 'cache' : 14, - 'cached' : 15, - 'remote' : 16, - 'local' : 17, - 'lcache' : 18, - - # PB Protocol Messages - 'version' : 19, - 'login' : 20, - 'password' : 21, - 'challenge' : 22, - 'logged_in' : 23, - 'not_logged_in' : 24, - 'cachemessage' : 25, - 'message' : 26, - 'answer' : 27, - 'error' : 28, - 'decref' : 29, - 'decache' : 30, - 'uncache' : 31, - } - - incomingVocabulary = {} - for k, v in outgoingVocabulary.items(): - incomingVocabulary[v] = k - - def __init__(self, isClient=1): - self.listStack = [] - self.outgoingSymbols = copy.copy(self.outgoingVocabulary) - self.outgoingSymbolCount = 0 - self.isClient = isClient - - def sendEncoded(self, obj): - io = cStringIO.StringIO() - self._encode(obj, io.write) - value = io.getvalue() - self.transport.write(value) - - def _encode(self, obj, write): - if isinstance(obj, (list, tuple)): - if len(obj) > SIZE_LIMIT: - raise BananaError( - "list/tuple is too long to send (%d)" % (len(obj),)) - int2b128(len(obj), write) - write(LIST) - for elem in obj: - self._encode(elem, write) - elif isinstance(obj, (int, long)): - if obj < self._smallestLongInt or obj > self._largestLongInt: - raise BananaError( - "int/long is too large to send (%d)" % (obj,)) - if obj < self._smallestInt: - int2b128(-obj, write) - write(LONGNEG) - elif obj < 0: - int2b128(-obj, write) - write(NEG) - elif obj <= self._largestInt: - int2b128(obj, write) - write(INT) - else: - int2b128(obj, write) - write(LONGINT) - elif isinstance(obj, float): - write(FLOAT) - write(struct.pack("!d", obj)) - elif isinstance(obj, str): - # TODO: an API for extending banana... - if self.currentDialect == "pb" and obj in self.outgoingSymbols: - symbolID = self.outgoingSymbols[obj] - int2b128(symbolID, write) - write(VOCAB) - else: - if len(obj) > SIZE_LIMIT: - raise BananaError( - "string is too long to send (%d)" % (len(obj),)) - int2b128(len(obj), write) - write(STRING) - write(obj) - else: - raise BananaError("could not send object: %r" % (obj,)) - - -# For use from the interactive interpreter -_i = Banana() -_i.connectionMade() -_i._selectDialect("none") - - -def encode(lst): - """Encode a list s-expression.""" - io = cStringIO.StringIO() - _i.transport = io - _i.sendEncoded(lst) - return io.getvalue() - - -def decode(st): - """ - Decode a banana-encoded string. - """ - l = [] - _i.expressionReceived = l.append - try: - _i.dataReceived(st) - finally: - _i.buffer = '' - del _i.expressionReceived - return l[0] diff --git a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/flavors.py b/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/flavors.py deleted file mode 100755 index 61d6b802..00000000 --- a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/flavors.py +++ /dev/null @@ -1,590 +0,0 @@ -# -*- test-case-name: twisted.test.test_pb -*- -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - -""" -This module represents flavors of remotely acessible objects. - -Currently this is only objects accessible through Perspective Broker, but will -hopefully encompass all forms of remote access which can emulate subsets of PB -(such as XMLRPC or SOAP). - -Future Plans: Optimization. Exploitation of new-style object model. -Optimizations to this module should not affect external-use semantics at all, -but may have a small impact on users who subclass and override methods. - -@author: Glyph Lefkowitz -""" - -# NOTE: this module should NOT import pb; it is supposed to be a module which -# abstractly defines remotely accessible types. Many of these types expect to -# be serialized by Jelly, but they ought to be accessible through other -# mechanisms (like XMLRPC) - -# system imports -import sys -from zope.interface import implements, Interface - -# twisted imports -from twisted.python import log, reflect - -# sibling imports -from jelly import setUnjellyableForClass, setUnjellyableForClassTree, setUnjellyableFactoryForClass, unjellyableRegistry -from jelly import Jellyable, Unjellyable, _newDummyLike -from jelly import setInstanceState, getInstanceState - -# compatibility -setCopierForClass = setUnjellyableForClass -setCopierForClassTree = setUnjellyableForClassTree -setFactoryForClass = setUnjellyableFactoryForClass -copyTags = unjellyableRegistry - -copy_atom = "copy" -cache_atom = "cache" -cached_atom = "cached" -remote_atom = "remote" - - -class NoSuchMethod(AttributeError): - """Raised if there is no such remote method""" - - -class IPBRoot(Interface): - """Factory for root Referenceable objects for PB servers.""" - - def rootObject(broker): - """Return root Referenceable for broker.""" - - -class Serializable(Jellyable): - """An object that can be passed remotely. - - I am a style of object which can be serialized by Perspective - Broker. Objects which wish to be referenceable or copied remotely - have to subclass Serializable. However, clients of Perspective - Broker will probably not want to directly subclass Serializable; the - Flavors of transferable objects are listed below. - - What it means to be \"Serializable\" is that an object can be - passed to or returned from a remote method. Certain basic types - (dictionaries, lists, tuples, numbers, strings) are serializable by - default; however, classes need to choose a specific serialization - style: L{Referenceable}, L{Viewable}, L{Copyable} or L{Cacheable}. - - You may also pass C{[lists, dictionaries, tuples]} of L{Serializable} - instances to or return them from remote methods, as many levels deep - as you like. - """ - - def processUniqueID(self): - """Return an ID which uniquely represents this object for this process. - - By default, this uses the 'id' builtin, but can be overridden to - indicate that two values are identity-equivalent (such as proxies - for the same object). - """ - - return id(self) - -class Referenceable(Serializable): - perspective = None - """I am an object sent remotely as a direct reference. - - When one of my subclasses is sent as an argument to or returned - from a remote method call, I will be serialized by default as a - direct reference. - - This means that the peer will be able to call methods on me; - a method call xxx() from my peer will be resolved to methods - of the name remote_xxx. - """ - - def remoteMessageReceived(self, broker, message, args, kw): - """A remote message has been received. Dispatch it appropriately. - - The default implementation is to dispatch to a method called - 'remote_messagename' and call it with the same arguments. - """ - args = broker.unserialize(args) - kw = broker.unserialize(kw) - method = getattr(self, "remote_%s" % message, None) - if method is None: - raise NoSuchMethod("No such method: remote_%s" % (message,)) - try: - state = method(*args, **kw) - except TypeError: - log.msg("%s didn't accept %s and %s" % (method, args, kw)) - raise - return broker.serialize(state, self.perspective) - - def jellyFor(self, jellier): - """(internal) - - Return a tuple which will be used as the s-expression to - serialize this to a peer. - """ - - return ["remote", jellier.invoker.registerReference(self)] - - -class Root(Referenceable): - """I provide a root object to L{pb.Broker}s for a L{pb.BrokerFactory}. - - When a L{pb.BrokerFactory} produces a L{pb.Broker}, it supplies that - L{pb.Broker} with an object named \"root\". That object is obtained - by calling my rootObject method. - """ - - implements(IPBRoot) - - def rootObject(self, broker): - """A L{pb.BrokerFactory} is requesting to publish me as a root object. - - When a L{pb.BrokerFactory} is sending me as the root object, this - method will be invoked to allow per-broker versions of an - object. By default I return myself. - """ - return self - - -class ViewPoint(Referenceable): - """ - I act as an indirect reference to an object accessed through a - L{pb.Perspective}. - - Simply put, I combine an object with a perspective so that when a - peer calls methods on the object I refer to, the method will be - invoked with that perspective as a first argument, so that it can - know who is calling it. - - While L{Viewable} objects will be converted to ViewPoints by default - when they are returned from or sent as arguments to a remote - method, any object may be manually proxied as well. (XXX: Now that - this class is no longer named C{Proxy}, this is the only occourance - of the term 'proxied' in this docstring, and may be unclear.) - - This can be useful when dealing with L{pb.Perspective}s, L{Copyable}s, - and L{Cacheable}s. It is legal to implement a method as such on - a perspective:: - - | def perspective_getViewPointForOther(self, name): - | defr = self.service.getPerspectiveRequest(name) - | defr.addCallbacks(lambda x, self=self: ViewPoint(self, x), log.msg) - | return defr - - This will allow you to have references to Perspective objects in two - different ways. One is through the initial 'attach' call -- each - peer will have a L{pb.RemoteReference} to their perspective directly. The - other is through this method; each peer can get a L{pb.RemoteReference} to - all other perspectives in the service; but that L{pb.RemoteReference} will - be to a L{ViewPoint}, not directly to the object. - - The practical offshoot of this is that you can implement 2 varieties - of remotely callable methods on this Perspective; view_xxx and - C{perspective_xxx}. C{view_xxx} methods will follow the rules for - ViewPoint methods (see ViewPoint.L{remoteMessageReceived}), and - C{perspective_xxx} methods will follow the rules for Perspective - methods. - """ - - def __init__(self, perspective, object): - """Initialize me with a Perspective and an Object. - """ - self.perspective = perspective - self.object = object - - def processUniqueID(self): - """Return an ID unique to a proxy for this perspective+object combination. - """ - return (id(self.perspective), id(self.object)) - - def remoteMessageReceived(self, broker, message, args, kw): - """A remote message has been received. Dispatch it appropriately. - - The default implementation is to dispatch to a method called - 'C{view_messagename}' to my Object and call it on my object with - the same arguments, modified by inserting my Perspective as - the first argument. - """ - args = broker.unserialize(args, self.perspective) - kw = broker.unserialize(kw, self.perspective) - method = getattr(self.object, "view_%s" % message) - try: - state = method(*(self.perspective,)+args, **kw) - except TypeError: - log.msg("%s didn't accept %s and %s" % (method, args, kw)) - raise - rv = broker.serialize(state, self.perspective, method, args, kw) - return rv - - -class Viewable(Serializable): - """I will be converted to a L{ViewPoint} when passed to or returned from a remote method. - - The beginning of a peer's interaction with a PB Service is always - through a perspective. However, if a C{perspective_xxx} method returns - a Viewable, it will be serialized to the peer as a response to that - method. - """ - - def jellyFor(self, jellier): - """Serialize a L{ViewPoint} for me and the perspective of the given broker. - """ - return ViewPoint(jellier.invoker.serializingPerspective, self).jellyFor(jellier) - - - -class Copyable(Serializable): - """Subclass me to get copied each time you are returned from or passed to a remote method. - - When I am returned from or passed to a remote method call, I will be - converted into data via a set of callbacks (see my methods for more - info). That data will then be serialized using Jelly, and sent to - the peer. - - The peer will then look up the type to represent this with; see - L{RemoteCopy} for details. - """ - - def getStateToCopy(self): - """Gather state to send when I am serialized for a peer. - - I will default to returning self.__dict__. Override this to - customize this behavior. - """ - - return self.__dict__ - - def getStateToCopyFor(self, perspective): - """ - Gather state to send when I am serialized for a particular - perspective. - - I will default to calling L{getStateToCopy}. Override this to - customize this behavior. - """ - - return self.getStateToCopy() - - def getTypeToCopy(self): - """Determine what type tag to send for me. - - By default, send the string representation of my class - (package.module.Class); normally this is adequate, but - you may override this to change it. - """ - - return reflect.qual(self.__class__) - - def getTypeToCopyFor(self, perspective): - """Determine what type tag to send for me. - - By default, defer to self.L{getTypeToCopy}() normally this is - adequate, but you may override this to change it. - """ - - return self.getTypeToCopy() - - def jellyFor(self, jellier): - """Assemble type tag and state to copy for this broker. - - This will call L{getTypeToCopyFor} and L{getStateToCopy}, and - return an appropriate s-expression to represent me. - """ - - if jellier.invoker is None: - return getInstanceState(self, jellier) - p = jellier.invoker.serializingPerspective - t = self.getTypeToCopyFor(p) - state = self.getStateToCopyFor(p) - sxp = jellier.prepare(self) - sxp.extend([t, jellier.jelly(state)]) - return jellier.preserve(self, sxp) - - -class Cacheable(Copyable): - """A cached instance. - - This means that it's copied; but there is some logic to make sure - that it's only copied once. Additionally, when state is retrieved, - it is passed a "proto-reference" to the state as it will exist on - the client. - - XXX: The documentation for this class needs work, but it's the most - complex part of PB and it is inherently difficult to explain. - """ - - def getStateToCacheAndObserveFor(self, perspective, observer): - """ - Get state to cache on the client and client-cache reference - to observe locally. - - This is similiar to getStateToCopyFor, but it additionally - passes in a reference to the client-side RemoteCache instance - that will be created when it is unserialized. This allows - Cacheable instances to keep their RemoteCaches up to date when - they change, such that no changes can occur between the point - at which the state is initially copied and the client receives - it that are not propogated. - """ - - return self.getStateToCopyFor(perspective) - - def jellyFor(self, jellier): - """Return an appropriate tuple to serialize me. - - Depending on whether this broker has cached me or not, this may - return either a full state or a reference to an existing cache. - """ - if jellier.invoker is None: - return getInstanceState(self, jellier) - luid = jellier.invoker.cachedRemotelyAs(self, 1) - if luid is None: - luid = jellier.invoker.cacheRemotely(self) - p = jellier.invoker.serializingPerspective - type_ = self.getTypeToCopyFor(p) - observer = RemoteCacheObserver(jellier.invoker, self, p) - state = self.getStateToCacheAndObserveFor(p, observer) - l = jellier.prepare(self) - jstate = jellier.jelly(state) - l.extend([type_, luid, jstate]) - return jellier.preserve(self, l) - else: - return cached_atom, luid - - def stoppedObserving(self, perspective, observer): - """This method is called when a client has stopped observing me. - - The 'observer' argument is the same as that passed in to - getStateToCacheAndObserveFor. - """ - - - -class RemoteCopy(Unjellyable): - """I am a remote copy of a Copyable object. - - When the state from a L{Copyable} object is received, an instance will - be created based on the copy tags table (see setUnjellyableForClass) and - sent the L{setCopyableState} message. I provide a reasonable default - implementation of that message; subclass me if you wish to serve as - a copier for remote data. - - NOTE: copiers are invoked with no arguments. Do not implement a - constructor which requires args in a subclass of L{RemoteCopy}! - """ - - def setCopyableState(self, state): - """I will be invoked with the state to copy locally. - - 'state' is the data returned from the remote object's - 'getStateToCopyFor' method, which will often be the remote - object's dictionary (or a filtered approximation of it depending - on my peer's perspective). - """ - - self.__dict__ = state - - def unjellyFor(self, unjellier, jellyList): - if unjellier.invoker is None: - return setInstanceState(self, unjellier, jellyList) - self.setCopyableState(unjellier.unjelly(jellyList[1])) - return self - - - -class RemoteCache(RemoteCopy, Serializable): - """A cache is a local representation of a remote L{Cacheable} object. - - This represents the last known state of this object. It may - also have methods invoked on it -- in order to update caches, - the cached class generates a L{pb.RemoteReference} to this object as - it is originally sent. - - Much like copy, I will be invoked with no arguments. Do not - implement a constructor that requires arguments in one of my - subclasses. - """ - - def remoteMessageReceived(self, broker, message, args, kw): - """A remote message has been received. Dispatch it appropriately. - - The default implementation is to dispatch to a method called - 'C{observe_messagename}' and call it on my with the same arguments. - """ - - args = broker.unserialize(args) - kw = broker.unserialize(kw) - method = getattr(self, "observe_%s" % message) - try: - state = method(*args, **kw) - except TypeError: - log.msg("%s didn't accept %s and %s" % (method, args, kw)) - raise - return broker.serialize(state, None, method, args, kw) - - def jellyFor(self, jellier): - """serialize me (only for the broker I'm for) as the original cached reference - """ - if jellier.invoker is None: - return getInstanceState(self, jellier) - assert jellier.invoker is self.broker, "You cannot exchange cached proxies between brokers." - return 'lcache', self.luid - - - def unjellyFor(self, unjellier, jellyList): - if unjellier.invoker is None: - return setInstanceState(self, unjellier, jellyList) - self.broker = unjellier.invoker - self.luid = jellyList[1] - cProxy = _newDummyLike(self) - # XXX questionable whether this was a good design idea... - init = getattr(cProxy, "__init__", None) - if init: - init() - unjellier.invoker.cacheLocally(jellyList[1], self) - cProxy.setCopyableState(unjellier.unjelly(jellyList[2])) - # Might have changed due to setCopyableState method; we'll assume that - # it's bad form to do so afterwards. - self.__dict__ = cProxy.__dict__ - # chomp, chomp -- some existing code uses "self.__dict__ =", some uses - # "__dict__.update". This is here in order to handle both cases. - self.broker = unjellier.invoker - self.luid = jellyList[1] - return cProxy - -## def __really_del__(self): -## """Final finalization call, made after all remote references have been lost. -## """ - - def __cmp__(self, other): - """Compare me [to another RemoteCache. - """ - if isinstance(other, self.__class__): - return cmp(id(self.__dict__), id(other.__dict__)) - else: - return cmp(id(self.__dict__), other) - - def __hash__(self): - """Hash me. - """ - return int(id(self.__dict__) % sys.maxint) - - broker = None - luid = None - - def __del__(self): - """Do distributed reference counting on finalize. - """ - try: - # log.msg( ' --- decache: %s %s' % (self, self.luid) ) - if self.broker: - self.broker.decCacheRef(self.luid) - except: - log.deferr() - -def unjellyCached(unjellier, unjellyList): - luid = unjellyList[1] - cNotProxy = unjellier.invoker.cachedLocallyAs(luid) - cProxy = _newDummyLike(cNotProxy) - return cProxy - -setUnjellyableForClass("cached", unjellyCached) - -def unjellyLCache(unjellier, unjellyList): - luid = unjellyList[1] - obj = unjellier.invoker.remotelyCachedForLUID(luid) - return obj - -setUnjellyableForClass("lcache", unjellyLCache) - -def unjellyLocal(unjellier, unjellyList): - obj = unjellier.invoker.localObjectForID(unjellyList[1]) - return obj - -setUnjellyableForClass("local", unjellyLocal) - -class RemoteCacheMethod: - """A method on a reference to a L{RemoteCache}. - """ - - def __init__(self, name, broker, cached, perspective): - """(internal) initialize. - """ - self.name = name - self.broker = broker - self.perspective = perspective - self.cached = cached - - def __cmp__(self, other): - return cmp((self.name, self.broker, self.perspective, self.cached), other) - - def __hash__(self): - return hash((self.name, self.broker, self.perspective, self.cached)) - - def __call__(self, *args, **kw): - """(internal) action method. - """ - cacheID = self.broker.cachedRemotelyAs(self.cached) - if cacheID is None: - from pb import ProtocolError - raise ProtocolError("You can't call a cached method when the object hasn't been given to the peer yet.") - return self.broker._sendMessage('cache', self.perspective, cacheID, self.name, args, kw) - -class RemoteCacheObserver: - """I am a reverse-reference to the peer's L{RemoteCache}. - - I am generated automatically when a cache is serialized. I - represent a reference to the client's L{RemoteCache} object that - will represent a particular L{Cacheable}; I am the additional - object passed to getStateToCacheAndObserveFor. - """ - - def __init__(self, broker, cached, perspective): - """(internal) Initialize me. - - @param broker: a L{pb.Broker} instance. - - @param cached: a L{Cacheable} instance that this L{RemoteCacheObserver} - corresponds to. - - @param perspective: a reference to the perspective who is observing this. - """ - - self.broker = broker - self.cached = cached - self.perspective = perspective - - def __repr__(self): - return "<RemoteCacheObserver(%s, %s, %s) at %s>" % ( - self.broker, self.cached, self.perspective, id(self)) - - def __hash__(self): - """Generate a hash unique to all L{RemoteCacheObserver}s for this broker/perspective/cached triplet - """ - - return ( (hash(self.broker) % 2**10) - + (hash(self.perspective) % 2**10) - + (hash(self.cached) % 2**10)) - - def __cmp__(self, other): - """Compare me to another L{RemoteCacheObserver}. - """ - - return cmp((self.broker, self.perspective, self.cached), other) - - def callRemote(self, _name, *args, **kw): - """(internal) action method. - """ - cacheID = self.broker.cachedRemotelyAs(self.cached) - if cacheID is None: - from pb import ProtocolError - raise ProtocolError("You can't call a cached method when the " - "object hasn't been given to the peer yet.") - return self.broker._sendMessage('cache', self.perspective, cacheID, - _name, args, kw) - - def remoteMethod(self, key): - """Get a L{pb.RemoteMethod} for this key. - """ - return RemoteCacheMethod(key, self.broker, self.cached, self.perspective) diff --git a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/interfaces.py b/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/interfaces.py deleted file mode 100755 index 6d48d002..00000000 --- a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/interfaces.py +++ /dev/null @@ -1,28 +0,0 @@ -""" -Twisted Spread Interfaces. - -This module is unused so far. It's also undecided whether this module -will remain monolithic. -""" - -from zope.interface import Interface - -class IJellyable(Interface): - def jellyFor(jellier): - """ - Jelly myself for jellier. - """ - -class IUnjellyable(Interface): - def unjellyFor(jellier, jellyList): - """ - Unjelly myself for the jellier. - - @param jellier: A stateful object which exists for the lifetime of a - single call to L{unjelly}. - - @param jellyList: The C{list} which represents the jellied state of the - object to be unjellied. - - @return: The object which results from unjellying. - """ diff --git a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/jelly.py b/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/jelly.py deleted file mode 100755 index 18795304..00000000 --- a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/jelly.py +++ /dev/null @@ -1,1151 +0,0 @@ -# -*- test-case-name: twisted.test.test_jelly -*- -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - -""" -S-expression-based persistence of python objects. - -It does something very much like L{Pickle<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 C{set} builtin and the C{sets.Set} class are serialized to the same -thing, and unserialized to C{set} if available, else to C{sets.Set}. It means -that there's a possibility of type switching in the serialization process. The -solution is to always use C{set} if possible, and only use C{sets.Set} under -Python 2.3; this can be accomplished by using L{twisted.python.compat.set}. - -The same rule applies for C{frozenset} and C{sets.ImmutableSet}. - -@author: Glyph Lefkowitz -""" - -# System Imports -import pickle -import types -import warnings -from types import StringType -from types import UnicodeType -from types import IntType -from types import TupleType -from types import ListType -from types import LongType -from types import FloatType -from types import FunctionType -from types import MethodType -from types import ModuleType -from types import DictionaryType -from types import InstanceType -from types import NoneType -from types import ClassType -import copy - -import datetime -from types import BooleanType - -try: - import decimal -except ImportError: - decimal = None - -try: - _set = set -except NameError: - _set = None - -try: - # Filter out deprecation warning for Python >= 2.6 - warnings.filterwarnings("ignore", category=DeprecationWarning, - message="the sets module is deprecated", append=True) - import sets as _sets -finally: - warnings.filters.pop() - - -from zope.interface import implements - -# Twisted Imports -from twisted.python.reflect import namedObject, qual -from twisted.persisted.crefutil import NotKnown, _Tuple, _InstanceMethod -from twisted.persisted.crefutil import _DictKeyAndValue, _Dereference -from twisted.persisted.crefutil import _Container -from twisted.python.compat import reduce - -from twisted.spread.interfaces import IJellyable, IUnjellyable - -DictTypes = (DictionaryType,) - -None_atom = "None" # N -# code -class_atom = "class" # c -module_atom = "module" # m -function_atom = "function" # f - -# references -dereference_atom = 'dereference' # D -persistent_atom = 'persistent' # p -reference_atom = 'reference' # r - -# mutable collections -dictionary_atom = "dictionary" # d -list_atom = 'list' # l -set_atom = 'set' - -# immutable collections -# (assignment to __dict__ and __class__ still might go away!) -tuple_atom = "tuple" # t -instance_atom = 'instance' # i -frozenset_atom = 'frozenset' - - -# errors -unpersistable_atom = "unpersistable"# u -unjellyableRegistry = {} -unjellyableFactoryRegistry = {} - -_NO_STATE = object() - -def _newInstance(cls, state=_NO_STATE): - """ - Make a new instance of a class without calling its __init__ method. - Supports both new- and old-style classes. - - @param state: A C{dict} used to update C{inst.__dict__} or C{_NO_STATE} - to skip this part of initialization. - - @return: A new instance of C{cls}. - """ - if not isinstance(cls, types.ClassType): - # new-style - inst = cls.__new__(cls) - - if state is not _NO_STATE: - inst.__dict__.update(state) # Copy 'instance' behaviour - else: - if state is not _NO_STATE: - inst = InstanceType(cls, state) - else: - inst = InstanceType(cls) - return inst - - - -def _maybeClass(classnamep): - try: - object - except NameError: - isObject = 0 - else: - isObject = isinstance(classnamep, type) - if isinstance(classnamep, ClassType) or isObject: - return qual(classnamep) - return classnamep - - - -def setUnjellyableForClass(classname, unjellyable): - """ - Set which local class will represent a remote type. - - 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. - """ - - global unjellyableRegistry - classname = _maybeClass(classname) - unjellyableRegistry[classname] = unjellyable - globalSecurity.allowTypes(classname) - - - -def setUnjellyableFactoryForClass(classname, copyFactory): - """ - Set the factory to construct a remote instance of a type:: - - jellier.setUnjellyableFactoryForClass('module.package.Class', MyFactory) - - Call this at the module level immediately after its class definition. - C{copyFactory} should return an instance or subclass of - L{RemoteCopy<pb.RemoteCopy>}. - - Similar to L{setUnjellyableForClass} except it uses a factory instead - of creating an instance. - """ - - global unjellyableFactoryRegistry - classname = _maybeClass(classname) - unjellyableFactoryRegistry[classname] = copyFactory - globalSecurity.allowTypes(classname) - - - -def setUnjellyableForClassTree(module, baseClass, prefix=None): - """ - Set all classes in a module derived from C{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 \'\'. - - @param module: a module object from which to pull the Copied classes. - (passing sys.modules[__name__] might be useful) - - @param baseClass: the base class from which all your Copied classes derive. - - @param prefix: the string prefixed to classnames to form the - unjellyableRegistry. - """ - if prefix is None: - prefix = module.__name__ - - if prefix: - prefix = "%s." % prefix - - for i in dir(module): - i_ = getattr(module, i) - if type(i_) == types.ClassType: - if issubclass(i_, baseClass): - setUnjellyableForClass('%s%s' % (prefix, i), i_) - - - -def getInstanceState(inst, jellier): - """ - Utility method to default to 'normal' state rules in serialization. - """ - if hasattr(inst, "__getstate__"): - state = inst.__getstate__() - else: - state = inst.__dict__ - sxp = jellier.prepare(inst) - sxp.extend([qual(inst.__class__), jellier.jelly(state)]) - return jellier.preserve(inst, sxp) - - - -def setInstanceState(inst, unjellier, jellyList): - """ - Utility method to default to 'normal' state rules in unserialization. - """ - state = unjellier.unjelly(jellyList[1]) - if hasattr(inst, "__setstate__"): - inst.__setstate__(state) - else: - inst.__dict__ = state - return inst - - - -class Unpersistable: - """ - This is an instance of a class that comes back when something couldn't be - unpersisted. - """ - - def __init__(self, reason): - """ - Initialize an unpersistable object with a descriptive C{reason} string. - """ - self.reason = reason - - - def __repr__(self): - return "Unpersistable(%s)" % repr(self.reason) - - - -class Jellyable: - """ - Inherit from me to Jelly yourself directly with the `getStateFor' - convenience method. - """ - implements(IJellyable) - - def getStateFor(self, jellier): - return self.__dict__ - - - def jellyFor(self, jellier): - """ - @see: L{twisted.spread.interfaces.IJellyable.jellyFor} - """ - sxp = jellier.prepare(self) - sxp.extend([ - qual(self.__class__), - jellier.jelly(self.getStateFor(jellier))]) - return jellier.preserve(self, sxp) - - - -class Unjellyable: - """ - Inherit from me to Unjelly yourself directly with the - C{setStateFor} convenience method. - """ - implements(IUnjellyable) - - def setStateFor(self, unjellier, state): - self.__dict__ = state - - - def unjellyFor(self, unjellier, jellyList): - """ - Perform the inverse operation of L{Jellyable.jellyFor}. - - @see: L{twisted.spread.interfaces.IUnjellyable.unjellyFor} - """ - state = unjellier.unjelly(jellyList[1]) - self.setStateFor(unjellier, state) - return self - - - -class _Jellier: - """ - (Internal) This class manages state for a call to jelly() - """ - - def __init__(self, taster, persistentStore, invoker): - """ - Initialize. - """ - self.taster = taster - # `preserved' is a dict of previously seen instances. - self.preserved = {} - # `cooked' is a dict of previously backreferenced instances to their - # `ref' lists. - self.cooked = {} - self.cooker = {} - self._ref_id = 1 - self.persistentStore = persistentStore - self.invoker = invoker - - - def _cook(self, object): - """ - (internal) Backreference an object. - - Notes on this method for the hapless future maintainer: If I've already - gone through the prepare/preserve cycle on the specified object (it is - being referenced after the serializer is \"done with\" it, e.g. this - reference is NOT circular), the copy-in-place of aList is relevant, - since the list being modified is the actual, pre-existing jelly - expression that was returned for that object. If not, it's technically - superfluous, since the value in self.preserved didn't need to be set, - but the invariant that self.preserved[id(object)] is a list is - convenient because that means we don't have to test and create it or - not create it here, creating fewer code-paths. that's why - self.preserved is always set to a list. - - Sorry that this code is so hard to follow, but Python objects are - tricky to persist correctly. -glyph - """ - aList = self.preserved[id(object)] - newList = copy.copy(aList) - # make a new reference ID - refid = self._ref_id - self._ref_id = self._ref_id + 1 - # replace the old list in-place, so that we don't have to track the - # previous reference to it. - aList[:] = [reference_atom, refid, newList] - self.cooked[id(object)] = [dereference_atom, refid] - return aList - - - def prepare(self, object): - """ - (internal) Create a list for persisting an object to. This will allow - backreferences to be made internal to the object. (circular - references). - - The reason this needs to happen is that we don't generate an ID for - every object, so we won't necessarily know which ID the object will - have in the future. When it is 'cooked' ( see _cook ), it will be - assigned an ID, and the temporary placeholder list created here will be - modified in-place to create an expression that gives this object an ID: - [reference id# [object-jelly]]. - """ - - # create a placeholder list to be preserved - self.preserved[id(object)] = [] - # keep a reference to this object around, so it doesn't disappear! - # (This isn't always necessary, but for cases where the objects are - # dynamically generated by __getstate__ or getStateToCopyFor calls, it - # is; id() will return the same value for a different object if it gets - # garbage collected. This may be optimized later.) - self.cooker[id(object)] = object - return [] - - - def preserve(self, object, sexp): - """ - (internal) Mark an object's persistent list for later referral. - """ - # if I've been cooked in the meanwhile, - if id(object) in self.cooked: - # replace the placeholder empty list with the real one - self.preserved[id(object)][2] = sexp - # but give this one back. - sexp = self.preserved[id(object)] - else: - self.preserved[id(object)] = sexp - return sexp - - constantTypes = {types.StringType : 1, types.IntType : 1, - types.FloatType : 1, types.LongType : 1} - - - def _checkMutable(self,obj): - objId = id(obj) - if objId in self.cooked: - return self.cooked[objId] - if objId in self.preserved: - self._cook(obj) - return self.cooked[objId] - - - def jelly(self, obj): - if isinstance(obj, Jellyable): - preRef = self._checkMutable(obj) - if preRef: - return preRef - return obj.jellyFor(self) - objType = type(obj) - if self.taster.isTypeAllowed(qual(objType)): - # "Immutable" Types - if ((objType is StringType) or - (objType is IntType) or - (objType is LongType) or - (objType is FloatType)): - return obj - elif objType is MethodType: - return ["method", - obj.im_func.__name__, - self.jelly(obj.im_self), - self.jelly(obj.im_class)] - - elif UnicodeType and objType is UnicodeType: - return ['unicode', obj.encode('UTF-8')] - elif objType is NoneType: - return ['None'] - elif objType is FunctionType: - name = obj.__name__ - return ['function', str(pickle.whichmodule(obj, obj.__name__)) - + '.' + - name] - elif objType is ModuleType: - return ['module', obj.__name__] - elif objType is BooleanType: - return ['boolean', obj and 'true' or 'false'] - elif objType is datetime.datetime: - if obj.tzinfo: - raise NotImplementedError( - "Currently can't jelly datetime objects with tzinfo") - return ['datetime', '%s %s %s %s %s %s %s' % ( - obj.year, obj.month, obj.day, obj.hour, - obj.minute, obj.second, obj.microsecond)] - elif objType is datetime.time: - if obj.tzinfo: - raise NotImplementedError( - "Currently can't jelly datetime objects with tzinfo") - return ['time', '%s %s %s %s' % (obj.hour, obj.minute, - obj.second, obj.microsecond)] - elif objType is datetime.date: - return ['date', '%s %s %s' % (obj.year, obj.month, obj.day)] - elif objType is datetime.timedelta: - return ['timedelta', '%s %s %s' % (obj.days, obj.seconds, - obj.microseconds)] - elif objType is ClassType or issubclass(objType, type): - return ['class', qual(obj)] - elif decimal is not None and objType is decimal.Decimal: - return self.jelly_decimal(obj) - else: - preRef = self._checkMutable(obj) - if preRef: - return preRef - # "Mutable" Types - sxp = self.prepare(obj) - if objType is ListType: - sxp.extend(self._jellyIterable(list_atom, obj)) - elif objType is TupleType: - sxp.extend(self._jellyIterable(tuple_atom, obj)) - elif objType in DictTypes: - sxp.append(dictionary_atom) - for key, val in obj.items(): - sxp.append([self.jelly(key), self.jelly(val)]) - elif (_set is not None and objType is set or - objType is _sets.Set): - sxp.extend(self._jellyIterable(set_atom, obj)) - elif (_set is not None and objType is frozenset or - objType is _sets.ImmutableSet): - sxp.extend(self._jellyIterable(frozenset_atom, obj)) - else: - className = qual(obj.__class__) - persistent = None - if self.persistentStore: - persistent = self.persistentStore(obj, self) - if persistent is not None: - sxp.append(persistent_atom) - sxp.append(persistent) - elif self.taster.isClassAllowed(obj.__class__): - sxp.append(className) - if hasattr(obj, "__getstate__"): - state = obj.__getstate__() - else: - state = obj.__dict__ - sxp.append(self.jelly(state)) - else: - self.unpersistable( - "instance of class %s deemed insecure" % - qual(obj.__class__), sxp) - return self.preserve(obj, sxp) - else: - if objType is InstanceType: - raise InsecureJelly("Class not allowed for instance: %s %s" % - (obj.__class__, obj)) - raise InsecureJelly("Type not allowed for object: %s %s" % - (objType, obj)) - - - def _jellyIterable(self, atom, obj): - """ - Jelly an iterable object. - - @param atom: the identifier atom of the object. - @type atom: C{str} - - @param obj: any iterable object. - @type obj: C{iterable} - - @return: a generator of jellied data. - @rtype: C{generator} - """ - yield atom - for item in obj: - yield self.jelly(item) - - - def jelly_decimal(self, d): - """ - Jelly a decimal object. - - @param d: a decimal object to serialize. - @type d: C{decimal.Decimal} - - @return: jelly for the decimal object. - @rtype: C{list} - """ - sign, guts, exponent = d.as_tuple() - value = reduce(lambda left, right: left * 10 + right, guts) - if sign: - value = -value - return ['decimal', value, exponent] - - - def unpersistable(self, reason, sxp=None): - """ - (internal) Returns an sexp: (unpersistable "reason"). Utility method - for making note that a particular object could not be serialized. - """ - if sxp is None: - sxp = [] - sxp.append(unpersistable_atom) - sxp.append(reason) - return sxp - - - -class _Unjellier: - - def __init__(self, taster, persistentLoad, invoker): - self.taster = taster - self.persistentLoad = persistentLoad - self.references = {} - self.postCallbacks = [] - self.invoker = invoker - - - def unjellyFull(self, obj): - o = self.unjelly(obj) - for m in self.postCallbacks: - m() - return o - - - def unjelly(self, obj): - if type(obj) is not types.ListType: - return obj - jelType = obj[0] - if not self.taster.isTypeAllowed(jelType): - raise InsecureJelly(jelType) - regClass = unjellyableRegistry.get(jelType) - if regClass is not None: - if isinstance(regClass, ClassType): - inst = _Dummy() # XXX chomp, chomp - inst.__class__ = regClass - method = inst.unjellyFor - elif isinstance(regClass, type): - # regClass.__new__ does not call regClass.__init__ - inst = regClass.__new__(regClass) - method = inst.unjellyFor - else: - method = regClass # this is how it ought to be done - val = method(self, obj) - if hasattr(val, 'postUnjelly'): - self.postCallbacks.append(inst.postUnjelly) - return val - regFactory = unjellyableFactoryRegistry.get(jelType) - if regFactory is not None: - state = self.unjelly(obj[1]) - inst = regFactory(state) - if hasattr(inst, 'postUnjelly'): - self.postCallbacks.append(inst.postUnjelly) - return inst - thunk = getattr(self, '_unjelly_%s'%jelType, None) - if thunk is not None: - ret = thunk(obj[1:]) - else: - nameSplit = jelType.split('.') - modName = '.'.join(nameSplit[:-1]) - if not self.taster.isModuleAllowed(modName): - raise InsecureJelly( - "Module %s not allowed (in type %s)." % (modName, jelType)) - clz = namedObject(jelType) - if not self.taster.isClassAllowed(clz): - raise InsecureJelly("Class %s not allowed." % jelType) - if hasattr(clz, "__setstate__"): - ret = _newInstance(clz) - state = self.unjelly(obj[1]) - ret.__setstate__(state) - else: - state = self.unjelly(obj[1]) - ret = _newInstance(clz, state) - if hasattr(clz, 'postUnjelly'): - self.postCallbacks.append(ret.postUnjelly) - return ret - - - def _unjelly_None(self, exp): - return None - - - def _unjelly_unicode(self, exp): - if UnicodeType: - return unicode(exp[0], "UTF-8") - else: - return Unpersistable("Could not unpersist unicode: %s" % (exp[0],)) - - - def _unjelly_decimal(self, exp): - """ - Unjelly decimal objects, if decimal is available. If not, return a - L{Unpersistable} object instead. - """ - if decimal is None: - return Unpersistable( - "Could not unpersist decimal: %s" % (exp[0] * (10**exp[1]),)) - value = exp[0] - exponent = exp[1] - if value < 0: - sign = 1 - else: - sign = 0 - guts = decimal.Decimal(value).as_tuple()[1] - return decimal.Decimal((sign, guts, exponent)) - - - def _unjelly_boolean(self, exp): - if BooleanType: - assert exp[0] in ('true', 'false') - return exp[0] == 'true' - else: - return Unpersistable("Could not unpersist boolean: %s" % (exp[0],)) - - - def _unjelly_datetime(self, exp): - return datetime.datetime(*map(int, exp[0].split())) - - - def _unjelly_date(self, exp): - return datetime.date(*map(int, exp[0].split())) - - - def _unjelly_time(self, exp): - return datetime.time(*map(int, exp[0].split())) - - - def _unjelly_timedelta(self, exp): - days, seconds, microseconds = map(int, exp[0].split()) - return datetime.timedelta( - days=days, seconds=seconds, microseconds=microseconds) - - - def unjellyInto(self, obj, loc, jel): - o = self.unjelly(jel) - if isinstance(o, NotKnown): - o.addDependant(obj, loc) - obj[loc] = o - return o - - - def _unjelly_dereference(self, lst): - refid = lst[0] - x = self.references.get(refid) - if x is not None: - return x - der = _Dereference(refid) - self.references[refid] = der - return der - - - def _unjelly_reference(self, lst): - refid = lst[0] - exp = lst[1] - o = self.unjelly(exp) - ref = self.references.get(refid) - if (ref is None): - self.references[refid] = o - elif isinstance(ref, NotKnown): - ref.resolveDependants(o) - self.references[refid] = o - else: - assert 0, "Multiple references with same ID!" - return o - - - def _unjelly_tuple(self, lst): - l = range(len(lst)) - finished = 1 - for elem in l: - if isinstance(self.unjellyInto(l, elem, lst[elem]), NotKnown): - finished = 0 - if finished: - return tuple(l) - else: - return _Tuple(l) - - - def _unjelly_list(self, lst): - l = range(len(lst)) - for elem in l: - self.unjellyInto(l, elem, lst[elem]) - return l - - - def _unjellySetOrFrozenset(self, lst, containerType): - """ - Helper method to unjelly set or frozenset. - - @param lst: the content of the set. - @type lst: C{list} - - @param containerType: the type of C{set} to use. - """ - l = range(len(lst)) - finished = True - for elem in l: - data = self.unjellyInto(l, elem, lst[elem]) - if isinstance(data, NotKnown): - finished = False - if not finished: - return _Container(l, containerType) - else: - return containerType(l) - - - def _unjelly_set(self, lst): - """ - Unjelly set using either the C{set} builtin if available, or - C{sets.Set} as fallback. - """ - if _set is not None: - containerType = set - else: - containerType = _sets.Set - return self._unjellySetOrFrozenset(lst, containerType) - - - def _unjelly_frozenset(self, lst): - """ - Unjelly frozenset using either the C{frozenset} builtin if available, - or C{sets.ImmutableSet} as fallback. - """ - if _set is not None: - containerType = frozenset - else: - containerType = _sets.ImmutableSet - return self._unjellySetOrFrozenset(lst, containerType) - - - def _unjelly_dictionary(self, lst): - d = {} - for k, v in lst: - kvd = _DictKeyAndValue(d) - self.unjellyInto(kvd, 0, k) - self.unjellyInto(kvd, 1, v) - return d - - - def _unjelly_module(self, rest): - moduleName = rest[0] - if type(moduleName) != types.StringType: - raise InsecureJelly( - "Attempted to unjelly a module with a non-string name.") - if not self.taster.isModuleAllowed(moduleName): - raise InsecureJelly( - "Attempted to unjelly module named %r" % (moduleName,)) - mod = __import__(moduleName, {}, {},"x") - return mod - - - def _unjelly_class(self, rest): - clist = rest[0].split('.') - modName = '.'.join(clist[:-1]) - if not self.taster.isModuleAllowed(modName): - raise InsecureJelly("module %s not allowed" % modName) - klaus = namedObject(rest[0]) - objType = type(klaus) - if objType not in (types.ClassType, types.TypeType): - raise InsecureJelly( - "class %r unjellied to something that isn't a class: %r" % ( - rest[0], klaus)) - if not self.taster.isClassAllowed(klaus): - raise InsecureJelly("class not allowed: %s" % qual(klaus)) - return klaus - - - def _unjelly_function(self, rest): - modSplit = rest[0].split('.') - modName = '.'.join(modSplit[:-1]) - if not self.taster.isModuleAllowed(modName): - raise InsecureJelly("Module not allowed: %s"% modName) - # XXX do I need an isFunctionAllowed? - function = namedObject(rest[0]) - return function - - - def _unjelly_persistent(self, rest): - if self.persistentLoad: - pload = self.persistentLoad(rest[0], self) - return pload - else: - return Unpersistable("Persistent callback not found") - - - def _unjelly_instance(self, rest): - clz = self.unjelly(rest[0]) - if type(clz) is not types.ClassType: - raise InsecureJelly("Instance found with non-class class.") - if hasattr(clz, "__setstate__"): - inst = _newInstance(clz, {}) - state = self.unjelly(rest[1]) - inst.__setstate__(state) - else: - state = self.unjelly(rest[1]) - inst = _newInstance(clz, state) - if hasattr(clz, 'postUnjelly'): - self.postCallbacks.append(inst.postUnjelly) - return inst - - - def _unjelly_unpersistable(self, rest): - return Unpersistable("Unpersistable data: %s" % (rest[0],)) - - - def _unjelly_method(self, rest): - """ - (internal) Unjelly a method. - """ - im_name = rest[0] - im_self = self.unjelly(rest[1]) - im_class = self.unjelly(rest[2]) - if type(im_class) is not types.ClassType: - raise InsecureJelly("Method found with non-class class.") - if im_name in im_class.__dict__: - if im_self is None: - im = getattr(im_class, im_name) - elif isinstance(im_self, NotKnown): - im = _InstanceMethod(im_name, im_self, im_class) - else: - im = MethodType(im_class.__dict__[im_name], im_self, im_class) - else: - raise TypeError('instance method changed') - return im - - - -class _Dummy: - """ - (Internal) Dummy class, used for unserializing instances. - """ - - - -class _DummyNewStyle(object): - """ - (Internal) Dummy class, used for unserializing instances of new-style - classes. - """ - - -def _newDummyLike(instance): - """ - Create a new instance like C{instance}. - - The new instance has the same class and instance dictionary as the given - instance. - - @return: The new instance. - """ - if isinstance(instance.__class__, type): - # New-style class - dummy = _DummyNewStyle() - else: - # Classic class - dummy = _Dummy() - dummy.__class__ = instance.__class__ - dummy.__dict__ = instance.__dict__ - return dummy - - -#### Published Interface. - - -class InsecureJelly(Exception): - """ - 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. - """ - - def isModuleAllowed(self, moduleName): - """ - DummySecurityOptions.isModuleAllowed(moduleName) -> boolean - returns 1 if a module by that name is allowed, 0 otherwise - """ - return 1 - - - def isClassAllowed(self, klass): - """ - DummySecurityOptions.isClassAllowed(class) -> boolean - Assumes the module has already been allowed. Returns 1 if the given - class is allowed, 0 otherwise. - """ - return 1 - - - def isTypeAllowed(self, typeName): - """ - DummySecurityOptions.isTypeAllowed(typeName) -> boolean - Returns 1 if the given type is allowed, 0 otherwise. - """ - return 1 - - - -class SecurityOptions: - """ - This will by default disallow everything, except for 'none'. - """ - - basicTypes = ["dictionary", "list", "tuple", - "reference", "dereference", "unpersistable", - "persistent", "long_int", "long", "dict"] - - def __init__(self): - """ - SecurityOptions() initialize. - """ - # I don't believe any of these types can ever pose a security hazard, - # except perhaps "reference"... - self.allowedTypes = {"None": 1, - "bool": 1, - "boolean": 1, - "string": 1, - "str": 1, - "int": 1, - "float": 1, - "datetime": 1, - "time": 1, - "date": 1, - "timedelta": 1, - "NoneType": 1} - if hasattr(types, 'UnicodeType'): - self.allowedTypes['unicode'] = 1 - if decimal is not None: - self.allowedTypes['decimal'] = 1 - self.allowedTypes['set'] = 1 - self.allowedTypes['frozenset'] = 1 - self.allowedModules = {} - self.allowedClasses = {} - - - def allowBasicTypes(self): - """ - Allow all `basic' types. (Dictionary and list. Int, string, and float - are implicitly allowed.) - """ - self.allowTypes(*self.basicTypes) - - - def allowTypes(self, *types): - """ - SecurityOptions.allowTypes(typeString): Allow a particular type, by its - name. - """ - for typ in types: - if not isinstance(typ, str): - typ = qual(typ) - self.allowedTypes[typ] = 1 - - - def allowInstancesOf(self, *classes): - """ - SecurityOptions.allowInstances(klass, klass, ...): allow instances - of the specified classes - - This will also allow the 'instance', 'class' (renamed 'classobj' in - Python 2.3), and 'module' types, as well as basic types. - """ - self.allowBasicTypes() - self.allowTypes("instance", "class", "classobj", "module") - for klass in classes: - self.allowTypes(qual(klass)) - self.allowModules(klass.__module__) - self.allowedClasses[klass] = 1 - - - def allowModules(self, *modules): - """ - SecurityOptions.allowModules(module, module, ...): allow modules by - name. This will also allow the 'module' type. - """ - for module in modules: - if type(module) == types.ModuleType: - module = module.__name__ - self.allowedModules[module] = 1 - - - def isModuleAllowed(self, moduleName): - """ - SecurityOptions.isModuleAllowed(moduleName) -> boolean - returns 1 if a module by that name is allowed, 0 otherwise - """ - return moduleName in self.allowedModules - - - def isClassAllowed(self, klass): - """ - SecurityOptions.isClassAllowed(class) -> boolean - Assumes the module has already been allowed. Returns 1 if the given - class is allowed, 0 otherwise. - """ - return klass in self.allowedClasses - - - def isTypeAllowed(self, typeName): - """ - SecurityOptions.isTypeAllowed(typeName) -> boolean - Returns 1 if the given type is allowed, 0 otherwise. - """ - return (typeName in self.allowedTypes or '.' in typeName) - - -globalSecurity = SecurityOptions() -globalSecurity.allowBasicTypes() - - - -def jelly(object, taster=DummySecurityOptions(), persistentStore=None, - invoker=None): - """ - Serialize to s-expression. - - 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. - """ - return _Jellier(taster, persistentStore, invoker).jelly(object) - - - -def unjelly(sexp, taster=DummySecurityOptions(), persistentLoad=None, - invoker=None): - """ - Unserialize from s-expression. - - 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. - """ - return _Unjellier(taster, persistentLoad, invoker).unjellyFull(sexp) diff --git a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/pb.py b/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/pb.py deleted file mode 100755 index 7e9a5b6a..00000000 --- a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/pb.py +++ /dev/null @@ -1,1434 +0,0 @@ -# -*- test-case-name: twisted.test.test_pb -*- -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - -""" -Perspective Broker - -\"This isn\'t a professional opinion, but it's probably got enough -internet to kill you.\" --glyph - -Introduction -============ - -This is a broker for proxies for and copies of objects. It provides a -translucent interface layer to those proxies. - -The protocol is not opaque, because it provides objects which represent the -remote proxies and require no context (server references, IDs) to operate on. - -It is not transparent because it does I{not} attempt to make remote objects -behave identically, or even similiarly, to local objects. Method calls are -invoked asynchronously, and specific rules are applied when serializing -arguments. - -To get started, begin with L{PBClientFactory} and L{PBServerFactory}. - -@author: Glyph Lefkowitz -""" - -import random -import types - -from zope.interface import implements, Interface - -# Twisted Imports -from twisted.python import log, failure, reflect -from twisted.python.hashlib import md5 -from twisted.internet import defer, protocol -from twisted.cred.portal import Portal -from twisted.cred.credentials import IAnonymous, ICredentials -from twisted.cred.credentials import IUsernameHashedPassword, Anonymous -from twisted.persisted import styles -from twisted.python.components import registerAdapter - -from twisted.spread.interfaces import IJellyable, IUnjellyable -from twisted.spread.jelly import jelly, unjelly, globalSecurity -from twisted.spread import banana - -from twisted.spread.flavors import Serializable -from twisted.spread.flavors import Referenceable, NoSuchMethod -from twisted.spread.flavors import Root, IPBRoot -from twisted.spread.flavors import ViewPoint -from twisted.spread.flavors import Viewable -from twisted.spread.flavors import Copyable -from twisted.spread.flavors import Jellyable -from twisted.spread.flavors import Cacheable -from twisted.spread.flavors import RemoteCopy -from twisted.spread.flavors import RemoteCache -from twisted.spread.flavors import RemoteCacheObserver -from twisted.spread.flavors import copyTags - -from twisted.spread.flavors import setUnjellyableForClass -from twisted.spread.flavors import setUnjellyableFactoryForClass -from twisted.spread.flavors import setUnjellyableForClassTree -# These three are backwards compatibility aliases for the previous three. -# Ultimately they should be deprecated. -exarkun -from twisted.spread.flavors import setCopierForClass -from twisted.spread.flavors import setFactoryForClass -from twisted.spread.flavors import setCopierForClassTree - - -MAX_BROKER_REFS = 1024 - -portno = 8787 - - - -class ProtocolError(Exception): - """ - This error is raised when an invalid protocol statement is received. - """ - - - -class DeadReferenceError(ProtocolError): - """ - This error is raised when a method is called on a dead reference (one whose - broker has been disconnected). - """ - - - -class Error(Exception): - """ - This error can be raised to generate known error conditions. - - When a PB callable method (perspective_, remote_, view_) raises - this error, it indicates that a traceback should not be printed, - but instead, the string representation of the exception should be - sent. - """ - - - -class RemoteError(Exception): - """ - This class is used to wrap a string-ified exception from the remote side to - be able to reraise it. (Raising string exceptions is no longer possible in - Python 2.6+) - - The value of this exception will be a str() representation of the remote - value. - - @ivar remoteType: The full import path of the exception class which was - raised on the remote end. - @type remoteType: C{str} - - @ivar remoteTraceback: The remote traceback. - @type remoteTraceback: C{str} - - @note: It's not possible to include the remoteTraceback if this exception is - thrown into a generator. It must be accessed as an attribute. - """ - def __init__(self, remoteType, value, remoteTraceback): - Exception.__init__(self, value) - self.remoteType = remoteType - self.remoteTraceback = remoteTraceback - - - -class RemoteMethod: - """ - This is a translucent reference to a remote message. - """ - def __init__(self, obj, name): - """ - Initialize with a L{RemoteReference} and the name of this message. - """ - self.obj = obj - self.name = name - - - def __cmp__(self, other): - return cmp((self.obj, self.name), other) - - - def __hash__(self): - return hash((self.obj, self.name)) - - - def __call__(self, *args, **kw): - """ - Asynchronously invoke a remote method. - """ - return self.obj.broker._sendMessage('',self.obj.perspective, - self.obj.luid, self.name, args, kw) - - - -class PBConnectionLost(Exception): - pass - - - -class IPerspective(Interface): - """ - per*spec*tive, n. : The relationship of aspects of a subject to each - other and to a whole: 'a perspective of history'; 'a need to view - the problem in the proper perspective'. - - This is a Perspective Broker-specific wrapper for an avatar. That - is to say, a PB-published view on to the business logic for the - system's concept of a 'user'. - - The concept of attached/detached is no longer implemented by the - framework. The realm is expected to implement such semantics if - needed. - """ - - def perspectiveMessageReceived(broker, message, args, kwargs): - """ - This method is called when a network message is received. - - @arg broker: The Perspective Broker. - - @type message: str - @arg message: The name of the method called by the other end. - - @type args: list in jelly format - @arg args: The arguments that were passed by the other end. It - is recommend that you use the `unserialize' method of the - broker to decode this. - - @type kwargs: dict in jelly format - @arg kwargs: The keyword arguments that were passed by the - other end. It is recommended that you use the - `unserialize' method of the broker to decode this. - - @rtype: A jelly list. - @return: It is recommended that you use the `serialize' method - of the broker on whatever object you need to return to - generate the return value. - """ - - - -class Avatar: - """ - A default IPerspective implementor. - - This class is intended to be subclassed, and a realm should return - an instance of such a subclass when IPerspective is requested of - it. - - A peer requesting a perspective will receive only a - L{RemoteReference} to a pb.Avatar. When a method is called on - that L{RemoteReference}, it will translate to a method on the - remote perspective named 'perspective_methodname'. (For more - information on invoking methods on other objects, see - L{flavors.ViewPoint}.) - """ - - implements(IPerspective) - - def perspectiveMessageReceived(self, broker, message, args, kw): - """ - This method is called when a network message is received. - - This will call:: - - self.perspective_%(message)s(*broker.unserialize(args), - **broker.unserialize(kw)) - - to handle the method; subclasses of Avatar are expected to - implement methods using this naming convention. - """ - - args = broker.unserialize(args, self) - kw = broker.unserialize(kw, self) - method = getattr(self, "perspective_%s" % message) - try: - state = method(*args, **kw) - except TypeError: - log.msg("%s didn't accept %s and %s" % (method, args, kw)) - raise - return broker.serialize(state, self, method, args, kw) - - - -class AsReferenceable(Referenceable): - """ - A reference directed towards another object. - """ - - def __init__(self, object, messageType="remote"): - self.remoteMessageReceived = getattr( - object, messageType + "MessageReceived") - - - -class RemoteReference(Serializable, styles.Ephemeral): - """ - A translucent reference to a remote object. - - I may be a reference to a L{flavors.ViewPoint}, a - L{flavors.Referenceable}, or an L{IPerspective} implementor (e.g., - pb.Avatar). From the client's perspective, it is not possible to - tell which except by convention. - - I am a \"translucent\" reference because although no additional - bookkeeping overhead is given to the application programmer for - manipulating a reference, return values are asynchronous. - - See also L{twisted.internet.defer}. - - @ivar broker: The broker I am obtained through. - @type broker: L{Broker} - """ - - implements(IUnjellyable) - - def __init__(self, perspective, broker, luid, doRefCount): - """(internal) Initialize me with a broker and a locally-unique ID. - - The ID is unique only to the particular Perspective Broker - instance. - """ - self.luid = luid - self.broker = broker - self.doRefCount = doRefCount - self.perspective = perspective - self.disconnectCallbacks = [] - - def notifyOnDisconnect(self, callback): - """Register a callback to be called if our broker gets disconnected. - - This callback will be called with one argument, this instance. - """ - assert callable(callback) - self.disconnectCallbacks.append(callback) - if len(self.disconnectCallbacks) == 1: - self.broker.notifyOnDisconnect(self._disconnected) - - def dontNotifyOnDisconnect(self, callback): - """Remove a callback that was registered with notifyOnDisconnect.""" - self.disconnectCallbacks.remove(callback) - if not self.disconnectCallbacks: - self.broker.dontNotifyOnDisconnect(self._disconnected) - - def _disconnected(self): - """Called if we are disconnected and have callbacks registered.""" - for callback in self.disconnectCallbacks: - callback(self) - self.disconnectCallbacks = None - - def jellyFor(self, jellier): - """If I am being sent back to where I came from, serialize as a local backreference. - """ - if jellier.invoker: - assert self.broker == jellier.invoker, "Can't send references to brokers other than their own." - return "local", self.luid - else: - return "unpersistable", "References cannot be serialized" - - def unjellyFor(self, unjellier, unjellyList): - self.__init__(unjellier.invoker.unserializingPerspective, unjellier.invoker, unjellyList[1], 1) - return self - - def callRemote(self, _name, *args, **kw): - """Asynchronously invoke a remote method. - - @type _name: C{str} - @param _name: the name of the remote method to invoke - @param args: arguments to serialize for the remote function - @param kw: keyword arguments to serialize for the remote function. - @rtype: L{twisted.internet.defer.Deferred} - @returns: a Deferred which will be fired when the result of - this remote call is received. - """ - # note that we use '_name' instead of 'name' so the user can call - # remote methods with 'name' as a keyword parameter, like this: - # ref.callRemote("getPeopleNamed", count=12, name="Bob") - - return self.broker._sendMessage('',self.perspective, self.luid, - _name, args, kw) - - def remoteMethod(self, key): - """Get a L{RemoteMethod} for this key. - """ - return RemoteMethod(self, key) - - def __cmp__(self,other): - """Compare me [to another L{RemoteReference}]. - """ - if isinstance(other, RemoteReference): - if other.broker == self.broker: - return cmp(self.luid, other.luid) - return cmp(self.broker, other) - - def __hash__(self): - """Hash me. - """ - return self.luid - - def __del__(self): - """Do distributed reference counting on finalization. - """ - if self.doRefCount: - self.broker.sendDecRef(self.luid) - -setUnjellyableForClass("remote", RemoteReference) - -class Local: - """(internal) A reference to a local object. - """ - - def __init__(self, object, perspective=None): - """Initialize. - """ - self.object = object - self.perspective = perspective - self.refcount = 1 - - def __repr__(self): - return "<pb.Local %r ref:%s>" % (self.object, self.refcount) - - def incref(self): - """Increment and return my reference count. - """ - self.refcount = self.refcount + 1 - return self.refcount - - def decref(self): - """Decrement and return my reference count. - """ - self.refcount = self.refcount - 1 - return self.refcount - - -## -# Failure -## - -class CopyableFailure(failure.Failure, Copyable): - """ - A L{flavors.RemoteCopy} and L{flavors.Copyable} version of - L{twisted.python.failure.Failure} for serialization. - """ - - unsafeTracebacks = 0 - - def getStateToCopy(self): - """ - Collect state related to the exception which occurred, discarding - state which cannot reasonably be serialized. - """ - state = self.__dict__.copy() - state['tb'] = None - state['frames'] = [] - state['stack'] = [] - state['value'] = str(self.value) # Exception instance - if isinstance(self.type, str): - state['type'] = self.type - else: - state['type'] = reflect.qual(self.type) # Exception class - if self.unsafeTracebacks: - state['traceback'] = self.getTraceback() - else: - state['traceback'] = 'Traceback unavailable\n' - return state - - - -class CopiedFailure(RemoteCopy, failure.Failure): - """ - A L{CopiedFailure} is a L{pb.RemoteCopy} of a L{failure.Failure} - transfered via PB. - - @ivar type: The full import path of the exception class which was raised on - the remote end. - @type type: C{str} - - @ivar value: A str() representation of the remote value. - @type value: L{CopiedFailure} or C{str} - - @ivar traceback: The remote traceback. - @type traceback: C{str} - """ - - def printTraceback(self, file=None, elideFrameworkCode=0, detail='default'): - if file is None: - file = log.logfile - file.write("Traceback from remote host -- ") - file.write(self.traceback) - file.write(self.type + ": " + self.value) - file.write('\n') - - - def throwExceptionIntoGenerator(self, g): - """ - Throw the original exception into the given generator, preserving - traceback information if available. In the case of a L{CopiedFailure} - where the exception type is a string, a L{pb.RemoteError} is thrown - instead. - - @return: The next value yielded from the generator. - @raise StopIteration: If there are no more values in the generator. - @raise RemoteError: The wrapped remote exception. - """ - return g.throw(RemoteError(self.type, self.value, self.traceback)) - - printBriefTraceback = printTraceback - printDetailedTraceback = printTraceback - -setUnjellyableForClass(CopyableFailure, CopiedFailure) - - - -def failure2Copyable(fail, unsafeTracebacks=0): - f = types.InstanceType(CopyableFailure, fail.__dict__) - f.unsafeTracebacks = unsafeTracebacks - return f - - - -class Broker(banana.Banana): - """I am a broker for objects. - """ - - version = 6 - username = None - factory = None - - def __init__(self, isClient=1, security=globalSecurity): - banana.Banana.__init__(self, isClient) - self.disconnected = 0 - self.disconnects = [] - self.failures = [] - self.connects = [] - self.localObjects = {} - self.security = security - self.pageProducers = [] - self.currentRequestID = 0 - self.currentLocalID = 0 - self.unserializingPerspective = None - # Some terms: - # PUID: process unique ID; return value of id() function. type "int". - # LUID: locally unique ID; an ID unique to an object mapped over this - # connection. type "int" - # GUID: (not used yet) globally unique ID; an ID for an object which - # may be on a redirected or meta server. Type as yet undecided. - # Dictionary mapping LUIDs to local objects. - # set above to allow root object to be assigned before connection is made - # self.localObjects = {} - # Dictionary mapping PUIDs to LUIDs. - self.luids = {} - # Dictionary mapping LUIDs to local (remotely cached) objects. Remotely - # cached means that they're objects which originate here, and were - # copied remotely. - self.remotelyCachedObjects = {} - # Dictionary mapping PUIDs to (cached) LUIDs - self.remotelyCachedLUIDs = {} - # Dictionary mapping (remote) LUIDs to (locally cached) objects. - self.locallyCachedObjects = {} - self.waitingForAnswers = {} - - # Mapping from LUIDs to weakref objects with callbacks for performing - # any local cleanup which may be necessary for the corresponding - # object once it no longer exists. - self._localCleanup = {} - - - def resumeProducing(self): - """Called when the consumer attached to me runs out of buffer. - """ - # Go backwards over the list so we can remove indexes from it as we go - for pageridx in xrange(len(self.pageProducers)-1, -1, -1): - pager = self.pageProducers[pageridx] - pager.sendNextPage() - if not pager.stillPaging(): - del self.pageProducers[pageridx] - if not self.pageProducers: - self.transport.unregisterProducer() - - # Streaming producer methods; not necessary to implement. - def pauseProducing(self): - pass - - def stopProducing(self): - pass - - def registerPageProducer(self, pager): - self.pageProducers.append(pager) - if len(self.pageProducers) == 1: - self.transport.registerProducer(self, 0) - - def expressionReceived(self, sexp): - """Evaluate an expression as it's received. - """ - if isinstance(sexp, types.ListType): - command = sexp[0] - methodName = "proto_%s" % command - method = getattr(self, methodName, None) - if method: - method(*sexp[1:]) - else: - self.sendCall("didNotUnderstand", command) - else: - raise ProtocolError("Non-list expression received.") - - - def proto_version(self, vnum): - """Protocol message: (version version-number) - - Check to make sure that both ends of the protocol are speaking - the same version dialect. - """ - - if vnum != self.version: - raise ProtocolError("Version Incompatibility: %s %s" % (self.version, vnum)) - - - def sendCall(self, *exp): - """Utility method to send an expression to the other side of the connection. - """ - self.sendEncoded(exp) - - def proto_didNotUnderstand(self, command): - """Respond to stock 'C{didNotUnderstand}' message. - - Log the command that was not understood and continue. (Note: - this will probably be changed to close the connection or raise - an exception in the future.) - """ - log.msg("Didn't understand command: %r" % command) - - def connectionReady(self): - """Initialize. Called after Banana negotiation is done. - """ - self.sendCall("version", self.version) - for notifier in self.connects: - try: - notifier() - except: - log.deferr() - self.connects = None - if self.factory: # in tests we won't have factory - self.factory.clientConnectionMade(self) - - def connectionFailed(self): - # XXX should never get called anymore? check! - for notifier in self.failures: - try: - notifier() - except: - log.deferr() - self.failures = None - - waitingForAnswers = None - - def connectionLost(self, reason): - """The connection was lost. - """ - self.disconnected = 1 - # nuke potential circular references. - self.luids = None - if self.waitingForAnswers: - for d in self.waitingForAnswers.values(): - try: - d.errback(failure.Failure(PBConnectionLost(reason))) - except: - log.deferr() - # Assure all Cacheable.stoppedObserving are called - for lobj in self.remotelyCachedObjects.values(): - cacheable = lobj.object - perspective = lobj.perspective - try: - cacheable.stoppedObserving(perspective, RemoteCacheObserver(self, cacheable, perspective)) - except: - log.deferr() - # Loop on a copy to prevent notifiers to mixup - # the list by calling dontNotifyOnDisconnect - for notifier in self.disconnects[:]: - try: - notifier() - except: - log.deferr() - self.disconnects = None - self.waitingForAnswers = None - self.localSecurity = None - self.remoteSecurity = None - self.remotelyCachedObjects = None - self.remotelyCachedLUIDs = None - self.locallyCachedObjects = None - self.localObjects = None - - def notifyOnDisconnect(self, notifier): - """Call the given callback when the Broker disconnects.""" - assert callable(notifier) - self.disconnects.append(notifier) - - def notifyOnFail(self, notifier): - """Call the given callback if the Broker fails to connect.""" - assert callable(notifier) - self.failures.append(notifier) - - def notifyOnConnect(self, notifier): - """Call the given callback when the Broker connects.""" - assert callable(notifier) - if self.connects is None: - try: - notifier() - except: - log.err() - else: - self.connects.append(notifier) - - def dontNotifyOnDisconnect(self, notifier): - """Remove a callback from list of disconnect callbacks.""" - try: - self.disconnects.remove(notifier) - except ValueError: - pass - - def localObjectForID(self, luid): - """ - Get a local object for a locally unique ID. - - @return: An object previously stored with L{registerReference} or - C{None} if there is no object which corresponds to the given - identifier. - """ - lob = self.localObjects.get(luid) - if lob is None: - return - return lob.object - - maxBrokerRefsViolations = 0 - - def registerReference(self, object): - """Get an ID for a local object. - - Store a persistent reference to a local object and map its id() - to a generated, session-unique ID and return that ID. - """ - - assert object is not None - puid = object.processUniqueID() - luid = self.luids.get(puid) - if luid is None: - if len(self.localObjects) > MAX_BROKER_REFS: - self.maxBrokerRefsViolations = self.maxBrokerRefsViolations + 1 - if self.maxBrokerRefsViolations > 3: - self.transport.loseConnection() - raise Error("Maximum PB reference count exceeded. " - "Goodbye.") - raise Error("Maximum PB reference count exceeded.") - - luid = self.newLocalID() - self.localObjects[luid] = Local(object) - self.luids[puid] = luid - else: - self.localObjects[luid].incref() - return luid - - def setNameForLocal(self, name, object): - """Store a special (string) ID for this object. - - This is how you specify a 'base' set of objects that the remote - protocol can connect to. - """ - assert object is not None - self.localObjects[name] = Local(object) - - def remoteForName(self, name): - """Returns an object from the remote name mapping. - - Note that this does not check the validity of the name, only - creates a translucent reference for it. - """ - return RemoteReference(None, self, name, 0) - - def cachedRemotelyAs(self, instance, incref=0): - """Returns an ID that says what this instance is cached as remotely, or C{None} if it's not. - """ - - puid = instance.processUniqueID() - luid = self.remotelyCachedLUIDs.get(puid) - if (luid is not None) and (incref): - self.remotelyCachedObjects[luid].incref() - return luid - - def remotelyCachedForLUID(self, luid): - """Returns an instance which is cached remotely, with this LUID. - """ - return self.remotelyCachedObjects[luid].object - - def cacheRemotely(self, instance): - """ - XXX""" - puid = instance.processUniqueID() - luid = self.newLocalID() - if len(self.remotelyCachedObjects) > MAX_BROKER_REFS: - self.maxBrokerRefsViolations = self.maxBrokerRefsViolations + 1 - if self.maxBrokerRefsViolations > 3: - self.transport.loseConnection() - raise Error("Maximum PB cache count exceeded. " - "Goodbye.") - raise Error("Maximum PB cache count exceeded.") - - self.remotelyCachedLUIDs[puid] = luid - # This table may not be necessary -- for now, it's to make sure that no - # monkey business happens with id(instance) - self.remotelyCachedObjects[luid] = Local(instance, self.serializingPerspective) - return luid - - def cacheLocally(self, cid, instance): - """(internal) - - Store a non-filled-out cached instance locally. - """ - self.locallyCachedObjects[cid] = instance - - def cachedLocallyAs(self, cid): - instance = self.locallyCachedObjects[cid] - return instance - - def serialize(self, object, perspective=None, method=None, args=None, kw=None): - """Jelly an object according to the remote security rules for this broker. - """ - - if isinstance(object, defer.Deferred): - object.addCallbacks(self.serialize, lambda x: x, - callbackKeywords={ - 'perspective': perspective, - 'method': method, - 'args': args, - 'kw': kw - }) - return object - - # XXX This call is NOT REENTRANT and testing for reentrancy is just - # crazy, so it likely won't be. Don't ever write methods that call the - # broker's serialize() method recursively (e.g. sending a method call - # from within a getState (this causes concurrency problems anyway so - # you really, really shouldn't do it)) - - # self.jellier = _NetJellier(self) - self.serializingPerspective = perspective - self.jellyMethod = method - self.jellyArgs = args - self.jellyKw = kw - try: - return jelly(object, self.security, None, self) - finally: - self.serializingPerspective = None - self.jellyMethod = None - self.jellyArgs = None - self.jellyKw = None - - def unserialize(self, sexp, perspective = None): - """Unjelly an sexp according to the local security rules for this broker. - """ - - self.unserializingPerspective = perspective - try: - return unjelly(sexp, self.security, None, self) - finally: - self.unserializingPerspective = None - - def newLocalID(self): - """Generate a new LUID. - """ - self.currentLocalID = self.currentLocalID + 1 - return self.currentLocalID - - def newRequestID(self): - """Generate a new request ID. - """ - self.currentRequestID = self.currentRequestID + 1 - return self.currentRequestID - - def _sendMessage(self, prefix, perspective, objectID, message, args, kw): - pbc = None - pbe = None - answerRequired = 1 - if 'pbcallback' in kw: - pbc = kw['pbcallback'] - del kw['pbcallback'] - if 'pberrback' in kw: - pbe = kw['pberrback'] - del kw['pberrback'] - if 'pbanswer' in kw: - assert (not pbe) and (not pbc), "You can't specify a no-answer requirement." - answerRequired = kw['pbanswer'] - del kw['pbanswer'] - if self.disconnected: - raise DeadReferenceError("Calling Stale Broker") - try: - netArgs = self.serialize(args, perspective=perspective, method=message) - netKw = self.serialize(kw, perspective=perspective, method=message) - except: - return defer.fail(failure.Failure()) - requestID = self.newRequestID() - if answerRequired: - rval = defer.Deferred() - self.waitingForAnswers[requestID] = rval - if pbc or pbe: - log.msg('warning! using deprecated "pbcallback"') - rval.addCallbacks(pbc, pbe) - else: - rval = None - self.sendCall(prefix+"message", requestID, objectID, message, answerRequired, netArgs, netKw) - return rval - - def proto_message(self, requestID, objectID, message, answerRequired, netArgs, netKw): - self._recvMessage(self.localObjectForID, requestID, objectID, message, answerRequired, netArgs, netKw) - def proto_cachemessage(self, requestID, objectID, message, answerRequired, netArgs, netKw): - self._recvMessage(self.cachedLocallyAs, requestID, objectID, message, answerRequired, netArgs, netKw) - - def _recvMessage(self, findObjMethod, requestID, objectID, message, answerRequired, netArgs, netKw): - """Received a message-send. - - Look up message based on object, unserialize the arguments, and - invoke it with args, and send an 'answer' or 'error' response. - """ - try: - object = findObjMethod(objectID) - if object is None: - raise Error("Invalid Object ID") - netResult = object.remoteMessageReceived(self, message, netArgs, netKw) - except Error, e: - if answerRequired: - # If the error is Jellyable or explicitly allowed via our - # security options, send it back and let the code on the - # other end deal with unjellying. If it isn't Jellyable, - # wrap it in a CopyableFailure, which ensures it can be - # unjellied on the other end. We have to do this because - # all errors must be sent back. - if isinstance(e, Jellyable) or self.security.isClassAllowed(e.__class__): - self._sendError(e, requestID) - else: - self._sendError(CopyableFailure(e), requestID) - except: - if answerRequired: - log.msg("Peer will receive following PB traceback:", isError=True) - f = CopyableFailure() - self._sendError(f, requestID) - log.err() - else: - if answerRequired: - if isinstance(netResult, defer.Deferred): - args = (requestID,) - netResult.addCallbacks(self._sendAnswer, self._sendFailureOrError, - callbackArgs=args, errbackArgs=args) - # XXX Should this be done somewhere else? - else: - self._sendAnswer(netResult, requestID) - ## - # success - ## - - def _sendAnswer(self, netResult, requestID): - """(internal) Send an answer to a previously sent message. - """ - self.sendCall("answer", requestID, netResult) - - def proto_answer(self, requestID, netResult): - """(internal) Got an answer to a previously sent message. - - Look up the appropriate callback and call it. - """ - d = self.waitingForAnswers[requestID] - del self.waitingForAnswers[requestID] - d.callback(self.unserialize(netResult)) - - ## - # failure - ## - def _sendFailureOrError(self, fail, requestID): - """ - Call L{_sendError} or L{_sendFailure}, depending on whether C{fail} - represents an L{Error} subclass or not. - """ - if fail.check(Error) is None: - self._sendFailure(fail, requestID) - else: - self._sendError(fail, requestID) - - - def _sendFailure(self, fail, requestID): - """Log error and then send it.""" - log.msg("Peer will receive following PB traceback:") - log.err(fail) - self._sendError(fail, requestID) - - def _sendError(self, fail, requestID): - """(internal) Send an error for a previously sent message. - """ - if isinstance(fail, failure.Failure): - # If the failures value is jellyable or allowed through security, - # send the value - if (isinstance(fail.value, Jellyable) or - self.security.isClassAllowed(fail.value.__class__)): - fail = fail.value - elif not isinstance(fail, CopyableFailure): - fail = failure2Copyable(fail, self.factory.unsafeTracebacks) - if isinstance(fail, CopyableFailure): - fail.unsafeTracebacks = self.factory.unsafeTracebacks - self.sendCall("error", requestID, self.serialize(fail)) - - def proto_error(self, requestID, fail): - """(internal) Deal with an error. - """ - d = self.waitingForAnswers[requestID] - del self.waitingForAnswers[requestID] - d.errback(self.unserialize(fail)) - - ## - # refcounts - ## - - def sendDecRef(self, objectID): - """(internal) Send a DECREF directive. - """ - self.sendCall("decref", objectID) - - def proto_decref(self, objectID): - """(internal) Decrement the reference count of an object. - - If the reference count is zero, it will free the reference to this - object. - """ - refs = self.localObjects[objectID].decref() - if refs == 0: - puid = self.localObjects[objectID].object.processUniqueID() - del self.luids[puid] - del self.localObjects[objectID] - self._localCleanup.pop(puid, lambda: None)() - - ## - # caching - ## - - def decCacheRef(self, objectID): - """(internal) Send a DECACHE directive. - """ - self.sendCall("decache", objectID) - - def proto_decache(self, objectID): - """(internal) Decrement the reference count of a cached object. - - If the reference count is zero, free the reference, then send an - 'uncached' directive. - """ - refs = self.remotelyCachedObjects[objectID].decref() - # log.msg('decaching: %s #refs: %s' % (objectID, refs)) - if refs == 0: - lobj = self.remotelyCachedObjects[objectID] - cacheable = lobj.object - perspective = lobj.perspective - # TODO: force_decache needs to be able to force-invalidate a - # cacheable reference. - try: - cacheable.stoppedObserving(perspective, RemoteCacheObserver(self, cacheable, perspective)) - except: - log.deferr() - puid = cacheable.processUniqueID() - del self.remotelyCachedLUIDs[puid] - del self.remotelyCachedObjects[objectID] - self.sendCall("uncache", objectID) - - def proto_uncache(self, objectID): - """(internal) Tell the client it is now OK to uncache an object. - """ - # log.msg("uncaching locally %d" % objectID) - obj = self.locallyCachedObjects[objectID] - obj.broker = None -## def reallyDel(obj=obj): -## obj.__really_del__() -## obj.__del__ = reallyDel - del self.locallyCachedObjects[objectID] - - - -def respond(challenge, password): - """Respond to a challenge. - - This is useful for challenge/response authentication. - """ - m = md5() - m.update(password) - hashedPassword = m.digest() - m = md5() - m.update(hashedPassword) - m.update(challenge) - doubleHashedPassword = m.digest() - return doubleHashedPassword - -def challenge(): - """I return some random data.""" - crap = '' - for x in range(random.randrange(15,25)): - crap = crap + chr(random.randint(65,90)) - crap = md5(crap).digest() - return crap - - -class PBClientFactory(protocol.ClientFactory): - """ - Client factory for PB brokers. - - As with all client factories, use with reactor.connectTCP/SSL/etc.. - getPerspective and getRootObject can be called either before or - after the connect. - """ - - protocol = Broker - unsafeTracebacks = False - - def __init__(self, unsafeTracebacks=False, security=globalSecurity): - """ - @param unsafeTracebacks: if set, tracebacks for exceptions will be sent - over the wire. - @type unsafeTracebacks: C{bool} - - @param security: security options used by the broker, default to - C{globalSecurity}. - @type security: L{twisted.spread.jelly.SecurityOptions} - """ - self.unsafeTracebacks = unsafeTracebacks - self.security = security - self._reset() - - - def buildProtocol(self, addr): - """ - Build the broker instance, passing the security options to it. - """ - p = self.protocol(isClient=True, security=self.security) - p.factory = self - return p - - - def _reset(self): - self.rootObjectRequests = [] # list of deferred - self._broker = None - self._root = None - - def _failAll(self, reason): - deferreds = self.rootObjectRequests - self._reset() - for d in deferreds: - d.errback(reason) - - def clientConnectionFailed(self, connector, reason): - self._failAll(reason) - - def clientConnectionLost(self, connector, reason, reconnecting=0): - """Reconnecting subclasses should call with reconnecting=1.""" - if reconnecting: - # any pending requests will go to next connection attempt - # so we don't fail them. - self._broker = None - self._root = None - else: - self._failAll(reason) - - def clientConnectionMade(self, broker): - self._broker = broker - self._root = broker.remoteForName("root") - ds = self.rootObjectRequests - self.rootObjectRequests = [] - for d in ds: - d.callback(self._root) - - def getRootObject(self): - """Get root object of remote PB server. - - @return: Deferred of the root object. - """ - if self._broker and not self._broker.disconnected: - return defer.succeed(self._root) - d = defer.Deferred() - self.rootObjectRequests.append(d) - return d - - def disconnect(self): - """If the factory is connected, close the connection. - - Note that if you set up the factory to reconnect, you will need to - implement extra logic to prevent automatic reconnection after this - is called. - """ - if self._broker: - self._broker.transport.loseConnection() - - def _cbSendUsername(self, root, username, password, client): - return root.callRemote("login", username).addCallback( - self._cbResponse, password, client) - - def _cbResponse(self, (challenge, challenger), password, client): - return challenger.callRemote("respond", respond(challenge, password), client) - - - def _cbLoginAnonymous(self, root, client): - """ - Attempt an anonymous login on the given remote root object. - - @type root: L{RemoteReference} - @param root: The object on which to attempt the login, most likely - returned by a call to L{PBClientFactory.getRootObject}. - - @param client: A jellyable object which will be used as the I{mind} - parameter for the login attempt. - - @rtype: L{Deferred} - @return: A L{Deferred} which will be called back with a - L{RemoteReference} to an avatar when anonymous login succeeds, or - which will errback if anonymous login fails. - """ - return root.callRemote("loginAnonymous", client) - - - def login(self, credentials, client=None): - """ - Login and get perspective from remote PB server. - - Currently the following credentials are supported:: - - L{twisted.cred.credentials.IUsernamePassword} - L{twisted.cred.credentials.IAnonymous} - - @rtype: L{Deferred} - @return: A L{Deferred} which will be called back with a - L{RemoteReference} for the avatar logged in to, or which will - errback if login fails. - """ - d = self.getRootObject() - - if IAnonymous.providedBy(credentials): - d.addCallback(self._cbLoginAnonymous, client) - else: - d.addCallback( - self._cbSendUsername, credentials.username, - credentials.password, client) - return d - - - -class PBServerFactory(protocol.ServerFactory): - """ - Server factory for perspective broker. - - Login is done using a Portal object, whose realm is expected to return - avatars implementing IPerspective. The credential checkers in the portal - should accept IUsernameHashedPassword or IUsernameMD5Password. - - Alternatively, any object providing or adaptable to L{IPBRoot} can be - used instead of a portal to provide the root object of the PB server. - """ - - unsafeTracebacks = False - - # object broker factory - protocol = Broker - - def __init__(self, root, unsafeTracebacks=False, security=globalSecurity): - """ - @param root: factory providing the root Referenceable used by the broker. - @type root: object providing or adaptable to L{IPBRoot}. - - @param unsafeTracebacks: if set, tracebacks for exceptions will be sent - over the wire. - @type unsafeTracebacks: C{bool} - - @param security: security options used by the broker, default to - C{globalSecurity}. - @type security: L{twisted.spread.jelly.SecurityOptions} - """ - self.root = IPBRoot(root) - self.unsafeTracebacks = unsafeTracebacks - self.security = security - - - def buildProtocol(self, addr): - """ - Return a Broker attached to the factory (as the service provider). - """ - proto = self.protocol(isClient=False, security=self.security) - proto.factory = self - proto.setNameForLocal("root", self.root.rootObject(proto)) - return proto - - def clientConnectionMade(self, protocol): - # XXX does this method make any sense? - pass - - -class IUsernameMD5Password(ICredentials): - """ - I encapsulate a username and a hashed password. - - This credential is used for username/password over PB. CredentialCheckers - which check this kind of credential must store the passwords in plaintext - form or as a MD5 digest. - - @type username: C{str} or C{Deferred} - @ivar username: The username associated with these credentials. - """ - - def checkPassword(password): - """ - Validate these credentials against the correct password. - - @type password: C{str} - @param password: The correct, plaintext password against which to - check. - - @rtype: C{bool} or L{Deferred} - @return: C{True} if the credentials represented by this object match the - given password, C{False} if they do not, or a L{Deferred} which will - be called back with one of these values. - """ - - def checkMD5Password(password): - """ - Validate these credentials against the correct MD5 digest of the - password. - - @type password: C{str} - @param password: The correct MD5 digest of a password against which to - check. - - @rtype: C{bool} or L{Deferred} - @return: C{True} if the credentials represented by this object match the - given digest, C{False} if they do not, or a L{Deferred} which will - be called back with one of these values. - """ - - -class _PortalRoot: - """Root object, used to login to portal.""" - - implements(IPBRoot) - - def __init__(self, portal): - self.portal = portal - - def rootObject(self, broker): - return _PortalWrapper(self.portal, broker) - -registerAdapter(_PortalRoot, Portal, IPBRoot) - - - -class _JellyableAvatarMixin: - """ - Helper class for code which deals with avatars which PB must be capable of - sending to a peer. - """ - def _cbLogin(self, (interface, avatar, logout)): - """ - Ensure that the avatar to be returned to the client is jellyable and - set up disconnection notification to call the realm's logout object. - """ - if not IJellyable.providedBy(avatar): - avatar = AsReferenceable(avatar, "perspective") - - puid = avatar.processUniqueID() - - # only call logout once, whether the connection is dropped (disconnect) - # or a logout occurs (cleanup), and be careful to drop the reference to - # it in either case - logout = [ logout ] - def maybeLogout(): - if not logout: - return - fn = logout[0] - del logout[0] - fn() - self.broker._localCleanup[puid] = maybeLogout - self.broker.notifyOnDisconnect(maybeLogout) - - return avatar - - - -class _PortalWrapper(Referenceable, _JellyableAvatarMixin): - """ - Root Referenceable object, used to login to portal. - """ - - def __init__(self, portal, broker): - self.portal = portal - self.broker = broker - - - def remote_login(self, username): - """ - Start of username/password login. - """ - c = challenge() - return c, _PortalAuthChallenger(self.portal, self.broker, username, c) - - - def remote_loginAnonymous(self, mind): - """ - Attempt an anonymous login. - - @param mind: An object to use as the mind parameter to the portal login - call (possibly None). - - @rtype: L{Deferred} - @return: A Deferred which will be called back with an avatar when login - succeeds or which will be errbacked if login fails somehow. - """ - d = self.portal.login(Anonymous(), mind, IPerspective) - d.addCallback(self._cbLogin) - return d - - - -class _PortalAuthChallenger(Referenceable, _JellyableAvatarMixin): - """ - Called with response to password challenge. - """ - implements(IUsernameHashedPassword, IUsernameMD5Password) - - def __init__(self, portal, broker, username, challenge): - self.portal = portal - self.broker = broker - self.username = username - self.challenge = challenge - - - def remote_respond(self, response, mind): - self.response = response - d = self.portal.login(self, mind, IPerspective) - d.addCallback(self._cbLogin) - return d - - - # IUsernameHashedPassword: - def checkPassword(self, password): - return self.checkMD5Password(md5(password).digest()) - - - # IUsernameMD5Password - def checkMD5Password(self, md5Password): - md = md5() - md.update(md5Password) - md.update(self.challenge) - correct = md.digest() - return self.response == correct - - -__all__ = [ - # Everything from flavors is exposed publically here. - 'IPBRoot', 'Serializable', 'Referenceable', 'NoSuchMethod', 'Root', - 'ViewPoint', 'Viewable', 'Copyable', 'Jellyable', 'Cacheable', - 'RemoteCopy', 'RemoteCache', 'RemoteCacheObserver', 'copyTags', - 'setUnjellyableForClass', 'setUnjellyableFactoryForClass', - 'setUnjellyableForClassTree', - 'setCopierForClass', 'setFactoryForClass', 'setCopierForClassTree', - - 'MAX_BROKER_REFS', 'portno', - - 'ProtocolError', 'DeadReferenceError', 'Error', 'PBConnectionLost', - 'RemoteMethod', 'IPerspective', 'Avatar', 'AsReferenceable', - 'RemoteReference', 'CopyableFailure', 'CopiedFailure', 'failure2Copyable', - 'Broker', 'respond', 'challenge', 'PBClientFactory', 'PBServerFactory', - 'IUsernameMD5Password', - ] diff --git a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/publish.py b/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/publish.py deleted file mode 100755 index 5bc18687..00000000 --- a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/publish.py +++ /dev/null @@ -1,142 +0,0 @@ -# -*- test-case-name: twisted.test.test_pb -*- -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - -""" -Persistently cached objects for PB. - -Maintainer: Glyph Lefkowitz - -Future Plans: None known. -""" - -import time - -from twisted.internet import defer -from twisted.spread import banana, jelly, flavors - - -class Publishable(flavors.Cacheable): - """An object whose cached state persists across sessions. - """ - def __init__(self, publishedID): - self.republish() - self.publishedID = publishedID - - def republish(self): - """Set the timestamp to current and (TODO) update all observers. - """ - self.timestamp = time.time() - - def view_getStateToPublish(self, perspective): - '(internal)' - return self.getStateToPublishFor(perspective) - - def getStateToPublishFor(self, perspective): - """Implement me to special-case your state for a perspective. - """ - return self.getStateToPublish() - - def getStateToPublish(self): - """Implement me to return state to copy as part of the publish phase. - """ - raise NotImplementedError("%s.getStateToPublishFor" % self.__class__) - - def getStateToCacheAndObserveFor(self, perspective, observer): - """Get all necessary metadata to keep a clientside cache. - """ - if perspective: - pname = perspective.perspectiveName - sname = perspective.getService().serviceName - else: - pname = "None" - sname = "None" - - return {"remote": flavors.ViewPoint(perspective, self), - "publishedID": self.publishedID, - "perspective": pname, - "service": sname, - "timestamp": self.timestamp} - -class RemotePublished(flavors.RemoteCache): - """The local representation of remote Publishable object. - """ - isActivated = 0 - _wasCleanWhenLoaded = 0 - def getFileName(self, ext='pub'): - return ("%s-%s-%s.%s" % - (self.service, self.perspective, str(self.publishedID), ext)) - - def setCopyableState(self, state): - self.__dict__.update(state) - self._activationListeners = [] - try: - dataFile = file(self.getFileName(), "rb") - data = dataFile.read() - dataFile.close() - except IOError: - recent = 0 - else: - newself = jelly.unjelly(banana.decode(data)) - recent = (newself.timestamp == self.timestamp) - if recent: - self._cbGotUpdate(newself.__dict__) - self._wasCleanWhenLoaded = 1 - else: - self.remote.callRemote('getStateToPublish').addCallbacks(self._cbGotUpdate) - - def __getstate__(self): - other = self.__dict__.copy() - # Remove PB-specific attributes - del other['broker'] - del other['remote'] - del other['luid'] - # remove my own runtime-tracking stuff - del other['_activationListeners'] - del other['isActivated'] - return other - - def _cbGotUpdate(self, newState): - self.__dict__.update(newState) - self.isActivated = 1 - # send out notifications - for listener in self._activationListeners: - listener(self) - self._activationListeners = [] - self.activated() - dataFile = file(self.getFileName(), "wb") - dataFile.write(banana.encode(jelly.jelly(self))) - dataFile.close() - - - def activated(self): - """Implement this method if you want to be notified when your - publishable subclass is activated. - """ - - def callWhenActivated(self, callback): - """Externally register for notification when this publishable has received all relevant data. - """ - if self.isActivated: - callback(self) - else: - self._activationListeners.append(callback) - -def whenReady(d): - """ - Wrap a deferred returned from a pb method in another deferred that - expects a RemotePublished as a result. This will allow you to wait until - the result is really available. - - Idiomatic usage would look like:: - - publish.whenReady(serverObject.getMeAPublishable()).addCallback(lookAtThePublishable) - """ - d2 = defer.Deferred() - d.addCallbacks(_pubReady, d2.errback, - callbackArgs=(d2,)) - return d2 - -def _pubReady(result, d2): - '(internal)' - result.callWhenActivated(d2.callback) diff --git a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/ui/__init__.py b/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/ui/__init__.py deleted file mode 100755 index 56bf7664..00000000 --- a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/ui/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ - -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - - -""" -Twisted Spread UI: UI utilities for various toolkits connecting to PB. -""" - -# Undeprecating this until someone figures out a real plan for alternatives to spread.ui. -##import warnings -##warnings.warn("twisted.spread.ui is deprecated. Please do not use.", DeprecationWarning) diff --git a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/ui/gtk2util.py b/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/ui/gtk2util.py deleted file mode 100755 index a576388e..00000000 --- a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/ui/gtk2util.py +++ /dev/null @@ -1,218 +0,0 @@ -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - -import gtk - -from twisted import copyright -from twisted.internet import defer -from twisted.python import failure, log, util -from twisted.spread import pb -from twisted.cred.credentials import UsernamePassword - -from twisted.internet import error as netError - -def login(client=None, **defaults): - """ - @param host: - @param port: - @param identityName: - @param password: - @param serviceName: - @param perspectiveName: - - @returntype: Deferred RemoteReference of Perspective - """ - d = defer.Deferred() - LoginDialog(client, d, defaults) - return d - -class GladeKeeper: - """ - @cvar gladefile: The file in which the glade GUI definition is kept. - @type gladefile: str - - @cvar _widgets: Widgets that should be attached to me as attributes. - @type _widgets: list of strings - """ - - gladefile = None - _widgets = () - - def __init__(self): - from gtk import glade - self.glade = glade.XML(self.gladefile) - - # mold can go away when we get a newer pygtk (post 1.99.14) - mold = {} - for k in dir(self): - mold[k] = getattr(self, k) - self.glade.signal_autoconnect(mold) - self._setWidgets() - - def _setWidgets(self): - get_widget = self.glade.get_widget - for widgetName in self._widgets: - setattr(self, "_" + widgetName, get_widget(widgetName)) - - -class LoginDialog(GladeKeeper): - # IdentityConnector host port identityName password - # requestLogin -> identityWrapper or login failure - # requestService serviceName perspectiveName client - - # window killed - # cancel button pressed - # login button activated - - fields = ['host','port','identityName','password', - 'perspectiveName'] - - _widgets = ("hostEntry", "portEntry", "identityNameEntry", "passwordEntry", - "perspectiveNameEntry", "statusBar", - "loginDialog") - - _advancedControls = ['perspectiveLabel', 'perspectiveNameEntry', - 'protocolLabel', 'versionLabel'] - - gladefile = util.sibpath(__file__, "login2.glade") - - _timeoutID = None - - def __init__(self, client, deferred, defaults): - self.client = client - self.deferredResult = deferred - - GladeKeeper.__init__(self) - - self.setDefaults(defaults) - self._loginDialog.show() - - - def setDefaults(self, defaults): - if not defaults.has_key('port'): - defaults['port'] = str(pb.portno) - elif isinstance(defaults['port'], (int, long)): - defaults['port'] = str(defaults['port']) - - for k, v in defaults.iteritems(): - if k in self.fields: - widget = getattr(self, "_%sEntry" % (k,)) - widget.set_text(v) - - def _setWidgets(self): - GladeKeeper._setWidgets(self) - self._statusContext = self._statusBar.get_context_id("Login dialog.") - get_widget = self.glade.get_widget - get_widget("versionLabel").set_text(copyright.longversion) - get_widget("protocolLabel").set_text("Protocol PB-%s" % - (pb.Broker.version,)) - - def _on_loginDialog_response(self, widget, response): - handlers = {gtk.RESPONSE_NONE: self._windowClosed, - gtk.RESPONSE_DELETE_EVENT: self._windowClosed, - gtk.RESPONSE_OK: self._doLogin, - gtk.RESPONSE_CANCEL: self._cancelled} - handler = handlers.get(response) - if handler is not None: - handler() - else: - log.msg("Unexpected dialog response %r from %s" % (response, - widget)) - - def _on_loginDialog_close(self, widget, userdata=None): - self._windowClosed() - - def _on_loginDialog_destroy_event(self, widget, userdata=None): - self._windowClosed() - - def _cancelled(self): - if not self.deferredResult.called: - self.deferredResult.errback(netError.UserError("User hit Cancel.")) - self._loginDialog.destroy() - - def _windowClosed(self, reason=None): - if not self.deferredResult.called: - self.deferredResult.errback(netError.UserError("Window closed.")) - - def _doLogin(self): - idParams = {} - - idParams['host'] = self._hostEntry.get_text() - idParams['port'] = self._portEntry.get_text() - idParams['identityName'] = self._identityNameEntry.get_text() - idParams['password'] = self._passwordEntry.get_text() - - try: - idParams['port'] = int(idParams['port']) - except ValueError: - pass - - f = pb.PBClientFactory() - from twisted.internet import reactor - reactor.connectTCP(idParams['host'], idParams['port'], f) - creds = UsernamePassword(idParams['identityName'], idParams['password']) - d = f.login(creds, self.client) - def _timeoutLogin(): - self._timeoutID = None - d.errback(failure.Failure(defer.TimeoutError("Login timed out."))) - self._timeoutID = reactor.callLater(30, _timeoutLogin) - d.addCallbacks(self._cbGotPerspective, self._ebFailedLogin) - self.statusMsg("Contacting server...") - - # serviceName = self._serviceNameEntry.get_text() - # perspectiveName = self._perspectiveNameEntry.get_text() - # if not perspectiveName: - # perspectiveName = idParams['identityName'] - - # d = _identityConnector.requestService(serviceName, perspectiveName, - # self.client) - # d.addCallbacks(self._cbGotPerspective, self._ebFailedLogin) - # setCursor to waiting - - def _cbGotPerspective(self, perspective): - self.statusMsg("Connected to server.") - if self._timeoutID is not None: - self._timeoutID.cancel() - self._timeoutID = None - self.deferredResult.callback(perspective) - # clear waiting cursor - self._loginDialog.destroy() - - def _ebFailedLogin(self, reason): - if isinstance(reason, failure.Failure): - reason = reason.value - self.statusMsg(reason) - if isinstance(reason, (unicode, str)): - text = reason - else: - text = unicode(reason) - msg = gtk.MessageDialog(self._loginDialog, - gtk.DIALOG_DESTROY_WITH_PARENT, - gtk.MESSAGE_ERROR, - gtk.BUTTONS_CLOSE, - text) - msg.show_all() - msg.connect("response", lambda *a: msg.destroy()) - - # hostname not found - # host unreachable - # connection refused - # authentication failed - # no such service - # no such perspective - # internal server error - - def _on_advancedButton_toggled(self, widget, userdata=None): - active = widget.get_active() - if active: - op = "show" - else: - op = "hide" - for widgetName in self._advancedControls: - widget = self.glade.get_widget(widgetName) - getattr(widget, op)() - - def statusMsg(self, text): - if not isinstance(text, (unicode, str)): - text = unicode(text) - return self._statusBar.push(self._statusContext, text) diff --git a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/ui/login2.glade b/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/ui/login2.glade deleted file mode 100644 index af8c53da..00000000 --- a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/ui/login2.glade +++ /dev/null @@ -1,461 +0,0 @@ -<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
-<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
-
-<glade-interface>
-
-<widget class="GtkDialog" id="loginDialog">
- <property name="title" translatable="yes">Login</property>
- <property name="type">GTK_WINDOW_TOPLEVEL</property>
- <property name="window_position">GTK_WIN_POS_NONE</property>
- <property name="modal">False</property>
- <property name="resizable">True</property>
- <property name="destroy_with_parent">True</property>
- <property name="has_separator">True</property>
- <signal name="response" handler="_on_loginDialog_response" last_modification_time="Sat, 25 Jan 2003 13:52:57 GMT"/>
- <signal name="close" handler="_on_loginDialog_close" last_modification_time="Sat, 25 Jan 2003 13:53:04 GMT"/>
-
- <child internal-child="vbox">
- <widget class="GtkVBox" id="dialog-vbox1">
- <property name="visible">True</property>
- <property name="homogeneous">False</property>
- <property name="spacing">0</property>
-
- <child internal-child="action_area">
- <widget class="GtkHButtonBox" id="dialog-action_area1">
- <property name="visible">True</property>
- <property name="layout_style">GTK_BUTTONBOX_END</property>
-
- <child>
- <widget class="GtkButton" id="cancelbutton1">
- <property name="visible">True</property>
- <property name="can_default">True</property>
- <property name="can_focus">True</property>
- <property name="label">gtk-cancel</property>
- <property name="use_stock">True</property>
- <property name="relief">GTK_RELIEF_NORMAL</property>
- <property name="response_id">-6</property>
- </widget>
- </child>
-
- <child>
- <widget class="GtkButton" id="loginButton">
- <property name="visible">True</property>
- <property name="can_default">True</property>
- <property name="has_default">True</property>
- <property name="can_focus">True</property>
- <property name="relief">GTK_RELIEF_NORMAL</property>
- <property name="response_id">-5</property>
-
- <child>
- <widget class="GtkAlignment" id="alignment1">
- <property name="visible">True</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xscale">0</property>
- <property name="yscale">0</property>
-
- <child>
- <widget class="GtkHBox" id="hbox2">
- <property name="visible">True</property>
- <property name="homogeneous">False</property>
- <property name="spacing">2</property>
-
- <child>
- <widget class="GtkImage" id="image1">
- <property name="visible">True</property>
- <property name="stock">gtk-ok</property>
- <property name="icon_size">4</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkLabel" id="label9">
- <property name="visible">True</property>
- <property name="label" translatable="yes">_Login</property>
- <property name="use_underline">True</property>
- <property name="use_markup">False</property>
- <property name="justify">GTK_JUSTIFY_LEFT</property>
- <property name="wrap">False</property>
- <property name="selectable">False</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
- </widget>
- </child>
- </widget>
- </child>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="pack_type">GTK_PACK_END</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkStatusbar" id="statusBar">
- <property name="visible">True</property>
- <property name="has_resize_grip">False</property>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="pack_type">GTK_PACK_END</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkTable" id="table1">
- <property name="visible">True</property>
- <property name="n_rows">6</property>
- <property name="n_columns">2</property>
- <property name="homogeneous">False</property>
- <property name="row_spacing">2</property>
- <property name="column_spacing">0</property>
-
- <child>
- <widget class="GtkLabel" id="hostLabel">
- <property name="visible">True</property>
- <property name="label" translatable="yes">_Host:</property>
- <property name="use_underline">True</property>
- <property name="use_markup">False</property>
- <property name="justify">GTK_JUSTIFY_LEFT</property>
- <property name="wrap">False</property>
- <property name="selectable">False</property>
- <property name="xalign">0.9</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- <property name="mnemonic_widget">hostEntry</property>
- <accessibility>
- <atkrelation target="hostEntry" type="label-for"/>
- <atkrelation target="portEntry" type="label-for"/>
- </accessibility>
- </widget>
- <packing>
- <property name="left_attach">0</property>
- <property name="right_attach">1</property>
- <property name="top_attach">0</property>
- <property name="bottom_attach">1</property>
- <property name="x_options">fill</property>
- <property name="y_options"></property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkHBox" id="hbox1">
- <property name="visible">True</property>
- <property name="homogeneous">False</property>
- <property name="spacing">0</property>
-
- <child>
- <widget class="GtkEntry" id="hostEntry">
- <property name="visible">True</property>
- <property name="tooltip" translatable="yes">The name of a host to connect to.</property>
- <property name="can_focus">True</property>
- <property name="has_focus">True</property>
- <property name="editable">True</property>
- <property name="visibility">True</property>
- <property name="max_length">0</property>
- <property name="text" translatable="yes">localhost</property>
- <property name="has_frame">True</property>
- <property name="invisible_char" translatable="yes">*</property>
- <property name="activates_default">True</property>
- <accessibility>
- <atkrelation target="hostLabel" type="labelled-by"/>
- </accessibility>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">True</property>
- <property name="fill">True</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkEntry" id="portEntry">
- <property name="visible">True</property>
- <property name="tooltip" translatable="yes">The number of a port to connect on.</property>
- <property name="can_focus">True</property>
- <property name="editable">True</property>
- <property name="visibility">True</property>
- <property name="max_length">0</property>
- <property name="text" translatable="yes">8787</property>
- <property name="has_frame">True</property>
- <property name="invisible_char" translatable="yes">*</property>
- <property name="activates_default">True</property>
- <property name="width_chars">5</property>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">True</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">0</property>
- <property name="bottom_attach">1</property>
- <property name="y_options">fill</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkLabel" id="nameLabel">
- <property name="visible">True</property>
- <property name="label" translatable="yes">_Name:</property>
- <property name="use_underline">True</property>
- <property name="use_markup">False</property>
- <property name="justify">GTK_JUSTIFY_LEFT</property>
- <property name="wrap">False</property>
- <property name="selectable">False</property>
- <property name="xalign">0.9</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- <property name="mnemonic_widget">identityNameEntry</property>
- </widget>
- <packing>
- <property name="left_attach">0</property>
- <property name="right_attach">1</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options">fill</property>
- <property name="y_options"></property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkEntry" id="identityNameEntry">
- <property name="visible">True</property>
- <property name="tooltip" translatable="yes">An identity to log in as.</property>
- <property name="can_focus">True</property>
- <property name="editable">True</property>
- <property name="visibility">True</property>
- <property name="max_length">0</property>
- <property name="text" translatable="yes"></property>
- <property name="has_frame">True</property>
- <property name="invisible_char" translatable="yes">*</property>
- <property name="activates_default">True</property>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="y_options"></property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkEntry" id="passwordEntry">
- <property name="visible">True</property>
- <property name="tooltip" translatable="yes">The Identity's log-in password.</property>
- <property name="can_focus">True</property>
- <property name="editable">True</property>
- <property name="visibility">False</property>
- <property name="max_length">0</property>
- <property name="text" translatable="yes"></property>
- <property name="has_frame">True</property>
- <property name="invisible_char" translatable="yes">*</property>
- <property name="activates_default">True</property>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- <property name="y_options"></property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkLabel" id="passwordLabel">
- <property name="visible">True</property>
- <property name="label" translatable="yes">_Password:</property>
- <property name="use_underline">True</property>
- <property name="use_markup">False</property>
- <property name="justify">GTK_JUSTIFY_LEFT</property>
- <property name="wrap">False</property>
- <property name="selectable">False</property>
- <property name="xalign">0.9</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- <property name="mnemonic_widget">passwordEntry</property>
- </widget>
- <packing>
- <property name="left_attach">0</property>
- <property name="right_attach">1</property>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- <property name="x_options">fill</property>
- <property name="y_options"></property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkLabel" id="perspectiveLabel">
- <property name="label" translatable="yes">Perspective:</property>
- <property name="use_underline">False</property>
- <property name="use_markup">False</property>
- <property name="justify">GTK_JUSTIFY_LEFT</property>
- <property name="wrap">False</property>
- <property name="selectable">False</property>
- <property name="xalign">0.9</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- </widget>
- <packing>
- <property name="left_attach">0</property>
- <property name="right_attach">1</property>
- <property name="top_attach">5</property>
- <property name="bottom_attach">6</property>
- <property name="x_options">fill</property>
- <property name="y_options"></property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkEntry" id="perspectiveNameEntry">
- <property name="tooltip" translatable="yes">The name of a Perspective to request.</property>
- <property name="can_focus">True</property>
- <property name="editable">True</property>
- <property name="visibility">True</property>
- <property name="max_length">0</property>
- <property name="text" translatable="yes"></property>
- <property name="has_frame">True</property>
- <property name="invisible_char" translatable="yes">*</property>
- <property name="activates_default">False</property>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">5</property>
- <property name="bottom_attach">6</property>
- <property name="y_options"></property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkVBox" id="vbox1">
- <property name="visible">True</property>
- <property name="homogeneous">False</property>
- <property name="spacing">0</property>
-
- <child>
- <widget class="GtkLabel" id="protocolLabel">
- <property name="label" translatable="yes">Insert Protocol Version Here</property>
- <property name="use_underline">False</property>
- <property name="use_markup">False</property>
- <property name="justify">GTK_JUSTIFY_LEFT</property>
- <property name="wrap">False</property>
- <property name="selectable">False</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkLabel" id="versionLabel">
- <property name="label" translatable="yes">Insert Twisted Version Here</property>
- <property name="use_underline">False</property>
- <property name="use_markup">False</property>
- <property name="justify">GTK_JUSTIFY_LEFT</property>
- <property name="wrap">False</property>
- <property name="selectable">False</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="left_attach">0</property>
- <property name="right_attach">2</property>
- <property name="top_attach">4</property>
- <property name="bottom_attach">5</property>
- <property name="x_options">fill</property>
- <property name="y_options">fill</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkAlignment" id="alignment2">
- <property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="yalign">0.5</property>
- <property name="xscale">0</property>
- <property name="yscale">1</property>
-
- <child>
- <widget class="GtkToggleButton" id="advancedButton">
- <property name="visible">True</property>
- <property name="tooltip" translatable="yes">Advanced options.</property>
- <property name="can_focus">True</property>
- <property name="label" translatable="yes">Advanced >></property>
- <property name="use_underline">True</property>
- <property name="relief">GTK_RELIEF_NORMAL</property>
- <property name="active">False</property>
- <property name="inconsistent">False</property>
- <signal name="toggled" handler="_on_advancedButton_toggled" object="Login" last_modification_time="Sat, 25 Jan 2003 13:47:17 GMT"/>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="left_attach">0</property>
- <property name="right_attach">2</property>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
- <property name="y_options"></property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
- </widget>
- </child>
-</widget>
-
-</glade-interface>
diff --git a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/ui/tktree.py b/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/ui/tktree.py deleted file mode 100755 index 8fbe4624..00000000 --- a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/ui/tktree.py +++ /dev/null @@ -1,204 +0,0 @@ -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - -""" -What I want it to look like: - -+- One -| \- Two -| |- Three -| |- Four -| +- Five -| | \- Six -| |- Seven -+- Eight -| \- Nine -""" - -import os -from Tkinter import * - -class Node: - def __init__(self): - """ - Do whatever you want here. - """ - self.item=None - def getName(self): - """ - Return the name of this node in the tree. - """ - pass - def isExpandable(self): - """ - Return true if this node is expandable. - """ - return len(self.getSubNodes())>0 - def getSubNodes(self): - """ - Return the sub nodes of this node. - """ - return [] - def gotDoubleClick(self): - """ - Called when we are double clicked. - """ - pass - def updateMe(self): - """ - Call me when something about me changes, so that my representation - changes. - """ - if self.item: - self.item.update() - -class FileNode(Node): - def __init__(self,name): - Node.__init__(self) - self.name=name - def getName(self): - return os.path.basename(self.name) - def isExpandable(self): - return os.path.isdir(self.name) - def getSubNodes(self): - names=map(lambda x,n=self.name:os.path.join(n,x),os.listdir(self.name)) - return map(FileNode,names) - -class TreeItem: - def __init__(self,widget,parent,node): - self.widget=widget - self.node=node - node.item=self - if self.node.isExpandable(): - self.expand=0 - else: - self.expand=None - self.parent=parent - if parent: - self.level=self.parent.level+1 - else: - self.level=0 - self.first=0 # gets set in Tree.expand() - self.subitems=[] - def __del__(self): - del self.node - del self.widget - def __repr__(self): - return "<Item for Node %s at level %s>"%(self.node.getName(),self.level) - def render(self): - """ - Override in a subclass. - """ - raise NotImplementedError - def update(self): - self.widget.update(self) - -class ListboxTreeItem(TreeItem): - def render(self): - start=self.level*"| " - if self.expand==None and not self.first: - start=start+"|" - elif self.expand==0: - start=start+"L" - elif self.expand==1: - start=start+"+" - else: - start=start+"\\" - r=[start+"- "+self.node.getName()] - if self.expand: - for i in self.subitems: - r.extend(i.render()) - return r - -class ListboxTree: - def __init__(self,parent=None,**options): - self.box=apply(Listbox,[parent],options) - self.box.bind("<Double-1>",self.flip) - self.roots=[] - self.items=[] - def pack(self,*args,**kw): - """ - for packing. - """ - apply(self.box.pack,args,kw) - def grid(self,*args,**kw): - """ - for gridding. - """ - apply(self.box.grid,args,kw) - def yview(self,*args,**kw): - """ - for scrolling. - """ - apply(self.box.yview,args,kw) - def addRoot(self,node): - r=ListboxTreeItem(self,None,node) - self.roots.append(r) - self.items.append(r) - self.box.insert(END,r.render()[0]) - return r - def curselection(self): - c=self.box.curselection() - if not c: return - return self.items[int(c[0])] - def flip(self,*foo): - if not self.box.curselection(): return - item=self.items[int(self.box.curselection()[0])] - if item.expand==None: return - if not item.expand: - self.expand(item) - else: - self.close(item) - item.node.gotDoubleClick() - def expand(self,item): - if item.expand or item.expand==None: return - item.expand=1 - item.subitems=map(lambda x,i=item,s=self:ListboxTreeItem(s,i,x),item.node.getSubNodes()) - if item.subitems: - item.subitems[0].first=1 - i=self.items.index(item) - self.items,after=self.items[:i+1],self.items[i+1:] - self.items=self.items+item.subitems+after - c=self.items.index(item) - self.box.delete(c) - r=item.render() - for i in r: - self.box.insert(c,i) - c=c+1 - def close(self,item): - if not item.expand: return - item.expand=0 - length=len(item.subitems) - for i in item.subitems: - self.close(i) - c=self.items.index(item) - del self.items[c+1:c+1+length] - for i in range(length+1): - self.box.delete(c) - self.box.insert(c,item.render()[0]) - def remove(self,item): - if item.expand: - self.close(item) - c=self.items.index(item) - del self.items[c] - if item.parent: - item.parent.subitems.remove(item) - self.box.delete(c) - def update(self,item): - if item.expand==None: - c=self.items.index(item) - self.box.delete(c) - self.box.insert(c,item.render()[0]) - elif item.expand: - self.close(item) - self.expand(item) - -if __name__=="__main__": - tk=Tk() - s=Scrollbar() - t=ListboxTree(tk,yscrollcommand=s.set) - t.pack(side=LEFT,fill=BOTH) - s.config(command=t.yview) - s.pack(side=RIGHT,fill=Y) - t.addRoot(FileNode("C:/")) - #mainloop() diff --git a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/ui/tkutil.py b/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/ui/tkutil.py deleted file mode 100755 index 2aee67d6..00000000 --- a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/ui/tkutil.py +++ /dev/null @@ -1,397 +0,0 @@ - -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - -"""Utilities for building L{PB<twisted.spread.pb>} clients with L{Tkinter}. -""" -from Tkinter import * -from tkSimpleDialog import _QueryString -from tkFileDialog import _Dialog -from twisted.spread import pb -from twisted.internet import reactor -from twisted import copyright - -import string - -#normalFont = Font("-adobe-courier-medium-r-normal-*-*-120-*-*-m-*-iso8859-1") -#boldFont = Font("-adobe-courier-bold-r-normal-*-*-120-*-*-m-*-iso8859-1") -#errorFont = Font("-adobe-courier-medium-o-normal-*-*-120-*-*-m-*-iso8859-1") - -class _QueryPassword(_QueryString): - def body(self, master): - - w = Label(master, text=self.prompt, justify=LEFT) - w.grid(row=0, padx=5, sticky=W) - - self.entry = Entry(master, name="entry",show="*") - self.entry.grid(row=1, padx=5, sticky=W+E) - - if self.initialvalue: - self.entry.insert(0, self.initialvalue) - self.entry.select_range(0, END) - - return self.entry - -def askpassword(title, prompt, **kw): - '''get a password from the user - - @param title: the dialog title - @param prompt: the label text - @param **kw: see L{SimpleDialog} class - - @returns: a string - ''' - d = apply(_QueryPassword, (title, prompt), kw) - return d.result - -def grid_setexpand(widget): - cols,rows=widget.grid_size() - for i in range(cols): - widget.columnconfigure(i,weight=1) - for i in range(rows): - widget.rowconfigure(i,weight=1) - -class CList(Frame): - def __init__(self,parent,labels,disablesorting=0,**kw): - Frame.__init__(self,parent) - self.labels=labels - self.lists=[] - self.disablesorting=disablesorting - kw["exportselection"]=0 - for i in range(len(labels)): - b=Button(self,text=labels[i],anchor=W,height=1,pady=0) - b.config(command=lambda s=self,i=i:s.setSort(i)) - b.grid(column=i,row=0,sticky=N+E+W) - box=apply(Listbox,(self,),kw) - box.grid(column=i,row=1,sticky=N+E+S+W) - self.lists.append(box) - grid_setexpand(self) - self.rowconfigure(0,weight=0) - self._callall("bind",'<Button-1>',self.Button1) - self._callall("bind",'<B1-Motion>',self.Button1) - self.bind('<Up>',self.UpKey) - self.bind('<Down>',self.DownKey) - self.sort=None - - def _callall(self,funcname,*args,**kw): - rets=[] - for l in self.lists: - func=getattr(l,funcname) - ret=apply(func,args,kw) - if ret!=None: rets.append(ret) - if rets: return rets - - def Button1(self,e): - index=self.nearest(e.y) - self.select_clear(0,END) - self.select_set(index) - self.activate(index) - return "break" - - def UpKey(self,e): - index=self.index(ACTIVE) - if index: - self.select_clear(0,END) - self.select_set(index-1) - return "break" - - def DownKey(self,e): - index=self.index(ACTIVE) - if index!=self.size()-1: - self.select_clear(0,END) - self.select_set(index+1) - return "break" - - def setSort(self,index): - if self.sort==None: - self.sort=[index,1] - elif self.sort[0]==index: - self.sort[1]=-self.sort[1] - else: - self.sort=[index,1] - self._sort() - - def _sort(self): - if self.disablesorting: - return - if self.sort==None: - return - ind,direc=self.sort - li=list(self.get(0,END)) - li.sort(lambda x,y,i=ind,d=direc:d*cmp(x[i],y[i])) - self.delete(0,END) - for l in li: - self._insert(END,l) - def activate(self,index): - self._callall("activate",index) - - # def bbox(self,index): - # return self._callall("bbox",index) - - def curselection(self): - return self.lists[0].curselection() - - def delete(self,*args): - apply(self._callall,("delete",)+args) - - def get(self,*args): - bad=apply(self._callall,("get",)+args) - if len(args)==1: - return bad - ret=[] - for i in range(len(bad[0])): - r=[] - for j in range(len(bad)): - r.append(bad[j][i]) - ret.append(r) - return ret - - def index(self,index): - return self.lists[0].index(index) - - def insert(self,index,items): - self._insert(index,items) - self._sort() - - def _insert(self,index,items): - for i in range(len(items)): - self.lists[i].insert(index,items[i]) - - def nearest(self,y): - return self.lists[0].nearest(y) - - def see(self,index): - self._callall("see",index) - - def size(self): - return self.lists[0].size() - - def selection_anchor(self,index): - self._callall("selection_anchor",index) - - select_anchor=selection_anchor - - def selection_clear(self,*args): - apply(self._callall,("selection_clear",)+args) - - select_clear=selection_clear - - def selection_includes(self,index): - return self.lists[0].select_includes(index) - - select_includes=selection_includes - - def selection_set(self,*args): - apply(self._callall,("selection_set",)+args) - - select_set=selection_set - - def xview(self,*args): - if not args: return self.lists[0].xview() - apply(self._callall,("xview",)+args) - - def yview(self,*args): - if not args: return self.lists[0].yview() - apply(self._callall,("yview",)+args) - -class ProgressBar: - def __init__(self, master=None, orientation="horizontal", - min=0, max=100, width=100, height=18, - doLabel=1, appearance="sunken", - fillColor="blue", background="gray", - labelColor="yellow", labelFont="Verdana", - labelText="", labelFormat="%d%%", - value=0, bd=2): - # preserve various values - self.master=master - self.orientation=orientation - self.min=min - self.max=max - self.width=width - self.height=height - self.doLabel=doLabel - self.fillColor=fillColor - self.labelFont= labelFont - self.labelColor=labelColor - self.background=background - self.labelText=labelText - self.labelFormat=labelFormat - self.value=value - self.frame=Frame(master, relief=appearance, bd=bd) - self.canvas=Canvas(self.frame, height=height, width=width, bd=0, - highlightthickness=0, background=background) - self.scale=self.canvas.create_rectangle(0, 0, width, height, - fill=fillColor) - self.label=self.canvas.create_text(self.canvas.winfo_reqwidth() / 2, - height / 2, text=labelText, - anchor="c", fill=labelColor, - font=self.labelFont) - self.update() - self.canvas.pack(side='top', fill='x', expand='no') - - def updateProgress(self, newValue, newMax=None): - if newMax: - self.max = newMax - self.value = newValue - self.update() - - def update(self): - # Trim the values to be between min and max - value=self.value - if value > self.max: - value = self.max - if value < self.min: - value = self.min - # Adjust the rectangle - if self.orientation == "horizontal": - self.canvas.coords(self.scale, 0, 0, - float(value) / self.max * self.width, self.height) - else: - self.canvas.coords(self.scale, 0, - self.height - (float(value) / - self.max*self.height), - self.width, self.height) - # Now update the colors - self.canvas.itemconfig(self.scale, fill=self.fillColor) - self.canvas.itemconfig(self.label, fill=self.labelColor) - # And update the label - if self.doLabel: - if value: - if value >= 0: - pvalue = int((float(value) / float(self.max)) * - 100.0) - else: - pvalue = 0 - self.canvas.itemconfig(self.label, text=self.labelFormat - % pvalue) - else: - self.canvas.itemconfig(self.label, text='') - else: - self.canvas.itemconfig(self.label, text=self.labelFormat % - self.labelText) - self.canvas.update_idletasks() - -class DirectoryBrowser(_Dialog): - command = "tk_chooseDirectory" - -def askdirectory(**options): - "Ask for a directory to save to." - - return apply(DirectoryBrowser, (), options).show() - -class GenericLogin(Toplevel): - def __init__(self,callback,buttons): - Toplevel.__init__(self) - self.callback=callback - Label(self,text="Twisted v%s"%copyright.version).grid(column=0,row=0,columnspan=2) - self.entries={} - row=1 - for stuff in buttons: - label,value=stuff[:2] - if len(stuff)==3: - dict=stuff[2] - else: dict={} - Label(self,text=label+": ").grid(column=0,row=row) - e=apply(Entry,(self,),dict) - e.grid(column=1,row=row) - e.insert(0,value) - self.entries[label]=e - row=row+1 - Button(self,text="Login",command=self.doLogin).grid(column=0,row=row) - Button(self,text="Cancel",command=self.close).grid(column=1,row=row) - self.protocol('WM_DELETE_WINDOW',self.close) - - def close(self): - self.tk.quit() - self.destroy() - - def doLogin(self): - values={} - for k in self.entries.keys(): - values[string.lower(k)]=self.entries[k].get() - self.callback(values) - self.destroy() - -class Login(Toplevel): - def __init__(self, - callback, - referenced = None, - initialUser = "guest", - initialPassword = "guest", - initialHostname = "localhost", - initialService = "", - initialPortno = pb.portno): - Toplevel.__init__(self) - version_label = Label(self,text="Twisted v%s" % copyright.version) - self.pbReferenceable = referenced - self.pbCallback = callback - # version_label.show() - self.username = Entry(self) - self.password = Entry(self,show='*') - self.hostname = Entry(self) - self.service = Entry(self) - self.port = Entry(self) - - self.username.insert(0,initialUser) - self.password.insert(0,initialPassword) - self.service.insert(0,initialService) - self.hostname.insert(0,initialHostname) - self.port.insert(0,str(initialPortno)) - - userlbl=Label(self,text="Username:") - passlbl=Label(self,text="Password:") - servicelbl=Label(self,text="Service:") - hostlbl=Label(self,text="Hostname:") - portlbl=Label(self,text="Port #:") - self.logvar=StringVar() - self.logvar.set("Protocol PB-%s"%pb.Broker.version) - self.logstat = Label(self,textvariable=self.logvar) - self.okbutton = Button(self,text="Log In", command=self.login) - - version_label.grid(column=0,row=0,columnspan=2) - z=0 - for i in [[userlbl,self.username], - [passlbl,self.password], - [hostlbl,self.hostname], - [servicelbl,self.service], - [portlbl,self.port]]: - i[0].grid(column=0,row=z+1) - i[1].grid(column=1,row=z+1) - z = z+1 - - self.logstat.grid(column=0,row=6,columnspan=2) - self.okbutton.grid(column=0,row=7,columnspan=2) - - self.protocol('WM_DELETE_WINDOW',self.tk.quit) - - def loginReset(self): - self.logvar.set("Idle.") - - def loginReport(self, txt): - self.logvar.set(txt) - self.after(30000, self.loginReset) - - def login(self): - host = self.hostname.get() - port = self.port.get() - service = self.service.get() - try: - port = int(port) - except: - pass - user = self.username.get() - pswd = self.password.get() - pb.connect(host, port, user, pswd, service, - client=self.pbReferenceable).addCallback(self.pbCallback).addErrback( - self.couldNotConnect) - - def couldNotConnect(self,f): - self.loginReport("could not connect:"+f.getErrorMessage()) - -if __name__=="__main__": - root=Tk() - o=CList(root,["Username","Online","Auto-Logon","Gateway"]) - o.pack() - for i in range(0,16,4): - o.insert(END,[i,i+1,i+2,i+3]) - mainloop() diff --git a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/util.py b/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/util.py deleted file mode 100755 index 3c529b4e..00000000 --- a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/spread/util.py +++ /dev/null @@ -1,215 +0,0 @@ -# -*- test-case-name: twisted.test.test_pb -*- - -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - - -""" -Utility classes for spread. -""" - -from twisted.internet import defer -from twisted.python.failure import Failure -from twisted.spread import pb -from twisted.protocols import basic -from twisted.internet import interfaces - -from zope.interface import implements - - -class LocalMethod: - def __init__(self, local, name): - self.local = local - self.name = name - - def __call__(self, *args, **kw): - return self.local.callRemote(self.name, *args, **kw) - - -class LocalAsRemote: - """ - A class useful for emulating the effects of remote behavior locally. - """ - reportAllTracebacks = 1 - - def callRemote(self, name, *args, **kw): - """ - Call a specially-designated local method. - - self.callRemote('x') will first try to invoke a method named - sync_x and return its result (which should probably be a - Deferred). Second, it will look for a method called async_x, - which will be called and then have its result (or Failure) - automatically wrapped in a Deferred. - """ - if hasattr(self, 'sync_'+name): - return getattr(self, 'sync_'+name)(*args, **kw) - try: - method = getattr(self, "async_" + name) - return defer.succeed(method(*args, **kw)) - except: - f = Failure() - if self.reportAllTracebacks: - f.printTraceback() - return defer.fail(f) - - def remoteMethod(self, name): - return LocalMethod(self, name) - - -class LocalAsyncForwarder: - """ - A class useful for forwarding a locally-defined interface. - """ - - def __init__(self, forwarded, interfaceClass, failWhenNotImplemented=0): - assert interfaceClass.providedBy(forwarded) - self.forwarded = forwarded - self.interfaceClass = interfaceClass - self.failWhenNotImplemented = failWhenNotImplemented - - def _callMethod(self, method, *args, **kw): - return getattr(self.forwarded, method)(*args, **kw) - - def callRemote(self, method, *args, **kw): - if self.interfaceClass.queryDescriptionFor(method): - result = defer.maybeDeferred(self._callMethod, method, *args, **kw) - return result - elif self.failWhenNotImplemented: - return defer.fail( - Failure(NotImplementedError, - "No Such Method in Interface: %s" % method)) - else: - return defer.succeed(None) - - -class Pager: - """ - I am an object which pages out information. - """ - def __init__(self, collector, callback=None, *args, **kw): - """ - Create a pager with a Reference to a remote collector and - an optional callable to invoke upon completion. - """ - if callable(callback): - self.callback = callback - self.callbackArgs = args - self.callbackKeyword = kw - else: - self.callback = None - self._stillPaging = 1 - self.collector = collector - collector.broker.registerPageProducer(self) - - def stillPaging(self): - """ - (internal) Method called by Broker. - """ - if not self._stillPaging: - self.collector.callRemote("endedPaging") - if self.callback is not None: - self.callback(*self.callbackArgs, **self.callbackKeyword) - return self._stillPaging - - def sendNextPage(self): - """ - (internal) Method called by Broker. - """ - self.collector.callRemote("gotPage", self.nextPage()) - - def nextPage(self): - """ - Override this to return an object to be sent to my collector. - """ - raise NotImplementedError() - - def stopPaging(self): - """ - Call this when you're done paging. - """ - self._stillPaging = 0 - - -class StringPager(Pager): - """ - A simple pager that splits a string into chunks. - """ - def __init__(self, collector, st, chunkSize=8192, callback=None, *args, **kw): - self.string = st - self.pointer = 0 - self.chunkSize = chunkSize - Pager.__init__(self, collector, callback, *args, **kw) - - def nextPage(self): - val = self.string[self.pointer:self.pointer+self.chunkSize] - self.pointer += self.chunkSize - if self.pointer >= len(self.string): - self.stopPaging() - return val - - -class FilePager(Pager): - """ - Reads a file in chunks and sends the chunks as they come. - """ - implements(interfaces.IConsumer) - - def __init__(self, collector, fd, callback=None, *args, **kw): - self.chunks = [] - Pager.__init__(self, collector, callback, *args, **kw) - self.startProducing(fd) - - def startProducing(self, fd): - self.deferred = basic.FileSender().beginFileTransfer(fd, self) - self.deferred.addBoth(lambda x : self.stopPaging()) - - def registerProducer(self, producer, streaming): - self.producer = producer - if not streaming: - self.producer.resumeProducing() - - def unregisterProducer(self): - self.producer = None - - def write(self, chunk): - self.chunks.append(chunk) - - def sendNextPage(self): - """ - Get the first chunk read and send it to collector. - """ - if not self.chunks: - return - val = self.chunks.pop(0) - self.producer.resumeProducing() - self.collector.callRemote("gotPage", val) - - -# Utility paging stuff. -class CallbackPageCollector(pb.Referenceable): - """ - I receive pages from the peer. You may instantiate a Pager with a - remote reference to me. I will call the callback with a list of pages - once they are all received. - """ - def __init__(self, callback): - self.pages = [] - self.callback = callback - - def remote_gotPage(self, page): - self.pages.append(page) - - def remote_endedPaging(self): - self.callback(self.pages) - - -def getAllPages(referenceable, methodName, *args, **kw): - """ - A utility method that will call a remote method which expects a - PageCollector as the first argument. - """ - d = defer.Deferred() - referenceable.callRemote(methodName, CallbackPageCollector(d.callback), *args, **kw) - return d - |