[Checkins] SVN: martian/branches/philikon-decl-dir-rules/src/martian/ Work towards more declarative directives: Directives are no longer able to retrieve

Philipp von Weitershausen philikon at philikon.de
Mon May 5 06:31:20 EDT 2008


Log message for revision 86440:
  Work towards more declarative directives: Directives are no longer able to retrieve
  values themselves, you first have to "bind" them.  The benefit of that is that the
  retrieval of values is completely encapsulated in this bound directive object,
  which includes for instance the computation of a default (which may vary from
  grokker to grokker).
  

Changed:
  U   martian/branches/philikon-decl-dir-rules/src/martian/directive.py
  U   martian/branches/philikon-decl-dir-rules/src/martian/directive.txt
  U   martian/branches/philikon-decl-dir-rules/src/martian/util.py

-=-
Modified: martian/branches/philikon-decl-dir-rules/src/martian/directive.py
===================================================================
--- martian/branches/philikon-decl-dir-rules/src/martian/directive.py	2008-05-05 10:13:51 UTC (rev 86439)
+++ martian/branches/philikon-decl-dir-rules/src/martian/directive.py	2008-05-05 10:31:19 UTC (rev 86440)
@@ -149,33 +149,45 @@
     def factory(self, value):
         return value
 
-    def get_default(self, component):
-        return self.default
-
     @classmethod
     def dotted_name(cls):
         return cls.__module__ + '.' + cls.__name__
 
     @classmethod
-    def get(cls, component, module=None):
-        # Create an instance of the directive without calling __init__
-        self = cls.__new__(cls)
+    def set(cls, component, value):
+        cls.store.setattr(component, cls, value)
 
-        value = self.store.get(self, component, _USE_DEFAULT)
+    @classmethod
+    def bind(cls, default=None, get_default=None, name=None):
+        return BoundDirective(cls, default, get_default, name)
+
+
+class BoundDirective(object):
+
+    def __init__(self, directive, default=None, get_default=None, name=None):
+        self.directive = directive
+        self.default = default
+        if name is None:
+            name = directive.__name__
+        self.name = name
+        if get_default is not None:
+            self.get_default = get_default
+
+    def get_default(self, component, module, **data):
+        if self.default is not None:
+            return self.default
+        return self.directive.default
+
+    def get(self, component, module=None, **data):
+        directive = self.directive
+        value = directive.store.get(directive, component, default=_USE_DEFAULT)
         if value is _USE_DEFAULT and module is not None:
-            value = self.store.get(self, module, _USE_DEFAULT)
+            value = directive.store.get(directive, module, default=_USE_DEFAULT)
         if value is _USE_DEFAULT:
-            value = self.get_default(component)
-
+            value = self.get_default(component, module, **data)
         return value
 
-    @classmethod
-    def set(cls, component, value):
-        # Create an instance of the directive without calling __init__
-        self = cls.__new__(cls)
-        cls.store.setattr(component, self, value)
 
-
 class MultipleTimesDirective(Directive):
     store = MULTIPLE
     default = []

Modified: martian/branches/philikon-decl-dir-rules/src/martian/directive.txt
===================================================================
--- martian/branches/philikon-decl-dir-rules/src/martian/directive.txt	2008-05-05 10:13:51 UTC (rev 86439)
+++ martian/branches/philikon-decl-dir-rules/src/martian/directive.txt	2008-05-05 10:31:19 UTC (rev 86440)
@@ -28,10 +28,11 @@
   >>> class Foo(object):
   ...    description(u"This is a description")
 
-After setting it, we can use the ``get`` method on the directive to
-retrieve it from the class again::
+After setting the description, we bind the directive and use the bound
+directive's ``get`` method to retrieve the description from the
+component (in other words, the class) again::
 
-  >>> description.get(Foo)
+  >>> description.bind().get(Foo)
   u'This is a description'
 
 Directives in different namespaces get stored differently. We'll
@@ -43,9 +44,9 @@
   >>> class Foo(object):
   ...     description(u"Description1")
   ...     description2(u"Description2")
-  >>> description.get(Foo)
+  >>> description.bind().get(Foo)
   u'Description1'
-  >>> description2.get(Foo)
+  >>> description2.bind().get(Foo)
   u'Description2'
 
 If we check the value of a class without the directive, we see the
@@ -53,14 +54,14 @@
 
   >>> class Foo(object):
   ...     pass
-  >>> description.get(Foo)
+  >>> description.bind().get(Foo)
   u''
 
 In certain cases we need to set a value on a component as if the directive was
 actually used::
 
   >>> description.set(Foo, u'value as set')
-  >>> description.get(Foo)
+  >>> description.bind().get(Foo)
   u'value as set'
 
 Subclasses of the original class will inherit the properties set by the
@@ -72,7 +73,7 @@
   >>> class Bar(Foo):
   ...     pass
   ...
-  >>> description.get(Bar)
+  >>> description.bind().get(Bar)
   'This is a foo.'
 
 When we use the directive outside of class scope, we get an error
@@ -128,14 +129,14 @@
 
   >>> class Foo(object):
   ...   layer('Test')
-  >>> layer.get(Foo)
+  >>> layer.bind().get(Foo)
   'Test'
 
 The defaulting to ``None`` works::
 
   >>> class Foo(object):
   ...   pass
-  >>> layer.get(Foo) is None
+  >>> layer.bind().get(Foo) is None
   True
 
 We can also use it in a module::
