What are schemas?

The following explanation is taken from zope.schema.README.txt.

What is a schema, how does it compare to an interface?

A schema is an extended interface which defines fields. You can validate that the attributes of an object conform to their fields defined on the schema. With plain interfaces you can only validate that methods conform to their interface specification.

So interfaces and schemas refer to different aspects of an object (respectively its code and state).

A schema starts out like an interface but defines certain fields to which an object's attributes must conform. Let's look at a stripped down example:

>>> import re

>>> class IContact(zope.interface.Interface):
...     """Provides access to basic contact information."""
...
...     first = zope.schema.TextLine(title=u"First name")
...
...     last = zope.schema.TextLine(title=u"Last name")
...
...     email = zope.schema.TextLine(title=u"Electronic mail address")
...
...     address = zope.schema.Text(title=u"Postal address")
...
...     postalCode = zope.schema.TextLine(
...         title=u"Postal code",
...         constraint=re.compile("\d{5,5}(-\d{4,4})?$").match)

TextLine? is a field and expresses that an attribute is a single line of Unicode text. Text expresses an arbitrary Unicode ("text") object. The most interesting part is the last attribute specification. It constrains the postalCode attribute to only have values that are US postal codes.

Now we want a class that adheres to the IContact? schema:

>>> class Contact(object):
...     zope.interface.implements(IContact)
...
...     def __init__(self, first, last, email, address, pc):
...         self.first = first
...         self.last = last
...         self.email = email
...         self.address = address
...         self.postalCode = pc

Now you can see if an instance of Contact actually implements the schema:

>>> someone = Contact(u'Tim', u'Roberts', u'tim@roberts', u'',
...                   u'12032-3492')

>>> for field in zope.schema.getFields(IContact).values():
...     bound = field.bind(someone)
...     bound.validate(bound.get(someone))



( 97 subscribers )