From cb1bf28c1631ad7daaae1ca919777af65ac32619 Mon Sep 17 00:00:00 2001 From: Gil Forcada Date: Fri, 5 Feb 2016 01:39:53 +0100 Subject: [PATCH] Cleanup Follow https://github.com/plone/jenkins.plone.org/blob/master/docs/source/run-qa-on-package.rst to clean up the code. --- CHANGES.rst | 2 + plone/__init__.py | 8 +- plone/app/__init__.py | 8 +- plone/app/discussion/browser/captcha.py | 5 +- plone/app/discussion/browser/comment.py | 37 ++-- plone/app/discussion/browser/comments.py | 102 ++++----- plone/app/discussion/browser/controlpanel.py | 86 ++++---- plone/app/discussion/browser/conversation.py | 10 +- plone/app/discussion/browser/migration.py | 83 ++++--- plone/app/discussion/browser/moderation.py | 29 +-- plone/app/discussion/browser/traversal.py | 5 +- plone/app/discussion/catalog.py | 10 +- plone/app/discussion/comment.py | 81 ++++--- plone/app/discussion/contentrules.py | 3 + plone/app/discussion/conversation.py | 10 +- plone/app/discussion/events.py | 1 + plone/app/discussion/interfaces.py | 203 +++++++++--------- plone/app/discussion/subscribers.py | 1 + plone/app/discussion/testing.py | 18 +- plone/app/discussion/tests/test_catalog.py | 56 ++--- plone/app/discussion/tests/test_comment.py | 79 +++---- .../discussion/tests/test_comments_viewlet.py | 109 +++++----- .../app/discussion/tests/test_contentrules.py | 56 ++--- .../app/discussion/tests/test_controlpanel.py | 4 +- .../app/discussion/tests/test_conversation.py | 36 ++-- plone/app/discussion/tests/test_events.py | 12 +- plone/app/discussion/tests/test_indexers.py | 21 +- .../discussion/tests/test_moderation_view.py | 8 +- .../discussion/tests/test_notifications.py | 68 +++--- plone/app/discussion/tests/test_robot.py | 1 + plone/app/discussion/tests/test_workflow.py | 11 +- plone/app/discussion/tool.py | 7 +- plone/app/discussion/upgrades.py | 1 + 33 files changed, 620 insertions(+), 551 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 5e47cd9..96cc31c 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -15,6 +15,8 @@ Fixes: Issue https://github.com/plone/Products.CMFPlone/issues/1332 [staeff, fredvd] +- Cleanup code according to our style guide. + [gforcada] 2.4.9 (2015-11-25) diff --git a/plone/__init__.py b/plone/__init__.py index f48ad10..68c04af 100644 --- a/plone/__init__.py +++ b/plone/__init__.py @@ -1,6 +1,2 @@ -# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages -try: - __import__('pkg_resources').declare_namespace(__name__) -except ImportError: - from pkgutil import extend_path - __path__ = extend_path(__path__, __name__) +# -*- coding: utf-8 -*- +__import__('pkg_resources').declare_namespace(__name__) diff --git a/plone/app/__init__.py b/plone/app/__init__.py index f48ad10..68c04af 100644 --- a/plone/app/__init__.py +++ b/plone/app/__init__.py @@ -1,6 +1,2 @@ -# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages -try: - __import__('pkg_resources').declare_namespace(__name__) -except ImportError: - from pkgutil import extend_path - __path__ = extend_path(__path__, __name__) +# -*- coding: utf-8 -*- +__import__('pkg_resources').declare_namespace(__name__) diff --git a/plone/app/discussion/browser/captcha.py b/plone/app/discussion/browser/captcha.py index 0d03da3..559cd89 100644 --- a/plone/app/discussion/browser/captcha.py +++ b/plone/app/discussion/browser/captcha.py @@ -12,7 +12,8 @@ from z3c.form import interfaces from z3c.form.field import Fields from zope import interface from zope.annotation import factory -from zope.component import adapts, queryUtility +from zope.component import adapts +from zope.component import queryUtility from zope.interface import Interface from zope.publisher.interfaces.browser import IDefaultBrowserLayer @@ -51,7 +52,7 @@ class CaptchaExtender(extensible.FormExtender): def update(self): if self.captcha != 'disabled' and self.isAnon: # Add a captcha field if captcha is enabled in the registry - self.add(ICaptcha, prefix="") + self.add(ICaptcha, prefix='') if self.captcha == 'captcha': from plone.formwidget.captcha import CaptchaFieldWidget self.form.fields['captcha'].widgetFactory = CaptchaFieldWidget diff --git a/plone/app/discussion/browser/comment.py b/plone/app/discussion/browser/comment.py index d5574e7..9f22d93 100644 --- a/plone/app/discussion/browser/comment.py +++ b/plone/app/discussion/browser/comment.py @@ -1,16 +1,17 @@ +# -*- coding: utf-8 -*- from AccessControl import getSecurityManager from Acquisition import aq_inner from Acquisition import aq_parent -from zope.component import getUtility -from Products.CMFCore.utils import getToolByName -from Products.Five.browser import BrowserView -from Products.statusmessages.interfaces import IStatusMessage from comments import CommentForm from plone.app.discussion import _ from plone.registry.interfaces import IRegistry from plone.z3cform.layout import wrap_form +from Products.CMFCore.utils import getToolByName +from Products.Five.browser import BrowserView +from Products.statusmessages.interfaces import IStatusMessage from z3c.form import button from zope.component import getMultiAdapter +from zope.component import getUtility class View(BrowserView): @@ -21,9 +22,9 @@ class View(BrowserView): has been posted. Redirect from the comment object URL - "/path/to/object/++conversation++default/123456789" to the content object + '/path/to/object/++conversation++default/123456789' to the content object where the comment has been posted appended by an HTML anchor that points to - the comment "/path/to/object#comment-123456789". + the comment '/path/to/object#comment-123456789'. Context is the comment object. The parent of the comment object is the conversation. The parent of the conversation is the content object where @@ -46,15 +47,15 @@ class View(BrowserView): will redirect right to the binary object, bypassing comments. """ if obj.portal_type in view_action_types: - url = "%s/view" % url + url = '{0}/view'.format(url) - self.request.response.redirect('%s#%s' % (url, context.id)) + self.request.response.redirect('{0}#{1}'.format(url, context.id)) class EditCommentForm(CommentForm): """Form to edit an existing comment.""" ignoreContext = True - id = "edit-comment-form" + id = 'edit-comment-form' label = _(u'edit_comment_form_title', default=u'Edit comment') def updateWidgets(self): @@ -71,8 +72,8 @@ class EditCommentForm(CommentForm): target = portal_state.portal_url() self.request.response.redirect(target) - @button.buttonAndHandler(_(u"edit_comment_form_button", - default=u"Edit comment"), name='comment') + @button.buttonAndHandler(_(u'edit_comment_form_button', + default=u'Edit comment'), name='comment') def handleComment(self, action): # Validate form @@ -93,19 +94,19 @@ class EditCommentForm(CommentForm): # Redirect to comment IStatusMessage(self.request).add(_(u'comment_edit_notification', - default="Comment was edited"), + default='Comment was edited'), type='info') return self._redirect( - target=self.action.replace("@@edit-comment", "@@view")) + target=self.action.replace('@@edit-comment', '@@view')) @button.buttonAndHandler(_(u'cancel_form_button', default=u'Cancel'), name='cancel') def handle_cancel(self, action): - IStatusMessage(self.request).add( - _(u'comment_edit_cancel_notification', - default=u'Edit comment cancelled'), - type='info') - return self._redirect(target=self.context.absolute_url()) + IStatusMessage(self.request).add( + _(u'comment_edit_cancel_notification', + default=u'Edit comment cancelled'), + type='info') + return self._redirect(target=self.context.absolute_url()) EditComment = wrap_form(EditCommentForm) diff --git a/plone/app/discussion/browser/comments.py b/plone/app/discussion/browser/comments.py index 77214d1..a1c80af 100644 --- a/plone/app/discussion/browser/comments.py +++ b/plone/app/discussion/browser/comments.py @@ -2,11 +2,8 @@ from AccessControl import getSecurityManager from AccessControl import Unauthorized from Acquisition import aq_inner -from DateTime import DateTime -from Products.CMFCore.utils import getToolByName -from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile -from Products.statusmessages.interfaces import IStatusMessage from datetime import datetime +from DateTime import DateTime from plone.app.discussion import _ from plone.app.discussion.browser.validator import CaptchaValidator from plone.app.discussion.interfaces import ICaptcha @@ -19,6 +16,9 @@ from plone.registry.interfaces import IRegistry from plone.z3cform import z2 from plone.z3cform.fieldsets import extensible from plone.z3cform.interfaces import IWrappedForm +from Products.CMFCore.utils import getToolByName +from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile +from Products.statusmessages.interfaces import IStatusMessage from urllib import quote as url_quote from z3c.form import button from z3c.form import field @@ -34,32 +34,36 @@ from zope.interface import alsoProvides COMMENT_DESCRIPTION_PLAIN_TEXT = _( - u"comment_description_plain_text", - default=u"You can add a comment by filling out the form below. " + - u"Plain text formatting.") + u'comment_description_plain_text', + default=u'You can add a comment by filling out the form below. ' + u'Plain text formatting.' +) COMMENT_DESCRIPTION_MARKDOWN = _( - u"comment_description_markdown", - default=u"You can add a comment by filling out the form below. " + - u"Plain text formatting. You can use the Markdown syntax for " + - u"links and images.") + u'comment_description_markdown', + default=u'You can add a comment by filling out the form below. ' + u'Plain text formatting. You can use the Markdown syntax for ' + u'links and images.' +) COMMENT_DESCRIPTION_INTELLIGENT_TEXT = _( - u"comment_description_intelligent_text", - default=u"You can add a comment by filling out the form below. " + - u"Plain text formatting. Web and email addresses are " + - u"transformed into clickable links.") + u'comment_description_intelligent_text', + default=u'You can add a comment by filling out the form below. ' + u'Plain text formatting. Web and email addresses are ' + u'transformed into clickable links.' +) COMMENT_DESCRIPTION_MODERATION_ENABLED = _( - u"comment_description_moderation_enabled", - default=u"Comments are moderated.") + u'comment_description_moderation_enabled', + default=u'Comments are moderated.' +) class CommentForm(extensible.ExtensibleForm, form.Form): ignoreContext = True # don't use context to get widget data id = None - label = _(u"Add a comment") + label = _(u'Add a comment') fields = field.Fields(IComment).omit('portal_type', '__parent__', '__name__', @@ -81,13 +85,13 @@ class CommentForm(extensible.ExtensibleForm, form.Form): # Widgets self.widgets['in_reply_to'].mode = interfaces.HIDDEN_MODE - self.widgets['text'].addClass("autoresize") - self.widgets['user_notification'].label = _(u"") + self.widgets['text'].addClass('autoresize') + self.widgets['user_notification'].label = _(u'') # Rename the id of the text widgets because there can be css-id # clashes with the text field of documents when using and overlay # with TinyMCE. - self.widgets['text'].id = "form-widgets-comment-text" + self.widgets['text'].id = 'form-widgets-comment-text' # Anonymous / Logged-in mtool = getToolByName(self.context, 'portal_membership') @@ -99,7 +103,7 @@ class CommentForm(extensible.ExtensibleForm, form.Form): if anon: if settings.anonymous_email_enabled: # according to IDiscussionSettings.anonymous_email_enabled: - # "If selected, anonymous user will have to give their email." + # 'If selected, anonymous user will have to give their email.' self.widgets['author_email'].field.required = True self.widgets['author_email'].required = True else: @@ -121,11 +125,11 @@ class CommentForm(extensible.ExtensibleForm, form.Form): def updateActions(self): super(CommentForm, self).updateActions() - self.actions['cancel'].addClass("standalone") - self.actions['cancel'].addClass("hide") - self.actions['comment'].addClass("context") + self.actions['cancel'].addClass('standalone') + self.actions['cancel'].addClass('hide') + self.actions['comment'].addClass('context') - @button.buttonAndHandler(_(u"add_comment_button", default=u"Comment"), + @button.buttonAndHandler(_(u'add_comment_button', default=u'Comment'), name='comment') def handleComment(self, action): context = aq_inner(self.context) @@ -134,8 +138,9 @@ class CommentForm(extensible.ExtensibleForm, form.Form): if not self.__parent__.restrictedTraverse( '@@conversation_view' ).enabled(): - raise Unauthorized("Discussion is not enabled for this content " - "object.") + raise Unauthorized( + 'Discussion is not enabled for this content object.' + ) # Validation form data, errors = self.extractData() @@ -151,7 +156,7 @@ class CommentForm(extensible.ExtensibleForm, form.Form): anon = portal_membership.isAnonymousUser() if captcha_enabled and anonymous_comments and anon: if 'captcha' not in data: - data['captcha'] = u"" + data['captcha'] = u'' captcha = CaptchaValidator(self.context, self.request, None, @@ -160,7 +165,7 @@ class CommentForm(extensible.ExtensibleForm, form.Form): captcha.validate(data['captcha']) # some attributes are not always set - author_name = u"" + author_name = u'' # Create comment comment = createObject('plone.Comment') @@ -207,14 +212,14 @@ class CommentForm(extensible.ExtensibleForm, form.Form): if email and isinstance(email, str): email = unicode(email, 'utf-8') comment.changeOwnership(user, recursive=False) - comment.manage_setLocalRoles(memberid, ["Owner"]) + comment.manage_setLocalRoles(memberid, ['Owner']) comment.creator = memberid comment.author_username = memberid comment.author_name = fullname # XXX: according to IComment interface author_email must not be # set for logged in users, cite: - # "for anonymous comments only, set to None for logged in comments" + # 'for anonymous comments only, set to None for logged in comments' comment.author_email = email # /XXX @@ -223,8 +228,8 @@ class CommentForm(extensible.ExtensibleForm, form.Form): else: # pragma: no cover raise Unauthorized( - u"Anonymous user tries to post a comment, but anonymous " - u"commenting is disabled. Or user does not have the " + u'Anonymous user tries to post a comment, but anonymous ' + u'commenting is disabled. Or user does not have the ' u"'reply to item' permission." ) @@ -255,14 +260,14 @@ class CommentForm(extensible.ExtensibleForm, form.Form): if comment_review_state == 'pending' and not can_review: # Show info message when comment moderation is enabled IStatusMessage(self.context.REQUEST).addStatusMessage( - _("Your comment awaits moderator approval."), - type="info") + _('Your comment awaits moderator approval.'), + type='info') self.request.response.redirect(self.action) else: # Redirect to comment (inside a content object page) self.request.response.redirect(self.action + '#' + str(comment_id)) - @button.buttonAndHandler(_(u"Cancel")) + @button.buttonAndHandler(_(u'Cancel')) def handleCancel(self, action): # This method should never be called, it's only there to show # a cancel button that is handled by a jQuery method. @@ -278,9 +283,9 @@ class CommentsViewlet(ViewletBase): super(CommentsViewlet, self).update() discussion_allowed = self.is_discussion_allowed() anonymous_allowed_or_can_reply = ( - self.is_anonymous() - and self.anonymous_discussion_allowed() - or self.can_reply() + self.is_anonymous() and + self.anonymous_discussion_allowed() or + self.can_reply() ) if discussion_allowed and anonymous_allowed_or_can_reply: z2.switch_on(self, request_layer=IFormLayer) @@ -356,10 +361,10 @@ class CommentsViewlet(ViewletBase): settings = registry.forInterface(IDiscussionSettings, check=False) # text transform setting - if settings.text_transform == "text/x-web-intelligent": + if settings.text_transform == 'text/x-web-intelligent': message = translate(Message(COMMENT_DESCRIPTION_INTELLIGENT_TEXT), context=self.request) - elif settings.text_transform == "text/x-web-markdown": + elif settings.text_transform == 'text/x-web-markdown': message = translate(Message(COMMENT_DESCRIPTION_MARKDOWN), context=self.request) else: @@ -367,7 +372,7 @@ class CommentsViewlet(ViewletBase): context=self.request) # comment workflow - wftool = getToolByName(context, "portal_workflow", None) + wftool = getToolByName(context, 'portal_workflow', None) workflow_chain = wftool.getChainForPortalType('Discussion Item') if workflow_chain: comment_workflow = workflow_chain[0] @@ -375,7 +380,7 @@ class CommentsViewlet(ViewletBase): # check if the current workflow implements a pending state. If this # is true comments are moderated if 'pending' in comment_workflow.states: - message = message + " " + \ + message = message + ' ' + \ translate(Message(COMMENT_DESCRIPTION_MODERATION_ENABLED), context=self.request) @@ -445,7 +450,7 @@ class CommentsViewlet(ViewletBase): if username is None: return None else: - return "%s/author/%s" % (self.context.portal_url(), username) + return '{0}/author/{1}'.format(self.context.portal_url(), username) def get_commenter_portrait(self, username=None): @@ -491,9 +496,10 @@ class CommentsViewlet(ViewletBase): return portal_membership.isAnonymousUser() def login_action(self): - return '%s/login_form?came_from=%s' % \ - (self.navigation_root_url, - url_quote(self.request.get('URL', '')),) + return '{0}/login_form?came_from={1}'.format( + self.navigation_root_url, + url_quote(self.request.get('URL', '')), + ) def format_time(self, time): # We have to transform Python datetime into Zope DateTime diff --git a/plone/app/discussion/browser/controlpanel.py b/plone/app/discussion/browser/controlpanel.py index 5317569..7bcc807 100644 --- a/plone/app/discussion/browser/controlpanel.py +++ b/plone/app/discussion/browser/controlpanel.py @@ -1,9 +1,4 @@ # -*- coding: utf-8 -*- -from Products.CMFCore.interfaces._content import IDiscussionResponse -from Products.CMFCore.utils import getToolByName -from Products.CMFPlone.interfaces.controlpanel import IMailSchema -from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile -from Products.statusmessages.interfaces import IStatusMessage from plone.app.controlpanel.interfaces import IConfigurationChangedEvent from plone.app.discussion.interfaces import _ from plone.app.discussion.interfaces import IDiscussionSettings @@ -11,6 +6,11 @@ from plone.app.discussion.upgrades import update_registry from plone.app.registry.browser import controlpanel from plone.registry.interfaces import IRecordModifiedEvent from plone.registry.interfaces import IRegistry +from Products.CMFCore.interfaces._content import IDiscussionResponse +from Products.CMFCore.utils import getToolByName +from Products.CMFPlone.interfaces.controlpanel import IMailSchema +from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile +from Products.statusmessages.interfaces import IStatusMessage from z3c.form import button from z3c.form.browser.checkbox import SingleCheckBoxFieldWidget from zope.component import getMultiAdapter @@ -23,19 +23,19 @@ class DiscussionSettingsEditForm(controlpanel.RegistryEditForm): """Discussion settings form. """ schema = IDiscussionSettings - id = "DiscussionSettingsEditForm" - label = _(u"Discussion settings") + id = 'DiscussionSettingsEditForm' + label = _(u'Discussion settings') description = _( - u"help_discussion_settings_editform", - default=u"Some discussion related settings are not " - u"located in the Discussion Control Panel.\n" - u"To enable comments for a specific content type, " - u"go to the Types Control Panel of this type and " - u"choose \"Allow comments\".\n" - u"To enable the moderation workflow for comments, " - u"go to the Types Control Panel, choose " - u"\"Comment\" and set workflow to " - u"\"Comment Review Workflow\"." + u'help_discussion_settings_editform', + default=u'Some discussion related settings are not ' + u'located in the Discussion Control Panel.\n' + u'To enable comments for a specific content type, ' + u'go to the Types Control Panel of this type and ' + u'choose "Allow comments".\n' + u'To enable the moderation workflow for comments, ' + u'go to the Types Control Panel, choose ' + u'"Comment" and set workflow to ' + u'"Comment Review Workflow".' ) def updateFields(self): @@ -65,13 +65,15 @@ class DiscussionSettingsEditForm(controlpanel.RegistryEditForm): # provide auto-upgrade update_registry(self.context) super(DiscussionSettingsEditForm, self).updateWidgets() - self.widgets['globally_enabled'].label = _(u"Enable Comments") - self.widgets['anonymous_comments'].label = _(u"Anonymous Comments") - self.widgets['show_commenter_image'].label = _(u"Commenter Image") - self.widgets['moderator_notification_enabled'].label = \ - _(u"Moderator Email Notification") - self.widgets['user_notification_enabled'].label = \ - _(u"User Email Notification") + self.widgets['globally_enabled'].label = _(u'Enable Comments') + self.widgets['anonymous_comments'].label = _(u'Anonymous Comments') + self.widgets['show_commenter_image'].label = _(u'Commenter Image') + self.widgets['moderator_notification_enabled'].label = _( + u'Moderator Email Notification' + ) + self.widgets['user_notification_enabled'].label = _( + u'User Email Notification' + ) @button.buttonAndHandler(_('Save'), name=None) def handleSave(self, action): @@ -80,16 +82,20 @@ class DiscussionSettingsEditForm(controlpanel.RegistryEditForm): self.status = self.formErrorsMessage return self.applyChanges(data) - IStatusMessage(self.request).addStatusMessage(_(u"Changes saved"), - "info") - self.context.REQUEST.RESPONSE.redirect("@@discussion-controlpanel") + IStatusMessage(self.request).addStatusMessage(_(u'Changes saved'), + 'info') + self.context.REQUEST.RESPONSE.redirect('@@discussion-controlpanel') @button.buttonAndHandler(_('Cancel'), name='cancel') def handleCancel(self, action): - IStatusMessage(self.request).addStatusMessage(_(u"Edit cancelled"), - "info") - self.request.response.redirect("%s/%s" % (self.context.absolute_url(), - self.control_panel_view)) + IStatusMessage(self.request).addStatusMessage(_(u'Edit cancelled'), + 'info') + self.request.response.redirect( + '{0}/{1}'.format( + self.context.absolute_url(), + self.control_panel_view + ) + ) class DiscussionSettingsControlPanel(controlpanel.ControlPanelFormWrapper): @@ -104,38 +110,38 @@ class DiscussionSettingsControlPanel(controlpanel.ControlPanelFormWrapper): """ registry = queryUtility(IRegistry) settings = registry.forInterface(IDiscussionSettings, check=False) - wftool = getToolByName(self.context, "portal_workflow", None) + wftool = getToolByName(self.context, 'portal_workflow', None) workflow_chain = wftool.getChainForPortalType('Discussion Item') output = [] # Globally enabled if settings.globally_enabled: - output.append("globally_enabled") + output.append('globally_enabled') # Comment moderation one_state_worklow_disabled = 'one_state_workflow' not in workflow_chain comment_review_workflow_disabled = \ 'comment_review_workflow' not in workflow_chain if one_state_worklow_disabled and comment_review_workflow_disabled: - output.append("moderation_custom") + output.append('moderation_custom') elif settings.moderation_enabled: - output.append("moderation_enabled") + output.append('moderation_enabled') if settings.edit_comment_enabled: - output.append("edit_comment_enabled") + output.append('edit_comment_enabled') if settings.delete_own_comment_enabled: - output.append("delte_own_comment_enabled") + output.append('delete_own_comment_enabled') # Anonymous comments if settings.anonymous_comments: - output.append("anonymous_comments") + output.append('anonymous_comments') # Invalid mail setting ctrlOverview = getMultiAdapter((self.context, self.request), name='overview-controlpanel') if ctrlOverview.mailhost_warning(): - output.append("invalid_mail_setup") + output.append('invalid_mail_setup') # Workflow wftool = getToolByName(self.context, 'portal_workflow', None) @@ -161,7 +167,7 @@ class DiscussionSettingsControlPanel(controlpanel.ControlPanelFormWrapper): def custom_comment_workflow_warning(self): """Returns a warning string if a custom comment workflow is enabled. """ - wftool = getToolByName(self.context, "portal_workflow", None) + wftool = getToolByName(self.context, 'portal_workflow', None) workflow_chain = wftool.getChainForPortalType('Discussion Item') one_state_workflow_enabled = 'one_state_workflow' in workflow_chain comment_review_workflow_enabled = \ diff --git a/plone/app/discussion/browser/conversation.py b/plone/app/discussion/browser/conversation.py index e4bcecb..1e3f9b2 100644 --- a/plone/app/discussion/browser/conversation.py +++ b/plone/app/discussion/browser/conversation.py @@ -1,18 +1,20 @@ +# -*- coding: utf-8 -*- from Acquisition import aq_base from Acquisition import aq_chain from Acquisition import aq_inner +from plone.app.discussion.interfaces import IDiscussionSettings +from plone.registry.interfaces import IRegistry from Products.CMFCore.interfaces import IFolderish from Products.CMFCore.utils import getToolByName from Products.CMFPlone.interfaces import INonStructuralFolder from Products.CMFPlone.interfaces import IPloneSiteRoot -from plone.app.discussion.interfaces import IDiscussionSettings -from plone.registry.interfaces import IRegistry from zope.component import queryUtility + try: from plone.dexterity.interfaces import IDexterityContent DEXTERITY_INSTALLED = True -except: +except ImportError: DEXTERITY_INSTALLED = False @@ -130,7 +132,7 @@ class ConversationView(object): return False # Check if discussion is allowed on the content object - if hasattr(context, "allow_discussion"): + if hasattr(context, 'allow_discussion'): if context.allow_discussion is not None: return context.allow_discussion diff --git a/plone/app/discussion/browser/migration.py b/plone/app/discussion/browser/migration.py index 2e43f4d..1d8190b 100644 --- a/plone/app/discussion/browser/migration.py +++ b/plone/app/discussion/browser/migration.py @@ -1,12 +1,15 @@ +# -*- coding: utf-8 -*- from Acquisition import aq_inner from Acquisition import aq_parent +from datetime import datetime from DateTime import DateTime +from plone.app.discussion.comment import CommentFactory +from plone.app.discussion.interfaces import IComment +from plone.app.discussion.interfaces import IConversation +from plone.app.discussion.interfaces import IReplies from Products.CMFCore.interfaces._content import IDiscussionResponse from Products.CMFCore.utils import getToolByName from Products.Five.browser import BrowserView -from datetime import datetime -from plone.app.discussion.comment import CommentFactory -from plone.app.discussion.interfaces import IConversation, IReplies, IComment from types import TupleType import transaction @@ -35,11 +38,11 @@ class View(BrowserView): self.total_comments_migrated = 0 self.total_comments_deleted = 0 - dry_run = "dry_run" in self.request + dry_run = 'dry_run' in self.request # This is for testing only. # Do not use transactions during a test. - test = "test" in self.request + test = 'test' in self.request if not test: transaction.begin() # pragma: no cover @@ -71,10 +74,10 @@ class View(BrowserView): for reply in replies: # log - indent = " " + indent = ' ' for i in range(depth): - indent += " " - log("%smigrate_reply: '%s'." % (indent, reply.title)) + indent += ' ' + log('{0}migrate_reply: "{1}".'.format(indent, reply.title)) should_migrate = True if filter_callback and not filter_callback(reply): @@ -172,7 +175,7 @@ class View(BrowserView): talkback.deleteReply(reply.id) obj = aq_parent(talkback) obj.talkback = None - log("%sremove %s" % (indent, reply.id)) + log('{0}remove {1}'.format(indent, reply.id)) self.total_comments_deleted += 1 # Return True when all comments on a certain level have been @@ -182,7 +185,7 @@ class View(BrowserView): # Find content brains = catalog.searchResults( object_provides='Products.CMFCore.interfaces._content.IContentish') - log("Found %s content objects." % len(brains)) + log('Found {0} content objects.'.format(len(brains))) count_discussion_items = len( catalog.searchResults(Type='Discussion Item') @@ -196,12 +199,20 @@ class View(BrowserView): ) ) - log("Found %s Discussion Item objects." % count_discussion_items) - log("Found %s old discussion items." % count_comments_old) - log("Found %s plone.app.discussion comments." % count_comments_pad) + log( + 'Found {0} Discussion Item objects.'.format( + count_discussion_items + ) + ) + log('Found {0} old discussion items.'.format(count_comments_old)) + log( + 'Found {0} plone.app.discussion comments.'.format( + count_comments_pad + ) + ) - log("\n") - log("Start comment migration.") + log('\n') + log('Start comment migration.') # This loop is necessary to get all contentish objects, but not # the Discussion Items. This wouldn't be necessary if the @@ -219,46 +230,54 @@ class View(BrowserView): replies = talkback.getReplies() if replies: conversation = IConversation(obj) - log("\n") - log("Migrate '%s' (%s)" % (obj.Title(), - obj.absolute_url(relative=1))) + log('\n') + log( + 'Migrate "{0}" ({1})'.format( + obj.Title(), + obj.absolute_url(relative=1) + ) + ) migrate_replies(context, 0, replies) obj = aq_parent(talkback) obj.talkback = None if self.total_comments_deleted != self.total_comments_migrated: log( - "Something went wrong during migration. The number of " + - "migrated comments (%s) differs from the number of deleted " + - "comments (%s)." % ( + 'Something went wrong during migration. The number of ' + 'migrated comments ({0}) differs from the number of deleted ' + 'comments ({1}).'.format( self.total_comments_migrated, self.total_comments_deleted ) ) if not test: # pragma: no cover transaction.abort() # pragma: no cover - log("Abort transaction") # pragma: no cover + log('Abort transaction') # pragma: no cover - log("\n") - log("Comment migration finished.") - log("\n") + log('\n') + log('Comment migration finished.') + log('\n') - log("%s of %s comments migrated." - % (self.total_comments_migrated, count_comments_old)) + log( + '{0} of {1} comments migrated.'.format( + self.total_comments_migrated, + count_comments_old + ) + ) if self.total_comments_migrated != count_comments_old: log( - "%s comments could not be migrated." % ( + '{0} comments could not be migrated.'.format( count_comments_old - self.total_comments_migrated ) ) # pragma: no cover - log("Please make sure your " + - "portal catalog is up-to-date.") # pragma: no cover + log('Please make sure your ' + + 'portal catalog is up-to-date.') # pragma: no cover if dry_run and not test: transaction.abort() # pragma: no cover - log("Dry run") # pragma: no cover - log("Abort transaction") # pragma: no cover + log('Dry run') # pragma: no cover + log('Abort transaction') # pragma: no cover if not test: transaction.commit() # pragma: no cover return '\n'.join(out) diff --git a/plone/app/discussion/browser/moderation.py b/plone/app/discussion/browser/moderation.py index 3648924..722386d 100644 --- a/plone/app/discussion/browser/moderation.py +++ b/plone/app/discussion/browser/moderation.py @@ -1,15 +1,15 @@ # -*- coding: utf-8 -*- -from AccessControl import Unauthorized from AccessControl import getSecurityManager +from AccessControl import Unauthorized from Acquisition import aq_inner from Acquisition import aq_parent +from plone.app.discussion.interfaces import _ +from plone.app.discussion.interfaces import IComment +from plone.app.discussion.interfaces import IReplies from Products.CMFCore.utils import getToolByName from Products.Five.browser import BrowserView from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile from Products.statusmessages.interfaces import IStatusMessage -from plone.app.discussion.interfaces import _ -from plone.app.discussion.interfaces import IComment -from plone.app.discussion.interfaces import IReplies class View(BrowserView): @@ -101,8 +101,8 @@ class DeleteComment(BrowserView): del conversation[comment.id] content_object.reindexObject() IStatusMessage(self.context.REQUEST).addStatusMessage( - _("Comment deleted."), - type="info") + _('Comment deleted.'), + type='info') came_from = self.context.REQUEST.HTTP_REFERER # if the referrer already has a came_from in it, don't redirect back if len(came_from) == 0 or 'came_from=' in came_from: @@ -133,14 +133,17 @@ class DeleteOwnComment(DeleteComment): sm = getSecurityManager() comment = comment or aq_inner(self.context) userid = sm.getUser().getId() - return (sm.checkPermission('Delete own comments', - comment) - and 'Owner' in comment.get_local_roles_for_userid(userid)) + return ( + sm.checkPermission('Delete own comments', comment) and + 'Owner' in comment.get_local_roles_for_userid(userid) + ) def can_delete(self, comment=None): comment = comment or self.context - return (len(IReplies(aq_inner(comment))) == 0 - and self.could_delete(comment=comment)) + return ( + len(IReplies(aq_inner(comment))) == 0 and + self.could_delete(comment=comment) + ) def __call__(self): if self.can_delete(): @@ -179,8 +182,8 @@ class PublishComment(BrowserView): comment.reindexObject() content_object.reindexObject(idxs=['total_comments']) IStatusMessage(self.context.REQUEST).addStatusMessage( - _("Comment approved."), - type="info") + _('Comment approved.'), + type='info') came_from = self.context.REQUEST.HTTP_REFERER # if the referrer already has a came_from in it, don't redirect back if len(came_from) == 0 or 'came_from=' in came_from: diff --git a/plone/app/discussion/browser/traversal.py b/plone/app/discussion/browser/traversal.py index 63dcc51..964c4db 100644 --- a/plone/app/discussion/browser/traversal.py +++ b/plone/app/discussion/browser/traversal.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- """Implement the ++comments++ traversal namespace. This should return the IDiscussion container for the context, from which traversal will continue into an actual comment object. @@ -29,8 +30,8 @@ class ConversationNamespace(object): def traverse(self, name, ignore): - if name == "default": - name = u"" + if name == 'default': + name = u'' conversation = queryAdapter(self.context, IConversation, name=name) if conversation is None: diff --git a/plone/app/discussion/catalog.py b/plone/app/discussion/catalog.py index 3a9a4d2..ede2674 100644 --- a/plone/app/discussion/catalog.py +++ b/plone/app/discussion/catalog.py @@ -1,15 +1,17 @@ +# -*- coding: utf-8 -*- """Catalog indexers, using plone.indexer. These will populate standard catalog indexes with values based on the IComment interface. Also provide event handlers to actually catalog the comments. """ from DateTime import DateTime +from plone.app.discussion.interfaces import IComment +from plone.app.discussion.interfaces import IConversation +from plone.indexer import indexer +from plone.uuid.interfaces import IUUID from Products.CMFCore.interfaces import IContentish from Products.CMFPlone.utils import safe_unicode from Products.ZCatalog.interfaces import IZCatalog -from plone.app.discussion.interfaces import IConversation, IComment -from plone.indexer import indexer -from plone.uuid.interfaces import IUUID from string import join @@ -78,7 +80,7 @@ def description(object): text = join(object.getText( targetMimetype='text/plain').split()[:MAX_DESCRIPTION]) if len(object.getText().split()) > 25: - text += " [...]" + text += ' [...]' return text diff --git a/plone/app/discussion/comment.py b/plone/app/discussion/comment.py index 2bc8354..507014a 100644 --- a/plone/app/discussion/comment.py +++ b/plone/app/discussion/comment.py @@ -3,16 +3,9 @@ """ from AccessControl import ClassSecurityInfo from AccessControl.SecurityManagement import getSecurityManager -from Acquisition import Implicit from Acquisition import aq_base from Acquisition import aq_parent -from Products.CMFCore import permissions -from Products.CMFCore.CMFCatalogAware import CatalogAware -from Products.CMFCore.CMFCatalogAware import WorkflowAware -from Products.CMFCore.DynamicType import DynamicType -from Products.CMFCore.utils import getToolByName -from Products.CMFPlone.interfaces.controlpanel import IMailSchema -from Products.CMFPlone.utils import safe_unicode +from Acquisition import Implicit from datetime import datetime from OFS.owner import Owned from OFS.role import RoleManager @@ -27,6 +20,13 @@ from plone.app.discussion.interfaces import IComment from plone.app.discussion.interfaces import IConversation from plone.app.discussion.interfaces import IDiscussionSettings from plone.registry.interfaces import IRegistry +from Products.CMFCore import permissions +from Products.CMFCore.CMFCatalogAware import CatalogAware +from Products.CMFCore.CMFCatalogAware import WorkflowAware +from Products.CMFCore.DynamicType import DynamicType +from Products.CMFCore.utils import getToolByName +from Products.CMFPlone.interfaces.controlpanel import IMailSchema +from Products.CMFPlone.utils import safe_unicode from smtplib import SMTPException from zope.annotation.interfaces import IAnnotatable from zope.component import getUtility @@ -41,28 +41,28 @@ import logging COMMENT_TITLE = _( - u"comment_title", - default=u"${author_name} on ${content}") + u'comment_title', + default=u'${author_name} on ${content}') MAIL_NOTIFICATION_MESSAGE = _( - u"mail_notification_message", - default=u"A comment on '${title}' " - u"has been posted here: ${link}\n\n" - u"---\n" - u"${text}\n" - u"---\n") + u'mail_notification_message', + default=u'A comment on "${title}" ' + u'has been posted here: ${link}\n\n' + u'---\n' + u'${text}\n' + u'---\n') MAIL_NOTIFICATION_MESSAGE_MODERATOR = _( - u"mail_notification_message_moderator", - default=u"A comment on '${title}' " - u"has been posted here: ${link}\n\n" - u"---\n" - u"${text}\n" - u"---\n\n" - u"Approve comment:\n${link_approve}\n\n" - u"Delete comment:\n${link_delete}\n") + u'mail_notification_message_moderator', + default=u'A comment on "${title}" ' + u'has been posted here: ${link}\n\n' + u'---\n' + u'${text}\n' + u'---\n\n' + u'Approve comment:\n${link_approve}\n\n' + u'Delete comment:\n${link_delete}\n') -logger = logging.getLogger("plone.app.discussion") +logger = logging.getLogger('plone.app.discussion') class Comment(CatalogAware, WorkflowAware, DynamicType, Traversable, @@ -86,10 +86,10 @@ class Comment(CatalogAware, WorkflowAware, DynamicType, Traversable, comment_id = None # long in_reply_to = None # long - title = u"" + title = u'' mime_type = None - text = u"" + text = u'' creator = None creation_date = None @@ -157,14 +157,12 @@ class Comment(CatalogAware, WorkflowAware, DynamicType, Traversable, if transform: return transform.getData() else: - logger = logging.getLogger("plone.app.discussion") - logger.error(_( - u"Transform '%s' => '%s' not available." % ( - sourceMimetype, - targetMimetype - ) + - u"Failed to transform comment '%s'." % self.absolute_url() - )) + logger = logging.getLogger('plone.app.discussion') + msg = u'Transform "{0}" => "{1}" not available. Failed to ' \ + u'transform comment "{2}".' + logger.error( + msg.format(sourceMimetype, targetMimetype, self.absolute_url()) + ) return text def Title(self): @@ -177,8 +175,8 @@ class Comment(CatalogAware, WorkflowAware, DynamicType, Traversable, if not self.author_name: author_name = translate( Message(_( - u"label_anonymous", - default=u"Anonymous" + u'label_anonymous', + default=u'Anonymous' )) ) else: @@ -198,8 +196,7 @@ class Comment(CatalogAware, WorkflowAware, DynamicType, Traversable, """ return self.creator or self.author_name - security.declareProtected(permissions.View, 'Type') - + @security.protected(permissions.View) def Type(self): """The Discussion Item content type. """ @@ -292,7 +289,7 @@ def notify_content_object_moved(obj, event): ) brains = catalog.searchResults(dict( path={'query': old_path}, - portal_type="Discussion Item" + portal_type='Discussion Item' )) for brain in brains: catalog.uncatalog_object(brain.getPath()) @@ -346,7 +343,7 @@ def notify_user(obj, event): if not emails: return - subject = translate(_(u"A comment has been posted."), + subject = translate(_(u'A comment has been posted.'), context=obj.REQUEST) message = translate( Message( @@ -412,7 +409,7 @@ def notify_moderator(obj, event): content_object = aq_parent(conversation) # Compose email - subject = translate(_(u"A comment has been posted."), context=obj.REQUEST) + subject = translate(_(u'A comment has been posted.'), context=obj.REQUEST) link_approve = obj.absolute_url() + '/@@moderate-publish-comment' link_delete = obj.absolute_url() + '/@@moderate-delete-comment' message = translate( diff --git a/plone/app/discussion/contentrules.py b/plone/app/discussion/contentrules.py index 81b832b..390178b 100644 --- a/plone/app/discussion/contentrules.py +++ b/plone/app/discussion/contentrules.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- """ Content rules handlers """ from plone.app.discussion import _ @@ -9,6 +10,7 @@ except ImportError: class BaseSubstitution(object): """ Fallback class if plone.stringinterp is not available """ + def __init__(self, context, **kwargs): self.context = context @@ -27,6 +29,7 @@ def execute_comment(event): class CommentSubstitution(BaseSubstitution): """ Comment string substitution """ + def __init__(self, context, **kwargs): super(CommentSubstitution, self).__init__(context, **kwargs) diff --git a/plone/app/discussion/conversation.py b/plone/app/discussion/conversation.py index 0e074a7..9c03c6d 100644 --- a/plone/app/discussion/conversation.py +++ b/plone/app/discussion/conversation.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- """The conversation and replies adapters The conversation is responsible for storing all comments. It provides a @@ -20,12 +21,12 @@ from BTrees.OIBTree import OIBTree from OFS.event import ObjectWillBeAddedEvent from OFS.event import ObjectWillBeRemovedEvent from OFS.Traversable import Traversable -from Products.CMFPlone.interfaces import IHideFromBreadcrumbs -from Products.CMFPlone import DISCUSSION_ANNOTATION_KEY as ANNOTATION_KEY from persistent import Persistent from plone.app.discussion.comment import Comment from plone.app.discussion.interfaces import IConversation from plone.app.discussion.interfaces import IReplies +from Products.CMFPlone import DISCUSSION_ANNOTATION_KEY as ANNOTATION_KEY +from Products.CMFPlone.interfaces import IHideFromBreadcrumbs from zope.annotation.interfaces import IAnnotatable from zope.annotation.interfaces import IAnnotations from zope.component import adapter @@ -38,7 +39,6 @@ from zope.lifecycleevent import ObjectAddedEvent from zope.lifecycleevent import ObjectCreatedEvent from zope.lifecycleevent import ObjectRemovedEvent - import time @@ -53,7 +53,7 @@ class Conversation(Traversable, Persistent, Explicit): __allow_access_to_unprotected_subobjects__ = True - def __init__(self, id="++conversation++default"): + def __init__(self, id='++conversation++default'): self.id = id # username -> count of comments; key is removed when count reaches 0 @@ -427,7 +427,7 @@ class CommentReplies(ConversationReplies): ) if self.conversation is None or conversation_has_no_children: raise TypeError("This adapter doesn't know what to do with the " - "parent conversation") + 'parent conversation') self.comment_id = self.comment.comment_id diff --git a/plone/app/discussion/events.py b/plone/app/discussion/events.py index aefe2ab..29d636c 100644 --- a/plone/app/discussion/events.py +++ b/plone/app/discussion/events.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- """ Custom discussion events """ from plone.app.discussion.interfaces import ICommentAddedEvent diff --git a/plone/app/discussion/interfaces.py b/plone/app/discussion/interfaces.py index ad773a5..b5de309 100644 --- a/plone/app/discussion/interfaces.py +++ b/plone/app/discussion/interfaces.py @@ -30,25 +30,24 @@ class IConversation(IIterableMapping): """ total_comments = schema.Int( - title=_(u"Total number of public comments on this item"), + title=_(u'Total number of public comments on this item'), min=0, readonly=True, ) last_comment_date = schema.Date( - title=_(u"Date of the most recent public comment"), + title=_(u'Date of the most recent public comment'), readonly=True, ) commentators = schema.Set( - title=_(u"The set of unique commentators (usernames)"), + title=_(u'The set of unique commentators (usernames)'), readonly=True, ) public_commentators = schema.Set( title=_( - u"The set of unique commentators (usernames) of" - u" published_comments" + u'The set of unique commentators (usernames) of published_comments' ), readonly=True, ) @@ -129,57 +128,57 @@ class IComment(Interface): """ portal_type = schema.ASCIILine( - title=_(u"Portal type"), - default="Discussion Item", + title=_(u'Portal type'), + default='Discussion Item', ) __parent__ = schema.Object( - title=_(u"Conversation"), schema=Interface) + title=_(u'Conversation'), schema=Interface) - __name__ = schema.TextLine(title=_(u"Name")) + __name__ = schema.TextLine(title=_(u'Name')) comment_id = schema.Int( - title=_(u"A comment id unique to this conversation")) + title=_(u'A comment id unique to this conversation')) in_reply_to = schema.Int( - title=_(u"Id of comment this comment is in reply to"), + title=_(u'Id of comment this comment is in reply to'), required=False, ) # for logged in comments - set to None for anonymous - author_username = schema.TextLine(title=_(u"Name"), required=False) + author_username = schema.TextLine(title=_(u'Name'), required=False) # for anonymous comments only, set to None for logged in comments - author_name = schema.TextLine(title=_(u"Name"), required=False) - author_email = schema.TextLine(title=_(u"Email"), required=False) + author_name = schema.TextLine(title=_(u'Name'), required=False) + author_email = schema.TextLine(title=_(u'Email'), required=False) - title = schema.TextLine(title=_(u"label_subject", - default=u"Subject")) + title = schema.TextLine(title=_(u'label_subject', + default=u'Subject')) - mime_type = schema.ASCIILine(title=_(u"MIME type"), default="text/plain") + mime_type = schema.ASCIILine(title=_(u'MIME type'), default='text/plain') text = schema.Text( title=_( - u"label_comment", - default=u"Comment" + u'label_comment', + default=u'Comment' ) ) user_notification = schema.Bool( title=_( - u"Notify me of new comments via email." + u'Notify me of new comments via email.' ), required=False ) - creator = schema.TextLine(title=_(u"Username of the commenter")) - creation_date = schema.Date(title=_(u"Creation date")) - modification_date = schema.Date(title=_(u"Modification date")) + creator = schema.TextLine(title=_(u'Username of the commenter')) + creation_date = schema.Date(title=_(u'Creation date')) + modification_date = schema.Date(title=_(u'Modification date')) class ICaptcha(Interface): """Captcha/ReCaptcha text field to extend the existing comment form. """ - captcha = schema.TextLine(title=_(u"Captcha"), + captcha = schema.TextLine(title=_(u'Captcha'), required=False) @@ -195,137 +194,137 @@ class IDiscussionSettings(Interface): # - Search control panel: Show comments in search results globally_enabled = schema.Bool( - title=_(u"label_globally_enabled", - default=u"Globally enable comments"), + title=_(u'label_globally_enabled', + default=u'Globally enable comments'), description=_( - u"help_globally_enabled", - default=u"If selected, users are able to post comments on the " - u"site. Though, you have to enable comments for " - u"specific content types, folders or content objects " - u"before users will be able to post comments." + u'help_globally_enabled', + default=u'If selected, users are able to post comments on the ' + u'site. Though, you have to enable comments for ' + u'specific content types, folders or content objects ' + u'before users will be able to post comments.' ), required=False, default=False, ) anonymous_comments = schema.Bool( - title=_(u"label_anonymous_comments", - default="Enable anonymous comments"), + title=_(u'label_anonymous_comments', + default='Enable anonymous comments'), description=_( - u"help_anonymous_comments", - default=u"If selected, anonymous users are able to post " - u"comments without loggin in. It is highly " - u"recommended to use a captcha solution to prevent " - u"spam if this setting is enabled." + u'help_anonymous_comments', + default=u'If selected, anonymous users are able to post ' + u'comments without loggin in. It is highly ' + u'recommended to use a captcha solution to prevent ' + u'spam if this setting is enabled.' ), required=False, default=False, ) anonymous_email_enabled = schema.Bool( - title=_(u"label_anonymous_email_enabled", - default=u"Enable anonymous email field"), + title=_(u'label_anonymous_email_enabled', + default=u'Enable anonymous email field'), description=_( - u"help_anonymous_email_enabled", - default=u"If selected, anonymous user will have to " - u"give their email."), + u'help_anonymous_email_enabled', + default=u'If selected, anonymous user will have to ' + u'give their email.'), required=False, default=False ) moderation_enabled = schema.Bool( title=_( - u"label_moderation_enabled", - default="Enable comment moderation" + u'label_moderation_enabled', + default='Enable comment moderation' ), description=_( - u"help_moderation_enabled", - default=u"If selected, comments will enter a 'Pending' state " - u"in which they are invisible to the public. A user " - u"with the 'Review comments' permission ('Reviewer' " - u"or 'Manager') can approve comments to make them " - u"visible to the public. If you want to enable a " - u"custom comment workflow, you have to go to the " - u"types control panel." + u'help_moderation_enabled', + default=u'If selected, comments will enter a "Pending" state ' + u'in which they are invisible to the public. A user ' + u'with the "Review comments" permission ("Reviewer" ' + u'or "Manager") can approve comments to make them ' + u'visible to the public. If you want to enable a ' + u'custom comment workflow, you have to go to the ' + u'types control panel.' ), required=False, default=False, ) edit_comment_enabled = schema.Bool( - title=_(u"label_edit_comment_enabled", - default="Enable editing of comments"), - description=_(u"help_edit_comment_enabled", - default=u"If selected, supports editing " - "of comments for users with the 'Edit comments' " - "permission."), + title=_(u'label_edit_comment_enabled', + default='Enable editing of comments'), + description=_(u'help_edit_comment_enabled', + default=u'If selected, supports editing ' + 'of comments for users with the "Edit comments" ' + 'permission.'), required=False, default=False, ) delete_own_comment_enabled = schema.Bool( - title=_(u"label_delete_own_comment_enabled", - default="Enable deleting own comments"), - description=_(u"help_delete_own_comment_enabled", - default=u"If selected, supports deleting " - "of own comments for users with the " - "'Delete own comments' permission."), + title=_(u'label_delete_own_comment_enabled', + default='Enable deleting own comments'), + description=_(u'help_delete_own_comment_enabled', + default=u'If selected, supports deleting ' + 'of own comments for users with the ' + '"Delete own comments" permission.'), required=False, default=False, ) text_transform = schema.Choice( - title=_(u"label_text_transform", - default="Comment text transform"), + title=_(u'label_text_transform', + default='Comment text transform'), description=_( - u"help_text_transform", - default=u"Use this setting to choose if the comment text " + - u"should be transformed in any way. You can choose " - u"between 'Plain text' and 'Intelligent text'. " + - u"'Intelligent text' converts plain text into HTML " + - u"where line breaks and indentation is preserved, " + - u"and web and email addresses are made into " + - u"clickable links."), + u'help_text_transform', + default=u'Use this setting to choose if the comment text ' + u'should be transformed in any way. You can choose ' + u'between "Plain text" and "Intelligent text". ' + u'"Intelligent text" converts plain text into HTML ' + u'where line breaks and indentation is preserved, ' + u'and web and email addresses are made into ' + u'clickable links.'), required=True, default='text/plain', vocabulary='plone.app.discussion.vocabularies.TextTransformVocabulary', ) captcha = schema.Choice( - title=_(u"label_captcha", - default="Captcha"), + title=_(u'label_captcha', + default='Captcha'), description=_( - u"help_captcha", - default=u"Use this setting to enable or disable Captcha " - u"validation for comments. Install " - u"plone.formwidget.captcha, " - u"plone.formwidget.recaptcha, collective.akismet, or " - u"collective.z3cform.norobots if there are no options " - u"available."), + u'help_captcha', + default=u'Use this setting to enable or disable Captcha ' + u'validation for comments. Install ' + u'plone.formwidget.captcha, ' + u'plone.formwidget.recaptcha, collective.akismet, or ' + u'collective.z3cform.norobots if there are no options ' + u'available.'), required=True, default='disabled', vocabulary='plone.app.discussion.vocabularies.CaptchaVocabulary', ) show_commenter_image = schema.Bool( - title=_(u"label_show_commenter_image", - default=u"Show commenter image"), + title=_(u'label_show_commenter_image', + default=u'Show commenter image'), description=_( - u"help_show_commenter_image", - default=u"If selected, an image of the user is shown next to " - u"the comment."), + u'help_show_commenter_image', + default=u'If selected, an image of the user is shown next to ' + u'the comment.'), required=False, default=True, ) moderator_notification_enabled = schema.Bool( - title=_(u"label_moderator_notification_enabled", - default=u"Enable moderator email notification"), + title=_(u'label_moderator_notification_enabled', + default=u'Enable moderator email notification'), description=_( - u"help_moderator_notification_enabled", - default=u"If selected, the moderator is notified if a comment " - u"needs attention. The moderator email address can " + - u"be set below."), + u'help_moderator_notification_enabled', + default=u'If selected, the moderator is notified if a comment ' + u'needs attention. The moderator email address can ' + u'be set below.'), required=False, default=False, ) @@ -337,20 +336,20 @@ class IDiscussionSettings(Interface): ), description=_( u'help_moderator_email', - default=u"Address to which moderator notifications " - u"will be sent."), + default=u'Address to which moderator notifications ' + u'will be sent.'), required=False, ) user_notification_enabled = schema.Bool( title=_( - u"label_user_notification_enabled", - default=u"Enable user email notification" + u'label_user_notification_enabled', + default=u'Enable user email notification' ), description=_( - u"help_user_notification_enabled", - default=u"If selected, users can choose to be notified " - u"of new comments by email."), + u'help_user_notification_enabled', + default=u'If selected, users can choose to be notified ' + u'of new comments by email.'), required=False, default=False ) diff --git a/plone/app/discussion/subscribers.py b/plone/app/discussion/subscribers.py index 07e0bb5..9663243 100644 --- a/plone/app/discussion/subscribers.py +++ b/plone/app/discussion/subscribers.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- from Products.CMFCore.utils import getToolByName diff --git a/plone/app/discussion/testing.py b/plone/app/discussion/testing.py index 9c7c41c..1612edd 100644 --- a/plone/app/discussion/testing.py +++ b/plone/app/discussion/testing.py @@ -1,4 +1,4 @@ -from Products.CMFCore.utils import getToolByName +# -*- coding: utf-8 -*- from plone.app.contenttypes.testing import PLONE_APP_CONTENTTYPES_FIXTURE from plone.app.discussion.interfaces import IDiscussionSettings from plone.app.robotframework.testing import REMOTE_LIBRARY_ROBOT_TESTING @@ -9,14 +9,16 @@ from plone.app.testing import PloneSandboxLayer from plone.app.testing import setRoles from plone.app.testing import TEST_USER_ID from plone.registry.interfaces import IRegistry +from Products.CMFCore.utils import getToolByName from zope.component import queryUtility from zope.configuration import xmlconfig + try: import plone.app.collection # noqa - COLLECTION_TYPE = "Collection" -except: - COLLECTION_TYPE = "Topic" + COLLECTION_TYPE = 'Collection' +except ImportError: + COLLECTION_TYPE = 'Topic' class PloneAppDiscussion(PloneSandboxLayer): @@ -77,7 +79,7 @@ class PloneAppDiscussion(PloneSandboxLayer): gtool.addPrincipalToGroup(self.REVIEWER_NAME, 'Reviewers') mtool.addMember('jim', 'Jim', ['Member'], []) mtool.getMemberById('jim').setMemberProperties( - {"fullname": 'Jim Fult\xc3\xb8rn'}) + {'fullname': 'Jim Fult\xc3\xb8rn'}) acl_users.userFolderAddUser( self.MANAGER_USER_NAME, @@ -107,14 +109,14 @@ PLONE_APP_DISCUSSION_ROBOT_FIXTURE = PloneAppDiscussionRobot() PLONE_APP_DISCUSSION_FIXTURE = PloneAppDiscussion() PLONE_APP_DISCUSSION_INTEGRATION_TESTING = IntegrationTesting( bases=(PLONE_APP_DISCUSSION_FIXTURE,), - name="PloneAppDiscussion:Integration") + name='PloneAppDiscussion:Integration') PLONE_APP_DISCUSSION_FUNCTIONAL_TESTING = FunctionalTesting( bases=(PLONE_APP_DISCUSSION_FIXTURE,), - name="PloneAppDiscussion:Functional") + name='PloneAppDiscussion:Functional') PLONE_APP_DISCUSSION_ROBOT_TESTING = FunctionalTesting( bases=( PLONE_APP_DISCUSSION_ROBOT_FIXTURE, REMOTE_LIBRARY_ROBOT_TESTING ), - name="PloneAppDiscussion:Robot" + name='PloneAppDiscussion:Robot' ) diff --git a/plone/app/discussion/tests/test_catalog.py b/plone/app/discussion/tests/test_catalog.py index f549110..9cfcbfc 100644 --- a/plone/app/discussion/tests/test_catalog.py +++ b/plone/app/discussion/tests/test_catalog.py @@ -1,11 +1,12 @@ +# -*- coding: utf-8 -*- """Test the plone.app.discussion catalog indexes """ -from Products.CMFCore.utils import getToolByName from datetime import datetime from plone.app.discussion.interfaces import IConversation from plone.app.discussion.testing import PLONE_APP_DISCUSSION_INTEGRATION_TESTING # noqa from plone.app.testing import setRoles from plone.app.testing import TEST_USER_ID +from Products.CMFCore.utils import getToolByName from zope.annotation.interfaces import IAnnotations from zope.component import createObject @@ -74,7 +75,7 @@ class ConversationCatalogTest(unittest.TestCase): 'query': '/'.join(self.portal.doc1.getPhysicalPath()) }, - portal_type="Document" + portal_type='Document' )) self.conversation = conversation self.brains = brains @@ -92,14 +93,15 @@ class ConversationCatalogTest(unittest.TestCase): new_comment2_id = self.conversation.addComment(comment2) comment2 = self.portal.doc1.restrictedTraverse( - '++conversation++default/%s' % new_comment2_id) + '++conversation++default/{0}'.format(new_comment2_id) + ) comment2.reindexObject() brains = self.catalog.searchResults(dict( path={ 'query': '/'.join(self.portal.doc1.getPhysicalPath()) }, - portal_type="Document" + portal_type='Document' )) doc1_brain = brains[0] self.assertEqual(doc1_brain.total_comments, 2) @@ -120,14 +122,15 @@ class ConversationCatalogTest(unittest.TestCase): new_comment2_id = self.conversation.addComment(comment2) comment2 = self.portal.doc1.restrictedTraverse( - '++conversation++default/%s' % new_comment2_id) + '++conversation++default/{0}'.format(new_comment2_id) + ) comment2.reindexObject() brains = self.catalog.searchResults(dict( path={ 'query': '/'.join(self.portal.doc1.getPhysicalPath()) }, - portal_type="Document" + portal_type='Document' )) doc1_brain = brains[0] self.assertEqual( @@ -143,7 +146,7 @@ class ConversationCatalogTest(unittest.TestCase): 'query': '/'.join(self.portal.doc1.getPhysicalPath()) }, - portal_type="Document" + portal_type='Document' )) doc1_brain = brains[0] self.assertEqual( @@ -158,7 +161,7 @@ class ConversationCatalogTest(unittest.TestCase): 'query': '/'.join(self.portal.doc1.getPhysicalPath()) }, - portal_type="Document" + portal_type='Document' )) doc1_brain = brains[0] self.assertEqual(doc1_brain.last_comment_date, None) @@ -176,7 +179,8 @@ class ConversationCatalogTest(unittest.TestCase): new_comment2_id = self.conversation.addComment(comment2) comment2 = self.portal.doc1.restrictedTraverse( - '++conversation++default/%s' % new_comment2_id) + '++conversation++default/{0}'.format(new_comment2_id) + ) comment2.reindexObject() brains = self.catalog.searchResults(dict( @@ -184,7 +188,7 @@ class ConversationCatalogTest(unittest.TestCase): 'query': '/'.join(self.portal.doc1.getPhysicalPath()) }, - portal_type="Document" + portal_type='Document' )) doc1_brain = brains[0] @@ -197,7 +201,7 @@ class ConversationCatalogTest(unittest.TestCase): 'query': '/'.join(self.portal.doc1.getPhysicalPath()) }, - portal_type="Document" + portal_type='Document' )) doc1_brain = brains[0] self.assertEqual(doc1_brain.commentators, ('Jim',)) @@ -209,7 +213,7 @@ class ConversationCatalogTest(unittest.TestCase): 'query': '/'.join(self.portal.doc1.getPhysicalPath()) }, - portal_type="Document" + portal_type='Document' )) doc1_brain = brains[0] self.assertEqual(doc1_brain.commentators, ()) @@ -220,7 +224,7 @@ class ConversationCatalogTest(unittest.TestCase): 'query': '/'.join(self.portal.doc1.getPhysicalPath()) }, - portal_type="Discussion Item" + portal_type='Discussion Item' )) comment1_brain = brains[0] self.assertEqual(comment1_brain.commentators, None) @@ -228,14 +232,14 @@ class ConversationCatalogTest(unittest.TestCase): self.assertEqual(comment1_brain.total_comments, None) def test_dont_index_private_commentators(self): - self.comment1.manage_permission("View", roles=tuple()) + self.comment1.manage_permission('View', roles=tuple()) self.portal.doc1.reindexObject() brains = self.catalog.searchResults(dict( path={ 'query': '/'.join(self.portal.doc1.getPhysicalPath()) }, - portal_type="Document" + portal_type='Document' )) doc1_brain = brains[0] self.assertEqual(doc1_brain.commentators, ()) @@ -262,7 +266,8 @@ class CommentCatalogTest(unittest.TestCase): # Comment brain self.comment = self.portal.doc1.restrictedTraverse( - '++conversation++default/%s' % new_comment1_id) + '++conversation++default/{0}'.format(new_comment1_id) + ) brains = self.catalog.searchResults(dict( path={ 'query': @@ -281,7 +286,8 @@ class CommentCatalogTest(unittest.TestCase): # Comment brain comment = self.portal.doc1.restrictedTraverse( - '++conversation++default/%s' % cid) + '++conversation++default/{0}'.format(cid) + ) brains = self.catalog.searchResults(dict( path={ 'query': @@ -289,7 +295,7 @@ class CommentCatalogTest(unittest.TestCase): } )) comment_brain = brains[0] - self.assertEqual(comment_brain.Title, "Anonymous on Document 1") + self.assertEqual(comment_brain.Title, 'Anonymous on Document 1') def test_type(self): self.assertEqual(self.comment_brain.portal_type, 'Discussion Item') @@ -329,7 +335,7 @@ class CommentCatalogTest(unittest.TestCase): """ brains = self.catalog.searchResults({'portal_type': 'Discussion Item'}) self.assertEqual(len(brains), 1) - self.portal.manage_delObjects(["doc1"]) + self.portal.manage_delObjects(['doc1']) brains = self.catalog.searchResults({'portal_type': 'Discussion Item'}) self.assertEqual(len(brains), 0) @@ -362,13 +368,13 @@ class CommentCatalogTest(unittest.TestCase): # Make sure no old comment brains are brains = self.catalog.searchResults(dict( - portal_type="Discussion Item", + portal_type='Discussion Item', path={'query': '/'.join(self.portal.folder1.getPhysicalPath())} )) self.assertEqual(len(brains), 0) brains = self.catalog.searchResults(dict( - portal_type="Discussion Item", + portal_type='Discussion Item', path={ 'query': '/'.join(self.portal.folder2.getPhysicalPath()) } @@ -411,14 +417,14 @@ class CommentCatalogTest(unittest.TestCase): # Make sure no old comment brains are left brains = self.catalog.searchResults(dict( - portal_type="Discussion Item", + portal_type='Discussion Item', path={'query': '/plone/sourcefolder/moveme'} )) self.assertEqual(len(brains), 0) # make sure comments are correctly index on the target brains = self.catalog.searchResults(dict( - portal_type="Discussion Item", + portal_type='Discussion Item', path={'query': '/plone/targetfolder/moveme'} )) self.assertEqual(len(brains), 1) @@ -432,7 +438,7 @@ class CommentCatalogTest(unittest.TestCase): # We need to commit here so that _p_jar isn't None and move will work transaction.savepoint(optimistic=True) - self.portal.manage_renameObject("doc1", "doc2") + self.portal.manage_renameObject('doc1', 'doc2') brains = self.catalog.searchResults( portal_type='Discussion Item') @@ -535,7 +541,7 @@ class NoConversationCatalogTest(unittest.TestCase): 'query': '/'.join(self.portal.doc1.getPhysicalPath()) }, - portal_type="Document" + portal_type='Document' )) self.conversation = conversation self.brains = brains diff --git a/plone/app/discussion/tests/test_comment.py b/plone/app/discussion/tests/test_comment.py index 127197e..b041eb4 100644 --- a/plone/app/discussion/tests/test_comment.py +++ b/plone/app/discussion/tests/test_comment.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- -from Products.CMFCore.utils import getToolByName from plone.app.discussion.browser.comment import View from plone.app.discussion.interfaces import IComment from plone.app.discussion.interfaces import IConversation @@ -7,6 +6,7 @@ from plone.app.discussion.interfaces import IReplies from plone.app.discussion.testing import PLONE_APP_DISCUSSION_INTEGRATION_TESTING # noqa from plone.app.testing import setRoles from plone.app.testing import TEST_USER_ID +from Products.CMFCore.utils import getToolByName from zope.component import createObject from zope.component import getMultiAdapter @@ -41,9 +41,9 @@ class CommentTest(unittest.TestCase): datetime.datetime.now() - datetime.datetime.utcnow() utc_to_local_diff = abs(utc_to_local_diff.seconds) if utc_to_local_diff < 60: - logger.warning("Your computer is living in a timezone where local " - "time equals utc time. Some potential errors can " - "get hidden by that") + logger.warning('Your computer is living in a timezone where local ' + 'time equals utc time. Some potential errors can ' + 'get hidden by that') comment1 = createObject('plone.Comment') local_utc = datetime.datetime.utcnow() for date in (comment1.creation_date, comment1.modification_date): @@ -92,15 +92,15 @@ class CommentTest(unittest.TestCase): def test_title(self): conversation = IConversation(self.portal.doc1) comment1 = createObject('plone.Comment') - comment1.author_name = "Jim Fulton" + comment1.author_name = 'Jim Fulton' conversation.addComment(comment1) - self.assertEqual("Jim Fulton on Document 1", comment1.Title()) + self.assertEqual('Jim Fulton on Document 1', comment1.Title()) def test_no_name_title(self): conversation = IConversation(self.portal.doc1) comment1 = createObject('plone.Comment') conversation.addComment(comment1) - self.assertEqual("Anonymous on Document 1", comment1.Title()) + self.assertEqual('Anonymous on Document 1', comment1.Title()) def test_title_special_characters(self): self.portal.invokeFactory( @@ -110,9 +110,9 @@ class CommentTest(unittest.TestCase): ) conversation = IConversation(self.portal.doc_sp_chars) comment1 = createObject('plone.Comment') - comment1.author_name = u"Tarek Ziadé" + comment1.author_name = u'Tarek Ziadé' conversation.addComment(comment1) - self.assertEqual(u"Tarek Ziadé on Document äüö", comment1.Title()) + self.assertEqual(u'Tarek Ziadé on Document äüö', comment1.Title()) def test_title_special_characters_utf8(self): self.portal.invokeFactory( @@ -122,19 +122,19 @@ class CommentTest(unittest.TestCase): ) conversation = IConversation(self.portal.doc_sp_chars_utf8) comment1 = createObject('plone.Comment') - comment1.author_name = "Hüüb Bôûmä" + comment1.author_name = 'Hüüb Bôûmä' conversation.addComment(comment1) - self.assertEqual(u"Hüüb Bôûmä on Document ëïû", comment1.Title()) + self.assertEqual(u'Hüüb Bôûmä on Document ëïû', comment1.Title()) def test_creator(self): comment1 = createObject('plone.Comment') - comment1.creator = "jim" - self.assertEqual("jim", comment1.Creator()) + comment1.creator = 'jim' + self.assertEqual('jim', comment1.Creator()) def test_creator_author_name(self): comment1 = createObject('plone.Comment') - comment1.author_name = "joey" - self.assertEqual("joey", comment1.Creator()) + comment1.author_name = 'joey' + self.assertEqual('joey', comment1.Creator()) def test_owner(self): comment1 = createObject('plone.Comment') @@ -151,25 +151,23 @@ class CommentTest(unittest.TestCase): def test_getText(self): comment1 = createObject('plone.Comment') - comment1.text = """First paragraph - - Second paragraph""" + comment1.text = 'First paragraph\n\nSecond paragraph' self.assertEqual( comment1.getText(), - "

