[Zope3-dev] How to add schema fields programmatically, from an outside schema definition?

Marius Gedminas mgedmin at b4net.lt
Sun Jan 2 18:18:59 EST 2005


Hi,

On Fri, Dec 31, 2004 at 12:07:17AM +0200, Petri Savolainen wrote:
> Rather than coding schema in python, I've specified one using YAML 
> markup (http://www.yaml.org) and stored it in an outside file. Here's a 
> simple snippet:
> 
> IPerson:
>    # A person
>    first:
>       type: TextLine
>       title: First name
>       description: The first name, also known as given name, of the person
> 
> But what is the right spot within zope3 processing chain to add the 
> schema fields into the interface class? It appears it is not ok to 
> simply try and add fields to the class from within the same module where 
> IPerson is defined is not working, as in:
> 
> class IPerson(...):
>   ...
> 
> setSchema("schemata.yml",IPerson)
> 
> 
> Any advice?

I see at least two options:

  1. Define a loadSchema function that constructs a schema by creating all
     the schema fields and calling InterfaceClass:

        def loadSchema(filename, interfacename):
            """Load a named schema from a YAML file.

            Example:

              IPerson = loadSchema("schemas.yaml", "IPerson")

            where schemas.yaml contains:

              ...

            """
            fields = {} # field name -> zope.schema.Field object
            # ... yaml parsing, about which I know nothing ...
            return InterfaceClass(interfacename, (), fields)

      If you want to define methods as well as schema fields, you have
      to define two interfaces:

        IPersonSchema = loadSchema("schemas.yaml", "IPersonSchema")

        class IPerson(IPersonSchema):
            def method1(...):
                ...
            ...

     If you do not want methods, then you can extend this line of
     thought and define a loadSchemas("schemas.yaml") that returns a
     dict of all schemas defined in the yaml file, and then maybe even
     do

        globals().update(loadSchemas("schemas.yaml"))

     so that you won't have to explicitly list all schemas defined in
     the file.  However consider the readability of the source code
     before doing this.

  2. Define a setSchema function that mucks with the locals dict of the
     parent frame, like zope.app.container.constraints do:

        def setSchema(filename):
            """Add all schema fields from a YAML file to the schema definition.

            Example:

              class IPerson(Interface):

                  setSchema("schemas.yaml")

                  def method1(...):
                      ....

            where schemas.yaml contains:

               ...

            """
            caller = sys._getframe(1)
            interfacename = caller.f_code.co_name
            # check that this function was called from class scope
            # (see zope.app.container.constrainst.contains or
            # zope.interface.advice.addClassAdvisor)
            fields = {} # field name -> zope.schema.Field object
            # ... yaml parsing, about which I know nothing ...
            caller.f_locals.update(fields)

     Again, this is somewhat magic, so consider the maintainability of
     the code.  On the other hand, magic like this is already used in
     several places in Zope 3 (zope.interface.implements,
     zope.app.container.constraints.contains, etc.), so it should not be
     a complete surprise for developers.

HTH,
Marius Gedminas
-- 
For vi emulation of emacs, just type ":sh emacs" (without the quotes).
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
Url : http://mail.zope.org/pipermail/zope3-dev/attachments/20050103/b95a8daa/attachment.bin


More information about the Zope3-dev mailing list