Back to index

plone3  3.1.7
meta.py
Go to the documentation of this file.
00001 
00002 from zope.configuration.exceptions import ConfigurationError
00003 
00004 def configfeature(_context, feature, instance, attribute, negate=False):
00005     """Imports a python object and uses an attribute of it as a boolean value
00006     to declare a feature or not.
00007 
00008     Usage
00009     -----
00010 
00011     We can have an object with attributes,
00012 
00013     >>> class dictlike(object):
00014     ...     pass
00015     >>> conf1 = dictlike()
00016     >>> conf1.this = True
00017     >>> conf1.that = False
00018 
00019     and its attributes can defined a feature if they evaluate to True.
00020     The feature will not be defined if the value evaluates to False.
00021 
00022     >>> from zope.configuration.config import ConfigurationContext
00023     >>> c = ConfigurationContext()
00024     >>> configfeature(c, 'f1', conf1, 'this')
00025     >>> c.hasFeature('f1')
00026     True
00027     >>> configfeature(c, 'f2', conf1, 'that')
00028     >>> c.hasFeature('f2')
00029     False
00030 
00031     The boolean value can be negated, this allows it
00032     to overcome the shortage of negating possibilit of zcml:condition.
00033 
00034     >>> configfeature(c, 'f3', conf1, 'this', True)
00035     >>> c.hasFeature('f3')
00036     False
00037     >>> configfeature(c, 'f4', conf1, 'that', True)
00038     >>> c.hasFeature('f4')
00039     True
00040 
00041     Instead of an object with attributes, a dictionary can also be used:
00042 
00043     >>> dconf = {}
00044     >>> dconf['this'] = True
00045     >>> dconf['that'] = False
00046 
00047     >>> configfeature(c, 'f5', dconf, 'this')
00048     >>> c.hasFeature('f5')
00049     True
00050     >>> configfeature(c, 'f6', dconf, 'that')
00051     >>> c.hasFeature('f6')
00052     False
00053 
00054 
00055     Error handling
00056     --------------
00057 
00058     If there is an unexistent attribute, an error is reported.
00059 
00060     >>> configfeature(c, 'f7', conf1, 'nosuch')         #doctest: +ELLIPSIS
00061     Traceback (most recent call last):
00062     ...
00063     ConfigurationError: Object ... does not have attribute or key "nosuch"
00064 
00065     >>> configfeature(c, 'f8', dconf, 'nosuch')         #doctest: +ELLIPSIS
00066     Traceback (most recent call last):
00067     ...
00068     ConfigurationError: Object ... does not have attribute or key "nosuch"
00069 
00070 
00071     Finally, like with the "provides" directive normally:
00072     Spaces are not allowed in feature names (this is reserved for providing
00073     many features with a single directive in the futute).
00074 
00075     >>> configfeature(c, 'two words', conf1, 'this')
00076     Traceback (most recent call last):
00077     ...
00078     ValueError: Only one feature name allowed
00079 
00080     """
00081 
00082     try:
00083         value = getattr(instance, attribute)
00084     except AttributeError:
00085         # also try as dictionary value
00086         try:
00087             value = instance[attribute]
00088         except (TypeError, ValueError, KeyError):
00089             raise ConfigurationError, 'Object %s does not have attribute or key "%s"' % (instance, attribute)
00090 
00091     value = bool(value)
00092     if negate:
00093         value = not value
00094 
00095     if len(feature.split()) > 1:
00096         raise ValueError("Only one feature name allowed")
00097 
00098     if value:
00099         _context.provideFeature(feature)