First paragraph

Second paragraph

" + '

First paragraph

Second paragraph

' ) def test_getText_escapes_HTML(self): comment1 = createObject('plone.Comment') - comment1.text = """Got HTML?""" + comment1.text = 'Got HTML?' self.assertEqual( comment1.getText(), - "

<b>Got HTML?</b>

" + '

<b>Got HTML?</b>

' ) def test_getText_with_non_ascii_characters(self): comment1 = createObject('plone.Comment') - comment1.text = u"""Umlaute sind ä, ö und ü.""" + comment1.text = u'Umlaute sind ä, ö und ü.' self.assertEqual( comment1.getText(), '

Umlaute sind \xc3\xa4, \xc3\xb6 und \xc3\xbc.

' @@ -177,15 +175,15 @@ class CommentTest(unittest.TestCase): def test_getText_doesnt_link(self): comment1 = createObject('plone.Comment') - comment1.text = "Go to http://www.plone.org" + comment1.text = 'Go to http://www.plone.org' self.assertEqual( comment1.getText(), - "

Go to http://www.plone.org

" + '

Go to http://www.plone.org

' ) def test_getText_uses_comment_mime_type(self): comment1 = createObject('plone.Comment') - comment1.text = "Go to http://www.plone.org" + comment1.text = 'Go to http://www.plone.org' comment1.mime_type = 'text/x-web-intelligent' self.assertEqual( comment1.getText(), @@ -229,7 +227,8 @@ class CommentTest(unittest.TestCase): new_comment1_id = conversation.addComment(comment1) comment = self.portal.doc1.restrictedTraverse( - '++conversation++default/%s' % new_comment1_id) + '++conversation++default/{0}'.format(new_comment1_id) + ) self.assertTrue(IComment.providedBy(comment)) self.assertEqual( @@ -260,12 +259,13 @@ class CommentTest(unittest.TestCase): comment1.text = 'Comment text' new_comment1_id = conversation.addComment(comment1) comment = self.portal.image1.restrictedTraverse( - '++conversation++default/%s' % new_comment1_id) + '++conversation++default/{0}'.format(new_comment1_id) + ) view = View(comment, self.request) View.__call__(view) response = self.request.response - self.assertIn("/view", response.headers['location']) + self.assertIn('/view', response.headers['location']) def test_workflow(self): """Basic test for the 'comment_review_workflow' @@ -301,8 +301,8 @@ class CommentTest(unittest.TestCase): def test_fti(self): # test that we can look up an FTI for Discussion Item - self.assertTrue( - "Discussion Item" in + self.assertIn( + 'Discussion Item', self.portal.portal_types.objectIds() ) @@ -327,7 +327,8 @@ class CommentTest(unittest.TestCase): new_comment1_id = conversation.addComment(comment1) comment = self.portal.doc1.restrictedTraverse( - '++conversation++default/%s' % new_comment1_id) + '++conversation++default/{0}'.format(new_comment1_id) + ) # make sure the view is there self.assertTrue(getMultiAdapter((comment, self.request), @@ -364,7 +365,8 @@ class RepliesTest(unittest.TestCase): comment.text = 'Comment text' new_id = replies.addComment(comment) comment = self.portal.doc1.restrictedTraverse( - '++conversation++default/%s' % new_id) + '++conversation++default/{0}'.format(new_id) + ) # Add a reply to the CommentReplies adapter of the first comment re_comment = createObject('plone.Comment') @@ -400,7 +402,8 @@ class RepliesTest(unittest.TestCase): comment.text = 'Comment text' new_id = replies.addComment(comment) comment = self.portal.doc1.restrictedTraverse( - '++conversation++default/%s' % new_id) + '++conversation++default/{0}'.format(new_id) + ) # Add a reply to the CommentReplies adapter of the first comment re_comment = createObject('plone.Comment') @@ -435,7 +438,8 @@ class RepliesTest(unittest.TestCase): comment.text = 'Comment text' new_id = conversation.addComment(comment) comment = self.portal.doc1.restrictedTraverse( - '++conversation++default/%s' % new_id) + '++conversation++default/{0}'.format(new_id) + ) # Add a reply to the CommentReplies adapter of the first comment re_comment = createObject('plone.Comment') @@ -443,7 +447,7 @@ class RepliesTest(unittest.TestCase): replies = IReplies(comment) new_re_id = replies.addComment(re_comment) re_comment = self.portal.doc1.restrictedTraverse( - '++conversation++default/%s' % new_re_id + '++conversation++default/{0}'.format(new_re_id) ) # Add a reply to the reply @@ -452,7 +456,7 @@ class RepliesTest(unittest.TestCase): replies = IReplies(re_comment) new_re_re_id = replies.addComment(re_re_comment) re_re_comment = self.portal.doc1.restrictedTraverse( - '++conversation++default/%s' % new_re_re_id + '++conversation++default/{0}'.format(new_re_re_id) ) # Add a reply to the replies reply @@ -461,7 +465,8 @@ class RepliesTest(unittest.TestCase): replies = IReplies(re_re_comment) new_re_re_re_id = replies.addComment(re_re_re_comment) re_re_re_comment = self.portal.doc1.restrictedTraverse( - '++conversation++default/%s' % new_re_re_re_id) + '++conversation++default/{0}'.format(new_re_re_re_id) + ) self.assertEqual( ('', 'plone', 'doc1', '++conversation++default', str(new_id)), diff --git a/plone/app/discussion/tests/test_comments_viewlet.py b/plone/app/discussion/tests/test_comments_viewlet.py index ef4d72b..8d91e38 100644 --- a/plone/app/discussion/tests/test_comments_viewlet.py +++ b/plone/app/discussion/tests/test_comments_viewlet.py @@ -2,8 +2,6 @@ from AccessControl import Unauthorized from datetime import datetime from OFS.Image import Image -from Products.CMFCore.utils import getToolByName -from Products.CMFPlone.tests import dummy from plone.app.discussion import interfaces from plone.app.discussion.browser.comment import EditCommentForm from plone.app.discussion.browser.comments import CommentForm @@ -17,6 +15,8 @@ from plone.app.testing import setRoles from plone.app.testing import TEST_USER_ID from plone.app.testing import TEST_USER_NAME from plone.registry.interfaces import IRegistry +from Products.CMFCore.utils import getToolByName +from Products.CMFPlone.tests import dummy from z3c.form.interfaces import IFormLayer from zope import interface from zope.annotation.interfaces import IAttributeAnnotatable @@ -49,7 +49,7 @@ class TestCommentForm(unittest.TestCase): interfaces.IDiscussionLayer, ) - wftool = getToolByName(self.portal, "portal_workflow") + wftool = getToolByName(self.portal, 'portal_workflow') wftool.doActionFor(self.portal.doc1, action='publish') self.portal.doc1.allow_discussion = True self.membershipTool = getToolByName(self.folder, 'portal_membership') @@ -80,7 +80,7 @@ class TestCommentForm(unittest.TestCase): adapts=(Interface, IBrowserRequest), provides=Interface, factory=CommentForm, - name=u"comment-form" + name=u'comment-form' ) # The form should return an error if the comment text field is empty @@ -88,13 +88,13 @@ class TestCommentForm(unittest.TestCase): commentForm = getMultiAdapter( (self.context, request), - name=u"comment-form" + name=u'comment-form' ) commentForm.update() data, errors = commentForm.extractData() # pylint: disable-msg=W0612 self.assertEqual(len(errors), 1) - self.assertFalse(commentForm.handleComment(commentForm, "foo")) + self.assertFalse(commentForm.handleComment(commentForm, 'foo')) # The form is submitted successfully, if the required text field is # filled out @@ -102,22 +102,22 @@ class TestCommentForm(unittest.TestCase): commentForm = getMultiAdapter( (self.context, request), - name=u"comment-form" + name=u'comment-form' ) commentForm.update() data, errors = commentForm.extractData() # pylint: disable-msg=W0612 self.assertEqual(len(errors), 0) - self.assertFalse(commentForm.handleComment(commentForm, "foo")) + self.assertFalse(commentForm.handleComment(commentForm, 'foo')) comments = IConversation(commentForm.context).getComments() comments = [comment for comment in comments] # consume iterator self.assertEqual(len(comments), 1) for comment in comments: - self.assertEqual(comment.text, u"bar") - self.assertEqual(comment.creator, "test_user_1_") - self.assertEqual(comment.getOwner().getUserName(), "test-user") + self.assertEqual(comment.text, u'bar') + self.assertEqual(comment.creator, 'test_user_1_') + self.assertEqual(comment.getOwner().getUserName(), 'test-user') local_roles = comment.get_local_roles() self.assertEqual(len(local_roles), 1) userid, roles = local_roles[0] @@ -144,14 +144,14 @@ class TestCommentForm(unittest.TestCase): adapts=(Interface, IBrowserRequest), provides=Interface, factory=CommentForm, - name=u"comment-form" + name=u'comment-form' ) provideAdapter( adapts=(Interface, IBrowserRequest), provides=Interface, factory=EditCommentForm, - name=u"edit-comment-form" + name=u'edit-comment-form' ) # The form is submitted successfully, if the required text field is @@ -160,13 +160,13 @@ class TestCommentForm(unittest.TestCase): commentForm = getMultiAdapter( (self.context, request), - name=u"comment-form" + name=u'comment-form' ) commentForm.update() data, errors = commentForm.extractData() # pylint: disable-msg=W0612 self.assertEqual(len(errors), 0) - self.assertFalse(commentForm.handleComment(commentForm, "foo")) + self.assertFalse(commentForm.handleComment(commentForm, 'foo')) # Edit the last comment conversation = IConversation(self.context) @@ -174,25 +174,25 @@ class TestCommentForm(unittest.TestCase): request = make_request(form={'form.widgets.text': u'foobar'}) editForm = getMultiAdapter( (comment, request), - name=u"edit-comment-form" + name=u'edit-comment-form' ) editForm.update() data, errors = editForm.extractData() # pylint: disable-msg=W0612 self.assertEqual(len(errors), 0) - self.assertFalse(editForm.handleComment(editForm, "foo")) + self.assertFalse(editForm.handleComment(editForm, 'foo')) comment = [x for x in conversation.getComments()][-1] - self.assertEquals(comment.text, u"foobar") + self.assertEqual(comment.text, u'foobar') comments = IConversation(commentForm.context).getComments() comments = [c for c in comments] # consume iterator self.assertEqual(len(comments), 1) for comment in comments: - self.assertEqual(comment.text, u"foobar") - self.assertEqual(comment.creator, "test_user_1_") + self.assertEqual(comment.text, u'foobar') + self.assertEqual(comment.creator, 'test_user_1_') - self.assertEqual(comment.getOwner().getUserName(), "test-user") + self.assertEqual(comment.getOwner().getUserName(), 'test-user') local_roles = comment.get_local_roles() self.assertEqual(len(local_roles), 1) userid, roles = local_roles[0] @@ -219,7 +219,7 @@ class TestCommentForm(unittest.TestCase): adapts=(Interface, IBrowserRequest), provides=Interface, factory=CommentForm, - name=u"comment-form" + name=u'comment-form' ) # The form is submitted successfully, if the required text field is @@ -228,31 +228,31 @@ class TestCommentForm(unittest.TestCase): commentForm = getMultiAdapter( (self.context, form_request), - name=u"comment-form" + name=u'comment-form' ) commentForm.update() data, errors = commentForm.extractData() # pylint: disable-msg=W0612 self.assertEqual(len(errors), 0) - self.assertFalse(commentForm.handleComment(commentForm, "foo")) + self.assertFalse(commentForm.handleComment(commentForm, 'foo')) # Delete the last comment conversation = IConversation(self.context) comment = [x for x in conversation.getComments()][-1] deleteView = getMultiAdapter( (comment, self.request), - name=u"moderate-delete-comment" + name=u'moderate-delete-comment' ) - # try to delete last comment without "Delete comments" permission + # try to delete last comment without 'Delete comments' permission setRoles(self.portal, TEST_USER_ID, ['Member']) self.assertRaises( Unauthorized, comment.restrictedTraverse, - "@@moderate-delete-comment" + '@@moderate-delete-comment' ) deleteView() self.assertEqual(1, len([x for x in conversation.getComments()])) - # try to delete last comment with "Delete comments" permission + # try to delete last comment with 'Delete comments' permission setRoles(self.portal, TEST_USER_ID, ['Reviewer']) deleteView() self.assertEqual(0, len([x for x in conversation.getComments()])) @@ -277,7 +277,7 @@ class TestCommentForm(unittest.TestCase): adapts=(Interface, IBrowserRequest), provides=Interface, factory=CommentForm, - name=u"comment-form" + name=u'comment-form' ) # The form is submitted successfully, if the required text field is @@ -286,20 +286,20 @@ class TestCommentForm(unittest.TestCase): commentForm = getMultiAdapter( (self.context, form_request), - name=u"comment-form" + name=u'comment-form' ) commentForm.update() data, errors = commentForm.extractData() # pylint: disable-msg=W0612 self.assertEqual(len(errors), 0) - self.assertFalse(commentForm.handleComment(commentForm, "foo")) + self.assertFalse(commentForm.handleComment(commentForm, 'foo')) # Delete the last comment conversation = IConversation(self.context) comment = [x for x in conversation.getComments()][-1] deleteView = getMultiAdapter( (comment, self.request), - name=u"delete-own-comment" + name=u'delete-own-comment' ) # try to delete last comment with johndoe setRoles(self.portal, 'johndoe', ['Member']) @@ -307,7 +307,7 @@ class TestCommentForm(unittest.TestCase): self.assertRaises( Unauthorized, comment.restrictedTraverse, - "@@delete-own-comment" + '@@delete-own-comment' ) self.assertEqual(1, len([x for x in conversation.getComments()])) # try to delete last comment with the same user that created it @@ -338,7 +338,7 @@ class TestCommentForm(unittest.TestCase): provideAdapter(adapts=(Interface, IBrowserRequest), provides=Interface, factory=CommentForm, - name=u"comment-form") + name=u'comment-form') # Post an anonymous comment and provide a name request = make_request(form={ @@ -348,20 +348,20 @@ class TestCommentForm(unittest.TestCase): commentForm = getMultiAdapter( (self.context, request), - name=u"comment-form" + name=u'comment-form' ) commentForm.update() data, errors = commentForm.extractData() # pylint: disable-msg=W0612 self.assertEqual(len(errors), 0) - self.assertFalse(commentForm.handleComment(commentForm, "action")) + self.assertFalse(commentForm.handleComment(commentForm, 'action')) comments = IConversation(commentForm.context).getComments() comments = [comment for comment in comments] # consume itertor self.assertEqual(len(comments), 1) for comment in IConversation(commentForm.context).getComments(): - self.assertEqual(comment.text, u"bar") + self.assertEqual(comment.text, u'bar') self.assertIsNone(comment.creator) roles = comment.get_local_roles() self.assertEqual(len(roles), 0) @@ -385,13 +385,13 @@ class TestCommentForm(unittest.TestCase): provideAdapter(adapts=(Interface, IBrowserRequest), provides=Interface, factory=CommentForm, - name=u"comment-form") + name=u'comment-form') request = make_request(form={'form.widgets.text': u'bar'}) commentForm = getMultiAdapter( (self.context, request), - name=u"comment-form" + name=u'comment-form' ) commentForm.update() data, errors = commentForm.extractData() # pylint: disable-msg=W0612 @@ -403,7 +403,7 @@ class TestCommentForm(unittest.TestCase): self.assertRaises(Unauthorized, commentForm.handleComment, commentForm, - "foo") + 'foo') def test_anonymous_can_not_add_comments_if_discussion_is_not_allowed(self): """Make sure that anonymous users can't post comments if anonymous @@ -424,12 +424,12 @@ class TestCommentForm(unittest.TestCase): provideAdapter(adapts=(Interface, IBrowserRequest), provides=Interface, factory=CommentForm, - name=u"comment-form") + name=u'comment-form') request = make_request(form={'form.widgets.text': u'bar'}) commentForm = getMultiAdapter((self.context, request), - name=u"comment-form") + name=u'comment-form') commentForm.update() data, errors = commentForm.extractData() # pylint: disable-msg=W0612 @@ -438,7 +438,7 @@ class TestCommentForm(unittest.TestCase): Unauthorized, commentForm.handleComment, commentForm, - "foo" + 'foo' ) @@ -519,20 +519,20 @@ class TestCommentsViewlet(unittest.TestCase): self.assertTrue(self.viewlet.comment_transform_message()) self.assertEqual( self.viewlet.comment_transform_message(), - "You can add a comment by filling out the form below. Plain " + - "text formatting.") + 'You can add a comment by filling out the form below. Plain ' + + 'text formatting.') # Set text transform to intelligent text registry = queryUtility(IRegistry) settings = registry.forInterface(IDiscussionSettings, check=False) - settings.text_transform = "text/x-web-intelligent" + settings.text_transform = 'text/x-web-intelligent' # Make sure the comment description changes accordingly self.assertEqual( self.viewlet.comment_transform_message(), - "You can add a comment by filling out the form below. " + - "Plain text formatting. Web and email addresses are transformed " + - "into clickable links." + 'You can add a comment by filling out the form below. ' + + 'Plain text formatting. Web and email addresses are transformed ' + + 'into clickable links.' ) # Enable moderation workflow @@ -543,9 +543,9 @@ class TestCommentsViewlet(unittest.TestCase): # Make sure the comment description shows that comments are moderated self.assertEqual( self.viewlet.comment_transform_message(), - "You can add a comment by filling out the form below. " + - "Plain text formatting. Web and email addresses are transformed " + - "into clickable links. Comments are moderated.") + 'You can add a comment by filling out the form below. ' + + 'Plain text formatting. Web and email addresses are transformed ' + + 'into clickable links. Comments are moderated.') def test_has_replies(self): self.assertEqual(self.viewlet.has_replies(), False) @@ -599,10 +599,11 @@ class TestCommentsViewlet(unittest.TestCase): reply['actions'][0]['id'], 'publish' ) + expected_url = 'http://nohost/plone/doc1/++conversation++default/{0}' \ + '/content_status_modify?workflow_action=publish' self.assertEqual( reply['actions'][0]['url'], - 'http://nohost/plone/doc1/++conversation++default/%s' % int(c1) + - '/content_status_modify?workflow_action=publish' + expected_url.format(int(c1)) ) def test_get_commenter_home_url(self): diff --git a/plone/app/discussion/tests/test_contentrules.py b/plone/app/discussion/tests/test_contentrules.py index 5498b3f..b5d7599 100644 --- a/plone/app/discussion/tests/test_contentrules.py +++ b/plone/app/discussion/tests/test_contentrules.py @@ -1,7 +1,8 @@ # -*- coding: utf-8 -*- from plone.app.discussion.interfaces import ICommentAddedEvent from plone.app.discussion.interfaces import ICommentRemovedEvent -from plone.app.discussion.interfaces import IConversation, IReplies +from plone.app.discussion.interfaces import IConversation +from plone.app.discussion.interfaces import IReplies from plone.app.discussion.interfaces import IReplyAddedEvent from plone.app.discussion.interfaces import IReplyRemovedEvent from plone.app.discussion.testing import PLONE_APP_DISCUSSION_INTEGRATION_TESTING # noqa @@ -37,10 +38,10 @@ class CommentContentRulesTest(unittest.TestCase): self.document = self.portal['doc1'] comment = createObject('plone.Comment') - comment.text = "This is a comment" - comment.author_username = "jim" - comment.author_name = "Jim" - comment.author_email = "jim@example.com" + comment.text = 'This is a comment' + comment.author_username = 'jim' + comment.author_name = 'Jim' + comment.author_email = 'jim@example.com' conversation = IConversation(self.document) conversation.addComment(comment) @@ -52,28 +53,28 @@ class CommentContentRulesTest(unittest.TestCase): def testCommentIdStringSubstitution(self): comment_id = getAdapter(self.document, IStringSubstitution, - name=u"comment_id") + name=u'comment_id') self.assertIsInstance(comment_id(), long) def testCommentTextStringSubstitution(self): comment_text = getAdapter(self.document, IStringSubstitution, - name=u"comment_text") - self.assertEqual(comment_text(), u"This is a comment") + name=u'comment_text') + self.assertEqual(comment_text(), u'This is a comment') def testCommentUserIdStringSubstitution(self): comment_user_id = getAdapter(self.document, IStringSubstitution, - name=u"comment_user_id") - self.assertEqual(comment_user_id(), u"jim") + name=u'comment_user_id') + self.assertEqual(comment_user_id(), u'jim') def testCommentUserFullNameStringSubstitution(self): comment_user_fullname = getAdapter(self.document, IStringSubstitution, - name=u"comment_user_fullname") - self.assertEqual(comment_user_fullname(), u"Jim") + name=u'comment_user_fullname') + self.assertEqual(comment_user_fullname(), u'Jim') def testCommentUserEmailStringSubstitution(self): comment_user_email = getAdapter(self.document, IStringSubstitution, - name=u"comment_user_email") - self.assertEqual(comment_user_email(), u"jim@example.com") + name=u'comment_user_email') + self.assertEqual(comment_user_email(), u'jim@example.com') class ReplyContentRulesTest(unittest.TestCase): @@ -95,13 +96,14 @@ class ReplyContentRulesTest(unittest.TestCase): comment.text = 'This is a comment' new_id = replies.addComment(comment) comment = self.document.restrictedTraverse( - '++conversation++default/%s' % new_id) + '++conversation++default/{0}'.format(new_id) + ) re_comment = createObject('plone.Comment') re_comment.text = 'This is a reply' - re_comment.author_username = "julia" - re_comment.author_name = "Juliana" - re_comment.author_email = "julia@example.com" + re_comment.author_username = 'julia' + re_comment.author_name = 'Juliana' + re_comment.author_email = 'julia@example.com' replies = IReplies(comment) replies.addComment(re_comment) @@ -110,7 +112,7 @@ class ReplyContentRulesTest(unittest.TestCase): reply_id = getAdapter( self.document, IStringSubstitution, - name=u"comment_id" + name=u'comment_id' ) self.assertIsInstance(reply_id(), long) @@ -118,30 +120,30 @@ class ReplyContentRulesTest(unittest.TestCase): reply_text = getAdapter( self.document, IStringSubstitution, - name=u"comment_text" + name=u'comment_text' ) - self.assertEqual(reply_text(), u"This is a reply") + self.assertEqual(reply_text(), u'This is a reply') def testReplyUserIdStringSubstitution(self): reply_user_id = getAdapter( self.document, IStringSubstitution, - name=u"comment_user_id" + name=u'comment_user_id' ) - self.assertEqual(reply_user_id(), u"julia") + self.assertEqual(reply_user_id(), u'julia') def testReplyUserFullNameStringSubstitution(self): reply_user_fullname = getAdapter( self.document, IStringSubstitution, - name=u"comment_user_fullname" + name=u'comment_user_fullname' ) - self.assertEqual(reply_user_fullname(), u"Juliana") + self.assertEqual(reply_user_fullname(), u'Juliana') def testReplyUserEmailStringSubstitution(self): reply_user_email = getAdapter( self.document, IStringSubstitution, - name=u"comment_user_email" + name=u'comment_user_email' ) - self.assertEqual(reply_user_email(), u"julia@example.com") + self.assertEqual(reply_user_email(), u'julia@example.com') diff --git a/plone/app/discussion/tests/test_controlpanel.py b/plone/app/discussion/tests/test_controlpanel.py index 2f9bdcd..64ae7d4 100644 --- a/plone/app/discussion/tests/test_controlpanel.py +++ b/plone/app/discussion/tests/test_controlpanel.py @@ -29,14 +29,14 @@ class RegistryTest(unittest.TestCase): def test_discussion_controlpanel_view(self): view = getMultiAdapter( (self.portal, self.portal.REQUEST), - name="discussion-controlpanel" + name='discussion-controlpanel' ) view = view.__of__(self.portal) self.assertTrue(view()) def test_discussion_in_controlpanel(self): # Check if discussion is in the control panel - self.controlpanel = getToolByName(self.portal, "portal_controlpanel") + self.controlpanel = getToolByName(self.portal, 'portal_controlpanel') self.assertTrue( 'discussion' in [ a.getAction(self)['id'] diff --git a/plone/app/discussion/tests/test_conversation.py b/plone/app/discussion/tests/test_conversation.py index d30019d..2720927 100644 --- a/plone/app/discussion/tests/test_conversation.py +++ b/plone/app/discussion/tests/test_conversation.py @@ -1,6 +1,6 @@ +# -*- coding: utf-8 -*- from Acquisition import aq_base from Acquisition import aq_parent -from Products.CMFCore.utils import getToolByName from datetime import datetime from datetime import timedelta from plone.app.discussion import interfaces @@ -13,6 +13,7 @@ from plone.app.testing import setRoles from plone.app.testing import TEST_USER_ID from plone.app.vocabularies.types import BAD_TYPES from plone.registry.interfaces import IRegistry +from Products.CMFCore.utils import getToolByName from zope import interface from zope.annotation.interfaces import IAnnotations from zope.component import createObject @@ -24,7 +25,7 @@ import unittest2 as unittest try: from plone.dexterity.interfaces import IDexterityContent DEXTERITY = True -except: +except ImportError: DEXTERITY = False @@ -82,12 +83,12 @@ class ConversationTest(unittest.TestCase): conversation = IConversation(self.portal.doc1) comment = createObject('plone.Comment') - comment.author_username = "nobody" + comment.author_username = 'nobody' conversation.addComment(comment) - comment.manage_permission("View", roles=tuple()) + comment.manage_permission('View', roles=tuple()) self.assertEqual(0, conversation.total_comments()) self.assertEqual(None, conversation.last_comment_date) - self.assertEqual(["nobody"], list(conversation.commentators)) + self.assertEqual(['nobody'], list(conversation.commentators)) self.assertEqual([], list(conversation.public_commentators)) def test_delete_comment(self): @@ -434,22 +435,22 @@ class ConversationTest(unittest.TestCase): # swapped in comment1 = createObject('plone.Comment') comment1.text = 'Comment text' - comment1.author_username = "Jim" + comment1.author_username = 'Jim' conversation.addComment(comment1) comment2 = createObject('plone.Comment') comment2.text = 'Comment text' - comment2.author_username = "Joe" + comment2.author_username = 'Joe' conversation.addComment(comment2) comment3 = createObject('plone.Comment') comment3.text = 'Comment text' - comment3.author_username = "Jack" + comment3.author_username = 'Jack' new_comment3_id = conversation.addComment(comment3) comment4 = createObject('plone.Comment') comment4.text = 'Comment text' - comment4.author_username = "Jack" + comment4.author_username = 'Jack' new_comment4_id = conversation.addComment(comment4) # check if all commentators are in the commentators list @@ -680,10 +681,10 @@ class ConversationEnabledForDexterityTypesTest(unittest.TestCase): ) if DEXTERITY: - interface.alsoProvides( - self.portal.doc1, - IDexterityContent - ) + interface.alsoProvides( + self.portal.doc1, + IDexterityContent + ) def _makeOne(self, *args, **kw): return self.portal.doc1.restrictedTraverse('@@conversation_view') @@ -839,16 +840,19 @@ class RepliesTest(unittest.TestCase): # Create the nested comment structure new_id_1 = replies.addComment(comment1) comment1 = self.portal.doc1.restrictedTraverse( - '++conversation++default/%s' % new_id_1) + '++conversation++default/{0}'.format(new_id_1) + ) replies_to_comment1 = IReplies(comment1) new_id_2 = replies.addComment(comment2) comment2 = self.portal.doc1.restrictedTraverse( - '++conversation++default/%s' % new_id_2) + '++conversation++default/{0}'.format(new_id_2) + ) replies_to_comment2 = IReplies(comment2) new_id_1_1 = replies_to_comment1.addComment(comment1_1) comment1_1 = self.portal.doc1.restrictedTraverse( - '++conversation++default/%s' % new_id_1_1) + '++conversation++default/{0}'.format(new_id_1_1) + ) replies_to_comment1_1 = IReplies(comment1_1) replies_to_comment1_1.addComment(comment1_1_1) diff --git a/plone/app/discussion/tests/test_events.py b/plone/app/discussion/tests/test_events.py index ae942e0..93cc219 100644 --- a/plone/app/discussion/tests/test_events.py +++ b/plone/app/discussion/tests/test_events.py @@ -1,11 +1,11 @@ # -*- coding: utf-8 -*- -from Zope2.App import zcml from plone.app.discussion.interfaces import IConversation from plone.app.discussion.interfaces import IReplies from plone.app.discussion.testing import PLONE_APP_DISCUSSION_INTEGRATION_TESTING # noqa from plone.app.testing import setRoles from plone.app.testing import TEST_USER_ID from zope.component import createObject +from Zope2.App import zcml import Products.Five import unittest2 as unittest @@ -86,7 +86,7 @@ class CommentEventsTest(unittest.TestCase): """ - zcml.load_config("configure.zcml", Products.Five) + zcml.load_config('configure.zcml', Products.Five) zcml.load_string(configure) def test_addEvent(self): @@ -139,7 +139,7 @@ class RepliesEventsTest(unittest.TestCase): """ - zcml.load_config("configure.zcml", Products.Five) + zcml.load_config('configure.zcml', Products.Five) zcml.load_string(configure) def test_addEvent(self): @@ -152,7 +152,8 @@ class RepliesEventsTest(unittest.TestCase): comment.text = 'Comment text' new_id = replies.addComment(comment) comment = self.document.restrictedTraverse( - '++conversation++default/%s' % new_id) + '++conversation++default/{0}'.format(new_id) + ) re_comment = createObject('plone.Comment') re_comment.text = 'Comment text' @@ -172,7 +173,8 @@ class RepliesEventsTest(unittest.TestCase): comment.text = 'Comment text' new_id = replies.addComment(comment) comment = self.portal.doc1.restrictedTraverse( - '++conversation++default/%s' % new_id) + '++conversation++default/{0}'.format(new_id) + ) re_comment = createObject('plone.Comment') re_comment.text = 'Comment text' diff --git a/plone/app/discussion/tests/test_indexers.py b/plone/app/discussion/tests/test_indexers.py index 37f1264..a7d0d96 100644 --- a/plone/app/discussion/tests/test_indexers.py +++ b/plone/app/discussion/tests/test_indexers.py @@ -1,7 +1,8 @@ +# -*- coding: utf-8 -*- """Test for the plone.app.discussion indexers """ -from DateTime import DateTime from datetime import datetime +from DateTime import DateTime from plone.app.discussion import catalog from plone.app.discussion.interfaces import IConversation from plone.app.discussion.testing import PLONE_APP_DISCUSSION_INTEGRATION_TESTING # noqa @@ -39,24 +40,24 @@ class ConversationIndexersTest(unittest.TestCase): comment1 = createObject('plone.Comment') comment1.text = 'Comment Text' - comment1.creator = "jim" - comment1.author_username = "Jim" + comment1.creator = 'jim' + comment1.author_username = 'Jim' comment1.creation_date = datetime(2006, 9, 17, 14, 18, 12) comment1.modification_date = datetime(2006, 9, 17, 14, 18, 12) self.new_id1 = conversation.addComment(comment1) comment2 = createObject('plone.Comment') comment2.text = 'Comment Text' - comment2.creator = "emma" - comment2.author_username = "Emma" + comment2.creator = 'emma' + comment2.author_username = 'Emma' comment2.creation_date = datetime(2007, 12, 13, 4, 18, 12) comment2.modification_date = datetime(2007, 12, 13, 4, 18, 12) self.new_id2 = conversation.addComment(comment2) comment3 = createObject('plone.Comment') comment3.text = 'Comment Text' - comment3.creator = "lukas" - comment3.author_username = "Lukas" + comment3.creator = 'lukas' + comment3.author_username = 'Lukas' comment3.creation_date = datetime(2009, 4, 12, 11, 12, 12) comment3.modification_date = datetime(2009, 4, 12, 11, 12, 12) self.new_id3 = conversation.addComment(comment3) @@ -118,8 +119,8 @@ class CommentIndexersTest(unittest.TestCase): comment = createObject('plone.Comment') comment.text = 'Lorem ipsum dolor sit amet.' - comment.creator = "jim" - comment.author_name = "Jim" + comment.creator = 'jim' + comment.author_name = 'Jim' comment.creation_date = datetime(2006, 9, 17, 14, 18, 12) comment.modification_date = datetime(2008, 3, 12, 7, 32, 52) @@ -149,7 +150,7 @@ class CommentIndexersTest(unittest.TestCase): self.conversation.addComment(comment_long) self.assertEqual( catalog.description(comment_long)(), - LONG_TEXT_CUT.replace("\n", " ") + LONG_TEXT_CUT.replace('\n', ' ') ) def test_dates(self): diff --git a/plone/app/discussion/tests/test_moderation_view.py b/plone/app/discussion/tests/test_moderation_view.py index aa5ace2..9233a8c 100644 --- a/plone/app/discussion/tests/test_moderation_view.py +++ b/plone/app/discussion/tests/test_moderation_view.py @@ -1,11 +1,11 @@ # -*- coding: utf-8 -*- -from Products.CMFCore.utils import getToolByName from plone.app.discussion.browser.moderation import BulkActionsView from plone.app.discussion.browser.moderation import View from plone.app.discussion.interfaces import IConversation from plone.app.discussion.testing import PLONE_APP_DISCUSSION_INTEGRATION_TESTING # noqa from plone.app.testing import setRoles from plone.app.testing import TEST_USER_ID +from Products.CMFCore.utils import getToolByName from zope.component import createObject import unittest @@ -75,7 +75,7 @@ class ModerationBulkActionsViewTest(unittest.TestCase): comment1.Creator = 'Jim' new_id_1 = conversation.addComment(comment1) self.comment1 = self.portal.doc1.restrictedTraverse( - '++conversation++default/%s' % new_id_1 + '++conversation++default/{0}'.format(new_id_1) ) comment2 = createObject('plone.Comment') comment2.title = 'Comment 2' @@ -83,7 +83,7 @@ class ModerationBulkActionsViewTest(unittest.TestCase): comment2.Creator = 'Joe' new_id_2 = conversation.addComment(comment2) self.comment2 = self.portal.doc1.restrictedTraverse( - '++conversation++default/%s' % new_id_2 + '++conversation++default/{0}'.format(new_id_2) ) comment3 = createObject('plone.Comment') comment3.title = 'Comment 3' @@ -91,7 +91,7 @@ class ModerationBulkActionsViewTest(unittest.TestCase): comment3.Creator = 'Emma' new_id_3 = conversation.addComment(comment3) self.comment3 = self.portal.doc1.restrictedTraverse( - '++conversation++default/%s' % new_id_3 + '++conversation++default/{0}'.format(new_id_3) ) self.conversation = conversation diff --git a/plone/app/discussion/tests/test_notifications.py b/plone/app/discussion/tests/test_notifications.py index fc0571b..28b5daa 100644 --- a/plone/app/discussion/tests/test_notifications.py +++ b/plone/app/discussion/tests/test_notifications.py @@ -1,13 +1,13 @@ # -*- coding: utf-8 -*- from Acquisition import aq_base +from plone.app.discussion.interfaces import IConversation +from plone.app.discussion.testing import PLONE_APP_DISCUSSION_INTEGRATION_TESTING # noqa +from plone.app.testing import setRoles +from plone.app.testing import TEST_USER_ID +from plone.registry.interfaces import IRegistry from Products.CMFPlone.interfaces import IMailSchema from Products.CMFPlone.tests.utils import MockMailHost from Products.MailHost.interfaces import IMailHost -from plone.app.discussion.interfaces import IConversation -from plone.app.discussion.testing import PLONE_APP_DISCUSSION_INTEGRATION_TESTING # noqa -from plone.app.testing import TEST_USER_ID -from plone.app.testing import setRoles -from plone.registry.interfaces import IRegistry from zope.component import createObject from zope.component import getSiteManager from zope.component import getUtility @@ -32,7 +32,7 @@ class TestUserNotificationUnit(unittest.TestCase): # We need to fake a valid mail setup registry = getUtility(IRegistry) mail_settings = registry.forInterface(IMailSchema, prefix='plone') - mail_settings.email_from_address = "portal@plone.test" + mail_settings.email_from_address = 'portal@plone.test' self.mailhost = self.portal.MailHost # Enable user notification setting registry = queryUtility(IRegistry) @@ -40,7 +40,7 @@ class TestUserNotificationUnit(unittest.TestCase): '.user_notification_enabled'] = True # Archetypes content types store data as utf-8 encoded strings # The missing u in front of a string is therefor not missing - self.portal.doc1.title = 'Kölle Alaaf' # What is "Fasching"? + self.portal.doc1.title = 'Kölle Alaaf' # What is 'Fasching'? self.conversation = IConversation(self.portal.doc1) def beforeTearDown(self): @@ -56,7 +56,7 @@ class TestUserNotificationUnit(unittest.TestCase): comment = createObject('plone.Comment') comment.text = 'Comment text' comment.user_notification = True - comment.author_email = "john@plone.test" + comment.author_email = 'john@plone.test' self.conversation.addComment(comment) comment = createObject('plone.Comment') comment.text = 'Comment text' @@ -75,11 +75,10 @@ class TestUserNotificationUnit(unittest.TestCase): # The output should be encoded in a reasonable manner # (in this case quoted-printable): self.assertTrue( - "A comment on \'K=C3=B6lle Alaaf\' has been posted here:" + 'A comment on "K=C3=B6lle Alaaf" has been posted here:' in msg) self.assertTrue( - "http://nohost/plone/d=\noc1/view#%s" - % comment_id + 'http://nohost/plone/d=\noc1/view#{0}'.format(comment_id) in msg) self.assertTrue('Comment text' in msg) self.assertFalse('Approve comment' in msg) @@ -94,7 +93,7 @@ class TestUserNotificationUnit(unittest.TestCase): comment = createObject('plone.Comment') comment.text = 'Comment text' comment.user_notification = True - comment.author_email = "john@plone.test" + comment.author_email = 'john@plone.test' self.conversation.addComment(comment) comment = createObject('plone.Comment') comment.text = 'Comment text' @@ -124,7 +123,7 @@ class TestUserNotificationUnit(unittest.TestCase): comment = createObject('plone.Comment') comment.text = 'Comment text' comment.user_notification = True - comment.author_email = "john@plone.test" + comment.author_email = 'john@plone.test' self.conversation.addComment(comment) comment = createObject('plone.Comment') comment.text = 'Comment text' @@ -139,12 +138,12 @@ class TestUserNotificationUnit(unittest.TestCase): comment = createObject('plone.Comment') comment.text = 'Comment text' comment.user_notification = True - comment.author_email = "john@plone.test" + comment.author_email = 'john@plone.test' self.conversation.addComment(comment) comment = createObject('plone.Comment') comment.text = 'Comment text' comment.user_notification = True - comment.author_email = "john@plone.test" + comment.author_email = 'john@plone.test' self.conversation.addComment(comment) @@ -171,7 +170,7 @@ class TestModeratorNotificationUnit(unittest.TestCase): # We need to fake a valid mail setup registry = getUtility(IRegistry) mail_settings = registry.forInterface(IMailSchema, prefix='plone') - mail_settings.email_from_address = "portal@plone.test" + mail_settings.email_from_address = 'portal@plone.test' self.mailhost = self.portal.MailHost # Enable comment moderation self.portal.portal_types['Document'].allow_discussion = True @@ -187,7 +186,7 @@ class TestModeratorNotificationUnit(unittest.TestCase): ] = True # Archetypes content types store data as utf-8 encoded strings # The missing u in front of a string is therefor not missing - self.portal.doc1.title = 'Kölle Alaaf' # What is "Fasching"? + self.portal.doc1.title = 'Kölle Alaaf' # What is 'Fasching'? self.conversation = IConversation(self.portal.doc1) def beforeTearDown(self): @@ -216,21 +215,28 @@ class TestModeratorNotificationUnit(unittest.TestCase): # The output should be encoded in a reasonable manner # (in this case quoted-printable): self.assertTrue( - "A comment on \'K=C3=B6lle Alaaf\' has been posted here:" + 'A comment on "K=C3=B6lle Alaaf" has been posted here:' in msg) - self.assertTrue( - "http://nohost/plone/d=\noc1/view#%s" - % comment_id - in msg) - self.assertTrue('Comment text' in msg) - self.assertTrue( - 'Approve comment:\nhttp://nohost/plone/doc1/' + - '++conversation++default/%s/@@moderat=\ne-publish-comment' - % comment_id in msg) - self.assertTrue( - 'Delete comment:\nhttp://nohost/plone/doc1/' + - '++conversation++default/%s/@@moderat=\ne-delete-comment' - % comment_id in msg) + self.assertIn( + 'http://nohost/plone/d=\noc1/view#{0}'.format(comment_id), + msg + ) + self.assertIn( + 'Comment text', + msg + ) + text = 'Approve comment:\nhttp://nohost/plone/doc1/' \ + '++conversation++default/{0}/@@moderat=\ne-publish-comment' + self.assertIn( + text.format(comment_id), + msg + ) + text = 'Delete comment:\nhttp://nohost/plone/doc1/' \ + '++conversation++default/{0}/@@moderat=\ne-delete-comment' + self.assertIn( + text.format(comment_id), + msg + ) def test_notify_moderator_specific_address(self): # A moderator email address can be specified in the control panel. diff --git a/plone/app/discussion/tests/test_robot.py b/plone/app/discussion/tests/test_robot.py index 80cee95..7163326 100644 --- a/plone/app/discussion/tests/test_robot.py +++ b/plone/app/discussion/tests/test_robot.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- from plone.app.discussion.testing import PLONE_APP_DISCUSSION_ROBOT_TESTING from plone.app.testing import ROBOT_TEST_LEVEL from plone.testing import layered diff --git a/plone/app/discussion/tests/test_workflow.py b/plone/app/discussion/tests/test_workflow.py index d8dcff3..2597593 100644 --- a/plone/app/discussion/tests/test_workflow.py +++ b/plone/app/discussion/tests/test_workflow.py @@ -2,8 +2,6 @@ """Test plone.app.discussion workflow and permissions. """ from AccessControl import Unauthorized -from Products.CMFCore.permissions import View -from Products.CMFCore.utils import _checkPermission as checkPerm from plone.app.discussion.interfaces import IConversation from plone.app.discussion.interfaces import IDiscussionLayer from plone.app.discussion.testing import PLONE_APP_DISCUSSION_INTEGRATION_TESTING # noqa @@ -11,6 +9,8 @@ from plone.app.testing import login from plone.app.testing import logout from plone.app.testing import setRoles from plone.app.testing import TEST_USER_ID +from Products.CMFCore.permissions import View +from Products.CMFCore.utils import _checkPermission as checkPerm from zope.component import createObject from zope.interface import alsoProvides @@ -87,7 +87,7 @@ class PermissionsSetupTest(unittest.TestCase): plone.app.discussion assigns this permission to 'Authenticated' as well to emulate the behavior of the old commenting system. """ - ReplyToItemPerm = "Reply to item" + ReplyToItemPerm = 'Reply to item' # should be allowed as Member self.assertTrue(self.checkPermission(ReplyToItemPerm, self.portal)) # should be allowed as Authenticated @@ -126,7 +126,7 @@ class CommentOneStateWorkflowTest(unittest.TestCase): cid = conversation.addComment(comment) self.comment = self.folder.doc1.restrictedTraverse( - '++conversation++default/%s' % cid + '++conversation++default/{0}'.format(cid) ) self.portal.acl_users._doAddUser('member', 'secret', ['Member'], []) @@ -192,7 +192,8 @@ class CommentReviewWorkflowTest(unittest.TestCase): comment.text = 'Comment text' comment_id = conversation.addComment(comment) comment = self.portal.doc1.restrictedTraverse( - '++conversation++default/%s' % comment_id) + '++conversation++default/{0}'.format(comment_id) + ) self.conversation = conversation self.comment_id = comment_id diff --git a/plone/app/discussion/tool.py b/plone/app/discussion/tool.py index cc8e63d..f581274 100644 --- a/plone/app/discussion/tool.py +++ b/plone/app/discussion/tool.py @@ -1,14 +1,15 @@ +# -*- coding: utf-8 -*- """The portal_discussion tool, usually accessed via queryUtility(ICommentingTool). The default implementation delegates to the standard portal_catalog for indexing comments. BBB support for the old portal_discussion is provided in the bbb package. """ -from OFS.SimpleItem import SimpleItem -from Products.CMFCore.utils import UniqueObject -from Products.CMFCore.utils import getToolByName from interfaces import IComment from interfaces import ICommentingTool +from OFS.SimpleItem import SimpleItem +from Products.CMFCore.utils import getToolByName +from Products.CMFCore.utils import UniqueObject from zope import interface from zope.component import queryUtility diff --git a/plone/app/discussion/upgrades.py b/plone/app/discussion/upgrades.py index f19bd30..1019dc0 100644 --- a/plone/app/discussion/upgrades.py +++ b/plone/app/discussion/upgrades.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- from plone.app.discussion.interfaces import IDiscussionSettings from plone.registry.interfaces import IRegistry from zope.component import getUtility