diff --git a/bootstrap.py b/bootstrap.py index ed57894..f9cd227 100644 --- a/bootstrap.py +++ b/bootstrap.py @@ -18,16 +18,17 @@ use the -c option to specify an alternate configuration file. """ +from optparse import OptionParser + import os import shutil import sys import tempfile -from optparse import OptionParser tmpeggs = tempfile.mkdtemp() -usage = '''\ +usage = """\ [DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options] Bootstraps a buildout-based project. @@ -37,28 +38,40 @@ Note that by using --find-links to point to local resources, you can keep this script from going over the network. -''' +""" parser = OptionParser(usage=usage) parser.add_option("-v", "--version", help="use a specific zc.buildout version") -parser.add_option("-t", "--accept-buildout-test-releases", - dest='accept_buildout_test_releases', - action="store_true", default=False, - help=("Normally, if you do not specify a --version, the " - "bootstrap script and buildout gets the newest " - "*final* versions of zc.buildout and its recipes and " - "extensions for you. If you use this flag, " - "bootstrap and buildout will get the newest releases " - "even if they are alphas or betas.")) -parser.add_option("-c", "--config-file", - help=("Specify the path to the buildout configuration " - "file to be used.")) -parser.add_option("-f", "--find-links", - help=("Specify a URL to search for buildout releases")) -parser.add_option("--allow-site-packages", - action="store_true", default=False, - help=("Let bootstrap.py use existing site packages")) +parser.add_option( + "-t", + "--accept-buildout-test-releases", + dest="accept_buildout_test_releases", + action="store_true", + default=False, + help=( + "Normally, if you do not specify a --version, the " + "bootstrap script and buildout gets the newest " + "*final* versions of zc.buildout and its recipes and " + "extensions for you. If you use this flag, " + "bootstrap and buildout will get the newest releases " + "even if they are alphas or betas." + ), +) +parser.add_option( + "-c", + "--config-file", + help=("Specify the path to the buildout configuration " "file to be used."), +) +parser.add_option( + "-f", "--find-links", help=("Specify a URL to search for buildout releases") +) +parser.add_option( + "--allow-site-packages", + action="store_true", + default=False, + help=("Let bootstrap.py use existing site packages"), +) options, args = parser.parse_args() @@ -75,23 +88,25 @@ from urllib2 import urlopen ez = {} -exec(urlopen('https://bootstrap.pypa.io/ez_setup.py').read(), ez) +exec(urlopen("https://bootstrap.pypa.io/ez_setup.py").read(), ez) if not options.allow_site_packages: # ez_setup imports site, which adds site packages - # this will remove them from the path to ensure that incompatible versions + # this will remove them from the path to ensure that incompatible versions # of setuptools are not in the path import site - # inside a virtualenv, there is no 'getsitepackages'. + + # inside a virtualenv, there is no 'getsitepackages'. # We can't remove these reliably - if hasattr(site, 'getsitepackages'): + if hasattr(site, "getsitepackages"): for sitepackage_path in site.getsitepackages(): sys.path[:] = [x for x in sys.path if sitepackage_path not in x] setup_args = dict(to_dir=tmpeggs, download_delay=0) -ez['use_setuptools'](**setup_args) -import setuptools +ez["use_setuptools"](**setup_args) import pkg_resources +import setuptools + # This does not (always?) update the default working set. We will # do it. @@ -104,36 +119,43 @@ ws = pkg_resources.working_set -cmd = [sys.executable, '-c', - 'from setuptools.command.easy_install import main; main()', - '-mZqNxd', tmpeggs] +cmd = [ + sys.executable, + "-c", + "from setuptools.command.easy_install import main; main()", + "-mZqNxd", + tmpeggs, +] find_links = os.environ.get( - 'bootstrap-testing-find-links', - options.find_links or - ('http://downloads.buildout.org/' - if options.accept_buildout_test_releases else None) - ) + "bootstrap-testing-find-links", + options.find_links + or ( + "http://downloads.buildout.org/" + if options.accept_buildout_test_releases + else None + ), +) if find_links: - cmd.extend(['-f', find_links]) + cmd.extend(["-f", find_links]) -setuptools_path = ws.find( - pkg_resources.Requirement.parse('setuptools')).location +setuptools_path = ws.find(pkg_resources.Requirement.parse("setuptools")).location -requirement = 'zc.buildout' +requirement = "zc.buildout" version = options.version if version is None and not options.accept_buildout_test_releases: # Figure out the most recent final version of zc.buildout. import setuptools.package_index - _final_parts = '*final-', '*final' + + _final_parts = "*final-", "*final" def _final_version(parsed_version): for part in parsed_version: - if (part[:1] == '*') and (part not in _final_parts): + if (part[:1] == "*") and (part not in _final_parts): return False return True - index = setuptools.package_index.PackageIndex( - search_path=[setuptools_path]) + + index = setuptools.package_index.PackageIndex(search_path=[setuptools_path]) if find_links: index.add_find_links((find_links,)) req = pkg_resources.Requirement.parse(requirement) @@ -152,13 +174,14 @@ def _final_version(parsed_version): best.sort() version = best[-1].version if version: - requirement = '=='.join((requirement, version)) + requirement = "==".join((requirement, version)) cmd.append(requirement) import subprocess + + if subprocess.call(cmd, env=dict(os.environ, PYTHONPATH=setuptools_path)) != 0: - raise Exception( - "Failed to execute command:\n%s" % repr(cmd)[1:-1]) + raise Exception("Failed to execute command:\n%s" % repr(cmd)[1:-1]) ###################################################################### # Import and run buildout @@ -167,12 +190,13 @@ def _final_version(parsed_version): ws.require(requirement) import zc.buildout.buildout -if not [a for a in args if '=' not in a]: - args.append('bootstrap') + +if not [a for a in args if "=" not in a]: + args.append("bootstrap") # if -c was provided, we push it back into args for buildout' main function if options.config_file is not None: - args[0:0] = ['-c', options.config_file] + args[0:0] = ["-c", options.config_file] zc.buildout.buildout.main(args) shutil.rmtree(tmpeggs) diff --git a/news/71.breaking b/news/71.breaking new file mode 100644 index 0000000..e600182 --- /dev/null +++ b/news/71.breaking @@ -0,0 +1,2 @@ +Code style, use plone.base and remove Archetypes bbb code. +[jensens] diff --git a/plone/__init__.py b/plone/__init__.py index 68c04af..5284146 100644 --- a/plone/__init__.py +++ b/plone/__init__.py @@ -1,2 +1 @@ -# -*- coding: utf-8 -*- -__import__('pkg_resources').declare_namespace(__name__) +__import__("pkg_resources").declare_namespace(__name__) diff --git a/plone/app/__init__.py b/plone/app/__init__.py index 68c04af..5284146 100644 --- a/plone/app/__init__.py +++ b/plone/app/__init__.py @@ -1,2 +1 @@ -# -*- coding: utf-8 -*- -__import__('pkg_resources').declare_namespace(__name__) +__import__("pkg_resources").declare_namespace(__name__) diff --git a/plone/app/contentrules/__init__.py b/plone/app/contentrules/__init__.py index 056463f..8543404 100644 --- a/plone/app/contentrules/__init__.py +++ b/plone/app/contentrules/__init__.py @@ -1,6 +1,5 @@ -# -*- coding: utf-8 -*- # Import PloneMessageFactory to create messages in the plone domain from zope.i18nmessageid import MessageFactory -PloneMessageFactory = MessageFactory('plone') +PloneMessageFactory = MessageFactory("plone") diff --git a/plone/app/contentrules/actions/__init__.py b/plone/app/contentrules/actions/__init__.py index 9089cfe..7693358 100644 --- a/plone/app/contentrules/actions/__init__.py +++ b/plone/app/contentrules/actions/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from plone.app.contentrules.browser.formhelper import AddForm from plone.app.contentrules.browser.formhelper import EditForm from plone.app.uuid.utils import uuidToPhysicalPath @@ -9,33 +8,33 @@ import os -class ContentWrapper(object): +class ContentWrapper: """ The sole purpose of this is to transform target_folder values from UUID to path, which all of content rules expects """ def __init__(self, content): - self.__dict__['content'] = content + self.__dict__["content"] = content @property def target_folder(self): content = self.content - if content.target_folder and content.target_folder[0] == '/': + if content.target_folder and content.target_folder[0] == "/": # need to convert to uuid site = getSite() - site_path = '/'.join(site.getPhysicalPath()) - path = os.path.join(site_path, content.target_folder.lstrip('/')) + site_path = "/".join(site.getPhysicalPath()) + path = os.path.join(site_path, content.target_folder.lstrip("/")) target = site.restrictedTraverse(path, None) if target is not None: return IUUID(target, None) def __getattr__(self, name, default=None): - return getattr(self.__dict__['content'], name, default) + return getattr(self.__dict__["content"], name, default) def __setattr__(self, name, value): - setattr(self.__dict__['content'], name, value) + setattr(self.__dict__["content"], name, value) class ActionAddForm(AddForm): @@ -47,17 +46,16 @@ def create(self, data): is what the z3c form widget uses, to paths. """ a = self.Type() - if data.get('target_folder', None): + if data.get("target_folder", None): site = getSite() - site_path = '/'.join(site.getPhysicalPath()) - path = uuidToPhysicalPath(data['target_folder']) + site_path = "/".join(site.getPhysicalPath()) + path = uuidToPhysicalPath(data["target_folder"]) if path: - data['target_folder'] = path[len(site_path):] + data["target_folder"] = path[len(site_path) :] form.applyChanges(self, a, data) return a class ActionEditForm(EditForm): - def getContent(self): - return ContentWrapper(super(ActionEditForm, self).getContent()) + return ContentWrapper(super().getContent()) diff --git a/plone/app/contentrules/actions/copy.py b/plone/app/contentrules/actions/copy.py index 4157a09..8f00f62 100644 --- a/plone/app/contentrules/actions/copy.py +++ b/plone/app/contentrules/actions/copy.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from Acquisition import aq_base from OFS.event import ObjectClonedEvent from OFS.SimpleItem import SimpleItem @@ -7,10 +6,10 @@ from plone.app.contentrules.actions import ActionEditForm from plone.app.contentrules.browser.formhelper import ContentRuleFormWrapper from plone.app.vocabularies.catalog import CatalogSource +from plone.base.utils import pretty_title_or_id from plone.contentrules.rule.interfaces import IExecutable from plone.contentrules.rule.interfaces import IRuleElementData from Products.CMFCore.utils import getToolByName -from Products.CMFPlone import utils from Products.statusmessages.interfaces import IStatusMessage from ZODB.POSException import ConflictError from zope import schema @@ -30,8 +29,8 @@ class ICopyAction(Interface): """ target_folder = schema.Choice( - title=_(u'Target folder'), - description=_(u'As a path relative to the portal root.'), + title=_("Target folder"), + description=_("As a path relative to the portal root."), required=True, source=CatalogSource(is_folderish=True), ) @@ -39,23 +38,20 @@ class ICopyAction(Interface): @implementer(ICopyAction, IRuleElementData) class CopyAction(SimpleItem): - """The actual persistent implementation of the action element. - """ + """The actual persistent implementation of the action element.""" - target_folder = '' - element = 'plone.actions.Copy' + target_folder = "" + element = "plone.actions.Copy" @property def summary(self): - return _(u'Copy to folder ${folder}.', - mapping=dict(folder=self.target_folder)) + return _("Copy to folder ${folder}.", mapping=dict(folder=self.target_folder)) @adapter(Interface, ICopyAction, Interface) @implementer(IExecutable) -class CopyActionExecutor(object): - """The executor for this action. - """ +class CopyActionExecutor: + """The executor for this action.""" def __init__(self, context, element, event): self.context = context @@ -63,14 +59,14 @@ def __init__(self, context, element, event): self.event = event def __call__(self): - portal_url = getToolByName(self.context, 'portal_url', None) + portal_url = getToolByName(self.context, "portal_url", None) if portal_url is None: return False obj = self.event.object path = self.element.target_folder - if len(path) > 1 and path[0] == '/': + if len(path) > 1 and path[0] == "/": path = path[1:] target = portal_url.getPortalObject().unrestrictedTraverse( str(path), @@ -80,10 +76,7 @@ def __call__(self): if target is None: self.error( obj, - _( - u'Target folder ${target} does not exist.', - mapping={'target': path} - ) + _("Target folder ${target} does not exist.", mapping={"target": path}), ) return False @@ -110,43 +103,45 @@ def __call__(self): obj._postCopy(target, op=0) - OFS.subscribers.compatibilityCall('manage_afterClone', obj, obj) + OFS.subscribers.compatibilityCall("manage_afterClone", obj, obj) notify(ObjectClonedEvent(obj)) return True def error(self, obj, error): - request = getattr(self.context, 'REQUEST', None) + request = getattr(self.context, "REQUEST", None) if request is not None: - title = utils.pretty_title_or_id(obj, obj) + title = pretty_title_or_id(obj, obj) message = _( - u'Unable to copy ${name} as part of content rule ' - u"'copy' action: ${error}", - mapping={'name': title, 'error': error} + "Unable to copy ${name} as part of content rule " + "'copy' action: ${error}", + mapping={"name": title, "error": error}, ) - IStatusMessage(request).addStatusMessage(message, type='error') + IStatusMessage(request).addStatusMessage(message, type="error") def generate_id(self, target, old_id): - taken = getattr(aq_base(target), 'has_key', None) + taken = getattr(aq_base(target), "has_key", None) if taken is None: item_ids = set(target.objectIds()) - def taken(x): return x in item_ids + def taken(x): + return x in item_ids + if not taken(old_id): return old_id idx = 1 - while taken('{0}.{1}'.format(old_id, idx)): + while taken(f"{old_id}.{idx}"): idx += 1 - return '{0}.{1}'.format(old_id, idx) + return f"{old_id}.{idx}" class CopyAddForm(ActionAddForm): - """An add form for move-to-folder actions. - """ + """An add form for move-to-folder actions.""" + schema = ICopyAction - label = _(u'Add Copy Action') - description = _(u'A copy action can copy an object to a different folder.') + label = _("Add Copy Action") + description = _("A copy action can copy an object to a different folder.") Type = CopyAction @@ -159,10 +154,11 @@ class CopyEditForm(ActionEditForm): z3c.form does all the magic here. """ + schema = ICopyAction - label = _(u'Edit Copy Action') - description = _(u'A copy action can copy an object to a different folder.') - form_name = _(u'Configure element') + label = _("Edit Copy Action") + description = _("A copy action can copy an object to a different folder.") + form_name = _("Configure element") class CopyEditFormView(ContentRuleFormWrapper): diff --git a/plone/app/contentrules/actions/delete.py b/plone/app/contentrules/actions/delete.py index 4193b5b..25c8ec9 100644 --- a/plone/app/contentrules/actions/delete.py +++ b/plone/app/contentrules/actions/delete.py @@ -1,12 +1,11 @@ -# -*- coding: utf-8 -*- from Acquisition import aq_inner from Acquisition import aq_parent from OFS.SimpleItem import SimpleItem from plone.app.contentrules import PloneMessageFactory as _ from plone.app.contentrules.browser.formhelper import NullAddForm +from plone.base.utils import pretty_title_or_id from plone.contentrules.rule.interfaces import IExecutable from plone.contentrules.rule.interfaces import IRuleElementData -from Products.CMFPlone import utils from Products.statusmessages.interfaces import IStatusMessage from ZODB.POSException import ConflictError from zope.component import adapter @@ -17,24 +16,21 @@ class IDeleteAction(Interface): - """Interface for the configurable aspects of a delete action. - """ + """Interface for the configurable aspects of a delete action.""" @implementer(IDeleteAction, IRuleElementData) class DeleteAction(SimpleItem): - """The actual persistent implementation of the action element. - """ + """The actual persistent implementation of the action element.""" - element = 'plone.actions.Delete' - summary = _(u'Delete object') + element = "plone.actions.Delete" + summary = _("Delete object") @adapter(Interface, IDeleteAction, Interface) @implementer(IExecutable) -class DeleteActionExecutor(object): - """The executor for this action. - """ +class DeleteActionExecutor: + """The executor for this action.""" def __init__(self, context, element, event): self.context = context @@ -58,17 +54,18 @@ def __call__(self): return True def error(self, obj, error): - request = getattr(self.context, 'REQUEST', None) + request = getattr(self.context, "REQUEST", None) if request is not None: - title = utils.pretty_title_or_id(obj, obj) - message = _(u"Unable to remove ${name} as part of content rule 'delete' action: ${error}", # noqa - mapping={'name': title, 'error': error}) - IStatusMessage(request).addStatusMessage(message, type='error') + title = pretty_title_or_id(obj, obj) + message = _( + "Unable to remove ${name} as part of content rule 'delete' action: ${error}", # noqa + mapping={"name": title, "error": error}, + ) + IStatusMessage(request).addStatusMessage(message, type="error") class DeleteAddForm(NullAddForm): - """A degenerate "add form" for delete actions. - """ + """A degenerate "add form" for delete actions.""" def create(self): return DeleteAction() diff --git a/plone/app/contentrules/actions/logger.py b/plone/app/contentrules/actions/logger.py index dc23218..d52d70b 100644 --- a/plone/app/contentrules/actions/logger.py +++ b/plone/app/contentrules/actions/logger.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from OFS.SimpleItem import SimpleItem from plone.app.contentrules import PloneMessageFactory as _ from plone.app.contentrules.actions import ActionAddForm @@ -9,18 +8,16 @@ from Products.CMFCore.utils import getToolByName from zope import schema from zope.component import adapter -from zope.interface.interfaces import IObjectEvent from zope.interface import implementer from zope.interface import Interface +from zope.interface.interfaces import IObjectEvent import logging -logger = logging.getLogger('plone.contentrules.logger') +logger = logging.getLogger("plone.contentrules.logger") handler = logging.StreamHandler() -formatter = logging.Formatter( - '%(asctime)s - %(name)s - %(levelname)s - %(message)s' -) +formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") handler.setFormatter(formatter) logger.addHandler(handler) @@ -31,23 +28,20 @@ class ILoggerAction(Interface): This is also used to create add and edit forms, below. """ - targetLogger = schema.ASCIILine(title=_(u'Logger name'), - default='Plone') + targetLogger = schema.ASCIILine(title=_("Logger name"), default="Plone") - loggingLevel = schema.Int(title=_(u'Logging level'), - default=20) # INFO + loggingLevel = schema.Int(title=_("Logging level"), default=20) # INFO message = schema.TextLine( - title=_(u'Message'), + title=_("Message"), description=_( - 'help_contentrules_logger_message', - default=u'&e = the triggering event, ' - u'&c = the context, &u = the user', + "help_contentrules_logger_message", + default="&e = the triggering event, " "&c = the context, &u = the user", ), default=_( - 'text_contentrules_logger_message', - default=u'Caught &e at &c by &u', - ) + "text_contentrules_logger_message", + default="Caught &e at &c by &u", + ), ) @@ -58,20 +52,20 @@ class LoggerAction(SimpleItem): Note that we must mix in Explicit to keep Zope 2 security happy. """ - targetLogger = '' - loggingLevel = '' - message = '' + targetLogger = "" + loggingLevel = "" + message = "" - element = 'plone.actions.Logger' + element = "plone.actions.Logger" @property def summary(self): - return _(u'Log message ${message}', mapping=dict(message=self.message)) + return _("Log message ${message}", mapping=dict(message=self.message)) @adapter(Interface, ILoggerAction, Interface) @implementer(IExecutable) -class LoggerActionExecutor(object): +class LoggerActionExecutor: """The executor for this action. This is registered as an adapter in configure.zcml @@ -84,24 +78,23 @@ def __init__(self, context, element, event): def processedMessage(self): processedMessage = self.element.message - if '&e' in processedMessage: + if "&e" in processedMessage: event_class = self.event.__class__ processedMessage = processedMessage.replace( - '&e', - '{0}.{1}'.format( + "&e", + "{}.{}".format( event_class.__module__, event_class.__name__, - ) + ), ) - if '&c' in processedMessage and IObjectEvent.providedBy(self.event): - processedMessage = processedMessage.replace( - '&c', repr(self.event.object)) + if "&c" in processedMessage and IObjectEvent.providedBy(self.event): + processedMessage = processedMessage.replace("&c", repr(self.event.object)) - if '&u' in processedMessage: - mtool = getToolByName(self.context, 'portal_membership') + if "&u" in processedMessage: + mtool = getToolByName(self.context, "portal_membership") member = mtool.getAuthenticatedMember().getUserName() - processedMessage = processedMessage.replace('&u', member) + processedMessage = processedMessage.replace("&u", member) return processedMessage @@ -112,12 +105,12 @@ def __call__(self): class LoggerAddForm(ActionAddForm): - """An add form for logger rule actions. - """ + """An add form for logger rule actions.""" + schema = ILoggerAction - label = _(u'Add Logger Action') - description = _(u'A logger action can output a message to the system log.') - form_name = _(u'Configure element') + label = _("Add Logger Action") + description = _("A logger action can output a message to the system log.") + form_name = _("Configure element") Type = LoggerAction @@ -130,10 +123,11 @@ class LoggerEditForm(ActionEditForm): z3c.form does all the magic here. """ + schema = ILoggerAction - label = _(u'Edit Logger Action') - description = _(u'A logger action can output a message to the system log.') - form_name = _(u'Configure element') + label = _("Edit Logger Action") + description = _("A logger action can output a message to the system log.") + form_name = _("Configure element") class LoggerEditFormView(ContentRuleFormWrapper): diff --git a/plone/app/contentrules/actions/mail.py b/plone/app/contentrules/actions/mail.py index d4d6468..92211f5 100644 --- a/plone/app/contentrules/actions/mail.py +++ b/plone/app/contentrules/actions/mail.py @@ -1,16 +1,15 @@ -# -*- coding: utf-8 -*- from Acquisition import aq_inner from OFS.SimpleItem import SimpleItem from plone.app.contentrules import PloneMessageFactory as _ from plone.app.contentrules.actions import ActionAddForm from plone.app.contentrules.actions import ActionEditForm from plone.app.contentrules.browser.formhelper import ContentRuleFormWrapper +from plone.base.interfaces.controlpanel import IMailSchema from plone.contentrules.rule.interfaces import IExecutable from plone.contentrules.rule.interfaces import IRuleElementData from plone.registry.interfaces import IRegistry from plone.stringinterp.interfaces import IStringInterpolator from Products.CMFCore.utils import getToolByName -from Products.CMFPlone.interfaces.controlpanel import IMailSchema from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile from Products.MailHost.MailHost import MailHostError from Products.statusmessages.interfaces import IStatusMessage @@ -18,50 +17,47 @@ from zope import schema from zope.component import adapter from zope.component import getUtility -from zope.interface.interfaces import ComponentLookupError from zope.globalrequest import getRequest from zope.interface import implementer from zope.interface import Interface +from zope.interface.interfaces import ComponentLookupError import logging -import six -logger = logging.getLogger('plone.contentrules') +logger = logging.getLogger("plone.contentrules") class IMailAction(Interface): - """Definition of the configuration available for a mail action - """ + """Definition of the configuration available for a mail action""" + subject = schema.TextLine( - title=_(u'Subject'), - description=_(u'Subject of the message'), - required=True + title=_("Subject"), description=_("Subject of the message"), required=True ) source = schema.TextLine( - title=_(u'Email source'), + title=_("Email source"), description=_( - 'The email address that sends the email. If no email is provided ' - 'here, it will use the portal from address.' + "The email address that sends the email. If no email is provided " + "here, it will use the portal from address." ), - required=False + required=False, ) recipients = schema.TextLine( - title=_(u'Email recipients'), + title=_("Email recipients"), description=_( - 'The email where you want to send this message. To send it to ' - 'different email addresses, just separate them with ,' + "The email where you want to send this message. To send it to " + "different email addresses, just separate them with ," ), - required=True + required=True, ) exclude_actor = schema.Bool( - title=_(u'Exclude actor from recipients'), - description=_('Do not send the email to the user that did the action.') + title=_("Exclude actor from recipients"), + description=_("Do not send the email to the user that did the action."), ) message = schema.Text( - title=_(u'Message'), - description=_(u'The message that you want to mail.'), - required=True + title=_("Message"), + description=_("The message that you want to mail."), + required=True, ) @@ -71,39 +67,38 @@ class MailAction(SimpleItem): The implementation of the action defined before """ - subject = u'' - source = u'' - recipients = u'' - message = u'' + subject = "" + source = "" + recipients = "" + message = "" exclude_actor = False - element = 'plone.actions.Mail' + element = "plone.actions.Mail" @property def summary(self): - return _(u'Email report to ${recipients}', - mapping=dict(recipients=self.recipients)) + return _( + "Email report to ${recipients}", mapping=dict(recipients=self.recipients) + ) @implementer(IExecutable) @adapter(Interface, IMailAction, Interface) -class MailActionExecutor(object): - """The executor for this action. - """ +class MailActionExecutor: + """The executor for this action.""" def __init__(self, context, element, event): self.context = context self.element = element self.event = event registry = getUtility(IRegistry) - self.mail_settings = registry.forInterface(IMailSchema, - prefix='plone') + self.mail_settings = registry.forInterface(IMailSchema, prefix="plone") def __call__(self): - mailhost = getToolByName(aq_inner(self.context), 'MailHost') + mailhost = getToolByName(aq_inner(self.context), "MailHost") if not mailhost: raise ComponentLookupError( - 'You must have a Mailhost utility to execute this action' + "You must have a Mailhost utility to execute this action" ) email_charset = self.mail_settings.email_charset @@ -124,39 +119,33 @@ def __call__(self): if request: messages = IStatusMessage(request) msg = _( - u'Error sending email from content rule. You must ' - u'provide a source address for mail ' - u'actions or enter an email in the portal properties' + "Error sending email from content rule. You must " + "provide a source address for mail " + "actions or enter an email in the portal properties" ) - messages.add(msg, type=u'error') + messages.add(msg, type="error") return False from_name = self.mail_settings.email_from_name.strip('"') - if six.PY2 and isinstance(from_name, six.text_type): - from_name = from_name.encode('utf8') - source = '"{0}" <{1}>'.format(from_name, from_address) + source = f'"{from_name}" <{from_address}>' recip_string = interpolator(self.element.recipients) if recip_string: # check recipient is not None or empty string - recipients = set([ - str(mail.strip()) for mail in recip_string.split(',') - if mail.strip() - ]) + recipients = { + str(mail.strip()) for mail in recip_string.split(",") if mail.strip() + } else: recipients = set() if self.element.exclude_actor: - mtool = getToolByName(aq_inner(self.context), 'portal_membership') - actor_email = mtool.getAuthenticatedMember().getProperty( - 'email', - '' - ) + mtool = getToolByName(aq_inner(self.context), "portal_membership") + actor_email = mtool.getAuthenticatedMember().getProperty("email", "") if actor_email in recipients: recipients.remove(actor_email) # prepend interpolated message with \n to avoid interpretation # of first line as header - message = u'\n{0}'.format(interpolator(self.element.message)) + message = f"\n{interpolator(self.element.message)}" subject = interpolator(self.element.subject) @@ -168,12 +157,17 @@ def __call__(self): # AlecM thinks this wouldn't be a problem if mail queuing was # always on -- but it isn't. (stevem) # so we test if queue is not on to set immediate - mailhost.send(message, email_recipient, source, - subject=subject, charset=email_charset, - immediate=not mailhost.smtp_queue) + mailhost.send( + message, + email_recipient, + source, + subject=subject, + charset=email_charset, + immediate=not mailhost.smtp_queue, + ) except (MailHostError, SMTPException): logger.exception( - 'mail error: Attempt to send mail in content rule failed' + "mail error: Attempt to send mail in content rule failed" ) return True @@ -183,13 +177,14 @@ class MailAddForm(ActionAddForm): """ An add form for the mail action """ + schema = IMailAction - label = _(u'Add Mail Action') - description = _(u'A mail action can mail different recipient.') - form_name = _(u'Configure element') + label = _("Add Mail Action") + description = _("A mail action can mail different recipient.") + form_name = _("Configure element") Type = MailAction # custom template will allow us to add help text - template = ViewPageTemplateFile('templates/mail.pt') + template = ViewPageTemplateFile("templates/mail.pt") class MailAddFormView(ContentRuleFormWrapper): @@ -200,13 +195,14 @@ class MailEditForm(ActionEditForm): """ An edit form for the mail action """ + schema = IMailAction - label = _(u'Edit Mail Action') - description = _(u'A mail action can mail different recipient.') - form_name = _(u'Configure element') + label = _("Edit Mail Action") + description = _("A mail action can mail different recipient.") + form_name = _("Configure element") # custom template will allow us to add help text - template = ViewPageTemplateFile('templates/mail.pt') + template = ViewPageTemplateFile("templates/mail.pt") class MailEditFormView(ContentRuleFormWrapper): diff --git a/plone/app/contentrules/actions/move.py b/plone/app/contentrules/actions/move.py index c343331..ae54d72 100644 --- a/plone/app/contentrules/actions/move.py +++ b/plone/app/contentrules/actions/move.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from Acquisition import aq_base from Acquisition import aq_inner from Acquisition import aq_parent @@ -10,10 +9,10 @@ from plone.app.contentrules.actions import ActionEditForm from plone.app.contentrules.browser.formhelper import ContentRuleFormWrapper from plone.app.vocabularies.catalog import CatalogSource +from plone.base.utils import pretty_title_or_id from plone.contentrules.rule.interfaces import IExecutable from plone.contentrules.rule.interfaces import IRuleElementData from Products.CMFCore.utils import getToolByName -from Products.CMFPlone import utils from Products.statusmessages.interfaces import IStatusMessage from ZODB.POSException import ConflictError from zope import schema @@ -32,8 +31,8 @@ class IMoveAction(Interface): """ target_folder = schema.Choice( - title=_(u'Target folder'), - description=_(u'As a path relative to the portal root.'), + title=_("Target folder"), + description=_("As a path relative to the portal root."), required=True, source=CatalogSource(is_folderish=True), ) @@ -41,25 +40,20 @@ class IMoveAction(Interface): @implementer(IMoveAction, IRuleElementData) class MoveAction(SimpleItem): - """The actual persistent implementation of the action element. - """ + """The actual persistent implementation of the action element.""" - target_folder = '' - element = 'plone.actions.Move' + target_folder = "" + element = "plone.actions.Move" @property def summary(self): - return _( - u'Move to folder ${folder}', - mapping=dict(folder=self.target_folder) - ) + return _("Move to folder ${folder}", mapping=dict(folder=self.target_folder)) @adapter(Interface, IMoveAction, Interface) @implementer(IExecutable) -class MoveActionExecutor(object): - """The executor for this action. - """ +class MoveActionExecutor: + """The executor for this action.""" def __init__(self, context, element, event): self.context = context @@ -67,7 +61,7 @@ def __init__(self, context, element, event): self.event = event def __call__(self): - portal_url = getToolByName(self.context, 'portal_url', None) + portal_url = getToolByName(self.context, "portal_url", None) if portal_url is None: return False @@ -75,7 +69,7 @@ def __call__(self): parent = aq_parent(aq_inner(obj)) path = self.element.target_folder - if len(path) > 1 and path[0] == '/': + if len(path) > 1 and path[0] == "/": path = path[1:] target = portal_url.getPortalObject().unrestrictedTraverse( str(path), @@ -86,9 +80,9 @@ def __call__(self): self.error( obj, _( - u'Target folder ${target} does not exist.', - mapping={'target': path}, - ) + "Target folder ${target} does not exist.", + mapping={"target": path}, + ), ) return False @@ -135,37 +129,39 @@ def __call__(self): return True def error(self, obj, error): - request = getattr(self.context, 'REQUEST', None) + request = getattr(self.context, "REQUEST", None) if request is not None: - title = utils.pretty_title_or_id(obj, obj) + title = pretty_title_or_id(obj, obj) message = _( - u'Unable to move ${name} as part of content rule ' - u"'move' action: ${error}", - mapping={'name': title, 'error': error} + "Unable to move ${name} as part of content rule " + "'move' action: ${error}", + mapping={"name": title, "error": error}, ) - IStatusMessage(request).addStatusMessage(message, type='error') + IStatusMessage(request).addStatusMessage(message, type="error") def generate_id(self, target, old_id): - taken = getattr(aq_base(target), 'has_key', None) + taken = getattr(aq_base(target), "has_key", None) if taken is None: item_ids = set(target.objectIds()) - def taken(x): return x in item_ids + def taken(x): + return x in item_ids + if not taken(old_id): return old_id idx = 1 - while taken('{0}.{1}'.format(old_id, idx)): + while taken(f"{old_id}.{idx}"): idx += 1 - return '{0}.{1}'.format(old_id, idx) + return f"{old_id}.{idx}" class MoveAddForm(ActionAddForm): - """An add form for move-to-folder actions. - """ + """An add form for move-to-folder actions.""" + schema = IMoveAction - label = _(u'Add Move Action') - description = _(u'A move action can move an object to a different folder.') - form_name = _(u'Configure element') + label = _("Add Move Action") + description = _("A move action can move an object to a different folder.") + form_name = _("Configure element") Type = MoveAction @@ -178,10 +174,11 @@ class MoveEditForm(ActionEditForm): z3c.form does all the magic here. """ + schema = IMoveAction - label = _(u'Edit Move Action') - description = _(u'A move action can move an object to a different folder.') - form_name = _(u'Configure element') + label = _("Edit Move Action") + description = _("A move action can move an object to a different folder.") + form_name = _("Configure element") class MoveEditFormView(ContentRuleFormWrapper): diff --git a/plone/app/contentrules/actions/notify.py b/plone/app/contentrules/actions/notify.py index 3dcd87f..a03cd64 100644 --- a/plone/app/contentrules/actions/notify.py +++ b/plone/app/contentrules/actions/notify.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from OFS.SimpleItem import SimpleItem from plone.app.contentrules import PloneMessageFactory as _ from plone.app.contentrules.actions import ActionAddForm @@ -20,41 +19,40 @@ class INotifyAction(Interface): """ message = schema.TextLine( - title=_(u'Message'), - description=_(u'The message to send to the user.'), + title=_("Message"), + description=_("The message to send to the user."), required=True, ) message_type = schema.Choice( - title=_(u'Message type'), - description=_(u'Select the type of message to display.'), - values=('info', 'warning', 'error'), + title=_("Message type"), + description=_("Select the type of message to display."), + values=("info", "warning", "error"), required=True, - default='info', + default="info", ) @implementer(INotifyAction, IRuleElementData) class NotifyAction(SimpleItem): - """The actual persistent implementation of the notify action element. - """ + """The actual persistent implementation of the notify action element.""" - message = '' - message_type = '' + message = "" + message_type = "" - element = 'plone.actions.Notify' + element = "plone.actions.Notify" @property def summary(self): return _( - u'Notify with message ${message}', + "Notify with message ${message}", mapping=dict(message=self.message), ) @adapter(Interface, INotifyAction, Interface) @implementer(IExecutable) -class NotifyActionExecutor(object): +class NotifyActionExecutor: """The executor for this action. This is registered as an adapter in configure.zcml @@ -74,12 +72,12 @@ def __call__(self): class NotifyAddForm(ActionAddForm): - """An add form for notify rule actions. - """ + """An add form for notify rule actions.""" + schema = INotifyAction - label = _(u'Add Notify Action') - description = _(u'A notify action can show a message to the user.') - form_name = _(u'Configure element') + label = _("Add Notify Action") + description = _("A notify action can show a message to the user.") + form_name = _("Configure element") Type = NotifyAction @@ -92,10 +90,11 @@ class NotifyEditForm(ActionEditForm): z3c.form does all the magic here. """ + schema = INotifyAction - label = _(u'Edit Notify Action') - description = _(u'A notify action can show a message to the user.') - form_name = _(u'Configure element') + label = _("Edit Notify Action") + description = _("A notify action can show a message to the user.") + form_name = _("Configure element") class NotifyEditFormView(ContentRuleFormWrapper): diff --git a/plone/app/contentrules/actions/versioning.py b/plone/app/contentrules/actions/versioning.py index c255571..817c674 100644 --- a/plone/app/contentrules/actions/versioning.py +++ b/plone/app/contentrules/actions/versioning.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from OFS.SimpleItem import SimpleItem from plone.app.contentrules import PloneMessageFactory as _ from plone.app.contentrules.actions import ActionAddForm @@ -20,33 +19,31 @@ class IVersioningAction(Interface): """ comment = schema.TextLine( - title=_(u'Comment'), - description=_( - u'The comment added to the history while versioning the content.'), + title=_("Comment"), + description=_("The comment added to the history while versioning the content."), required=False, ) @implementer(IVersioningAction, IRuleElementData) class VersioningAction(SimpleItem): - """The actual persistent implementation of the versioning action element. - """ + """The actual persistent implementation of the versioning action element.""" - comment = '' + comment = "" - element = 'plone.actions.Versioning' + element = "plone.actions.Versioning" @property def summary(self): return _( - u'Versioning with comment ${comment}', + "Versioning with comment ${comment}", mapping=dict(comment=self.comment), ) @adapter(Interface, IVersioningAction, Interface) @implementer(IExecutable) -class VersioningActionExecutor(object): +class VersioningActionExecutor: """The executor for this action. This is registered as an adapter in configure.zcml @@ -59,19 +56,21 @@ def __init__(self, context, element, event): def __call__(self): comment = _(self.element.comment) - pr = getToolByName(self.context, 'portal_repository') + pr = getToolByName(self.context, "portal_repository") pr.save(obj=self.event.object, comment=comment) return True class VersioningAddForm(ActionAddForm): - """An add form for versioning rule actions. - """ + """An add form for versioning rule actions.""" + schema = IVersioningAction - label = _(u'Add Versioning Action') - description = _(u'A versioning action will store a version of a content ' - u'no matter versioning is enabled for it or not.') - form_name = _(u'Configure element') + label = _("Add Versioning Action") + description = _( + "A versioning action will store a version of a content " + "no matter versioning is enabled for it or not." + ) + form_name = _("Configure element") Type = VersioningAction @@ -84,11 +83,14 @@ class VersioningEditForm(ActionEditForm): z3c.form does all the magic here. """ + schema = IVersioningAction - label = _(u'Edit Versioning Action') - description = _(u'A versioning action will store a version of a content ' - u'no matter versioning is enabled for it or not.') - form_name = _(u'Configure element') + label = _("Edit Versioning Action") + description = _( + "A versioning action will store a version of a content " + "no matter versioning is enabled for it or not." + ) + form_name = _("Configure element") class VersioningEditFormView(ContentRuleFormWrapper): diff --git a/plone/app/contentrules/actions/workflow.py b/plone/app/contentrules/actions/workflow.py index 9f75eb9..211e42a 100644 --- a/plone/app/contentrules/actions/workflow.py +++ b/plone/app/contentrules/actions/workflow.py @@ -1,13 +1,13 @@ -# -*- coding: utf-8 -*- from OFS.SimpleItem import SimpleItem from plone.app.contentrules import PloneMessageFactory as _ from plone.app.contentrules.actions import ActionAddForm from plone.app.contentrules.actions import ActionEditForm from plone.app.contentrules.browser.formhelper import ContentRuleFormWrapper +from plone.base.utils import pretty_title_or_id +from plone.base.utils import safe_text from plone.contentrules.rule.interfaces import IExecutable from plone.contentrules.rule.interfaces import IRuleElementData from Products.CMFCore.utils import getToolByName -from Products.CMFPlone import utils from Products.statusmessages.interfaces import IStatusMessage from ZODB.POSException import ConflictError from zope import schema @@ -23,34 +23,32 @@ class IWorkflowAction(Interface): """ transition = schema.Choice( - title=_(u'Transition'), - description=_(u'Select the workflow transition to attempt'), + title=_("Transition"), + description=_("Select the workflow transition to attempt"), required=True, - vocabulary='plone.app.vocabularies.WorkflowTransitions', + vocabulary="plone.app.vocabularies.WorkflowTransitions", ) @implementer(IWorkflowAction, IRuleElementData) class WorkflowAction(SimpleItem): - """The actual persistent implementation of the action element. - """ + """The actual persistent implementation of the action element.""" - transition = '' - element = 'plone.actions.Workflow' + transition = "" + element = "plone.actions.Workflow" @property def summary(self): return _( - u'Execute transition ${transition}', + "Execute transition ${transition}", mapping=dict(transition=self.transition), ) @adapter(Interface, IWorkflowAction, Interface) @implementer(IExecutable) -class WorkflowActionExecutor(object): - """The executor for this action. - """ +class WorkflowActionExecutor: + """The executor for this action.""" def __init__(self, context, element, event): self.context = context @@ -58,7 +56,7 @@ def __init__(self, context, element, event): self.event = event def __call__(self): - portal_workflow = getToolByName(self.context, 'portal_workflow', None) + portal_workflow = getToolByName(self.context, "portal_workflow", None) if portal_workflow is None: return False @@ -75,24 +73,24 @@ def __call__(self): return True def error(self, obj, error): - request = getattr(self.context, 'REQUEST', None) + request = getattr(self.context, "REQUEST", None) if request is not None: - title = utils.safe_unicode(utils.pretty_title_or_id(obj, obj)) - error = utils.safe_unicode(error) + title = safe_text(pretty_title_or_id(obj, obj)) + error = safe_text(error) message = _( - u"Unable to change state of ${name} as part of content rule 'workflow' action: ${error}", # noqa - mapping={'name': title, 'error': error}) - IStatusMessage(request).addStatusMessage(message, type='error') + "Unable to change state of ${name} as part of content rule 'workflow' action: ${error}", # noqa + mapping={"name": title, "error": error}, + ) + IStatusMessage(request).addStatusMessage(message, type="error") class WorkflowAddForm(ActionAddForm): - """An add form for workflow actions. - """ + """An add form for workflow actions.""" + schema = IWorkflowAction - label = _(u'Add Workflow Action') - description = _( - u'A workflow action triggers a workflow transition on an object.') - form_name = _(u'Configure element') + label = _("Add Workflow Action") + description = _("A workflow action triggers a workflow transition on an object.") + form_name = _("Configure element") Type = WorkflowAction @@ -101,13 +99,12 @@ class WorkflowAddFormView(ContentRuleFormWrapper): class WorkflowEditForm(ActionEditForm): - """An edit form for workflow rule actions. - """ + """An edit form for workflow rule actions.""" + schema = IWorkflowAction - label = _(u'Edit Workflow Action') - description = _( - u'A workflow action triggers a workflow transition on an object.') - form_name = _(u'Configure element') + label = _("Edit Workflow Action") + description = _("A workflow action triggers a workflow transition on an object.") + form_name = _("Configure element") class WorkflowEditFormView(ContentRuleFormWrapper): diff --git a/plone/app/contentrules/api.py b/plone/app/contentrules/api.py index 7fd8cd4..754fc18 100644 --- a/plone/app/contentrules/api.py +++ b/plone/app/contentrules/api.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from plone.app.contentrules.rule import get_assignments from plone.app.contentrules.rule import insert_assignment from plone.contentrules.engine.assignments import RuleAssignment @@ -7,8 +6,7 @@ from zope.component import queryUtility -def assign_rule(container, rule_id, enabled=True, bubbles=True, - insert_before=None): +def assign_rule(container, rule_id, enabled=True, bubbles=True, insert_before=None): """Assign @param string rule_id rule to @@ -32,13 +30,13 @@ def assign_rule(container, rule_id, enabled=True, bubbles=True, assignable[rule_id].enabled = bool(enabled) assignable[rule_id].bubbles = bool(bubbles) - path = '/'.join(container.getPhysicalPath()) + path = "/".join(container.getPhysicalPath()) insert_assignment(storage[rule_id], path) if insert_before: position = None keys = list(assignable.keys()) - if insert_before == '*': + if insert_before == "*": position = 0 elif insert_before in keys: position = keys.index(insert_before) @@ -51,13 +49,13 @@ def assign_rule(container, rule_id, enabled=True, bubbles=True, def unassign_rule(container, rule_id): """Remove - @param string rule_id - rule from - @param object container + @param string rule_id + rule from + @param object container """ assignable = IRuleAssignmentManager(container) storage = queryUtility(IRuleStorage) - path = '/'.join(container.getPhysicalPath()) + path = "/".join(container.getPhysicalPath()) del assignable[rule_id] get_assignments(storage[rule_id]).remove(path) diff --git a/plone/app/contentrules/browser/__init__.py b/plone/app/contentrules/browser/__init__.py index ec51c5a..792d600 100644 --- a/plone/app/contentrules/browser/__init__.py +++ b/plone/app/contentrules/browser/__init__.py @@ -1,2 +1 @@ -# -*- coding: utf-8 -*- # diff --git a/plone/app/contentrules/browser/adding.py b/plone/app/contentrules/browser/adding.py index 79dc4c0..febf16c 100644 --- a/plone/app/contentrules/browser/adding.py +++ b/plone/app/contentrules/browser/adding.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from Acquisition import aq_base from Acquisition import aq_inner from Acquisition import aq_parent @@ -26,28 +25,33 @@ class RuleAdding(SimpleItem, BrowserView): # This is necessary so that context.absolute_url() works properly on the # add form, which in turn fixes the URL - id = '+rule' + id = "+rule" def __init__(self, context, request): self.context = context self.request = request def add(self, content): - """Add the rule to the context - """ + """Add the rule to the context""" storage = getUtility(IRuleStorage) chooser = INameChooser(storage) name = chooser.chooseName(None, content) self._chosen_name = name storage[name] = content - IStatusMessage(self.request).add(_( - u'New content rule created. ' - u'Please add conditions and actions at the bottom of the page.'), - type=u'info') + IStatusMessage(self.request).add( + _( + "New content rule created. " + "Please add conditions and actions at the bottom of the page." + ), + type="info", + ) def renderAddButton(self): - warn('The renderAddButton method is deprecated, use nameAllowed', - DeprecationWarning, 2) + warn( + "The renderAddButton method is deprecated, use nameAllowed", + DeprecationWarning, + 2, + ) def namesAccepted(self): return False @@ -79,13 +83,19 @@ def __init__(self, context, request): self.request = request def nextURL(self): - url = str(getMultiAdapter( - (aq_parent(self.context), self.request), name=u'absolute_url')) - return url + '/@@manage-content-rules' + url = str( + getMultiAdapter( + (aq_parent(self.context), self.request), name="absolute_url" + ) + ) + return url + "/@@manage-content-rules" def renderAddButton(self): - warn('The renderAddButton method is deprecated, use nameAllowed', - DeprecationWarning, 2) + warn( + "The renderAddButton method is deprecated, use nameAllowed", + DeprecationWarning, + 2, + ) def namesAccepted(self): return False @@ -108,11 +118,10 @@ class RuleConditionAdding(RuleElementAdding): # This is necessary so that context.absolute_url() works properly on the # add form, which in turn fixes the URL - id = '+condition' + id = "+condition" def add(self, content): - """Add the rule element to the context rule - """ + """Add the rule element to the context rule""" rule = aq_base(aq_inner(self.context)) rule.conditions.append(content) @@ -122,10 +131,9 @@ class RuleActionAdding(RuleElementAdding): # This is necessary so that context.absolute_url() works properly on the # add form, which in turn fixes the URL - id = '+action' + id = "+action" def add(self, content): - """Add the rule element to the context rule - """ + """Add the rule element to the context rule""" rule = aq_base(aq_inner(self.context)) rule.actions.append(content) diff --git a/plone/app/contentrules/browser/assignments.py b/plone/app/contentrules/browser/assignments.py index 3d30673..ec50215 100644 --- a/plone/app/contentrules/browser/assignments.py +++ b/plone/app/contentrules/browser/assignments.py @@ -1,8 +1,7 @@ -# -*- coding: utf-8 -*- from Acquisition import aq_inner from Acquisition import aq_parent -from plone.app.contentrules import PloneMessageFactory as _ from plone.app.contentrules import api +from plone.app.contentrules import PloneMessageFactory as _ from plone.contentrules.engine.interfaces import IRuleAssignmentManager from plone.contentrules.engine.interfaces import IRuleStorage from plone.memoize.instance import memoize @@ -16,10 +15,9 @@ class ManageAssignments(BrowserView): - """Manage contextual rule assignments - """ + """Manage contextual rule assignments""" - template = ViewPageTemplateFile('templates/manage-assignments.pt') + template = ViewPageTemplateFile("templates/manage-assignments.pt") def __call__(self): context = aq_inner(self.context) @@ -27,58 +25,57 @@ def __call__(self): form = request.form status = IStatusMessage(self.request) - operation = request.get('operation', None) + operation = request.get("operation", None) - if operation == 'move_up': + if operation == "move_up": assignable = IRuleAssignmentManager(context) - rule_id = request.get('rule_id') + rule_id = request.get("rule_id") keys = list(assignable.keys()) idx = keys.index(rule_id) del keys[idx] keys.insert(idx - 1, rule_id) assignable.updateOrder(keys) - elif operation == 'move_down': + elif operation == "move_down": assignable = IRuleAssignmentManager(context) - rule_id = request.get('rule_id') + rule_id = request.get("rule_id") keys = list(assignable.keys()) idx = keys.index(rule_id) del keys[idx] keys.insert(idx + 1, rule_id) assignable.updateOrder(keys) - elif 'form.button.AddAssignment' in form: - rule_id = form.get('rule_id') + elif "form.button.AddAssignment" in form: + rule_id = form.get("rule_id") api.assign_rule(self.context, rule_id) - elif 'form.button.Delete' in form: - rule_ids = form.get('rule_ids', ()) + elif "form.button.Delete" in form: + rule_ids = form.get("rule_ids", ()) for r in rule_ids: api.unassign_rule(self.context, r) - status.addStatusMessage(_(u'Assignments deleted.'), type='info') - elif 'form.button.Enable' in form: - rule_ids = form.get('rule_ids', ()) + status.addStatusMessage(_("Assignments deleted."), type="info") + elif "form.button.Enable" in form: + rule_ids = form.get("rule_ids", ()) for r in rule_ids: api.edit_rule_assignment(context, r, enabled=True) - status.addStatusMessage(_(u'Assignments enabled.'), type='info') - elif 'form.button.Disable' in form: - rule_ids = form.get('rule_ids', ()) + status.addStatusMessage(_("Assignments enabled."), type="info") + elif "form.button.Disable" in form: + rule_ids = form.get("rule_ids", ()) for r in rule_ids: api.edit_rule_assignment(context, r, enabled=False) - status.addStatusMessage(_(u'Assignments disabled.'), type='info') - elif 'form.button.Bubble' in form: - rule_ids = form.get('rule_ids', ()) + status.addStatusMessage(_("Assignments disabled."), type="info") + elif "form.button.Bubble" in form: + rule_ids = form.get("rule_ids", ()) for r in rule_ids: - api.edit_rule_assignment( - context, r, bubbles=True, enabled=True) + api.edit_rule_assignment(context, r, bubbles=True, enabled=True) - status.addStatusMessage(_(u'Changes saved.'), type='info') - elif 'form.button.NoBubble' in form: - rule_ids = form.get('rule_ids', ()) + status.addStatusMessage(_("Changes saved."), type="info") + elif "form.button.NoBubble" in form: + rule_ids = form.get("rule_ids", ()) for r in rule_ids: api.edit_rule_assignment(context, r, bubbles=False) - status.addStatusMessage(_(u'Changes saved.'), type='info') + status.addStatusMessage(_("Changes saved."), type="info") return self.template() @@ -88,7 +85,7 @@ def globally_enabled(self): @memoize def view_url(self): - return self.context.absolute_url() + '/@@manage-content-rules' + return self.context.absolute_url() + "/@@manage-content-rules" @memoize def type_name(self): @@ -103,7 +100,7 @@ def acquired_rules(self): if ISiteRoot.providedBy(self.context): return [] - in_use = set([r['id'] for r in self.assigned_rules()]) + in_use = {r["id"] for r in self.assigned_rules()} storage = getUtility(IRuleStorage) events = self._events() @@ -118,17 +115,19 @@ def acquired_rules(self): if key not in in_use and assignment.bubbles: rule = storage.get(key, None) if rule is not None: - url = '{0}/@@manage-content-rules'.format( + url = "{}/@@manage-content-rules".format( context.absolute_url(), ) - assignments.append(dict( - id=key, - title=rule.title, - description=rule.description, - trigger=events.get(rule.event, 'Unknown'), - url=url, - enabled=(assignment.enabled and rule.enabled), - )) + assignments.append( + dict( + id=key, + title=rule.title, + description=rule.description, + trigger=events.get(rule.event, "Unknown"), + url=url, + enabled=(assignment.enabled and rule.enabled), + ) + ) if ISiteRoot.providedBy(context): context = None else: @@ -146,40 +145,44 @@ def assigned_rules(self): for key, assignment in assignable.items(): rule = storage.get(key, None) if rule is not None: - assignments.append(dict(id=key, - title=rule.title, - description=rule.description, - trigger=events.get( - rule.event, - 'Unknown' - ), - url=self._rule_url(key), - bubbles=assignment.bubbles, - enabled=assignment.enabled, - global_enabled=rule.enabled, )) + assignments.append( + dict( + id=key, + title=rule.title, + description=rule.description, + trigger=events.get(rule.event, "Unknown"), + url=self._rule_url(key), + bubbles=assignment.bubbles, + enabled=assignment.enabled, + global_enabled=rule.enabled, + ) + ) return assignments def has_rules(self): return len(self.assigned_rules()) > 0 or len(self.acquired_rules()) > 0 def assignable_rules(self): - in_use = set([r['id'] for r in self.assigned_rules()]) + in_use = {r["id"] for r in self.assigned_rules()} assignable = [] for key, rule in getUtility(IRuleStorage).items(): if key not in in_use: - assignable.append(dict(id=key, - title=rule.title, - description=rule.description, )) + assignable.append( + dict( + id=key, + title=rule.title, + description=rule.description, + ) + ) return assignable @memoize def _events(self): - eventsFactory = getUtility( - IVocabularyFactory, name='plone.contentrules.events') - return dict([(e.value, e.token) for e in eventsFactory(self.context)]) + eventsFactory = getUtility(IVocabularyFactory, name="plone.contentrules.events") + return {e.value: e.token for e in eventsFactory(self.context)} def _rule_url(self, key): - return '{0}/++rule++{1}/@@manage-elements'.format( + return "{}/++rule++{}/@@manage-elements".format( self._portal_url(), key, ) @@ -187,5 +190,6 @@ def _rule_url(self, key): @memoize def _portal_url(self): portal_state = getMultiAdapter( - (self.context, self.request), name='plone_portal_state') + (self.context, self.request), name="plone_portal_state" + ) return portal_state.portal_url() diff --git a/plone/app/contentrules/browser/configure.zcml b/plone/app/contentrules/browser/configure.zcml index a97da0b..3f59775 100644 --- a/plone/app/contentrules/browser/configure.zcml +++ b/plone/app/contentrules/browser/configure.zcml @@ -94,7 +94,7 @@ /> 0 - assigned_class = 'assignment-unassigned' + assigned_class = "assignment-unassigned" if assigned: - assigned_class = 'assignment-assigned' - - info.append({ - 'id': r.__name__, - 'title': r.title, - 'description': r.description, - 'enabled': r.enabled, - 'assigned': assigned, - 'trigger': events[r.event], - 'row_class': '{0} {1} {2}'.format( - trigger_class, - enabled_class, - assigned_class, - ) - }) + assigned_class = "assignment-assigned" + + info.append( + { + "id": r.__name__, + "title": r.title, + "description": r.description, + "enabled": r.enabled, + "assigned": assigned, + "trigger": events[r.event], + "row_class": "{} {} {}".format( + trigger_class, + enabled_class, + assigned_class, + ), + } + ) return info @@ -96,22 +98,20 @@ def ruleTypesToShow(self): else: continue - eventname = translate( - event.token, context=self.request, domain='plone') - selector.append({'id': get_trigger_class(event.value), - 'title': eventname}) + eventname = translate(event.token, context=self.request, domain="plone") + selector.append({"id": get_trigger_class(event.value), "title": eventname}) return selector def statesToShow(self): return ( { - 'id': 'state-enabled', - 'title': _(u'label_rule_enabled', default=u'Enabled'), + "id": "state-enabled", + "title": _("label_rule_enabled", default="Enabled"), }, { - 'id': 'state-disabled', - 'title': _(u'label_rule_disabled', default=u'Disabled'), + "id": "state-disabled", + "title": _("label_rule_disabled", default="Disabled"), }, ) @@ -121,41 +121,42 @@ def _getRules(self): @memoize def _events(self): - eventsFactory = getUtility( - IVocabularyFactory, name='plone.contentrules.events') + eventsFactory = getUtility(IVocabularyFactory, name="plone.contentrules.events") return eventsFactory(self.context) def delete_rule(self): self.authorize() - rule_id = self.request['rule-id'] + rule_id = self.request["rule-id"] storage = getUtility(IRuleStorage) del storage[rule_id] - return 'ok' + return "ok" def enable_rule(self): self.authorize() storage = getUtility(IRuleStorage) - rule_id = self.request['rule-id'] + rule_id = self.request["rule-id"] storage[rule_id].enabled = True - return 'ok' + return "ok" def disable_rule(self): self.authorize() storage = getUtility(IRuleStorage) - rule_id = self.request['rule-id'] + rule_id = self.request["rule-id"] storage[rule_id].enabled = False - return 'ok' + return "ok" def globally_disable(self): self.authorize() storage = getUtility(IRuleStorage) storage.active = False - return translate(_('Content rules has been globally disabled'), - context=self.request) + return translate( + _("Content rules has been globally disabled"), context=self.request + ) def globally_enable(self): self.authorize() storage = getUtility(IRuleStorage) storage.active = True - return translate(_('Content rules has been globally enabled'), - context=self.request) + return translate( + _("Content rules has been globally enabled"), context=self.request + ) diff --git a/plone/app/contentrules/browser/elements.py b/plone/app/contentrules/browser/elements.py index 97879c6..eb06937 100644 --- a/plone/app/contentrules/browser/elements.py +++ b/plone/app/contentrules/browser/elements.py @@ -1,8 +1,7 @@ -# -*- coding: utf-8 -*- from AccessControl import Unauthorized from Acquisition import aq_inner -from plone.app.contentrules import PloneMessageFactory as _ from plone.app.contentrules import api +from plone.app.contentrules import PloneMessageFactory as _ from plone.app.contentrules.rule import get_assignments from plone.contentrules.engine import utils from plone.contentrules.rule.interfaces import IRuleAction @@ -21,63 +20,61 @@ class ManageElements(BrowserView): - """Manage elements in a rule - """ + """Manage elements in a rule""" - template = ViewPageTemplateFile('templates/manage-elements.pt') + template = ViewPageTemplateFile("templates/manage-elements.pt") def __call__(self): redirect = False form = self.request.form - idx = form.get('element_id', 0) + idx = form.get("element_id", 0) rule = aq_inner(self.context) status = IStatusMessage(self.request) - if 'form.button.Save' in form: + if "form.button.Save" in form: self.authorize() - rule.title = form.get('title', rule.title) - rule.description = form.get('description', rule.description) - rule.stop = bool(form.get('stopExecuting', False)) - rule.cascading = bool(form.get('cascading', False)) - rule.enabled = bool(form.get('enabled', False)) - status.addStatusMessage(_(u'Changes saved.'), type='info') - elif 'form.button.EditCondition' in form: - editview = self.conditions()[idx]['editview'] + rule.title = form.get("title", rule.title) + rule.description = form.get("description", rule.description) + rule.stop = bool(form.get("stopExecuting", False)) + rule.cascading = bool(form.get("cascading", False)) + rule.enabled = bool(form.get("enabled", False)) + status.addStatusMessage(_("Changes saved."), type="info") + elif "form.button.EditCondition" in form: + editview = self.conditions()[idx]["editview"] self.request.response.redirect(editview) redirect = True - elif 'form.button.DeleteCondition' in form: + elif "form.button.DeleteCondition" in form: self.authorize() del rule.conditions[idx] - status.addStatusMessage(_(u'Condition deleted.'), type='info') - elif 'form.button.MoveConditionUp' in form: + status.addStatusMessage(_("Condition deleted."), type="info") + elif "form.button.MoveConditionUp" in form: self._move_up(rule.conditions, idx) - status.addStatusMessage(_(u'Condition moved up.'), type='info') - elif 'form.button.MoveConditionDown' in form: + status.addStatusMessage(_("Condition moved up."), type="info") + elif "form.button.MoveConditionDown" in form: self._move_down(rule.conditions, idx) - status.addStatusMessage(_(u'Condition moved down.'), type='info') - elif 'form.button.EditAction' in form: - editview = self.actions()[idx]['editview'] + status.addStatusMessage(_("Condition moved down."), type="info") + elif "form.button.EditAction" in form: + editview = self.actions()[idx]["editview"] self.request.response.redirect(editview) redirect = True - elif 'form.button.DeleteAction' in form: + elif "form.button.DeleteAction" in form: self.authorize() del rule.actions[idx] - status.addStatusMessage(_(u'Action deleted.'), type='info') - elif 'form.button.MoveActionUp' in form: + status.addStatusMessage(_("Action deleted."), type="info") + elif "form.button.MoveActionUp" in form: self._move_up(rule.actions, idx) - status.addStatusMessage(_(u'Action moved up.'), type='info') - elif 'form.button.MoveActionDown' in form: + status.addStatusMessage(_("Action moved up."), type="info") + elif "form.button.MoveActionDown" in form: self._move_down(rule.actions, idx) - status.addStatusMessage(_(u'Action moved down.'), type='info') - elif 'form.button.ApplyOnWholeSite' in form: + status.addStatusMessage(_("Action moved down."), type="info") + elif "form.button.ApplyOnWholeSite" in form: self.globally_assign() IStatusMessage(self.request).add( - _(u'The rule has been enabled on site root ' - u'and all its subfolders') + _("The rule has been enabled on site root " "and all its subfolders") ) - self.view_url = self.base_url + '/@@manage-elements' + self.view_url = self.base_url + "/@@manage-elements" self.rule_title = self.context.title self.rule_description = self.context.description self.rule_stop = self.context.stop @@ -88,8 +85,9 @@ def __call__(self): return self.template() def authorize(self): - authenticator = getMultiAdapter((self.context, self.request), - name=u'authenticator') + authenticator = getMultiAdapter( + (self.context, self.request), name="authenticator" + ) if not authenticator.verify(): raise Unauthorized @@ -98,13 +96,12 @@ def base_url(self): return aq_inner(self.context).absolute_url() def rule_event(self): - eventsFactory = getUtility(IVocabularyFactory, - name='plone.contentrules.events') + eventsFactory = getUtility(IVocabularyFactory, name="plone.contentrules.events") for e in eventsFactory(self.context): if e.value == self.context.event: - return translate(e.token, context=self.request, domain='plone') + return translate(e.token, context=self.request, domain="plone") - return 'Unknown event' # should not happen + return "Unknown event" # should not happen @memoize def actions(self): @@ -112,7 +109,7 @@ def actions(self): for name, utility in getUtilitiesFor(IRuleAction): actions[name] = utility - return self._populate_info(self.context.actions, actions, 'action') + return self._populate_info(self.context.actions, actions, "action") @memoize def conditions(self): @@ -120,18 +117,20 @@ def conditions(self): for name, utility in getUtilitiesFor(IRuleCondition): conditions[name] = utility - return self._populate_info(self.context.conditions, - conditions, 'condition') + return self._populate_info(self.context.conditions, conditions, "condition") def addable_conditions(self): rule = aq_inner(self.context) info = [] for element in utils.allAvailableConditions(rule.event): - info.append({ - 'title': element.title, - 'description': element.description, - 'addview': element.addview}) + info.append( + { + "title": element.title, + "description": element.description, + "addview": element.addview, + } + ) return info @@ -140,10 +139,13 @@ def addable_actions(self): info = [] for element in utils.allAvailableActions(rule.event): - info.append({ - 'title': element.title, - 'description': element.description, - 'addview': element.addview}) + info.append( + { + "title": element.title, + "description": element.description, + "addview": element.addview, + } + ) return info @@ -151,28 +153,33 @@ def assignments(self): rule = aq_inner(self.context) paths = set(get_assignments(rule)) - site = getToolByName(rule, 'portal_url').getPortalObject() - site_path = '/'.join(site.getPhysicalPath()) + site = getToolByName(rule, "portal_url").getPortalObject() + site_path = "/".join(site.getPhysicalPath()) info = [] if site_path in paths: paths.remove(site_path) - info.append({ - 'url': site.absolute_url(), - 'title': site.title_or_id(), - 'description': site.Description(), - 'icon': 'plone-home' - }) - - catalog = getToolByName(rule, 'portal_catalog') - for a in catalog(path=dict(query=list(paths), depth=0), - sort_on='sortable_title'): - info.append({ - 'url': a.getURL(), - 'title': a.Title or a.getId, - 'description': a.Description, - 'icon': f'contenttype/{a.portal_type.lower()}' - }) + info.append( + { + "url": site.absolute_url(), + "title": site.title_or_id(), + "description": site.Description(), + "icon": "plone-home", + } + ) + + catalog = getToolByName(rule, "portal_catalog") + for a in catalog( + path=dict(query=list(paths), depth=0), sort_on="sortable_title" + ): + info.append( + { + "url": a.getURL(), + "title": a.Title or a.getId, + "description": a.Description, + "icon": f"contenttype/{a.portal_type.lower()}", + } + ) return info @@ -195,21 +202,24 @@ def _populate_info(self, elements, meta, namespace): editview = None if descriptor.editview: - editview = '{0}/++{1}++{2}/{3}'.format( + editview = "{}/++{}++{}/{}".format( base_url, namespace, idx, descriptor.editview, ) - info.append({ - 'title': descriptor.title, - 'description': descriptor.description, - 'summary': data.summary, - 'editview': editview, - 'first': (idx == 0), - 'last': (idx == last), - 'idx': idx}) + info.append( + { + "title": descriptor.title, + "description": descriptor.description, + "summary": data.summary, + "editview": editview, + "first": (idx == 0), + "last": (idx == last), + "idx": idx, + } + ) return info def _move_up(self, elements, idx): @@ -226,5 +236,5 @@ def _move_down(self, elements, idx): def globally_assign(self): self.authorize() - portal = getToolByName(self.context, 'portal_url').getPortalObject() + portal = getToolByName(self.context, "portal_url").getPortalObject() api.assign_rule(portal, self.context.__name__) diff --git a/plone/app/contentrules/browser/formhelper.py b/plone/app/contentrules/browser/formhelper.py index 8e321b4..7dafd6f 100644 --- a/plone/app/contentrules/browser/formhelper.py +++ b/plone/app/contentrules/browser/formhelper.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from Acquisition import aq_inner from Acquisition import aq_parent from plone.app.contentrules import PloneMessageFactory as _ @@ -36,20 +35,20 @@ def create(self, data): def create(self): return MyAssignment() """ + ignoreContext = True def updateActions(self): - super(AddForm, self).updateActions() - self.actions['save'].addClass('btn btn-primary') - self.actions['cancel'].addClass('btn btn-secondary') + super().updateActions() + self.actions["save"].addClass("btn btn-primary") + self.actions["cancel"].addClass("btn btn-secondary") def nextURL(self): rule = aq_parent(aq_inner(self.context)) context = aq_parent(aq_inner(rule)) - url = str(getMultiAdapter( - (context, self.request), name=u'absolute_url')) - focus = self.context.id.strip('+') - return '{0}/++rule++{1}/@@manage-elements#{2}'.format( + url = str(getMultiAdapter((context, self.request), name="absolute_url")) + focus = self.context.id.strip("+") + return "{}/++rule++{}/@@manage-elements#{}".format( url, rule.__name__, focus, @@ -58,7 +57,7 @@ def nextURL(self): def add(self, content): self.context.add(content) - @button.buttonAndHandler(_(u'label_save', default=u'Save'), name='save') + @button.buttonAndHandler(_("label_save", default="Save"), name="save") def handle_save_action(self, action): data, errors = self.extractData() if errors: @@ -71,14 +70,14 @@ def handle_save_action(self, action): self.request.response.redirect(self.nextURL()) @button.buttonAndHandler( - _(u'label_cancel', default=u'Cancel'), - name='cancel', + _("label_cancel", default="Cancel"), + name="cancel", ) def handle_cancel_action(self, action): nextURL = self.nextURL() if nextURL: self.request.response.redirect(self.nextURL()) - return '' + return "" class NullAddForm(BrowserView): @@ -97,30 +96,28 @@ def __call__(self): nextURL = self.nextURL() if nextURL: self.request.response.redirect(self.nextURL()) - return '' + return "" def nextURL(self): rule = aq_parent(aq_inner(self.context)) context = aq_parent(aq_inner(rule)) - url = str(getMultiAdapter( - (context, self.request), name=u'absolute_url')) - return '{0}/++rule++{1}/@@manage-elements'.format(url, rule.__name__) + url = str(getMultiAdapter((context, self.request), name="absolute_url")) + return f"{url}/++rule++{rule.__name__}/@@manage-elements" def create(self): - raise NotImplementedError('concrete classes must implement create()') + raise NotImplementedError("concrete classes must implement create()") @implementer(IContentRulesForm) class EditForm(AutoExtensibleForm, form.EditForm): - """An edit form for rule elements. - """ + """An edit form for rule elements.""" def updateActions(self): - super(EditForm, self).updateActions() - self.actions['save'].addClass('btn btn-primary') - self.actions['cancel'].addClass('btn btn-secondary') + super().updateActions() + self.actions["save"].addClass("btn btn-primary") + self.actions["cancel"].addClass("btn btn-secondary") - @button.buttonAndHandler(_(u'label_save', default=u'Save'), name='save') + @button.buttonAndHandler(_("label_save", default="Save"), name="save") def handle_save_action(self, action): data, errors = self.extractData() if errors: @@ -130,26 +127,25 @@ def handle_save_action(self, action): nextURL = self.nextURL() if nextURL: self.request.response.redirect(self.nextURL()) - return '' + return "" @button.buttonAndHandler( - _(u'label_cancel', default=u'Cancel'), - name='cancel', + _("label_cancel", default="Cancel"), + name="cancel", ) def handle_cancel_action(self, action): nextURL = self.nextURL() if nextURL: self.request.response.redirect(self.nextURL()) - return '' + return "" def nextURL(self): element = aq_inner(self.context) rule = aq_parent(element) context = aq_parent(rule) - url = str(getMultiAdapter( - (context, self.request), name=u'absolute_url')) - focus = self.context.id.strip('+') - return '{0}/++rule++{1}/@@manage-elements#{2}'.format( + url = str(getMultiAdapter((context, self.request), name="absolute_url")) + focus = self.context.id.strip("+") + return "{}/++rule++{}/@@manage-elements#{}".format( url, rule.__name__, focus, @@ -158,4 +154,4 @@ def nextURL(self): class ContentRuleFormWrapper(layout.FormWrapper): - index = ViewPageTemplateFile('templates/contentrules-pageform.pt') + index = ViewPageTemplateFile("templates/contentrules-pageform.pt") diff --git a/plone/app/contentrules/browser/info.py b/plone/app/contentrules/browser/info.py index 9026c8e..2b2f2ea 100644 --- a/plone/app/contentrules/browser/info.py +++ b/plone/app/contentrules/browser/info.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from AccessControl import getSecurityManager from plone.contentrules.engine.interfaces import IRuleAssignable from plone.contentrules.engine.interfaces import IRuleStorage @@ -7,17 +6,15 @@ class ContentRulesInfo(BrowserView): - def show_rules_tab(self): - """Whether or not the rules tab should be shown - """ + """Whether or not the rules tab should be shown""" if not IRuleAssignable.providedBy(self.context): return False check_permission = getSecurityManager().checkPermission can_manage_rules = check_permission( - 'Content rules: Manage rules', + "Content rules: Manage rules", self.context, ) if not can_manage_rules: diff --git a/plone/app/contentrules/browser/interfaces.py b/plone/app/contentrules/browser/interfaces.py index 4d60466..a59d47d 100644 --- a/plone/app/contentrules/browser/interfaces.py +++ b/plone/app/contentrules/browser/interfaces.py @@ -1,20 +1,16 @@ -# -*- coding: utf-8 -*- from zope.browser.interfaces import IAdding from zope.interface import Interface class IContentRulesInfo(Interface): - """Site-wide information about content rules - """ + """Site-wide information about content rules""" def show_rules_tab(): - """Determine whether or not the rules tab should be shown. - """ + """Determine whether or not the rules tab should be shown.""" class IContentRulesControlPanel(Interface): - """Marker interface for rules control panel view - """ + """Marker interface for rules control panel view""" def globally_disabled(): """Wether content rules are globally disabled or not""" @@ -43,5 +39,4 @@ class IRuleActionAdding(IRuleElementAdding): class IContentRulesForm(Interface): - """Marker interface for forms that need content rules layout - """ + """Marker interface for forms that need content rules layout""" diff --git a/plone/app/contentrules/browser/navigation.py b/plone/app/contentrules/browser/navigation.py index 6238959..4bb7bda 100644 --- a/plone/app/contentrules/browser/navigation.py +++ b/plone/app/contentrules/browser/navigation.py @@ -1,25 +1,23 @@ -# -*- coding: utf-8 -*- from plone.app.contentrules import PloneMessageFactory as _ from Products.CMFCore.utils import getToolByName from Products.CMFPlone.browser.navigation import PhysicalNavigationBreadcrumbs class RuleBreadcrumbs(PhysicalNavigationBreadcrumbs): - def breadcrumbs(self): - portal_url = getToolByName(self.context, 'portal_url')() + portal_url = getToolByName(self.context, "portal_url")() return ( { - 'absolute_url': '{0}/@@rules-controlpanel'.format(portal_url), - 'Title': _( - 'title_manage_contentrules', - default=u'Content Rules', + "absolute_url": f"{portal_url}/@@rules-controlpanel", + "Title": _( + "title_manage_contentrules", + default="Content Rules", ), }, { - 'absolute_url': '{0}/@@manage-elements'.format( + "absolute_url": "{}/@@manage-elements".format( self.context.absolute_url(), ), - 'Title': self.context.title or self.context.id, + "Title": self.context.title or self.context.id, }, ) diff --git a/plone/app/contentrules/browser/rule.py b/plone/app/contentrules/browser/rule.py index 89d800d..caaa6f1 100644 --- a/plone/app/contentrules/browser/rule.py +++ b/plone/app/contentrules/browser/rule.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from Acquisition import aq_inner from Acquisition import aq_parent from plone.app.contentrules import PloneMessageFactory as _ @@ -6,32 +5,33 @@ from plone.app.contentrules.browser.formhelper import ContentRuleFormWrapper from plone.app.contentrules.browser.formhelper import EditForm from plone.app.contentrules.rule import Rule +from plone.base.utils import base_hasattr from plone.contentrules.rule.interfaces import IRuleConfiguration -from Products.CMFPlone.utils import base_hasattr from z3c.form.form import applyChanges from zope.component import getMultiAdapter class RuleAddForm(AddForm): - """An add form for rules. - """ + """An add form for rules.""" + schema = IRuleConfiguration ignoreContext = True - label = _(u'Add Rule') - description = _(u'Add a new rule. Once complete, you can manage the ' - u"rule's actions and conditions separately.") + label = _("Add Rule") + description = _( + "Add a new rule. Once complete, you can manage the " + "rule's actions and conditions separately." + ) def nextURL(self): context = aq_parent(aq_inner(self.context)) - url = str(getMultiAdapter( - (context, self.request), name=u'absolute_url')) - if base_hasattr(self.context, '_chosen_name'): - return '{0}/++rule++{1}/@@manage-elements'.format( + url = str(getMultiAdapter((context, self.request), name="absolute_url")) + if base_hasattr(self.context, "_chosen_name"): + return "{}/++rule++{}/@@manage-elements".format( url, self.context._chosen_name, ) else: - return '{0}/@@rules-controlpanel'.format(url) + return f"{url}/@@rules-controlpanel" def create(self, data): rule = Rule() @@ -44,17 +44,16 @@ class RuleAddFormView(ContentRuleFormWrapper): class RuleEditForm(EditForm): - """An edit form for rules. - """ + """An edit form for rules.""" + schema = IRuleConfiguration - label = _(u'Edit Rule') - description = _(u'Edit an existing rule.') + label = _("Edit Rule") + description = _("Edit an existing rule.") def nextURL(self): context = aq_parent(aq_inner(self.context)) - url = str(getMultiAdapter( - (context, self.request), name=u'absolute_url')) - return url + '/@@rules-controlpanel' + url = str(getMultiAdapter((context, self.request), name="absolute_url")) + return url + "/@@rules-controlpanel" class RuleEditFormView(ContentRuleFormWrapper): diff --git a/plone/app/contentrules/browser/traversal.py b/plone/app/contentrules/browser/traversal.py index 3fdc208..70416f9 100644 --- a/plone/app/contentrules/browser/traversal.py +++ b/plone/app/contentrules/browser/traversal.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from plone.contentrules.engine.interfaces import IRuleStorage from plone.contentrules.rule.interfaces import IRule from Products.CMFCore.interfaces import ISiteRoot @@ -11,7 +10,7 @@ @adapter(ISiteRoot, IBrowserRequest) @implementer(ITraversable) -class RuleNamespace(object): +class RuleNamespace: """Used to traverse to a rule. Traversing to portal/++rule++foo will retrieve the rule with id 'foo' @@ -29,7 +28,7 @@ def traverse(self, name, ignore): @adapter(IRule, IBrowserRequest) @implementer(ITraversable) -class RuleConditionNamespace(object): +class RuleConditionNamespace: """Used to traverse to a rule condition Traversing to portal/++rule++foo/++condition++1 will retrieve the second @@ -42,7 +41,7 @@ def __init__(self, context, request=None): def traverse(self, name, ignore): condition = self.context.conditions[int(name)] - traversal_id = '++condition++{0}'.format(name) + traversal_id = f"++condition++{name}" if condition.id != traversal_id: condition.__name__ = condition.id = traversal_id return condition @@ -50,7 +49,7 @@ def traverse(self, name, ignore): @adapter(IRule, IBrowserRequest) @implementer(ITraversable) -class RuleActionNamespace(object): +class RuleActionNamespace: """Used to traverse to a rule condition Traversing to portal/++rule++foo/++action++1 will retrieve the second @@ -63,7 +62,7 @@ def __init__(self, context, request=None): def traverse(self, name, ignore): action = self.context.actions[int(name)] - traversal_id = '++action++{0}'.format(name) + traversal_id = f"++action++{name}" if action.id != traversal_id: action.__name__ = action.id = traversal_id return action diff --git a/plone/app/contentrules/conditions/__init__.py b/plone/app/contentrules/conditions/__init__.py index 40a96af..e69de29 100644 --- a/plone/app/contentrules/conditions/__init__.py +++ b/plone/app/contentrules/conditions/__init__.py @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/plone/app/contentrules/conditions/fileextension.py b/plone/app/contentrules/conditions/fileextension.py index a15b7e6..81f7356 100644 --- a/plone/app/contentrules/conditions/fileextension.py +++ b/plone/app/contentrules/conditions/fileextension.py @@ -1,9 +1,9 @@ -# -*- coding: utf-8 -*- from OFS.SimpleItem import SimpleItem from plone.app.contentrules import PloneMessageFactory as _ from plone.app.contentrules.browser.formhelper import AddForm from plone.app.contentrules.browser.formhelper import ContentRuleFormWrapper from plone.app.contentrules.browser.formhelper import EditForm +from plone.app.contenttypes.interfaces import IFile from plone.contentrules.rule.interfaces import IExecutable from plone.contentrules.rule.interfaces import IRuleElementData from z3c.form import form @@ -11,11 +11,6 @@ from zope.component import adapter from zope.interface import implementer from zope.interface import Interface -from plone.app.contenttypes.interfaces import IFile -try: - from Products.ATContentTypes.interfaces import IFileContent -except ImportError: - IFileContent = None class IFileExtensionCondition(Interface): @@ -25,9 +20,9 @@ class IFileExtensionCondition(Interface): """ file_extension = schema.TextLine( - title=_(u'File extension'), - description=_(u'The file extension to check for'), - required=True + title=_("File extension"), + description=_("The file extension to check for"), + required=True, ) @@ -38,20 +33,17 @@ class FileExtensionCondition(SimpleItem): Note that we must mix in Explicit to keep Zope 2 security happy. """ - file_extension = u'' - element = 'plone.conditions.FileExtension' + file_extension = "" + element = "plone.conditions.FileExtension" @property def summary(self): - return _( - u'File extension is ${ext}', - mapping=dict(ext=self.file_extension) - ) + return _("File extension is ${ext}", mapping=dict(ext=self.file_extension)) @implementer(IExecutable) @adapter(Interface, IFileExtensionCondition, Interface) -class FileExtensionConditionExecutor(object): +class FileExtensionConditionExecutor: """The executor for this condition. This is registered as an adapter in configure.zcml @@ -66,33 +58,29 @@ def __call__(self): obj = self.event.object if IFile.providedBy(obj): - base_unit = getattr(obj, 'file', None) - name = getattr(base_unit, 'filename', None) - elif IFileContent is None: - return False - elif not IFileContent.providedBy(obj): - return False + base_unit = getattr(obj, "file", None) + name = getattr(base_unit, "filename", None) else: base_unit = obj.getFile() - get_filename = getattr(base_unit, 'getFilename', None) + get_filename = getattr(base_unit, "getFilename", None) if not get_filename: return False name = get_filename() - extension = name[name.rfind('.') + 1:] + extension = name[name.rfind(".") + 1 :] return extension == self.element.file_extension class FileExtensionAddForm(AddForm): - """An add form for file extension rule conditions. - """ + """An add form for file extension rule conditions.""" + schema = IFileExtensionCondition - label = _(u'Add File Extension Condition') + label = _("Add File Extension Condition") description = _( - u'A file extension condition can restrict a rule from ' - u'executing unless the target is a File with a particular extension.' + "A file extension condition can restrict a rule from " + "executing unless the target is a File with a particular extension." ) - form_name = _(u'Configure element') + form_name = _("Configure element") def create(self, data): c = FileExtensionCondition() @@ -109,13 +97,14 @@ class FileExtensionEditForm(EditForm): z3c.form does all the magic here. """ + schema = IFileExtensionCondition - label = _(u'Edit File Extension Condition') + label = _("Edit File Extension Condition") description = _( - u'A file extension condition can restrict a rule from ' - u'executing unless the target is a File with a particular extension.' + "A file extension condition can restrict a rule from " + "executing unless the target is a File with a particular extension." ) - form_name = _(u'Configure element') + form_name = _("Configure element") class FileExtensionEditFormView(ContentRuleFormWrapper): diff --git a/plone/app/contentrules/conditions/group.py b/plone/app/contentrules/conditions/group.py index 8b6f554..b897f31 100644 --- a/plone/app/contentrules/conditions/group.py +++ b/plone/app/contentrules/conditions/group.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from OFS.SimpleItem import SimpleItem from plone.app.contentrules import PloneMessageFactory as _ from plone.app.contentrules.browser.formhelper import AddForm @@ -21,10 +20,10 @@ class IGroupCondition(Interface): """ group_names = schema.Set( - title=_(u'Group name'), - description=_(u'The name of the group.'), + title=_("Group name"), + description=_("The name of the group."), required=True, - value_type=schema.Choice(vocabulary='plone.app.vocabularies.Groups') + value_type=schema.Choice(vocabulary="plone.app.vocabularies.Groups"), ) @@ -36,19 +35,18 @@ class GroupCondition(SimpleItem): """ group_names = [] - element = 'plone.conditions.Group' + element = "plone.conditions.Group" @property def summary(self): return _( - u'Groups are: ${names}', - mapping=dict(names=', '.join(self.group_names)) + "Groups are: ${names}", mapping=dict(names=", ".join(self.group_names)) ) @implementer(IExecutable) @adapter(Interface, IGroupCondition, Interface) -class GroupConditionExecutor(object): +class GroupConditionExecutor: """The executor for this condition. This is registered as an adapter in configure.zcml @@ -60,14 +58,12 @@ def __init__(self, context, element, event): self.event = event def __call__(self): - portal_membership = getToolByName( - self.context, 'portal_membership', None) - portal_groups = getToolByName(self.context, 'portal_groups', None) + portal_membership = getToolByName(self.context, "portal_membership", None) + portal_groups = getToolByName(self.context, "portal_groups", None) if portal_groups is None or portal_groups is None: return False member = portal_membership.getAuthenticatedMember() - groupIds = [g.getId() - for g in portal_groups.getGroupsByUserId(member.getId())] + groupIds = [g.getId() for g in portal_groups.getGroupsByUserId(member.getId())] for g in self.element.group_names: if g in groupIds: return True @@ -75,15 +71,15 @@ def __call__(self): class GroupAddForm(AddForm): - """An add form for group rule conditions. - """ + """An add form for group rule conditions.""" + schema = IGroupCondition - label = _(u'Add Group Condition') + label = _("Add Group Condition") description = _( - u'A group condition can prevent a rule from executing ' - u'unless the current user is a member of a particular group.' + "A group condition can prevent a rule from executing " + "unless the current user is a member of a particular group." ) - form_name = _(u'Configure element') + form_name = _("Configure element") def create(self, data): c = GroupCondition() @@ -96,15 +92,15 @@ class GroupAddFormView(ContentRuleFormWrapper): class GroupEditForm(EditForm): - """An edit form for group conditions - """ + """An edit form for group conditions""" + schema = IGroupCondition - label = _(u'Edit Group Condition') + label = _("Edit Group Condition") description = _( - u'A group condition can prevent a rule from executing ' - u'unless the current user is a member of a particular group.' + "A group condition can prevent a rule from executing " + "unless the current user is a member of a particular group." ) - form_name = _(u'Configure element') + form_name = _("Configure element") class GroupEditFormView(ContentRuleFormWrapper): diff --git a/plone/app/contentrules/conditions/portaltype.py b/plone/app/contentrules/conditions/portaltype.py index 3919821..81d1f7e 100644 --- a/plone/app/contentrules/conditions/portaltype.py +++ b/plone/app/contentrules/conditions/portaltype.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from Acquisition import aq_base from Acquisition import aq_inner from OFS.SimpleItem import SimpleItem @@ -13,10 +12,10 @@ from z3c.form import form from zope import schema from zope.component import adapter +from zope.component.hooks import getSite from zope.i18n import translate from zope.interface import implementer from zope.interface import Interface -from zope.component.hooks import getSite class IPortalTypeCondition(Interface): @@ -26,12 +25,12 @@ class IPortalTypeCondition(Interface): """ check_types = schema.Set( - title=_(u'Content type'), - description=_(u'The content type to check for.'), + title=_("Content type"), + description=_("The content type to check for."), required=True, value_type=schema.Choice( - vocabulary='plone.app.vocabularies.ReallyUserFriendlyTypes' - ) + vocabulary="plone.app.vocabularies.ReallyUserFriendlyTypes" + ), ) @@ -43,27 +42,24 @@ class PortalTypeCondition(SimpleItem): """ check_types = [] - element = 'plone.conditions.PortalType' + element = "plone.conditions.PortalType" @property def summary(self): portal = getSite() - portal_types = getToolByName(portal, 'portal_types') + portal_types = getToolByName(portal, "portal_types") titles = [] for name in self.check_types: fti = getattr(portal_types, name, None) if fti is not None: title = translate(fti.Title(), context=portal.REQUEST) titles.append(title) - return _( - u'Content types are: ${names}', - mapping=dict(names=', '.join(titles)) - ) + return _("Content types are: ${names}", mapping=dict(names=", ".join(titles))) @implementer(IExecutable) @adapter(Interface, IPortalTypeCondition, Interface) -class PortalTypeConditionExecutor(object): +class PortalTypeConditionExecutor: """The executor for this condition. This is registered as an adapter in configure.zcml @@ -76,7 +72,7 @@ def __init__(self, context, element, event): def __call__(self): obj = aq_inner(self.event.object) - if not hasattr(aq_base(obj), 'getTypeInfo'): + if not hasattr(aq_base(obj), "getTypeInfo"): return False elif ITypesTool.providedBy(obj): # types tool have a getTypeInfo method @@ -89,15 +85,14 @@ def __call__(self): class PortalTypeAddForm(AddForm): - """An add form for portal type conditions. - """ + """An add form for portal type conditions.""" + schema = IPortalTypeCondition - label = _(u'Add Content Type Condition') + label = _("Add Content Type Condition") description = _( - u'A portal type condition makes the rule apply only to ' - u'certain content types.' + "A portal type condition makes the rule apply only to " "certain content types." ) - form_name = _(u'Configure element') + form_name = _("Configure element") def create(self, data): c = PortalTypeCondition() @@ -110,15 +105,14 @@ class PortalTypeAddFormView(ContentRuleFormWrapper): class PortalTypeEditForm(EditForm): - """An edit form for portal type conditions - """ + """An edit form for portal type conditions""" + schema = IPortalTypeCondition - label = _(u'Edit Content Type Condition') + label = _("Edit Content Type Condition") description = _( - u'A portal type condition makes the rule apply only to certain ' - u'content types.' + "A portal type condition makes the rule apply only to certain " "content types." ) - form_name = _(u'Configure element') + form_name = _("Configure element") class PortalTypeEditFormView(ContentRuleFormWrapper): diff --git a/plone/app/contentrules/conditions/role.py b/plone/app/contentrules/conditions/role.py index a95ceac..7967310 100644 --- a/plone/app/contentrules/conditions/role.py +++ b/plone/app/contentrules/conditions/role.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from Acquisition import aq_inner from OFS.SimpleItem import SimpleItem from plone.app.contentrules import PloneMessageFactory as _ @@ -22,10 +21,10 @@ class IRoleCondition(Interface): """ role_names = schema.Set( - title=_(u'Roles'), - description=_(u'The roles to check for.'), + title=_("Roles"), + description=_("The roles to check for."), required=True, - value_type=schema.Choice(vocabulary='plone.app.vocabularies.Roles') + value_type=schema.Choice(vocabulary="plone.app.vocabularies.Roles"), ) @@ -37,19 +36,16 @@ class RoleCondition(SimpleItem): """ role_names = [] - element = 'plone.conditions.Role' + element = "plone.conditions.Role" @property def summary(self): - return _( - u'Roles are: ${names}', - mapping=dict(names=', '.join(self.role_names)) - ) + return _("Roles are: ${names}", mapping=dict(names=", ".join(self.role_names))) @implementer(IExecutable) @adapter(Interface, IRoleCondition, Interface) -class RoleConditionExecutor(object): +class RoleConditionExecutor: """The executor for this condition. This is registered as an adapter in configure.zcml @@ -61,13 +57,11 @@ def __init__(self, context, element, event): self.event = event def __call__(self): - portal_membership = getToolByName( - self.context, 'portal_membership', None) + portal_membership = getToolByName(self.context, "portal_membership", None) if portal_membership is None: return False member = portal_membership.getAuthenticatedMember() - roles_in_context = member.getRolesInContext( - aq_inner(self.event.object)) + roles_in_context = member.getRolesInContext(aq_inner(self.event.object)) for r in self.element.role_names: if r in roles_in_context: return True @@ -75,15 +69,15 @@ def __call__(self): class RoleAddForm(AddForm): - """An add form for role rule conditions. - """ + """An add form for role rule conditions.""" + schema = IRoleCondition - label = _(u'Add Role Condition') + label = _("Add Role Condition") description = _( - u'A role condition can prevent rules from executing unless ' - u'the current user has a particular role.' + "A role condition can prevent rules from executing unless " + "the current user has a particular role." ) - form_name = _(u'Configure element') + form_name = _("Configure element") def create(self, data): c = RoleCondition() @@ -96,15 +90,15 @@ class RoleAddFormView(ContentRuleFormWrapper): class RoleEditForm(EditForm): - """An edit form for role conditions - """ + """An edit form for role conditions""" + schema = IRoleCondition - label = _(u'Add Role Condition') + label = _("Add Role Condition") description = _( - u'A role condition can prevent rules from executing unless ' - u'the current user has a particular role.' + "A role condition can prevent rules from executing unless " + "the current user has a particular role." ) - form_name = _(u'Configure element') + form_name = _("Configure element") class RoleEditFormView(ContentRuleFormWrapper): diff --git a/plone/app/contentrules/conditions/talesexpression.py b/plone/app/contentrules/conditions/talesexpression.py index 1a351b0..e23344e 100644 --- a/plone/app/contentrules/conditions/talesexpression.py +++ b/plone/app/contentrules/conditions/talesexpression.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from OFS.SimpleItem import SimpleItem from plone.app.contentrules import PloneMessageFactory as _ from plone.app.contentrules.browser.formhelper import AddForm @@ -23,9 +22,10 @@ class ITalesExpressionCondition(Interface): """ tales_expression = schema.TextLine( - title=_(u'TALES expression'), - description=_(u'The TALES expression to check.'), - required=True) + title=_("TALES expression"), + description=_("The TALES expression to check."), + required=True, + ) @implementer(ITalesExpressionCondition, IRuleElementData) @@ -34,18 +34,20 @@ class TalesExpressionCondition(SimpleItem): element. """ - tales_expression = '' - element = 'plone.conditions.TalesExpression' + tales_expression = "" + element = "plone.conditions.TalesExpression" @property def summary(self): - return _(u'TALES expression is: ${tales_expression}', - mapping={'tales_expression': self.tales_expression}) + return _( + "TALES expression is: ${tales_expression}", + mapping={"tales_expression": self.tales_expression}, + ) @implementer(IExecutable) @adapter(Interface, ITalesExpressionCondition, Interface) -class TalesExpressionConditionExecutor(object): +class TalesExpressionConditionExecutor: """The executor for this condition. This is registered as an adapter in configure.zcml @@ -59,22 +61,24 @@ def __init__(self, context, element, event): def __call__(self): object = self.event.object folder = self.context - portal = getToolByName(folder, 'portal_url').getPortalObject() + portal = getToolByName(folder, "portal_url").getPortalObject() expression = self.element.tales_expression ec = createExprContext(folder, portal, object) # Workaround CMFCore/PageTemplates issue with unicode missing context - ec.contexts['context'] = ec.contexts['here'] + ec.contexts["context"] = ec.contexts["here"] return bool(Expression(expression)(ec)) class TalesExpressionAddForm(AddForm): - """An add form for tales expression condition. - """ + """An add form for tales expression condition.""" + schema = ITalesExpressionCondition - label = _(u'Add TALES Expression Condition') - description = _(u'A TALES expression condition makes the rule apply ' - u'only if TALES expression is not False in context.') - form_name = _(u'Configure element') + label = _("Add TALES Expression Condition") + description = _( + "A TALES expression condition makes the rule apply " + "only if TALES expression is not False in context." + ) + form_name = _("Configure element") def create(self, data): c = TalesExpressionCondition() @@ -87,13 +91,15 @@ class TalesExpressionAddFormView(ContentRuleFormWrapper): class TalesExpressionEditForm(EditForm): - """An edit form for TALES expression condition - """ + """An edit form for TALES expression condition""" + schema = ITalesExpressionCondition - label = _(u'Edit TALES Expression Condition') - description = _(u'A TALES expression condition makes the rule apply ' - u'only if TALES expression is not False in context.') - form_name = _(u'Configure element') + label = _("Edit TALES Expression Condition") + description = _( + "A TALES expression condition makes the rule apply " + "only if TALES expression is not False in context." + ) + form_name = _("Configure element") class TalesExpressionEditFormView(ContentRuleFormWrapper): diff --git a/plone/app/contentrules/conditions/wfstate.py b/plone/app/contentrules/conditions/wfstate.py index 5f2042a..8cc960c 100644 --- a/plone/app/contentrules/conditions/wfstate.py +++ b/plone/app/contentrules/conditions/wfstate.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from OFS.SimpleItem import SimpleItem from plone.app.contentrules import PloneMessageFactory as _ from plone.app.contentrules.browser.formhelper import AddForm @@ -21,12 +20,10 @@ class IWorkflowStateCondition(Interface): """ wf_states = schema.Set( - title=_(u'Workflow state'), - description=_(u'The workflow states to check for.'), + title=_("Workflow state"), + description=_("The workflow states to check for."), required=True, - value_type=schema.Choice( - vocabulary='plone.app.vocabularies.WorkflowStates' - ) + value_type=schema.Choice(vocabulary="plone.app.vocabularies.WorkflowStates"), ) @@ -37,21 +34,20 @@ class WorkflowStateCondition(SimpleItem): """ wf_states = [] - element = 'plone.conditions.WorkflowState' + element = "plone.conditions.WorkflowState" @property def summary(self): return _( - u'Workflow states are: ${states}', - mapping=dict(states=', '.join(self.wf_states)) + "Workflow states are: ${states}", + mapping=dict(states=", ".join(self.wf_states)), ) @implementer(IExecutable) @adapter(Interface, IWorkflowStateCondition, Interface) -class WorkflowStateConditionExecutor(object): - """The executor for this condition. - """ +class WorkflowStateConditionExecutor: + """The executor for this condition.""" def __init__(self, context, element, event): self.context = context @@ -59,24 +55,25 @@ def __init__(self, context, element, event): self.event = event def __call__(self): - portal_workflow = getToolByName(self.context, 'portal_workflow', None) + portal_workflow = getToolByName(self.context, "portal_workflow", None) if portal_workflow is None: return False - state = portal_workflow.getInfoFor( - self.event.object, 'review_state', None) + state = portal_workflow.getInfoFor(self.event.object, "review_state", None) if state is None: return False return state in self.element.wf_states class WorkflowStateAddForm(AddForm): - """An add form for workflow state conditions. - """ + """An add form for workflow state conditions.""" + schema = IWorkflowStateCondition - label = _(u'Add Workflow State Condition') - description = _(u'A workflow state condition can restrict rules to ' - u'objects in particular workflow states') - form_name = _(u'Configure element') + label = _("Add Workflow State Condition") + description = _( + "A workflow state condition can restrict rules to " + "objects in particular workflow states" + ) + form_name = _("Configure element") def create(self, data): c = WorkflowStateCondition() @@ -93,11 +90,14 @@ class WorkflowStateEditForm(EditForm): z3c.form does all the magic here. """ + schema = IWorkflowStateCondition - label = _(u'Edit Workflow State Condition') - description = _(u'A workflow state condition can restrict rules to ' - u'objects in particular workflow states') - form_name = _(u'Configure element') + label = _("Edit Workflow State Condition") + description = _( + "A workflow state condition can restrict rules to " + "objects in particular workflow states" + ) + form_name = _("Configure element") class WorkflowStateEditFormView(ContentRuleFormWrapper): diff --git a/plone/app/contentrules/conditions/wftransition.py b/plone/app/contentrules/conditions/wftransition.py index a1b914c..ff82a58 100644 --- a/plone/app/contentrules/conditions/wftransition.py +++ b/plone/app/contentrules/conditions/wftransition.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from OFS.SimpleItem import SimpleItem from plone.app.contentrules import PloneMessageFactory as _ from plone.app.contentrules.browser.formhelper import AddForm @@ -21,12 +20,12 @@ class IWorkflowTransitionCondition(Interface): """ wf_transitions = schema.Set( - title=_(u'Workflow transition'), - description=_(u'The workflow transitions to check for.'), + title=_("Workflow transition"), + description=_("The workflow transitions to check for."), required=True, value_type=schema.Choice( - vocabulary='plone.app.vocabularies.WorkflowTransitions' - ) + vocabulary="plone.app.vocabularies.WorkflowTransitions" + ), ) @@ -37,19 +36,20 @@ class WorkflowTransitionCondition(SimpleItem): """ wf_transitions = [] - element = 'plone.conditions.WorkflowTransition' + element = "plone.conditions.WorkflowTransition" @property def summary(self): - return _(u'Workflow transitions are: ${transitions}', - mapping=dict(transitions=', '.join(self.wf_transitions))) + return _( + "Workflow transitions are: ${transitions}", + mapping=dict(transitions=", ".join(self.wf_transitions)), + ) @implementer(IExecutable) @adapter(Interface, IWorkflowTransitionCondition, IActionSucceededEvent) -class WorkflowTransitionConditionExecutor(object): - """The executor for this condition. - """ +class WorkflowTransitionConditionExecutor: + """The executor for this condition.""" def __init__(self, context, element, event): self.context = context @@ -61,13 +61,15 @@ def __call__(self): class WorkflowTransitionAddForm(AddForm): - """An add form for workflow transition conditions. - """ + """An add form for workflow transition conditions.""" + schema = IWorkflowTransitionCondition - label = _(u'Add Workflow Transition Condition') - description = _(u'A workflow transition condition can restrict rules to ' - u'execute only after a certain transition.') - form_name = _(u'Configure element') + label = _("Add Workflow Transition Condition") + description = _( + "A workflow transition condition can restrict rules to " + "execute only after a certain transition." + ) + form_name = _("Configure element") def create(self, data): c = WorkflowTransitionCondition() @@ -84,11 +86,14 @@ class WorkflowTransitionEditForm(EditForm): z3c.form does all the magic here. """ + schema = IWorkflowTransitionCondition - label = _(u'Edit Workflow Transition Condition') - description = _(u'A workflow transition condition can restrict rules to ' - u'execute only after a certain transition.') - form_name = _(u'Configure element') + label = _("Edit Workflow Transition Condition") + description = _( + "A workflow transition condition can restrict rules to " + "execute only after a certain transition." + ) + form_name = _("Configure element") class WorkflowTransitionEditFormView(ContentRuleFormWrapper): diff --git a/plone/app/contentrules/configure.zcml b/plone/app/contentrules/configure.zcml index 1262ffc..eca3cbe 100644 --- a/plone/app/contentrules/configure.zcml +++ b/plone/app/contentrules/configure.zcml @@ -27,18 +27,6 @@ - - - - - - - - - - - - diff --git a/plone/app/contentrules/exportimport/__init__.py b/plone/app/contentrules/exportimport/__init__.py index 40a96af..e69de29 100644 --- a/plone/app/contentrules/exportimport/__init__.py +++ b/plone/app/contentrules/exportimport/__init__.py @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/plone/app/contentrules/exportimport/interfaces.py b/plone/app/contentrules/exportimport/interfaces.py index e04dba8..bd74ed8 100644 --- a/plone/app/contentrules/exportimport/interfaces.py +++ b/plone/app/contentrules/exportimport/interfaces.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from zope.interface import Interface diff --git a/plone/app/contentrules/exportimport/rules.py b/plone/app/contentrules/exportimport/rules.py index 6dda435..c34ac83 100644 --- a/plone/app/contentrules/exportimport/rules.py +++ b/plone/app/contentrules/exportimport/rules.py @@ -1,7 +1,9 @@ -# -*- coding: utf-8 -*- from Acquisition import aq_base +from lxml import etree from plone.app.contentrules import api -from plone.app.contentrules.exportimport.interfaces import IRuleElementExportImportHandler # noqa +from plone.app.contentrules.exportimport.interfaces import ( + IRuleElementExportImportHandler, +) from plone.app.contentrules.rule import get_assignments from plone.app.contentrules.rule import Rule from plone.contentrules.engine.interfaces import IRuleAssignmentManager @@ -10,12 +12,15 @@ from plone.contentrules.rule.interfaces import IRuleCondition from plone.contentrules.rule.interfaces import IRuleElement from plone.contentrules.rule.interfaces import IRuleElementData +from plone.supermodel.utils import elementToValue +from plone.supermodel.utils import valueToElement from Products.CMFCore.interfaces import ISiteRoot from Products.GenericSetup.interfaces import IBody from Products.GenericSetup.interfaces import ISetupEnviron from Products.GenericSetup.utils import _getDottedName from Products.GenericSetup.utils import _resolveDottedName from Products.GenericSetup.utils import XMLAdapterBase +from xml.dom import minidom from zope.component import adapter from zope.component import getUtility from zope.component import queryMultiAdapter @@ -26,25 +31,18 @@ from zope.schema.interfaces import ICollection from zope.schema.interfaces import IField from zope.schema.interfaces import IFromUnicode -from plone.supermodel.utils import elementToValue, valueToElement -from lxml import etree -from xml.dom import minidom - - -import six def as_bool(string, default=False): if string is None or not str(string): return default - return string.lower() == 'true' + return string.lower() == "true" @adapter(Interface) @implementer(IRuleElementExportImportHandler) -class PropertyRuleElementExportImportHandler(object): - """Import portlet assignment settings based on zope.schema properties - """ +class PropertyRuleElementExportImportHandler: + """Import portlet assignment settings based on zope.schema properties""" def __init__(self, element): data = IRuleElementData(element) @@ -57,7 +55,7 @@ def import_element(self, node): return for child in node.childNodes: - if child.nodeName == 'property': + if child.nodeName == "property": self.import_node(self.descriptor.schema, child) def export_element(self, doc, node): @@ -72,12 +70,12 @@ def export_element(self, doc, node): child = self.export_field(doc, field) node.appendChild(child) + # Helper methods def import_node(self, interface, child): - """Import a single node - """ - property_name = child.getAttribute('name') + """Import a single node""" + property_name = child.getAttribute("name") field = interface.get(property_name, None) if field is None: @@ -93,20 +91,19 @@ def import_node(self, interface, child): field.set(self.element, value) def export_field(self, doc, field): - """Turn a zope.schema field into a node and return it - """ + """Turn a zope.schema field into a node and return it""" field = field.bind(self.element) value = field.get(self.element) - child = doc.createElement('property') - child.setAttribute('name', field.__name__) + child = doc.createElement("property") + child.setAttribute("name", field.__name__) # supermodel gives us an etree node but GS uses minidom so we need to convert it node = valueToElement(field, value) if node.text: - child.appendChild(doc.createTextNode(six.text_type(node.text))) - # Assumes there are not other text nodes and we can throw away the parent node + child.appendChild(doc.createTextNode(str(node.text))) + # Assumes there are not other text nodes and we can throw away the parent node for node in node.iterchildren(): xml = etree.tostring(node, encoding="utf8") child.appendChild(minidom.parseString(xml).firstChild) @@ -116,33 +113,29 @@ def export_field(self, doc, field): @adapter(ISiteRoot, ISetupEnviron) @implementer(IBody) class RulesXMLAdapter(XMLAdapterBase): - """In- and exporter for a local portlet configuration - """ + """In- and exporter for a local portlet configuration""" - name = 'contentrules' - _LOGGER_ID = 'contentrules' + name = "contentrules" + _LOGGER_ID = "contentrules" def _exportNode(self): - """Export rules - """ - node = self._doc.createElement('contentrules') + """Export rules""" + node = self._doc.createElement("contentrules") child = self._extractRules() if child is not None: node.appendChild(child) - self._logger.info('Content rules exported') + self._logger.info("Content rules exported") return node def _importNode(self, node): - """Import rules - """ + """Import rules""" if self.environ.shouldPurge(): self._purgeRules() self._initRules(node) - self._logger.info('Content rules imported') + self._logger.info("Content rules imported") def _purgeRules(self): - """Purge all registered rules - """ + """Purge all registered rules""" storage = queryUtility(IRuleStorage) if storage is not None: # If we delete a rule, assignments will be removed as well @@ -150,8 +143,7 @@ def _purgeRules(self): del storage[k] def _initRules(self, node): - """Import rules from the given node - """ + """Import rules from the given node""" site = self.environ.getSite() storage = queryUtility(IRuleStorage) @@ -159,10 +151,10 @@ def _initRules(self, node): return for child in node.childNodes: - if child.nodeName == 'rule': + if child.nodeName == "rule": rule = None - name = child.getAttribute('name') + name = child.getAttribute("name") if name: rule = storage.get(name, None) @@ -180,30 +172,29 @@ def _initRules(self, node): del rule.conditions[:] del rule.actions[:] - rule.title = child.getAttribute('title') - rule.description = child.getAttribute('description') - event_name = child.getAttribute('event') + rule.title = child.getAttribute("title") + rule.description = child.getAttribute("description") + event_name = child.getAttribute("event") rule.event = _resolveDottedName(event_name) if not rule.event: - raise ImportError('Can not import {0}'.format(event_name)) + raise ImportError(f"Can not import {event_name}") - rule.enabled = as_bool(child.getAttribute('enabled'), True) - rule.stop = as_bool(child.getAttribute('stop-after')) - rule.cascading = as_bool(child.getAttribute('cascading')) + rule.enabled = as_bool(child.getAttribute("enabled"), True) + rule.stop = as_bool(child.getAttribute("stop-after")) + rule.cascading = as_bool(child.getAttribute("cascading")) # Aq-wrap to enable complex setters for elements below # to work rule = rule.__of__(site) for rule_config_node in child.childNodes: - if rule_config_node.nodeName == 'conditions': + if rule_config_node.nodeName == "conditions": for condition_node in rule_config_node.childNodes: - if not condition_node.nodeName == 'condition': + if not condition_node.nodeName == "condition": continue - type_ = condition_node.getAttribute('type') - element_type = getUtility( - IRuleCondition, name=type_) + type_ = condition_node.getAttribute("type") + element_type = getUtility(IRuleCondition, name=type_) if element_type.factory is None: continue @@ -212,18 +203,17 @@ def _initRules(self, node): # Aq-wrap in case of complex setters condition = condition.__of__(rule) - handler = IRuleElementExportImportHandler( - condition) + handler = IRuleElementExportImportHandler(condition) handler.import_element(condition_node) rule.conditions.append(aq_base(condition)) - elif rule_config_node.nodeName == 'actions': + elif rule_config_node.nodeName == "actions": for action_node in rule_config_node.childNodes: - if not action_node.nodeName == 'action': + if not action_node.nodeName == "action": continue - type_ = action_node.getAttribute('type') + type_ = action_node.getAttribute("type") element_type = getUtility(IRuleAction, name=type_) if element_type.factory is None: continue @@ -238,9 +228,9 @@ def _initRules(self, node): rule.actions.append(aq_base(action)) - elif child.nodeName == 'assignment': - location = child.getAttribute('location') - if location.startswith('/'): + elif child.nodeName == "assignment": + location = child.getAttribute("location") + if location.startswith("/"): location = location[1:] try: @@ -248,17 +238,17 @@ def _initRules(self, node): except KeyError: continue - name = child.getAttribute('name') - api.assign_rule(container, name, - enabled=as_bool(child.getAttribute('enabled')), - bubbles=as_bool(child.getAttribute('bubbles')), - insert_before=child.getAttribute( - 'insert-before'), - ) + name = child.getAttribute("name") + api.assign_rule( + container, + name, + enabled=as_bool(child.getAttribute("enabled")), + bubbles=as_bool(child.getAttribute("bubbles")), + insert_before=child.getAttribute("insert-before"), + ) def _extractRules(self): - """Extract rules to a document fragment - """ + """Extract rules to a document fragment""" site = self.environ.getSite() storage = queryUtility(IRuleStorage) @@ -269,15 +259,15 @@ def _extractRules(self): assignment_paths = set() for name, rule in sorted(storage.items()): - rule_node = self._doc.createElement('rule') - - rule_node.setAttribute('name', name) - rule_node.setAttribute('title', rule.title) - rule_node.setAttribute('description', rule.description) - rule_node.setAttribute('event', _getDottedName(rule.event)) - rule_node.setAttribute('enabled', str(rule.enabled)) - rule_node.setAttribute('stop-after', str(rule.stop)) - rule_node.setAttribute('cascading', str(rule.cascading)) + rule_node = self._doc.createElement("rule") + + rule_node.setAttribute("name", name) + rule_node.setAttribute("title", rule.title) + rule_node.setAttribute("description", rule.description) + rule_node.setAttribute("event", _getDottedName(rule.event)) + rule_node.setAttribute("enabled", str(rule.enabled)) + rule_node.setAttribute("stop-after", str(rule.stop)) + rule_node.setAttribute("cascading", str(rule.cascading)) # Aq-wrap so that exporting fields with clever getters or # vocabularies will work. We also aq-wrap conditions and # actions below. @@ -285,13 +275,13 @@ def _extractRules(self): rule = rule.__of__(site) # Add conditions - conditions_node = self._doc.createElement('conditions') + conditions_node = self._doc.createElement("conditions") for condition in rule.conditions: condition_data = IRuleElementData(condition) condition = condition.__of__(rule) - condition_node = self._doc.createElement('condition') - condition_node.setAttribute('type', condition_data.element) + condition_node = self._doc.createElement("condition") + condition_node.setAttribute("type", condition_data.element) handler = IRuleElementExportImportHandler(condition) handler.export_element(self._doc, condition_node) @@ -299,13 +289,13 @@ def _extractRules(self): rule_node.appendChild(conditions_node) # Add actions - actions_node = self._doc.createElement('actions') + actions_node = self._doc.createElement("actions") for action in rule.actions: action_data = IRuleElementData(action) action = action.__of__(rule) - action_node = self._doc.createElement('action') - action_node.setAttribute('type', action_data.element) + action_node = self._doc.createElement("action") + action_node.setAttribute("type", action_data.element) handler = IRuleElementExportImportHandler(action) handler.export_element(self._doc, action_node) @@ -317,7 +307,7 @@ def _extractRules(self): # Export assignments last - this is necessary to ensure they # are orderd properly - site_path_length = len('/'.join(site.getPhysicalPath())) + site_path_length = len("/".join(site.getPhysicalPath())) for path in sorted(assignment_paths): try: container = site.unrestrictedTraverse(path) @@ -330,26 +320,22 @@ def _extractRules(self): location = path[site_path_length:] for name, assignment in sorted(assignable.items()): - assignment_node = self._doc.createElement('assignment') - assignment_node.setAttribute('location', location) - assignment_node.setAttribute('name', name) - assignment_node.setAttribute( - 'enabled', str(assignment.enabled)) - assignment_node.setAttribute( - 'bubbles', str(assignment.bubbles)) + assignment_node = self._doc.createElement("assignment") + assignment_node.setAttribute("location", location) + assignment_node.setAttribute("name", name) + assignment_node.setAttribute("enabled", str(assignment.enabled)) + assignment_node.setAttribute("bubbles", str(assignment.bubbles)) fragment.appendChild(assignment_node) return fragment def importRules(context): - """Import content rules - """ + """Import content rules""" site = context.getSite() - importer = queryMultiAdapter((site, context), IBody, - name=u'plone.contentrules') + importer = queryMultiAdapter((site, context), IBody, name="plone.contentrules") if importer is not None: - filename = '{0}{1}'.format(importer.name, importer.suffix) + filename = f"{importer.name}{importer.suffix}" body = context.readDataFile(filename) if body is not None: importer.filename = filename # for error reporting @@ -357,17 +343,15 @@ def importRules(context): def exportRules(context): - """Export content rules - """ + """Export content rules""" site = context.getSite() - exporter = queryMultiAdapter((site, context), IBody, - name=u'plone.contentrules') + exporter = queryMultiAdapter((site, context), IBody, name="plone.contentrules") if exporter is not None: - filename = '{0}{1}'.format(exporter.name, exporter.suffix) + filename = f"{exporter.name}{exporter.suffix}" body = exporter.body # make sure it's encoded as earlier version of GS didn't do this - if isinstance(body, six.text_type): - encoding = context.getEncoding() or 'utf-8' + if isinstance(body, str): + encoding = context.getEncoding() or "utf-8" body = body.encode(encoding) if body is not None: context.writeDataFile(filename, body, exporter.mime_type) diff --git a/plone/app/contentrules/handlers.py b/plone/app/contentrules/handlers.py index b105cb0..b9b62ec 100644 --- a/plone/app/contentrules/handlers.py +++ b/plone/app/contentrules/handlers.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from Acquisition import aq_inner from Acquisition import aq_parent from plone.app.discussion.interfaces import IComment @@ -24,17 +23,17 @@ def _get_uid(context): return uid try: - return '/'.join(context.getPhysicalPath()) + return "/".join(context.getPhysicalPath()) except AttributeError: pass try: return context.id except AttributeError: - return '' + return "" -class DuplicateRuleFilter(object): +class DuplicateRuleFilter: """A filter which can prevent rules from being executed more than once regardless of context. """ @@ -48,12 +47,20 @@ def reset(self): self.cascade = False def __call__(self, context, rule, event): - exec_context = getattr(event, 'object', context) + exec_context = getattr(event, "object", context) uid = _get_uid(exec_context) - if (uid, rule.__name__, ) in self.executed: + if ( + uid, + rule.__name__, + ) in self.executed: return False else: - self.executed.add((uid, rule.__name__, )) + self.executed.add( + ( + uid, + rule.__name__, + ) + ) return True @@ -62,20 +69,18 @@ def __call__(self, context, rule, event): def init(): - if not hasattr(_status, 'rule_filter'): + if not hasattr(_status, "rule_filter"): _status.rule_filter = DuplicateRuleFilter() def close(event): - """Close the event processing when the request ends - """ - if hasattr(_status, 'rule_filter'): + """Close the event processing when the request ends""" + if hasattr(_status, "rule_filter"): _status.rule_filter.reset() def execute(context, event): - """Execute all rules relative to the context, and bubble as appropriate. - """ + """Execute all rules relative to the context, and bubble as appropriate.""" # Do nothing if there is no rule storage or it is not active storage = queryUtility(IRuleStorage) if storage is None or not storage.active: @@ -123,17 +128,17 @@ def execute(context, event): # execute rules again rule_filter.in_progress = False + # Event handlers def execute_rules(event): - """ When an action is invoked on an object, - execute rules assigned to its parent. - Base action executor handler """ + """When an action is invoked on an object, + execute rules assigned to its parent. + Base action executor handler""" execute(aq_parent(aq_inner(event.object)), event) def added(event): - """When an object is added, execute rules assigned to its new parent. - """ + """When an object is added, execute rules assigned to its new parent.""" obj = event.object if IContentish.providedBy(obj) or IComment.providedBy(obj): @@ -144,7 +149,7 @@ def added(event): def removed(event): """When an IObjectRemovedEvent was received, execute rules assigned to its - previous parent. + previous parent. """ obj = event.object if not (IContentish.providedBy(obj) or IComment.providedBy(obj)): @@ -154,8 +159,7 @@ def removed(event): def modified(event): - """When an object is modified, execute rules assigned to its parent - """ + """When an object is modified, execute rules assigned to its parent""" obj = event.object if not (IContentish.providedBy(obj) or IComment.providedBy(obj)): @@ -175,8 +179,7 @@ def modified(event): def copied(event): - """When an object is copied, execute rules assigned to its parent - """ + """When an object is copied, execute rules assigned to its parent""" obj = event.object if not (IContentish.providedBy(obj) or IComment.providedBy(obj)): return @@ -197,18 +200,15 @@ def execute_user_rules(event): def user_created(event): - """When a user has been created, execute rules assigned to the Plonesite. - """ + """When a user has been created, execute rules assigned to the Plonesite.""" execute_user_rules(event) def user_logged_in(event): - """When a user is logged in, execute rules assigned to the Plonesite. - """ + """When a user is logged in, execute rules assigned to the Plonesite.""" execute_user_rules(event) def user_logged_out(event): - """When a user is logged out, execute rules assigned to the Plonesite. - """ + """When a user is logged out, execute rules assigned to the Plonesite.""" execute_user_rules(event) diff --git a/plone/app/contentrules/namechooser.py b/plone/app/contentrules/namechooser.py index 00ce7b6..f85bfb6 100644 --- a/plone/app/contentrules/namechooser.py +++ b/plone/app/contentrules/namechooser.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from zope.container.contained import NameChooser from zope.container.interfaces import INameChooser from zope.interface import implementer @@ -9,8 +8,7 @@ @implementer(INameChooser) class RuleNameChooser(NameChooser): - """A name chooser for content rules. - """ + """A name chooser for content rules.""" def __init__(self, context): self.context = context @@ -22,10 +20,10 @@ def chooseName(self, name, object): name = object.__class__.__name__.lower() i = 1 - new_name = '{0}-{1}'.format(name, i) + new_name = f"{name}-{i}" while new_name in container and i <= ATTEMPTS: i += 1 - new_name = '{0}-{1}'.format(name, i) + new_name = f"{name}-{i}" self.checkName(new_name, object) return new_name diff --git a/plone/app/contentrules/rule.py b/plone/app/contentrules/rule.py index ce79112..a7a652b 100644 --- a/plone/app/contentrules/rule.py +++ b/plone/app/contentrules/rule.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from Acquisition import aq_base from BTrees.OOBTree import OOSet from OFS.SimpleItem import SimpleItem @@ -11,7 +10,7 @@ from zope.component import queryUtility -ANNOTATION_KEY = 'plone.app.contentrules.ruleassignments' +ANNOTATION_KEY = "plone.app.contentrules.ruleassignments" class Rule(SimpleItem, BaseRule): @@ -19,11 +18,11 @@ class Rule(SimpleItem, BaseRule): identical. """ - __name__ = u'' + __name__ = "" @property def id(self): - return '++rule++{0}'.format(self.__name__) + return f"++rule++{self.__name__}" def get_assignments(rule): @@ -59,8 +58,7 @@ def rule_removed(rule, event): def container_moved(container, event): - if event.oldParent is None or event.newParent is None or \ - event.oldName is None: + if event.oldParent is None or event.newParent is None or event.oldName is None: return assignable = IRuleAssignmentManager(container, None) @@ -69,15 +67,15 @@ def container_moved(container, event): if assignable is None or storage is None: return - old_path = '{0}/{1}'.format( - '/'.join(event.oldParent.getPhysicalPath()), + old_path = "{}/{}".format( + "/".join(event.oldParent.getPhysicalPath()), event.oldName, ) - new_path = '/'.join(container.getPhysicalPath()) + new_path = "/".join(container.getPhysicalPath()) if aq_base(event.object) is not aq_base(container): - new_path_of_moved = '/'.join(event.object.getPhysicalPath()) - old_path = old_path + new_path[len(new_path_of_moved):] + new_path_of_moved = "/".join(event.object.getPhysicalPath()) + old_path = old_path + new_path[len(new_path_of_moved) :] for rule_name in assignable.keys(): rule = storage.get(rule_name, None) @@ -96,7 +94,7 @@ def container_removed(container, event): if assignable is None or storage is None: return - path = '/'.join(container.getPhysicalPath()) + path = "/".join(container.getPhysicalPath()) for rule_name in assignable.keys(): rule = storage.get(rule_name, None) if rule is not None: diff --git a/plone/app/contentrules/testing.py b/plone/app/contentrules/testing.py index 30ebfca..1839443 100644 --- a/plone/app/contentrules/testing.py +++ b/plone/app/contentrules/testing.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from plone.app.contenttypes.testing import PLONE_APP_CONTENTTYPES_FIXTURE from plone.app.testing import FunctionalTesting from plone.app.testing import IntegrationTesting @@ -13,7 +12,7 @@ class PloneAppContentrulesLayer(PloneSandboxLayer): defaultBases = (PLONE_APP_CONTENTTYPES_FIXTURE,) def setUpZope(self, app, configurationContext): - self.loadZCML('testing.zcml', package=plone.app.contentrules.tests) + self.loadZCML("testing.zcml", package=plone.app.contentrules.tests) PLONE_APP_CONTENTRULES_FIXTURE = PloneAppContentrulesLayer() @@ -21,11 +20,11 @@ def setUpZope(self, app, configurationContext): PLONE_APP_CONTENTRULES_INTEGRATION_TESTING = IntegrationTesting( bases=(PLONE_APP_CONTENTRULES_FIXTURE, MOCK_MAILHOST_FIXTURE), - name='PloneAppContentrulesLayer:IntegrationTesting', + name="PloneAppContentrulesLayer:IntegrationTesting", ) PLONE_APP_CONTENTRULES_FUNCTIONAL_TESTING = FunctionalTesting( bases=(PLONE_APP_CONTENTRULES_FIXTURE,), - name='PloneAppContentrulesLayer:FunctionalTesting', + name="PloneAppContentrulesLayer:FunctionalTesting", ) diff --git a/plone/app/contentrules/tests/base.py b/plone/app/contentrules/tests/base.py index 4bd5bf3..f75529e 100644 --- a/plone/app/contentrules/tests/base.py +++ b/plone/app/contentrules/tests/base.py @@ -1,7 +1,8 @@ -# -*- coding: utf-8 -*- """Base class for integration tests, based on plone.app.testing """ -from plone.app.contentrules.testing import PLONE_APP_CONTENTRULES_INTEGRATION_TESTING # noqa: E501 +from plone.app.contentrules.testing import ( # noqa: E501 + PLONE_APP_CONTENTRULES_INTEGRATION_TESTING, +) from plone.app.testing import login from plone.app.testing import setRoles from plone.app.testing import TEST_USER_ID @@ -20,19 +21,18 @@ class ContentRulesTestCase(unittest.TestCase): layer = PLONE_APP_CONTENTRULES_INTEGRATION_TESTING def setUp(self): - self.portal = self.layer['portal'] - self.request = self.layer['request'] + self.portal = self.layer["portal"] + self.request = self.layer["request"] login(self.portal, TEST_USER_NAME) - setRoles(self.portal, TEST_USER_ID, ['Manager']) - self.portal.invokeFactory('Folder', 'f1') - self.folder = self.portal['f1'] - self.folder.invokeFactory('Document', 'd1') - self.portal.invokeFactory('Folder', 'target') + setRoles(self.portal, TEST_USER_ID, ["Manager"]) + self.portal.invokeFactory("Folder", "f1") + self.folder = self.portal["f1"] + self.folder.invokeFactory("Document", "d1") + self.portal.invokeFactory("Folder", "target") def addAuthToRequest(self): - portal = self.layer['portal'] - request = self.layer['request'] - authenticator = getMultiAdapter( - (portal, request), name=u'authenticator') + portal = self.layer["portal"] + request = self.layer["request"] + authenticator = getMultiAdapter((portal, request), name="authenticator") auth = authenticator.authenticator().split('value="')[1].rstrip('"/>') - request.form['_authenticator'] = auth + request.form["_authenticator"] = auth diff --git a/plone/app/contentrules/tests/dummy.py b/plone/app/contentrules/tests/dummy.py index cc658c0..41e0d23 100644 --- a/plone/app/contentrules/tests/dummy.py +++ b/plone/app/contentrules/tests/dummy.py @@ -1,36 +1,33 @@ -# -*- coding: utf-8 -*- from OFS.SimpleItem import SimpleItem from plone.contentrules.rule.interfaces import IRuleElementData from plone.uuid.interfaces import IAttributeUUID -from zope.interface.interfaces import IObjectEvent from zope.interface import implementer +from zope.interface.interfaces import IObjectEvent @implementer(IRuleElementData) class DummyCondition(SimpleItem): - element = 'dummy.condition' - summary = 'Dummy condition' + element = "dummy.condition" + summary = "Dummy condition" @implementer(IRuleElementData) class DummyAction(SimpleItem): - element = 'dummy.action' - summary = 'Dummy action' + element = "dummy.action" + summary = "Dummy action" @implementer(IObjectEvent) -class DummyEvent(object): - +class DummyEvent: def __init__(self, object): self.object = object -class DummyRule(object): - - def __init__(self, name='dummy'): +class DummyRule: + def __init__(self, name="dummy"): self.__name__ = name @implementer(IAttributeUUID) -class DummyNonArchetypesContext(object): +class DummyNonArchetypesContext: pass diff --git a/plone/app/contentrules/tests/test_action_copy.py b/plone/app/contentrules/tests/test_action_copy.py index 4714258..2bac17a 100644 --- a/plone/app/contentrules/tests/test_action_copy.py +++ b/plone/app/contentrules/tests/test_action_copy.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from plone.app.contentrules.actions.copy import CopyAction from plone.app.contentrules.actions.copy import CopyEditFormView from plone.app.contentrules.rule import Rule @@ -10,102 +9,97 @@ from plone.contentrules.rule.interfaces import IRuleAction from zope.component import getMultiAdapter from zope.component import getUtility -from zope.interface.interfaces import IObjectEvent from zope.interface import implementer +from zope.interface.interfaces import IObjectEvent @implementer(IObjectEvent) -class DummyEvent(object): - +class DummyEvent: def __init__(self, object): self.object = object class TestCopyAction(ContentRulesTestCase): - def testRegistered(self): - element = getUtility(IRuleAction, name='plone.actions.Copy') - self.assertEqual('plone.actions.Copy', element.addview) - self.assertEqual('edit', element.editview) + element = getUtility(IRuleAction, name="plone.actions.Copy") + self.assertEqual("plone.actions.Copy", element.addview) + self.assertEqual("edit", element.editview) self.assertEqual(None, element.for_) self.assertEqual(IObjectEvent, element.event) def testInvokeAddView(self): - element = getUtility(IRuleAction, name='plone.actions.Copy') + element = getUtility(IRuleAction, name="plone.actions.Copy") storage = getUtility(IRuleStorage) - storage[u'foo'] = Rule() - rule = self.portal.restrictedTraverse('++rule++foo') + storage["foo"] = Rule() + rule = self.portal.restrictedTraverse("++rule++foo") - adding = getMultiAdapter((rule, self.portal.REQUEST), name='+action') - addview = getMultiAdapter( - (adding, self.portal.REQUEST), name=element.addview) + adding = getMultiAdapter((rule, self.portal.REQUEST), name="+action") + addview = getMultiAdapter((adding, self.portal.REQUEST), name=element.addview) addview.form_instance.update() action = addview.form_instance.create( - data={'target_folder': '/target', }) + data={ + "target_folder": "/target", + } + ) addview.form_instance.add(action) e = rule.actions[0] self.assertTrue(isinstance(e, CopyAction)) - self.assertEqual('/target', e.target_folder) + self.assertEqual("/target", e.target_folder) def testInvokeEditView(self): - element = getUtility(IRuleAction, name='plone.actions.Copy') + element = getUtility(IRuleAction, name="plone.actions.Copy") e = CopyAction() - editview = getMultiAdapter( - (e, self.folder.REQUEST), name=element.editview) + editview = getMultiAdapter((e, self.folder.REQUEST), name=element.editview) self.assertTrue(isinstance(editview, CopyEditFormView)) def testExecute(self): e = CopyAction() - e.target_folder = '/target' + e.target_folder = "/target" - ex = getMultiAdapter( - (self.folder, e, DummyEvent(self.folder.d1)), IExecutable) + ex = getMultiAdapter((self.folder, e, DummyEvent(self.folder.d1)), IExecutable) self.assertEqual(True, ex()) - self.assertTrue('d1' in self.folder.objectIds()) - self.assertTrue('d1' in self.portal.target.objectIds()) + self.assertTrue("d1" in self.folder.objectIds()) + self.assertTrue("d1" in self.portal.target.objectIds()) def testExecuteWithError(self): e = CopyAction() - e.target_folder = '/dummy' + e.target_folder = "/dummy" - ex = getMultiAdapter( - (self.folder, e, DummyEvent(self.folder.d1)), IExecutable) + ex = getMultiAdapter((self.folder, e, DummyEvent(self.folder.d1)), IExecutable) self.assertEqual(False, ex()) - self.assertTrue('d1' in self.folder.objectIds()) - self.assertFalse('d1' in self.portal.target.objectIds()) + self.assertTrue("d1" in self.folder.objectIds()) + self.assertFalse("d1" in self.portal.target.objectIds()) def testExecuteWithoutPermissionsOnTarget(self): - setRoles(self.portal, TEST_USER_ID, ('Member', )) + setRoles(self.portal, TEST_USER_ID, ("Member",)) e = CopyAction() - e.target_folder = '/target' + e.target_folder = "/target" - ex = getMultiAdapter( - (self.folder, e, DummyEvent(self.folder.d1)), IExecutable) + ex = getMultiAdapter((self.folder, e, DummyEvent(self.folder.d1)), IExecutable) self.assertEqual(True, ex()) - self.assertTrue('d1' in self.folder.objectIds()) - self.assertTrue('d1' in self.portal.target.objectIds()) + self.assertTrue("d1" in self.folder.objectIds()) + self.assertTrue("d1" in self.portal.target.objectIds()) def testExecuteWithNamingConflict(self): - setRoles(self.portal, TEST_USER_ID, ('Manager', )) - self.portal.target.invokeFactory('Document', 'd1') - setRoles(self.portal, TEST_USER_ID, ('Member', )) + setRoles(self.portal, TEST_USER_ID, ("Manager",)) + self.portal.target.invokeFactory("Document", "d1") + setRoles(self.portal, TEST_USER_ID, ("Member",)) e = CopyAction() - e.target_folder = '/target' + e.target_folder = "/target" - ex = getMultiAdapter( - (self.folder, e, DummyEvent(self.folder.d1)), IExecutable) + ex = getMultiAdapter((self.folder, e, DummyEvent(self.folder.d1)), IExecutable) self.assertEqual(True, ex()) - self.assertTrue('d1' in self.folder.objectIds()) - self.assertTrue('d1' in self.portal.target.objectIds()) - self.assertTrue('d1.1' in self.portal.target.objectIds()) + self.assertTrue("d1" in self.folder.objectIds()) + self.assertTrue("d1" in self.portal.target.objectIds()) + self.assertTrue("d1.1" in self.portal.target.objectIds()) def testExecuteWithNamingConflictDoesNotStupidlyAcquireHasKey(self): # self.folder is an ATBTreeFolder and so has a has_key. @@ -113,16 +107,17 @@ def testExecuteWithNamingConflictDoesNotStupidlyAcquireHasKey(self): # Let's make sure we don't accidentally acquire has_key and use # this for the check for unique id. - self.folder.invokeFactory('Folder', 'target') - self.folder.target.invokeFactory('Document', 'd1') + self.folder.invokeFactory("Folder", "target") + self.folder.target.invokeFactory("Document", "d1") e = CopyAction() - e.target_folder = '/f1/target' + e.target_folder = "/f1/target" ex = getMultiAdapter( - (self.folder.target, e, DummyEvent(self.folder.d1)), IExecutable) + (self.folder.target, e, DummyEvent(self.folder.d1)), IExecutable + ) self.assertEqual(True, ex()) - self.assertTrue('d1' in self.folder.objectIds()) - self.assertTrue('d1' in self.folder.target.objectIds()) - self.assertTrue('d1.1' in self.folder.target.objectIds()) + self.assertTrue("d1" in self.folder.objectIds()) + self.assertTrue("d1" in self.folder.target.objectIds()) + self.assertTrue("d1.1" in self.folder.target.objectIds()) diff --git a/plone/app/contentrules/tests/test_action_delete.py b/plone/app/contentrules/tests/test_action_delete.py index 1eb8e45..b4275ad 100644 --- a/plone/app/contentrules/tests/test_action_delete.py +++ b/plone/app/contentrules/tests/test_action_delete.py @@ -1,46 +1,45 @@ -# -*- coding: utf-8 -*- from plone.app.contentrules.actions.delete import DeleteAction from plone.app.contentrules.rule import Rule from plone.app.contentrules.tests.base import ContentRulesTestCase +from plone.app.testing import login +from plone.app.testing import setRoles +from plone.app.testing import TEST_USER_ID +from plone.app.testing import TEST_USER_NAME from plone.contentrules.engine.interfaces import IRuleStorage from plone.contentrules.rule.interfaces import IExecutable from plone.contentrules.rule.interfaces import IRuleAction from zope.component import getMultiAdapter from zope.component import getUtility -from zope.interface.interfaces import IObjectEvent from zope.interface import implementer -from plone.app.testing import login -from plone.app.testing import TEST_USER_ID -from plone.app.testing import TEST_USER_NAME -from plone.app.testing import setRoles +from zope.interface.interfaces import IObjectEvent @implementer(IObjectEvent) -class DummyEvent(object): - +class DummyEvent: def __init__(self, object): self.object = object class TestDeleteAction(ContentRulesTestCase): - def testRegistered(self): - element = getUtility(IRuleAction, name='plone.actions.Delete') - self.assertEqual('plone.actions.Delete', element.addview) + element = getUtility(IRuleAction, name="plone.actions.Delete") + self.assertEqual("plone.actions.Delete", element.addview) self.assertEqual(None, element.editview) self.assertEqual(None, element.for_) self.assertEqual(IObjectEvent, element.event) def testInvokeAddView(self): - element = getUtility(IRuleAction, name='plone.actions.Delete') + element = getUtility(IRuleAction, name="plone.actions.Delete") storage = getUtility(IRuleStorage) - storage[u'foo'] = Rule() - rule = self.portal.restrictedTraverse('++rule++foo') + storage["foo"] = Rule() + rule = self.portal.restrictedTraverse("++rule++foo") adding = getMultiAdapter( - (rule.__of__(self.portal), self.portal.REQUEST), name='+action') + (rule.__of__(self.portal), self.portal.REQUEST), name="+action" + ) addview = getMultiAdapter( - (adding.__of__(rule), self.portal.REQUEST), name=element.addview) + (adding.__of__(rule), self.portal.REQUEST), name=element.addview + ) addview() e = rule.actions[0] @@ -49,8 +48,7 @@ def testInvokeAddView(self): def testExecute(self): e = DeleteAction() - ex = getMultiAdapter( - (self.folder, e, DummyEvent(self.folder.d1)), IExecutable) + ex = getMultiAdapter((self.folder, e, DummyEvent(self.folder.d1)), IExecutable) self.assertEqual(True, ex()) - self.assertFalse('d1' in self.folder.objectIds()) + self.assertFalse("d1" in self.folder.objectIds()) diff --git a/plone/app/contentrules/tests/test_action_logger.py b/plone/app/contentrules/tests/test_action_logger.py index e98cd23..7de104d 100644 --- a/plone/app/contentrules/tests/test_action_logger.py +++ b/plone/app/contentrules/tests/test_action_logger.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from plone.app.contentrules.actions.logger import LoggerAction from plone.app.contentrules.actions.logger import LoggerEditFormView from plone.app.contentrules.rule import Rule @@ -10,92 +9,90 @@ from plone.contentrules.rule.interfaces import IRuleAction from zope.component import getMultiAdapter from zope.component import getUtility -from zope.interface.interfaces import IObjectEvent from zope.interface import implementer from zope.interface import Interface +from zope.interface.interfaces import IObjectEvent @implementer(Interface) -class DummyEvent(object): +class DummyEvent: pass @implementer(IObjectEvent) -class DummyObjectEvent(object): - +class DummyObjectEvent: def __init__(self, obj): self.object = obj class TestLoggerAction(ContentRulesTestCase): - def testRegistered(self): - element = getUtility(IRuleAction, name='plone.actions.Logger') - self.assertEqual('plone.actions.Logger', element.addview) - self.assertEqual('edit', element.editview) + element = getUtility(IRuleAction, name="plone.actions.Logger") + self.assertEqual("plone.actions.Logger", element.addview) + self.assertEqual("edit", element.editview) self.assertEqual(None, element.for_) self.assertEqual(None, element.event) def testInvokeAddView(self): - element = getUtility(IRuleAction, name='plone.actions.Logger') + element = getUtility(IRuleAction, name="plone.actions.Logger") storage = getUtility(IRuleStorage) - storage[u'foo'] = Rule() - rule = self.portal.restrictedTraverse('++rule++foo') + storage["foo"] = Rule() + rule = self.portal.restrictedTraverse("++rule++foo") - adding = getMultiAdapter((rule, self.portal.REQUEST), name='+action') - addview = getMultiAdapter( - (adding, self.portal.REQUEST), name=element.addview) + adding = getMultiAdapter((rule, self.portal.REQUEST), name="+action") + addview = getMultiAdapter((adding, self.portal.REQUEST), name=element.addview) addview.form_instance.update() content = addview.form_instance.create( - data={'targetLogger': 'foo', 'loggingLevel': 10, 'message': 'bar'}) + data={"targetLogger": "foo", "loggingLevel": 10, "message": "bar"} + ) addview.form_instance.add(content) e = rule.actions[0] self.assertTrue(isinstance(e, LoggerAction)) - self.assertEqual('foo', e.targetLogger) + self.assertEqual("foo", e.targetLogger) self.assertEqual(10, e.loggingLevel) - self.assertEqual('bar', e.message) + self.assertEqual("bar", e.message) def testInvokeEditView(self): - element = getUtility(IRuleAction, name='plone.actions.Logger') + element = getUtility(IRuleAction, name="plone.actions.Logger") e = LoggerAction() - editview = getMultiAdapter( - (e, self.folder.REQUEST), name=element.editview) + editview = getMultiAdapter((e, self.folder.REQUEST), name=element.editview) self.assertTrue(isinstance(editview, LoggerEditFormView)) def testProcessedMessage(self): e = LoggerAction() - e.targetLogger = 'testing' + e.targetLogger = "testing" e.loggingLevel = 0 - e.message = 'Test log event' + e.message = "Test log event" ex = getMultiAdapter( - (self.folder, e, DummyObjectEvent(self.folder)), IExecutable) - self.assertEqual('Test log event', ex.processedMessage()) + (self.folder, e, DummyObjectEvent(self.folder)), IExecutable + ) + self.assertEqual("Test log event", ex.processedMessage()) - e.message = 'Test log event : &c' + e.message = "Test log event : &c" self.assertEqual( - 'Test log event : ', + "Test log event : ", ex.processedMessage(), ) - e.message = 'Test log event : &e' + e.message = "Test log event : &e" self.assertEqual( - 'Test log event : ' - 'plone.app.contentrules.tests.test_action_logger.DummyObjectEvent', + "Test log event : " + "plone.app.contentrules.tests.test_action_logger.DummyObjectEvent", ex.processedMessage(), ) - e.message = 'Test log event : &u' + e.message = "Test log event : &u" self.assertEqual( - 'Test log event : {0}'.format(TEST_USER_NAME), + f"Test log event : {TEST_USER_NAME}", ex.processedMessage(), ) def testExecute(self): e = LoggerAction() - e.targetLogger = 'testing' + e.targetLogger = "testing" e.loggingLevel = 0 - e.message = 'Test log event' + e.message = "Test log event" ex = getMultiAdapter((self.folder, e, DummyEvent()), IExecutable) self.assertTrue(ex()) diff --git a/plone/app/contentrules/tests/test_action_mail.py b/plone/app/contentrules/tests/test_action_mail.py index b67acb1..f42ec2f 100644 --- a/plone/app/contentrules/tests/test_action_mail.py +++ b/plone/app/contentrules/tests/test_action_mail.py @@ -1,5 +1,5 @@ -# -*- coding: utf-8 -*- from Acquisition import aq_base +from email import message_from_bytes from plone.app.contentrules.actions.mail import MailAction from plone.app.contentrules.actions.mail import MailAddFormView from plone.app.contentrules.actions.mail import MailEditFormView @@ -7,240 +7,217 @@ from plone.app.contentrules.tests.base import ContentRulesTestCase from plone.app.testing import setRoles from plone.app.testing import TEST_USER_ID +from plone.base.interfaces.controlpanel import IMailSchema from plone.contentrules.engine.interfaces import IRuleStorage from plone.contentrules.rule.interfaces import IExecutable from plone.contentrules.rule.interfaces import IRuleAction from plone.registry.interfaces import IRegistry -from Products.CMFPlone.interfaces.controlpanel import IMailSchema -from Products.CMFPlone.tests.utils import MockMailHost from Products.MailHost.interfaces import IMailHost from zope.component import getMultiAdapter from zope.component import getSiteManager from zope.component import getUtility -from zope.interface.interfaces import IObjectEvent from zope.interface import implementer +from zope.interface.interfaces import IObjectEvent import unittest -try: - # Python 3 - from email import message_from_bytes -except ImportError: - # Python 2 - from email import message_from_string as message_from_bytes - @implementer(IObjectEvent) -class DummyEvent(object): - +class DummyEvent: def __init__(self, object): self.object = object class TestMailAction(ContentRulesTestCase): - def setUp(self): - super(TestMailAction, self).setUp() - self.folder['d1'].setTitle(u'Wälkommen') + super().setUp() + self.folder["d1"].setTitle("Wälkommen") users = ( - ('userone', 'User One', 'user@one.com', ('Manager', 'Member')), - ('usertwo', 'User Two', 'user@two.com', ('Reviewer', 'Member')), - ('userthree', 'User Three', 'user@three.com', ('Owner', 'Member')), - ('userfour', 'User Four', 'user@four.com', ('Member', )), + ("userone", "User One", "user@one.com", ("Manager", "Member")), + ("usertwo", "User Two", "user@two.com", ("Reviewer", "Member")), + ("userthree", "User Three", "user@three.com", ("Owner", "Member")), + ("userfour", "User Four", "user@four.com", ("Member",)), ) for id, fname, email, roles in users: - self.portal.portal_membership.addMember(id, 'secret', roles, []) + self.portal.portal_membership.addMember(id, "secret", roles, []) member = self.portal.portal_membership.getMemberById(id) - member.setMemberProperties({'fullname': fname, 'email': email}) + member.setMemberProperties({"fullname": fname, "email": email}) # XXX: remove the manager role that was set in the base class setRoles(self.portal, TEST_USER_ID, []) def testRegistered(self): - element = getUtility(IRuleAction, name='plone.actions.Mail') - self.assertEqual('plone.actions.Mail', element.addview) - self.assertEqual('edit', element.editview) + element = getUtility(IRuleAction, name="plone.actions.Mail") + self.assertEqual("plone.actions.Mail", element.addview) + self.assertEqual("edit", element.editview) self.assertEqual(None, element.for_) def testInvokeAddView(self): - element = getUtility(IRuleAction, name='plone.actions.Mail') + element = getUtility(IRuleAction, name="plone.actions.Mail") storage = getUtility(IRuleStorage) - storage[u'foo'] = Rule() - rule = self.portal.restrictedTraverse('++rule++foo') + storage["foo"] = Rule() + rule = self.portal.restrictedTraverse("++rule++foo") - adding = getMultiAdapter((rule, self.portal.REQUEST), name='+action') - addview = getMultiAdapter((adding, self.portal.REQUEST), - name=element.addview) + adding = getMultiAdapter((rule, self.portal.REQUEST), name="+action") + addview = getMultiAdapter((adding, self.portal.REQUEST), name=element.addview) self.assertTrue(isinstance(addview, MailAddFormView)) addview.form_instance.update() output = addview.form_instance() - self.assertIn('

Substitutions

', output) + self.assertIn("

Substitutions

", output) content = addview.form_instance.create( data={ - 'subject': 'My Subject', - 'source': 'foo@bar.be', - 'recipients': 'foo@bar.be,bar@foo.be', - 'message': 'Hey, Oh!', + "subject": "My Subject", + "source": "foo@bar.be", + "recipients": "foo@bar.be,bar@foo.be", + "message": "Hey, Oh!", } ) addview.form_instance.add(content) e = rule.actions[0] self.assertTrue(isinstance(e, MailAction)) - self.assertEqual('My Subject', e.subject) - self.assertEqual('foo@bar.be', e.source) - self.assertEqual('foo@bar.be,bar@foo.be', e.recipients) - self.assertEqual('Hey, Oh!', e.message) + self.assertEqual("My Subject", e.subject) + self.assertEqual("foo@bar.be", e.source) + self.assertEqual("foo@bar.be,bar@foo.be", e.recipients) + self.assertEqual("Hey, Oh!", e.message) def testInvokeEditView(self): - element = getUtility(IRuleAction, name='plone.actions.Mail') + element = getUtility(IRuleAction, name="plone.actions.Mail") e = MailAction() - editview = getMultiAdapter((e, self.folder.REQUEST), - name=element.editview) + editview = getMultiAdapter((e, self.folder.REQUEST), name=element.editview) self.assertTrue(isinstance(editview, MailEditFormView)) def testExecute(self): # this avoids sending mail as currentuser@foobar.com self.portal.portal_membership.getAuthenticatedMember().setProperties( - email='currentuser@foobar.com') + email="currentuser@foobar.com" + ) e = MailAction() - e.source = '$user_email' - e.recipients = 'bar@foo.be, bar@foo.be, $reviewer_emails, ' \ - '$manager_emails, $member_emails' - e.message = u"Päge '${title}' created in ${url} !" - ex = getMultiAdapter((self.folder, e, DummyEvent(self.folder.d1)), - IExecutable) + e.source = "$user_email" + e.recipients = ( + "bar@foo.be, bar@foo.be, $reviewer_emails, " + "$manager_emails, $member_emails" + ) + e.message = "Päge '${title}' created in ${url} !" + ex = getMultiAdapter((self.folder, e, DummyEvent(self.folder.d1)), IExecutable) ex() sent_mails = {} for mail_sent in self.portal.MailHost.messages: mail_sent_msg = message_from_bytes(mail_sent) - sent_mails[mail_sent_msg.get('To')] = mail_sent_msg + sent_mails[mail_sent_msg.get("To")] = mail_sent_msg - mailSent = sent_mails['bar@foo.be'] - self.assertEqual('text/plain; charset="utf-8"', - mailSent.get('Content-Type')) - self.assertEqual('currentuser@foobar.com', mailSent.get('From')) + mailSent = sent_mails["bar@foo.be"] + self.assertEqual('text/plain; charset="utf-8"', mailSent.get("Content-Type")) + self.assertEqual("currentuser@foobar.com", mailSent.get("From")) # The output message should be a utf-8 encoded string self.assertEqual( - u"Päge 'Wälkommen' created in http://nohost/plone/f1/d1 !", - mailSent.get_payload(decode=True).decode('utf8')) + "Päge 'Wälkommen' created in http://nohost/plone/f1/d1 !", + mailSent.get_payload(decode=True).decode("utf8"), + ) # check interpolation of $reviewer_emails - self.assertTrue('user@two.com' in sent_mails) + self.assertTrue("user@two.com" in sent_mails) # check interpolation of $manager_emails - self.assertTrue('user@one.com' in sent_mails) + self.assertTrue("user@one.com" in sent_mails) # check interpolation of $member_emails emails = [ - 'bar@foo.be', - 'user@one.com', - 'user@two.com', - 'user@three.com', - 'user@four.com', + "bar@foo.be", + "user@one.com", + "user@two.com", + "user@three.com", + "user@four.com", ] - self.assertEqual( - set(emails), - set(sent_mails.keys())) + self.assertEqual(set(emails), set(sent_mails.keys())) def testExecuteNoSource(self): e = MailAction() - e.recipients = 'bar@foo.be,foo@bar.be' - e.message = 'Document created !' - ex = getMultiAdapter((self.folder, e, DummyEvent(self.folder.d1)), - IExecutable) + e.recipients = "bar@foo.be,foo@bar.be" + e.message = "Document created !" + ex = getMultiAdapter((self.folder, e, DummyEvent(self.folder.d1)), IExecutable) # this no longer errors since it breaks usability self.assertTrue(ex) # and will return False for the unsent message # (happens when no sender address can be computed) registry = getUtility(IRegistry) - mail_settings = registry.forInterface(IMailSchema, prefix='plone') + mail_settings = registry.forInterface(IMailSchema, prefix="plone") mail_settings.email_from_address = "" self.assertEqual(ex(), False) # if we provide a site mail address the message sends correctly - mail_settings.email_from_address = 'manager@portal.be' - mail_settings.email_from_name = u'plone@rulez' + mail_settings.email_from_address = "manager@portal.be" + mail_settings.email_from_name = "plone@rulez" ex() self.assertEqual(len(self.portal.MailHost.messages), 2) mailSent = message_from_bytes(self.portal.MailHost.messages[0]) - self.assertEqual('text/plain; charset="utf-8"', - mailSent.get('Content-Type')) - self.assertIn(mailSent.get('To'), ['bar@foo.be', 'foo@bar.be']) - self.assertEqual('"plone@rulez" ', - mailSent.get('From')) - self.assertEqual('Document created !', - mailSent.get_payload()) + self.assertEqual('text/plain; charset="utf-8"', mailSent.get("Content-Type")) + self.assertIn(mailSent.get("To"), ["bar@foo.be", "foo@bar.be"]) + self.assertEqual('"plone@rulez" ', mailSent.get("From")) + self.assertEqual("Document created !", mailSent.get_payload()) def testExecuteMultiRecipients(self): e = MailAction() - e.source = 'foo@bar.be' - e.recipients = 'bar@foo.be,foo@bar.be' - e.message = 'Document created !' - ex = getMultiAdapter((self.folder, e, DummyEvent(self.folder.d1)), - IExecutable) + e.source = "foo@bar.be" + e.recipients = "bar@foo.be,foo@bar.be" + e.message = "Document created !" + ex = getMultiAdapter((self.folder, e, DummyEvent(self.folder.d1)), IExecutable) ex() self.assertEqual(len(self.portal.MailHost.messages), 2) # in py3 the order of mails is non-determininistic # because sending iterates over a set of recipients for msg in self.portal.MailHost.messages: - if b'bar@foo.be' in msg: + if b"bar@foo.be" in msg: mailSent1 = message_from_bytes(msg) else: mailSent2 = message_from_bytes(msg) - self.assertEqual('text/plain; charset="utf-8"', - mailSent1.get('Content-Type')) - self.assertEqual('bar@foo.be', mailSent1.get('To')) - self.assertEqual('foo@bar.be', mailSent1.get('From')) - self.assertEqual('Document created !', - mailSent1.get_payload()) - self.assertEqual('text/plain; charset="utf-8"', - mailSent2.get('Content-Type')) - self.assertEqual('foo@bar.be', mailSent2.get('To')) - self.assertEqual('foo@bar.be', mailSent2.get('From')) - self.assertEqual('Document created !', - mailSent2.get_payload()) + self.assertEqual('text/plain; charset="utf-8"', mailSent1.get("Content-Type")) + self.assertEqual("bar@foo.be", mailSent1.get("To")) + self.assertEqual("foo@bar.be", mailSent1.get("From")) + self.assertEqual("Document created !", mailSent1.get_payload()) + self.assertEqual('text/plain; charset="utf-8"', mailSent2.get("Content-Type")) + self.assertEqual("foo@bar.be", mailSent2.get("To")) + self.assertEqual("foo@bar.be", mailSent2.get("From")) + self.assertEqual("Document created !", mailSent2.get_payload()) def testExecuteExcludeActor(self): self.portal.portal_membership.getAuthenticatedMember().setProperties( - email='currentuser@foobar.com') + email="currentuser@foobar.com" + ) e = MailAction() - e.source = '$user_email' + e.source = "$user_email" e.exclude_actor = True - e.recipients = 'bar@foo.be, currentuser@foobar.com' - e.message = u'A dummy event just happened !!!!!' - ex = getMultiAdapter((self.folder, e, DummyEvent(self.folder.d1)), - IExecutable) + e.recipients = "bar@foo.be, currentuser@foobar.com" + e.message = "A dummy event just happened !!!!!" + ex = getMultiAdapter((self.folder, e, DummyEvent(self.folder.d1)), IExecutable) ex() self.assertEqual(len(self.portal.MailHost.messages), 1) mailSent = message_from_bytes(self.portal.MailHost.messages[0]) - self.assertEqual('bar@foo.be', mailSent.get('To')) + self.assertEqual("bar@foo.be", mailSent.get("To")) def testExecuteNoRecipients(self): # no recipient e = MailAction() - e.source = 'foo@bar.be' - e.recipients = '' - e.message = 'Document created !' - ex = getMultiAdapter((self.folder, e, DummyEvent(self.folder.d1)), - IExecutable) + e.source = "foo@bar.be" + e.recipients = "" + e.message = "Document created !" + ex = getMultiAdapter((self.folder, e, DummyEvent(self.folder.d1)), IExecutable) ex() self.assertEqual(len(self.portal.MailHost.messages), 0) - @unittest.skip( - 'Monkey patching does not work well with mocking. Needs fixing.' - ) + @unittest.skip("Monkey patching does not work well with mocking. Needs fixing.") def testExecuteBadMailHost(self): # Our goal is that mailing errors should not cause exceptions self.portal.portal_membership.getAuthenticatedMember().setProperties( - email='currentuser@foobar.com') + email="currentuser@foobar.com" + ) e = MailAction() - e.source = '$user_email' - e.recipients = 'bar@foo.be, $reviewer_emails, $manager_emails, ' \ - '$member_emails' - e.message = u"Päge '${title}' created in ${url} !" - ex = getMultiAdapter((self.folder, e, DummyEvent(self.folder.d1)), - IExecutable) + e.source = "$user_email" + e.recipients = ( + "bar@foo.be, $reviewer_emails, $manager_emails, " "$member_emails" + ) + e.message = "Päge '${title}' created in ${url} !" + ex = getMultiAdapter((self.folder, e, DummyEvent(self.folder.d1)), IExecutable) ex() diff --git a/plone/app/contentrules/tests/test_action_modify.py b/plone/app/contentrules/tests/test_action_modify.py index 0deb751..4b10d58 100644 --- a/plone/app/contentrules/tests/test_action_modify.py +++ b/plone/app/contentrules/tests/test_action_modify.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from plone.app.contentrules import handlers from unittest import TestCase from zope.lifecycleevent import ObjectAddedEvent @@ -6,12 +5,10 @@ class TestModifyAction(TestCase): - def setUp(self): self.called = False def register_call(testcase): - def inner_register_call(event): testcase.called = True @@ -25,15 +22,17 @@ def tearDown(self): self.called = False def testIgnoreAddedEvents(self): - class Content(object): + class Content: __parent__ = None __name__ = None + handlers.modified(ObjectAddedEvent(Content())) self.assertFalse(self.called) def testIgnoreDeletedEvents(self): - class Content(object): + class Content: __parent__ = None __name__ = None + handlers.modified(ObjectRemovedEvent(Content())) self.assertFalse(self.called) diff --git a/plone/app/contentrules/tests/test_action_move.py b/plone/app/contentrules/tests/test_action_move.py index c39caf1..654933c 100644 --- a/plone/app/contentrules/tests/test_action_move.py +++ b/plone/app/contentrules/tests/test_action_move.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from plone.app.contentrules.actions.move import MoveAction from plone.app.contentrules.actions.move import MoveEditFormView from plone.app.contentrules.rule import Rule @@ -10,115 +9,110 @@ from plone.contentrules.rule.interfaces import IRuleAction from zope.component import getMultiAdapter from zope.component import getUtility -from zope.interface.interfaces import IObjectEvent from zope.interface import implementer +from zope.interface.interfaces import IObjectEvent @implementer(IObjectEvent) -class DummyEvent(object): - +class DummyEvent: def __init__(self, object): self.object = object class TestMoveAction(ContentRulesTestCase): - def testRegistered(self): - element = getUtility(IRuleAction, name='plone.actions.Move') - self.assertEqual('plone.actions.Move', element.addview) - self.assertEqual('edit', element.editview) + element = getUtility(IRuleAction, name="plone.actions.Move") + self.assertEqual("plone.actions.Move", element.addview) + self.assertEqual("edit", element.editview) self.assertEqual(None, element.for_) self.assertEqual(IObjectEvent, element.event) def testInvokeAddView(self): - element = getUtility(IRuleAction, name='plone.actions.Move') + element = getUtility(IRuleAction, name="plone.actions.Move") storage = getUtility(IRuleStorage) - storage[u'foo'] = Rule() - rule = self.portal.restrictedTraverse('++rule++foo') + storage["foo"] = Rule() + rule = self.portal.restrictedTraverse("++rule++foo") - adding = getMultiAdapter((rule, self.portal.REQUEST), name='+action') - addview = getMultiAdapter( - (adding, self.portal.REQUEST), name=element.addview) + adding = getMultiAdapter((rule, self.portal.REQUEST), name="+action") + addview = getMultiAdapter((adding, self.portal.REQUEST), name=element.addview) addview.form_instance.update() content = addview.form_instance.create( - data={'target_folder': '/target', }) + data={ + "target_folder": "/target", + } + ) addview.form_instance.add(content) e = rule.actions[0] self.assertTrue(isinstance(e, MoveAction)) - self.assertEqual('/target', e.target_folder) + self.assertEqual("/target", e.target_folder) def testInvokeEditView(self): - element = getUtility(IRuleAction, name='plone.actions.Move') + element = getUtility(IRuleAction, name="plone.actions.Move") e = MoveAction() - editview = getMultiAdapter( - (e, self.folder.REQUEST), name=element.editview) + editview = getMultiAdapter((e, self.folder.REQUEST), name=element.editview) self.assertTrue(isinstance(editview, MoveEditFormView)) def testExecute(self): e = MoveAction() - e.target_folder = '/target' + e.target_folder = "/target" - ex = getMultiAdapter( - (self.folder, e, DummyEvent(self.folder.d1)), IExecutable) + ex = getMultiAdapter((self.folder, e, DummyEvent(self.folder.d1)), IExecutable) self.assertEqual(True, ex()) - self.assertFalse('d1' in self.folder.objectIds()) - self.assertTrue('d1' in self.portal.target.objectIds()) + self.assertFalse("d1" in self.folder.objectIds()) + self.assertTrue("d1" in self.portal.target.objectIds()) # test catalog is ok - brains = self.portal.portal_catalog(id='d1') + brains = self.portal.portal_catalog(id="d1") self.assertEqual(len(brains), 1) - self.assertEqual(brains[0].getPath(), '/plone/target/d1') + self.assertEqual(brains[0].getPath(), "/plone/target/d1") def testExecuteWithError(self): e = MoveAction() - e.target_folder = '/dummy' + e.target_folder = "/dummy" - ex = getMultiAdapter( - (self.folder, e, DummyEvent(self.folder.d1)), IExecutable) + ex = getMultiAdapter((self.folder, e, DummyEvent(self.folder.d1)), IExecutable) self.assertEqual(False, ex()) - self.assertTrue('d1' in self.folder.objectIds()) - self.assertFalse('d1' in self.portal.target.objectIds()) + self.assertTrue("d1" in self.folder.objectIds()) + self.assertFalse("d1" in self.portal.target.objectIds()) def testExecuteWithoutPermissionsOnTarget(self): - setRoles(self.portal, TEST_USER_ID, ('Member', )) + setRoles(self.portal, TEST_USER_ID, ("Member",)) e = MoveAction() - e.target_folder = '/target' + e.target_folder = "/target" - ex = getMultiAdapter( - (self.folder, e, DummyEvent(self.folder.d1)), IExecutable) + ex = getMultiAdapter((self.folder, e, DummyEvent(self.folder.d1)), IExecutable) self.assertEqual(True, ex()) - self.assertFalse('d1' in self.folder.objectIds()) - self.assertTrue('d1' in self.portal.target.objectIds()) + self.assertFalse("d1" in self.folder.objectIds()) + self.assertTrue("d1" in self.portal.target.objectIds()) def testExecuteWithNamingConflict(self): - setRoles(self.portal, TEST_USER_ID, ('Manager', )) - self.portal.target.invokeFactory('Document', 'd1') - setRoles(self.portal, TEST_USER_ID, ('Member', )) + setRoles(self.portal, TEST_USER_ID, ("Manager",)) + self.portal.target.invokeFactory("Document", "d1") + setRoles(self.portal, TEST_USER_ID, ("Member",)) e = MoveAction() - e.target_folder = '/target' + e.target_folder = "/target" - ex = getMultiAdapter( - (self.folder, e, DummyEvent(self.folder.d1)), IExecutable) + ex = getMultiAdapter((self.folder, e, DummyEvent(self.folder.d1)), IExecutable) self.assertEqual(True, ex()) - self.assertFalse('d1' in self.folder.objectIds()) - self.assertTrue('d1' in self.portal.target.objectIds()) - self.assertTrue('d1.1' in self.portal.target.objectIds()) + self.assertFalse("d1" in self.folder.objectIds()) + self.assertTrue("d1" in self.portal.target.objectIds()) + self.assertTrue("d1.1" in self.portal.target.objectIds()) def testExecuteWithSameSourceAndTargetFolder(self): - setRoles(self.portal, TEST_USER_ID, ('Manager', )) - self.portal.target.invokeFactory('Document', 'd1') - setRoles(self.portal, TEST_USER_ID, ('Member', )) + setRoles(self.portal, TEST_USER_ID, ("Manager",)) + self.portal.target.invokeFactory("Document", "d1") + setRoles(self.portal, TEST_USER_ID, ("Member",)) e = MoveAction() - e.target_folder = '/target' + e.target_folder = "/target" ex = getMultiAdapter( (self.portal.target, e, DummyEvent(self.portal.target.d1)), @@ -126,7 +120,7 @@ def testExecuteWithSameSourceAndTargetFolder(self): ) self.assertEqual(True, ex()) - self.assertEqual(['d1'], list(self.portal.target.objectIds())) + self.assertEqual(["d1"], list(self.portal.target.objectIds())) def testExecuteWithNamingConflictDoesNotStupidlyAcquireHasKey(self): # self.folder is an ATBTreeFolder and so has a has_key. @@ -134,16 +128,17 @@ def testExecuteWithNamingConflictDoesNotStupidlyAcquireHasKey(self): # Let's make sure we don't accidentally acquire has_key and use # this for the check for unique id. - self.folder.invokeFactory('Folder', 'target') - self.folder.target.invokeFactory('Document', 'd1') + self.folder.invokeFactory("Folder", "target") + self.folder.target.invokeFactory("Document", "d1") e = MoveAction() - e.target_folder = '/f1/target' + e.target_folder = "/f1/target" ex = getMultiAdapter( - (self.folder.target, e, DummyEvent(self.folder.d1)), IExecutable) + (self.folder.target, e, DummyEvent(self.folder.d1)), IExecutable + ) self.assertEqual(True, ex()) - self.assertFalse('d1' in self.folder.objectIds()) - self.assertTrue('d1' in self.folder.target.objectIds()) - self.assertTrue('d1.1' in self.folder.target.objectIds()) + self.assertFalse("d1" in self.folder.objectIds()) + self.assertTrue("d1" in self.folder.target.objectIds()) + self.assertTrue("d1.1" in self.folder.target.objectIds()) diff --git a/plone/app/contentrules/tests/test_action_notify.py b/plone/app/contentrules/tests/test_action_notify.py index 03fa951..32e1456 100644 --- a/plone/app/contentrules/tests/test_action_notify.py +++ b/plone/app/contentrules/tests/test_action_notify.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from plone.app.contentrules.actions.notify import NotifyAction from plone.app.contentrules.actions.notify import NotifyEditFormView from plone.app.contentrules.rule import Rule @@ -15,54 +14,54 @@ @implementer(Interface) -class DummyEvent(object): +class DummyEvent: pass class TestNotifyAction(ContentRulesTestCase): - def testRegistered(self): - element = getUtility(IRuleAction, name='plone.actions.Notify') - self.assertEqual('plone.actions.Notify', element.addview) - self.assertEqual('edit', element.editview) + element = getUtility(IRuleAction, name="plone.actions.Notify") + self.assertEqual("plone.actions.Notify", element.addview) + self.assertEqual("edit", element.editview) self.assertEqual(None, element.for_) self.assertEqual(None, element.event) def testInvokeAddView(self): - element = getUtility(IRuleAction, name='plone.actions.Notify') + element = getUtility(IRuleAction, name="plone.actions.Notify") storage = getUtility(IRuleStorage) - storage[u'foo'] = Rule() - rule = self.portal.restrictedTraverse('++rule++foo') + storage["foo"] = Rule() + rule = self.portal.restrictedTraverse("++rule++foo") - adding = getMultiAdapter((rule, self.request), name='+action') + adding = getMultiAdapter((rule, self.request), name="+action") addview = getMultiAdapter((adding, self.request), name=element.addview) addview.form_instance.update() - content = addview.form_instance.create(data={'message': 'Hello world', - 'message_type': 'info'}) + content = addview.form_instance.create( + data={"message": "Hello world", "message_type": "info"} + ) addview.form_instance.add(content) e = rule.actions[0] self.assertTrue(isinstance(e, NotifyAction)) - self.assertEqual('Hello world', e.message) - self.assertEqual('info', e.message_type) + self.assertEqual("Hello world", e.message) + self.assertEqual("info", e.message_type) def testInvokeEditView(self): - element = getUtility(IRuleAction, name='plone.actions.Notify') + element = getUtility(IRuleAction, name="plone.actions.Notify") e = NotifyAction() editview = getMultiAdapter((e, self.request), name=element.editview) self.assertTrue(isinstance(editview, NotifyEditFormView)) def testExecute(self): e = NotifyAction() - e.message = 'Hello world' - e.message_type = 'info' + e.message = "Hello world" + e.message_type = "info" ex = getMultiAdapter((self.folder, e, DummyEvent()), IExecutable) self.assertEqual(True, ex()) new_cookies = self.request.RESPONSE.cookies[STATUSMESSAGEKEY] - messages = _decodeCookieValue(new_cookies['value']) + messages = _decodeCookieValue(new_cookies["value"]) self.assertEqual(1, len(messages)) - self.assertEqual('Hello world', messages[0].message) - self.assertEqual('info', messages[0].type) + self.assertEqual("Hello world", messages[0].message) + self.assertEqual("info", messages[0].type) diff --git a/plone/app/contentrules/tests/test_action_versioning.py b/plone/app/contentrules/tests/test_action_versioning.py index 2e522c3..d8557bf 100644 --- a/plone/app/contentrules/tests/test_action_versioning.py +++ b/plone/app/contentrules/tests/test_action_versioning.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from plone.app.contentrules.actions.versioning import VersioningAction from plone.app.contentrules.actions.versioning import VersioningEditFormView from plone.app.contentrules.rule import Rule @@ -13,50 +12,47 @@ @implementer(Interface) -class DummyEvent(object): - +class DummyEvent: def __init__(self, object): self.object = object class TestVersioningAction(ContentRulesTestCase): - def testRegistered(self): - element = getUtility(IRuleAction, name='plone.actions.Versioning') - self.assertEqual('plone.actions.Versioning', element.addview) - self.assertEqual('edit', element.editview) + element = getUtility(IRuleAction, name="plone.actions.Versioning") + self.assertEqual("plone.actions.Versioning", element.addview) + self.assertEqual("edit", element.editview) self.assertEqual(None, element.for_) self.assertEqual(None, element.event) def testInvokeAddView(self): - element = getUtility(IRuleAction, name='plone.actions.Versioning') + element = getUtility(IRuleAction, name="plone.actions.Versioning") storage = getUtility(IRuleStorage) - storage[u'foo'] = Rule() - rule = self.portal.restrictedTraverse('++rule++foo') + storage["foo"] = Rule() + rule = self.portal.restrictedTraverse("++rule++foo") - adding = getMultiAdapter((rule, self.request), name='+action') + adding = getMultiAdapter((rule, self.request), name="+action") addview = getMultiAdapter((adding, self.request), name=element.addview) addview.form_instance.update() - content = addview.form_instance.create(data={'comment': 'Hello world'}) + content = addview.form_instance.create(data={"comment": "Hello world"}) addview.form_instance.add(content) e = rule.actions[0] self.assertTrue(isinstance(e, VersioningAction)) - self.assertEqual('Hello world', e.comment) + self.assertEqual("Hello world", e.comment) def testInvokeEditView(self): - element = getUtility(IRuleAction, name='plone.actions.Versioning') + element = getUtility(IRuleAction, name="plone.actions.Versioning") e = VersioningAction() editview = getMultiAdapter((e, self.request), name=element.editview) self.assertTrue(isinstance(editview, VersioningEditFormView)) def testExecute(self): e = VersioningAction() - e.comment = 'Hello world' + e.comment = "Hello world" - ex = getMultiAdapter( - (self.folder, e, DummyEvent(self.folder)), IExecutable) + ex = getMultiAdapter((self.folder, e, DummyEvent(self.folder)), IExecutable) # not version for now pr = self.portal.portal_repository self.assertEqual(pr.getHistoryMetadata(self.folder), []) @@ -64,8 +60,10 @@ def testExecute(self): # action will create first version self.assertEqual(True, ex()) self.assertEqual( - pr.getHistoryMetadata(self.folder).getLength(countPurged=False), 1) + pr.getHistoryMetadata(self.folder).getLength(countPurged=False), 1 + ) # calling action again will create a second version ex() self.assertEqual( - pr.getHistoryMetadata(self.folder).getLength(countPurged=False), 2) + pr.getHistoryMetadata(self.folder).getLength(countPurged=False), 2 + ) diff --git a/plone/app/contentrules/tests/test_action_workflow.py b/plone/app/contentrules/tests/test_action_workflow.py index b4859b3..dfa10b8 100644 --- a/plone/app/contentrules/tests/test_action_workflow.py +++ b/plone/app/contentrules/tests/test_action_workflow.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from plone.app.contentrules.actions.workflow import WorkflowAction from plone.app.contentrules.actions.workflow import WorkflowEditFormView from plone.app.contentrules.rule import Rule @@ -8,83 +7,81 @@ from plone.contentrules.rule.interfaces import IRuleAction from zope.component import getMultiAdapter from zope.component import getUtility -from zope.interface.interfaces import IObjectEvent from zope.interface import implementer +from zope.interface.interfaces import IObjectEvent @implementer(IObjectEvent) -class DummyEvent(object): - +class DummyEvent: def __init__(self, object): self.object = object class TestWorkflowAction(ContentRulesTestCase): - def testRegistered(self): - element = getUtility(IRuleAction, name='plone.actions.Workflow') - self.assertEqual('plone.actions.Workflow', element.addview) - self.assertEqual('edit', element.editview) + element = getUtility(IRuleAction, name="plone.actions.Workflow") + self.assertEqual("plone.actions.Workflow", element.addview) + self.assertEqual("edit", element.editview) self.assertEqual(None, element.for_) self.assertEqual(IObjectEvent, element.event) def testInvokeAddView(self): - element = getUtility(IRuleAction, name='plone.actions.Workflow') + element = getUtility(IRuleAction, name="plone.actions.Workflow") storage = getUtility(IRuleStorage) - storage[u'foo'] = Rule() - rule = self.portal.restrictedTraverse('++rule++foo') + storage["foo"] = Rule() + rule = self.portal.restrictedTraverse("++rule++foo") - adding = getMultiAdapter((rule, self.portal.REQUEST), name='+action') - addview = getMultiAdapter( - (adding, self.portal.REQUEST), name=element.addview) + adding = getMultiAdapter((rule, self.portal.REQUEST), name="+action") + addview = getMultiAdapter((adding, self.portal.REQUEST), name=element.addview) addview.form_instance.update() content = addview.form_instance.create( - data={'transition': 'publish', }) + data={ + "transition": "publish", + } + ) addview.form_instance.add(content) e = rule.actions[0] self.assertTrue(isinstance(e, WorkflowAction)) - self.assertEqual('publish', e.transition) + self.assertEqual("publish", e.transition) def testInvokeEditView(self): - element = getUtility(IRuleAction, name='plone.actions.Workflow') + element = getUtility(IRuleAction, name="plone.actions.Workflow") e = WorkflowAction() - editview = getMultiAdapter( - (e, self.folder.REQUEST), name=element.editview) + editview = getMultiAdapter((e, self.folder.REQUEST), name=element.editview) self.assertTrue(isinstance(editview, WorkflowEditFormView)) def testExecute(self): e = WorkflowAction() - e.transition = 'publish' + e.transition = "publish" - ex = getMultiAdapter( - (self.folder, e, DummyEvent(self.folder.d1)), IExecutable) + ex = getMultiAdapter((self.folder, e, DummyEvent(self.folder.d1)), IExecutable) self.assertEqual(True, ex()) self.assertEqual( - 'published', + "published", self.portal.portal_workflow.getInfoFor( self.folder.d1, - 'review_state', - ) + "review_state", + ), ) def testExecuteWithError(self): e = WorkflowAction() - e.transition = 'foobar' + e.transition = "foobar" old_state = self.portal.portal_workflow.getInfoFor( - self.folder.d1, 'review_state') + self.folder.d1, "review_state" + ) - ex = getMultiAdapter( - (self.folder, e, DummyEvent(self.folder.d1)), IExecutable) + ex = getMultiAdapter((self.folder, e, DummyEvent(self.folder.d1)), IExecutable) self.assertEqual(False, ex()) self.assertEqual( old_state, self.portal.portal_workflow.getInfoFor( self.folder.d1, - 'review_state', - ) + "review_state", + ), ) diff --git a/plone/app/contentrules/tests/test_browser.py b/plone/app/contentrules/tests/test_browser.py index d9e0dda..f87ef42 100644 --- a/plone/app/contentrules/tests/test_browser.py +++ b/plone/app/contentrules/tests/test_browser.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from plone.app.contentrules.testing import PLONE_APP_CONTENTRULES_FUNCTIONAL_TESTING from plone.testing import layered @@ -6,16 +5,18 @@ import unittest -optionflags = (doctest.NORMALIZE_WHITESPACE | - doctest.ELLIPSIS | - doctest.REPORT_NDIFF) +optionflags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS | doctest.REPORT_NDIFF def test_suite(): suite = unittest.TestSuite() - for doc in ['assignment.txt', 'simplepublish.txt', 'multipublish.txt']: - suite.addTest(layered( - doctest.DocFileSuite(doc, package='plone.app.contentrules.tests', - optionflags=optionflags), - layer=PLONE_APP_CONTENTRULES_FUNCTIONAL_TESTING)) + for doc in ["assignment.txt", "simplepublish.txt", "multipublish.txt"]: + suite.addTest( + layered( + doctest.DocFileSuite( + doc, package="plone.app.contentrules.tests", optionflags=optionflags + ), + layer=PLONE_APP_CONTENTRULES_FUNCTIONAL_TESTING, + ) + ) return suite diff --git a/plone/app/contentrules/tests/test_cascading_rule.py b/plone/app/contentrules/tests/test_cascading_rule.py index b006440..efeac84 100644 --- a/plone/app/contentrules/tests/test_cascading_rule.py +++ b/plone/app/contentrules/tests/test_cascading_rule.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from plone.app.contentrules.api import edit_rule_assignment from plone.app.contentrules.testing import PLONE_APP_CONTENTRULES_FUNCTIONAL_TESTING from plone.app.testing import applyProfile @@ -16,28 +15,28 @@ class TestCascadingRule(unittest.TestCase): layer = PLONE_APP_CONTENTRULES_FUNCTIONAL_TESTING def setUp(self): - self.portal = self.layer['portal'] - self.request = self.layer['request'] + self.portal = self.layer["portal"] + self.request = self.layer["request"] login(self.portal, TEST_USER_NAME) - setRoles(self.portal, TEST_USER_ID, ['Manager']) - self.portal.invokeFactory('Folder', 'news') - self.portal.invokeFactory('Folder', 'events') + setRoles(self.portal, TEST_USER_ID, ["Manager"]) + self.portal.invokeFactory("Folder", "news") + self.portal.invokeFactory("Folder", "events") - applyProfile(self.portal, 'plone.app.contentrules:testing') - edit_rule_assignment(self.portal, 'test4', bubbles=1, enabled=1) - edit_rule_assignment(self.portal, 'test5', bubbles=1, enabled=1) + applyProfile(self.portal, "plone.app.contentrules:testing") + edit_rule_assignment(self.portal, "test4", bubbles=1, enabled=1) + edit_rule_assignment(self.portal, "test5", bubbles=1, enabled=1) def test_cascading_rule(self): # check that test2 rule and test4 rule are executed # test2 rule publishes the event in news folder # test4 rule moves it in events folder when it is published - createContentInContainer(self.portal.news, 'Event', id='my-event') - self.assertFalse('my-event' in self.portal.news) - self.assertTrue('my-event' in self.portal.events) + createContentInContainer(self.portal.news, "Event", id="my-event") + self.assertFalse("my-event" in self.portal.news) + self.assertTrue("my-event" in self.portal.events) wtool = self.portal.portal_workflow self.assertEqual( - wtool.getInfoFor(self.portal.events['my-event'], 'review_state'), - 'published', + wtool.getInfoFor(self.portal.events["my-event"], "review_state"), + "published", ) diff --git a/plone/app/contentrules/tests/test_condition_group.py b/plone/app/contentrules/tests/test_condition_group.py index 2145750..27cbde7 100644 --- a/plone/app/contentrules/tests/test_condition_group.py +++ b/plone/app/contentrules/tests/test_condition_group.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from plone.app.contentrules.conditions.group import GroupCondition from plone.app.contentrules.conditions.group import GroupEditFormView from plone.app.contentrules.rule import Rule @@ -8,65 +7,56 @@ from plone.contentrules.rule.interfaces import IRuleCondition from zope.component import getMultiAdapter from zope.component import getUtility -from zope.interface.interfaces import IObjectEvent from zope.interface import implementer +from zope.interface.interfaces import IObjectEvent @implementer(IObjectEvent) -class DummyEvent(object): - +class DummyEvent: def __init__(self, obj): self.object = obj class TestGroupCondition(ContentRulesTestCase): - def testRegistered(self): - element = getUtility(IRuleCondition, name='plone.conditions.Group') - self.assertEqual('plone.conditions.Group', element.addview) - self.assertEqual('edit', element.editview) + element = getUtility(IRuleCondition, name="plone.conditions.Group") + self.assertEqual("plone.conditions.Group", element.addview) + self.assertEqual("edit", element.editview) self.assertEqual(None, element.for_) self.assertEqual(None, element.event) def testInvokeAddView(self): - element = getUtility(IRuleCondition, name='plone.conditions.Group') + element = getUtility(IRuleCondition, name="plone.conditions.Group") storage = getUtility(IRuleStorage) - storage[u'foo'] = Rule() - rule = self.portal.restrictedTraverse('++rule++foo') + storage["foo"] = Rule() + rule = self.portal.restrictedTraverse("++rule++foo") - adding = getMultiAdapter( - (rule, self.portal.REQUEST), name='+condition') - addview = getMultiAdapter( - (adding, self.portal.REQUEST), name=element.addview) + adding = getMultiAdapter((rule, self.portal.REQUEST), name="+condition") + addview = getMultiAdapter((adding, self.portal.REQUEST), name=element.addview) addview.form_instance.update() - content = addview.form_instance.create( - data={'group_names': ['Manager']}) + content = addview.form_instance.create(data={"group_names": ["Manager"]}) addview.form_instance.add(content) e = rule.conditions[0] self.assertTrue(isinstance(e, GroupCondition)) - self.assertEqual(['Manager'], e.group_names) + self.assertEqual(["Manager"], e.group_names) def testInvokeEditView(self): - element = getUtility(IRuleCondition, name='plone.conditions.Group') + element = getUtility(IRuleCondition, name="plone.conditions.Group") e = GroupCondition() - editview = getMultiAdapter( - (e, self.folder.REQUEST), name=element.editview) + editview = getMultiAdapter((e, self.folder.REQUEST), name=element.editview) self.assertTrue(isinstance(editview, GroupEditFormView)) def testExecute(self): e = GroupCondition() - e.group_names = ['Administrators', 'Reviewers'] + e.group_names = ["Administrators", "Reviewers"] - ex = getMultiAdapter( - (self.portal, e, DummyEvent(self.folder)), IExecutable) + ex = getMultiAdapter((self.portal, e, DummyEvent(self.folder)), IExecutable) self.assertFalse(ex()) - group = self.portal.portal_groups.getGroupById('Administrators') - group.addMember( - self.portal.portal_membership.getAuthenticatedMember().getId()) + group = self.portal.portal_groups.getGroupById("Administrators") + group.addMember(self.portal.portal_membership.getAuthenticatedMember().getId()) - ex = getMultiAdapter( - (self.portal, e, DummyEvent(self.portal)), IExecutable) + ex = getMultiAdapter((self.portal, e, DummyEvent(self.portal)), IExecutable) self.assertTrue(ex()) diff --git a/plone/app/contentrules/tests/test_condition_portal_type.py b/plone/app/contentrules/tests/test_condition_portal_type.py index 3bdfedf..87f1cc8 100644 --- a/plone/app/contentrules/tests/test_condition_portal_type.py +++ b/plone/app/contentrules/tests/test_condition_portal_type.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from plone.app.contentrules.conditions.portaltype import PortalTypeCondition from plone.app.contentrules.conditions.portaltype import PortalTypeEditFormView from plone.app.contentrules.rule import Rule @@ -9,70 +8,60 @@ from Products.CMFCore.interfaces import ITypesTool from zope.component import getMultiAdapter from zope.component import getUtility -from zope.interface.interfaces import IObjectEvent from zope.interface import implementer +from zope.interface.interfaces import IObjectEvent @implementer(IObjectEvent) -class DummyEvent(object): - +class DummyEvent: def __init__(self, obj): self.object = obj class TestPortalTypeCondition(ContentRulesTestCase): - def testRegistered(self): - element = getUtility( - IRuleCondition, name='plone.conditions.PortalType') - self.assertEqual('plone.conditions.PortalType', element.addview) - self.assertEqual('edit', element.editview) + element = getUtility(IRuleCondition, name="plone.conditions.PortalType") + self.assertEqual("plone.conditions.PortalType", element.addview) + self.assertEqual("edit", element.editview) self.assertEqual(None, element.for_) self.assertEqual(IObjectEvent, element.event) def testInvokeAddView(self): - element = getUtility( - IRuleCondition, name='plone.conditions.PortalType') + element = getUtility(IRuleCondition, name="plone.conditions.PortalType") storage = getUtility(IRuleStorage) - storage[u'foo'] = Rule() - rule = self.portal.restrictedTraverse('++rule++foo') + storage["foo"] = Rule() + rule = self.portal.restrictedTraverse("++rule++foo") - adding = getMultiAdapter( - (rule, self.portal.REQUEST), name='+condition') - addview = getMultiAdapter( - (adding, self.portal.REQUEST), name=element.addview) + adding = getMultiAdapter((rule, self.portal.REQUEST), name="+condition") + addview = getMultiAdapter((adding, self.portal.REQUEST), name=element.addview) addview.form_instance.update() content = addview.form_instance.create( - data={'check_types': ['Folder', 'Image']}) + data={"check_types": ["Folder", "Image"]} + ) addview.form_instance.add(content) e = rule.conditions[0] self.assertTrue(isinstance(e, PortalTypeCondition)) - self.assertEqual(['Folder', 'Image'], e.check_types) + self.assertEqual(["Folder", "Image"], e.check_types) def testInvokeEditView(self): - element = getUtility( - IRuleCondition, name='plone.conditions.PortalType') + element = getUtility(IRuleCondition, name="plone.conditions.PortalType") e = PortalTypeCondition() - editview = getMultiAdapter( - (e, self.folder.REQUEST), name=element.editview) + editview = getMultiAdapter((e, self.folder.REQUEST), name=element.editview) self.assertTrue(isinstance(editview, PortalTypeEditFormView)) def testExecute(self): e = PortalTypeCondition() - e.check_types = ['Folder', 'Image'] + e.check_types = ["Folder", "Image"] - ex = getMultiAdapter( - (self.portal, e, DummyEvent(self.folder)), IExecutable) + ex = getMultiAdapter((self.portal, e, DummyEvent(self.folder)), IExecutable) self.assertTrue(ex()) - ex = getMultiAdapter( - (self.portal, e, DummyEvent(self.portal)), IExecutable) + ex = getMultiAdapter((self.portal, e, DummyEvent(self.portal)), IExecutable) self.assertFalse(ex()) self.folder.portal_types = None self.portal.getSiteManager().unregisterUtility(provided=ITypesTool) - ex = getMultiAdapter( - (self.portal, e, DummyEvent(self.folder)), IExecutable) + ex = getMultiAdapter((self.portal, e, DummyEvent(self.folder)), IExecutable) self.assertFalse(ex()) diff --git a/plone/app/contentrules/tests/test_condition_role.py b/plone/app/contentrules/tests/test_condition_role.py index 252cf80..94850ce 100644 --- a/plone/app/contentrules/tests/test_condition_role.py +++ b/plone/app/contentrules/tests/test_condition_role.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from plone.app.contentrules.conditions.role import RoleCondition from plone.app.contentrules.conditions.role import RoleEditFormView from plone.app.contentrules.rule import Rule @@ -8,63 +7,57 @@ from plone.contentrules.rule.interfaces import IRuleCondition from zope.component import getMultiAdapter from zope.component import getUtility -from zope.interface.interfaces import IObjectEvent from zope.interface import implementer +from zope.interface.interfaces import IObjectEvent @implementer(IObjectEvent) -class DummyEvent(object): - +class DummyEvent: def __init__(self, obj): self.object = obj class TestRoleCondition(ContentRulesTestCase): - def testRegistered(self): - element = getUtility(IRuleCondition, name='plone.conditions.Role') - self.assertEqual('plone.conditions.Role', element.addview) - self.assertEqual('edit', element.editview) + element = getUtility(IRuleCondition, name="plone.conditions.Role") + self.assertEqual("plone.conditions.Role", element.addview) + self.assertEqual("edit", element.editview) self.assertEqual(None, element.for_) self.assertEqual(None, element.event) def testInvokeAddView(self): - element = getUtility(IRuleCondition, name='plone.conditions.Role') + element = getUtility(IRuleCondition, name="plone.conditions.Role") storage = getUtility(IRuleStorage) - storage[u'foo'] = Rule() - rule = self.portal.restrictedTraverse('++rule++foo') + storage["foo"] = Rule() + rule = self.portal.restrictedTraverse("++rule++foo") - adding = getMultiAdapter( - (rule, self.portal.REQUEST), name='+condition') - addview = getMultiAdapter( - (adding, self.portal.REQUEST), name=element.addview) + adding = getMultiAdapter((rule, self.portal.REQUEST), name="+condition") + addview = getMultiAdapter((adding, self.portal.REQUEST), name=element.addview) addview.form_instance.update() content = addview.form_instance.create( - data={'role_names': ['Manager', 'Member']}) + data={"role_names": ["Manager", "Member"]} + ) addview.form_instance.add(content) e = rule.conditions[0] self.assertTrue(isinstance(e, RoleCondition)) - self.assertEqual(['Manager', 'Member'], e.role_names) + self.assertEqual(["Manager", "Member"], e.role_names) def testInvokeEditView(self): - element = getUtility(IRuleCondition, name='plone.conditions.Role') + element = getUtility(IRuleCondition, name="plone.conditions.Role") e = RoleCondition() - editview = getMultiAdapter( - (e, self.folder.REQUEST), name=element.editview) + editview = getMultiAdapter((e, self.folder.REQUEST), name=element.editview) self.assertTrue(isinstance(editview, RoleEditFormView)) def testExecute(self): e = RoleCondition() - e.role_names = ['Manager', 'Member'] + e.role_names = ["Manager", "Member"] - ex = getMultiAdapter( - (self.portal, e, DummyEvent(self.folder)), IExecutable) + ex = getMultiAdapter((self.portal, e, DummyEvent(self.folder)), IExecutable) self.assertTrue(ex()) - e.role_names = ['Reviewer'] + e.role_names = ["Reviewer"] - ex = getMultiAdapter( - (self.portal, e, DummyEvent(self.portal)), IExecutable) + ex = getMultiAdapter((self.portal, e, DummyEvent(self.portal)), IExecutable) self.assertFalse(ex()) diff --git a/plone/app/contentrules/tests/test_condition_tales_expression.py b/plone/app/contentrules/tests/test_condition_tales_expression.py index 201330b..af207c4 100644 --- a/plone/app/contentrules/tests/test_condition_tales_expression.py +++ b/plone/app/contentrules/tests/test_condition_tales_expression.py @@ -1,6 +1,9 @@ -# -*- coding: utf-8 -*- -from plone.app.contentrules.conditions.talesexpression import TalesExpressionCondition # noqa -from plone.app.contentrules.conditions.talesexpression import TalesExpressionEditFormView # noqa +from plone.app.contentrules.conditions.talesexpression import ( # noqa + TalesExpressionCondition, +) +from plone.app.contentrules.conditions.talesexpression import ( # noqa + TalesExpressionEditFormView, +) from plone.app.contentrules.rule import Rule from plone.app.contentrules.tests.base import ContentRulesTestCase from plone.contentrules.engine.interfaces import IRuleStorage @@ -8,76 +11,64 @@ from plone.contentrules.rule.interfaces import IRuleCondition from zope.component import getMultiAdapter from zope.component import getUtility -from zope.interface.interfaces import IObjectEvent from zope.interface import implementer +from zope.interface.interfaces import IObjectEvent @implementer(IObjectEvent) -class DummyEvent(object): - +class DummyEvent: def __init__(self, obj): self.object = obj class TestTalesExpressionCondition(ContentRulesTestCase): - def testRegistered(self): - element = getUtility( - IRuleCondition, name='plone.conditions.TalesExpression') - self.assertEqual('plone.conditions.TalesExpression', element.addview) - self.assertEqual('edit', element.editview) + element = getUtility(IRuleCondition, name="plone.conditions.TalesExpression") + self.assertEqual("plone.conditions.TalesExpression", element.addview) + self.assertEqual("edit", element.editview) self.assertEqual(None, element.for_) def testInvokeAddView(self): - element = getUtility( - IRuleCondition, name='plone.conditions.TalesExpression') + element = getUtility(IRuleCondition, name="plone.conditions.TalesExpression") storage = getUtility(IRuleStorage) - storage[u'foo'] = Rule() - rule = self.portal.restrictedTraverse('++rule++foo') + storage["foo"] = Rule() + rule = self.portal.restrictedTraverse("++rule++foo") - adding = getMultiAdapter( - (rule, self.portal.REQUEST), name='+condition') - addview = getMultiAdapter( - (adding, self.portal.REQUEST), name=element.addview) + adding = getMultiAdapter((rule, self.portal.REQUEST), name="+condition") + addview = getMultiAdapter((adding, self.portal.REQUEST), name=element.addview) addview.form_instance.update() content = addview.form_instance.create( - data={'tales_expression': 'python:"plone" in object.Subject()'}) + data={"tales_expression": 'python:"plone" in object.Subject()'} + ) addview.form_instance.add(content) e = rule.conditions[0] self.assertTrue(isinstance(e, TalesExpressionCondition)) - self.assertEqual('python:"plone" in object.Subject()', - e.tales_expression) + self.assertEqual('python:"plone" in object.Subject()', e.tales_expression) def testInvokeEditView(self): - element = getUtility( - IRuleCondition, name='plone.conditions.TalesExpression') + element = getUtility(IRuleCondition, name="plone.conditions.TalesExpression") e = TalesExpressionCondition() - editview = getMultiAdapter( - (e, self.folder.REQUEST), name=element.editview) + editview = getMultiAdapter((e, self.folder.REQUEST), name=element.editview) self.assertTrue(isinstance(editview, TalesExpressionEditFormView)) def testExecute(self): e = TalesExpressionCondition() e.tales_expression = 'python:"plone" in object.Subject()' - ex = getMultiAdapter( - (self.portal, e, DummyEvent(self.folder)), IExecutable) + ex = getMultiAdapter((self.portal, e, DummyEvent(self.folder)), IExecutable) self.assertEqual(False, ex()) - ex = getMultiAdapter( - (self.portal, e, DummyEvent(self.portal)), IExecutable) + ex = getMultiAdapter((self.portal, e, DummyEvent(self.portal)), IExecutable) self.assertEqual(False, ex()) - self.folder.setSubject(('plone', 'contentrules')) - ex = getMultiAdapter( - (self.portal, e, DummyEvent(self.folder)), IExecutable) + self.folder.setSubject(("plone", "contentrules")) + ex = getMultiAdapter((self.portal, e, DummyEvent(self.folder)), IExecutable) self.assertEqual(True, ex()) def testExecuteUnicodeString(self): e = TalesExpressionCondition() - e.tales_expression = u'string:${portal_url}' - ex = getMultiAdapter( - (self.portal, e, DummyEvent(self.folder)), IExecutable) + e.tales_expression = "string:${portal_url}" + ex = getMultiAdapter((self.portal, e, DummyEvent(self.folder)), IExecutable) self.assertEqual(True, ex()) diff --git a/plone/app/contentrules/tests/test_condition_wfstate.py b/plone/app/contentrules/tests/test_condition_wfstate.py index 710d25d..1970de9 100644 --- a/plone/app/contentrules/tests/test_condition_wfstate.py +++ b/plone/app/contentrules/tests/test_condition_wfstate.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from plone.app.contentrules.conditions.wfstate import WorkflowStateCondition from plone.app.contentrules.conditions.wfstate import WorkflowStateEditFormView from plone.app.contentrules.rule import Rule @@ -8,70 +7,60 @@ from plone.contentrules.rule.interfaces import IRuleCondition from zope.component import getMultiAdapter from zope.component import getUtility -from zope.interface.interfaces import IObjectEvent from zope.interface import implementer +from zope.interface.interfaces import IObjectEvent @implementer(IObjectEvent) -class DummyEvent(object): - +class DummyEvent: def __init__(self, obj): self.object = obj class TestWorkflowStateCondition(ContentRulesTestCase): - def testRegistered(self): - element = getUtility( - IRuleCondition, name='plone.conditions.WorkflowState') - self.assertEqual('plone.conditions.WorkflowState', element.addview) - self.assertEqual('edit', element.editview) + element = getUtility(IRuleCondition, name="plone.conditions.WorkflowState") + self.assertEqual("plone.conditions.WorkflowState", element.addview) + self.assertEqual("edit", element.editview) self.assertEqual(None, element.for_) self.assertEqual(IObjectEvent, element.event) def testInvokeAddView(self): - element = getUtility( - IRuleCondition, name='plone.conditions.WorkflowState') + element = getUtility(IRuleCondition, name="plone.conditions.WorkflowState") storage = getUtility(IRuleStorage) - storage[u'foo'] = Rule() - rule = self.portal.restrictedTraverse('++rule++foo') + storage["foo"] = Rule() + rule = self.portal.restrictedTraverse("++rule++foo") - adding = getMultiAdapter( - (rule, self.portal.REQUEST), name='+condition') - addview = getMultiAdapter( - (adding, self.portal.REQUEST), name=element.addview) + adding = getMultiAdapter((rule, self.portal.REQUEST), name="+condition") + addview = getMultiAdapter((adding, self.portal.REQUEST), name=element.addview) addview.form_instance.update() content = addview.form_instance.create( - data={'wf_states': ['visible', 'published']}) + data={"wf_states": ["visible", "published"]} + ) addview.form_instance.add(content) e = rule.conditions[0] self.assertTrue(isinstance(e, WorkflowStateCondition)) - self.assertEqual(['visible', 'published'], e.wf_states) + self.assertEqual(["visible", "published"], e.wf_states) def testInvokeEditView(self): - element = getUtility( - IRuleCondition, name='plone.conditions.WorkflowState') + element = getUtility(IRuleCondition, name="plone.conditions.WorkflowState") e = WorkflowStateCondition() - editview = getMultiAdapter( - (e, self.folder.REQUEST), name=element.editview) + editview = getMultiAdapter((e, self.folder.REQUEST), name=element.editview) self.assertTrue(isinstance(editview, WorkflowStateEditFormView)) def testExecute(self): e = WorkflowStateCondition() - e.wf_states = ['visible', 'private'] + e.wf_states = ["visible", "private"] - ex = getMultiAdapter( - (self.portal, e, DummyEvent(self.folder)), IExecutable) + ex = getMultiAdapter((self.portal, e, DummyEvent(self.folder)), IExecutable) self.assertTrue(ex()) - self.portal.portal_workflow.doActionFor(self.folder, 'publish') + self.portal.portal_workflow.doActionFor(self.folder, "publish") - ex = getMultiAdapter( - (self.portal, e, DummyEvent(self.folder)), IExecutable) + ex = getMultiAdapter((self.portal, e, DummyEvent(self.folder)), IExecutable) self.assertFalse(ex()) - ex = getMultiAdapter( - (self.portal, e, DummyEvent(self.portal)), IExecutable) + ex = getMultiAdapter((self.portal, e, DummyEvent(self.portal)), IExecutable) self.assertFalse(ex()) diff --git a/plone/app/contentrules/tests/test_condition_wftransition.py b/plone/app/contentrules/tests/test_condition_wftransition.py index 4de5dfb..d83316d 100644 --- a/plone/app/contentrules/tests/test_condition_wftransition.py +++ b/plone/app/contentrules/tests/test_condition_wftransition.py @@ -1,6 +1,9 @@ -# -*- coding: utf-8 -*- -from plone.app.contentrules.conditions.wftransition import WorkflowTransitionCondition # noqa -from plone.app.contentrules.conditions.wftransition import WorkflowTransitionEditFormView # noqa +from plone.app.contentrules.conditions.wftransition import ( # noqa + WorkflowTransitionCondition, +) +from plone.app.contentrules.conditions.wftransition import ( # noqa + WorkflowTransitionEditFormView, +) from plone.app.contentrules.rule import Rule from plone.app.contentrules.tests.base import ContentRulesTestCase from plone.contentrules.engine.interfaces import IRuleStorage @@ -13,48 +16,41 @@ class TestWorkflowTransitionCondition(ContentRulesTestCase): - def testRegistered(self): - element = getUtility( - IRuleCondition, name='plone.conditions.WorkflowTransition') - self.assertEqual( - 'plone.conditions.WorkflowTransition', element.addview) - self.assertEqual('edit', element.editview) + element = getUtility(IRuleCondition, name="plone.conditions.WorkflowTransition") + self.assertEqual("plone.conditions.WorkflowTransition", element.addview) + self.assertEqual("edit", element.editview) self.assertEqual(None, element.for_) self.assertEqual(IActionSucceededEvent, element.event) def testInvokeAddView(self): - element = getUtility( - IRuleCondition, name='plone.conditions.WorkflowTransition') + element = getUtility(IRuleCondition, name="plone.conditions.WorkflowTransition") storage = getUtility(IRuleStorage) - storage[u'foo'] = Rule() - rule = self.portal.restrictedTraverse('++rule++foo') + storage["foo"] = Rule() + rule = self.portal.restrictedTraverse("++rule++foo") - adding = getMultiAdapter( - (rule, self.portal.REQUEST), name='+condition') - addview = getMultiAdapter( - (adding, self.portal.REQUEST), name=element.addview) + adding = getMultiAdapter((rule, self.portal.REQUEST), name="+condition") + addview = getMultiAdapter((adding, self.portal.REQUEST), name=element.addview) addview.form_instance.update() content = addview.form_instance.create( - data={'wf_transitions': ['publish', 'hide']}) + data={"wf_transitions": ["publish", "hide"]} + ) addview.form_instance.add(content) e = rule.conditions[0] self.assertTrue(isinstance(e, WorkflowTransitionCondition)) - self.assertEqual(['publish', 'hide'], e.wf_transitions) + self.assertEqual(["publish", "hide"], e.wf_transitions) def testInvokeEditView(self): - element = getUtility( - IRuleCondition, name='plone.conditions.WorkflowTransition') + element = getUtility(IRuleCondition, name="plone.conditions.WorkflowTransition") e = WorkflowTransitionCondition() - editview = getMultiAdapter( - (e, self.folder.REQUEST), name=element.editview) + editview = getMultiAdapter((e, self.folder.REQUEST), name=element.editview) self.assertTrue(isinstance(editview, WorkflowTransitionEditFormView)) def testExecute(self): e = WorkflowTransitionCondition() - e.wf_transitions = ['publish', 'hide'] + e.wf_transitions = ["publish", "hide"] ex = getMultiAdapter( ( @@ -62,10 +58,10 @@ def testExecute(self): e, ActionSucceededEvent( self.folder, - 'dummy_workflow', - 'publish', + "dummy_workflow", + "publish", None, - ) + ), ), IExecutable, ) @@ -77,10 +73,10 @@ def testExecute(self): e, ActionSucceededEvent( self.folder, - 'dummy_workflow', - 'retract', + "dummy_workflow", + "retract", None, - ) + ), ), IExecutable, ) @@ -92,10 +88,10 @@ def testExecute(self): e, ActionSucceededEvent( self.folder, - 'dummy_workflow', - 'hide', + "dummy_workflow", + "hide", None, - ) + ), ), IExecutable, ) diff --git a/plone/app/contentrules/tests/test_configuration.py b/plone/app/contentrules/tests/test_configuration.py index 885cd7a..5e0d50b 100644 --- a/plone/app/contentrules/tests/test_configuration.py +++ b/plone/app/contentrules/tests/test_configuration.py @@ -1,5 +1,6 @@ -# -*- coding: utf-8 -*- -from plone.app.contentrules.testing import PLONE_APP_CONTENTRULES_FUNCTIONAL_TESTING # noqa: E501 +from plone.app.contentrules.testing import ( # noqa: E501 + PLONE_APP_CONTENTRULES_FUNCTIONAL_TESTING, +) from plone.app.testing import applyProfile from plone.app.testing import login from plone.app.testing import setRoles @@ -22,72 +23,71 @@ class TestGenericSetup(unittest.TestCase): layer = PLONE_APP_CONTENTRULES_FUNCTIONAL_TESTING def setUp(self): - self.portal = self.layer['portal'] - self.request = self.layer['request'] + self.portal = self.layer["portal"] + self.request = self.layer["request"] login(self.portal, TEST_USER_NAME) - setRoles(self.portal, TEST_USER_ID, ['Manager']) - self.portal.invokeFactory('Folder', 'news') - self.portal.invokeFactory('Folder', 'events') + setRoles(self.portal, TEST_USER_ID, ["Manager"]) + self.portal.invokeFactory("Folder", "news") + self.portal.invokeFactory("Folder", "events") self.storage = getUtility(IRuleStorage) - applyProfile(self.portal, 'plone.app.contentrules:testing') + applyProfile(self.portal, "plone.app.contentrules:testing") def testRuleInstalled(self): - self.assertTrue('test1' in self.storage) - self.assertTrue('test2' in self.storage) + self.assertTrue("test1" in self.storage) + self.assertTrue("test2" in self.storage) def testRulesConfigured(self): - rule1 = self.storage['test1'] - self.assertEqual('Test rule 1', rule1.title) - self.assertEqual('A test rule', rule1.description) + rule1 = self.storage["test1"] + self.assertEqual("Test rule 1", rule1.title) + self.assertEqual("A test rule", rule1.description) self.assertEqual(IObjectModifiedEvent, rule1.event) self.assertEqual(True, rule1.enabled) self.assertEqual(False, rule1.stop) self.assertEqual(2, len(rule1.conditions)) - self.assertEqual('plone.conditions.PortalType', - rule1.conditions[0].element) - self.assertEqual(set(['Document', 'News Item']), - set(rule1.conditions[0].check_types)) - self.assertEqual('plone.conditions.Role', rule1.conditions[1].element) - self.assertEqual(['Manager'], list(rule1.conditions[1].role_names)) + self.assertEqual("plone.conditions.PortalType", rule1.conditions[0].element) + self.assertEqual( + {"Document", "News Item"}, set(rule1.conditions[0].check_types) + ) + self.assertEqual("plone.conditions.Role", rule1.conditions[1].element) + self.assertEqual(["Manager"], list(rule1.conditions[1].role_names)) self.assertEqual(1, len(rule1.actions)) - self.assertEqual('plone.actions.Notify', rule1.actions[0].element) - self.assertEqual(u'A message: Hej d\xe5', rule1.actions[0].message) - self.assertEqual('info', rule1.actions[0].message_type) + self.assertEqual("plone.actions.Notify", rule1.actions[0].element) + self.assertEqual("A message: Hej d\xe5", rule1.actions[0].message) + self.assertEqual("info", rule1.actions[0].message_type) - rule2 = self.storage['test2'] - self.assertEqual('Test rule 2', rule2.title) - self.assertEqual('Another test rule', rule2.description) + rule2 = self.storage["test2"] + self.assertEqual("Test rule 2", rule2.title) + self.assertEqual("Another test rule", rule2.description) self.assertEqual(IObjectModifiedEvent, rule2.event) self.assertEqual(False, rule2.enabled) self.assertEqual(True, rule2.stop) self.assertEqual(1, len(rule2.conditions)) - self.assertEqual('plone.conditions.PortalType', - rule2.conditions[0].element) - self.assertEqual(['Event'], list(rule2.conditions[0].check_types)) + self.assertEqual("plone.conditions.PortalType", rule2.conditions[0].element) + self.assertEqual(["Event"], list(rule2.conditions[0].check_types)) self.assertEqual(1, len(rule2.actions)) - self.assertEqual('plone.actions.Workflow', rule2.actions[0].element) - self.assertEqual('publish', rule2.actions[0].transition) + self.assertEqual("plone.actions.Workflow", rule2.actions[0].element) + self.assertEqual("publish", rule2.actions[0].transition) def testRuleAssigned(self): assignable = IRuleAssignmentManager(self.portal.news) self.assertEqual(3, len(assignable)) - self.assertEqual(True, assignable['test1'].enabled) - self.assertEqual(False, assignable['test1'].bubbles) + self.assertEqual(True, assignable["test1"].enabled) + self.assertEqual(False, assignable["test1"].bubbles) - self.assertEqual(False, assignable['test2'].enabled) - self.assertEqual(True, assignable['test2'].bubbles) + self.assertEqual(False, assignable["test2"].enabled) + self.assertEqual(True, assignable["test2"].bubbles) - self.assertEqual(False, assignable['test3'].enabled) - self.assertEqual(False, assignable['test3'].bubbles) + self.assertEqual(False, assignable["test3"].enabled) + self.assertEqual(False, assignable["test3"].bubbles) def testAssignmentOrdering(self): assignable = IRuleAssignmentManager(self.portal.news) - self.assertEqual(set([u'test3', u'test2', u'test1']), set(assignable.keys())) + self.assertEqual({"test3", "test2", "test1"}, set(assignable.keys())) def testImportTwice(self): # Ensure rules, actions/conditions and assignments are not duplicated @@ -95,7 +95,8 @@ def testImportTwice(self): portal_setup = self.portal.portal_setup time.sleep(1) # avoid timestamp colission portal_setup.runAllImportStepsFromProfile( - 'profile-plone.app.contentrules:testing') + "profile-plone.app.contentrules:testing" + ) # We should get the same results as before self.testRuleInstalled() @@ -106,22 +107,23 @@ def testExport(self): self.maxDiff = None site = self.portal context = TarballExportContext(self.portal.portal_setup) - exporter = getMultiAdapter( - (site, context), IBody, name=u'plone.contentrules') + exporter = getMultiAdapter((site, context), IBody, name="plone.contentrules") - body = exporter.body.decode('utf8') + body = exporter.body.decode("utf8") # There is a bug in supermodel such that Set fields can be exported in a random order - body = body.replace(""" + body = body.replace( + """ News Item Document -""",""" +""", + """ Document News Item -""" +""", ) - expected = u""" + expected = """ """ - + self.assertEqual(expected.strip(), body.strip()) diff --git a/plone/app/contentrules/tests/test_events.py b/plone/app/contentrules/tests/test_events.py index 0d20093..374f632 100644 --- a/plone/app/contentrules/tests/test_events.py +++ b/plone/app/contentrules/tests/test_events.py @@ -1,9 +1,7 @@ -# -*- coding: utf-8 -*- from plone.app.contentrules.tests.base import ContentRulesTestCase class TestEvents(ContentRulesTestCase): - def testEventHandlerExecutesRules(self): # XXX Test missing pass diff --git a/plone/app/contentrules/tests/test_handlers.py b/plone/app/contentrules/tests/test_handlers.py index fce4c5f..678d9bc 100644 --- a/plone/app/contentrules/tests/test_handlers.py +++ b/plone/app/contentrules/tests/test_handlers.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from plone.app.contentrules import handlers from plone.app.contentrules.tests import dummy from plone.app.contentrules.tests.base import ContentRulesTestCase @@ -7,9 +6,8 @@ class TestDuplicateRuleFilter(ContentRulesTestCase): - def setUp(self): - super(TestDuplicateRuleFilter, self).setUp() + super().setUp() self.context = self.folder self.event = dummy.DummyEvent(self.context) self.rulefilter = handlers.DuplicateRuleFilter() @@ -28,7 +26,7 @@ def test_call_two_events_in_same_context(self): # they are not filtered to_execute = self.rulefilter(self.context, self.rule, self.event) self.assertTrue(to_execute) - self.portal.invokeFactory('Folder', 'folder2') + self.portal.invokeFactory("Folder", "folder2") event2 = dummy.DummyEvent(self.portal.folder2) to_execute = self.rulefilter(self.context, self.rule, event2) self.assertTrue(to_execute) @@ -38,19 +36,3 @@ def test_call_uuidaware(self): self.assertTrue(to_execute) to_execute = self.rulefilter(self.uuidaware, self.rule, self.event) self.assertTrue(not to_execute) - - def test_delayed_events(self): - # many events can be delayed - # But this was only true for Archetypes content. - # The tests no use dexterity so we skip it: - return - - self.portal.invokeFactory('Folder', 'folder2') - event1 = dummy.DummyEvent(self.folder) - event2 = dummy.DummyEvent(self.portal.folder2) - from plone.app.contentrules.handlers import _status - _status.delayed_events = {} - handlers.added(event1) - handlers.added(event2) - from plone.app.contentrules.handlers import _status - self.assertEqual(len(_status.delayed_events), 2) diff --git a/plone/app/contentrules/tests/test_rule_assignment_mapping.py b/plone/app/contentrules/tests/test_rule_assignment_mapping.py index 5f563b4..4b62a7c 100644 --- a/plone/app/contentrules/tests/test_rule_assignment_mapping.py +++ b/plone/app/contentrules/tests/test_rule_assignment_mapping.py @@ -1,9 +1,10 @@ -# -*- coding: utf-8 -*- from plone.app.contentrules import api from plone.app.contentrules.rule import get_assignments from plone.app.contentrules.rule import insert_assignment from plone.app.contentrules.rule import Rule -from plone.app.contentrules.testing import PLONE_APP_CONTENTRULES_FUNCTIONAL_TESTING # noqa: E501 +from plone.app.contentrules.testing import ( # noqa: E501 + PLONE_APP_CONTENTRULES_FUNCTIONAL_TESTING, +) from plone.app.contentrules.tests.base import ContentRulesTestCase from plone.app.testing import login from plone.app.testing import setRoles @@ -23,122 +24,124 @@ class TestRuleAssignmentMapping(unittest.TestCase): layer = PLONE_APP_CONTENTRULES_FUNCTIONAL_TESTING def setUp(self): - self.portal = self.layer['portal'] - self.request = self.layer['request'] + self.portal = self.layer["portal"] + self.request = self.layer["request"] login(self.portal, TEST_USER_NAME) - setRoles(self.portal, TEST_USER_ID, ['Manager']) - self.portal.invokeFactory('Folder', 'f1') - self.folder = self.portal['f1'] - self.folder.invokeFactory('Document', 'd1') - self.portal.invokeFactory('Folder', 'target') - self.folder.invokeFactory('Folder', 'f1') - self.folder.f1.invokeFactory('Folder', 'f11') - self.folder.f1.invokeFactory('Folder', 'f12') + setRoles(self.portal, TEST_USER_ID, ["Manager"]) + self.portal.invokeFactory("Folder", "f1") + self.folder = self.portal["f1"] + self.folder.invokeFactory("Document", "d1") + self.portal.invokeFactory("Folder", "target") + self.folder.invokeFactory("Folder", "f1") + self.folder.f1.invokeFactory("Folder", "f11") + self.folder.f1.invokeFactory("Folder", "f12") self.storage = getUtility(IRuleStorage) - self.storage['r1'] = Rule() - self.storage['r2'] = Rule() - self.storage['r3'] = Rule() + self.storage["r1"] = Rule() + self.storage["r2"] = Rule() + self.storage["r3"] = Rule() self.f11a = IRuleAssignmentManager(self.folder.f1.f11) - self.f11a['r1'] = RuleAssignment('r1', bubbles=True) - insert_assignment(self.storage['r1'], - '/'.join(self.folder.f1.f11.getPhysicalPath())) + self.f11a["r1"] = RuleAssignment("r1", bubbles=True) + insert_assignment( + self.storage["r1"], "/".join(self.folder.f1.f11.getPhysicalPath()) + ) self.f12a = IRuleAssignmentManager(self.folder.f1.f12) - self.f12a['r1'] = RuleAssignment('r1', bubbles=True) - insert_assignment(self.storage['r1'], - '/'.join(self.folder.f1.f12.getPhysicalPath())) + self.f12a["r1"] = RuleAssignment("r1", bubbles=True) + insert_assignment( + self.storage["r1"], "/".join(self.folder.f1.f12.getPhysicalPath()) + ) - self.f12a['r2'] = RuleAssignment('r2', bubbles=True) - insert_assignment(self.storage['r2'], - '/'.join(self.folder.f1.f12.getPhysicalPath())) + self.f12a["r2"] = RuleAssignment("r2", bubbles=True) + insert_assignment( + self.storage["r2"], "/".join(self.folder.f1.f12.getPhysicalPath()) + ) def testRuleRemoved(self): - self.assertTrue('r1' in self.f11a) - self.assertTrue('r1' in self.f12a) + self.assertTrue("r1" in self.f11a) + self.assertTrue("r1" in self.f12a) - del self.storage['r1'] + del self.storage["r1"] - self.assertFalse('r1' in self.f11a) - self.assertFalse('r1' in self.f12a) + self.assertFalse("r1" in self.f11a) + self.assertFalse("r1" in self.f12a) def testContainerMoved(self): - f12path = '/'.join(self.folder.f1.f12.getPhysicalPath()) - self.assertTrue(f12path in get_assignments(self.storage['r1'])) - self.assertTrue(f12path in get_assignments(self.storage['r2'])) + f12path = "/".join(self.folder.f1.f12.getPhysicalPath()) + self.assertTrue(f12path in get_assignments(self.storage["r1"])) + self.assertTrue(f12path in get_assignments(self.storage["r2"])) transaction.savepoint(1) - self.folder.f1.manage_renameObject('f12', 'f12a') - f12apath = '/'.join(self.folder.f1.f12a.getPhysicalPath()) + self.folder.f1.manage_renameObject("f12", "f12a") + f12apath = "/".join(self.folder.f1.f12a.getPhysicalPath()) - self.assertFalse(f12path in get_assignments(self.storage['r1'])) - self.assertFalse(f12path in get_assignments(self.storage['r2'])) + self.assertFalse(f12path in get_assignments(self.storage["r1"])) + self.assertFalse(f12path in get_assignments(self.storage["r2"])) - self.assertTrue(f12apath in get_assignments(self.storage['r1'])) - self.assertTrue(f12apath in get_assignments(self.storage['r1'])) + self.assertTrue(f12apath in get_assignments(self.storage["r1"])) + self.assertTrue(f12apath in get_assignments(self.storage["r1"])) def testParentOfContainerMoved(self): - f12path = '/'.join(self.folder.f1.f12.getPhysicalPath()) - self.assertTrue(f12path in get_assignments(self.storage['r1'])) - self.assertTrue(f12path in get_assignments(self.storage['r2'])) + f12path = "/".join(self.folder.f1.f12.getPhysicalPath()) + self.assertTrue(f12path in get_assignments(self.storage["r1"])) + self.assertTrue(f12path in get_assignments(self.storage["r2"])) transaction.savepoint(1) - self.folder.manage_renameObject('f1', 'f1a') - f12apath = '/'.join(self.folder.f1a.f12.getPhysicalPath()) + self.folder.manage_renameObject("f1", "f1a") + f12apath = "/".join(self.folder.f1a.f12.getPhysicalPath()) - self.assertFalse(f12path in get_assignments(self.storage['r1'])) - self.assertFalse(f12path in get_assignments(self.storage['r2'])) + self.assertFalse(f12path in get_assignments(self.storage["r1"])) + self.assertFalse(f12path in get_assignments(self.storage["r2"])) - self.assertTrue(f12apath in get_assignments(self.storage['r1'])) - self.assertTrue(f12apath in get_assignments(self.storage['r1'])) + self.assertTrue(f12apath in get_assignments(self.storage["r1"])) + self.assertTrue(f12apath in get_assignments(self.storage["r1"])) def testContainerRemoved(self): - f12path = '/'.join(self.folder.f1.f12.getPhysicalPath()) - self.assertTrue(f12path in get_assignments(self.storage['r1'])) - self.assertTrue(f12path in get_assignments(self.storage['r2'])) + f12path = "/".join(self.folder.f1.f12.getPhysicalPath()) + self.assertTrue(f12path in get_assignments(self.storage["r1"])) + self.assertTrue(f12path in get_assignments(self.storage["r2"])) transaction.savepoint(1) - self.folder._delObject('f1') + self.folder._delObject("f1") - self.assertFalse(f12path in get_assignments(self.storage['r1'])) - self.assertFalse(f12path in get_assignments(self.storage['r2'])) + self.assertFalse(f12path in get_assignments(self.storage["r1"])) + self.assertFalse(f12path in get_assignments(self.storage["r2"])) def testRuleAssignmentRemovedAPI(self): - self.assertTrue('r1' in self.f11a) - self.assertTrue('r1' in self.f12a) + self.assertTrue("r1" in self.f11a) + self.assertTrue("r1" in self.f12a) - api.unassign_rule(self.folder.f1.f11, 'r1') + api.unassign_rule(self.folder.f1.f11, "r1") - self.assertFalse('r1' in self.f11a) - self.assertTrue('r1' in self.f12a) + self.assertFalse("r1" in self.f11a) + self.assertTrue("r1" in self.f12a) def testRuleAssignmentEditedAPI(self): - self.assertTrue(self.f11a['r1'].bubbles) - self.assertTrue(self.f11a['r1'].enabled) + self.assertTrue(self.f11a["r1"].bubbles) + self.assertTrue(self.f11a["r1"].enabled) - api.edit_rule_assignment(self.folder.f1.f11, 'r1', - bubbles=False, enabled=False) + api.edit_rule_assignment(self.folder.f1.f11, "r1", bubbles=False, enabled=False) - self.assertFalse(self.f11a['r1'].bubbles) - self.assertFalse(self.f11a['r1'].enabled) + self.assertFalse(self.f11a["r1"].bubbles) + self.assertFalse(self.f11a["r1"].enabled) - api.edit_rule_assignment(self.folder.f1.f11, 'r1', - bubbles=True, enabled=True) + api.edit_rule_assignment(self.folder.f1.f11, "r1", bubbles=True, enabled=True) - self.assertTrue(self.f11a['r1'].bubbles) - self.assertTrue(self.f11a['r1'].enabled) + self.assertTrue(self.f11a["r1"].bubbles) + self.assertTrue(self.f11a["r1"].enabled) def testRuleAssignmentAddedAPI(self): - api.assign_rule(self.folder.f1.f11, 'r2', enabled=True, bubbles=True) - self.assertTrue('r2' in self.f11a) - self.assertTrue(self.f11a['r2'].enabled) - self.assertTrue(self.f11a['r2'].bubbles) - - api.assign_rule(self.folder.f1.f11, 'r3', enabled=True, bubbles=False, - insert_before='r2') - self.assertTrue('r3' in self.f11a) - self.assertTrue(self.f11a['r3'].enabled) - self.assertFalse(self.f11a['r3'].bubbles) - - self.assertEqual(self.f11a.keys(), ['r1', 'r3', 'r2']) + api.assign_rule(self.folder.f1.f11, "r2", enabled=True, bubbles=True) + self.assertTrue("r2" in self.f11a) + self.assertTrue(self.f11a["r2"].enabled) + self.assertTrue(self.f11a["r2"].bubbles) + + api.assign_rule( + self.folder.f1.f11, "r3", enabled=True, bubbles=False, insert_before="r2" + ) + self.assertTrue("r3" in self.f11a) + self.assertTrue(self.f11a["r3"].enabled) + self.assertFalse(self.f11a["r3"].bubbles) + + self.assertEqual(self.f11a.keys(), ["r1", "r3", "r2"]) diff --git a/plone/app/contentrules/tests/test_rule_management_views.py b/plone/app/contentrules/tests/test_rule_management_views.py index 1f12657..f96137f 100644 --- a/plone/app/contentrules/tests/test_rule_management_views.py +++ b/plone/app/contentrules/tests/test_rule_management_views.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from .dummy import DummyAction from .dummy import DummyCondition from plone.app.contentrules.browser.rule import RuleEditFormView @@ -12,17 +11,15 @@ class DummyModifiedRule(Rule): - title = 'My test rule' - description = 'Test my rule' + title = "My test rule" + description = "Test my rule" event = IObjectModifiedEvent enabled = True class TestRuleManagementViews(ContentRulesTestCase): - def testRuleAdding(self): - adding = getMultiAdapter( - (self.portal, self.portal.REQUEST), name='+rule') + adding = getMultiAdapter((self.portal, self.portal.REQUEST), name="+rule") storage = getUtility(IRuleStorage) self.assertEqual(0, len(storage)) r = Rule() @@ -31,39 +28,40 @@ def testRuleAdding(self): self.assertTrue(list(storage.values())[0] is r) def testRuleAddView(self): - adding = getMultiAdapter( - (self.portal, self.portal.REQUEST), name='+rule') + adding = getMultiAdapter((self.portal, self.portal.REQUEST), name="+rule") addview = getMultiAdapter( - (adding, self.portal.REQUEST), name='plone.ContentRule') + (adding, self.portal.REQUEST), name="plone.ContentRule" + ) storage = getUtility(IRuleStorage) self.assertEqual(0, len(storage)) addview.form_instance.update() - content = addview.form_instance.create({'title': 'foo', 'description': 'bar', 'event': None}) # noqa + content = addview.form_instance.create( + {"title": "foo", "description": "bar", "event": None} + ) # noqa addview.form_instance.add(content) self.assertEqual(1, len(storage)) - self.assertEqual('foo', list(storage.values())[0].title) + self.assertEqual("foo", list(storage.values())[0].title) def testRuleEditView(self): r = Rule() - editview = getMultiAdapter((r, self.portal.REQUEST), name='edit') + editview = getMultiAdapter((r, self.portal.REQUEST), name="edit") self.assertTrue(isinstance(editview, RuleEditFormView)) class TestRuleElementManagementViews(ContentRulesTestCase): - def afterSetUp(self): - self.setRoles(('Manager', )) + self.setRoles(("Manager",)) def testRuleStopModification(self): storage = getUtility(IRuleStorage) - storage[u'foo'] = Rule() + storage["foo"] = Rule() - rule = self.portal.restrictedTraverse('++rule++foo') - view = rule.restrictedTraverse('manage-elements') - view.template = lambda: 'No template thanks' + rule = self.portal.restrictedTraverse("++rule++foo") + view = rule.restrictedTraverse("manage-elements") + view.template = lambda: "No template thanks" - self.portal.REQUEST.form['stopExecuting'] = 'on' - self.portal.REQUEST.form['form.button.Save'] = True + self.portal.REQUEST.form["stopExecuting"] = "on" + self.portal.REQUEST.form["form.button.Save"] = True self.addAuthToRequest() self.assertEqual(False, rule.stop) @@ -72,10 +70,9 @@ def testRuleStopModification(self): def testRuleConditionAdding(self): storage = getUtility(IRuleStorage) - storage[u'foo'] = Rule() - rule = self.portal.restrictedTraverse('++rule++foo') - adding = getMultiAdapter( - (rule, self.portal.REQUEST), name='+condition') + storage["foo"] = Rule() + rule = self.portal.restrictedTraverse("++rule++foo") + adding = getMultiAdapter((rule, self.portal.REQUEST), name="+condition") d = DummyCondition() self.assertEqual(0, len(rule.conditions)) adding.add(d) @@ -84,9 +81,9 @@ def testRuleConditionAdding(self): def testRuleActionAdding(self): storage = getUtility(IRuleStorage) - storage[u'foo'] = Rule() - rule = self.portal.restrictedTraverse('++rule++foo') - adding = getMultiAdapter((rule, self.portal.REQUEST), name='+action') + storage["foo"] = Rule() + rule = self.portal.restrictedTraverse("++rule++foo") + adding = getMultiAdapter((rule, self.portal.REQUEST), name="+action") d = DummyAction() self.assertEqual(0, len(rule.actions)) adding.add(d) @@ -96,49 +93,48 @@ def testRuleActionAdding(self): def testRulesControlPanel(self): portal = self.portal storage = getUtility(IRuleStorage) - storage[u'foo'] = DummyModifiedRule() - controlpanel = portal.restrictedTraverse('@@rules-controlpanel') + storage["foo"] = DummyModifiedRule() + controlpanel = portal.restrictedTraverse("@@rules-controlpanel") registered_rules = controlpanel.registeredRules() self.assertEqual(1, len(registered_rules)) registered_rule = registered_rules[0] self.assertEqual( - registered_rule['row_class'], - 'trigger-iobjectmodifiedevent state-enabled assignment-unassigned', + registered_rule["row_class"], + "trigger-iobjectmodifiedevent state-enabled assignment-unassigned", ) - self.assertEqual(registered_rule['trigger'], - 'Object modified') - self.assertTrue(registered_rule['enabled']) - self.assertFalse(registered_rule['assigned']) + self.assertEqual(registered_rule["trigger"], "Object modified") + self.assertTrue(registered_rule["enabled"]) + self.assertFalse(registered_rule["assigned"]) rule_types = controlpanel.ruleTypesToShow() - rule_types_ids = [r['id'] for r in rule_types] - self.assertTrue('trigger-iobjectmodifiedevent' in rule_types_ids) - self.assertFalse('trigger-iobjectaddedevent' in rule_types_ids) + rule_types_ids = [r["id"] for r in rule_types] + self.assertTrue("trigger-iobjectmodifiedevent" in rule_types_ids) + self.assertFalse("trigger-iobjectaddedevent" in rule_types_ids) rule_states = controlpanel.statesToShow() - rule_states_ids = [r['id'] for r in rule_states] - self.assertTrue('state-enabled' in rule_states_ids) - self.assertTrue('state-disabled' in rule_states_ids) + rule_states_ids = [r["id"] for r in rule_states] + self.assertTrue("state-enabled" in rule_states_ids) + self.assertTrue("state-disabled" in rule_states_ids) # enable rule - portal.REQUEST['rule-id'] = 'foo' + portal.REQUEST["rule-id"] = "foo" self.addAuthToRequest() - portal.restrictedTraverse('@@contentrule-disable').disable_rule() + portal.restrictedTraverse("@@contentrule-disable").disable_rule() registered_rules = controlpanel.registeredRules() - self.assertFalse(registered_rules[0]['enabled']) + self.assertFalse(registered_rules[0]["enabled"]) - portal.restrictedTraverse('@@contentrule-enable').enable_rule() + portal.restrictedTraverse("@@contentrule-enable").enable_rule() registered_rules = controlpanel.registeredRules() - self.assertTrue(registered_rules[0]['enabled']) + self.assertTrue(registered_rules[0]["enabled"]) # works without ajax - portal.REQUEST.form['rule-id'] = 'foo' - portal.REQUEST.form['form.button.DisableRule'] = '1' - portal.restrictedTraverse('@@rules-controlpanel')() + portal.REQUEST.form["rule-id"] = "foo" + portal.REQUEST.form["form.button.DisableRule"] = "1" + portal.restrictedTraverse("@@rules-controlpanel")() registered_rules = controlpanel.registeredRules() - self.assertFalse(registered_rules[0]['enabled']) + self.assertFalse(registered_rules[0]["enabled"]) - portal.restrictedTraverse('@@contentrule-delete').delete_rule() + portal.restrictedTraverse("@@contentrule-delete").delete_rule() registered_rules = controlpanel.registeredRules() self.assertEqual(0, len(registered_rules)) @@ -147,16 +143,13 @@ def testChangeGloballyEnable(self): portal = self.portal self.addAuthToRequest() - portal.restrictedTraverse( - '@@contentrule-globally-enable').globally_enable() + portal.restrictedTraverse("@@contentrule-globally-enable").globally_enable() self.assertTrue(storage.active) - portal.restrictedTraverse( - '@@contentrule-globally-disable').globally_disable() + portal.restrictedTraverse("@@contentrule-globally-disable").globally_disable() self.assertFalse(storage.active) - portal.restrictedTraverse( - '@@contentrule-globally-enable').globally_enable() + portal.restrictedTraverse("@@contentrule-globally-enable").globally_enable() self.assertTrue(storage.active) # without ajax diff --git a/plone/app/contentrules/tests/test_setup.py b/plone/app/contentrules/tests/test_setup.py index 241f8cb..ca4db2f 100644 --- a/plone/app/contentrules/tests/test_setup.py +++ b/plone/app/contentrules/tests/test_setup.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from plone.app.contentrules.tests.base import ContentRulesTestCase from plone.contentrules.engine.interfaces import IRuleAssignable from plone.contentrules.rule.interfaces import IRuleEventType @@ -8,7 +7,6 @@ class TestProductInstall(ContentRulesTestCase): - def testRuleContainerInterfaces(self): self.assertTrue(IRuleAssignable.providedBy(self.folder)) self.assertTrue(IRuleAssignable.providedBy(self.portal)) diff --git a/plone/app/contentrules/tests/test_traversal.py b/plone/app/contentrules/tests/test_traversal.py index 26b1c49..ad16a73 100644 --- a/plone/app/contentrules/tests/test_traversal.py +++ b/plone/app/contentrules/tests/test_traversal.py @@ -1,8 +1,7 @@ -# -*- coding: utf-8 -*- -from Acquisition import aq_base -from Acquisition import aq_parent from .dummy import DummyAction from .dummy import DummyCondition +from Acquisition import aq_base +from Acquisition import aq_parent from plone.app.contentrules.rule import Rule from plone.app.contentrules.tests.base import ContentRulesTestCase from plone.contentrules.engine.interfaces import IRuleStorage @@ -10,57 +9,56 @@ class TestTraversal(ContentRulesTestCase): - def testTraverseToRule(self): r = Rule() storage = getUtility(IRuleStorage) - storage[u'r1'] = r - traversed = self.portal.restrictedTraverse('++rule++r1') + storage["r1"] = r + traversed = self.portal.restrictedTraverse("++rule++r1") self.assertTrue(aq_parent(traversed) is self.portal) self.assertTrue(aq_base(traversed) is r) def testTraverseToRuleCondition(self): r = Rule() e1 = DummyCondition() - e1.x = 'x' + e1.x = "x" e2 = DummyCondition() - e2.x = 'y' + e2.x = "y" r.conditions.append(e1) r.conditions.append(e2) storage = getUtility(IRuleStorage) - storage[u'r1'] = r + storage["r1"] = r - tr = self.portal.restrictedTraverse('++rule++r1') - te1 = tr.restrictedTraverse('++condition++0') - te2 = tr.restrictedTraverse('++condition++1') + tr = self.portal.restrictedTraverse("++rule++r1") + te1 = tr.restrictedTraverse("++condition++0") + te2 = tr.restrictedTraverse("++condition++1") self.assertTrue(aq_parent(te1) is tr) - self.assertEqual('x', te1.x) + self.assertEqual("x", te1.x) self.assertTrue(aq_parent(te2) is tr) - self.assertEqual('y', te2.x) + self.assertEqual("y", te2.x) def testTraverseToRuleAction(self): r = Rule() e1 = DummyAction() - e1.x = 'x' + e1.x = "x" e2 = DummyAction() - e2.x = 'y' + e2.x = "y" r.actions.append(e1) r.actions.append(e2) storage = getUtility(IRuleStorage) - storage[u'r1'] = r + storage["r1"] = r - tr = self.portal.restrictedTraverse('++rule++r1') - te1 = tr.restrictedTraverse('++action++0') - te2 = tr.restrictedTraverse('++action++1') + tr = self.portal.restrictedTraverse("++rule++r1") + te1 = tr.restrictedTraverse("++action++0") + te2 = tr.restrictedTraverse("++action++1") self.assertTrue(aq_parent(te1) is tr) - self.assertEqual('x', te1.x) + self.assertEqual("x", te1.x) self.assertTrue(aq_parent(te2) is tr) - self.assertEqual('y', te2.x) + self.assertEqual("y", te2.x) diff --git a/plone/app/contentrules/tests/utils.py b/plone/app/contentrules/tests/utils.py index 2917409..deac197 100644 --- a/plone/app/contentrules/tests/utils.py +++ b/plone/app/contentrules/tests/utils.py @@ -1,8 +1,7 @@ -# -*- coding: utf-8 -*- import doctest # Standard options for DocTests -optionflags = (doctest.ELLIPSIS | - doctest.NORMALIZE_WHITESPACE | - doctest.REPORT_ONLY_FIRST_FAILURE) +optionflags = ( + doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE | doctest.REPORT_ONLY_FIRST_FAILURE +) diff --git a/setup.cfg b/setup.cfg index 190e1a2..6b378d8 100644 --- a/setup.cfg +++ b/setup.cfg @@ -8,3 +8,10 @@ universal = 1 [zest.releaser] create-wheel = yes + +[isort] +# black compatible Plone isort rules: +profile = black +force_alphabetical_sort = True +force_single_line = True +lines_after_imports = 2 diff --git a/setup.py b/setup.py index eb8dbc9..50f3072 100644 --- a/setup.py +++ b/setup.py @@ -1,14 +1,14 @@ -# -*- coding: utf-8 -*- -from setuptools import setup, find_packages +from setuptools import find_packages +from setuptools import setup -version = '5.0.0a5.dev0' + +version = "5.0.0a5.dev0" setup( - name='plone.app.contentrules', + name="plone.app.contentrules", version=version, description="Plone integration for plone.contentrules", - long_description=(open("README.rst").read() + "\n\n" + - open("CHANGES.rst").read()), + long_description=(open("README.rst").read() + "\n\n" + open("CHANGES.rst").read()), classifiers=[ "Development Status :: 5 - Production/Stable", "Environment :: Web Environment", @@ -23,44 +23,43 @@ "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", ], - keywords='plone automatic content rules', - author='Plone Foundation', - author_email='plone-developers@lists.sourceforge.net', - url='https://pypi.org/project/plone.app.contentrules', - license='GPL version 2', + keywords="plone automatic content rules", + author="Plone Foundation", + author_email="plone-developers@lists.sourceforge.net", + url="https://pypi.org/project/plone.app.contentrules", + license="GPL version 2", packages=find_packages(), - namespace_packages=['plone', 'plone.app'], + namespace_packages=["plone", "plone.app"], include_package_data=True, zip_safe=False, - extras_require={'test': ['plone.app.testing', 'plone.app.contenttypes[test]']}, + extras_require={"test": ["plone.app.testing", "plone.app.contenttypes[test]"]}, install_requires=[ - 'setuptools', - 'six', - 'plone.contentrules', - 'plone.memoize', - 'plone.stringinterp', - 'plone.uuid', - 'plone.autoform', - 'plone.app.z3cform', - 'plone.app.vocabularies', - 'transaction', - 'zope.annotation', - 'zope.browser', - 'zope.component', - 'zope.container', - 'zope.event', - 'zope.i18nmessageid', - 'zope.interface', - 'zope.lifecycleevent', - 'zope.publisher >= 3.11.0', - 'zope.schema', - 'zope.site', - 'zope.traversing', - 'Acquisition', - 'Products.CMFCore', - 'Products.GenericSetup >= 2.0', - 'Products.statusmessages', - 'ZODB', - 'Zope', + "setuptools", + "plone.contentrules", + "plone.memoize", + "plone.stringinterp", + "plone.uuid", + "plone.autoform", + "plone.app.z3cform", + "plone.app.vocabularies", + "transaction", + "zope.annotation", + "zope.browser", + "zope.component", + "zope.container", + "zope.event", + "zope.i18nmessageid", + "zope.interface", + "zope.lifecycleevent", + "zope.publisher >= 3.11.0", + "zope.schema", + "zope.site", + "zope.traversing", + "Acquisition", + "Products.CMFCore", + "Products.GenericSetup >= 2.0", + "Products.statusmessages", + "ZODB", + "Zope", ], )