Example #1
0
 def __init__(self, reference):
     self.reference = reference
     self._id = None
     self._properties = StrictDict()
     self.currentCommand = None
Example #2
0
 def __init__(self, reference):
     self.reference = reference
     self._id = None
     self._properties = StrictDict()
     self.currentCommand = None
Example #3
0
class EngineFromReference(object):
    """Adapt a `RemoteReference` to an `IEngineBase` implementing object.
    
    When an engine connects to a controller, it calls the `register_engine`
    method of the controller and passes the controller a `RemoteReference` to
    itself.  This class is used to adapt this `RemoteReference` to an object
    that implements the full `IEngineBase` interface.
    
    See the documentation of `IEngineBase` for details on the methods.
    """
    
    implements(IEngineBase)
    
    def __init__(self, reference):
        self.reference = reference
        self._id = None
        self._properties = StrictDict()
        self.currentCommand = None
    
    def callRemote(self, *args, **kwargs):
        try:
            return self.reference.callRemote(*args, **kwargs)
        except DeadReferenceError:
            self.notifier()
            self.stopNotifying(self.notifier)
            return defer.fail()
    
    def get_id(self):
        """Return the Engines id."""
        return self._id
    
    def set_id(self, id):
        """Set the Engines id."""
        self._id = id
        return self.callRemote('set_id', id)
    
    id = property(get_id, set_id)
    
    def syncProperties(self, r):
        try:
            psync, result = r
        except (ValueError, TypeError):
            return r
        else:
            if psync:
                log.msg("sync properties")
                pick = self.checkReturnForFailure(psync)
                if isinstance(pick, failure.Failure):
                    self.properties = pick
                    return pick
                else:
                    self.properties = pickle.loads(pick)
            return result
    
    def _set_properties(self, dikt):
        self._properties.clear()
        self._properties.update(dikt)
    
    def _get_properties(self):
        if isinstance(self._properties, failure.Failure):
            self._properties.raiseException()
        return self._properties
    
    properties = property(_get_properties, _set_properties)
    
    #---------------------------------------------------------------------------
    # Methods from IEngine
    #---------------------------------------------------------------------------
    
    #---------------------------------------------------------------------------
    # execute
    #---------------------------------------------------------------------------
    
    def execute(self, lines):
        # self._needProperties = True
        d = self.callRemote('execute', lines)
        d.addCallback(self.syncProperties)
        return d.addCallback(self.checkReturnForFailure)
    
    #---------------------------------------------------------------------------
    # push
    #---------------------------------------------------------------------------
    
    def push(self, namespace):
        try:
            package = pickle.dumps(namespace, 2)
        except:
            return defer.fail(failure.Failure())
        else:
            if isinstance(package, failure.Failure):
                return defer.fail(package)
            else:
                d = self.callRemote('push', package)
                return d.addCallback(self.checkReturnForFailure)
    
    #---------------------------------------------------------------------------
    # pull
    #---------------------------------------------------------------------------
    
    def pull(self, keys):
        d = self.callRemote('pull', keys)
        d.addCallback(self.checkReturnForFailure)
        d.addCallback(pickle.loads)
        return d
    
    #---------------------------------------------------------------------------
    # push/pull_function
    #---------------------------------------------------------------------------
    
    def push_function(self, namespace):
        try:
            package = pickle.dumps(canDict(namespace), 2)
        except:
            return defer.fail(failure.Failure())
        else:
            if isinstance(package, failure.Failure):
                return defer.fail(package)
            else:
                d = self.callRemote('push_function', package)
                return d.addCallback(self.checkReturnForFailure)    
    
    def pull_function(self, keys):
        d = self.callRemote('pull_function', keys)
        d.addCallback(self.checkReturnForFailure)
        d.addCallback(pickle.loads)
        # The usage of globals() here is an attempt to bind any pickled functions
        # to the globals of this module.  What we really want is to have it bound
        # to the globals of the callers module.  This will require walking the 
        # stack.  BG 10/3/07.
        if len(keys)==1:
            d.addCallback(uncan, globals())
        elif len(keys)>1:
            d.addCallback(uncanSequence, globals())            
        return d
    
    #---------------------------------------------------------------------------
    # Other methods
    #---------------------------------------------------------------------------
    
    def get_result(self, i=None):
        return self.callRemote('get_result', i).addCallback(self.checkReturnForFailure)
    
    def reset(self):
        self._refreshProperties = True
        d = self.callRemote('reset')
        d.addCallback(self.syncProperties)
        return d.addCallback(self.checkReturnForFailure)
    
    def kill(self):
        #this will raise pb.PBConnectionLost on success
        d = self.callRemote('kill')
        d.addCallback(self.syncProperties)
        d.addCallback(self.checkReturnForFailure)
        d.addErrback(self.killBack)
        return d
    
    def killBack(self, f):
        log.msg('filling engine: %s' % f)
        return None
    
    def keys(self):
        return self.callRemote('keys').addCallback(self.checkReturnForFailure)
    
    #---------------------------------------------------------------------------
    # Properties methods
    #---------------------------------------------------------------------------
    
    def set_properties(self, properties):
        try:
            package = pickle.dumps(properties, 2)
        except:
            return defer.fail(failure.Failure())
        else:
            if isinstance(package, failure.Failure):
                return defer.fail(package)
            else:
                d = self.callRemote('set_properties', package)
                return d.addCallback(self.checkReturnForFailure)
        return d
    
    def get_properties(self, keys=None):
        d = self.callRemote('get_properties', keys)
        d.addCallback(self.checkReturnForFailure)
        d.addCallback(pickle.loads)
        return d
    
    def has_properties(self, keys):
        d = self.callRemote('has_properties', keys)
        d.addCallback(self.checkReturnForFailure)
        d.addCallback(pickle.loads)
        return d
    
    def del_properties(self, keys):
        d = self.callRemote('del_properties', keys)
        d.addCallback(self.checkReturnForFailure)
        # d.addCallback(pickle.loads)
        return d
    
    def clear_properties(self):
        d = self.callRemote('clear_properties')
        d.addCallback(self.checkReturnForFailure)
        return d
    
    #---------------------------------------------------------------------------
    # push/pull_serialized
    #---------------------------------------------------------------------------
    
    def push_serialized(self, namespace):
        """Older version of pushSerialize."""
        try:
            package = pickle.dumps(namespace, 2)
        except:
            return defer.fail(failure.Failure())
        else:
            if isinstance(package, failure.Failure):
                return defer.fail(package)
            else:
                d = self.callRemote('push_serialized', package)
                return d.addCallback(self.checkReturnForFailure)
    
    def pull_serialized(self, keys):
        d = self.callRemote('pull_serialized', keys)
        d.addCallback(self.checkReturnForFailure)
        d.addCallback(pickle.loads)
        return d
    
    #---------------------------------------------------------------------------
    # Misc
    #---------------------------------------------------------------------------
     
    def checkReturnForFailure(self, r):
        """See if a returned value is a pickled Failure object.
        
        To distinguish between general pickled objects and pickled Failures, the
        other side should prepend the string FAILURE: to any pickled Failure.
        """
        return unpackageFailure(r)
Example #4
0
class EngineFromReference(object):
    """Adapt a `RemoteReference` to an `IEngineBase` implementing object.
    
    When an engine connects to a controller, it calls the `register_engine`
    method of the controller and passes the controller a `RemoteReference` to
    itself.  This class is used to adapt this `RemoteReference` to an object
    that implements the full `IEngineBase` interface.
    
    See the documentation of `IEngineBase` for details on the methods.
    """
    
    implements(IEngineBase)
    
    def __init__(self, reference):
        self.reference = reference
        self._id = None
        self._properties = StrictDict()
        self.currentCommand = None
    
    def callRemote(self, *args, **kwargs):
        try:
            return self.reference.callRemote(*args, **kwargs)
        except DeadReferenceError:
            self.notifier()
            self.stopNotifying(self.notifier)
            return defer.fail()
    
    def get_id(self):
        """Return the Engines id."""
        return self._id
    
    def set_id(self, id):
        """Set the Engines id."""
        self._id = id
        return self.callRemote('set_id', id)
    
    id = property(get_id, set_id)
    
    def syncProperties(self, r):
        try:
            psync, result = r
        except (ValueError, TypeError):
            return r
        else:
            if psync:
                log.msg("sync properties")
                pick = self.checkReturnForFailure(psync)
                if isinstance(pick, failure.Failure):
                    self.properties = pick
                    return pick
                else:
                    self.properties = pickle.loads(pick)
            return result
    
    def _set_properties(self, dikt):
        self._properties.clear()
        self._properties.update(dikt)
    
    def _get_properties(self):
        if isinstance(self._properties, failure.Failure):
            self._properties.raiseException()
        return self._properties
    
    properties = property(_get_properties, _set_properties)
    
    #---------------------------------------------------------------------------
    # Methods from IEngine
    #---------------------------------------------------------------------------
    
    #---------------------------------------------------------------------------
    # execute
    #---------------------------------------------------------------------------
    
    def execute(self, lines):
        # self._needProperties = True
        d = self.callRemote('execute', lines)
        d.addCallback(self.syncProperties)
        return d.addCallback(self.checkReturnForFailure)
    
    #---------------------------------------------------------------------------
    # push
    #---------------------------------------------------------------------------
    
    def push(self, namespace):
        try:
            package = pickle.dumps(namespace, 2)
        except:
            return defer.fail(failure.Failure())
        else:
            if isinstance(package, failure.Failure):
                return defer.fail(package)
            else:
                d = self.callRemote('push', package)
                return d.addCallback(self.checkReturnForFailure)
    
    #---------------------------------------------------------------------------
    # pull
    #---------------------------------------------------------------------------
    
    def pull(self, keys):
        d = self.callRemote('pull', keys)
        d.addCallback(self.checkReturnForFailure)
        d.addCallback(pickle.loads)
        return d
    
    #---------------------------------------------------------------------------
    # push/pull_function
    #---------------------------------------------------------------------------
    
    def push_function(self, namespace):
        try:
            package = pickle.dumps(canDict(namespace), 2)
        except:
            return defer.fail(failure.Failure())
        else:
            if isinstance(package, failure.Failure):
                return defer.fail(package)
            else:
                d = self.callRemote('push_function', package)
                return d.addCallback(self.checkReturnForFailure)    
    
    def pull_function(self, keys):
        d = self.callRemote('pull_function', keys)
        d.addCallback(self.checkReturnForFailure)
        d.addCallback(pickle.loads)
        # The usage of globals() here is an attempt to bind any pickled functions
        # to the globals of this module.  What we really want is to have it bound
        # to the globals of the callers module.  This will require walking the 
        # stack.  BG 10/3/07.
        if len(keys)==1:
            d.addCallback(uncan, globals())
        elif len(keys)>1:
            d.addCallback(uncanSequence, globals())            
        return d
    
    #---------------------------------------------------------------------------
    # Other methods
    #---------------------------------------------------------------------------
    
    def get_result(self, i=None):
        return self.callRemote('get_result', i).addCallback(self.checkReturnForFailure)
    
    def reset(self):
        self._refreshProperties = True
        d = self.callRemote('reset')
        d.addCallback(self.syncProperties)
        return d.addCallback(self.checkReturnForFailure)
    
    def kill(self):
        #this will raise pb.PBConnectionLost on success
        d = self.callRemote('kill')
        d.addCallback(self.syncProperties)
        d.addCallback(self.checkReturnForFailure)
        d.addErrback(self.killBack)
        return d
    
    def killBack(self, f):
        log.msg('filling engine: %s' % f)
        return None
    
    def keys(self):
        return self.callRemote('keys').addCallback(self.checkReturnForFailure)
    
    #---------------------------------------------------------------------------
    # Properties methods
    #---------------------------------------------------------------------------
    
    def set_properties(self, properties):
        try:
            package = pickle.dumps(properties, 2)
        except:
            return defer.fail(failure.Failure())
        else:
            if isinstance(package, failure.Failure):
                return defer.fail(package)
            else:
                d = self.callRemote('set_properties', package)
                return d.addCallback(self.checkReturnForFailure)
        return d
    
    def get_properties(self, keys=None):
        d = self.callRemote('get_properties', keys)
        d.addCallback(self.checkReturnForFailure)
        d.addCallback(pickle.loads)
        return d
    
    def has_properties(self, keys):
        d = self.callRemote('has_properties', keys)
        d.addCallback(self.checkReturnForFailure)
        d.addCallback(pickle.loads)
        return d
    
    def del_properties(self, keys):
        d = self.callRemote('del_properties', keys)
        d.addCallback(self.checkReturnForFailure)
        # d.addCallback(pickle.loads)
        return d
    
    def clear_properties(self):
        d = self.callRemote('clear_properties')
        d.addCallback(self.checkReturnForFailure)
        return d
    
    #---------------------------------------------------------------------------
    # push/pull_serialized
    #---------------------------------------------------------------------------
    
    def push_serialized(self, namespace):
        """Older version of pushSerialize."""
        try:
            package = pickle.dumps(namespace, 2)
        except:
            return defer.fail(failure.Failure())
        else:
            if isinstance(package, failure.Failure):
                return defer.fail(package)
            else:
                d = self.callRemote('push_serialized', package)
                return d.addCallback(self.checkReturnForFailure)
    
    def pull_serialized(self, keys):
        d = self.callRemote('pull_serialized', keys)
        d.addCallback(self.checkReturnForFailure)
        d.addCallback(pickle.loads)
        return d
    
    #---------------------------------------------------------------------------
    # Misc
    #---------------------------------------------------------------------------
     
    def checkReturnForFailure(self, r):
        """See if a returned value is a pickled Failure object.
        
        To distinguish between general pickled objects and pickled Failures, the
        other side should prepend the string FAILURE: to any pickled Failure.
        """
        return unpackageFailure(r)