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

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

Add missing import (detected by extended tests).

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