Skip to content

Commit

Permalink
add directives based on the ones from plone.directives.form, but with…
Browse files Browse the repository at this point in the history
… no grok dependency

svn path=/plone.autoform/trunk/; revision=50414
  • Loading branch information
davisagli committed Jun 13, 2011
1 parent 5dd9082 commit 689cdfb
Show file tree
Hide file tree
Showing 7 changed files with 425 additions and 5 deletions.
10 changes: 8 additions & 2 deletions CHANGES.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
Changelog
=========

1.0.1 - Unreleased
------------------
2.0 - Unreleased
----------------

- Moved form schema directives here from plone.directives.form, and
reimplemented them as plone.supermodel directives to avoid depending on
grok. Included directives: omitted, no_omit, mode, widget, order_before,
order_after, read_permission, write_permission
[davisagli]


1.0 - 2011-05-13
Expand Down
3 changes: 2 additions & 1 deletion README.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ There are several ways to set the form data:
* Manually, by using ``setTaggedValue()`` on an interface.
* By loading the schema from a `plone.supermodel`_ XML file and using the
``form:`` prefix
* By using the grok directives in the `plone.directives.form`_ package.
* By using the directives from ``plone.autoform.directives`` while defining
a schema in Python.

To use the automatic form setup, mix in the following base class in your
forms::
Expand Down
30 changes: 30 additions & 0 deletions plone/autoform/configure.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,35 @@
factory=".supermodel.SecuritySchema"
name="plone.autoform.security"
/>

<adapter
factory=".directives.OmittedPlugin"
name="plone.autoform.omitted"
/>

<adapter
factory=".directives.ModePlugin"
name="plone.autoform.mode"
/>

<adapter
factory=".directives.WidgetPlugin"
name="plone.autoform.widget"
/>

<adapter
factory=".directives.OrderPlugin"
name="plone.autoform.order"
/>

<adapter
factory=".directives.ReadPermissionsPlugin"
name="plone.autoform.read_permissions"
/>

<adapter
factory=".directives.WritePermissionsPlugin"
name="plone.autoform.write_permissions"
/>

</configure>
131 changes: 131 additions & 0 deletions plone/autoform/directives.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
from zope.interface import Interface
from zope.interface.interfaces import IInterface

from plone.supermodel.directives import MetadataListDirective
from plone.supermodel.directives import MetadataDictDirective
from plone.supermodel.directives import ListCheckerPlugin
from plone.supermodel.directives import DictCheckerPlugin

from plone.autoform.interfaces import OMITTED_KEY, MODES_KEY, WIDGETS_KEY
from plone.autoform.interfaces import ORDER_KEY
from plone.autoform.interfaces import READ_PERMISSIONS_KEY, WRITE_PERMISSIONS_KEY


class omitted(MetadataListDirective):
"""Directive used to omit one or more fields
"""
key = OMITTED_KEY
value = 'true'

def factory(self, *args):
if not args:
raise TypeError('The omitted directive expects at least one argument.')
form_interface = Interface
if IInterface.providedBy(args[0]):
form_interface = args[0]
args = args[1:]
return [(form_interface, field, self.value) for field in args]


class no_omit(omitted):
"""Directive used to prevent one or more fields from being omitted
"""
value = 'false'


class OmittedPlugin(ListCheckerPlugin):

key = OMITTED_KEY

def fieldNames(self):
if self.value is None:
return
for _, fieldName, _ in self.value:
yield fieldName


class mode(MetadataListDirective):
"""Directive used to set the mode of one or more fields
"""
key = MODES_KEY

def factory(self, *args, **kw):
if len(args) > 1:
raise TypeError('The mode directive expects 0 or 1 non-keyword arguments.')
form_interface = Interface
if args:
form_interface = args[0]
return [(form_interface, field, mode) for field, mode in kw.items()]


class ModePlugin(OmittedPlugin):
key = MODES_KEY


class widget(MetadataDictDirective):
"""Directive used to set the widget for one or more fields
"""
key = WIDGETS_KEY

def factory(self, **kw):
widgets = {}
for field_name, widget in kw.items():
if not isinstance(widget, basestring):
widget = "%s.%s" % (widget.__module__, widget.__name__)
widgets[field_name] = widget
return widgets


class WidgetPlugin(DictCheckerPlugin):
key = WIDGETS_KEY


class order_before(MetadataListDirective):
"""Directive used to order one field before another
"""
key = ORDER_KEY

def factory(self, **kw):
return [(field_name, 'before', relative_to) for field_name, relative_to in kw.items()]


class order_after(MetadataListDirective):
"""Directive used to order one field after another
"""
key = ORDER_KEY

def factory(self, **kw):
return [(field_name, 'after', relative_to) for field_name, relative_to in kw.items()]


class OrderPlugin(ListCheckerPlugin):
key = ORDER_KEY

def fieldNames(self):
if self.value is None:
return
for fieldName, _, _ in self.value:
yield fieldName


class read_permission(MetadataDictDirective):
"""Directive used to set a field read permission
"""
key = READ_PERMISSIONS_KEY

def factory(self, **kw):
return kw


class write_permission(read_permission):
"""Directive used to set a field write permission
"""
key = WRITE_PERMISSIONS_KEY


class ReadPermissionsPlugin(DictCheckerPlugin):
key = READ_PERMISSIONS_KEY


class WritePermissionsPlugin(DictCheckerPlugin):
key = WRITE_PERMISSIONS_KEY
84 changes: 84 additions & 0 deletions plone/autoform/directives.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
Form directives
---------------

In addition to using XML, the tagged values used to control autoform's behavior
can instead be set up using "directives" called while defining a schema in
Python.

Below is an example that exercises the various directives::

from z3c.form.interfaces import IEditForm
from plone.supermodel import model
from plone.autoform import directives as form
from plone.app.z3cform.wysiwyg import WysiwygFieldWidget

class IMySchema(model.Schema):

# Add a new fieldset and put the 'footer' and 'dummy' fields in it.
# If the same fieldset is defined multiple times, the definitions
# will be merged, with the label from the first fieldset taking
# precedence.

model.fieldset('extra',
label=u"Extra info",
fields=['footer', 'dummy']
)

title = schema.TextLine(
title=u"Title"
)

summary = schema.Text(
title=u"Summary",
description=u"Summary of the body",
readonly=True
)

form.widget(body='plone.app.z3cform.wysiwyg.WysiwygFieldWidget')
model.primary('body')
body = schema.Text(
title=u"Body text",
required=False,
default=u"Body text goes here"
)


form.widget(footer=WysiwygFieldWidget)
footer = schema.Text(
title=u"Footer text",
required=False
)

form.omitted('dummy')
dummy = schema.Text(
title=u"Dummy"
)

form.omitted('edit_only')
form.no_omit(IEditForm, 'edit_only')
edit_only = schema.TextLine(
title = u'Only included on edit forms',
)

form.mode(secret='hidden')
form.mode(IEditForm, secret='input')
secret = schema.TextLine(
title=u"Secret",
default=u"Secret stuff (except on edit forms)"
)

form.order_before(not_last='summary')
not_last = schema.TextLine(
title=u"Not last",
)


Here, we have placed the directives immediately before the fields they
affect, but they could be placed anywhere in the interface body. All the
directives can take multiple values, usually in the form
``fieldname='value'``.

The ``omitted()``, ``no_omit``, and ``primary()`` directives take a list of
field names instead. The ``widget()`` directive allows widgets to be set either
as a dotted name, or using an imported field widget factory. The
``order_before()`` directive has a corresponding ``order_after()`` directive.
Loading

0 comments on commit 689cdfb

Please sign in to comment.