@@ -150,7 +151,7 @@
 module-level default which we just set. We pass the module as the
 second argument to the ``get`` method to have it fall back on this::
 
-  >>> layer.get(testmodule.Foo, testmodule)
+  >>> layer.bind().get(testmodule.Foo, testmodule)
   'Test2'
 
 Let's look at a module where the directive is not used::
@@ -163,7 +164,7 @@
 In this case, the value cannot be found so the system falls back on
 the default, ``None``::
 
-  >>> layer.get(testmodule.Foo, testmodule) is None
+  >>> layer.bind().get(testmodule.Foo, testmodule) is None
   True
 
 Using a directive multiple times
@@ -184,14 +185,14 @@
 
 We can now retrieve the value and we'll get a list::
 
-  >>> multi.get(Foo)
+  >>> multi.bind().get(Foo)
   [u'Once', u'Twice']
 
 The default value for a MultipleTimesDirective is an empty list::
 
   >>> class Bar(object):
   ...   pass
-  >>> multi.get(Bar)
+  >>> multi.bind().get(Bar)
   []
 
 Whenever the directive is used on a sub class of a component, the values set by
@@ -200,7 +201,7 @@
   >>> class Qux(Foo):
   ...     multi(u'Triple')
   ...
-  >>> multi.get(Qux)
+  >>> multi.bind().get(Qux)
   [u'Once', u'Twice', u'Triple']
 
 
@@ -226,7 +227,7 @@
 
 We can now retrieve the value and we'll get a to the items::
 
-  >>> d = multi.get(Bar)
+  >>> d = multi.bind().get(Bar)
   >>> print sorted(d.items())
   [(u'once', u'Once'), (u'twice', u'Twice')]
 
@@ -276,7 +277,7 @@
   ...   multi(3, 'DDD')
   ...   multi(4, 'EEE')
 
-  >>> d = multi.get(Fropple)
+  >>> d = multi.bind().get(Fropple)
   >>> print sorted(d.items())
   [(1, 'CCC'), (2, 'BBB'), (3, 'DDD'), (4, 'EEE')]
 
@@ -295,7 +296,7 @@
   ...     multi('Two')
   ...
   >>> module_with_directive = fake_import(module_with_directive)
-  >>> print multi.get(module_with_directive)
+  >>> print multi.bind().get(module_with_directive)
   ['One', 'Two']
 
   >>> from martian import MODULE
@@ -313,7 +314,7 @@
   ...     multi(2, 'Two')
   ...
   >>> module_with_directive = fake_import(module_with_directive)
-  >>> d = multi.get(module_with_directive)
+  >>> d = multi.bind().get(module_with_directive)
   >>> print sorted(d.items())
   [(1, 'One'), (2, 'Two')]
 
@@ -329,17 +330,21 @@
   >>> class name(Directive):
   ...     scope = CLASS
   ...     store = ONCE
-  ...     def get_default(self, component):
-  ...         return component.__name__.lower()
+  ...
+  >>> def default_name_lowercase(component, module, **data):
+  ...     return component.__name__.lower()
+  ...
+  >>> bound_name = name.bind(get_default=default_name_lowercase)
 
   >>> class Foo(object):
   ...   name('bar')
-  >>> name.get(Foo)
+
+  >>> bound_name.get(Foo)
   'bar'
 
   >>> class Foo(object):
   ...   pass
-  >>> name.get(Foo)
+  >>> bound_name.get(Foo)
   'foo'
 
 A marker directive
@@ -357,14 +362,14 @@
 
 Class ``Foo`` is now marked::
 
-  >>> mark.get(Foo)
+  >>> mark.bind().get(Foo)
   True
 
 When we have a class that isn't marked, we get the default value, ``False``::
 
   >>> class Bar(object):
   ...    pass
-  >>> mark.get(Bar)
+  >>> mark.bind().get(Bar)
   False
 
 If we pass in an argument, we get an error::
@@ -539,7 +544,7 @@
 As you would expect, the directive will correctly identify this class as a
 baseclass:
 
-  >>> baseclass.get(MyBase)
+  >>> baseclass.bind().get(MyBase)
   True
 
 But, if we create a subclass of this base class, the subclass won't inherit
@@ -548,7 +553,7 @@
   >>> class SubClass(MyBase):
   ...     pass
   ...
-  >>> baseclass.get(SubClass)
+  >>> baseclass.bind().get(SubClass)
   False
 
 Naturally, the directive will also report a false answer if the class doesn't
@@ -557,5 +562,5 @@
   >>> class NoBase(object):
   ...     pass
   ...
-  >>> baseclass.get(NoBase)
+  >>> baseclass.bind().get(NoBase)
   False

Modified: martian/branches/philikon-decl-dir-rules/src/martian/util.py
===================================================================
--- martian/branches/philikon-decl-dir-rules/src/martian/util.py	2008-05-05 10:13:51 UTC (rev 86439)
+++ martian/branches/philikon-decl-dir-rules/src/martian/util.py	2008-05-05 10:31:19 UTC (rev 86440)
@@ -49,7 +49,7 @@
     return sys._getframe(2).f_globals['__name__']
 
 def is_baseclass(name, component):
-    return (isclass(component) and martian.baseclass.get(component))
+    return (isclass(component) and martian.baseclass.bind().get(component))
 
 def defined_locally(obj, dotted_name):
     obj_module = getattr(obj, '__grok_module__', None)



More information about the Checkins mailing list