[Grok-dev] Re: Making an interface the default module context

Philipp von Weitershausen philipp at weitershausen.de
Mon Aug 4 04:22:31 EDT 2008


Martin Aspeli wrote:
>> Despite popular belief, grok doesn't actually use magic ;).
> 
> Do you prefer to be called "illusionists"? :)

Yes, much better! :)

>> If you can somehow find a rule by which this interface is found, then 
>> yes, it's possible. You'll have to override grokcore.component's 
>> ContextGrokker which looks at the module, determines the implicit 
>> module context and then uses the grok.context() directive to store 
>> this implicit context so that it'll look to subsequent grokkers as if 
>> grok.context() was used.
>>
>> So what you can do is write something like that:
>>
>>    from grokcore.component.meta import ContextGrokker
>>
>>    class MyContextGrokker(martian.GlobalGrokker):
>>        # execute this grokker before grokcore.component's ContextGrokker
>>        martian.priority(martian.priority.bind().get(ContextGrokker) + 1)
>>
>>        def grok(self, name, module, module_info, config, **kw):
>>            context = grok.context.bind().get(module=module)
>>            if context is None:
>>                # grok.context() wasn't used explicitly so let's try
>>                # to find an implicit context by our rules and then
>>                # set it
>>                implicit_context = somehow_determine_from(module)
>>                grok.context.set(module, implicit_context)
>>
>> All you now have to do is write this 'somehow_determine_from(module)' 
>> algorithm that looks at a module and finds your IFoo.
> 
> Maybe scan for something that provides IContext, if nothing implements it?

Sure, though I find it awkward having to write:

   class IFoo(Schema):
       pass

   alsoProvides(IFoo, IContext)

If you're trying to find implicit contexts that are interfaces, it'd be 
easier to look for interfaces that extend a certain interface, e.g. in 
your case that Schema thing. Here's what that could look like:

   def somehow_determine_from(module):
       results = []

       for name in dir(module):
           obj = module.getattr(module)
           if martian.util.defined_locally(obj, module.__name__):
               # obj wasn't imported into the module, it was
               # actually defined there
               if IInterface.providedBy(obj) and obj.extends(Schema):
                   results.append(obj)

       if not results:
          return None
       elif len(results) > 1:
          return grokcore.component.scan.AMIBIGUOUS_COMPONENT

       return results[0]


> I'm sure it can be done. My question is whether it's a good idea and 
> something worth having in Grok itself.

Maybe. If the function above were generalized a bit, it could have a 
place in grokcore.component or martian. We should see if this pattern 
comes up more often, though, and if it actually solves your problem.



More information about the Grok-dev mailing list