aboutsummaryrefslogtreecommitdiffhomepage
path: root/examples
diff options
context:
space:
mode:
authorGravatar Brendan Taylor <whateley@gmail.com>2011-04-11 19:59:51 -0600
committerGravatar Brendan Taylor <whateley@gmail.com>2011-04-11 19:59:51 -0600
commit841914c050bc00a39d9313c05856568696e58a23 (patch)
tree802747fe0388b230e02b0c49f9f946532629b404 /examples
parent3384703009e8190c8ad50821a4ace94c03733488 (diff)
move examples/data/scripts/uzbl-event-manager to bin/uzbl-event-manager
Diffstat (limited to 'examples')
-rwxr-xr-xexamples/data/scripts/uzbl-event-manager991
1 files changed, 0 insertions, 991 deletions
diff --git a/examples/data/scripts/uzbl-event-manager b/examples/data/scripts/uzbl-event-manager
deleted file mode 100755
index cb462c7..0000000
--- a/examples/data/scripts/uzbl-event-manager
+++ /dev/null
@@ -1,991 +0,0 @@
-#!/usr/bin/env python
-
-# Event Manager for Uzbl
-# Copyright (c) 2009-2010, Mason Larobina <mason.larobina@gmail.com>
-# Copyright (c) 2009, Dieter Plaetinck <dieter@plaetinck.be>
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-'''
-
-E V E N T _ M A N A G E R . P Y
-===============================
-
-Event manager for uzbl written in python.
-
-'''
-
-import atexit
-import imp
-import logging
-import os
-import socket
-import sys
-import time
-import weakref
-import re
-from collections import defaultdict
-from functools import partial
-from glob import glob
-from itertools import count
-from optparse import OptionParser
-from select import select
-from signal import signal, SIGTERM, SIGINT
-from socket import socket, AF_UNIX, SOCK_STREAM
-from traceback import format_exc
-
-def xdghome(key, default):
- '''Attempts to use the environ XDG_*_HOME paths if they exist otherwise
- use $HOME and the default path.'''
-
- xdgkey = "XDG_%s_HOME" % key
- if xdgkey in os.environ.keys() and os.environ[xdgkey]:
- return os.environ[xdgkey]
-
- return os.path.join(os.environ['HOME'], default)
-
-# `make install` will put the correct value here for your system
-PREFIX = '/usr/local/'
-
-# Setup xdg paths.
-DATA_DIR = os.path.join(xdghome('DATA', '.local/share/'), 'uzbl/')
-CACHE_DIR = os.path.join(xdghome('CACHE', '.cache/'), 'uzbl/')
-
-# Define some globals.
-SCRIPTNAME = os.path.basename(sys.argv[0])
-
-def get_exc():
- '''Format `format_exc` for logging.'''
- return "\n%s" % format_exc().rstrip()
-
-def expandpath(path):
- '''Expand and realpath paths.'''
- return os.path.realpath(os.path.expandvars(path))
-
-def ascii(u):
- '''Convert unicode strings into ascii for transmission over
- ascii-only streams/sockets/devices.'''
- return u.encode('utf-8')
-
-
-def daemonize():
- '''Daemonize the process using the Stevens' double-fork magic.'''
-
- logger.info('entering daemon mode')
-
- try:
- if os.fork():
- os._exit(0)
-
- except OSError:
- logger.critical(get_exc())
- sys.exit(1)
-
- os.chdir('/')
- os.setsid()
- os.umask(0)
-
- try:
- if os.fork():
- os._exit(0)
-
- except OSError:
- logger.critical(get_exc())
- sys.exit(1)
-
- if sys.stdout.isatty():
- sys.stdout.flush()
- sys.stderr.flush()
-
- devnull = '/dev/null'
- stdin = file(devnull, 'r')
- stdout = file(devnull, 'a+')
- stderr = file(devnull, 'a+', 0)
-
- os.dup2(stdin.fileno(), sys.stdin.fileno())
- os.dup2(stdout.fileno(), sys.stdout.fileno())
- os.dup2(stderr.fileno(), sys.stderr.fileno())
-
- logger.info('entered daemon mode')
-
-
-def make_dirs(path):
- '''Make all basedirs recursively as required.'''
-
- try:
- dirname = os.path.dirname(path)
- if not os.path.isdir(dirname):
- logger.debug('creating directories %r' % dirname)
- os.makedirs(dirname)
-
- except OSError:
- logger.error(get_exc())
-
-
-class EventHandler(object):
- '''Event handler class. Used to store args and kwargs which are merged
- come time to call the callback with the event args and kwargs.'''
-
- nextid = count().next
-
- def __init__(self, plugin, event, callback, args, kwargs):
- self.id = self.nextid()
- self.plugin = plugin
- self.event = event
- self.callback = callback
- self.args = args
- self.kwargs = kwargs
-
-
- def __repr__(self):
- elems = ['id=%d' % self.id, 'event=%s' % self.event,
- 'callback=%r' % self.callback]
-
- if self.args:
- elems.append('args=%s' % repr(self.args))
-
- if self.kwargs:
- elems.append('kwargs=%s' % repr(self.kwargs))
-
- elems.append('plugin=%s' % self.plugin.name)
- return u'<handler(%s)>' % ', '.join(elems)
-
-
- def call(self, uzbl, *args, **kwargs):
- '''Execute the handler function and merge argument lists.'''
-
- args = args + self.args
- kwargs = dict(self.kwargs.items() + kwargs.items())
- self.callback(uzbl, *args, **kwargs)
-
-
-
-
-
-class Plugin(object):
- '''Plugin module wrapper object.'''
-
- # Special functions exported from the Plugin instance to the
- # plugin namespace.
- special_functions = ['require', 'export', 'export_dict', 'connect',
- 'connect_dict', 'logger', 'unquote', 'splitquoted']
-
-
- def __init__(self, parent, name, path, plugin):
- self.parent = parent
- self.name = name
- self.path = path
- self.plugin = plugin
- self.logger = get_logger('plugin.%s' % name)
-
- # Weakrefs to all handlers created by this plugin
- self.handlers = set([])
-
- # Plugins init hook
- init = getattr(plugin, 'init', None)
- self.init = init if callable(init) else None
-
- # Plugins optional after hook
- after = getattr(plugin, 'after', None)
- self.after = after if callable(after) else None
-
- # Plugins optional cleanup hook
- cleanup = getattr(plugin, 'cleanup', None)
- self.cleanup = cleanup if callable(cleanup) else None
-
- assert init or after or cleanup, "missing hooks in plugin"
-
- # Export plugin's instance methods to plugin namespace
- for attr in self.special_functions:
- plugin.__dict__[attr] = getattr(self, attr)
-
-
- def __repr__(self):
- return u'<plugin(%r)>' % self.plugin
-
-
- def export(self, uzbl, attr, object, prepend=True):
- '''Attach `object` to `uzbl` instance. This is the preferred method
- of sharing functionality, functions, data and objects between
- plugins.
-
- If the object is callable you may wish to turn the callable object
- in to a meta-instance-method by prepending `uzbl` to the call stack.
- You can change this behaviour with the `prepend` argument.
- '''
-
- assert attr not in uzbl.exports, "attr %r already exported by %r" %\
- (attr, uzbl.exports[attr][0])
-
- prepend = True if prepend and callable(object) else False
- uzbl.__dict__[attr] = partial(object, uzbl) if prepend else object
- uzbl.exports[attr] = (self, object, prepend)
- uzbl.logger.info('exported %r to %r by plugin %r, prepended %r'
- % (object, 'uzbl.%s' % attr, self.name, prepend))
-
-
- def export_dict(self, uzbl, exports):
- for (attr, object) in exports.items():
- self.export(uzbl, attr, object)
-
-
- def find_handler(self, event, callback, args, kwargs):
- '''Check if a handler with the identical callback and arguments
- exists and return it.'''
-
- # Remove dead refs
- self.handlers -= set(filter(lambda ref: not ref(), self.handlers))
-
- # Find existing identical handler
- for handler in [ref() for ref in self.handlers]:
- if handler.event == event and handler.callback == callback \
- and handler.args == args and handler.kwargs == kwargs:
- return handler
-
-
- def connect(self, uzbl, event, callback, *args, **kwargs):
- '''Create an event handler object which handles `event` events.
-
- Arguments passed to the connect function (`args` and `kwargs`) are
- stored in the handler object and merged with the event arguments
- come handler execution.
-
- All handler functions must behave like a `uzbl` instance-method (that
- means `uzbl` is prepended to the callback call arguments).'''
-
- # Sanitise and check event name
- event = event.upper().strip()
- assert event and ' ' not in event
-
- assert callable(callback), 'callback must be callable'
-
- # Check if an identical handler already exists
- handler = self.find_handler(event, callback, args, kwargs)
- if not handler:
- # Create a new handler
- handler = EventHandler(self, event, callback, args, kwargs)
- self.handlers.add(weakref.ref(handler))
- self.logger.info('new %r' % handler)
-
- uzbl.handlers[event].append(handler)
- uzbl.logger.info('connected %r' % handler)
- return handler
-
-
- def connect_dict(self, uzbl, connects):
- for (event, callback) in connects.items():
- self.connect(uzbl, event, callback)
-
-
- def require(self, plugin):
- '''Check that plugin with name `plugin` has been loaded. Use this to
- ensure that your plugins dependencies have been met.'''
-
- assert plugin in self.parent.plugins, self.logger.critical(
- 'plugin %r required by plugin %r' (plugin, self.name))
-
- @classmethod
- def unquote(cls, s):
- '''Removes quotation marks around strings if any and interprets
- \\-escape sequences using `string_escape`'''
- if s and s[0] == s[-1] and s[0] in ['"', "'"]:
- s = s[1:-1]
- return s.encode('utf-8').decode('string_escape').decode('utf-8')
-
- _splitquoted = re.compile("( |\"(?:\\\\.|[^\"])*?\"|'(?:\\\\.|[^'])*?')")
- @classmethod
- def splitquoted(cls, text):
- '''Splits string on whitespace while respecting quotations'''
- return [cls.unquote(p) for p in cls._splitquoted.split(text) if p.strip()]
-
-
-class Uzbl(object):
- def __init__(self, parent, child_socket):
- self.opts = opts
- self.parent = parent
- self.child_socket = child_socket
- self.time = time.time()
- self.pid = None
- self.name = None
-
- # Flag if the instance has raised the INSTANCE_START event.
- self.instance_start = False
-
- # Use name "unknown" until name is discovered.
- self.logger = get_logger('uzbl-instance[]')
-
- # Track plugin event handlers and exported functions.
- self.exports = {}
- self.handlers = defaultdict(list)
-
- # Internal vars
- self._depth = 0
- self._buffer = ''
-
-
- def __repr__(self):
- return '<uzbl(%s)>' % ', '.join([
- 'pid=%s' % (self.pid if self.pid else "Unknown"),
- 'name=%s' % ('%r' % self.name if self.name else "Unknown"),
- 'uptime=%f' % (time.time()-self.time),
- '%d exports' % len(self.exports.keys()),
- '%d handlers' % sum([len(l) for l in self.handlers.values()])])
-
-
- def init_plugins(self):
- '''Call the init and after hooks in all loaded plugins for this
- instance.'''
-
- # Initialise each plugin with the current uzbl instance.
- for plugin in self.parent.plugins.values():
- if plugin.init:
- self.logger.debug('calling %r plugin init hook' % plugin.name)
- plugin.init(self)
-
- # Allow plugins to use exported features of other plugins by calling an
- # optional `after` function in the plugins namespace.
- for plugin in self.parent.plugins.values():
- if plugin.after:
- self.logger.debug('calling %r plugin after hook'%plugin.name)
- plugin.after(self)
-
-
- def send(self, msg):
- '''Send a command to the uzbl instance via the child socket
- instance.'''
-
- msg = msg.strip()
- assert self.child_socket, "socket inactive"
-
- if opts.print_events:
- print ascii(u'%s<-- %s' % (' ' * self._depth, msg))
-
- self.child_socket.send(ascii("%s\n" % msg))
-
-
- def read(self):
- '''Read data from the child socket and pass lines to the parse_msg
- function.'''
-
- try:
- raw = unicode(self.child_socket.recv(8192), 'utf-8', 'ignore')
- if not raw:
- self.logger.debug('read null byte')
- return self.close()
-
- except:
- self.logger.error(get_exc())
- return self.close()
-
- lines = (self._buffer + raw).split('\n')
- self._buffer = lines.pop()
-
- for line in filter(None, map(unicode.strip, lines)):
- try:
- self.parse_msg(line.strip())
-
- except:
- self.logger.error(get_exc())
- self.logger.error('erroneous event: %r' % line)
-
-
- def parse_msg(self, line):
- '''Parse an incoming message from a uzbl instance. Event strings
- will be parsed into `self.event(event, args)`.'''
-
- # Split by spaces (and fill missing with nulls)
- elems = (line.split(' ', 3) + ['',]*3)[:4]
-
- # Ignore non-event messages.
- if elems[0] != 'EVENT':
- logger.info('non-event message: %r' % line)
- if opts.print_events:
- print '--- %s' % ascii(line)
- return
-
- # Check event string elements
- (name, event, args) = elems[1:]
- assert name and event, 'event string missing elements'
- if not self.name:
- self.name = name
- self.logger = get_logger('uzbl-instance%s' % name)
- self.logger.info('found instance name %r' % name)
-
- assert self.name == name, 'instance name mismatch'
-
- # Handle the event with the event handlers through the event method
- self.event(event, args)
-
-
- def event(self, event, *args, **kargs):
- '''Raise an event.'''
-
- event = event.upper()
-
- if not opts.daemon_mode and opts.print_events:
- elems = [event,]
- if args: elems.append(unicode(args))
- if kargs: elems.append(unicode(kargs))
- print ascii(u'%s--> %s' % (' ' * self._depth, ' '.join(elems)))
-
- if event == "INSTANCE_START" and args:
- assert not self.instance_start, 'instance already started'
-
- self.pid = int(args[0])
- self.logger.info('found instance pid %r' % self.pid)
-
- self.init_plugins()
-
- elif event == "INSTANCE_EXIT":
- self.logger.info('uzbl instance exit')
- self.close()
-
- if event not in self.handlers:
- return
-
- for handler in self.handlers[event]:
- self._depth += 1
- try:
- handler.call(self, *args, **kargs)
-
- except:
- self.logger.error(get_exc())
-
- self._depth -= 1
-
-
- def close_connection(self, child_socket):
- '''Close child socket and delete the uzbl instance created for that
- child socket connection.'''
-
-
- def close(self):
- '''Close the client socket and call the plugin cleanup hooks.'''
-
- self.logger.debug('called close method')
-
- # Remove self from parent uzbls dict.
- if self.child_socket in self.parent.uzbls:
- self.logger.debug('removing self from uzbls list')
- del self.parent.uzbls[self.child_socket]
-
- try:
- if self.child_socket:
- self.logger.debug('closing child socket')
- self.child_socket.close()
-
- except:
- self.logger.error(get_exc())
-
- finally:
- self.child_socket = None
-
- # Call plugins cleanup hooks.
- for plugin in self.parent.plugins.values():
- if plugin.cleanup:
- self.logger.debug('calling %r plugin cleanup hook'
- % plugin.name)
- plugin.cleanup(self)
-
- logger.info('removed %r' % self)
-
-
-class UzblEventDaemon(object):
- def __init__(self):
- self.opts = opts
- self.server_socket = None
- self._quit = False
-
- # Hold uzbl instances
- # {child socket: Uzbl instance, ..}
- self.uzbls = {}
-
- # Hold plugins
- # {plugin name: Plugin instance, ..}
- self.plugins = {}
-
- # Register that the event daemon server has started by creating the
- # pid file.
- make_pid_file(opts.pid_file)
-
- # Register a function to clean up the socket and pid file on exit.
- atexit.register(self.quit)
-
- # Add signal handlers.
- for sigint in [SIGTERM, SIGINT]:
- signal(sigint, self.quit)
-
- # Load plugins into self.plugins
- self.load_plugins(opts.plugins)
-
-
- def load_plugins(self, plugins):
- '''Load event manager plugins.'''
-
- for path in plugins:
- logger.debug('loading plugin %r' % path)
- (dir, file) = os.path.split(path)
- name = file[:-3] if file.lower().endswith('.py') else file
-
- info = imp.find_module(name, [dir,])
- module = imp.load_module(name, *info)
-
- # Check if the plugin has a callable hook.
- hooks = filter(callable, [getattr(module, attr, None) \
- for attr in ['init', 'after', 'cleanup']])
- assert hooks, "no hooks in plugin %r" % module
-
- logger.debug('creating plugin instance for %r plugin' % name)
- plugin = Plugin(self, name, path, module)
- self.plugins[name] = plugin
- logger.info('new %r' % plugin)
-
-
- def create_server_socket(self):
- '''Create the event manager daemon socket for uzbl instance duplex
- communication.'''
-
- # Close old socket.
- self.close_server_socket()
-
- sock = socket(AF_UNIX, SOCK_STREAM)
- sock.bind(opts.server_socket)
- sock.listen(5)
-
- self.server_socket = sock
- logger.debug('bound server socket to %r' % opts.server_socket)
-
-
- def run(self):
- '''Main event daemon loop.'''
-
- logger.debug('entering main loop')
-
- # Create and listen on the server socket
- self.create_server_socket()
-
- if opts.daemon_mode:
- # Daemonize the process
- daemonize()
-
- # Update the pid file
- make_pid_file(opts.pid_file)
-
- try:
- # Accept incoming connections and listen for incoming data
- self.listen()
-
- except:
- if not self._quit:
- logger.critical(get_exc())
-
- # Clean up and exit
- self.quit()
-
- logger.debug('exiting main loop')
-
-
- def listen(self):
- '''Accept incoming connections and constantly poll instance sockets
- for incoming data.'''
-
- logger.info('listening on %r' % opts.server_socket)
-
- # Count accepted connections
- connections = 0
-
- while (self.uzbls or not connections) or (not opts.auto_close):
- socks = [self.server_socket] + self.uzbls.keys()
- reads, _, errors = select(socks, [], socks, 1)
-
- if self.server_socket in reads:
- reads.remove(self.server_socket)
-
- # Accept connection and create uzbl instance.
- child_socket = self.server_socket.accept()[0]
- self.uzbls[child_socket] = Uzbl(self, child_socket)
- connections += 1
-
- for uzbl in [self.uzbls[s] for s in reads]:
- uzbl.read()
-
- for uzbl in [self.uzbls[s] for s in errors]:
- uzbl.logger.error('socket read error')
- uzbl.close()
-
- logger.info('auto closing')
-
-
- def close_server_socket(self):
- '''Close and delete the server socket.'''
-
- try:
- if self.server_socket:
- logger.debug('closing server socket')
- self.server_socket.close()
- self.server_socket = None
-
- if os.path.exists(opts.server_socket):
- logger.info('unlinking %r' % opts.server_socket)
- os.unlink(opts.server_socket)
-
- except:
- logger.error(get_exc())
-
-
- def quit(self, sigint=None, *args):
- '''Close all instance socket objects, server socket and delete the
- pid file.'''
-
- if sigint == SIGTERM:
- logger.critical('caught SIGTERM, exiting')
-
- elif sigint == SIGINT:
- logger.critical('caught SIGINT, exiting')
-
- elif not self._quit:
- logger.debug('shutting down event manager')
-
- self.close_server_socket()
-
- for uzbl in self.uzbls.values():
- uzbl.close()
-
- del_pid_file(opts.pid_file)
-
- if not self._quit:
- logger.info('event manager shut down')
- self._quit = True
-
-
-def make_pid_file(pid_file):
- '''Creates a pid file at `pid_file`, fails silently.'''
-
- try:
- logger.debug('creating pid file %r' % pid_file)
- make_dirs(pid_file)
- pid = os.getpid()
- fileobj = open(pid_file, 'w')
- fileobj.write('%d' % pid)
- fileobj.close()
- logger.info('created pid file %r with pid %d' % (pid_file, pid))
-
- except:
- logger.error(get_exc())
-
-
-def del_pid_file(pid_file):
- '''Deletes a pid file at `pid_file`, fails silently.'''
-
- if os.path.isfile(pid_file):
- try:
- logger.debug('deleting pid file %r' % pid_file)
- os.remove(pid_file)
- logger.info('deleted pid file %r' % pid_file)
-
- except:
- logger.error(get_exc())
-
-
-def get_pid(pid_file):
- '''Reads a pid from pid file `pid_file`, fails None.'''
-
- try:
- logger.debug('reading pid file %r' % pid_file)
- fileobj = open(pid_file, 'r')
- pid = int(fileobj.read())
- fileobj.close()
- logger.info('read pid %d from pid file %r' % (pid, pid_file))
- return pid
-
- except (IOError, ValueError):
- logger.error(get_exc())
- return None
-
-
-def pid_running(pid):
- '''Checks if a process with a pid `pid` is running.'''
-
- try:
- os.kill(pid, 0)
- except OSError:
- return False
- else:
- return True
-
-
-def term_process(pid):
- '''Asks nicely then forces process with pid `pid` to exit.'''
-
- try:
- logger.info('sending SIGTERM to process with pid %r' % pid)
- os.kill(pid, SIGTERM)
-
- except OSError:
- logger.error(get_exc())
-
- logger.debug('waiting for process with pid %r to exit' % pid)
- start = time.time()
- while True:
- if not pid_running(pid):
- logger.debug('process with pid %d exit' % pid)
- return True
-
- if (time.time()-start) > 5:
- logger.warning('process with pid %d failed to exit' % pid)
- logger.info('sending SIGKILL to process with pid %d' % pid)
- try:
- os.kill(pid, SIGKILL)
- except:
- logger.critical(get_exc())
- raise
-
- if (time.time()-start) > 10:
- logger.critical('unable to kill process with pid %d' % pid)
- raise OSError
-
- time.sleep(0.25)
-
-
-def stop_action():
- '''Stop the event manager daemon.'''
-
- pid_file = opts.pid_file
- if not os.path.isfile(pid_file):
- logger.error('could not find running event manager with pid file %r'
- % opts.pid_file)
- return
-
- pid = get_pid(pid_file)
- if not pid_running(pid):
- logger.debug('no process with pid %r' % pid)
- del_pid_file(pid_file)
- return
-
- logger.debug('terminating process with pid %r' % pid)
- term_process(pid)
- del_pid_file(pid_file)
- logger.info('stopped event manager process with pid %d' % pid)
-
-
-def start_action():
- '''Start the event manager daemon.'''
-
- pid_file = opts.pid_file
- if os.path.isfile(pid_file):
- pid = get_pid(pid_file)
- if pid_running(pid):
- logger.error('event manager already started with pid %d' % pid)
- return
-
- logger.info('no process with pid %d' % pid)
- del_pid_file(pid_file)
-
- UzblEventDaemon().run()
-
-
-def restart_action():
- '''Restart the event manager daemon.'''
-
- stop_action()
- start_action()
-
-
-def list_action():
- '''List all the plugins that would be loaded in the current search
- dirs.'''
-
- names = {}
- for plugin in opts.plugins:
- (head, tail) = os.path.split(plugin)
- if tail not in names:
- names[tail] = plugin
-
- for plugin in sorted(names.values()):
- print plugin
-
-
-if __name__ == "__main__":
- parser = OptionParser('usage: %prog [options] {start|stop|restart|list}')
- add = parser.add_option
-
- add('-v', '--verbose',
- dest='verbose', default=2, action='count',
- help='increase verbosity')
-
- add('-d', '--plugin-dir',
- dest='plugin_dirs', action='append', metavar="DIR", default=[],
- help='add extra plugin search dir, same as `-l "DIR/*.py"`')
-
- add('-l', '--load-plugin',
- dest='load_plugins', action='append', metavar="PLUGIN", default=[],
- help='load plugin, loads before plugins in search dirs')
-
- socket_location = os.path.join(CACHE_DIR, 'event_daemon')
- add('-s', '--server-socket',
- dest='server_socket', metavar="SOCKET", default=socket_location,
- help='server AF_UNIX socket location')
-
- add('-p', '--pid-file',
- metavar="FILE", dest='pid_file',
- help='pid file location, defaults to server socket + .pid')
-
- add('-n', '--no-daemon',
- dest='daemon_mode', action='store_false', default=True,
- help='do not daemonize the process')
-
- add('-a', '--auto-close',
- dest='auto_close', action='store_true', default=False,
- help='auto close after all instances disconnect')
-
- add('-i', '--no-default-dirs',
- dest='default_dirs', action='store_false', default=True,
- help='ignore the default plugin search dirs')
-
- add('-o', '--log-file',
- dest='log_file', metavar='FILE',
- help='write logging output to a file, defaults to server socket +'
- ' .log')
-
- add('-q', '--quiet-events',
- dest='print_events', action="store_false", default=True,
- help="silence the printing of events to stdout")
-
- (opts, args) = parser.parse_args()
-
- opts.server_socket = expandpath(opts.server_socket)
-
- # Set default pid file location
- if not opts.pid_file:
- opts.pid_file = "%s.pid" % opts.server_socket
-
- else:
- opts.pid_file = expandpath(opts.pid_file)
-
- # Set default log file location
- if not opts.log_file:
- opts.log_file = "%s.log" % opts.server_socket
-
- else:
- opts.log_file = expandpath(opts.log_file)
-
- # Logging setup
- log_level = logging.CRITICAL - opts.verbose*10
-
- # Console logging handler
- ch = logging.StreamHandler()
- ch.setLevel(max(log_level+10, 10))
- ch.setFormatter(logging.Formatter(
- '%(name)s: %(levelname)s: %(message)s'))
-
- # File logging handler
- fh = logging.FileHandler(opts.log_file, 'w', 'utf-8', 1)
- fh.setLevel(max(log_level, 10))
- fh.setFormatter(logging.Formatter(
- '[%(created)f] %(name)s: %(levelname)s: %(message)s'))
-
- # logging.getLogger wrapper which sets the levels and adds the
- # file and console handlers automagically
- def get_logger(name):
- handlers = [ch, fh]
- level = [max(log_level, 10),]
- logger = logging.getLogger(name)
- logger.setLevel(level[0])
- for handler in handlers:
- logger.addHandler(handler)
-
- return logger
-
- # Get main logger
- logger = get_logger(SCRIPTNAME)
- logger.info('logging to %r' % opts.log_file)
-
- plugins = {}
-
- # Load all `opts.load_plugins` into the plugins list
- for path in opts.load_plugins:
- path = expandpath(path)
- matches = glob(path)
- if not matches:
- parser.error('cannot find plugin(s): %r' % path)
-
- for plugin in matches:
- (head, tail) = os.path.split(plugin)
- if tail not in plugins:
- logger.debug('found plugin: %r' % plugin)
- plugins[tail] = plugin
-
- else:
- logger.debug('ignoring plugin: %r' % plugin)
-
- # Add default plugin locations
- if opts.default_dirs:
- logger.debug('adding default plugin dirs to plugin dirs list')
- opts.plugin_dirs += [os.path.join(DATA_DIR, 'plugins/'),
- os.path.join(PREFIX, 'share/uzbl/examples/data/plugins/')]
-
- else:
- logger.debug('ignoring default plugin dirs')
-
- # Load all plugins in `opts.plugin_dirs` into the plugins list
- for dir in opts.plugin_dirs:
- dir = expandpath(dir)
- logger.debug('searching plugin dir: %r' % dir)
- for plugin in glob(os.path.join(dir, '*.py')):
- (head, tail) = os.path.split(plugin)
- if tail not in plugins:
- logger.debug('found plugin: %r' % plugin)
- plugins[tail] = plugin
-
- else:
- logger.debug('ignoring plugin: %r' % plugin)
-
- plugins = plugins.values()
-
- # Check all the paths in the plugins list are files
- for plugin in plugins:
- if not os.path.isfile(plugin):
- parser.error('plugin not a file: %r' % plugin)
-
- if opts.auto_close: logger.debug('will auto close')
- else: logger.debug('will not auto close')
-
- if opts.daemon_mode: logger.debug('will daemonize')
- else: logger.debug('will not daemonize')
-
- opts.plugins = plugins
-
- # init like {start|stop|..} daemon actions
- daemon_actions = {'start': start_action, 'stop': stop_action,
- 'restart': restart_action, 'list': list_action}
-
- if len(args) == 1:
- action = args[0]
- if action not in daemon_actions:
- parser.error('invalid action: %r' % action)
-
- elif not args:
- logger.warning('no daemon action given, assuming %r' % 'start')
- action = 'start'
-
- else:
- parser.error('invalid action argument: %r' % args)
-
- logger.info('daemon action %r' % action)
- # Do action
- daemon_actions[action]()
-
- logger.debug('process CPU time: %f' % time.clock())
-
-# vi: set et ts=4: