Initial import
[gregoa/zavai.git] / zavai / registry.py
1 import zavai
2
3 class Registry(object):
4     """Collection of resources.
5
6     Various factories can be registered by name on the registry. Then when an
7     object is requested for the first time, it is created using the factory.
8     When it is requested again, the existing object is reused.
9     """
10
11     def __init__(self):
12         self.factories = dict()
13         self.objects = dict()
14
15     def resource(self, name):
16         """Get a resource, instantiating it if it has not been done yet.
17
18         First it tries to use the factory registered with `name` itself. If it
19         fails, it tries to use the factory registered one level above (using
20         the dot '.' as a separator).
21
22         If no suitable factory has been found, returns None.
23         """
24         res = self.objects.get(name, None)
25         if res is None:
26             fac = self.factories.get(name, None)
27             if fac is None:
28                 root = name
29                 while True:
30                     pos = root.rfind(".")
31                     if pos == -1: break
32                     root = root[:pos]
33                     fac = self.factories.get(root, None)
34                 if fac is None:
35                     return None
36             res = fac(self, name)
37             if res is not None:
38                 self.objects[name] = res
39         return res
40
41     def menu(self, name):
42         """Get a menu resource, instantiating it if it has not been done yet.
43
44         All menu resources share the same factory, which builds zavai.Menu
45         objects.
46         """
47         return self.resource("menu." + name)
48
49     def menu_link(self, name, label):
50         """Return a MenuLink to the menu with the given name
51         """
52         return zavai.MenuLink(self, name, label)
53
54     def get_existing(self, name):
55         """Get a menu resource, but only if it has been already instantiated.
56
57         If the resource has not been instantiated yet, returns None.
58         """
59         return self.objects.get(name, None)
60
61     def register(self, name, factory):
62         """Register a factory for this registry.
63
64         Name is a name for this factory, like "menu.gps.monitor".
65
66         Factory is a function that creates a Resource object. The function will
67         be passed the Registry itself as the only parameter"""
68         if name in self.factories:
69             return KeyError("% is already registered as a factory", name)
70         self.factories[name] = factory
71
72     def shutdown(self):
73         """Shut down all objects in this Registry.
74
75         After shutting down, all objects cannot be used anymore"""
76         for o in self.objects.itervalues():
77             o.shutdown()
78         self.objects.clear()
79
80 class Resource(object):
81     def __init__(self, registry, name, *args, **kw):
82         """The default constructor does nothing, but is there to eat the
83         parameters passed by Registry in case subclassers do not need a
84         constructor"""
85         pass
86
87     def shutdown(self):
88         """Shut down this resource.
89
90         Normally one does nothing here, but it is important to give resources a
91         chance to do cleanup when the program quits.
92
93         This can be used for tasks like closing the tags on a GPX track,
94         releasing a FSO resource, restoring mixer settings and so on.
95         """
96         pass