Ignore:
Timestamp:
12 Feb 2011, 14:14:42 (14 years ago)
Author:
uli
Message:

Add a factory-factory.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • main/waeup.sirp/trunk/src/waeup/sirp/utils/helpers.py

    r4789 r5731  
    55import sys
    66import shutil
     7import grok
     8from zope.component.interfaces import IFactory
    79
    810def removeFileOrDirectory(filepath):
     
    9698    prefix = prefix[0].upper() + prefix[1:]
    9799    return '%s of %s' % (prefix, context.title)
     100
     101class FactoryBase(grok.GlobalUtility):
     102    """A factory for things.
     103
     104    This is a baseclass for easier creation of factories. Factories
     105    are utilities that are registered under a certain name and return
     106    instances of certain classes when called.
     107
     108    In :mod:`waeup.sirp` we use factories extensively for
     109    batching. While processing a batch some importer looks up a
     110    factory to create real-world instances that then get filled with
     111    data from imported CSV files.
     112
     113    To get rid of reimplementing the same stuff over and over again,
     114    most notably the methods defined here, we offer this base class
     115    (which will *not* be registered as a factory itself).
     116
     117    Real factories can then be created like this:
     118
     119       >>> import grok
     120       >>> from waeup.sirp.utils.helpers import FactoryBase
     121       >>> class MyObject(object):
     122       ...   # Some class we want to get instances of.
     123       ...   pass
     124       >>> class MyObjectFactory(FactoryBase):
     125       ...   # This is the factory for MyObject instances
     126       ...   grok.name(u'waeup.sirp.factory.MyObject')
     127       ...   factory = MyObject
     128
     129    That's it. It is essential to set the ``factory`` attribute, which
     130    will determine the class of which instances should be created when
     131    called. The given name must even be unique amongst all utilities
     132    registered during runtime. While you can pick any name you like
     133    you might want to prepend ``waeup.sirp.factory.`` to the name
     134    string to make sure it does not clash with names of other
     135    utilities one day.
     136
     137    Before all this works we have to grok the baseclass once and our
     138    freshly defined factory. This executes all the component
     139    registration stuff we don't want to do ourselves. In daily use
     140    this is done automatically on startup of a :mod:`waeup.sirp`
     141    system.
     142   
     143       >>> grok.testing.grok('waeup.sirp.utils.helpers')
     144       >>> grok.testing.grok_component(
     145       ...    'MyObjectFactory', MyObjectFactory
     146       ...  )
     147       True
     148
     149    After grokking we (and importers) can create objects without
     150    knowing about the location of the real class definition, just by
     151    the factory name:
     152
     153       >>> from zope.component import createObject
     154       >>> obj = createObject('waeup.sirp.factory.MyObject')
     155       >>> isinstance(obj, MyObject)
     156       True
     157
     158    We can also use the regular utility lookups to find our new
     159    factory:
     160
     161       >>> from zope.component import getUtility
     162       >>> from zope.component.interfaces import IFactory
     163       >>> factory = getUtility(
     164       ...   IFactory, name='waeup.sirp.factory.MyObject'
     165       ...   )
     166       >>> isinstance(factory, MyObjectFactory)
     167       True
     168
     169    And this factory generates `MyObject` instances:
     170
     171       >>> obj = factory()
     172       >>> isinstance(obj, MyObject)
     173       True
     174
     175    """
     176    grok.baseclass() # Do not grok this class, do not register us.
     177    grok.implements(IFactory)
     178    # You can override any of the following attributes in derived
     179    # classes. The `grok.name` setting *must* even be set to some
     180    # unique value.
     181    grok.name(u'waeup.Factory')
     182    title = u"Create instances of ``factory``.",
     183    description = u"This factory instantiates new applicant instances."
     184    factory = None
     185
     186    def __call__(self, *args, **kw):
     187        """The main factory function.
     188
     189        Returns an instance of the requested object.
     190        """
     191        return self.factory()
     192
     193    def getInterfaces(self):
     194        # Required by IFactory
     195        return implementedBy(self.factory)
Note: See TracChangeset for help on using the changeset viewer.