Changeset 533

Show
Ignore:
Timestamp:
05/04/2008 05:48:57 AM (3 months ago)
Author:
athomas
Message:

- Moved stuff into the "ape" package.
- Added a steup.py.
- Added tests for component, config and part of engine.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • ape/trunk/ape/component.py

    r531 r533  
    4242      for the extension point 
    4343    """ 
    44     property.__init__(self, self.Extensions) 
     44    property.__init__(self, self.extensions) 
    4545    self.interface = interface 
    4646    self.__doc__ = 'List of components that implement `%s`' % \ 
     
    174174    if not component: 
    175175      if cls not in ComponentMeta._components: 
    176         raise ComponentError('Component "%s" not registered' % cls.__name__) 
     176        raise Error('Component "%s" not registered' % cls.__name__) 
    177177      try: 
    178178        component = cls(self) 
    179179      except TypeError, e: 
    180         raise ComponentError('Unable to instantiate component %r (%s)' % 
    181                 (cls, e)) 
     180        raise Error('Unable to instantiate component %r (%s)' % (cls, e)) 
    182181    return component 
    183182 
  • ape/trunk/ape/config.py

    r531 r533  
    5454 
    5555    # Public API 
     56    def options(self): 
     57        return sorted(self.data.items()) 
     58 
     59    def has_option(self, name): 
     60        return name in self.data 
     61 
    5662    def get(self, name, default=None): 
    57         return self.data.get(name, default) 
     63        if name in self.data: 
     64            value = self.data.get(name, default) 
     65        else: 
     66            option = Option.registry.get(name) 
     67            if option is not None: 
     68                value = option.default 
     69                if value is None: 
     70                    value = default 
     71            else: 
     72                value = default 
     73        return value 
    5874 
    5975    def set(self, name, value, transient=False): 
     
    104120        if instance is None: 
    105121            return self 
    106         config = instance.engine.config 
    107         return self.accessor(config, self.name, self.default) 
     122        engine = getattr(instance, 'engine', None) 
     123        if engine is not None: 
     124            config = instance.engine.config 
     125            return self.accessor(config, self.name, self.default) 
     126        else: 
     127            return self.default 
    108128 
    109129    def __set__(self, instance, value): 
  • ape/trunk/ape/engine.py

    r531 r533  
    2020import sys 
    2121from ape.util import URI 
    22 from ape.component import Component, ComponentManager, Error 
    23 from ape.config import Configuration, URIOption 
     22from ape.component import Component, Interface, ExtensionPoint, \ 
     23                          ComponentManager, Error 
     24from ape.config import Configuration, URIOption, IntOption, ListOption 
    2425 
    2526 
     
    2829 
    2930 
     31class IEngineLifecycleListener(Interface): 
     32    """Hooks for engine startup and shutdown.""" 
     33 
     34    def engine_startup(self): 
     35        """Engine has started. 
     36         
     37        Config, logging and plugins are available at this stage. 
     38        """ 
     39 
     40    def engine_shutdown(self): 
     41        """Engine has stopped.""" 
     42 
     43 
    3044class Engine(Component, ComponentManager): 
    3145 
     46    lifecycle_listeners = ExtensionPoint(IEngineLifecycleListener) 
     47 
    3248    logging_uri = URIOption('logging', 'stderr://', 'Logging URI') 
    33  
    34     def __init__(self, application_name, config_file=None): 
     49    debug = IntOption('debug', 0, 'Debug level') 
     50    plugin_paths = ListOption('plugins.paths', [], 'Plugin search paths') 
     51 
     52    _active_engine = None 
     53 
     54    def __init__(self, application_name='app', config_file=None, 
     55                 defer_startup=False, debug=None): 
    3556        Component.__init__(self) 
    3657        ComponentManager.__init__(self) 
    3758 
    38         Engine._active_engine = self 
    3959        self.engine = self 
    4060        self.application_name = application_name 
     
    4262        self.log = self.initialise_logging(self.logging_uri) 
    4363 
     64        if debug is not None: 
     65            self.config.set('debug', debug, transient=True) 
     66 
     67        if not defer_startup: 
     68            self.startup() 
     69 
     70    def startup(self): 
     71        """Start the engine.""" 
     72        self.log.debug('Starting %s', self.application_name) 
     73        self.load_plugins(plugin_paths=self.plugin_paths) 
     74        for listener in self.lifecycle_listeners: 
     75            listener.engine_startup() 
     76        Engine._active_engine = self 
     77 
     78    def shutdown(self): 
     79        """Shutdown the engine.""" 
     80        if Engine._active_engine: 
     81            self.log.debug('Shutting down %s', self.application_name) 
     82            for listener in self.lifecycle_listeners: 
     83                listener.engine_shutdown() 
     84        self.shutdown_logging() 
     85        self.config = None 
     86        self.components = None 
     87        self.engine = None 
     88        Engine._active_engine = None 
    4489 
    4590    def load_plugins(self, entry_point_name=None, plugin_paths=None): 
     
    85130                log_error(entry, e) 
    86131 
    87     def parse_logger(self, uri): 
     132    def _parse_logger(self, uri): 
    88133        """Get logging level and formatter from a URI. 
    89134         
     
    97142        level = getattr(logging, level, logging.WARNING) 
    98143 
    99         default_format = '%(asctime)s agate %(levelname)s: %(message)s' 
     144        default_format = '%%(asctime)s %s %%(levelname)s: %%(message)s' % self.application_name 
    100145        default_date_format = '%Y-%m-%d %H:%M:%S' 
    101146        formatter = logging.Formatter( 
     
    150195                handler = logging.handlers.SysLogHandler(uri.path or '/dev/log') 
    151196            else: 
    152                 handler = logging.handlers.SysLogHandler((uri.host or 'localhost', 
    153                                                                                                     uri.port or 514)) 
     197                handler = logging.handlers.SysLogHandler( 
     198                    (uri.host or 'localhost', uri.port or 514) 
     199                    ) 
    154200        elif uri.scheme == 'stderr': 
    155201            handler = logging.StreamHandler(sys.stderr) 
     
    161207            raise Error('Unsupported logging scheme: %s' % uri) 
    162208 
    163         werkzeug_log = logging.getLogger('werkzeug') 
    164209        log = logging.getLogger(self.application_name) 
    165210 
    166         level, formatter = self.parse_logger(uri) 
     211        level, formatter = self._parse_logger(uri) 
    167212        handler.setFormatter(formatter) 
    168213        handler.setLevel(level) 
    169         #level = ConfigureHandler(db_handler, uri) 
    170214 
    171215        log.addHandler(handler) 
    172         #log.addHandler(db_handler) 
    173216        log.setLevel(level) 
    174         werkzeug_log.addHandler(handler) 
    175         werkzeug_log.setLevel(level) 
    176217        return log 
    177218 
    178219    def shutdown_logging(self): 
    179       """Shutdown logging.""" 
    180       # XXX This modifies globals in the logging module. 
    181       log = logging.getLogger(self.application_name) 
    182       log.handlers = [] 
    183       logging.shutdown() 
     220        """Shutdown logging.""" 
     221        # XXX This modifies globals in the logging module. 
     222        log = logging.getLogger(self.application_name) 
     223        logging.shutdown(log.handlers) 
     224        log.handlers = [] 
     225        self.log = None 
    184226 
    185227    def component_activated(self, component): 
     
    194236def get_active_engine(): 
    195237    """Return the active Engine.""" 
    196     try
     238    if Engine._active_engine is not None
    197239        return Engine._active_engine 
    198     except AttributeError: 
    199         raise Error('No active engine') 
     240    raise Error('No active engine') 
  • ape/trunk/ape/util.py

    r532 r533  
    2121 
    2222 
    23 # XXX Appropriated from http://swapoff.org/pyndexter. 
     23# XXX Appropriated from http://swapoff.org/pyndexter 
    2424class URI(object): 
    2525    """Parse a URI into its component parts. The `query` component is passed 
     
    9191        (?:(?P<scheme>[^:]+)://)? 
    9292        (?:(?P<username>[^:@]*) 
    93         (?::(?P<password>[^@]*))?@)? 
     93            (?::(?P<password>[^@]*))?@)? 
    9494        (?P<host>[^?/#:]*) 
    9595        (?::(?P<port>[\d]+))? 
     
    100100 
    101101    __slots__ = ['scheme', 'username', 'password', 'host', 'port', '_path', 
    102                  'query', 'fragment'] 
     102                             'query', 'fragment'] 
    103103 
    104104    def __init__(self, uri=None, scheme=None, username=None, password=None, 
     
    162162        >>> u == v 
    163163        True 
    164         >>> v.host = 'www.example.com' 
     164        >>> v.host = 'www.google.com' 
    165165        >>> u == v 
    166166        False 
     
    190190                [u'&'.join([u'%s=%s' % (urllib.quote(k), urllib.quote(str(v))) 
    191191                            for v in l]) 
    192                  for k, l in sorted(self.query.items())]) 
     192                 for k, l in sorted(self.query.items())] 
     193                ) 
    193194        if self.fragment: 
    194195            uri += u'#' + urllib.quote(self.fragment) 
     
    326327    delay = random.randint(a,b) 
    327328    time.sleep(delay) 
    328