[Checkins] SVN: martian/trunk/ Make resolve() work for fake modules by letting them properly importable
Martijn Faassen
faassen at infrae.com
Mon Jan 12 15:30:52 EST 2009
Log message for revision 94709:
Make resolve() work for fake modules by letting them properly importable
modules.
Changed:
U martian/trunk/CHANGES.txt
U martian/trunk/src/martian/README.txt
U martian/trunk/src/martian/core.txt
U martian/trunk/src/martian/directive.txt
U martian/trunk/src/martian/edgecase.txt
U martian/trunk/src/martian/testing.py
U martian/trunk/src/martian/tests/test_all.py
-=-
Modified: martian/trunk/CHANGES.txt
===================================================================
--- martian/trunk/CHANGES.txt 2009-01-12 19:53:00 UTC (rev 94708)
+++ martian/trunk/CHANGES.txt 2009-01-12 20:30:51 UTC (rev 94709)
@@ -20,6 +20,13 @@
* Pass along ``exclude_filter`` (and the new ``ignore_nonsource``
flag) to ModuleInfo constructor when it calls itself recursively.
+* Replace ``fake_import`` to import fake modules in tests with a real
+ python import statement (``from martiantest.fake import
+ my_fake_module``). This works by introducing a metaclass for
+ ``FakeModule`` that automatically registers it as a module. The
+ irony does not escape us. This also means that
+ ``martian.scan.resolve()`` will now work on fake modules.
+
0.11 (2008-09-24)
=================
Modified: martian/trunk/src/martian/README.txt
===================================================================
--- martian/trunk/src/martian/README.txt 2009-01-12 19:53:00 UTC (rev 94708)
+++ martian/trunk/src/martian/README.txt 2009-01-12 20:30:51 UTC (rev 94709)
@@ -125,10 +125,10 @@
class. Whenever you see ``FakeModule`` subclasses, imagine you're
looking at a module definition in a ``.py`` file. Now that we have
defined a module ``templating``, we also need to be able to import
-it. To do so we can use a a fake import statement that lets us do
-this::
+it. Fake modules are always placed automatically into the
+``martiantest.fake`` namespace so you can import them from there::
- >>> templating = fake_import(templating)
+ >>> from martiantest.fake import templating
Now let's try the ``render`` function for the registered template
types, to demonstrate that our framework works::
@@ -163,7 +163,7 @@
... return text
...
... templating.extension_handlers['.silly'] = SillyTemplate
- >>> sillytemplating = fake_import(sillytemplating)
+ >>> from martiantest.fake import sillytemplating
In the extension module, we manipulate the ``extension_handlers``
dictionary of the ``templating`` module (in normal code we'd need to
@@ -256,7 +256,7 @@
... # this hasn't changed
... template = extension_handlers[extension](data)
... return template.render(**kw)
- >>> templating = fake_import(templating)
+ >>> from martiantest.fake import templating
As you can see, there have been very few changes:
@@ -278,7 +278,7 @@
... def execute(self, class_, extension, **kw):
... templating.extension_handlers[extension] = class_
... return True
- >>> meta = fake_import(meta)
+ >>> from martiantest.fake import meta
What does this do? A ``ClassGrokker`` has its ``execute`` method
called for subclasses of what's indicated by the ``martian.component``
@@ -341,7 +341,7 @@
... for key, value in kw.items():
... text = text.replace('{%s}' % key, value)
... return text
- >>> sillytemplating = fake_import(sillytemplating)
+ >>> from martiantest.fake import sillytemplating
As you can see, the developer that uses the framework has no need
anymore to know about ``templating.extension_handlers``. Instead we can
@@ -389,7 +389,7 @@
... elephant = Animal('elephant')
... lion = Animal('lion')
... animals = {}
- >>> zoo = fake_import(zoo)
+ >>> from martiantest.fake import zoo
We define an ``InstanceGrokker`` subclass to grok ``Animal`` instances::
@@ -399,7 +399,7 @@
... def execute(self, instance, **kw):
... zoo.animals[instance.name] = instance
... return True
- >>> meta = fake_import(meta)
+ >>> from martiantest.fake import meta
Let's create a new registry with the ``AnimalGrokker`` in it::
Modified: martian/trunk/src/martian/core.txt
===================================================================
--- martian/trunk/src/martian/core.txt 2009-01-12 19:53:00 UTC (rev 94708)
+++ martian/trunk/src/martian/core.txt 2009-01-12 20:30:51 UTC (rev 94709)
@@ -21,7 +21,7 @@
... def handle(filepath):
... name, ext = os.path.splitext(filepath)
... return extension_handlers[ext](filepath)
- >>> filehandler = fake_import(filehandler)
+ >>> from martiantest.fake import filehandler
Now let's try the ``handle`` function for a few file types::
@@ -46,7 +46,7 @@
... return "PNG file"
...
... filehandler.extension_handlers['.png'] = handle_png
- >>> pnghandler = fake_import(pnghandler)
+ >>> from martiantest.fake import pnghandler
In the extension module, we manipulate the ``extension_handlers``
dictionary of the ``filehandler`` module and plug in our own
@@ -153,7 +153,7 @@
...
... def handle_svg(filepath):
... return "SVG file"
- >>> lotsofhandlers = fake_import(lotsofhandlers)
+ >>> from martiantest.fake import lotsofhandlers
Let's grok it::
@@ -192,9 +192,8 @@
... def handle(filepath):
... name, ext = os.path.splitext(filepath)
... return extension_handlers[ext](filepath)
+ >>> from martiantest.fake import filehandler
- >>> filehandler = fake_import(filehandler)
-
Let's use martian to do the registrations for us::
>>> module_grokker.grok('filehandler', filehandler)
@@ -217,7 +216,7 @@
... def __repr__(self):
... return '<Color %s %s %s>' % (self.r, self.g, self.b)
... all_colors = {}
- >>> color = fake_import(color)
+ >>> from martiantest.fake import color
We now want a grokker that can recognize colors and put them in the
``all_colors`` dictionary, with the names as the keys, and the color
@@ -250,7 +249,7 @@
... green = Color(0, 255, 0)
... blue = Color(0, 0, 255)
... white = Color(255, 255, 255)
- >>> colors = fake_import(colors)
+ >>> from martiantest.fake import colors
>>> colors_grokker = martian.ModuleGrokker()
>>> colors_grokker.register(color_grokker)
>>> colors_grokker.grok('colors', colors)
@@ -268,7 +267,7 @@
... class SpecialColor(Color):
... pass
... octarine = SpecialColor(-255, 0, -255)
- >>> subcolors = fake_import(subcolors)
+ >>> from martiantest.fake import subcolors
>>> colors_grokker.grok('subcolors', subcolors)
True
>>> 'octarine' in color.all_colors
@@ -289,7 +288,7 @@
... def __repr__(self):
... return '<Sound %s>' % (self.desc)
... all_sounds = {}
- >>> sound = fake_import(sound)
+ >>> from martiantest.fake import sound
>>> class SoundGrokker(martian.InstanceGrokker):
... martian.component(sound.Sound)
@@ -343,7 +342,7 @@
... scream = Sound('scream')
... dark_green = Color(0, 150, 0)
... cheer = Sound('cheer')
- >>> lightandsound = fake_import(lightandsound)
+ >>> from martiantest.fake import lightandsound
>>> module_grokker.grok('lightandsound', lightandsound)
True
>>> 'dark_red' in color.all_colors
@@ -376,7 +375,7 @@
... all_animals = {}
... def create_animal(name):
... return all_animals[name]()
- >>> animal = fake_import(animal)
+ >>> from martiantest.fake import animal
Let's define a grokker that can grok an ``Animal``. We could either
implement the ``grok`` method as with ``InstanceGrokkers``, or we can
@@ -570,7 +569,7 @@
... animal.name('lion')
... class Chair(object):
... animal.name('chair')
- >>> animals = fake_import(animals)
+ >>> from martiantest.fake import animals
First we need to wrap our ``AnimalGrokker`` into a ``MultiClassGrokker``::
@@ -721,7 +720,7 @@
... animal.name('sperm whale')
... # not grokked
... another = object()
- >>> mix = fake_import(mix)
+ >>> from martiantest.fake import mix
Let's construct a ``ModuleGrokker`` that can grok this module::
@@ -762,7 +761,7 @@
>>> class g(FakeModule):
... amount = 50
- >>> g = fake_import(g)
+ >>> from martiantest.fake import g
Now let's create a ``GlobalGrokker`` that reads ``amount`` and stores
it in the ``read_amount`` dictionary::
@@ -798,7 +797,7 @@
... pass
... all_machines = {}
... all_machine_instances = {}
- >>> oldstyle = fake_import(oldstyle)
+ >>> from martiantest.fake import oldstyle
Let's make a grokker for the old style class::
@@ -899,7 +898,7 @@
... one = Number(1)
... two = Number(2)
... four = Number(4)
- >>> numbers = fake_import(numbers)
+ >>> from martiantest.fake import numbers
>>> module_grokker.grok('numbers', numbers)
True
>>> sorted(all_numbers.items())
@@ -1045,7 +1044,7 @@
... def grok(self, name, obj, **kw):
... executed.append(name)
... return True
- >>> somemodule = fake_import(somemodule)
+ >>> from martiantest.fake import somemodule
>>> module_grokker = martian.ModuleGrokker(MetaMultiGrokker())
Let's grok the module once::
@@ -1064,7 +1063,7 @@
>>> class anothermodule(FakeModule):
... class TestSub(TestOnce):
... pass
- >>> anothermodule = fake_import(anothermodule)
+ >>> from martiantest.fake import anothermodule
>>> module_grokker.grok('anothermodule', anothermodule)
True
>>> executed
@@ -1081,7 +1080,7 @@
... def grok(self, name, obj, **kw):
... executed.append(name)
... return True
- >>> somemodule = fake_import(somemodule)
+ >>> from martiantest.fake import somemodule
>>> module_grokker.clear()
>>> module_grokker.grok('somemodule', somemodule) # once
True
@@ -1089,7 +1088,7 @@
True
>>> class anothermodule(FakeModule):
... test = TestInstanceOnce()
- >>> anothermodule = fake_import(anothermodule)
+ >>> from martiantest.fake import anothermodule
>>> module_grokker.grok('anothermodule', anothermodule)
True
>>> executed
@@ -1103,7 +1102,7 @@
... def grok(self, name, obj, **kw):
... executed.append(name)
... return True
- >>> somemodule = fake_import(somemodule)
+ >>> from martiantest.fake import somemodule
>>> module_grokker.clear()
>>> module_grokker.grok('somemodule', somemodule) # once
True
@@ -1119,7 +1118,7 @@
>>> class anothermodule(FakeModule):
... pass
- >>> anothermodule = fake_import(anothermodule)
+ >>> from martiantest.fake import anothermodule
>>> module_grokker.grok('anothermodule', anothermodule)
True
>>> executed
@@ -1172,7 +1171,7 @@
... pass
... class BSub(B):
... pass
- >>> mymodule = fake_import(mymodule)
+ >>> from martiantest.fake import mymodule
We'll grok it::
Modified: martian/trunk/src/martian/directive.txt
===================================================================
--- martian/trunk/src/martian/directive.txt 2009-01-12 19:53:00 UTC (rev 94708)
+++ martian/trunk/src/martian/directive.txt 2009-01-12 20:30:51 UTC (rev 94709)
@@ -151,7 +151,7 @@
... layer('Test2')
... class Foo(object):
... pass
- >>> testmodule = fake_import(testmodule)
+ >>> from martiantest.fake import testmodule
When we now try to access ``layer`` on ``Foo``, we find the
module-level default which we just set. We pass the module as the
@@ -165,7 +165,7 @@
>>> class testmodule(FakeModule):
... class Foo(object):
... pass
- >>> testmodule = fake_import(testmodule)
+ >>> from martiantest.fake import testmodule
In this case, the value cannot be found so the system falls back on
the default, ``None``::
@@ -325,7 +325,7 @@
... multi('One')
... multi('Two')
...
- >>> module_with_directive = fake_import(module_with_directive)
+ >>> from martiantest.fake import module_with_directive
>>> print multi.bind().get(module=module_with_directive)
['One', 'Two']
@@ -343,7 +343,7 @@
... multi(1, 'One')
... multi(2, 'Two')
...
- >>> module_with_directive = fake_import(module_with_directive)
+ >>> from martiantest.fake import module_with_directive
>>> d = multi.bind().get(module=module_with_directive)
>>> print sorted(d.items())
[(1, 'One'), (2, 'Two')]
Modified: martian/trunk/src/martian/edgecase.txt
===================================================================
--- martian/trunk/src/martian/edgecase.txt 2009-01-12 19:53:00 UTC (rev 94708)
+++ martian/trunk/src/martian/edgecase.txt 2009-01-12 20:30:51 UTC (rev 94709)
@@ -24,7 +24,7 @@
...
... store(some_function)
...
- >>> module_with_directive = fake_import(module_with_directive)
+ >>> from martiantest.fake import module_with_directive
Now imagine we have the following grokker for functions:
Modified: martian/trunk/src/martian/testing.py
===================================================================
--- martian/trunk/src/martian/testing.py 2009-01-12 19:53:00 UTC (rev 94708)
+++ martian/trunk/src/martian/testing.py 2009-01-12 20:30:51 UTC (rev 94709)
@@ -1,10 +1,12 @@
import new
+import sys
-class FakeModule(object):
- pass
-
def fake_import(fake_module):
- module = new.module(fake_module.__name__)
+ module_name = 'martiantest.fake.' + fake_module.__name__
+ module = new.module(module_name)
+ module_name_parts = module_name.split('.')
+ module.__file__ = '/' + '/'.join(module_name_parts)
+
glob = {}
for name in dir(fake_module):
if name.startswith('__') and '.' not in name:
@@ -43,4 +45,22 @@
glob[name] = new_func
except AttributeError:
pass
+
+ if not 'martiantest' in sys.modules:
+ sys.modules['martiantest'] = new.module('martiantest')
+ sys.modules['martiantest.fake'] = new.module('martiantest.fake')
+ sys.modules['martiantest'].fake = sys.modules['martiantest.fake']
+
+ sys.modules[module_name] = module
+ setattr(sys.modules['martiantest.fake'], module_name.split('.')[-1],
+ module)
+
return module
+
+class FakeModuleMetaclass(type):
+ def __init__(cls, classname, bases, dict_):
+ fake_import(cls)
+ return type.__init__(cls, classname, bases, dict_)
+
+class FakeModule(object):
+ __metaclass__ = FakeModuleMetaclass
Modified: martian/trunk/src/martian/tests/test_all.py
===================================================================
--- martian/trunk/src/martian/tests/test_all.py 2009-01-12 19:53:00 UTC (rev 94708)
+++ martian/trunk/src/martian/tests/test_all.py 2009-01-12 20:30:51 UTC (rev 94709)
@@ -1,10 +1,10 @@
import unittest
from zope.testing import doctest
-from martian.testing import FakeModule, fake_import
+from martian.testing import FakeModule
optionflags = doctest.NORMALIZE_WHITESPACE + doctest.ELLIPSIS
-globs = dict(FakeModule=FakeModule, fake_import=fake_import)
+globs = dict(FakeModule=FakeModule)
def test_suite():
suite = unittest.TestSuite()
More information about the Checkins
mailing list