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

Commit

Permalink
Python 3 compatibility: use the adapter and implementer decorators
Browse files Browse the repository at this point in the history
  • Loading branch information
ale-rt committed Feb 21, 2018
1 parent 7f3a742 commit b882647
Show file tree
Hide file tree
Showing 11 changed files with 81 additions and 74 deletions.
3 changes: 2 additions & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ Changelog

Bug fixes:

- * Add item here *
- Python 3 compatibility: use the adapter and implementer decorators
[ale-rt]

New features:

Expand Down
4 changes: 2 additions & 2 deletions 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()

>>> class Person(object):
... interface.implements(IPerson)
>>> @interface.implementer(IPerson)
... class Person(object):
... 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
30 changes: 17 additions & 13 deletions src/plone/z3cform/fieldsets/README.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,18 @@ 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
>>> from zope.interface import implementer
>>> from zope import schema

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

>>> class Test(object):
>>> @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,24 +63,26 @@ 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")
... bar = schema.TextLine(title=u"Bar")
... baz = schema.TextLine(title=u"Baz")
... fub = schema.TextLine(title=u"Fub")
... qux = schema.TextLine(title=u"Qux")

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
>>> class ExtraBehavior(Persistent):
... implements(IExtraBehavior)
... adapts(Test)
...
>>> @implementer(IExtraBehavior)
... @adapter(Test)
... class ExtraBehavior(Persistent):
...
...
... foo = u""
... bar = u""
... baz = u""
Expand All @@ -92,9 +96,9 @@ One plausible implementation is to use an annotation to store this data.
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.
>>> class ExtraBehaviorExtender(extensible.FormExtender):
... adapts(Test, TestRequest, TestForm) # context, request, form

>>> @adapter(Test, TestRequest, TestForm) # context, request, form
... class ExtraBehaviorExtender(extensible.FormExtender):
...
... def __init__(self, context, request, form):
... self.context = context
Expand Down
14 changes: 7 additions & 7 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

>>> class MyForm(form.Form):
... implements(IFieldsForm)
>>> @implementer(IFieldsForm)
... class MyForm(form.Form):
... fields = field.Fields(MySchema)
... ignoreContext = True # don't use context to get widget data
...
Expand All @@ -52,15 +52,15 @@ 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
>>> class Bar(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()
>>> request = make_request(form={'form.widgets.text': 'foo'})

Expand Down
2 changes: 1 addition & 1 deletion src/plone/z3cform/layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import zope.interface


@zope.interface.implementer(interfaces.IFormWrapper)
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
Expand All @@ -18,7 +19,6 @@ class FormWrapper(BrowserView):
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
Expand Down
14 changes: 7 additions & 7 deletions src/plone/z3cform/layout.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ Then we create a simple form:
... age = schema.Int(title=u"Age")

>>> from z3c.form.interfaces import IFieldsForm
>>> from zope.interface import implements
>>> class MyForm(form.Form):
... implements(IFieldsForm)
>>> from zope.interface import implementer
>>> @implementer(IFieldsForm)
... class MyForm(form.Form):
... fields = field.Fields(MySchema)
... ignoreContext = True # don't use context to get widget data
...
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
>>> class Bar(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,7 @@ 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 zope.interface import Interface
>>> from Acquisition import Implicit
>>> formWrapper = getMultiAdapter((context, request), name=u"test-form")
>>> form = formWrapper.form(context, request)
Expand Down
4 changes: 2 additions & 2 deletions src/plone/z3cform/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
import unittest


@interface.implementer(IFormLayer)
class TestRequest(TestRequest):
interface.implements(IFormLayer)

pass

def create_eventlog(event=interface.Interface):
value = []
Expand Down
22 changes: 13 additions & 9 deletions src/plone/z3cform/textlines/textlines.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import zope.interface
import zope.schema.interfaces


try:
# z3c.form 2.0 or later
from z3c.form.browser.textlines import TextLinesFieldWidget
Expand Down Expand Up @@ -53,12 +54,13 @@ def TextLinesFieldWidgetFactory(field, value_type, request):
"""IFieldWidget factory for TextLinesWidget."""
return TextLinesFieldWidget(field, request)

@zope.component.adapter(
zope.schema.interfaces.ISequence,
ITextLinesWidget,
)
class TextLinesConverter(converter.BaseDataConverter):
"""Data converter for ITextLinesWidget."""

zope.component.adapts(
zope.schema.interfaces.ISequence, ITextLinesWidget)

def toWidgetValue(self, value):
"""Convert from text lines to HTML representation."""
# if the value is the missing value, then an empty list is
Expand All @@ -82,12 +84,13 @@ def toFieldValue(self, value):
# additional


@zope.component.adapter(
zope.schema.interfaces.ISet,
ITextLinesWidget,
)
class TextLinesSetConverter(TextLinesConverter):
"""Data converter for ITextLinesWidget operating on a set."""

zope.component.adapts(
zope.schema.interfaces.ISet, ITextLinesWidget)

def toWidgetValue(self, value):
"""Convert from text lines to HTML representation."""
# if the value is the missing value, then an empty list is produced.
Expand All @@ -96,12 +99,13 @@ def toWidgetValue(self, value):
return u'\n'.join(unicode(v) for v in sorted(value))


@zope.component.adapter(
zope.schema.interfaces.IFrozenSet,
ITextLinesWidget,
)
class TextLinesFrozenSetConverter(TextLinesConverter):
"""Data converter for ITextLinesWidget operating on a frozenset."""

zope.component.adapts(
zope.schema.interfaces.IFrozenSet, ITextLinesWidget)

def toWidgetValue(self, value):
"""Convert from text lines to HTML representation."""
# if the value is the missing value, then an empty list is produced.
Expand Down
12 changes: 5 additions & 7 deletions src/plone/z3cform/traversal.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,17 @@
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


@adapter(IForm, IBrowserRequest)
@implementer(ITraversable)
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).
Expand All @@ -35,9 +37,6 @@ class implements IAcquirer, Zope may complain because the view probably
IAcquirer.
"""

implements(ITraversable)
adapts(IForm, IBrowserRequest)

def __init__(self, context, request=None):
self.context = context
self.request = request
Expand Down Expand Up @@ -137,15 +136,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
Loading

0 comments on commit b882647

Please sign in to comment.