Ejemplo n.º 1
0
 def __init__(self):
   self.objects = {}
   self.services = ServiceCollection()
   self.__obj_lock = Lock()
   self.interpreter = Interpreter(self)
Ejemplo n.º 2
0
class Registrar(object):
  """
    The Registrar defines a collection where services and objects can
    be registered. Other classes can then use and listen for those
    services and objects.

  """

  class _RepoSvc(object):  # pylint: disable-msg=R0903
    """ Repository Service
        Consists of the service function, a grammar that defines how
        a POS tagged query is to be turned into the service's arguments
        (structure defined in interpreter.py), a lock that controls
        concurrent access to the service, and an optional namespace to
        prevent plugins offering similar/same services from stepping on
        each others' toes.

    """
    def __init__(self, name, svc, grammar=None, usage='', namespace=None):
      self.name = name
      self.svc = svc
      self.grammar = grammar
      self.usage = usage
      self.namespace = namespace
      self.lock = Lock()

  class _RepoObj(object):  # pylint: disable-msg=R0903
    """ Repository Object
        Consists of an object placed into the repository and an event
        that handles alerting interested parties of changes to the object.
        The object itself should only change upon calls to register_object().
        Any changes to complex types may not produce a change_event signal.

    """
    def __init__(self, obj):
      self.obj = obj
      self.change_event = Event()

  def __init__(self):
    self.objects = {}
    self.services = ServiceCollection()
    self.__obj_lock = Lock()
    self.interpreter = Interpreter(self)

  def find_best_service(self, query):
    """Use the interpreter to find the single best
    (service, namespace, arguments) triplet for the given query.

    """
    return self.interpreter.best_interpretation(query)

  def find_services(self, query):
    """Use the interpreter to turn the query into a list of
    (service, namespace, arguments) triplets.

    """
    return self.interpreter.interpret(query)

  def register_service(self, svc_name, svc_func,
      grammar=None, usage='', namespace=None):
    """Register a function to be made available to clients and plugins.
    
    Keyword arguments:
    svc_name -- the name the service is registered under (may be a duplicate
      of an existing service)
    svc_func -- the function called when the service is requested
    grammar -- the grammar (defined in the Interpreter) that describes how
      keyword arguments for svc_func are assembled (default None)
    usage -- a string quickly defining how to use the service. Any
      occurrance of '%s' in the usage will be replaced with the name
      of the service. (default '')
    namespace -- any hashable object (preferably a string). When combined
      with svc_name, it is used to uniquely identify a specific implementation
      of a service. If both the svc_name and namespace collide, the service is
      overwritten. (default None)

    """
    usage = usage.replace('%s', svc_name)
    name = svc_name.lower()
    self.services.add(name, namespace, self._RepoSvc(
        name=name, svc=svc_func, grammar=grammar,
        usage=usage, namespace=namespace))

  def unregister_service(self, svc_name, namespace=None):
    """Remove the registered service with the provided name and
    (optional) namespace.

    """
    svc_name = svc_name.lower()
    svc = self.services.get(svc_name, namespace)
    if svc:
      with locked(svc.lock):
        self.services.remove(svc_name, namespace)

  def request_service(self, svc_name, namespace=None, argdict=None, **kwargs):
    """Call the service registered to svc_name with the specified (optional)
    namespace and given kwargs.

    """
    svc_name = svc_name.lower()
    if not self.services.get(svc_name, namespace):
      raise ServiceDoesNotExist("Service does not exist.")
    service = self.services.get(svc_name, namespace)
    with locked(service.lock):
      if argdict:
        try:
          kwargs.update(argdict)
        except AttributeError:
          pass
      return service.svc(**kwargs)

  def register_object(self, obj_name, obj):
    """Create a shallow copy of the provided object and register it.
    WARNING: Anything beyond simple objects may be changed without warning
    by other plugins.

    """
    obj_name = obj_name.lower()
    with locked(self.__obj_lock):
      if obj_name not in self.objects:
        self.objects[obj_name] = self._RepoObj(_copy(obj))
      else:
        self.objects[obj_name].obj = obj

      # Prevents the handler from needing a call to get_object
      self.objects[obj_name].change_event.fire(obj)

  def remove_object(self, obj_name):
    """Remove a registered object from the internal cache."""
    obj_name = obj_name.lower()
    with locked(self.__obj_lock):
      del self.objects[obj_name]

  def register_object_listener(self, obj_name, callback):
    """Register a callback to be executed whenever an object with the
    specified name is registered.
    
    Callback should take one argument - the new object

    """
    obj_name = obj_name.lower()
    if obj_name not in self.objects:
      self.objects[obj_name] = self._RepoObj(None)

    self.objects[obj_name].change_event += callback

  def remove_object_listener(self, obj_name, callback):
    """Remove the given callback from being run when the object registered
    under obj_name is updated. Must be called with the same function the
    listener was registered with.

    """
    obj_name = obj_name.lower()
    if obj_name in self.objects:
      self.objects[obj_name].change_event -= callback

  def get_object(self, obj_name):
    """Return a shallow copy of the object in the repository.
    WARNING: Anything beyond simple objects may be changed without warning
    by other plugins.

    """
    obj_name = obj_name.lower()
    if obj_name not in self.objects or self.objects[obj_name] is None:
      raise ObjectDoesNotExist(obj_name)
    return _copy(self.objects[obj_name].obj)
Ejemplo n.º 3
0
 def __init__(self):
     self.objects = {}
     self.services = ServiceCollection()
     self.__obj_lock = Lock()
     self.interpreter = Interpreter(self)
Ejemplo n.º 4
0
 def __init__(self):
     self.local_registrar = Registrar()
     self.remote_registrars = defaultdict(dict)
     self.interpreter = Interpreter(self)
Ejemplo n.º 5
0
class Registrar(object):
    """
    The Registrar defines a collection where services and objects can
    be registered. Other classes can then use and listen for those
    services and objects.

  """
    class _RepoSvc(object):  # pylint: disable-msg=R0903
        """ Repository Service
        Consists of the service function, a grammar that defines how
        a POS tagged query is to be turned into the service's arguments
        (structure defined in interpreter.py), a lock that controls
        concurrent access to the service, and an optional namespace to
        prevent plugins offering similar/same services from stepping on
        each others' toes.

    """
        def __init__(self, name, svc, grammar=None, usage='', namespace=None):
            self.name = name
            self.svc = svc
            self.grammar = grammar
            self.usage = usage
            self.namespace = namespace
            self.lock = Lock()

    class _RepoObj(object):  # pylint: disable-msg=R0903
        """ Repository Object
        Consists of an object placed into the repository and an event
        that handles alerting interested parties of changes to the object.
        The object itself should only change upon calls to register_object().
        Any changes to complex types may not produce a change_event signal.

    """
        def __init__(self, obj):
            self.obj = obj
            self.change_event = Event()

    def __init__(self):
        self.objects = {}
        self.services = ServiceCollection()
        self.__obj_lock = Lock()
        self.interpreter = Interpreter(self)

    def find_best_service(self, query):
        """Use the interpreter to find the single best
    (service, namespace, arguments) triplet for the given query.

    """
        return self.interpreter.best_interpretation(query)

    def find_services(self, query):
        """Use the interpreter to turn the query into a list of
    (service, namespace, arguments) triplets.

    """
        return self.interpreter.interpret(query)

    def register_service(self,
                         svc_name,
                         svc_func,
                         grammar=None,
                         usage='',
                         namespace=None):
        """Register a function to be made available to clients and plugins.
    
    Keyword arguments:
    svc_name -- the name the service is registered under (may be a duplicate
      of an existing service)
    svc_func -- the function called when the service is requested
    grammar -- the grammar (defined in the Interpreter) that describes how
      keyword arguments for svc_func are assembled (default None)
    usage -- a string quickly defining how to use the service. Any
      occurrance of '%s' in the usage will be replaced with the name
      of the service. (default '')
    namespace -- any hashable object (preferably a string). When combined
      with svc_name, it is used to uniquely identify a specific implementation
      of a service. If both the svc_name and namespace collide, the service is
      overwritten. (default None)

    """
        usage = usage.replace('%s', svc_name)
        name = svc_name.lower()
        self.services.add(
            name, namespace,
            self._RepoSvc(name=name,
                          svc=svc_func,
                          grammar=grammar,
                          usage=usage,
                          namespace=namespace))

    def unregister_service(self, svc_name, namespace=None):
        """Remove the registered service with the provided name and
    (optional) namespace.

    """
        svc_name = svc_name.lower()
        svc = self.services.get(svc_name, namespace)
        if svc:
            with locked(svc.lock):
                self.services.remove(svc_name, namespace)

    def request_service(self,
                        svc_name,
                        namespace=None,
                        argdict=None,
                        **kwargs):
        """Call the service registered to svc_name with the specified (optional)
    namespace and given kwargs.

    """
        svc_name = svc_name.lower()
        if not self.services.get(svc_name, namespace):
            raise ServiceDoesNotExist("Service does not exist.")
        service = self.services.get(svc_name, namespace)
        with locked(service.lock):
            if argdict:
                try:
                    kwargs.update(argdict)
                except AttributeError:
                    pass
            return service.svc(**kwargs)

    def register_object(self, obj_name, obj):
        """Create a shallow copy of the provided object and register it.
    WARNING: Anything beyond simple objects may be changed without warning
    by other plugins.

    """
        obj_name = obj_name.lower()
        with locked(self.__obj_lock):
            if obj_name not in self.objects:
                self.objects[obj_name] = self._RepoObj(_copy(obj))
            else:
                self.objects[obj_name].obj = obj

            # Prevents the handler from needing a call to get_object
            self.objects[obj_name].change_event.fire(obj)

    def remove_object(self, obj_name):
        """Remove a registered object from the internal cache."""
        obj_name = obj_name.lower()
        with locked(self.__obj_lock):
            del self.objects[obj_name]

    def register_object_listener(self, obj_name, callback):
        """Register a callback to be executed whenever an object with the
    specified name is registered.
    
    Callback should take one argument - the new object

    """
        obj_name = obj_name.lower()
        if obj_name not in self.objects:
            self.objects[obj_name] = self._RepoObj(None)

        self.objects[obj_name].change_event += callback

    def remove_object_listener(self, obj_name, callback):
        """Remove the given callback from being run when the object registered
    under obj_name is updated. Must be called with the same function the
    listener was registered with.

    """
        obj_name = obj_name.lower()
        if obj_name in self.objects:
            self.objects[obj_name].change_event -= callback

    def get_object(self, obj_name):
        """Return a shallow copy of the object in the repository.
    WARNING: Anything beyond simple objects may be changed without warning
    by other plugins.

    """
        obj_name = obj_name.lower()
        if obj_name not in self.objects or self.objects[obj_name] is None:
            raise ObjectDoesNotExist(obj_name)
        return _copy(self.objects[obj_name].obj)