Mercurial > hg > pyloader
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 |