[Checkins] SVN: martian/trunk/src/martian/ merge jw-class-or-module-scope-edge-cases
Jan-Wijbrand Kolman
janwijbrand at gmail.com
Fri Feb 20 15:52:45 EST 2009
Log message for revision 96854:
merge jw-class-or-module-scope-edge-cases
Changed:
U martian/trunk/src/martian/directive.py
U martian/trunk/src/martian/directive.txt
U martian/trunk/src/martian/edgecase.txt
-=-
Modified: martian/trunk/src/martian/directive.py
===================================================================
--- martian/trunk/src/martian/directive.py 2009-02-20 20:46:55 UTC (rev 96853)
+++ martian/trunk/src/martian/directive.py 2009-02-20 20:52:45 UTC (rev 96854)
@@ -130,11 +130,11 @@
def check(self, frame):
return util.frame_is_class(frame) and not is_fake_module(frame)
- def get(self, directive, component, module, get_default):
+ def get(self, directive, component, get_default):
result = directive.store.get(directive, component, _USE_DEFAULT)
if result is not _USE_DEFAULT:
return result
- # we may be really dealing with an instance instead of a class
+ # We may be really dealing with an instance instead of a class.
if not util.isclass(component):
component = component.__class__
for base in inspect.getmro(component):
@@ -152,13 +152,18 @@
def check(self, frame):
return util.frame_is_class(frame) or util.frame_is_module(frame)
- def get(self, directive, component, module, get_default):
+ def get(self, directive, component, get_default):
# look up class-level directive on this class or its bases
# we don't need to loop through the __mro__ here as Python will
# do it for us
result = directive.store.get(directive, component, _USE_DEFAULT)
if result is not _USE_DEFAULT:
return result
+
+ # we may be really dealing with an instance or a module here
+ if not util.isclass(component):
+ return get_default(component, component)
+
# now we need to loop through the mro, potentially twice
mro = inspect.getmro(component)
# look up module-level directive for this class or its bases
@@ -184,11 +189,11 @@
def check(self, frame):
return util.frame_is_module(frame) or is_fake_module(frame)
- def get(self, directive, component, module, get_default):
- result = directive.store.get(directive, module, _USE_DEFAULT)
+ def get(self, directive, component, get_default):
+ result = directive.store.get(directive, component, _USE_DEFAULT)
if result is not _USE_DEFAULT:
return result
- return get_default(component, module)
+ return get_default(component, component)
MODULE = ModuleScope()
@@ -265,7 +270,7 @@
directive = self.directive
def get_default(component, module):
return self.get_default(component, module, **data)
- return directive.scope.get(directive, component, module,
+ return directive.scope.get(directive, component,
get_default=get_default)
class MultipleTimesDirective(Directive):
Modified: martian/trunk/src/martian/directive.txt
===================================================================
--- martian/trunk/src/martian/directive.txt 2009-02-20 20:46:55 UTC (rev 96853)
+++ martian/trunk/src/martian/directive.txt 2009-02-20 20:52:45 UTC (rev 96854)
@@ -173,6 +173,49 @@
>>> layer.bind().get(testmodule.Foo, testmodule) is None
True
+
+
+
+Like with CLASS scope directive where values set are inherited by subclasses,
+values set on a class or module level are inherited too, even if the subclass
+is defined another module::
+
+ >>> class testmodule_a(FakeModule):
+ ... layer('Value set on baseclass module')
+ ... class FooA(object):
+ ... pass
+ >>> from martiantest.fake import testmodule_a
+ >>>
+ >>> class testmodule_b(FakeModule):
+ ... class FooB(testmodule_a.FooA):
+ ... pass
+ >>> from martiantest.fake import testmodule_b
+
+On the baseclass::
+
+ >>> layer.bind().get(testmodule_a.FooA)
+ 'Value set on baseclass module'
+
+Inherited by the subclass::
+
+ >>> layer.bind().get(testmodule_b.FooB)
+ 'Value set on baseclass module'
+
+Whenever there's a directive set on the baseclass' module, it will take
+precedence like with "normal" inheritance::
+
+ >>> class testmodule_c(FakeModule):
+ ... layer('Value set on subclass module')
+ ... class FooC(testmodule_a.FooA):
+ ... pass
+ >>> from martiantest.fake import testmodule_c
+
+ >>> layer.bind().get(testmodule_c.FooC)
+ 'Value set on subclass module'
+
+
+
+
Let's now look at this using a directive with CLASS scope only::
>>> class layer2(Directive):
@@ -402,7 +445,7 @@
... multi('Two')
...
>>> from martiantest.fake import module_with_directive
- >>> print multi.bind().get(module=module_with_directive)
+ >>> print multi.bind().get(module_with_directive)
['One', 'Two']
>>> from martian import MODULE
@@ -420,7 +463,7 @@
... multi(2, 'Two')
...
>>> from martiantest.fake import module_with_directive
- >>> d = multi.bind().get(module=module_with_directive)
+ >>> d = multi.bind().get(module_with_directive)
>>> print sorted(d.items())
[(1, 'One'), (2, 'Two')]
@@ -898,7 +941,7 @@
>>> from martian import validateClass
>>> class klass(Directive):
- ... scope = CLASS
+ ... scope = CLASS
... store = ONCE
... validate = validateClass
Modified: martian/trunk/src/martian/edgecase.txt
===================================================================
--- martian/trunk/src/martian/edgecase.txt 2009-02-20 20:46:55 UTC (rev 96853)
+++ martian/trunk/src/martian/edgecase.txt 2009-02-20 20:52:45 UTC (rev 96854)
@@ -45,3 +45,260 @@
>>> module_grokker.grok('module_with_directive', module_with_directive)
some_function 11
True
+
+Directive scope and default edge cases
+--------------------------------------
+
+ >>> from martian import Directive, CLASS_OR_MODULE, CLASS, MODULE
+ >>> from martian import ONCE
+
+MODULE scope directive on a module, with no explicit value::
+
+ >>> class mydir(martian.Directive):
+ ... scope = MODULE
+ ... store = ONCE
+ >>> class module_no_explicit_value(FakeModule):
+ ... fake_module = True
+ >>> from martiantest.fake import module_no_explicit_value
+ >>> mydir.bind().get(module_no_explicit_value) is None
+ True
+
+MODULE scope directive on a module, with an explicit value::
+
+ >>> class mydir2(martian.Directive):
+ ... scope = MODULE
+ ... store = ONCE
+ >>> class module_with_explicit_value(FakeModule):
+ ... fake_module = True
+ ... mydir2('the explicit value')
+ >>> from martiantest.fake import module_with_explicit_value
+ >>> mydir2.bind().get(module_with_explicit_value)
+ 'the explicit value'
+
+MODULE scope directive on a module, with no explicit value, with a custom default::
+
+ >>> class mydir(martian.Directive):
+ ... scope = MODULE
+ ... store = ONCE
+ >>> class module_custom_default(FakeModule):
+ ... fake_module = True
+ >>> from martiantest.fake import module_custom_default
+ >>> def custom(component, module, **data):
+ ... return 'a custom default value'
+ >>> mydir.bind(get_default=custom).get(module_custom_default)
+ 'a custom default value'
+
+CLASS scope directive on a class, with no explicit value::
+
+ >>> class mydir(martian.Directive):
+ ... scope = CLASS
+ ... store = ONCE
+ >>> class module_get_from_class_no_explicit(FakeModule):
+ ... class MyClass(object):
+ ... pass
+ >>> from martiantest.fake import module_get_from_class_no_explicit
+ >>> mydir.bind().get(module_get_from_class_no_explicit.MyClass) is None
+ True
+
+CLASS scope directive on an instance, with no explicit value::
+
+ >>> class mydir(martian.Directive):
+ ... scope = CLASS
+ ... store = ONCE
+ >>> class module_get_from_instance_no_explicit(FakeModule):
+ ... class MyClass(object):
+ ... pass
+ ... obj = MyClass()
+ >>> from martiantest.fake import module_get_from_instance_no_explicit
+ >>> mydir.bind().get(module_get_from_instance_no_explicit.obj) is None
+ True
+
+CLASS scope directive on a class, with an explicit value::
+
+ >>> class mydir(martian.Directive):
+ ... scope = CLASS
+ ... store = ONCE
+ >>> class module_get_from_class_with_explicit(FakeModule):
+ ... class MyClass(object):
+ ... mydir('explicitly set')
+ >>> from martiantest.fake import module_get_from_class_with_explicit
+ >>> mydir.bind().get(module_get_from_class_with_explicit.MyClass)
+ 'explicitly set'
+
+CLASS scope directive on an instance, with an explicit value::
+
+ >>> class mydir(martian.Directive):
+ ... scope = CLASS
+ ... store = ONCE
+ >>> class module_get_from_instance_with_explicit(FakeModule):
+ ... class MyClass(object):
+ ... mydir('explicitly set')
+ ... obj = MyClass()
+ >>> from martiantest.fake import module_get_from_instance_with_explicit
+ >>> mydir.bind().get(module_get_from_instance_with_explicit.obj)
+ 'explicitly set'
+
+CLASS scope directive on a class, with a custom default::
+
+ >>> class mydir(martian.Directive):
+ ... scope = CLASS
+ ... store = ONCE
+ >>> class module_get_from_class_with_custom(FakeModule):
+ ... class MyClass(object):
+ ... pass
+ >>> from martiantest.fake import module_get_from_class_with_custom
+ >>> def custom_get_default(component, module, **data):
+ ... return 'custom default'
+ >>> mydir.bind(get_default=custom_get_default).get(
+ ... module_get_from_class_with_custom.MyClass)
+ 'custom default'
+
+CLASS scope directive on an instance, with a custom default::
+
+ >>> class mydir(martian.Directive):
+ ... scope = CLASS
+ ... store = ONCE
+ >>> class module_get_from_instance_with_custom(FakeModule):
+ ... class MyClass(object):
+ ... pass
+ ... obj = MyClass()
+ >>> from martiantest.fake import module_get_from_instance_with_custom
+ >>> mydir.bind(get_default=custom_get_default).get(
+ ... module_get_from_instance_with_custom.obj)
+ 'custom default'
+
+CLASS_OR_MODULE scope directive on a module, with no explicit value::
+
+ >>> class mydir(martian.Directive):
+ ... scope = CLASS_OR_MODULE
+ ... store = ONCE
+ >>> class module(FakeModule):
+ ... fake_module = True
+ ... pass
+ >>> from martiantest.fake import module
+ >>> mydir.bind().get(module) is None
+ True
+
+CLASS_OR_MODULE scope directive on a class, with no explicit value::
+
+ >>> class mydir(martian.Directive):
+ ... scope = CLASS_OR_MODULE
+ ... store = ONCE
+ >>> class module(FakeModule):
+ ... fake_module = True
+ ... class MyClass(object):
+ ... pass
+ >>> from martiantest.fake import module
+ >>> mydir.bind().get(module.MyClass) is None
+ True
+
+CLASS_OR_MODULE scope directive on an instance, with no explicit value::
+
+ >>> class mydir(martian.Directive):
+ ... scope = CLASS_OR_MODULE
+ ... store = ONCE
+ >>> class module(FakeModule):
+ ... fake_module = True
+ ... class MyClass(object):
+ ... pass
+ ... obj = MyClass()
+ >>> from martiantest.fake import module
+ >>> mydir.bind().get(module.obj) is None
+ True
+
+CLASS_OR_MODULE scope directive on a module, with an explicit value::
+
+ >>> class mydir(martian.Directive):
+ ... scope = CLASS_OR_MODULE
+ ... store = ONCE
+ >>> class module(FakeModule):
+ ... fake_module = True
+ ... mydir('explicitly set, see?')
+ >>> from martiantest.fake import module
+ >>> mydir.bind().get(module)
+ 'explicitly set, see?'
+
+CLASS_OR_MODULE scope directive on a class, with an explicit value::
+
+ >>> class mydir(martian.Directive):
+ ... scope = CLASS_OR_MODULE
+ ... store = ONCE
+ >>> class module(FakeModule):
+ ... fake_module = True
+ ... class MyClass(object):
+ ... mydir('explicitly set, see?')
+ >>> from martiantest.fake import module
+ >>> mydir.bind().get(module.MyClass)
+ 'explicitly set, see?'
+
+CLASS_OR_MODULE scope directive on an instance, with an explicit value::
+
+ >>> class mydir(martian.Directive):
+ ... scope = CLASS_OR_MODULE
+ ... store = ONCE
+ >>> class module(FakeModule):
+ ... fake_module = True
+ ... class MyClass(object):
+ ... mydir('explicitly set, see?')
+ ... obj = MyClass()
+ >>> from martiantest.fake import module
+ >>> mydir.bind().get(module.obj)
+ 'explicitly set, see?'
+
+CLASS_OR_MODULE scope directive on a module, with a custom default::
+
+ >>> class mydir(martian.Directive):
+ ... scope = CLASS_OR_MODULE
+ ... store = ONCE
+ >>> class module(FakeModule):
+ ... fake_module = True
+ >>> from martiantest.fake import module
+ >>> mydir.bind(get_default=custom_get_default).get(module)
+ 'custom default'
+
+CLASS_OR_MODULE scope directive on a class, with a custom default::
+
+ >>> class mydir(martian.Directive):
+ ... scope = CLASS_OR_MODULE
+ ... store = ONCE
+ >>> class module(FakeModule):
+ ... fake_module = True
+ ... class MyClass(object):
+ ... pass
+ >>> from martiantest.fake import module
+ >>> mydir.bind(get_default=custom_get_default).get(module.MyClass)
+ 'custom default'
+
+CLASS_OR_MODULE scope directive on an instance, with a custom default::
+
+ >>> class mydir(martian.Directive):
+ ... scope = CLASS_OR_MODULE
+ ... store = ONCE
+ >>> class module(FakeModule):
+ ... fake_module = True
+ ... class MyClass(object):
+ ... pass
+ ... obj = MyClass()
+ >>> from martiantest.fake import module
+ >>> mydir.bind(get_default=custom_get_default).get(module.obj)
+ 'custom default'
+
+ CLASS_OR_MODULE scope directive on the module, with inheritance::
+
+ >>> class mydir(martian.Directive):
+ ... scope = CLASS_OR_MODULE
+ ... store = ONCE
+ >>> class module_b(FakeModule):
+ ... fake_module = True
+ ... mydir('a value')
+ ... class B(object):
+ ... pass
+ >>> from martiantest.fake import module_b
+ >>> class module_a(FakeModule):
+ ... fake_module = True
+ ... class A(module_b.B):
+ ... pass
+ >>> from martiantest.fake import module_a
+ >>> mydir.bind(get_default=custom_get_default).get(module_a.A)
+ 'a value'
+
More information about the Checkins
mailing list