source: main/waeup.sirp/trunk/src/waeup/sirp/utils/helpers.py @ 5736

Last change on this file since 5736 was 5736, checked in by uli, 14 years ago

Add doctest for getName.

File size: 6.8 KB
Line 
1"""General helper functions for WAeUP.
2"""
3import os
4import re
5import sys
6import shutil
7import grok
8from zope.component.interfaces import IFactory
9from zope.interface import implementedBy
10
11def removeFileOrDirectory(filepath):
12    """Remove a file or directory.
13    """
14    filepath = os.path.abspath(filepath)
15    if not os.path.exists(filepath):
16        return
17    if os.path.isdir(filepath):
18        shutil.rmtree(filepath)
19    else:
20        os.unlink(filepath)
21    return
22
23def copyFileSystemTree(src, dst, overwrite=False, del_old=False):
24    """Copy contents of directory src to directory dst.
25
26    Both directories must exists.
27
28    If `overwrite` is true, any same named objects will be
29    overwritten. Otherwise these files will not be touched.
30
31    If `del_old` is true, copied files and directories will be removed
32    from the src directory.
33
34    This functions returns a list of non-copied files.
35
36    Unix hidden files and directories (starting with '.') are not
37    processed by this function.
38    """
39    if not os.path.exists(src):
40        raise ValueError('source path does not exist: %s' % src)
41    if not os.path.exists(dst):
42        raise ValueError('destination path does not exist: %s' % dst)
43    if not os.path.isdir(src):
44        raise ValueError('source path is not a directory: %s' % src)
45    if not os.path.isdir(dst):
46        raise ValueError('destination path is not a directory: %s' % dst)
47    not_copied = []
48    for item in os.listdir(src):
49        if item.startswith('.'):
50            continue # We do not copy hidden stuff...
51        itemsrc = os.path.join(src, item)
52        itemdst = os.path.join(dst, item)
53
54        if os.path.exists(itemdst):
55            if overwrite is True:
56                removeFileOrDirectory(itemdst)
57            else:
58                not_copied.append(item)
59                continue
60       
61        if os.path.isdir(itemsrc):
62            shutil.copytree(itemsrc, itemdst)
63        else:
64            shutil.copy2(itemsrc, itemdst)
65        if del_old:
66            removeFileOrDirectory(itemsrc)
67    return not_copied
68
69
70def getInnerHTMLPart(html_code):
71    """Return the 'inner' part of a complete HTML snippet.
72
73    If there is a form part, get this.
74
75    If there is no form part, try to return the body part contents.
76
77    If there is no body, return as-is.
78    """
79
80    try:
81        result = re.match('^.+(<forms[^\>]*>.*</form>).+$', html_code,
82                          re.DOTALL).groups()[0]
83        return result
84    except AttributeError:
85        # No <form> part included
86        try:
87            result = re.match('^.+<body[^\>]*>(.*)</body>.*$', html_code,
88                              re.DOTALL).groups()[0]
89            return result
90        except AttributeError:
91            # No <form> and no <body> tag...
92            pass
93    return html_code
94
95def getName(context):
96    """Construct a name out of an object with prefix and title.
97
98    The `context` has to provide `title_prefix` and `title`
99    attributes.
100
101        >>> from waeup.sirp.utils.helpers import getName
102        >>> class FakeObject(object):
103        ...     title_prefix = 'department'
104        ...     title = 'Strange Things'
105        >>> getName(FakeObject())
106        'Department of Strange Things'
107
108    As we can see in the result the `title_prefix` is rendered
109    uppercase.
110       
111    """
112    prefix = context.title_prefix
113    prefix = prefix[0].upper() + prefix[1:]
114    return '%s of %s' % (prefix, context.title)
115
116class FactoryBase(grok.GlobalUtility):
117    """A factory for things.
118
119    This is a baseclass for easier creation of factories. Factories
120    are utilities that are registered under a certain name and return
121    instances of certain classes when called.
122
123    In :mod:`waeup.sirp` we use factories extensively for
124    batching. While processing a batch some importer looks up a
125    factory to create real-world instances that then get filled with
126    data from imported CSV files.
127
128    To get rid of reimplementing the same stuff over and over again,
129    most notably the methods defined here, we offer this base class
130    (which will *not* be registered as a factory itself).
131
132    Real factories can then be created like this:
133
134       >>> import grok
135       >>> from waeup.sirp.utils.helpers import FactoryBase
136       >>> class MyObject(object):
137       ...   # Some class we want to get instances of.
138       ...   pass
139       >>> class MyObjectFactory(FactoryBase):
140       ...   # This is the factory for MyObject instances
141       ...   grok.name(u'waeup.sirp.factory.MyObject')
142       ...   factory = MyObject
143
144    That's it. It is essential to set the ``factory`` attribute, which
145    will determine the class of which instances should be created when
146    called. The given name must even be unique amongst all utilities
147    registered during runtime. While you can pick any name you like
148    you might want to prepend ``waeup.sirp.factory.`` to the name
149    string to make sure it does not clash with names of other
150    utilities one day.
151
152    Before all this works we have to grok the baseclass once and our
153    freshly defined factory. This executes all the component
154    registration stuff we don't want to do ourselves. In daily use
155    this is done automatically on startup of a :mod:`waeup.sirp`
156    system.
157   
158       >>> grok.testing.grok('waeup.sirp.utils.helpers')
159       >>> grok.testing.grok_component(
160       ...    'MyObjectFactory', MyObjectFactory
161       ...  )
162       True
163
164    After grokking we (and importers) can create objects without
165    knowing about the location of the real class definition, just by
166    the factory name:
167
168       >>> from zope.component import createObject
169       >>> obj = createObject('waeup.sirp.factory.MyObject')
170       >>> isinstance(obj, MyObject)
171       True
172
173    We can also use the regular utility lookups to find our new
174    factory:
175
176       >>> from zope.component import getUtility
177       >>> from zope.component.interfaces import IFactory
178       >>> factory = getUtility(
179       ...   IFactory, name='waeup.sirp.factory.MyObject'
180       ...   )
181       >>> isinstance(factory, MyObjectFactory)
182       True
183
184    And this factory generates `MyObject` instances:
185
186       >>> obj = factory()
187       >>> isinstance(obj, MyObject)
188       True
189
190    """
191    grok.baseclass() # Do not grok this class, do not register us.
192    grok.implements(IFactory)
193    # You can override any of the following attributes in derived
194    # classes. The `grok.name` setting *must* even be set to some
195    # unique value.
196    grok.name(u'waeup.Factory')
197    title = u"Create instances of ``factory``.",
198    description = u"This factory instantiates new applicant instances."
199    factory = None
200
201    def __call__(self, *args, **kw):
202        """The main factory function.
203
204        Returns an instance of the requested object.
205        """
206        return self.factory()
207
208    def getInterfaces(self):
209        # Required by IFactory
210        return implementedBy(self.factory)
Note: See TracBrowser for help on using the repository browser.