[Checkins] SVN: zc.sourcefactory/trunk/s initial import of zc.sourcefactory

Benji York benji at zope.com
Mon Mar 19 15:04:12 EDT 2007


Log message for revision 73349:
  initial import of zc.sourcefactory
  

Changed:
  A   zc.sourcefactory/trunk/setup.py
  A   zc.sourcefactory/trunk/src/
  A   zc.sourcefactory/trunk/src/zc/
  A   zc.sourcefactory/trunk/src/zc/__init__.py
  A   zc.sourcefactory/trunk/src/zc/sourcefactory/
  A   zc.sourcefactory/trunk/src/zc/sourcefactory/README.txt
  A   zc.sourcefactory/trunk/src/zc/sourcefactory/__init__.py
  A   zc.sourcefactory/trunk/src/zc/sourcefactory/adapters.py
  A   zc.sourcefactory/trunk/src/zc/sourcefactory/adapters.txt
  A   zc.sourcefactory/trunk/src/zc/sourcefactory/basic.py
  A   zc.sourcefactory/trunk/src/zc/sourcefactory/browser/
  A   zc.sourcefactory/trunk/src/zc/sourcefactory/browser/README.txt
  A   zc.sourcefactory/trunk/src/zc/sourcefactory/browser/__init__.py
  A   zc.sourcefactory/trunk/src/zc/sourcefactory/browser/configure.zcml
  A   zc.sourcefactory/trunk/src/zc/sourcefactory/browser/mapping.py
  A   zc.sourcefactory/trunk/src/zc/sourcefactory/browser/source.py
  A   zc.sourcefactory/trunk/src/zc/sourcefactory/browser/tests.py
  A   zc.sourcefactory/trunk/src/zc/sourcefactory/browser/token.py
  A   zc.sourcefactory/trunk/src/zc/sourcefactory/browser/token.txt
  A   zc.sourcefactory/trunk/src/zc/sourcefactory/configure.zcml
  A   zc.sourcefactory/trunk/src/zc/sourcefactory/contextual.py
  A   zc.sourcefactory/trunk/src/zc/sourcefactory/factories.py
  A   zc.sourcefactory/trunk/src/zc/sourcefactory/ftesting.zcml
  A   zc.sourcefactory/trunk/src/zc/sourcefactory/interfaces.py
  A   zc.sourcefactory/trunk/src/zc/sourcefactory/mapping.py
  A   zc.sourcefactory/trunk/src/zc/sourcefactory/mapping.txt
  A   zc.sourcefactory/trunk/src/zc/sourcefactory/named.py
  A   zc.sourcefactory/trunk/src/zc/sourcefactory/policies.py
  A   zc.sourcefactory/trunk/src/zc/sourcefactory/source.py
  A   zc.sourcefactory/trunk/src/zc/sourcefactory/tests.py

-=-
Added: zc.sourcefactory/trunk/setup.py
===================================================================
--- zc.sourcefactory/trunk/setup.py	2007-03-19 19:00:55 UTC (rev 73348)
+++ zc.sourcefactory/trunk/setup.py	2007-03-19 19:04:09 UTC (rev 73349)
@@ -0,0 +1,12 @@
+from setuptools import setup, find_packages
+
+setup(
+    name="zc.sourcefactory",
+    version="0.1dev",
+    packages=find_packages('src'),
+    package_dir={'':'src'},
+    include_package_data=True,
+    install_requires=["setuptools"],
+    namespace_packages=['zc'],
+    zip_safe=False
+    )


Property changes on: zc.sourcefactory/trunk/setup.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: zc.sourcefactory/trunk/src/zc/__init__.py
===================================================================
--- zc.sourcefactory/trunk/src/zc/__init__.py	2007-03-19 19:00:55 UTC (rev 73348)
+++ zc.sourcefactory/trunk/src/zc/__init__.py	2007-03-19 19:04:09 UTC (rev 73349)
@@ -0,0 +1,7 @@
+# This directory is a Python namespace package.
+try:
+    import pkg_resources
+    pkg_resources.declare_namespace(__name__)
+except ImportError:
+    import pkgutil
+    __path__ = pkgutil.extend_path(__path__, __name__)


