From: Wichert A. <svn...@pl...> - 2008-07-26 11:14:53
|
Author: wichert Date: Sat Jul 26 11:15:00 2008 New Revision: 9924 Added: archetypes.markerfield/ archetypes.markerfield/branches/ archetypes.markerfield/tags/ archetypes.markerfield/trunk/ archetypes.markerfield/trunk/README.txt (contents, props changed) archetypes.markerfield/trunk/archetypes/ archetypes.markerfield/trunk/archetypes/__init__.py (contents, props changed) archetypes.markerfield/trunk/archetypes/markerfield/ archetypes.markerfield/trunk/archetypes/markerfield/__init__.py (contents, props changed) archetypes.markerfield/trunk/archetypes/markerfield/field.py (contents, props changed) archetypes.markerfield/trunk/archetypes/markerfield/tests/ archetypes.markerfield/trunk/archetypes/markerfield/tests/__init__.py (contents, props changed) archetypes.markerfield/trunk/archetypes/markerfield/tests/testUtils.py (contents, props changed) archetypes.markerfield/trunk/archetypes/markerfield/utils.py (contents, props changed) archetypes.markerfield/trunk/docs/ archetypes.markerfield/trunk/docs/HISTORY.txt (contents, props changed) archetypes.markerfield/trunk/setup.cfg archetypes.markerfield/trunk/setup.py (contents, props changed) Log: New package Added: archetypes.markerfield/trunk/README.txt ============================================================================== --- (empty file) +++ archetypes.markerfield/trunk/README.txt Sat Jul 26 11:15:00 2008 @@ -0,0 +1,45 @@ +Introduction +============ + +This packages contains a single Archetypes field that can manage one or +more marker interface on an object. + +It is most often used with `archetypes.schemaextender`_ to add a field to +a type which controls new optional behaviour. + +Example +======= + +This example adds a new item to the settings fieldset for an object +which controls an ICategory marker interface:: + + + class FolderExtender(object): + """Add a new 'category' field to all Archetypes based folder types. + """ + adapts(IBaseFolder) + implements(ISchemaExtender) + + fields = [ + InterfaceMarkerField("category", + schemata = "settings", + interfaces = (ICategory,), + widget = BooleanWidget( + title = _(u"label_category", + default=u"Is this folder a category."), + description = _(u"help_category", + default=u"This should briefly explain what " + u"categories are used for."), + ), + ), + ] + + + def __init__(self, context): + self.context = context + + + def getFields(self): + return self.fields + +.. _archetypes.schemaextender: http://pypi.python.org/pypi/archetypes.schemaextender Added: archetypes.markerfield/trunk/archetypes/__init__.py ============================================================================== --- (empty file) +++ archetypes.markerfield/trunk/archetypes/__init__.py Sat Jul 26 11:15:00 2008 @@ -0,0 +1,6 @@ +# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages +try: + __import__('pkg_resources').declare_namespace(__name__) +except ImportError: + from pkgutil import extend_path + __path__ = extend_path(__path__, __name__) Added: archetypes.markerfield/trunk/archetypes/markerfield/__init__.py ============================================================================== --- (empty file) +++ archetypes.markerfield/trunk/archetypes/markerfield/__init__.py Sat Jul 26 11:15:00 2008 @@ -0,0 +1 @@ +# Added: archetypes.markerfield/trunk/archetypes/markerfield/field.py ============================================================================== --- (empty file) +++ archetypes.markerfield/trunk/archetypes/markerfield/field.py Sat Jul 26 11:15:00 2008 @@ -0,0 +1,34 @@ +from archetypes.schemaextender.field import ExtensionField +from archetypes.markerfield.utils import addMarkerInterface +from archetypes.markerfield.utils import removeMarkerInterface +from Products.Archetypes.atapi import BooleanField + + +class InterfaceMarkerField(ExtensionField, BooleanField): + """Archetypes field to manage marker interface. + + This is a boolean field which will set or unset one or more marker + interfaces on an object. + + This field can be used with archetypes.schemaextender. It is commonly used + to manage optional behaviour for existing content types. + """ + + def get(self, instance, **kwargs): + for iface in self.interfaces: + if not iface.providedBy(instance): + return False + else: + return True + + + def getRaw(self, instance, **kwargs): + return self.get(instance) + + + def set(self, instance, value, **kwargs): + if value: + addMarkerInterface(instance, *self.interfaces) + else: + removeMarkerInterface(instance, *self.interfaces) + Added: archetypes.markerfield/trunk/archetypes/markerfield/tests/__init__.py ============================================================================== --- (empty file) +++ archetypes.markerfield/trunk/archetypes/markerfield/tests/__init__.py Sat Jul 26 11:15:00 2008 @@ -0,0 +1,2 @@ + + Added: archetypes.markerfield/trunk/archetypes/markerfield/tests/testUtils.py ============================================================================== --- (empty file) +++ archetypes.markerfield/trunk/archetypes/markerfield/tests/testUtils.py Sat Jul 26 11:15:00 2008 @@ -0,0 +1,81 @@ +from zope.interface import Interface +from zope.interface import implements +from zope.interface import providedBy +from unittest import TestCase +from unittest import makeSuite +from unittest import TestSuite +from archetypes.markerfield.utils import addMarkerInterface +from archetypes.markerfield.utils import removeMarkerInterface + +class MarkerInterface(Interface): + pass + +class SecondMarkerInterface(Interface): + pass + +class BaseInterface(Interface): + pass + +class Mock(object): + pass + +class MockWithInterface(object): + implements(BaseInterface) + + +class InterfaceTests(TestCase): + def ifaces(self, obj): + return [i.getName() for i in providedBy(obj)] + + + def testAddNothing(self): + obj=Mock() + addMarkerInterface(obj) + self.assertEqual(self.ifaces(obj), []) + + + def testAddSingleInterface(self): + obj=Mock() + addMarkerInterface(obj, MarkerInterface) + self.assertEqual(self.ifaces(obj), ["MarkerInterface"]) + + + def testAddMultipleInterfaces(self): + obj=Mock() + addMarkerInterface(obj, MarkerInterface, SecondMarkerInterface) + self.assertEqual(self.ifaces(obj), + ["MarkerInterface", "SecondMarkerInterface"]) + + + def testAddAdditionalInterface(self): + obj=MockWithInterface() + addMarkerInterface(obj, MarkerInterface) + self.assertEqual(self.ifaces(obj), ["MarkerInterface", "BaseInterface"]) + + + def testRemoveNonPresentInterface(self): + obj=Mock() + removeMarkerInterface(obj, MarkerInterface) + self.assertEqual(self.ifaces(obj), []) + + + def testAddAndRemoveSingleInterface(self): + obj=Mock() + addMarkerInterface(obj, MarkerInterface) + removeMarkerInterface(obj, MarkerInterface) + self.assertEqual(self.ifaces(obj), []) + + + def testAddTwoInterfacesAndRemoveOne(self): + obj=Mock() + addMarkerInterface(obj, MarkerInterface, SecondMarkerInterface) + removeMarkerInterface(obj, MarkerInterface) + self.assertEqual(self.ifaces(obj), ["SecondMarkerInterface"]) + + + + +def test_suite(): + suite=TestSuite() + suite.addTest(makeSuite(InterfaceTests)) + return suite Added: archetypes.markerfield/trunk/archetypes/markerfield/utils.py ============================================================================== --- (empty file) +++ archetypes.markerfield/trunk/archetypes/markerfield/utils.py Sat Jul 26 11:15:00 2008 @@ -0,0 +1,36 @@ +from Acquisition import aq_chain +from Acquisition import aq_inner +from zope.interface import alsoProvides +from zope.interface import noLongerProvides +from Products.CMFPlone.interfaces import IPloneSiteRoot +from plone.app.search.interfaces import ICategory + + +def addMarkerInterface(obj, *ifaces): + for iface in ifaces: + if not iface.providedBy(obj): + alsoProvides(obj, iface) + + +def removeMarkerInterface(obj, *ifaces): + for iface in ifaces: + if iface.providedBy(obj): + noLongerProvides(obj, iface) + + +def currentCategory(context): + for entry in aq_chain(aq_inner(context)): + if ICategory.providedBy(entry): + return entry + elif IPloneSiteRoot.providedBy(entry): + return None + else: + return None + + +def quoteSearchString(s): + bad_chars = ["(", ")"] + for char in bad_chars: + s = s.replace(char, '"%s"' % char) + return s + Added: archetypes.markerfield/trunk/docs/HISTORY.txt ============================================================================== --- (empty file) +++ archetypes.markerfield/trunk/docs/HISTORY.txt Sat Jul 26 11:15:00 2008 @@ -0,0 +1,8 @@ +Changelog +========= + +1.0 - Unreleased +---------------- + +* Initial release + Added: archetypes.markerfield/trunk/setup.cfg ============================================================================== --- (empty file) +++ archetypes.markerfield/trunk/setup.cfg Sat Jul 26 11:15:00 2008 @@ -0,0 +1,3 @@ +[egg_info] +tag_build = dev +tag_svn_revision = true Added: archetypes.markerfield/trunk/setup.py ============================================================================== --- (empty file) +++ archetypes.markerfield/trunk/setup.py Sat Jul 26 11:15:00 2008 @@ -0,0 +1,38 @@ +from setuptools import setup, find_packages +import os + +version = '1.0' + +setup(name='archetypes.markerfield', + version=version, + description="Interface marker field for Archetypes", + long_description=open("README.txt").read() + "\n" + + open(os.path.join("docs", "HISTORY.txt")).read(), + classifiers=[ + "Framework :: Zope2", + "Framework :: Plone", + "Intended Audience :: Developers", + "License :: OSI Approved :: Zope Public License", + "Programming Language :: Python", + "Topic :: Software Development :: Libraries :: Python Modules", + ], + keywords='', + author='Wichert Akkertman', + author_email='wi...@wi...', + url='', + license='ZPL', + packages=find_packages(exclude=['ez_setup']), + namespace_packages=['archetypes'], + include_package_data=True, + zip_safe=False, + install_requires=[ + 'setuptools', + 'archetypes.schemaextender', +# 'zope.component', +# 'zope.interface', +# 'Products.Archetypes', + ], + entry_points=""" + # -*- Entry points: -*- + """, + ) |