git.fiddlerwoaroof.com
Browse code

Fixed various problems with <registry.py>

Ed L authored on 03/03/2012 23:31:34
Showing 1 changed files
... ...
@@ -32,57 +32,43 @@ import contextlib
32 32
 import functools
33 33
 
34 34
 class CallableGeneratorContextManager(contextlib.GeneratorContextManager):
35
+	'''A subclass of :py:class:`contextlib.GeneratorContextManager` which can be called
36
+
37
+	Basically, this exists to avoid unecessary hassles with object methods which need special treatment'''
35 38
 	def __call__(self, *a, **kw):
39
+		'''Enter self's context and call the object returned by __enter__'''
36 40
 		with self as obj:
37 41
 			return obj(*a, **kw)
38
-try:
39
-	from contextlib import contextmanager
40
-except:
41
-	def contextmanager(func):
42
- 	  """@contextmanager decorator.
43
-
44
-    Typical usage:
45
-
46
-        @contextmanager
47
-        def some_generator(<arguments>):
48
-            <setup>
49
-            try:
50
-                yield <value>
51
-            finally:
52
-                <cleanup>
53
-
54
-    This makes this:
55
-
56
-        with some_generator(<arguments>) as <variable>:
57
-            <body>
58
-
59
-    equivalent to this:
60 42
 
61
-        <setup>
62
-        try:
63
-            <variable> = <value>
64
-            <body>
65
-        finally:
66
-            <cleanup>
67
-
68
-    """
69
-    @functools.wraps(func)
70
-    def helper(*args, **kwds):
71
-        return CallableGeneratorContextManager(func(*args, **kwds))
72
-    return helper
43
+#NOTE: (ed) this is ripped out of contextlib but I've replaced contextlib.GeneratorContextManager with the previous class
44
+def contextmanager(func):
45
+	'''see documentation for :py:class:`contextlib.GeneratorContextManager`'''
46
+	@functools.wraps(func)
47
+	def helper(*args, **kwds):
48
+		return CallableGeneratorContextManager(func(*args, **kwds))
49
+		# ^^^ This is the only line diferent from contextlib.contextmanager
50
+	return helper
73 51
 
74 52
 
75 53
 class RegisteredObj(object):
54
+	'''Interface definition for :py:attr:`Registry.child_class`'''
76 55
 	def __init__(self, name, *args):
77 56
 		self.name = name
78 57
 
79 58
 	def update(self, other):
59
+		'''override me'''
80 60
 		pass
81 61
 
82 62
 def make_ctxt_manager(name):
63
+	'''create a factory method for making and registering objects suitable to be registered in
64
+	the Registry.
65
+
66
+	:param str name: The name of the factory method
67
+	:return: A contextmanager
68
+	'''
83 69
 	@contextmanager
84
-	def _inner(self, name, *args):
85
-		obj = self.registry.get(name) if name in self.registry else self.child_class(name, *args)
70
+	def _inner(self, name, *args, **kwargs):
71
+		obj = self.registry.get(name) if name in self.registry else self.child_class(name, *args, **kwargs)
86 72
 		yield obj
87 73
 		if obj.name not in self.registry:
88 74
 			self.register(obj)
... ...
@@ -92,6 +78,8 @@ def make_ctxt_manager(name):
92 78
 
93 79
 import threading
94 80
 class Registry(object):
81
+	#: The kind of object to be stored in the registry
82
+	#: must, as a minimum implement the :py:class:`RegisteredObj` interface
95 83
 	child_class = None
96 84
 
97 85
 	def __setitem__(self, name, value):
... ...
@@ -119,6 +107,12 @@ class Registry(object):
119 107
 	_init_lock = threading.RLock()
120 108
 	@staticmethod
121 109
 	def setup(cls):
110
+		'''Decorate the registry with this, this sets the 'registry' attribute to an
111
+		empty dictionary and a factory function for creating child objects.
112
+
113
+		The name of the factory function is that of the class the registry registers,
114
+		but lowercase'''
115
+
122 116
 		with cls._init_lock:
123 117
 			factory_name = cls.child_class.__name__.lower()
124 118
 			setattr(cls, factory_name, make_ctxt_manager(factory_name))
... ...
@@ -139,6 +133,8 @@ class Registry(object):
139 133
 
140 134
 		return result
141 135
 
136
+### DEMO, read this for a practical example of how the above works:
137
+
142 138
 class DataObj(RegisteredObj):
143 139
 	def __init__(self, name, a):
144 140
 		RegisteredObj.__init__(self, name)