Skip to content

Commit

Permalink
Merge pull request #8 from plone/python3
Browse files Browse the repository at this point in the history
fix tests in py3
  • Loading branch information
pbauer committed Sep 21, 2018
2 parents a2bc18b + dc12de8 commit 0bd184d
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 45 deletions.
3 changes: 2 additions & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ New features:

Bug fixes:

- *add item here*
- Fix tests in py3.
[pbauer]


2.0.7 (2018-01-30)
Expand Down
86 changes: 45 additions & 41 deletions plone/contentrules/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ First, we create some rule elements.

Lets start with some basic imports:

>>> from zope.interface import Interface, implements
>>> from zope.component import adapts
>>> from zope.interface import Interface, implementer
>>> from zope.component import adapter
>>> from zope.component import getUtility, getAllUtilitiesRegisteredFor
>>> from zope import schema

Expand All @@ -56,8 +56,8 @@ and summary properties come from IRuleElementData and are used by the
user interface to discover the edit view and present a title and summery
to the user:

>>> class MoveToFolderAction(Persistent):
... implements(IMoveToFolderAction, IRuleElementData)
>>> @implementer(IMoveToFolderAction, IRuleElementData)
... class MoveToFolderAction(Persistent):
... targetFolder = ''
... element = "test.moveToFolder"
... @property
Expand All @@ -71,15 +71,15 @@ adaptable to IExecutable. This should be a multi-adapter from
>>> from plone.contentrules.rule.interfaces import IExecutable
>>> from zope.component.interfaces import IObjectEvent

>>> class MoveToFolderExecutor(object):
... implements(IExecutable)
... adapts(Interface, IMoveToFolderAction, IObjectEvent)
>>> @implementer(IExecutable)
... @adapter(Interface, IMoveToFolderAction, IObjectEvent)
... class MoveToFolderExecutor(object):
... def __init__(self, context, element, event):
... self.context = context
... self.element = element
... self.event = event
... def __call__(self):
... print "Tried to execute MoveToFolderExecutor, but not implemented"
... print("Tried to execute MoveToFolderExecutor, but not implemented")
... return True

>>> provideAdapter(MoveToFolderExecutor)
Expand Down Expand Up @@ -127,8 +127,8 @@ Again, we have to define an interface for the logger action:

A factory class holding configuration data:

>>> class LoggerAction(Persistent):
... implements(ILoggerAction, IRuleElementData)
>>> @implementer(ILoggerAction, IRuleElementData)
... class LoggerAction(Persistent):
... loggingLevel = ''
... targetLogger = ''
... message = ''
Expand All @@ -138,9 +138,9 @@ A factory class holding configuration data:
As well as the executor that does the actual logging, capable of being adapted
to IExecutable. In this case, it will adapt any context and any event.

>>> class LoggerActionExecutor(object):
... implements(IExecutable)
... adapts(Interface, ILoggerAction, Interface)
>>> @implementer(IExecutable)
... @adapter(Interface, ILoggerAction, Interface)
... class LoggerActionExecutor(object):
...
... def __init__(self, context, element, event):
... self.context = context
Expand Down Expand Up @@ -182,17 +182,17 @@ a given interface.
>>> class IInterfaceCondition(Interface):
... iface = Attribute(u'the interface')

>>> class InterfaceCondition(object):
... implements (IInterfaceCondition, IRuleElementData)
>>> @implementer (IInterfaceCondition, IRuleElementData)
... class InterfaceCondition(object):
... iface = None
... element = "test.interface"
... @property
... def summary(self):
... return "Check for interface " + self.iface.__identifier__

>>> class InterfaceConditionExecutor(object):
... implements(IExecutable)
... adapts(Interface, IInterfaceCondition, Interface)
>>> @implementer(IExecutable)
... @adapter(Interface, IInterfaceCondition, Interface)
... class InterfaceConditionExecutor(object):
...
... def __init__(self, context, element, event):
... self.context = context
Expand Down Expand Up @@ -226,22 +226,22 @@ present:
>>> class IHaltExecutionAction(Interface):
... pass

>>> class HaltExecutionAction(Persistent):
... implements (IHaltExecutionAction, IRuleElementData)
>>> @implementer (IHaltExecutionAction, IRuleElementData)
... class HaltExecutionAction(Persistent):
... element = "test.halt"
... summary = "Halt!"

>>> class HaltExecutionExecutor(object):
... implements(IExecutable)
... adapts(Interface, IHaltExecutionAction, Interface)
>>> @implementer(IExecutable)
... @adapter(Interface, IHaltExecutionAction, Interface)
... class HaltExecutionExecutor(object):
... # Above: the second "Interface" causes this
... # element to be available for every event
... def __init__(self, context, element, event):
... self.context = context
... self.element = element
... self.event = event
... def __call__(self):
... print "Rule Execution aborted at HaltAction"
... print("Rule Execution aborted at HaltAction")
... return False # False = Stop Execution! This is the payload.

>>> provideAdapter(HaltExecutionExecutor)
Expand Down Expand Up @@ -273,8 +273,9 @@ itself implies IAttributeAnnotatable.
>>> from plone.contentrules.engine.interfaces import IRuleAssignable
>>> class IMyContent(IRuleAssignable):
... pass
>>> class MyContent(object):
... implements(IMyContent)
>>> @implementer(IMyContent)
... class MyContent(object):
... pass

