Mercurial > hg > pyloader
view pyloader/factory.py @ 18:d303a5883991
even more stubbing
author | Jeff Hammel <jhammel@mozilla.com> |
---|---|
date | Fri, 27 May 2011 19:12:56 -0700 |
parents | edecb6fbd5a7 |
children | 8987867698ee |
line wrap: on
line source
""" abstract factories """ import loader import os from ConfigParser import SafeConfigParser as ConfigParser __all__ = ['CircularReferenceError', 'PyFactory', 'IniFactory'] class CircularReferenceError(Exception): """factory has detected a circular reference""" class PyFactory(object): delimeters = ('%(', ')s') def __init__(self, config=None, main=''): self.main = main # main section self.configure(config or {}) def configure(self, config): """load a new configuration""" # TODO: this should really be a configuration update. If you keep # track of all "apps" and their parents (i.e. as a ADG) # you should be able to update only relevent apps self.config = config self.seen = set() # already seen apps to note cyclic dependencies self.parsed = {} # instantiated apps def load(self, name=None): """load an object""" name = name or self.main # load main section by default assert name in self.config, "'%s' not found in configuration" if name in self.parsed: return self.parsed[name] if name in self.seen: raise CircularReferenceError('Circular reference! : %s' % name) self.seen.add(name) # get section section = self.config[name] assert 'path' in section # load object obj = loader.load(section['path']) # get the object's arguments (if any) args = section.get('args', None) kwargs = section.get('kwargs', None) # if args and kwargs aren't there, you're done! if args is None and kwargs is None: self.parsed[name] = obj return obj # interpolate arguments if args: args = [self.interpolate(arg) for arg in args] else: args = [] if kwargs: kwargs = dict([(key, self.interpolate(value)) for key, value in kwargs.items()]) else: kwargs = {} # invoke self.parsed[name] = obj(*args, **kwargs) return self.parsed[name] def interpolate(self, value): # only interpolate strings if not isinstance(value, basestring): return value if value.startswith(self.delimeters[0]) and value.endswith(self.delimeters[1]): value = value[len(self.delimeters[0]):-len(self.delimeters[1])] if value in self.config: return self.load(value) return value class IniFactory(PyFactory): def __init__(self, inifile, main=''): assert os.path.exists(inifile), "File not found: %s" % inifile def read(self): """reads configuration from an .ini file""" here = os.path.dirname(os.path.abspath(self.inifile)) # read configuration defaults={'here': here, 'this': os.path.abspath(self.inifile)} parser = ConfigParser(defaults=defaults) parser.optionxform = str # use whole case parser.read(self.inifile) # parse configuration config = {} for section in parser.sections(): # sanity check assert ':' in section, "No : in section: %s" % section name, path = section.split(':', 1) sect = config[name] = dict(path=path) for option in parser.options(section): pass