Package: dm.zope.schema
This package contains extensions forzope.schema.ModulesverifyA companion tozope.interface.verifyfor the schema part of
interfaces.It contains the functionverify_schema(iface,obj,context=None,check_declaration=True)which verifies thatobjsatisfies the schema part of interfaceiface.
Schema fields need to get bound to a context before they can be validated.contextspecifies this context and defaults toobj.check_declarationchecks thatobjdeclares to provideiface.schemaThe main content is the mixin classSchemaConfigured. It supports
configuration according the schema part of the interfaces implemented
by theSchemaConfiguredderived class. If you want to
control from which interfaces the schema is derived,
you can use the class attributeSC_SCHEMAS: its value should beNone(derive schema automatically from the implemented interfaces),
a single interface or a tuple of interfaces. Taking explicit control
over the interfaces used to determine the schema is especially important
for Zope 2 schema configured content classes (as their base
classOFS.SimpleItem.SimpleItemimplements a huge number of
interfaces whose fields you likely do not want in your schema).The mixin classSchemaConfiguredEvolutionprovides support
for schema evolution for (ZODB) persistent objects. Its__setstate__adds missing attributes to the object such that you can add new fields
to your schema and still find all corresponding attributes on the
respective objects even when those have been created before the extension.
Note: in order forSchemaConfiguredEvolutionto be effective, it must
come early in the method resolution order (mro)
(beforepersistent.Persistent).
That’s why is is a separate class and its feature not included
inSchemaConfigureditself (there may be good reasons
to haveSchemaConfiguredlate in themro).
As an alternative to the use ofSchemaConfiguredEvolution,
you can use default values defined on class level for new fields.Occasionally, functionsschemaitemsandschemadictmight be usefull.
They extract
the schema part of an interface or interface specification as
a list of id, field pairs or a dictionary, respectively.The fieldObjectis a replacement forzope.schema.Object.
In formerzope.schemaversions, itsObjectlacked field information in validation errors
(https://bugs.launchpad.net/zope.schema/+bug/620324) which made identification
of the affected fields unnecessarily difficult; this package’sObjectwas designed to work around this bug.
Modernzope.schemaversions have fixed the bug and
this package’sObjectnow behaves almost as that ofzope.schema.
However, it allows to suppress the check that the validated
object explicitely declares to provide the interface.Objecthas the additional
propertycheck_declarationto control this (defaults toTrue).propertymanagerThis module implements a schema basedOFS.PropertyManager.PropertyManagersubclass. The_propertiesattribute describing the properties is
not maintained on the class or its instances but derived from
the provided (respectively implemented) schemas. For the moment,
properties cannot be extended on an instance based level (other than by
providing another schema).zope.schemauses unicode to represent text.PropertyManagercan in principle support unicode properties. However, due to a
bug/weakness, the property management page handles them correctly
only, whenmanagement_page_charsetis not defined or has
valueUTF-8(note the upper case spelling!). We use unicode
properties by default unlessmanagement_page_charset.upper()yields
a value different fromUTF-8. We also provide a mixin classWorkaroundSpelling_management_page_charsetto work around Zope’s
stupid insistence on upper case spelling formanagement_page_charset.For the moment, the following field types are supported:Text,TextLine,Bytes,BytesLine,Bool,Int,FloatandListwith a value type ofTextLineorBytesLine.
Other types will raiseNotImplementedError.The module has been implemented to leveragedm.zope.generate.
An alternative would have been the implementation of the generation facilities
based on “zope.formlib” and the use of so called add forms. Depending
on experience, I may switch to this alternative.formThe module defines default edit (SchemaConfiguredEditForm)
and display (SchemaConfiguredDisplayForm) forms fordm.zope.schema.schema.SchemaConfigured.It depends onzope.formlib.widgetProvides display and edit widgets forTimedeltafields,
a decent display widget forPasswordfields (the default
displays passwords in cleartext) and an input widget forPasswordthat does not force you to provide the password value whenever you edit the form.It depends onzope.app.formin older Zope versions and onzope.formlibin newer ones.tagOften you would like to provide additional information for your fields -
usually with effects to presentation. Unfortunately,zope.schemahas
forgotten this use case: it is really hard to give existing fields
additional properties.Fortunately,zope.schemais build on top ofzope.interfaceand it
supports so called “tagged values” to add additional information to
its elements. This module uses this feature to provide additional information
for schema elements. As a matter of fact, it works for all schema elements,
not just fields.Note: If your schemas are used across different packages, ensure the
tag names are sufficiently specific to avoid name clashes, e.g.
by using an appropriate prefix.dataschemazope.schemais nice to describe objects with attributes. But sometimes,
you would like to work with mappings whose keys are described by
a schema. This module contains auxiliary classes to bridge the gap
between (schema controlled) objects and (schema controlled) mappings.SchemaDictis a dictionary with keys described by a schema
andMappingBySchemais a mixin class to provide a (schema controlled)
mapping interface to an object.z2This subpackage combines schema related and
Zope2/Zope 4+ functionality. In newer Zope versions, it depends onfive.formlib(and, of course, on Zope2 or Zope 4+, respectively).
Note thatfive.formlibwas not yet Python 3 compatible when
this package has been released.formThe module defines default edit (SchemaConfiguredEditForm)
and display (SchemaConfiguredDisplayForm) forms fordm.zope.schema.schema.SchemaConfiguredfor use in Zope2/Zope 4+.It depends onzope.formlib.constructorThis module contains an add form classSchemaConfiguredAddFormand a factoryadd_form_factoryfor the generation of an add form (called “constructor” by Zope 2)
fordm.zope.schema.schema.SchemaConfiguredbased classes.
The generated add form is usually used as part of theconstructorsparameter toregisterClass.add_form_factoryhas the parameters:namedefaultdescriptionclass_the class to generate the form fortitleCreate instance ofclass_the title shown in the formdescriptionclass_.__doc__the documentation shown in the formform_classSchemaConfiguredAddFormform class to be usedadd_form_factorygenerates azope.formlibform with fields
defined by the implemented schemas ofdm.zope.schema.schema.SchemaConfiguredclassclass_.This module is similar todm.zope.generate.constructor. However,
it works forSchemaConfiguredbased classes while the latter
supportsPropertyManagerbased classes.templateProvides the view page templateform_templateable to view and edit
Zope2/Zope 4+
schema configured content objects within the standard ZMI interface.ExamplesSetup: It defines two schemasS1andS2, an
interfaceIand a classCderiving fromSchemaConfiguredimplementing the schemas and the interface.>>> from zope.interface import Interface, implementer, providedBy
>>> from zope.schema import Int
>>>
>>> from dm.zope.schema.schema import SchemaConfigured
>>> from dm.zope.schema.verify import verify_schema
>>>
>>> class S1(Interface): i1 = Int(default=0)
...
>>> class S2(Interface): i2 = Int(default=1)
...
>>> class I(Interface):
...   def method(): pass
...
>>> @implementer(S1, S2, I)
... class C(SchemaConfigured):
...   def method(self): pass
...Cinstances have attributes corresponding to the schema fields.
If no arguments are given for the constructor, they get the field default
as value. Provided (keyword!) arguments override the defaults.>>> c = C()
>>> c.i1
0
>>> c.i2
1
>>> c = C(i1=5)
>>> c.i1
5The constructor rejects keyword arguments not defined in the schema
in order to quickly detect spelling errors. However, this hampers
the use ofsuperin the class hierarchy for the__init__method.
Maybe, future versions will provide a means to control this check.>>> c = C(x=5)
Traceback (most recent call last):
  ...
TypeError: non schema keyword argument: xIf the field values are appropriate,Cinstances provide the
schemas (as verified byverify_schema). Otherwise,verify_schemawill raise an exception.This example demonstrates also the elementary use
ofverify_schema. Note thatverify_schemaraises different
exceptions in case of failure depending on the version ofzope.schema(WrongContainedTypein older version,SchemaNotCorrectlyImplementedin newer versions).>>> verify_schema(S1, c)
>>> c.i1=None
>>> try: verify_schema(S1, c)
... except Exception as e: e.args[0]
[RequiredMissing('i1')]We can also explicitely specify which schemas our class should
support via the class variableSC_SCHEMAS.>>> class SC(SchemaConfigured):
...   SC_SCHEMAS = S1, S2
...
>>> sc = SC()
>>> sc.i1
0
>>> sc.i2
1
>>> verify_schema(S1, sc, check_declaration=False)We can create an edit (or display) form for our objects. Form fields
are automatically created for our schema fields.
The form classes have acustomize_fieldsmethod you can override
to provide custom fields and/or widgets.Similar functionality is available for Zope 2/Zope 4 in thez2subpackage.>>> from zope.publisher.browser import TestRequest
>>> from dm.zope.schema.form import SchemaConfiguredEditForm
>>>
>>> form = SchemaConfiguredEditForm(c, TestRequest())
>>> list([f.__name__ for f in form.form_fields])
['i1', 'i2']Schemas describe a data model with properties relevant for either
documentation, validation or the user interface. Occasionally,
you may want to use a schema for other purposes as well –
and then, you may lack properties to satisfy the requirements.
I ran into this fordm.zope.resellerwhere I wanted to
use schemas to also partially describe data models
in a relational database. For this, I needed the concept
“informational field” describing a field not directly stored in
the database but computed from other database fields.
I used tagging as shown in the example below.>>> from dm.zope.schema.tag import Tagger
>>> tag = Tagger("dm.zope.reseller")
>>> class S(Interface):
...   i1 = tag(Int(default=0), informational=True)
...   i2 = Int(default=1)
...We check for an informational field:>>> tag.get(S["i1"], "informational")
True
>>> tag.get(S["i2"], "informational")We can also ask which tags are available:>>> tag.list(S["i1"])
['informational']If we need to check for various tags on a field, we can wrap
it and then access the tags with typical mapping methods.>>> te = tag.wrap(S["i1"])
>>> list(te)
['informational']
>>> te["informational"]
True
>>> "informational" in te
True
>>> te.unwrap() is S["i1"]
TrueHistory4.0Now depends onzope.schema >= 4.Theschemamodule defines new fieldsFilesystemPathandIriRef.New modulez2.schemadefining new fieldsItemNameandItemPath.3.0Python3/Zope4 compatibility.
Note that the subpackagez2depends onfive.formlibwhich was not yet Python 3 compatible when this version was
released.Modern versions ofzope.schemahave removed a major weaknees
of itsObjectfield: its validation now registers for
failing subfields the field name in the corresponding exception
(usually in itsfieldattribute). TheObjectfield of this
package has been changed in an incompatible way to match thezope.schemabehaviour; its only difference is now that
it allows to suppress the “provides” check.More examples and test resources.2.1Modulestaganddataschema2.0form supportZope 2 constructor support