>>> context = MyContent()

Expand Down Expand Up @@ -459,8 +460,9 @@ higher up. Rules that are assigned not to bubble will not be executed.

Now consider what would happen if the interface condition failed:

>>> class OtherContent(object):
... implements(IRuleAssignable)
>>> @implementer(IRuleAssignable)
... class OtherContent(object):
... pass
>>> otherContext = OtherContent()

>>> otherManager = IRuleAssignmentManager(otherContext)
Expand Down Expand Up @@ -522,11 +524,12 @@ An element for IObjectCreatedEvent:

>>> class IObjectCreatedSpecificAction(Interface):
... pass
>>> class ObjectCreatedSpecificAction(Persistent):
... implements (IObjectCreatedSpecificAction)
>>> class ObjectCreatedExecutor(object):
... implements(IExecutable)
... adapts(Interface, IObjectCreatedSpecificAction, IObjectCreatedEvent) #!
>>> @implementer (IObjectCreatedSpecificAction)
... class ObjectCreatedSpecificAction(Persistent):
... pass
>>> @implementer(IExecutable)
... @adapter(Interface, IObjectCreatedSpecificAction, IObjectCreatedEvent) #!
... class ObjectCreatedExecutor(object):
... def __init__(self, context, element, event):
... self.context = context
... self.element = element
Expand All @@ -552,11 +555,12 @@ An element for IObjectCopiedEvent:

>>> class IObjectCopiedSpecificAction(Interface):
... pass
>>> class ObjectCopiedSpecificAction(Persistent):
... implements (IObjectCopiedSpecificAction)
>>> class ObjectCopiedExecutor(object):
... implements(IExecutable)
... adapts(Interface, IObjectCopiedSpecificAction, IObjectCopiedEvent) #!
>>> @implementer (IObjectCopiedSpecificAction)
... class ObjectCopiedSpecificAction(Persistent):
... pass
>>> @implementer(IExecutable)
... @adapter(Interface, IObjectCopiedSpecificAction, IObjectCopiedEvent) #!
... class ObjectCopiedExecutor(object):
... def __init__(self, context, element, event):
... self.context = context
... self.element = element
Expand All @@ -579,15 +583,15 @@ An element for IObjectCopiedEvent:

All elements so far, applicable for object events:

>>> map(lambda x: x.title, utils.allAvailableActions(IObjectEvent))
>>> list(map(lambda x: x.title, utils.allAvailableActions(IObjectEvent)))
['Move To Folder', 'Log Event', 'Halt Rule Execution']

For a more specific event, we may get more elements (i.e. those that also
apply to more general events):

>>> map(lambda x: x.title, utils.allAvailableActions(IObjectCopiedEvent))
>>> list(map(lambda x: x.title, utils.allAvailableActions(IObjectCopiedEvent)))
['Move To Folder', 'Log Event', 'Halt Rule Execution', 'Object Created specific action', 'Object Copied Specific Action']
>>> map(lambda x: x.title, utils.allAvailableActions(IObjectCreatedEvent))
>>> list(map(lambda x: x.title, utils.allAvailableActions(IObjectCreatedEvent)))
['Move To Folder', 'Log Event', 'Halt Rule Execution', 'Object Created specific action']

Filtering for specific events:
Expand Down
18 changes: 16 additions & 2 deletions plone/contentrules/tests.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import doctest
import re
import six
import unittest

from zope.component.testing import PlacelessSetup as CAPlacelessSetup
Expand All @@ -8,6 +10,14 @@
optionflags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS


class Py23DocChecker(doctest.OutputChecker):

def check_output(self, want, got, optionflags):
if not six.PY2:
want = re.sub("u'(.*?)'", "'\\1'", want)
return doctest.OutputChecker.check_output(self, want, got, optionflags)


class PlacelessSetup(CAPlacelessSetup, ContainerPlacelessSetup):

def setUp(self, doctesttest=None):
Expand Down Expand Up @@ -36,10 +46,14 @@ def test_suite():
'README.rst',
setUp=configurationSetUp,
tearDown=configurationTearDown,
optionflags=optionflags),
optionflags=optionflags,
checker=Py23DocChecker(),
),
doctest.DocFileSuite(
'zcml.rst',
setUp=configurationSetUp,
tearDown=configurationTearDown,
optionflags=optionflags),
optionflags=optionflags,
checker=Py23DocChecker(),
),
))
3 changes: 2 additions & 1 deletion plone/contentrules/zcml.rst
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ Here is how we would register these in ZCML:
... """

>>> from zope.configuration.xmlconfig import xmlconfig
>>> from StringIO import StringIO
>>> import six
>>> from six import StringIO

First, we need to make sure the ZCML directives are defined:

Expand Down
3 changes: 3 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,15 @@
"Framework :: Plone :: 4.3",
"Framework :: Plone :: 5.0",
"Framework :: Plone :: 5.1",
"Framework :: Plone :: 5.2",
"Framework :: Zope2",
"License :: OSI Approved :: GNU General Public License v2 (GPLv2)",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 2.6",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
],
keywords='Plone content rules events',
author='Plone Foundation',
Expand Down

0 comments on commit 0bd184d

Please sign in to comment.