From 3d9e04194d816f28621b6f3fdd5c73d58f271545 Mon Sep 17 00:00:00 2001 From: Mason Larobina Date: Fri, 1 Jan 2010 16:55:39 +0800 Subject: Correctness re-write of the export mechanism. Exporting is now done with the following two new functions: 1. `uzbl.export('external_name', function)` 2. `uzbl.export_dict({'name1': func1, 'name2': func2, ...})` This system is preferable to the old `__export__` variable for several reasons. The first being that the exporting system is now very similar to the connect (read: `uzbl.connect(..)` and `uzbl.connect_dict({..})`) system in the event manager. And consider the following: 1. User wishes to write a plugin that doesn't connect to any events but exports a function. 2. It's an arbitrary requirement that a plugin have an `init(uzbl)` function. 3. The user would have done the following (example plugin snippet): __export__ = 'my_function' def my_function(uzbl, ..): # Do something def init(uzbl): # Do nothing pass 4. The user now does the following: def my_function(uzbl, ..): # do something def init(uzbl): uzbl.export('my_function', my_function) Note that the name in `uzbl.export('external_name', function)` doesn't need to match the function name. Example pseudo-python: # In the plugin >>> def hello(uzbl): ... return "Hello, World!" >>> def init(uzbl): ... uzbl.export('say_hello', hello) ... print uzbl.say_hello() # In the event manager >>> plugin.init(uzbl) Hello, World! --- examples/data/uzbl/scripts/uzbl-event-manager | 101 ++++++++++---------------- 1 file changed, 38 insertions(+), 63 deletions(-) (limited to 'examples') diff --git a/examples/data/uzbl/scripts/uzbl-event-manager b/examples/data/uzbl/scripts/uzbl-event-manager index 916259a..afef6fd 100755 --- a/examples/data/uzbl/scripts/uzbl-event-manager +++ b/examples/data/uzbl/scripts/uzbl-event-manager @@ -350,61 +350,23 @@ class UzblInstance(object): def __init__(self, parent, client_socket): # Internal variables. - self._exports = {} - self._handlers = {} - self._parent = parent - self._client_socket = client_socket + self.exports = {} + self.handlers = {} + self.parent = parent + self.client_socket = client_socket self.depth = 0 self.buffer = '' self.pid = None - # Call the init() function in every plugin. Inside the init function - # is where the plugins insert the hooks into the event system. - self._init_plugins() - - - def __getattribute__(self, attr): - '''Expose any exported functions before class functions.''' - - if not attr.startswith('_'): - exports = object.__getattribute__(self, '_exports') - if attr in exports: - return exports[attr] - - return object.__getattribute__(self, attr) - - - def _init_plugins(self): - '''Call the init() function in every plugin and expose all exposable - functions in the plugins root namespace.''' - - plugins = self._parent['plugins'] - - # Map all plugin exports - for (name, plugin) in plugins.items(): - if not hasattr(plugin, '__export__'): - continue - - for export in plugin.__export__: - if export in self._exports: - raise KeyError("conflicting export: %r" % export) - - obj = getattr(plugin, export) - if callable(obj): - obj = partial(obj, self) - - self._exports[export] = obj - - echo("exposed attribute(s): %s" % ', '.join(self._exports.keys())) - - # Now call the init function in all plugins. - for (name, plugin) in plugins.items(): + # Call the init function in every plugin. The init function in each + # plugin is where that plugin connects functions to events and exports + # functions to the uzbl object. + for plugin in self.parent['plugins'].values(): try: plugin.init(self) except: - #print_exc() raise @@ -412,26 +374,43 @@ class UzblInstance(object): '''Send a command to the uzbl instance via the socket file.''' msg = msg.strip() - if self._client_socket: + if self.client_socket: print '%s<-- %s' % (' ' * self.depth, msg) - self._client_socket.send(("%s\n" % msg).encode('utf-8')) + self.client_socket.send(("%s\n" % msg).encode('utf-8')) else: print '%s!-- %s' % (' ' * self.depth, msg) + def export(self, name, function): + '''Export `function(uzbl, *args, ..)` inside a plugin to the uzbl + object like so `uzbl.function(*args, ..)`. This will allow other + plugins to call functions inside the current plugin (which is currently + calling this function) via the uzbl object.''' + + self.__dict__.__setitem__(name, partial(function, self)) + + + def export_dict(self, export_dict): + '''Export multiple (name, function)'s at once inside a dict of the + form `{name1: function1, name2: function2, ...}`.''' + + for (name, function) in export_dict.items(): + self.export(name, function) + + def connect(self, event, handler, *args, **kargs): - '''Connect event with handler and return the newly created handler. - Handlers can either be a function or a uzbl command string.''' + '''Connect a uzbl event with a handler. Handlers can either be a + function or a uzbl command string.''' event = event.upper().strip() assert event and ' ' not in event - if event not in self._handlers.keys(): - self._handlers[event] = [] + if event not in self.handlers.keys(): + self.handlers[event] = [] handlerobj = EventHandler(event, handler, *args, **kargs) - self._handlers[event].append(handlerobj) + self.handlers[event].append(handlerobj) print handlerobj @@ -449,7 +428,7 @@ class UzblInstance(object): def remove_by_id(self, hid): '''Remove connected event handler by unique handler id.''' - for (event, handlers) in self._handlers.items(): + for (event, handlers) in self.handlers.items(): for handler in list(handlers): if hid != handler.hid: continue @@ -464,7 +443,7 @@ class UzblInstance(object): def remove(self, handler): '''Remove connected event handler.''' - for (event, handlers) in self._handlers.items(): + for (event, handlers) in self.handlers.items(): if handler in handlers: echo("removed %r" % handler) handlers.remove(handler) @@ -493,10 +472,10 @@ class UzblInstance(object): if event == "INSTANCE_START" and args: self.pid = int(args[0]) - if event not in self._handlers: + if event not in self.handlers: return - for handler in self._handlers[event]: + for handler in self.handlers[event]: self.depth += 1 try: self.exec_handler(handler, *args, **kargs) @@ -511,19 +490,15 @@ class UzblInstance(object): '''Close the client socket and clean up.''' try: - self._client_socket.close() + self.client_socket.close() except: pass - for (name, plugin) in self._parent['plugins'].items(): + for (name, plugin) in self.parent['plugins'].items(): if hasattr(plugin, 'cleanup'): plugin.cleanup(self) - del self._exports - del self._handlers - del self._client_socket - class UzblEventDaemon(dict): def __init__(self): -- cgit v1.2.3