Skip to content

Commit

Permalink
Merge pull request #43 from plone/plone-base-overhaul
Browse files Browse the repository at this point in the history
Plone base overhaul
  • Loading branch information
jensens authored May 1, 2022
2 parents a1a0411 + 563121b commit 1acc6af
Show file tree
Hide file tree
Showing 16 changed files with 238 additions and 244 deletions.
2 changes: 2 additions & 0 deletions news/43.breaking
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Drop Python 2 and Plone 5.2, use plone.base.
[jensens]
3 changes: 1 addition & 2 deletions plone/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
# -*- coding: utf-8 -*-
__import__('pkg_resources').declare_namespace(__name__)
__import__("pkg_resources").declare_namespace(__name__)
3 changes: 1 addition & 2 deletions plone/app/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
# -*- coding: utf-8 -*-
__import__('pkg_resources').declare_namespace(__name__)
__import__("pkg_resources").declare_namespace(__name__)
1 change: 0 additions & 1 deletion plone/app/contentlisting/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@
# -*- coding: utf-8 -*-
23 changes: 10 additions & 13 deletions plone/app/contentlisting/browser.py
Original file line number Diff line number Diff line change
@@ -1,44 +1,41 @@
# -*- coding: utf-8 -*-
from plone.app.contentlisting.interfaces import IContentListing
from Products.CMFCore.utils import getToolByName
from zope.publisher.browser import BrowserView


class FolderListing(BrowserView):

def __call__(self, batch=False, b_size=20, b_start=0, orphan=0, **kw):
query = {}
query.update(kw)

query['path'] = {
'query': '/'.join(self.context.getPhysicalPath()),
'depth': 1,
query["path"] = {
"query": "/".join(self.context.getPhysicalPath()),
"depth": 1,
}

# if we don't have asked explicitly for other sorting, we'll want
# it by position in parent
if 'sort_on' not in query:
query['sort_on'] = 'getObjPositionInParent'
if "sort_on" not in query:
query["sort_on"] = "getObjPositionInParent"

# Provide batching hints to the catalog
if batch:
query['b_start'] = b_start
query['b_size'] = b_size + orphan
query["b_start"] = b_start
query["b_size"] = b_size + orphan

catalog = getToolByName(self.context, 'portal_catalog')
catalog = getToolByName(self.context, "portal_catalog")
results = catalog(query)
return IContentListing(results)


class ContentListingCollection(BrowserView):

def __call__(self, batch=False, b_size=20, b_start=0, **kw):

if 'orphan' in kw:
if "orphan" in kw:
# At the moment, orphan keyword is not supported by
# plone.app.contenttypes Collection behavior, nor by
# plone.app.querystring's querybuilder.
del kw['orphan']
del kw["orphan"]

res = self.context.results(
batch=batch,
Expand Down
46 changes: 22 additions & 24 deletions plone/app/contentlisting/catalog.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from Acquisition import aq_base
from plone.app.contentlisting.contentlisting import BaseContentListingObject
from plone.app.contentlisting.interfaces import IContentListingObject
Expand Down Expand Up @@ -28,10 +27,12 @@ def __init__(self, brain):
self.request = getRequest()

def __repr__(self):
return '<plone.app.contentlisting.catalog.'\
'CatalogContentListingObject instance at {0}>'.format(
return (
"<plone.app.contentlisting.catalog."
"CatalogContentListingObject instance at {}>".format(
self.getPath(),
)
)

__str__ = __repr__

Expand All @@ -40,7 +41,7 @@ def __getattr__(self, name):
underlying objects without knowing the names of all attributes.
"""

if name.startswith('_'):
if name.startswith("_"):
raise AttributeError(name)
brain_name = getattr(aq_base(self._brain), name, missing)
if brain_name is not missing:
Expand All @@ -56,8 +57,7 @@ def getDataOrigin(self):
# the real object.
if self._cached_realobject is not None:
return self._cached_realobject
else:
return self._brain
return self._brain

def getObject(self):
# Get the real, underlying object.
Expand All @@ -82,9 +82,9 @@ def getURL(self, relative=False):

def uuid(self):
# content objects might have UID and might not.
brain_uid = getattr(aq_base(self._brain), 'UID', None)
brain_uid = getattr(aq_base(self._brain), "UID", None)
if brain_uid is not None:
return self._brain.UID
return brain_uid
uuid = IUUID(self.getObject(), None)
if uuid is not None:
return uuid
Expand All @@ -106,8 +106,8 @@ def Description(self):

def CroppedDescription(self):
registry = queryUtility(IRegistry)
length = registry.get('plone.search_results_description_length')
plone_view = getMultiAdapter((self, self.request), name='plone')
length = registry.get("plone.search_results_description_length")
plone_view = getMultiAdapter((self, self.request), name="plone")
return plone_view.cropText(self.Description(), length)

def Type(self):
Expand All @@ -120,29 +120,28 @@ def listCreators(self):
return self._brain.listCreators

def getUserData(self, username):
_usercache = self.request.get('usercache', None)
_usercache = self.request.get("usercache", None)
if _usercache is None:
self.request.set('usercache', {})
self.request.set("usercache", {})
_usercache = {}
userdata = _usercache.get(username, None)
if userdata is None:
membershiptool = getToolByName(self._brain, 'portal_membership')
membershiptool = getToolByName(self._brain, "portal_membership")
userdata = membershiptool.getMemberInfo(self._brain.Creator)
if not userdata:
userdata = {
'username': username,
'description': '',
'language': '',
'home_page': '/HOMEPAGEURL',
'location': '',
'fullname': username,
"username": username,
"description": "",
"language": "",
"home_page": "/HOMEPAGEURL",
"location": "",
"fullname": username,
}
self.request.usercache[username] = userdata
return userdata

def Creator(self):
username = self._brain.Creator
return username
return self._brain.Creator

def Author(self):
return self.getUserData(self.Creator())
Expand Down Expand Up @@ -182,11 +181,10 @@ def Identifier(self):

def Language(self):
# The language of the content.
brain_language = getattr(aq_base(self._brain), 'Language', None)
brain_language = getattr(aq_base(self._brain), "Language", None)
if brain_language is not None:
return self._brain.Language
else:
return self.getObject().Language()
return self.getObject().Language()

def Rights(self):
raise NotImplementedError
2 changes: 1 addition & 1 deletion plone/app/contentlisting/configure.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

<adapter
factory=".contentlisting.ContentListing"
for="Products.CMFPlone.PloneBatch.Batch"
for="plone.base.batch.Batch"
/>

<adapter
Expand Down
40 changes: 19 additions & 21 deletions plone/app/contentlisting/contentlisting.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
# -*- coding: utf-8 -*-

from Acquisition import aq_base
from plone.app.contentlisting.interfaces import IContentListing
from plone.app.contentlisting.interfaces import IContentListingObject
from plone.app.layout.navigation.root import getNavigationRoot
from plone.base.interfaces import INavigationSchema
from plone.i18n.normalizer.interfaces import IIDNormalizer
from plone.registry.interfaces import IRegistry
from Products.CMFCore.utils import getToolByName
from Products.CMFPlone.interfaces import INavigationSchema
from Products.MimetypesRegistry.MimeTypeItem import guess_icon_path
from zope.component import getUtility
from zope.component import queryUtility
Expand All @@ -17,18 +15,18 @@


@implementer(IContentListing)
class ContentListing(object):
class ContentListing:
"""An IContentListing implementation based on sequences of objects."""

def __init__(self, sequence):
self._basesequence = sequence

def __getitem__(self, index):
"""`x.__getitem__(index)` <==> `x[index]`
"""
"""`x.__getitem__(index)` <==> `x[index]`"""
if isinstance(index, slice):
return IContentListing(
self._basesequence[index.start:index.stop:index.step])
self._basesequence[index.start : index.stop : index.step]
)
return IContentListingObject(self._basesequence[index])

def __len__(self):
Expand All @@ -40,7 +38,7 @@ def __len__(self):
@property
def actual_result_count(self):
bs = self._basesequence
return getattr(bs, 'actual_result_count', len(bs))
return getattr(bs, "actual_result_count", len(bs))

def __iter__(self):
"""Let the sequence be iterable and whenever we look at an object, it
Expand Down Expand Up @@ -106,7 +104,7 @@ def __getslice__(self, i, j):
return IContentListing(self._basesequence[i:j])


class BaseContentListingObject(object):
class BaseContentListingObject:
"""A baseclass for the different types of contentlistingobjects.
To avoid duplication of the stuff that is not implementation-specific.
Expand All @@ -123,39 +121,39 @@ def __hash__(self):
def ContentTypeClass(self):
# A normalised type name that identifies the object in listings.
# Used for CSS styling.
return 'contenttype-' + queryUtility(IIDNormalizer).normalize(
return "contenttype-" + queryUtility(IIDNormalizer).normalize(
self.PortalType(),
)

def ReviewStateClass(self):
# A normalised review state string for CSS styling use in listings.
return 'state-' + queryUtility(IIDNormalizer).normalize(
return "state-" + queryUtility(IIDNormalizer).normalize(
self.review_state(),
)

def appendViewAction(self):
# Decide whether to produce a string /view to append to links in
# results listings.
registry = getUtility(IRegistry)
types = registry.get('plone.types_use_view_action_in_listings', [])
types = registry.get("plone.types_use_view_action_in_listings", [])
if self.portal_type in types:
return '/view'
return ''
return "/view"
return ""

def isVisibleInNav(self):
# True, if this item should be visible in navigation trees.
exclude_from_nav_attr = getattr(self, 'exclude_from_nav', None)
exclude_from_nav_attr = getattr(self, "exclude_from_nav", None)
if exclude_from_nav_attr is not None and (
self.exclude_from_nav()
if callable(self.exclude_from_nav)
else self.exclude_from_nav
self.exclude_from_nav()
if callable(self.exclude_from_nav)
else self.exclude_from_nav
):
return False

registry = getUtility(IRegistry)
navigation_settings = registry.forInterface(
INavigationSchema,
prefix='plone',
prefix="plone",
)
if self.portal_type not in navigation_settings.displayed_types:
return False
Expand All @@ -166,12 +164,12 @@ def MimeTypeIcon(self):
mimeicon = None
navroot = getNavigationRoot(self._brain)
contenttype = aq_base(
getattr(self._brain, 'mime_type', None),
getattr(self._brain, "mime_type", None),
)
if contenttype:
mtt = getToolByName(
self._brain,
'mimetypes_registry',
"mimetypes_registry",
)
ctype = mtt.lookup(contenttype)
if ctype:
Expand Down
3 changes: 1 addition & 2 deletions plone/app/contentlisting/interfaces.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from Products.CMFCore.interfaces import IDublinCore
from zope.interface.common.sequence import IReadSequence

Expand Down Expand Up @@ -88,6 +87,6 @@ def ContentTypeClass():
"""

def MimeTypeIcon():
""" return mimetype icon from mimetype registry if contenttype is
"""return mimetype icon from mimetype registry if contenttype is
File else None
"""
Loading

0 comments on commit 1acc6af

Please sign in to comment.