[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