[Zope3-checkins] SVN: Zope3/trunk/src/zope/schema/ Updated schema
package's README.txt fiel and made it a doctest. The
Stephan Richter
srichter at cosmos.phy.tufts.edu
Fri Mar 4 08:41:06 EST 2005
Log message for revision 29396:
Updated schema package's README.txt fiel and made it a doctest. The
contents of the the file still sucks a lot, but a little less now.
Changed:
U Zope3/trunk/src/zope/schema/README.txt
U Zope3/trunk/src/zope/schema/fields.txt
A Zope3/trunk/src/zope/schema/tests/test_docs.py
-=-
Modified: Zope3/trunk/src/zope/schema/README.txt
===================================================================
--- Zope3/trunk/src/zope/schema/README.txt 2005-03-04 12:58:56 UTC (rev 29395)
+++ Zope3/trunk/src/zope/schema/README.txt 2005-03-04 13:41:06 UTC (rev 29396)
@@ -2,24 +2,21 @@
Zope 3 Schemas
==============
-.. contents::
-
-
Introduction
------------
-Schemas extend the notion of interfaces to descriptions of Attributes
-rather than methods. Every Schema is an interface and specifies the
-public fields of an object. A *Field* roughly corresponds to an
-attribute of a python object. But a Field provides space for a title
-and a description. It can also constrain its value and provide a
-validation method. Besides you can optionally specify characteristics
-such as its value being read-only or not required.
+Schemas extend the notion of interfaces to detailed descriptions of Attributes
+(but not methods). Every schema is an interface and specifies the public
+fields of an object. A *field* roughly corresponds to an attribute of a
+python object. But a Field provides space for at least a title and a
+description. It can also constrain its value and provide a validation method.
+Besides you can optionally specify characteristics such as its value being
+read-only or not required.
Zope 3 schemas were born when Jim Fulton and Martijn Faassen thought
-about Formulator for Zope 3 and PropertySets while at the `Zope 3
-sprint`_ at the `Zope BBQ`_ in Berlin. They realized that if you strip
-all view logic from forms then you have something similar to interfaces. And
+about Formulator for Zope 3 and ``PropertySets`` while at the `Zope 3
+sprint`_ at the `Zope BBQ`_ in Berlin. They realized that if you strip
+all view logic from forms then you have something similar to interfaces. And
thus schemas were born.
.. _Zope 3 sprint: http://dev.zope.org/Zope3/ZopeBBQ2002Sprint
@@ -36,87 +33,149 @@
Simple Usage
------------
+Let's have a look at a simple example. First we write an interface as usual,
+but instead of describing the attributes of the interface with ``Attribute``
+instances, we now use schema fields:
+ >>> import zope.interface
+ >>> import zope.schema
-
- >>> class Bookmark:
- ... def __init__(self, url):
- ... self.url = url
- ...
- >>> from zope.schema import TextLine, validateMapping
- >>> from zope.interface import Interface
- >>> class IBookmark(Interface):
- ... url = TextLine(title=u'url of the bookmark')
- ...
- ...
- >>> obj = Bookmark(u'zope website', u'http://www.zope.org',
- ... keywords=('web', 'python'))
- >>> validateMapping(IBookmark, obj.__dict__)
+ >>> class IBookmark(zope.interface.Interface):
+ ... title = zope.schema.TextLine(
+ ... title=u'Title',
+ ... description=u'The title of the bookmark',
+ ... required=True)
+ ...
+ ... url = zope.schema.URI(
+ ... title=u'Bookmark URL',
+ ... description=u'URL of the Bookmark',
+ ... required=True)
+ ...
+
+Now we create a class that implements this interface and create an isntance of
+it:
-The last statement validates that our object conforms to the
-``IBookmark`` Schema.
+ >>> class Bookmark(object):
+ ... zope.interface.implements(IBookmark)
+ ...
+ ... title = None
+ ... url = None
+ >>> bm = Bookmark()
+We would now like to only add validated values to the class. This can be done
+by first validating and then setting the value on the object. The first step
+is to define some data:
+
+ >>> title = u'Zope 3 Website'
+ >>> url = 'http://dev.zope.org/Zope3'
+
+Now we, get the fields from the interface:
+
+ >>> title_field = IBookmark.get('title')
+ >>> url_field = IBookmark.get('url')
+
+Next we have to bind these fields to the context, so that instance-specific
+information can be used for validation:
+
+ >>> title_bound = title_field.bind(bm)
+ >>> url_bound = url_field.bind(bm)
+
+Now that the fields are bound, we can finally validate the data:
+
+ >>> title_bound.validate(title)
+ >>> url_bound.validate(url)
+
+If the validation is successful, ``None`` is returned. If a validation error
+occurs a ``ValidationError`` will be raised; for example:
+
+ >>> url_bound.validate(u'http://zope.org/foo')
+ Traceback (most recent call last):
+ ...
+ WrongType: (u'http://zope.org/foo', <type 'str'>)
+
+ >>> url_bound.validate('foo.bar')
+ Traceback (most recent call last):
+ ...
+ InvalidURI: foo.bar
+
+Now that the data has been successfully validated, we can set it on the
+object:
+
+ >>> title_bound.set(bm, title)
+ >>> url_bound.set(bm, url)
+
+That's it. You still might think this is a lot of work to validate and set a
+value for an object. Note, however, that it is very easy to write helper
+functions that automate these tasks. If correctly designed, you will never
+have to worry explicitely about validation again, since the system takes care
+of it automatically.
+
+
What is a schema, how does it compare to an interface?
------------------------------------------------------
-A schema is an extended interface which defines Fields. You can
-validate that 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.
+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
+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 from the programmer's tutorial::
+down example from the programmer's tutorial:
- from zope.interface import Interface
- from zope.schema import Text, TextLine
+ >>> import re
- class IContact(Interface):
- """Provides access to basic contact information."""
+ >>> 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)
- first = TextLine(title=u"First name")
- last = TextLine(title=u"Last name")
- email = TextLine(title=u"Electronic mail address")
- address = Text(title=u"Postal address")
- postalCode = 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::
+Now we want a class that adheres to the ``IContact`` schema:
- class Contact(persistent.Persistent):
- implements(IContact)
+ >>> 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
- 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::
+schema:
- from zope.app.schema import validateMapping
- someone = Contact('Tim','Roberts', 'tim at roberts', '','')
- validateMapping(IContact, someone.__dict__)
+ >>> someone = Contact(u'Tim', u'Roberts', u'tim at roberts', u'',
+ ... u'12032-3492')
+
+ >>> for field in zope.schema.getFields(IContact).values():
+ ... bound = field.bind(someone)
+ ... bound.validate(bound.get(someone))
Data Modeling Concepts
-----------------------
-XXX much more is needed here!
-
The ``zope.schema`` package provides a core set of field types,
including single- and multi-line text fields, binary data fields,
integers, floating-point numbers, and date/time values.
@@ -134,7 +193,7 @@
same for all values of the type. Changes to the list are driven by
schema evolution.
- This is done by mixing-in the IEnumerated interface into the field
+ This is done by mixing-in the ``IEnumerated`` interface into the field
type, and the Enumerated mix-in for the implementation (or emulating
it in a concrete class).
@@ -161,7 +220,7 @@
If a field is designated as required, assigned field values must always
be non-missing. See the next section for a description of missing values.
-- A value designated as 'missing'
+- A value designated as ``missing``
Missing values, when assigned to an object, indicate that there is 'no
data' for that field. Missing values are analogous to null values in
@@ -183,6 +242,7 @@
Fields and Widgets
------------------
+
Widgets are components that display field values and, in the case of
writable fields, allow the user to edit those values.
@@ -201,8 +261,8 @@
by the user need to be converted to numbers such as int or float.
- Support the ability to assign a missing value to a field. For example,
- a widget may present a "None" option for selection that, when selected,
- indicates that the object should be updated with the field's 'missing'
+ a widget may present a ``None`` option for selection that, when selected,
+ indicates that the object should be updated with the field's ``missing``
value.
Modified: Zope3/trunk/src/zope/schema/fields.txt
===================================================================
--- Zope3/trunk/src/zope/schema/fields.txt 2005-03-04 12:58:56 UTC (rev 29395)
+++ Zope3/trunk/src/zope/schema/fields.txt 2005-03-04 13:41:06 UTC (rev 29396)
@@ -2,9 +2,6 @@
Fields
======
-.. contents::
-
-
This document highlights unusual and subtle aspects of various fields and
field classes, and is not intended to be a general introduction to schema
fields. Please see README.txt for a more general introduction.
@@ -17,7 +14,7 @@
("widgets").
Collections
-===========
+-----------
Normal fields typically describe the API of the attribute -- does it behave as a
Python Int, or a Float, or a Bool -- and various constraints to the model, such
@@ -68,7 +65,7 @@
would also be necessary to implement a Bag.
Choices and Vocabularies
-========================
+------------------------
Choice fields are the schema way of spelling enumerated fields and more. By
providing a dynamically generated vocabulary, the choices available to a
@@ -119,7 +116,7 @@
not too difficult itself.
Choices and Collections
-=======================
+-----------------------
Choices are a field type and can be used as a value_type for collections. Just
as a collection of an "Int" value_type constrains members to integers, so a
@@ -129,7 +126,7 @@
which the choice is based.
Using Choice and Collection Fields within a Widget Framework
-============================================================
+------------------------------------------------------------
While fields support several use cases, including code documentation and data
description and even casting, a significant use case influencing their design is
Added: Zope3/trunk/src/zope/schema/tests/test_docs.py
===================================================================
--- Zope3/trunk/src/zope/schema/tests/test_docs.py 2005-03-04 12:58:56 UTC (rev 29395)
+++ Zope3/trunk/src/zope/schema/tests/test_docs.py 2005-03-04 13:41:06 UTC (rev 29396)
@@ -0,0 +1,27 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL 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.
+#
+##############################################################################
+"""Tests for the schema package's documentation files
+
+$Id: tests.py 29143 2005-02-14 22:43:16Z srichter $
+"""
+import unittest
+from zope.testing import doctest
+
+def test_suite():
+ return unittest.TestSuite((
+ doctest.DocFileSuite('../README.txt'),
+ ))
+
+if __name__ == '__main__':
+ unittest.main(default='test_suite')
Property changes on: Zope3/trunk/src/zope/schema/tests/test_docs.py
___________________________________________________________________
Name: svn:eol-style
+ native
More information about the Zope3-Checkins
mailing list