diff --git a/CHANGES.rst b/CHANGES.rst index ccc5633..6f72879 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -6,7 +6,8 @@ Changelog Bug fixes: -- * Add item here * +- Python 3 compatibility: use the adapter and implementer decorators + [ale-rt] New features: diff --git a/src/plone/z3cform/crud/README.txt b/src/plone/z3cform/crud/README.txt index d1ec103..99b99d7 100644 --- a/src/plone/z3cform/crud/README.txt +++ b/src/plone/z3cform/crud/README.txt @@ -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): diff --git a/src/plone/z3cform/crud/crud.py b/src/plone/z3cform/crud/crud.py index 74f8a9a..901f00c 100644 --- a/src/plone/z3cform/crud/crud.py +++ b/src/plone/z3cform/crud/crud.py @@ -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: @@ -79,7 +80,6 @@ class AbstractCrudForm(object): >>> verifyClass(ICrudForm, AbstractCrudForm) True """ - interface.implements(ICrudForm) update_schema = None view_schema = None diff --git a/src/plone/z3cform/fieldsets/README.txt b/src/plone/z3cform/fieldsets/README.txt index 6ecff37..c17da29 100644 --- a/src/plone/z3cform/fieldsets/README.txt +++ b/src/plone/z3cform/fieldsets/README.txt @@ -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 @@ -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"" @@ -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 diff --git a/src/plone/z3cform/inputs.txt b/src/plone/z3cform/inputs.txt index f44abcf..5f6c89c 100644 --- a/src/plone/z3cform/inputs.txt +++ b/src/plone/z3cform/inputs.txt @@ -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 ... @@ -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'}) diff --git a/src/plone/z3cform/layout.py b/src/plone/z3cform/layout.py index 6752c7f..ffbe314 100644 --- a/src/plone/z3cform/layout.py +++ b/src/plone/z3cform/layout.py @@ -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 @@ -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 diff --git a/src/plone/z3cform/layout.txt b/src/plone/z3cform/layout.txt index bcf9f58..e1faa70 100644 --- a/src/plone/z3cform/layout.txt +++ b/src/plone/z3cform/layout.txt @@ -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 ... @@ -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: @@ -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() @@ -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) diff --git a/src/plone/z3cform/tests.py b/src/plone/z3cform/tests.py index 1f92eca..799c459 100644 --- a/src/plone/z3cform/tests.py +++ b/src/plone/z3cform/tests.py @@ -11,9 +11,9 @@ import unittest +@interface.implementer(IFormLayer) class TestRequest(TestRequest): - interface.implements(IFormLayer) - + pass def create_eventlog(event=interface.Interface): value = [] diff --git a/src/plone/z3cform/textlines/textlines.py b/src/plone/z3cform/textlines/textlines.py index 6395ca9..85c6304 100644 --- a/src/plone/z3cform/textlines/textlines.py +++ b/src/plone/z3cform/textlines/textlines.py @@ -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 @@ -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 @@ -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. @@ -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. diff --git a/src/plone/z3cform/traversal.py b/src/plone/z3cform/traversal.py index 793a152..305740e 100644 --- a/src/plone/z3cform/traversal.py +++ b/src/plone/z3cform/traversal.py @@ -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). @@ -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 @@ -137,6 +136,7 @@ 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. @@ -144,8 +144,6 @@ class WrapperWidgetTraversal(FormWidgetTraversal): 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) diff --git a/src/plone/z3cform/traversal.txt b/src/plone/z3cform/traversal.txt index 807ddcc..281aa17 100644 --- a/src/plone/z3cform/traversal.txt +++ b/src/plone/z3cform/traversal.txt @@ -40,11 +40,11 @@ First, we create a simple form and context. ... 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) - ... + ... ... def update(self): ... print "Updating test form" ... super(MyForm, self).update() @@ -59,9 +59,9 @@ First, we create a simple form and context. ... name=u"test-form") >>> from Acquisition import Implicit - >>> class Bar(Implicit): + >>> @implementer(Interface,MySchema) + ... class Bar(Implicit): ... __allow_access_to_unprotected_subobjects__ = 1 - ... implements(Interface,MySchema) ... age = 48 And define a helper to make a request and traverse to ++widget++ @@ -110,10 +110,10 @@ contains some values for it. >>> class MyListSchema(interface.Interface): ... list_field = schema.List(__name__='list_field',title=u"Object Field",value_type=schema.Int(title=u"Age")) - >>> class MyListForm(form.Form): - ... implements(IFieldsForm) + >>> @implementer(IFieldsForm) + ... class MyListForm(form.Form): ... fields = field.Fields(MyListSchema) - ... + ... ... def update(self): ... print "Updating test form" ... super(MyListForm, self).update() @@ -123,9 +123,9 @@ contains some values for it. ... factory=MyListForm, ... name=u"test-list-form") - >>> class Bar(Implicit): + >>> @implementer(Interface, MyListSchema) + ... class Bar(Implicit): ... __allow_access_to_unprotected_subobjects__ = 1 - ... implements(Interface, MyListSchema) ... list_field = [48,49,50] Make a request. We should be able to find the list_field @@ -179,10 +179,10 @@ Now create a schema that contains an object with a list of ages within it >>> class MyParentSchema(interface.Interface): ... obj_field = schema.Object(__name__='obj_field',title=u"Object Field",schema=MyListSchema) - >>> class MyParentForm(form.Form): - ... implements(IFieldsForm) + >>> @implementer(IFieldsForm) + ... class MyParentForm(form.Form): ... fields = field.Fields(MyParentSchema) - ... + ... ... def update(self): ... print "Updating test form" ... super(MyParentForm, self).update() @@ -192,14 +192,14 @@ Now create a schema that contains an object with a list of ages within it ... factory=MyParentForm, ... name=u"test-parent-form") - >>> class Baz(Implicit): + >>> @implementer(Interface, MyListSchema) + ... class Baz(Implicit): ... __allow_access_to_unprotected_subobjects__ = 1 - ... implements(Interface, MyListSchema) ... list_field = [48,49,50] - >>> class Bar(Implicit): + >>> @implementer(Interface, MyParentSchema) + ... class Bar(Implicit): ... __allow_access_to_unprotected_subobjects__ = 1 - ... implements(Interface, MyParentSchema) ... obj_field = Baz() @@ -268,12 +268,12 @@ Again, we create a simple form and context. ... 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 - ... + ... ... def update(self): ... print "Updating test form" ... super(MyForm, self).update() @@ -292,9 +292,9 @@ Again, we create a simple form and context. ... name=u"test-form") >>> from Acquisition import Implicit - >>> class Bar(Implicit): + >>> @implementer(Interface) + ... class Bar(Implicit): ... __allow_access_to_unprotected_subobjects__ = 1 - ... implements(Interface) >>> from zope.component import getMultiAdapter >>> context = Bar()