comparison pyloader/factory.py @ 10:ba2355d57998

finish baseline abstract factory implementation
author Jeff Hammel <jhammel@mozilla.com>
date Fri, 27 May 2011 06:40:15 -0700
parents ff634cc2e62b
children ff272dcd5cd8
comparison
equal deleted inserted replaced
9:ff634cc2e62b 10:ba2355d57998
11 11
12 delimeters = ('%(', ')s') 12 delimeters = ('%(', ')s')
13 13
14 def __init__(self, config=None, main=''): 14 def __init__(self, config=None, main=''):
15 self.main = main # main section 15 self.main = main # main section
16 self.configure(config or {})
17
18 def configure(self, config):
19 """load a new configuration"""
20 # TODO: this should really be a configuration update. If you keep
21 # track of all "apps" and their parents (i.e. as a ADG)
22 # you should be able to update only relevent apps
23 self.config = config
16 self.seen = set() # already seen apps to note cyclic dependencies 24 self.seen = set() # already seen apps to note cyclic dependencies
17 self.parsed = {} # instantiated apps 25 self.parsed = {} # instantiated apps
18 self.load(config or {})
19 26
20 def load(self, config, name=None): 27 def load(self, name=None):
28 """load an object"""
29
21 name = name or self.main # load main section by default 30 name = name or self.main # load main section by default
22 assert name in config, "'%s' not found in config" 31 assert name in self.config, "'%s' not found in configuration"
23 if name in self.parsed: 32 if name in self.parsed:
24 return self.parsed[name] 33 return self.parsed[name]
25 if name in self.seen: 34 if name in self.seen:
26 raise CircularReferenceError('Circular reference! : %s' % name) 35 raise CircularReferenceError('Circular reference! : %s' % name)
27 self.seen.add(name) 36 self.seen.add(name)
28 37
29 # get section 38 # get section
30 section = config['name'] 39 section = config[name]
31 assert 'path' in section 40 assert 'path' in section
32 41
33 # load object 42 # load object
34 obj = loader.load(section['path']) 43 obj = loader.load(section['path'])
35 44
36 # interpolate arguments 45 # get the object's arguments (if any)
37 args = section.get('args', None) 46 args = section.get('args', None)
38 kwargs = section.get('kwargs', None) 47 kwargs = section.get('kwargs', None)
48
49 # if args and kwargs aren't there, you're done!
50 if args is None and kwargs is None:
51 self.parsed[name] = obj
52 return obj
53
54 # interpolate arguments
39 if args: 55 if args:
40 args = [self.iterpolate(arg) for arg in args] 56 args = [self.iterpolate(arg) for arg in args]
41 if kwargs: 57 if kwargs:
42 kwargs = dict([(key, self.interpolate(value)) 58 kwargs = dict([(key, self.interpolate(value))
43 for key, value in kwargs.items()]) 59 for key, value in kwargs.items()])
44 60
45 # if args and kwargs aren't there, you're done! 61 # invoke
62 self.parsed[name] = obj(*args, **kwargs)
63 return self.parsed[name]
46 64
47 def interpolate(self, value): 65 def interpolate(self, value):
48 66
49 # only interpolate strings 67 # only interpolate strings
50 if not isinstance(value, basestring): 68 if not isinstance(value, basestring):
51 return value 69 return value
70
71 if value.startswith(self.delimeters[0]) and value.endswith(self.delimeters[1]):
72 value = value[len(self.delimeters[0]):-len(self.delimeters[1])]
73 if value in self.config:
74 return self.load(value)
75 elif value == 'self':
76 # reference this factory
77 # tricky and dangerous
78 return self
79 return value
80