diff --git a/composer/schema/README.txt b/composer/schema/README.txt
index 3943641..6fe1b64 100644
--- a/composer/schema/README.txt
+++ b/composer/schema/README.txt
@@ -7,6 +7,10 @@ Schema and Field Management
>>> from cybertools.composer.schema import Schema
>>> from cybertools.composer.schema import Field
+
+Working with predefined schemas
+===============================
+
We start with setting up a schema with fields.
>>> serviceSchema = Schema(
@@ -41,3 +45,48 @@ correct conversion of input data to context attributes.
>>> srv.title, srv.description, srv.capacity
(u'Service', u'', u'30')
+
+
+Creating a schema from an interface
+===================================
+
+ >>> from zope.interface import Interface, implements
+ >>> import zope.schema
+ >>> from cybertools.composer.schema.factory import SchemaFactory
+ >>> component.provideAdapter(SchemaFactory)
+
+ >>> class IPerson(Interface):
+ ... firstName = zope.schema.TextLine(title=u'First name')
+ ... lastName = zope.schema.TextLine(title=u'Last name')
+ ... age = zope.schema.Int(title=u'Age')
+
+ >>> class Person(object):
+ ... implements(IPerson)
+
+ >>> from cybertools.composer.schema.interfaces import ISchemaFactory
+ >>> factory = ISchemaFactory(Person())
+
+ >>> schema = factory(IPerson)
+ >>> for f in schema.fields:
+ ... print f.name, f.title, f.fieldType
+ firstName First name textline
+ lastName Last name textline
+ age Age number
+
+Using a more specialized schema factory
+---------------------------------------
+
+ >>> class PersonSchemaFactory(SchemaFactory):
+ ... def __call__(self, manager=None):
+ ... schema = super(PersonSchemaFactory, self).__call__(manager)
+ ... del schema.fields['firstName'] # don't show first name
+ ... return schema
+ >>> component.provideAdapter(PersonSchemaFactory, (IPerson,))
+
+ >>> factory = ISchemaFactory(Person())
+ >>> schema = factory(IPerson)
+ >>> for f in schema.fields:
+ ... print f.name, f.title, f.fieldType
+ lastName Last name textline
+ age Age number
+
diff --git a/composer/schema/configure.zcml b/composer/schema/configure.zcml
index 4b5b04e..ba907d8 100644
--- a/composer/schema/configure.zcml
+++ b/composer/schema/configure.zcml
@@ -12,4 +12,6 @@
+
+
diff --git a/composer/schema/factory.py b/composer/schema/factory.py
new file mode 100644
index 0000000..2974f84
--- /dev/null
+++ b/composer/schema/factory.py
@@ -0,0 +1,72 @@
+#
+# Copyright (c) 2007 Helmut Merz helmutm@cy55.de
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+"""
+Schema factory stuff.
+
+$Id$
+"""
+
+from zope.component import adapts
+from zope.interface import implements
+from zope.interface import Interface
+from zope import schema
+
+from cybertools.composer.schema.field import Field
+from cybertools.composer.schema.interfaces import ISchemaFactory
+from cybertools.composer.schema.schema import Schema
+
+
+class SchemaFactory(object):
+
+ implements(ISchemaFactory)
+ adapts(Interface)
+
+ fieldMapping = {
+ schema.TextLine: ('textline',),
+ schema.ASCII: ('textline',),
+ schema.Text: ('textarea',),
+ schema.Date: ('date',),
+ schema.Int: ('number',),
+ schema.Bool: ('checkbox',),
+ schema.Choice: ('dropdown',),
+ schema.Bytes: ('fileupload',),
+ }
+
+ def __init__(self, context):
+ self.context = context
+
+ def __call__(self, interface, **kw):
+ fieldMapping = self.fieldMapping
+ fields = []
+ for fname in schema.getFieldNamesInOrder(interface):
+ field = interface[fname]
+ if field.__class__ in fieldMapping:
+ info = fieldMapping[field.__class__]
+ voc = (getattr(field, 'vocabulary', ()) or
+ getattr(field, 'vocabularyName', None))
+ f = Field(field.getName(),
+ fieldType=info[0],
+ required=field.required,
+ default=field.default,
+ #default_method=getattr(field, 'default_method', None),
+ vocabulary=voc,
+ title=field.title,
+ description=field.description)
+ fields.append(f)
+ return Schema(name=interface.__name__, *fields, **kw)
diff --git a/composer/schema/interfaces.py b/composer/schema/interfaces.py
index 143e6f5..c4bb1e0 100644
--- a/composer/schema/interfaces.py
+++ b/composer/schema/interfaces.py
@@ -58,6 +58,15 @@ class ISchema(ITemplate):
'with this schema.')
+class ISchemaFactory(Interface):
+ """ Provides a schema when called. Typically used for adapters.
+ """
+
+ def __call__(interface, **kw):
+ """ Return a schema, based on the interface given.
+ """
+
+
class FieldType(SimpleTerm):
def __init__(self, value, token=None, title=None, **kw):
diff --git a/composer/schema/util.py b/composer/schema/util.py
deleted file mode 100644
index a81e4e9..0000000
--- a/composer/schema/util.py
+++ /dev/null
@@ -1,60 +0,0 @@
-#
-# Copyright (c) 2007 Helmut Merz helmutm@cy55.de
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
-
-"""
-Utility functions.
-
-$Id$
-"""
-
-from zope import schema
-from cybertools.composer.schema.schema import Schema
-from cybertools.composer.schema.field import Field
-
-
-fieldMapping = {
- schema.TextLine: ('textline',),
- schema.ASCII: ('textline',),
- schema.Text: ('textarea',),
- schema.Date: ('date',),
- schema.Int: ('number',),
- schema.Bool: ('checkbox',),
- schema.Choice: ('dropdown',),
- schema.Bytes: ('fileupload',),
-}
-
-
-def getSchemaFromInterface(ifc, manager):
- fields = []
- for fname in schema.getFieldNamesInOrder(ifc):
- field = ifc[fname]
- if field.__class__ in fieldMapping:
- info = fieldMapping[field.__class__]
- voc = getattr(field, 'vocabulary', ()) or getattr(field, 'vocabularyName', None)
- f = Field(field.getName(),
- fieldType=info[0],
- required=field.required,
- default=field.default,
- #default_method=getattr(field, 'default_method', None),
- vocabulary=voc,
- title=field.title,
- description=field.description)
- fields.append(f)
- return Schema(manager=manager, name=ifc.__name__, *fields)
-
-
diff --git a/util/jeep.py b/util/jeep.py
index d1e8b61..3ebcb41 100644
--- a/util/jeep.py
+++ b/util/jeep.py
@@ -93,6 +93,10 @@ class Jeep(object):
def append(self, obj):
self.insert(len(self), obj)
+ def extend(self, sequence):
+ for obj in sequence:
+ self.append(obj)
+
def insert(self, idx, obj):
key = getattr(obj, '__name__', getattr(obj, 'name', _notfound))
if key is _notfound: