Skip to content

Commit

Permalink
Cleanup: PEP8 et al., security/zca via decorators, ...
Browse files Browse the repository at this point in the history
  • Loading branch information
jensens committed Jul 27, 2015
1 parent bcc7404 commit 3702159
Show file tree
Hide file tree
Showing 14 changed files with 293 additions and 225 deletions.
3 changes: 2 additions & 1 deletion CHANGES.txt → CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ Changelog
4.1.3 (unreleased)
------------------

- Nothing changed yet.
- Cleanup: PEP8 et al., security/zca via decorators, ...
[jensens]


4.1.2 (2015-06-03)
Expand Down
27 changes: 12 additions & 15 deletions Products/CMFDynamicViewFTI/__init__.py
Original file line number Diff line number Diff line change
@@ -1,36 +1,33 @@
# -*- coding: utf-8 -*-

# $Id$

from Products.CMFCore import utils as cmf_utils
from Products.CMFCore.permissions import AddPortalContent
from Products.CMFCore.permissions import AddPortalFolders
from Products.CMFDynamicViewFTI.fti import DynamicViewTypeInformation
from Products.CMFDynamicViewFTI import content_for_tests

from Products.CMFDynamicViewFTI.fti import DynamicViewTypeInformation


def initialize(context):
# (DynamicViewTypeInformation factory is created from ZCML)
cmf_utils.registerIcon(
DynamicViewTypeInformation, 'images/typeinfo.gif', globals()
DynamicViewTypeInformation,
'images/typeinfo.gif',
globals()
)

context.registerClass(
content_for_tests.DynFolder,
permission=AddPortalFolders,
constructors=(('addDynFolder',
content_for_tests.addDynFolder),
),
constructors=(
('addDynFolder', content_for_tests.addDynFolder),
),
icon='images/typeinfo.gif'
)
)

context.registerClass(
content_for_tests.DynDocument,
permission=AddPortalContent,
constructors=(('addDynDocument',
content_for_tests.addDynDocument),
),
constructors=(
('addDynDocument', content_for_tests.addDynDocument),
),
icon='images/typeinfo.gif'
)
return
)
101 changes: 53 additions & 48 deletions Products/CMFDynamicViewFTI/browserdefault.py
Original file line number Diff line number Diff line change
@@ -1,31 +1,29 @@
# -*- coding: utf-8 -*-
"""Mixin class for selectable views
This module contains a mixin-class to support selecting default layout
templates and/or default pages (in the style of default_page/index_html).
The implementation extends TemplateMixin from Archetypes, and implements
the ISelectableBrowserDefault interface from CMFPlone.
"""

from zope.interface import implements
import zope.component
from zope.browsermenu.interfaces import IBrowserMenu

from ExtensionClass import Base
from AccessControl import ClassSecurityInfo
from App.class_init import InitializeClass
from Acquisition import aq_base
from Products.CMFCore.utils import getToolByName
from App.class_init import InitializeClass
from ExtensionClass import Base
from Products.CMFCore.permissions import View

from Products.CMFDynamicViewFTI.permissions import ModifyViewTemplate
from Products.CMFCore.utils import getToolByName
from Products.CMFDynamicViewFTI.fti import DynamicViewTypeInformation

from Products.CMFDynamicViewFTI.interfaces import ISelectableBrowserDefault
from Products.CMFDynamicViewFTI.permissions import ModifyViewTemplate
from zope.browsermenu.interfaces import IBrowserMenu
from zope.interface import implementer
import zope.component

_marker = object()
fti_meta_type = DynamicViewTypeInformation.meta_type


@implementer(ISelectableBrowserDefault)
class BrowserDefaultMixin(Base):
"""Mixin class for content types using the dynamic view FTI
Expand All @@ -35,7 +33,6 @@ class BrowserDefaultMixin(Base):
Note: folderish content types should overwrite HEAD like ATContentTypes
"""
implements(ISelectableBrowserDefault)

_at_fti_meta_type = fti_meta_type
aliases = {
Expand All @@ -53,8 +50,7 @@ class BrowserDefaultMixin(Base):

security = ClassSecurityInfo()

security.declareProtected(View, 'defaultView')

@security.protected(View)
def defaultView(self, request=None):
"""
Get the actual view to use. If a default page is set, its id will
Expand All @@ -66,8 +62,7 @@ def defaultView(self, request=None):
else:
return fti.defaultView(self)

security.declareProtected(View, '__call__')

@security.protected(View)
def __call__(self):
"""
Resolve and return the selected view template applied to the object.
Expand All @@ -76,8 +71,7 @@ def __call__(self):
template = self.unrestrictedTraverse(self.getLayout())
return template()

security.declareProtected(View, 'getDefaultPage')

@security.protected(View)
def getDefaultPage(self):
"""Return the id of the default page, or None if none is set.
Expand All @@ -93,8 +87,7 @@ def getDefaultPage(self):
else:
return fti.getDefaultPage(self, check_exists=True)

security.declareProtected(View, 'getLayout')

@security.protected(View)
def getLayout(self, **kw):
"""Get the selected view method.
Expand All @@ -106,8 +99,7 @@ def getLayout(self, **kw):
else:
return fti.getViewMethod(self)

security.declarePublic('canSetDefaultPage')

@security.public
def canSetDefaultPage(self):
"""Check if the user has permission to select a default page on this
(folderish) item, and the item is folderish.
Expand All @@ -118,16 +110,16 @@ def canSetDefaultPage(self):
member = mtool.getAuthenticatedMember()
return member.has_permission(ModifyViewTemplate, self)

security.declareProtected(ModifyViewTemplate, 'setDefaultPage')

@security.protected(ModifyViewTemplate)
def setDefaultPage(self, objectId):
"""Set the default page to display in this (folderish) object.
The objectId must be a value found in self.objectIds() (i.e. a contained
object). This object will be displayed as the default_page/index_html object
of this (folderish) object. This will override the current layout
template returned by getLayout(). Pass None for objectId to turn off
the default page and return to using the selected layout template.
The objectId must be a value found in self.objectIds() (i.e. a
contained object). This object will be displayed as the
default_page/index_html object of this (folderish) object. This will
override the current layout template returned by getLayout().
Pass None for objectId to turn off the default page and return to
using the selected layout template.
"""
new_page = old_page = None
if objectId is not None:
Expand Down Expand Up @@ -155,18 +147,19 @@ def setDefaultPage(self, objectId):
if old_page is not None:
old_page.reindexObject(['is_default_page'])

security.declareProtected(ModifyViewTemplate, 'setLayout')

@security.protected(ModifyViewTemplate)
def setLayout(self, layout):
"""Set the layout as the current view.
'layout' should be one of the list returned by getAvailableLayouts(), but it
is not enforced. If a default page has been set with setDefaultPage(), it is
turned off by calling setDefaultPage(None).
'layout' should be one of the list returned by getAvailableLayouts(),
but it is not enforced. If a default page has been set with
setDefaultPage(), it is turned off by calling setDefaultPage(None).
"""
if not (layout and isinstance(layout, basestring)):
raise ValueError("layout must be a non empty string, got %s(%s)" %
(layout, type(layout)))
raise ValueError(
"layout must be a non empty string, got %s(%s)" %
(layout, type(layout))
)

defaultPage = self.getDefaultPage()
if defaultPage is None and layout == self.getLayout():
Expand All @@ -179,24 +172,24 @@ def setLayout(self, layout):
# Archetypes remains? clean up
old = self.layout
if old and not isinstance(old, basestring):
raise RuntimeError("layout attribute exists on %s and is"
"no string: %s" % (self, type(old)))
raise RuntimeError(
"layout attribute exists on %s and is no string: %s" %
(self, type(old))
)
delattr(self, 'layout')

self.manage_addProperty('layout', layout, 'string')

self.setDefaultPage(None)

security.declareProtected(View, 'getDefaultLayout')

@security.protected(View)
def getDefaultLayout(self):
"""Get the default layout method.
"""
fti = self.getTypeInfo()
if fti is None:
return "base_view" # XXX
else:
return fti.getDefaultViewMethod(self)
return fti.getDefaultViewMethod(self)

security.declarePublic('canSetLayout')

Expand All @@ -207,8 +200,7 @@ def canSetLayout(self):
member = mtool.getAuthenticatedMember()
return member.has_permission(ModifyViewTemplate, self)

security.declareProtected(View, 'getAvailableLayouts')

@security.protected(View)
def getAvailableLayouts(self):
"""Get the layouts registered for this object from its FTI.
"""
Expand All @@ -218,13 +210,17 @@ def getAvailableLayouts(self):
result = []
method_ids = fti.getAvailableViewMethods(self)
for mid in method_ids:
view = zope.component.queryMultiAdapter((self, self.REQUEST),
zope.interface.Interface,
name=mid)
view = zope.component.queryMultiAdapter(
(self, self.REQUEST),
zope.interface.Interface,
name=mid
)

if view is not None:
menu = zope.component.getUtility(
IBrowserMenu, 'plone_displayviews')
IBrowserMenu,
'plone_displayviews'
)
item = menu.getMenuItemByAction(self, self.REQUEST, mid)
title = item and item.title or mid
result.append((mid, title))
Expand All @@ -243,12 +239,21 @@ def getAvailableLayouts(self):


def check_default_page(obj, event):
"""event subscriber, unset default page if target no longer exists
used by default for zope.container.interfaces.IContainerModifiedEvent
"""
container = obj
default_page_id = container.getProperty('default_page', '')
if default_page_id and not (default_page_id in container.objectIds()):
ISelectableBrowserDefault(container).setDefaultPage(None)


def rename_default_page(obj, event):
"""event subscriber, rename default page if targte was renamed
used by default for zope.lifecycleevent.interfaces.IObjectMovedEvent
"""
newParent = event.newParent
if newParent != event.oldParent:
return
Expand Down
8 changes: 2 additions & 6 deletions Products/CMFDynamicViewFTI/content_for_tests.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
from AccessControl.SecurityInfo import ClassSecurityInfo
from Products.CMFCore.permissions import AddPortalContent
from Products.CMFCore.permissions import AddPortalFolders
# -*- coding: utf-8 -*-
from Products.CMFCore.PortalFolder import PortalFolder
from Products.CMFCore.PortalContent import PortalContent
from App.class_init import InitializeClass

from browserdefault import BrowserDefaultMixin
from Products.CMFDynamicViewFTI.browserdefault import BrowserDefaultMixin


class DynFolder(PortalFolder, BrowserDefaultMixin):
Expand Down
Loading

0 comments on commit 3702159

Please sign in to comment.