Property changes on: zc.sourcefactory/trunk/src/zc/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: zc.sourcefactory/trunk/src/zc/sourcefactory/README.txt
===================================================================
--- zc.sourcefactory/trunk/src/zc/sourcefactory/README.txt	2007-03-19 19:00:55 UTC (rev 73348)
+++ zc.sourcefactory/trunk/src/zc/sourcefactory/README.txt	2007-03-19 19:04:09 UTC (rev 73349)
@@ -0,0 +1,135 @@
+================
+Source Factories
+================
+
+Source factories are used to simplify the creation of sources for certain
+standard cases.
+
+Sources split up the process of providing input fields with choices for users
+into several components: a context binder, a source class, a terms class, and a
+term class.
+
+This is the correct abstraction and will fit many complex cases very well. To
+reduce the amount of work to do for some standard cases, the source factories
+allow users to define only the business relevant code for getting a list of
+values, getting a token and a title to display.
+
+Simple case
+-----------
+
+In the most simple case, you only have to provide a method that returns a list
+of values and derive from 'BasicSourceFactory':
+
+  >>> import zc.sourcefactory.basic
+  >>> class MyStaticSource(zc.sourcefactory.basic.BasicSourceFactory):
+  ...     def getValues(self):
+  ...         return ['a', 'b', 'c']
+
+When calling the source factory, we get a source:
+
+  >>> source = MyStaticSource()
+  >>> import zope.schema.interfaces
+  >>> zope.schema.interfaces.ISource.providedBy(source)
+  True
+
+The values match our `getValues`-method of the factory:
+
+  >>> list(source)
+  ['a', 'b', 'c']
+  >>> 'a' in source
+  True
+  >>> len(source)
+  3
+
+Contextual sources
+------------------
+
+Sometimes we need context to determine the values. In this case, the
+`getValues`-method gets a parameter `context`.
+
+Let's assume we have a small object containing data to be used by the source:
+
+  >>> class Context(object):
+  ...      values = []
+
+  >>> import zc.sourcefactory.contextual
+  >>> class MyDynamicSource(
+  ...     zc.sourcefactory.contextual.BasicContextualSourceFactory):
+  ...     def getValues(self, context):
+  ...         return context.values
+
+When instanciating, we get a ContextSourceBinder:
+
+  >>> binder = MyDynamicSource()
+  >>> zope.schema.interfaces.IContextSourceBinder.providedBy(binder)
+  True
+
+Binding it to a context, we get a source:
+
+  >>> context = Context()
+  >>> source = binder(context)
+  >>> zope.schema.interfaces.ISource.providedBy(source)
+  True
+
+  >>> list(source)
+  []
+
+Modifying the context also modifies the data in the source:
+
+  >>> context.values = [1,2,3,4]
+  >>> list(source)
+  [1, 2, 3, 4]
+  >>> 1 in source
+  True
+  >>> len(source)
+  4
+
+Filtering
+---------
+
+Additional to providing the `getValues`-method you can also provide a
+`filterValue`-method that will allow you to reduce the items from the list,
+piece by piece.
+
+This is useful if you want to have more specific sources (by subclassing) that
+share the same basic origin of the data but have different filters applied to
+it.
+
+  >>> class FilteringSource(zc.sourcefactory.basic.BasicSourceFactory):
+  ...     def getValues(self):
+  ...         return xrange(1,20)
+  ...     def filterValue(self, value):
+  ...         return value % 2
+  >>> source = FilteringSource()
+  >>> list(source)
+  [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
+
+Subclassing modifies the filter, not the original data:
+
+  >>> class OtherFilteringSource(FilteringSource):
+  ...     def filterValue(self, value):
+  ...         return not value % 2
+  >>> source = OtherFilteringSource()
+  >>> list(source)
+  [2, 4, 6, 8, 10, 12, 14, 16, 18]
+
+The "in" operator get's applied also to filtered values
+
+  >>> 2 in source
+  True
+  >>> 3 in source
+  False
+
+The "len" also get's applied to filtered values:
+
+  >>> len(source)
+  9
+
+WARNING about the standard adapters for ITerms
+----------------------------------------------
+
+The standard adapters for ITerms are only suitable if the value types returned
+by your `getValues` function are homogenous. Mixing integers, persistent
+objects, strings, and unicode within one source may create non-unique tokens.
+In this case, you have to provide a custom `getToken`-method to provide unique
+and unambigous tokens.


Property changes on: zc.sourcefactory/trunk/src/zc/sourcefactory/README.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: zc.sourcefactory/trunk/src/zc/sourcefactory/__init__.py
===================================================================
--- zc.sourcefactory/trunk/src/zc/sourcefactory/__init__.py	2007-03-19 19:00:55 UTC (rev 73348)
+++ zc.sourcefactory/trunk/src/zc/sourcefactory/__init__.py	2007-03-19 19:04:09 UTC (rev 73349)
@@ -0,0 +1 @@
+# This directory is a Python package.


Property changes on: zc.sourcefactory/trunk/src/zc/sourcefactory/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: zc.sourcefactory/trunk/src/zc/sourcefactory/adapters.py
===================================================================
--- zc.sourcefactory/trunk/src/zc/sourcefactory/adapters.py	2007-03-19 19:00:55 UTC (rev 73348)
+++ zc.sourcefactory/trunk/src/zc/sourcefactory/adapters.py	2007-03-19 19:04:09 UTC (rev 73349)
@@ -0,0 +1,29 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Visible Source
+# License, Version 1.0 (ZVSL).  A copy of the ZVSL should accompany this
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Support to adapt factored sources to some common interfaces.
+
+"""
+__docformat__ = "reStructuredText"
+
+import zope.schema.interfaces
+import zope.component
+import zc.sourcefactory.source
+
+ at zope.interface.implementer(zope.schema.interfaces.ISourceQueriables)
+ at zope.component.adapter(zc.sourcefactory.source.FactoredSource)
+def getSourceQueriables(factored_source):
+    return zope.component.queryMultiAdapter(
+        (factored_source, factored_source.factory),
+        zope.schema.interfaces.ISourceQueriables)


Property changes on: zc.sourcefactory/trunk/src/zc/sourcefactory/adapters.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: zc.sourcefactory/trunk/src/zc/sourcefactory/adapters.txt
===================================================================
--- zc.sourcefactory/trunk/src/zc/sourcefactory/adapters.txt	2007-03-19 19:00:55 UTC (rev 73348)
+++ zc.sourcefactory/trunk/src/zc/sourcefactory/adapters.txt	2007-03-19 19:04:09 UTC (rev 73349)
@@ -0,0 +1,46 @@
+===========================
+Common adapters for sources
+===========================
+
+To allow adapting factored sources specific to the factory, a couple of
+standard interfaces that can be adapters are re-adapted as using a
+multi-adapter for (FactoredSource, SourceFactory).
+
+ISourceQueriables
+-----------------
+
+  >>> from zc.sourcefactory.basic import BasicSourceFactory
+  >>> class Factory(BasicSourceFactory):
+  ...     def getValues(self):
+  ...         return [1,2,3]
+  >>> source = Factory()
+
+  >>> from zope.schema.interfaces import ISourceQueriables
+  >>> import zope.interface
+  >>> class SourceQueriables(object):
+  ...     zope.interface.implements(ISourceQueriables)
+  ...     def __init__(self, source, factory):
+  ...         self.source = source
+  ...         self.factory = factory
+  ...     def getQueriables(self):
+  ...         return [('test', None)]
+
+  >>> from zc.sourcefactory.source import FactoredSource
+  >>> zope.component.provideAdapter(factory=SourceQueriables,
+  ...                               provides=ISourceQueriables,
+  ...                               adapts=(FactoredSource, Factory))
+
+  >>> queriables = ISourceQueriables(source)
+  >>> queriables.factory
+  <Factory object at 0x...>
+  >>> queriables.source
+  <zc.sourcefactory.source.FactoredSource object at 0x...>
+  >>> queriables.getQueriables()
+  [('test', None)]
+
+Cleanup
+-------
+
+  >>> zope.component.getSiteManager().unregisterAdapter(factory=SourceQueriables,
+  ...     provided=ISourceQueriables, required=(FactoredSource, Factory))
+  True


Property changes on: zc.sourcefactory/trunk/src/zc/sourcefactory/adapters.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: zc.sourcefactory/trunk/src/zc/sourcefactory/basic.py
===================================================================
--- zc.sourcefactory/trunk/src/zc/sourcefactory/basic.py	2007-03-19 19:00:55 UTC (rev 73348)
+++ zc.sourcefactory/trunk/src/zc/sourcefactory/basic.py	2007-03-19 19:04:09 UTC (rev 73349)
@@ -0,0 +1,31 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Visible Source
+# License, Version 1.0 (ZVSL).  A copy of the ZVSL should accompany this
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""The most basic source factory that supports all the required interfaces.
+
+This is used for sources that do not require the context.
+
+"""
+__docformat__ = "reStructuredText"
+
+
+import zc.sourcefactory.factories
+import zc.sourcefactory.policies
+
+class BasicSourceFactory(zc.sourcefactory.factories.BasicSourceFactory,
+                         zc.sourcefactory.policies.BasicSourcePolicy):
+    """Basic source factory implementation including a factory and the
+    basic policies.
+
+    """


Property changes on: zc.sourcefactory/trunk/src/zc/sourcefactory/basic.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: zc.sourcefactory/trunk/src/zc/sourcefactory/browser/README.txt
===================================================================
--- zc.sourcefactory/trunk/src/zc/sourcefactory/browser/README.txt	2007-03-19 19:00:55 UTC (rev 73348)
+++ zc.sourcefactory/trunk/src/zc/sourcefactory/browser/README.txt	2007-03-19 19:04:09 UTC (rev 73349)
@@ -0,0 +1,158 @@
+=====================================================
+Browser views for sources created by source factories
+=====================================================
+
+Sources that were created using source factories already come with ready-made
+terms and term objects.
+
+
+Simple use
+==========
+
+Let's start with a simple source factory:
+
+  >>> import zc.sourcefactory.basic
+  >>> class DemoSource(zc.sourcefactory.basic.BasicSourceFactory):
+  ...     def getValues(self):
+  ...         return ['a', 'b', 'c', 'd']
+  >>> source = DemoSource()
+  >>> list(source)
+  ['a', 'b', 'c', 'd']
+
+We need a request first, then we can adapt the source to ITerms:
+
+  >>> from zope.publisher.browser import TestRequest
+  >>> import zope.app.form.browser.interfaces
+  >>> import zope.component
+  >>> request = TestRequest()
+  >>> terms = zope.component.getMultiAdapter(
+  ...     (source, request), zope.app.form.browser.interfaces.ITerms)
+  >>> terms
+  <zc.sourcefactory.browser.source.FactoredTerms object at 0x...>
+
+For each value we get a factored term:
+
+  >>> terms.getTerm('a')
+  <zc.sourcefactory.browser.source.FactoredTerm object at 0x...>
+  >>> terms.getTerm('b')
+  <zc.sourcefactory.browser.source.FactoredTerm object at 0x...>
+  >>> terms.getTerm('c')
+  <zc.sourcefactory.browser.source.FactoredTerm object at 0x...>
+  >>> terms.getTerm('d')
+  <zc.sourcefactory.browser.source.FactoredTerm object at 0x...>
+
+Our terms are ITitledTokenizedTerm-compatible:
+
+  >>> import zope.schema.interfaces
+  >>> zope.schema.interfaces.ITitledTokenizedTerm.providedBy(
+  ...     terms.getTerm('a'))
+  True
+
+In the most simple case, the title of a term is the string representation of
+the object:
+
+XXX this should be unicode!
+
+  >>> terms.getTerm('a').title
+  'a'
+
+If an adapter from the value to IDCDescriptiveProperties exists, the title
+will be retrieved from this adapter:
+
+  >>> import persistent
+  >>> class MyObject(persistent.Persistent):
+  ...    custom_title = u'My custom title'
+  ...    _p_oid = 12
+  >>> class DCDescriptivePropertiesAdapter(object):
+  ...    def __init__(self, context):
+  ...        self.title = context.custom_title
+  ...        self.description = u""
+  >>> from zope.component import provideAdapter
+  >>> from zope.dublincore.interfaces import IDCDescriptiveProperties
+  >>> provideAdapter(DCDescriptivePropertiesAdapter, [MyObject],
+  ...     IDCDescriptiveProperties)
+  >>> terms.getTerm(MyObject()).title
+  u'My custom title'
+
+Extended use: provide your own titles
+=====================================
+
+Instead of relying on string representation or IDCDescriptiveProperties
+adapters you can specify the `getTitle` method on the source factory to
+determine the title for a value:
+
+  >>> class DemoSourceWithTitles(DemoSource):
+  ...     def getTitle(self, value):
+  ...         return value.custom_title
+  >>> source2 = DemoSourceWithTitles()
+  >>> terms2 = zope.component.getMultiAdapter(
+  ...     (source2, request), zope.app.form.browser.interfaces.ITerms)
+  >>> o1 = MyObject()
+  >>> o1.custom_title = u"Object one"
+  >>> o2 = MyObject()
+  >>> o2.custom_title = u"Object two"
+  >>> terms2.getTerm(o1).title
+  u'Object one'
+  >>> terms2.getTerm(o2).title
+  u'Object two'
+
+Extended use: provide your own tokens
+=====================================
+
+Instead of relying on default adapters to generate tokens for your values, you
+can override the `getToken` method on the source factory to determine the
+token for a value:
+
+  >>> class DemoObjectWithToken(object):
+  ...     token = None
+  >>> o1 = DemoObjectWithToken()
+  >>> o1.token = "one"
+  >>> o2 = DemoObjectWithToken()
+  >>> o2.token = "two"
+
+  >>> class DemoSourceWithTokens(DemoSource):
+  ...     values = [o1, o2]
+  ...     def getValues(self):
+  ...         return self.values
+  ...     def getToken(self, value):
+  ...         return value.token
+
+  >>> source3 = DemoSourceWithTokens()
+  >>> terms3 = zope.component.getMultiAdapter(
+  ...     (source3, request), zope.app.form.browser.interfaces.ITerms)
+
+  >>> terms3.getTerm(o1).token
+  'one'
+  >>> terms3.getTerm(o2).token
+  'two'
+
+Looking up by the custom tokens works as well:
+
+  >>> terms3.getValue("one") is o1
+  True
+  >>> terms3.getValue("two") is o2
+  True
+  >>> terms3.getValue("three")
+  Traceback (most recent call last):
+  KeyError: "No value with token 'three'"
+
+
+Value mapping sources
+=====================
+
+  XXX to come
+
+
+Iterfaces
+=========
+
+Both the FactoredSource and FactoredContextualSource have associated
+interfaces.
+
+  >>> from zc.sourcefactory import interfaces
+  >>> from zc.sourcefactory import source
+  >>> from zope import interface
+  >>> interface.classImplements(
+  ...     source.FactoredSource, interfaces.IFactoredSource)
+  >>> interface.classImplements(
+  ...     source.FactoredContextualSource, interfaces.IContextualSource)


Property changes on: zc.sourcefactory/trunk/src/zc/sourcefactory/browser/README.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: zc.sourcefactory/trunk/src/zc/sourcefactory/browser/__init__.py
===================================================================
--- zc.sourcefactory/trunk/src/zc/sourcefactory/browser/__init__.py	2007-03-19 19:00:55 UTC (rev 73348)
+++ zc.sourcefactory/trunk/src/zc/sourcefactory/browser/__init__.py	2007-03-19 19:04:09 UTC (rev 73349)
@@ -0,0 +1 @@
+# This directory is a Python package.


Property changes on: zc.sourcefactory/trunk/src/zc/sourcefactory/browser/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: zc.sourcefactory/trunk/src/zc/sourcefactory/browser/configure.zcml
===================================================================
--- zc.sourcefactory/trunk/src/zc/sourcefactory/browser/configure.zcml	2007-03-19 19:00:55 UTC (rev 73348)
+++ zc.sourcefactory/trunk/src/zc/sourcefactory/browser/configure.zcml	2007-03-19 19:04:09 UTC (rev 73349)
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:browser="http://namespaces.zope.org/browser"
+    i18n_domain="zc.sourcefactory">
+
+  <adapter factory=".source.FactoredTerms"/>
+  <adapter factory=".mapping.MappedTerms"/>
+
+  <adapter factory=".token.fromString"/>
+  <adapter factory=".token.fromUnicode"/>
+  <adapter factory=".token.fromInteger"/>
+  <adapter factory=".token.fromPersistent"/>
+  <adapter factory=".token.fromInterface"/>
+
+</configure>
+


Property changes on: zc.sourcefactory/trunk/src/zc/sourcefactory/browser/configure.zcml
___________________________________________________________________
Name: svn:eol-style
   + native

Added: zc.sourcefactory/trunk/src/zc/sourcefactory/browser/mapping.py
===================================================================
--- zc.sourcefactory/trunk/src/zc/sourcefactory/browser/mapping.py	2007-03-19 19:00:55 UTC (rev 73348)
+++ zc.sourcefactory/trunk/src/zc/sourcefactory/browser/mapping.py	2007-03-19 19:04:09 UTC (rev 73349)
@@ -0,0 +1,69 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Visible Source
+# License, Version 1.0 (ZVSL).  A copy of the ZVSL should accompany this
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Mapping-source related terms stuff
+
+"""
+__docformat__ = "reStructuredText"
+
+
+import zope.proxy
+import zope.interface
+import zope.component
+import zope.publisher.interfaces.browser
+
+import zope.app.form.browser.interfaces
+
+import zc.sourcefactory.mapping
+
+
+class MappedTerms(object):
+    """A terms implementation that knows how to handle a source that was 
+    created through a source factory.
+    """
+
+    zope.interface.implements(zope.app.form.browser.interfaces.ITerms)
+
+    zope.component.adapts(zc.sourcefactory.mapping.ValueMappingSource,
+        zope.publisher.interfaces.browser.IBrowserRequest)
+
+    def __init__(self, source, request):
+        self.base = zope.component.getMultiAdapter(
+            [source.base, request], zope.app.form.browser.interfaces.ITerms)
+        self.source = source
+        self.request = request
+
+    def getTerm(self, value):
+        real_value = self.source.mapReverse(value)
+        term = self.base.getTerm(real_value)
+        return MappedTermProxy(value, term)
+
+    def getValue(self, token):
+        return self.source.map(self.base.getValue(token))
+
+
+class MappedTermProxy(zope.proxy.ProxyBase):
+    """A mapped term that provides access to the mapped value
+    without destroying the real term.
+
+    """
+
+    __slots__ = ('value',)
+
+    def __new__(self, value, baseterm):
+        return zope.proxy.ProxyBase.__new__(self, baseterm)
+
+    def __init__(self, value, baseterm):
+        zope.proxy.ProxyBase.__init__(self, baseterm)
+        self.value = value


Property changes on: zc.sourcefactory/trunk/src/zc/sourcefactory/browser/mapping.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: zc.sourcefactory/trunk/src/zc/sourcefactory/browser/source.py
===================================================================
--- zc.sourcefactory/trunk/src/zc/sourcefactory/browser/source.py	2007-03-19 19:00:55 UTC (rev 73348)
+++ zc.sourcefactory/trunk/src/zc/sourcefactory/browser/source.py	2007-03-19 19:04:09 UTC (rev 73349)
@@ -0,0 +1,64 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Visible Source
+# License, Version 1.0 (ZVSL).  A copy of the ZVSL should accompany this
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Interfaces for zc.z4m.
+
+"""
+__docformat__ = "reStructuredText"
+
+
+import zope.interface
+import zope.component
+import zope.publisher.interfaces.browser
+import zope.schema.interfaces
+
+import zope.app.form.browser.interfaces
+
+import zc.sourcefactory.source
+
+
+class FactoredTerms(object):
+    """A terms implementation that knows how to handle a source that was
+    created through a source factory.
+    """
+
+    zope.interface.implements(zope.app.form.browser.interfaces.ITerms)
+
+    zope.component.adapts(
+        zc.sourcefactory.source.FactoredSource,
+        zope.publisher.interfaces.browser.IBrowserRequest)
+
+    def __init__(self, source, request):
+        self.source = source
+        self.request = request
+
+    def getTerm(self, value):
+        title = self.source.factory.getTitle(value)
+        token = self.source.factory.getToken(value)
+        return self.source.factory.createTerm(
+            self.source, value, title, token, self.request)
+
+    def getValue(self, token):
+        return self.source.factory.getValue(self.source, token)
+
+
+class FactoredTerm(object):
+    """A title tokenized term."""
+
+    zope.interface.implements(zope.schema.interfaces.ITitledTokenizedTerm)
+
+    def __init__(self, value, title, token):
+        self.value = value
+        self.title = title
+        self.token = token


Property changes on: zc.sourcefactory/trunk/src/zc/sourcefactory/browser/source.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: zc.sourcefactory/trunk/src/zc/sourcefactory/browser/tests.py
===================================================================
--- zc.sourcefactory/trunk/src/zc/sourcefactory/browser/tests.py	2007-03-19 19:00:55 UTC (rev 73348)
+++ zc.sourcefactory/trunk/src/zc/sourcefactory/browser/tests.py	2007-03-19 19:04:09 UTC (rev 73349)
@@ -0,0 +1,36 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Visible Source
+# License, Version 1.0 (ZVSL).  A copy of the ZVSL should accompany this
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Unit tests
+
+"""
+__docformat__ = "reStructuredText"
+
+import unittest
+
+from zope.testing import doctest
+import zope.app.testing.functional
+
+from zc.sourcefactory.tests import SourceFactoryLayer
+
+def test_suite():
+    suite = unittest.TestSuite()
+    token = zope.app.testing.functional.FunctionalDocFileSuite('token.txt')
+    token.layer = SourceFactoryLayer
+    readme =  zope.app.testing.functional.FunctionalDocFileSuite(
+            'README.txt', optionflags=doctest.ELLIPSIS)
+    readme.layer = SourceFactoryLayer
+    suite.addTest(token)
+    suite.addTest(readme)
+    return suite


Property changes on: zc.sourcefactory/trunk/src/zc/sourcefactory/browser/tests.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: zc.sourcefactory/trunk/src/zc/sourcefactory/browser/token.py
===================================================================
--- zc.sourcefactory/trunk/src/zc/sourcefactory/browser/token.py	2007-03-19 19:00:55 UTC (rev 73348)
+++ zc.sourcefactory/trunk/src/zc/sourcefactory/browser/token.py	2007-03-19 19:04:09 UTC (rev 73349)
@@ -0,0 +1,82 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Visible Source
+# License, Version 1.0 (ZVSL).  A copy of the ZVSL should accompany this
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Various token adapters.
+
+"""
+__docformat__ = "reStructuredText"
+
+
+import md5
+
+import ZODB.utils
+import ZODB.interfaces
+import persistent.interfaces
+
+import zope.proxy
+import zope.component
+import zope.interface
+
+import zc.sourcefactory.interfaces
+
+
+ at zope.component.adapter(str)
+ at zope.interface.implementer(zc.sourcefactory.interfaces.IToken)
+def fromString(value):
+    # We hash generic strings to be sure they are suitable
+    # for URL encoding.
+    return md5.md5(value).hexdigest()
+
+
+ at zope.component.adapter(unicode)
+ at zope.interface.implementer(zc.sourcefactory.interfaces.IToken)
+def fromUnicode(value):
+    value = value.encode("utf-8")
+    return fromString(value)
+
+
+ at zope.component.adapter(int)
+ at zope.interface.implementer(zc.sourcefactory.interfaces.IToken)
+def fromInteger(value):
+    # We do not have to hash integers as their string representations
+    # are definitely suitable for URL encoding.
+    return str(value)
+
+
+ at zope.component.adapter(persistent.interfaces.IPersistent)
+ at zope.interface.implementer(zc.sourcefactory.interfaces.IToken)
+def fromPersistent(value):
+    # Persistent objects are identified by their oid. If it is persistent but
+    # not added to the database, we try to get to the parent, add the value to
+    # the database and get the oid then.
+    try:
+        oid = value._p_oid
+    except AttributeError:
+        oid = None
+
+    if oid is None:
+        if not hasattr(value, '__parent__'):
+            raise ValueError('Can not determine OID for %r' % value)
+        # We have to remove proxies to avoid security here.
+        value_unproxied = zope.proxy.removeAllProxies(value)
+        connection = ZODB.interfaces.IConnection(value_unproxied.__parent__)
+        connection.add(value_unproxied)
+        oid = value_unproxied._p_oid
+    return ZODB.utils.oid_repr(oid)
+
+ at zope.component.adapter(zope.interface.interfaces.IInterface)
+ at zope.interface.implementer(zc.sourcefactory.interfaces.IToken)
+def fromInterface(value):
+    # Interface are identified by their module path and name
+    return "%s.%s" % (value.__module__, value.__name__)


Property changes on: zc.sourcefactory/trunk/src/zc/sourcefactory/browser/token.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: zc.sourcefactory/trunk/src/zc/sourcefactory/browser/token.txt
===================================================================
--- zc.sourcefactory/trunk/src/zc/sourcefactory/browser/token.txt	2007-03-19 19:00:55 UTC (rev 73348)
+++ zc.sourcefactory/trunk/src/zc/sourcefactory/browser/token.txt	2007-03-19 19:04:09 UTC (rev 73349)
@@ -0,0 +1,79 @@
+======
+Tokens
+======
+
+Tokens are an identifying representation of an object, suitable for
+transmission amongs URL-encoded data.
+
+The sourcefactory package provides a few standard generators for tokens:
+
+  >>> import zc.sourcefactory.browser.token
+
+Strings
+=======
+
+  >>> zc.sourcefactory.browser.token.fromString('somestring')
+  '1f129c42de5e4f043cbd88ff6360486f'
+
+Unicode
+=======
+
+  >>> zc.sourcefactory.browser.token.fromUnicode(
+  ...     u'somestring with umlauts öäü')
+  '45dadc304e0d6ae7f4864368bad74951'
+
+Integer
+=======
+
+  >>> zc.sourcefactory.browser.token.fromInteger(12)
+  '12'
+
+Persistent
+==========
+
+  >>> import persistent
+  >>> class PersistentDummy(persistent.Persistent):
+  ...     pass
+  >>> p = PersistentDummy()
+  >>> p._p_oid = 1234
+  >>> zc.sourcefactory.browser.token.fromPersistent(p)
+  '1234'
+
+If an object is persistent but has not been added to a database yet, it will
+be added to the database of it's __parent__:
+
+  >>> root = getRootFolder()
+  >>> p1 = PersistentDummy()
+  >>> p1.__parent__ = root
+  >>> zc.sourcefactory.browser.token.fromPersistent(p1)
+  '0x...'
+
+If an object has no parent, we fail:
+
+  >>> p2 = PersistentDummy()
+  >>> zc.sourcefactory.browser.token.fromPersistent(p2)
+  Traceback (most recent call last):
+  ValueError: Can not determine OID for <PersistentDummy object at 0x...>
+
+Security proxied objects are unpacked to get to their connection attributed:
+
+  >>> from zope.security.proxy import ProxyFactory
+  >>> p3 = PersistentDummy()
+  >>> root['p3'] = p3
+  >>> p3.__parent__ = root
+  >>> p3p = ProxyFactory(p3)
+  >>> p3p._p_jar
+  Traceback (most recent call last):
+  ForbiddenAttribute: ('_p_jar', <PersistentDummy object at 0x...>)
+
+  >>> zc.sourcefactory.browser.token.fromPersistent(p3p)
+  '0x...'
+
+Interfaces
+==========
+
+  >>> from zope.interface import Interface
+  >>> class I(Interface):
+  ...     pass
+  >>> zc.sourcefactory.browser.token.fromInterface(I)
+  '__builtin__.I'


Property changes on: zc.sourcefactory/trunk/src/zc/sourcefactory/browser/token.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: zc.sourcefactory/trunk/src/zc/sourcefactory/configure.zcml
===================================================================
--- zc.sourcefactory/trunk/src/zc/sourcefactory/configure.zcml	2007-03-19 19:00:55 UTC (rev 73348)
+++ zc.sourcefactory/trunk/src/zc/sourcefactory/configure.zcml	2007-03-19 19:04:09 UTC (rev 73349)
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    >
+
+  <class class=".source.FactoredSource">
+    <require
+        interface=".interfaces.IFactoredSource"
+        permission="zope.View"
+        />
+  </class>
+
+  <class class=".source.FactoredContextualSource">
+    <require
+        interface=".interfaces.IContextualSource"
+        permission="zope.View"
+        />
+  </class>
+
+  <adapter factory=".adapters.getSourceQueriables"/>
+
+  <include package=".browser"/>
+
+</configure>


Property changes on: zc.sourcefactory/trunk/src/zc/sourcefactory/configure.zcml
___________________________________________________________________
Name: svn:eol-style
   + native

Added: zc.sourcefactory/trunk/src/zc/sourcefactory/contextual.py
===================================================================
--- zc.sourcefactory/trunk/src/zc/sourcefactory/contextual.py	2007-03-19 19:00:55 UTC (rev 73348)
+++ zc.sourcefactory/trunk/src/zc/sourcefactory/contextual.py	2007-03-19 19:04:09 UTC (rev 73349)
@@ -0,0 +1,28 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Visible Source
+# License, Version 1.0 (ZVSL).  A copy of the ZVSL should accompany this
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""The most basic source factory that supports context binding.
+
+"""
+__docformat__ = "reStructuredText"
+
+
+import zc.sourcefactory.factories
+import zc.sourcefactory.policies
+
+
+class BasicContextualSourceFactory(
+    zc.sourcefactory.factories.ContextualSourceFactory,
+    zc.sourcefactory.policies.BasicContextualSourcePolicy):
+    """Abstract base implementation for a basic contextual source factory."""


Property changes on: zc.sourcefactory/trunk/src/zc/sourcefactory/contextual.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: zc.sourcefactory/trunk/src/zc/sourcefactory/factories.py
===================================================================
--- zc.sourcefactory/trunk/src/zc/sourcefactory/factories.py	2007-03-19 19:00:55 UTC (rev 73348)
+++ zc.sourcefactory/trunk/src/zc/sourcefactory/factories.py	2007-03-19 19:04:09 UTC (rev 73349)
@@ -0,0 +1,66 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Visible Source
+# License, Version 1.0 (ZVSL).  A copy of the ZVSL should accompany this
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Basic factories.
+
+"""
+__docformat__ = "reStructuredText"
+
+
+import zope.interface
+import zope.schema.interfaces
+
+import zc.sourcefactory.interfaces
+import zc.sourcefactory.source
+
+
+class BasicSourceFactory(object):
+    """Abstract base class for a source factory.
+
+    Implementors must provide an implementation for `getValues`.
+    """
+
+    zope.interface.implements(zc.sourcefactory.interfaces.ISourceFactory)
+
+    def __new__(cls):
+        """Create the factory object and return source."""
+        factory = object.__new__(cls)
+        factory.__init__()
+        return zc.sourcefactory.source.FactoredSource(factory)
+
+
+class ContextualSourceFactory(BasicSourceFactory):
+    """Abstract base class for a source factory for a context-bound source.
+
+    Implementors must provide an implementation for `getValues`.
+    """
+
+    def __new__(cls):
+        """Create the factory object and return source."""
+        factory = object.__new__(cls)
+        factory.__init__()
+        return FactoredContextualSourceBinder(factory)
+
+
+class FactoredContextualSourceBinder(object):
+    """A context source binder for factored sources."""
+
+    zope.interface.implements(zope.schema.interfaces.IContextSourceBinder)
+
+    def __init__(self, factory):
+        self.factory = factory
+
+    def __call__(self, context):
+        return zc.sourcefactory.source.FactoredContextualSource(
+            self.factory, context)


Property changes on: zc.sourcefactory/trunk/src/zc/sourcefactory/factories.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: zc.sourcefactory/trunk/src/zc/sourcefactory/ftesting.zcml
===================================================================
--- zc.sourcefactory/trunk/src/zc/sourcefactory/ftesting.zcml	2007-03-19 19:00:55 UTC (rev 73348)
+++ zc.sourcefactory/trunk/src/zc/sourcefactory/ftesting.zcml	2007-03-19 19:04:09 UTC (rev 73349)
@@ -0,0 +1,10 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:browser="http://namespaces.zope.org/browser"
+    >
+
+  <include package="zope.app.zcmlfiles" />
+  <include package="zope.app.keyreference" />
+  <include package="zc.sourcefactory" />
+
+</configure>


Property changes on: zc.sourcefactory/trunk/src/zc/sourcefactory/ftesting.zcml
___________________________________________________________________
Name: svn:eol-style
   + native

Added: zc.sourcefactory/trunk/src/zc/sourcefactory/interfaces.py
===================================================================
--- zc.sourcefactory/trunk/src/zc/sourcefactory/interfaces.py	2007-03-19 19:00:55 UTC (rev 73348)
+++ zc.sourcefactory/trunk/src/zc/sourcefactory/interfaces.py	2007-03-19 19:04:09 UTC (rev 73349)
@@ -0,0 +1,109 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Visible Source
+# License, Version 1.0 (ZVSL).  A copy of the ZVSL should accompany this
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Interfaces for zc.sourcefactory.
+
+"""
+__docformat__ = "reStructuredText"
+
+
+import zope.interface
+import zope.schema.interfaces
+
+class ISourceFactory(zope.interface.Interface):
+
+    def __call__():
+        """Create and return the source or source binder."""
+
+
+class IFactoredSource(zope.schema.interfaces.IIterableSource):
+    """An iterable source that was created from a source factory."""
+
+    factory = zope.interface.Attribute("The source factory.")
+
+
+class IContextualSource(IFactoredSource):
+    """A source operating in context."""
+
+    context = zope.interface.Attribute("The context the source is bound to.")
+    factory = zope.interface.Attribute("The source factory.")
+
+
+class INamedSource(zope.interface.Interface):
+    """A marker interface to register named source for."""
+
+
+class IToken(zope.interface.Interface):
+    """A string representing a token that uniquely identifies a value."""
+
+
+# Policies
+
+class ITokenPolicy(zope.interface.Interface):
+    """The token policy maps values and tokens."""
+
+    def getValue(source, token):
+        """Return a token for the value."""
+
+    def getToken(value):
+        """Return a token for the value."""
+
+
+class ITermPolicy(zope.interface.Interface):
+    """The term policy creates terms and provides data for terms."""
+
+    def createTerm(source, value, title, token, request):
+        """Create and return a term object."""
+
+    def getTitle(value):
+        """Return a title for the value.
+
+        The return value should not be localized; that is the
+        responsibility of the user.  The title may be an
+        internationalized message value.
+
+        """
+
+
+class IValuePolicy(zope.interface.Interface):
+    """The value policy retrieves and filters values for a source."""
+
+    def getValues():
+        """Return the values for the source."""
+
+    def filterValue(value):
+        """Determine whether the value should be filtered out or not."""
+
+
+class IContextualValuePolicy(zope.interface.Interface):
+    """The contextual value policy retrieves and filters values for a source
+    within context.
+
+    """
+
+    def getValues(context):
+        """Return the values for the source in the given context."""
+
+    def filterValue(context, value):
+        """Return the values for the source in the given context."""
+
+# Standard combined policies
+
+class ISourcePolicy(ITokenPolicy, ITermPolicy, IValuePolicy):
+    pass
+
+
+class IContextualSourcePolicy(
+    ITokenPolicy, ITermPolicy, IContextualValuePolicy):
+    pass


Property changes on: zc.sourcefactory/trunk/src/zc/sourcefactory/interfaces.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: zc.sourcefactory/trunk/src/zc/sourcefactory/mapping.py
===================================================================
--- zc.sourcefactory/trunk/src/zc/sourcefactory/mapping.py	2007-03-19 19:00:55 UTC (rev 73348)
+++ zc.sourcefactory/trunk/src/zc/sourcefactory/mapping.py	2007-03-19 19:04:09 UTC (rev 73349)
@@ -0,0 +1,74 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Visible Source
+# License, Version 1.0 (ZVSL).  A copy of the ZVSL should accompany this
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""A source proxy providing a mapping between values
+
+"""
+__docformat__ = "reStructuredText"
+
+import zope.interface
+import zope.schema.interfaces
+
+
+class ValueMappingSourceContextBinder(object):
+
+    zope.interface.implements(zope.schema.interfaces.IContextSourceBinder)
+
+    def __init__(self, base, map):
+        self.base = base
+        self.map = map
+
+    def __call__(self, context):
+        source = self.base(context)
+        return ValueMappingSource(source, self.map)
+
+
+class ValueMappingSource(object):
+
+    zope.interface.implements(zope.schema.interfaces.IIterableSource)
+
+    def __init__(self, base, map):
+        self.base = base
+        self._mapping_cache = {}
+        self.map = map
+
+    def mapReverse(self, mapped_value):
+        if mapped_value in self._mapping_cache:
+            return self._mapping_cache[mapped_value]
+
+        # Not found in cache, continue to look for the mapped value in
+        # the rest of the iterator
+        if not hasattr(self, '_cache_iterator'):
+            self._cache_iterator = iter(self.base)
+        for original_value in self._cache_iterator:
+            original_mapped_value = self.map(original_value)
+            self._mapping_cache[original_mapped_value] = original_value
+            if mapped_value == original_mapped_value:
+                return original_value
+        raise KeyError(mapped_value)
+
+    def __contains__(self, value):
+        try:
+            self.mapReverse(value)
+        except KeyError:
+            return False
+        else:
+            return True
+
+    def __iter__(self):
+        for item in self.base:
+            yield self.map(item)
+
+    def __len__(self):
+        return len(self.base)


Property changes on: zc.sourcefactory/trunk/src/zc/sourcefactory/mapping.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: zc.sourcefactory/trunk/src/zc/sourcefactory/mapping.txt
===================================================================
--- zc.sourcefactory/trunk/src/zc/sourcefactory/mapping.txt	2007-03-19 19:00:55 UTC (rev 73348)
+++ zc.sourcefactory/trunk/src/zc/sourcefactory/mapping.txt	2007-03-19 19:04:09 UTC (rev 73349)
@@ -0,0 +1,45 @@
+Mapping source values
+=====================
+
+Sometimes a source provides the right choice of objects, but the actual values
+we want to talk about are properties or computed views on those objects. The
+`mapping proxy source` helps us to map a source to a different value space.
+
+We start out with a source:
+
+  >>> source = [1,2,3,4,5]
+
+and we provide a method that maps the values of the original source to the
+values we want to see (we map the numbers to the characters in the english
+alphabet):
+
+  >>> map = lambda x: chr(x+96)
+
+Now we can create a mapped source:
+
+  >>> from zc.sourcefactory.mapping import ValueMappingSource
+  >>> mapped_source = ValueMappingSource(source, map)
+  >>> list(mapped_source)
+  ['a', 'b', 'c', 'd', 'e']
+  >>> len(mapped_source)
+  5
+  >>> 'a' in mapped_source
+  True
+  >>> 1 in mapped_source
+  False
+
+You can also use context-dependent sources:
+
+  >>> def bindSource(context):
+  ...     return [1,2,3,4,5]
+  >>> from zc.sourcefactory.mapping import ValueMappingSourceContextBinder
+  >>> binder = ValueMappingSourceContextBinder(bindSource, map)
+  >>> bound_source = binder(object())
+  >>> list(bound_source)
+  ['a', 'b', 'c', 'd', 'e']
+  >>> len(bound_source)
+  5
+  >>> 'a' in bound_source
+  True
+  >>> 1 in bound_source
+  False


Property changes on: zc.sourcefactory/trunk/src/zc/sourcefactory/mapping.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: zc.sourcefactory/trunk/src/zc/sourcefactory/named.py
===================================================================
--- zc.sourcefactory/trunk/src/zc/sourcefactory/named.py	2007-03-19 19:00:55 UTC (rev 73348)
+++ zc.sourcefactory/trunk/src/zc/sourcefactory/named.py	2007-03-19 19:04:09 UTC (rev 73349)
@@ -0,0 +1,43 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Visible Source
+# License, Version 1.0 (ZVSL).  A copy of the ZVSL should accompany this
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Named source binder
+
+"""
+__docformat__ = "reStructuredText"
+
+import zope.interface
+import zope.schema.interfaces
+
+import zc.sourcefactory.interfaces
+
+
+class NamedSource(object):
+    """Factory for named sources.
+
+    This is a generic thin wrapper to look up sources by name.
+    """
+
+    zope.interface.implements(zope.schema.interfaces.IContextSourceBinder)
+
+    def __init__(self, name):
+        self.name = name
+
+    def __call__(self, context):
+        factory = zope.component.getUtility(
+            zc.sourcefactory.interfaces.INamedSource, name=self.name)
+        source = factory()
+        if zope.schema.interfaces.IContextSourceBinder.providedBy(source):
+            source = source(context)
+        return source


Property changes on: zc.sourcefactory/trunk/src/zc/sourcefactory/named.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: zc.sourcefactory/trunk/src/zc/sourcefactory/policies.py
===================================================================
--- zc.sourcefactory/trunk/src/zc/sourcefactory/policies.py	2007-03-19 19:00:55 UTC (rev 73348)
+++ zc.sourcefactory/trunk/src/zc/sourcefactory/policies.py	2007-03-19 19:04:09 UTC (rev 73349)
@@ -0,0 +1,151 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Visible Source
+# License, Version 1.0 (ZVSL).  A copy of the ZVSL should accompany this
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Implementations of the basic policy components.
+
+"""
+__docformat__ = "reStructuredText"
+
+
+import zope.app.intid.interfaces
+import zope.component
+import zope.dublincore.interfaces
+
+import zc.sourcefactory.browser.source
+import zc.sourcefactory.interfaces
+
+
+# Term policies
+
+class BasicTermPolicy(object):
+    """A basic term policy.
+
+    createTerm creates a FactoredTerm object.
+
+    getTitle uses IDCDescriptiveProperties.title and falls back to
+    `str`-representation of the value.
+    """
+
+    zope.interface.implements(zc.sourcefactory.interfaces.ITermPolicy)
+
+    def createTerm(self, source, value, title, token, request):
+        return zc.sourcefactory.browser.source.FactoredTerm(
+            value, title, token)
+
+    def getTitle(self, value):
+        try:
+            md = zope.dublincore.interfaces.IDCDescriptiveProperties(value)
+        except TypeError:
+            md = None
+
+        if md:
+            title = md.title
+        else:
+            title = str(value)
+        return title
+
+
+# Token policies
+
+class BasicTokenPolicy(object):
+    """A basic token policy.
+
+    getToken adapts the value to IToken
+
+    getValue iterates over the source comparing the tokens of the values to the
+    token.
+    """
+
+    zope.interface.implements(zc.sourcefactory.interfaces.ITokenPolicy)
+
+    def getValue(self, source, token):
+        for value in source:
+            if source.factory.getToken(value) == token:
+                return value
+        raise KeyError, "No value with token '%s'" % token
+
+    def getToken(self, value):
+        return zc.sourcefactory.interfaces.IToken(value)
+
+
+class IntIdTokenPolicy(object):
+    """A token policy based on intids."""
+
+    zope.interface.implements(zc.sourcefactory.interfaces.ITokenPolicy)
+
+    def getValue(self, source, token):
+        iid = int(token)
+        value = self.intids.getObject(iid)
+        if value in self.source:
+            return value
+        else:
+            raise LookupError("no value matching token: %r" % token)
+
+    def getToken(self, value):
+        return str(self.intids.getId(value))
+
+    # We can't use zope.cachedescriptors.property.Lazy for this since
+    # the source factory exists across the entire process, and is used
+    # across different requests.  Using Lazy for this would result in
+    # the wrong ZODB connection being used in most threads.
+    #
+    @property
+    def intids(self):
+        return zope.component.getUtility(
+            zope.app.intid.interfaces.IIntIds)
+
+
+# Value policies
+
+class BasicValuePolicy(object):
+    """An abstract basic value policy.
+
+    `getValues()` is not implemented.
+
+    The filter allows all values.
+    """
+
+    zope.interface.implements(zc.sourcefactory.interfaces.IValuePolicy)
+
+    def filterValue(self, value):
+        return True
+
+class BasicContextualValuePolicy(BasicValuePolicy):
+    """An abstract basic value policy.
+
+    `getValues()` is not implemented.
+
+    The filter allows all values.
+    """
+
+    zope.interface.implements(
+        zc.sourcefactory.interfaces.IContextualValuePolicy)
+
+    def filterValue(self, context, value):
+        return True
+
+
+# Standard combined policies
+
+class BasicSourcePolicy(BasicValuePolicy, BasicTokenPolicy, BasicTermPolicy):
+    pass
+
+
+class BasicContextualSourcePolicy(
+    BasicContextualValuePolicy, BasicTokenPolicy, BasicTermPolicy):
+    pass
+
+
+class IntIdSourcePolicy(BasicValuePolicy, IntIdTokenPolicy, BasicTermPolicy):
+    pass


Property changes on: zc.sourcefactory/trunk/src/zc/sourcefactory/policies.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: zc.sourcefactory/trunk/src/zc/sourcefactory/source.py
===================================================================
--- zc.sourcefactory/trunk/src/zc/sourcefactory/source.py	2007-03-19 19:00:55 UTC (rev 73348)
+++ zc.sourcefactory/trunk/src/zc/sourcefactory/source.py	2007-03-19 19:04:09 UTC (rev 73349)
@@ -0,0 +1,67 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Visible Source
+# License, Version 1.0 (ZVSL).  A copy of the ZVSL should accompany this
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Source that uses the policies from the source factory.
+
+"""
+__docformat__ = "reStructuredText"
+
+
+import zope.interface
+import zope.schema.interfaces
+
+import zc.sourcefactory.interfaces
+
+
+class FactoredSource(object):
+    """An iterable source that was created from a source factory."""
+
+    zope.interface.implements(zc.sourcefactory.interfaces.IFactoredSource)
+
+    def __init__(self, factory):
+        self.factory = factory
+
+    def __iter__(self):
+        return self._get_filtered_values()
+
+    def __len__(self):
+        # This is potentially expensive!
+        return len(list(self._get_filtered_values()))
+
+    def __contains__(self, value):
+        return value in self._get_filtered_values()
+
+    def _get_filtered_values(self):
+        for value in self.factory.getValues():
+            if not self.factory.filterValue(value):
+                continue
+            yield value
+
+
+class FactoredContextualSource(FactoredSource):
+    """An iterable context-aware source that was created from a source factory.
+    """
+
+    zope.interface.implements(zc.sourcefactory.interfaces.IContextualSource)
+
+    def __init__(self, factory, context):
+        self.factory = factory
+        self.context = context
+        self.__parent__ = context
+
+    def _get_filtered_values(self):
+        for value in self.factory.getValues(self.context):
+            if not self.factory.filterValue(self.context, value):
+                continue
+            yield value


Property changes on: zc.sourcefactory/trunk/src/zc/sourcefactory/source.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: zc.sourcefactory/trunk/src/zc/sourcefactory/tests.py
===================================================================
--- zc.sourcefactory/trunk/src/zc/sourcefactory/tests.py	2007-03-19 19:00:55 UTC (rev 73348)
+++ zc.sourcefactory/trunk/src/zc/sourcefactory/tests.py	2007-03-19 19:04:09 UTC (rev 73349)
@@ -0,0 +1,40 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Visible Source
+# License, Version 1.0 (ZVSL).  A copy of the ZVSL should accompany this
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Unit tests
+
+"""
+__docformat__ = "reStructuredText"
+
+import os.path
+import unittest
+
+from zope.testing import doctest
+import zope.app.testing.functional
+from zope.app.testing.functional import FunctionalDocFileSuite
+
+here = os.path.realpath(os.path.dirname(__file__))
+
+SourceFactoryLayer = zope.app.testing.functional.ZCMLLayer(
+            os.path.join(here, "ftesting.zcml"), __name__, "SourceFactoryLayer")
+
+
+def test_suite():
+    suite = unittest.TestSuite()
+    suite.addTest(doctest.DocFileSuite('README.txt'))
+    suite.addTest(doctest.DocFileSuite('mapping.txt'))
+    adapters = FunctionalDocFileSuite('adapters.txt')
+    adapters.layer = SourceFactoryLayer
+    suite.addTest(adapters)
+    return suite


Property changes on: zc.sourcefactory/trunk/src/zc/sourcefactory/tests.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native



More information about the Checkins mailing list