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: