Skip to content
This repository has been archived by the owner on Apr 9, 2019. It is now read-only.

Commit

Permalink
implements -> implementer
Browse files Browse the repository at this point in the history
  • Loading branch information
tomgross committed Jun 2, 2017
1 parent fbfcda0 commit 6bd6d81
Show file tree
Hide file tree
Showing 10 changed files with 39 additions and 178 deletions.
2 changes: 1 addition & 1 deletion src/plone/z3cform/crud/README.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ First, let's define an interface and a class to play with:
... name = schema.TextLine()
... age = schema.Int()

>>> @interface.implementer(IPerson)
>>> class Person(object):
... interface.implements(IPerson)
... def __init__(self, name=None, age=None):
... self.name, self.age = name, age
... def __repr__(self):
Expand Down
2 changes: 1 addition & 1 deletion src/plone/z3cform/crud/crud.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ def link(item, field):
"""


@interface.implementer(ICrudForm)
class AbstractCrudForm(object):
"""The AbstractCrudForm is not a form but implements methods
necessary to comply with the ``ICrudForm`` interface:
Expand All @@ -79,7 +80,6 @@ class AbstractCrudForm(object):
>>> verifyClass(ICrudForm, AbstractCrudForm)
True
"""
interface.implements(ICrudForm)

update_schema = None
view_schema = None
Expand Down
13 changes: 7 additions & 6 deletions src/plone/z3cform/fieldsets/README.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,16 @@ To use this, you have to mix it into another form as the *first* base class:

>>> from zope.annotation import IAttributeAnnotatable
>>> from z3c.form import form, field, tests, group
>>> from zope.interface import Interface, implements
>>> from zope.interface import Interface, implementer
>>> from zope import schema

>>> class ITest(Interface):
... title = schema.TextLine(title=u"Title")

>>> @implementer(ITest, IAttributeAnnotatable)
>>> class Test(object):
... # avoid needing an acl_users for this test in Zope 2.10
... __allow_access_to_unprotected_subobjects__ = 1
... implements(ITest, IAttributeAnnotatable)
... title = u""
... def getPhysicalRoot(self): # needed for template to acquire REQUEST in Zope 2.10
... return self
Expand Down Expand Up @@ -61,7 +61,8 @@ convenience base class to make it easier to manipulate the fields of the
form.

>>> from plone.z3cform.fieldsets.interfaces import IFormExtender
>>> from zope.component import adapts, provideAdapter
>>> from zope.component import adapter
>>> from zope.component import provideAdapter

>>> class IExtraBehavior(Interface):
... foo = schema.TextLine(title=u"Foo")
Expand All @@ -75,9 +76,9 @@ One plausible implementation is to use an annotation to store this data.
>>> from zope.annotation import factory
>>> from zope.annotation.attribute import AttributeAnnotations
>>> from persistent import Persistent
>>> @implementer(IExtraBehavior)
>>> @adapter(Test)
>>> class ExtraBehavior(Persistent):
... implements(IExtraBehavior)
... adapts(Test)
...
... foo = u""
... bar = u""
Expand All @@ -93,8 +94,8 @@ We can now write the extender. The base class gives us some helper methods
to add, remove and move fields. Here, we do a bit of unnecessary work just
to exercise these methods.

>>> @adapter(Test, TestRequest, TestForm) # context, request, form
>>> class ExtraBehaviorExtender(extensible.FormExtender):
... adapts(Test, TestRequest, TestForm) # context, request, form
...
... def __init__(self, context, request, form):
... self.context = context
Expand Down
8 changes: 4 additions & 4 deletions src/plone/z3cform/inputs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ Then we create and register a simple form that expects unicode text input:
... text = schema.TextLine(title=u"Text")

>>> from z3c.form.interfaces import IFieldsForm
>>> from zope.interface import implements
>>> from zope.interface import implementer

>>> @implementer(IFieldsForm)
>>> class MyForm(form.Form):
... implements(IFieldsForm)
... fields = field.Fields(MySchema)
... ignoreContext = True # don't use context to get widget data
...
Expand All @@ -52,13 +52,13 @@ Then we create and register a simple form that expects unicode text input:
For our context, we define a class that inherits from Acquisition.

>>> from Acquisition import Implicit
>>> @implementer(Interface)
>>> class Bar(Implicit):
... __allow_access_to_unprotected_subobjects__ = 1
... implements(Interface)

Let's now look this up with some form data that is not encoded:

>>> from zope.interface import Interface, implements
>>> from zope.interface import Interface
>>> from zope.component import getMultiAdapter

>>> context = Bar()
Expand Down
101 changes: 3 additions & 98 deletions src/plone/z3cform/layout.py
Original file line number Diff line number Diff line change
@@ -1,98 +1,3 @@
from Acquisition import aq_inner
from Products.Five import BrowserView
from Products.Five.browser.pagetemplatefile import BoundPageTemplate
from plone.z3cform import interfaces
from plone.z3cform import z2
from zope.pagetemplate.interfaces import IPageTemplate
import z3c.form.interfaces
import zope.component
import zope.interface


class FormWrapper(BrowserView):
"""Use this as a base class for your Five view and override the
'form' attribute with your z3c.form form class. Your form will
then be rendered in the contents area of a layout template, the
'index' attribute.
Use the 'wrap' function in this module if you don't like defining
classes.
"""
zope.interface.implements(interfaces.IFormWrapper)

form = None # override this with a form class.
index = None # override with a page template, or rely on an adapter
request_layer = z3c.form.interfaces.IFormLayer

def __init__(self, context, request):
super(FormWrapper, self).__init__(context, request)
if self.form is not None:
self.form_instance = self.form(
aq_inner(self.context), self.request)
self.form_instance.__name__ = self.__name__

def update(self):
"""On update, we switch on the zope3 request, needed to work with
our z3c form. We update here the wrapped form.
Override this method if you have more than one form.
"""

if not z3c.form.interfaces.ISubForm.providedBy(self.form_instance):
zope.interface.alsoProvides(
self.form_instance,
interfaces.IWrappedForm)

z2.switch_on(self, request_layer=self.request_layer)
self.form_instance.update()

# If a form action redirected, don't render the wrapped form
if self.request.response.getStatus() in (302, 303):
self.contents = ""
return

# A z3c.form.form.AddForm does a redirect in its render method.
# So we have to render the form to see if we have a redirection.
# In the case of redirection, we don't render the layout at all.
self.contents = self.form_instance.render()

def __call__(self):
"""We use the update/render pattern. If a redirect happens in the
meantime, we simply skip the rendering.
"""
self.update()
return self.render()

def render(self):
"""This method renders the outer skeleton template, which in
turn calls the 'contents' method below.
We use an indirection to 'self.index' here to allow users to
override the skeleton template through the 'browser' zcml
directive. If no index template is set, we look up a an adapter from
(self, request) to IPageTemplate and use that instead.
"""
if self.request.response.getStatus() in (302, 303):
return u""
if self.index is None:
template = zope.component.getMultiAdapter(
(self, self.request), IPageTemplate)
return BoundPageTemplate(template, self)()
return self.index()

def label(self):
"""Override this method to use a different way of acquiring a
label or title for your page. Overriding this with a simple
attribute works as well.
"""
return self.form_instance.label


def wrap_form(form, __wrapper_class=FormWrapper, **kwargs):
class MyFormWrapper(__wrapper_class):
pass
assert z3c.form.interfaces.IForm.implementedBy(form)
MyFormWrapper.form = form
for name, value in kwargs.items():
setattr(MyFormWrapper, name, value)
return MyFormWrapper
# BBB
def wrap_form(form, __wrapper_class=None, **kwargs):
return form
9 changes: 4 additions & 5 deletions src/plone/z3cform/layout.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,8 @@ Then we create a simple form:
... age = schema.Int(title=u"Age")

>>> from z3c.form.interfaces import IFieldsForm
>>> from zope.interface import implements
>>> @implementer(IFieldsForm)
>>> class MyForm(form.Form):
... implements(IFieldsForm)
... fields = field.Fields(MySchema)
... ignoreContext = True # don't use context to get widget data
...
Expand All @@ -59,6 +58,7 @@ Then we create a simple form:
>>> from zope.component import provideAdapter
>>> from zope.publisher.interfaces.browser import IBrowserRequest
>>> from zope.interface import Interface
>>> from zope.interface import implementer

>>> provideAdapter(adapts=(Interface, IBrowserRequest),
... provides=Interface,
Expand All @@ -70,9 +70,9 @@ This is to satisfy permission checking later on, and it'll allow the
layout view to call ``aq_inner`` on the context:

>>> from Acquisition import Implicit
>>> @implementer(Interface)
>>> class Bar(Implicit):
... __allow_access_to_unprotected_subobjects__ = 1
... implements(Interface)

Let's verify that worked:

Expand Down Expand Up @@ -136,7 +136,7 @@ label from the form instance:
Send bad data to the form:

>>> request = make_request(form={'form.widgets.age': '12.1'})
>>> from zope.interface import Interface, implements
>>> from zope.interface import Interface
>>> formWrapper = getMultiAdapter((context, request), name=u"test-form")
>>> form = formWrapper.form(context, request)
>>> form.update()
Expand All @@ -149,7 +149,6 @@ Send bad data to the form:
And then send correct data to the form:

>>> request = make_request(form={'form.widgets.age': '12'})
>>> from zope.interface import Interface, implements
>>> from Acquisition import Implicit
>>> formWrapper = getMultiAdapter((context, request), name=u"test-form")
>>> form = formWrapper.form(context, request)
Expand Down
3 changes: 2 additions & 1 deletion src/plone/z3cform/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@
import unittest


@interface.implementer(IFormLayer)
class TestRequest(TestRequest):
interface.implements(IFormLayer)
""" A test request which implements IFormLayer """


def create_eventlog(event=interface.Interface):
Expand Down
2 changes: 1 addition & 1 deletion src/plone/z3cform/textlines/textlines.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@
class ITextLinesWidget(interfaces.IWidget):
"""Text lines widget."""

@zope.interface.implementerOnly(ITextLinesWidget)
class TextLinesWidget(textarea.TextAreaWidget):
"""Input type sequence widget implementation."""
zope.interface.implementsOnly(ITextLinesWidget)

def TextLinesFieldWidget(field, request):
"""IFieldWidget factory for TextLinesWidget."""
Expand Down
36 changes: 6 additions & 30 deletions src/plone/z3cform/traversal.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,39 +5,22 @@
from plone.z3cform.interfaces import IFormWrapper
from z3c.form import util
from z3c.form.interfaces import IForm
from zope.component import adapts
from zope.component import adapter
from zope.interface import alsoProvides
from zope.interface import implements
from zope.interface import implementer
from zope.interface import noLongerProvides
from zope.publisher.interfaces.browser import IBrowserRequest
from zope.traversing.interfaces import ITraversable
from zope.traversing.interfaces import TraversalError


@implementer(ITraversable)
@adapter(IForm, IBrowserRequest)
class FormWidgetTraversal(object):
"""Allow traversal to widgets via the ++widget++ namespace. The context
is the from itself (used when the layout wrapper view is not used).
Note that to support security in Zope 2.10, the widget being traversed to
must have an __of__ method, i.e. it must support acquisition. The easiest
way to do that, is to mix in Acquisition.Explicit. The acquisition parent
will be the layout form wrapper view.
In Zope 2.12, this is not necessary, because we also set the __parent__
pointer of the returned widget to be the traversal context.
Unfortunately, if you mix in Acquisition.Explicit in Zope 2.12 *and* the
class implements IAcquirer, Zope may complain because the view probably
does *not* implement acquisition (in Zope 2.12, views no longer mix in
Acquisiton.Explicit). To support both Zope 2.10 and Zope 2.12, you will
need to cheat and mix in Acquisition.Explicit, but use implementsOnly()
or some other mechanism to make sure the instance does not provide
IAcquirer.
"""

implements(ITraversable)
adapts(IForm, IBrowserRequest)

def __init__(self, context, request=None):
self.context = context
self.request = request
Expand Down Expand Up @@ -105,10 +88,7 @@ def traverse(self, name, ignored):
target = new_target
# subform-containing widget, only option is to go into subform
elif hasattr(target, 'subform'):
if part == 'widgets':
target = target.subform
else:
target = None
target = target.subform if part == 'widgets' else None
else:
raise TraversalError(
'Cannot traverse through ' +
Expand All @@ -118,10 +98,7 @@ def traverse(self, name, ignored):
if target is None:
raise TraversalError(part)

# Make the parent of the widget the traversal parent.
# This is required for security to work in Zope 2.12
if target is not None:
target.__parent__ = aq_inner(self.context)
return target
raise TraversalError(name)

Expand All @@ -137,15 +114,14 @@ def _form_traverse(self, form, name):
return group.widgets.get(name)


@adapter(IFormWrapper, IBrowserRequest)
class WrapperWidgetTraversal(FormWidgetTraversal):
"""Allow traversal to widgets via the ++widget++ namespace. The context
is the from layout wrapper.
The caveat about security above still applies!
"""

adapts(IFormWrapper, IBrowserRequest)

def _prepareForm(self):
form = self.context.form_instance
z2.switch_on(self.context, request_layer=self.context.request_layer)
Expand Down

0 comments on commit 6bd6d81

Please sign in to comment.