From 7a9be5d79b9f268fa8c0efd95f4d0e0429536483 Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Tue, 24 Sep 2024 11:47:59 +0200 Subject: [PATCH] more Python3 fixes (browser, resource) --- loops/browser/common.py | 48 +++++++------------------ loops/resource.py | 79 +++++++++++++++-------------------------- pyproject.toml | 1 + 3 files changed, 42 insertions(+), 86 deletions(-) diff --git a/loops/browser/common.py b/loops/browser/common.py index 0850b05..61e729d 100755 --- a/loops/browser/common.py +++ b/loops/browser/common.py @@ -1,47 +1,28 @@ -# -# Copyright (c) 2016 Helmut Merz helmutm@cy55.de -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# +# loops.browser.common -""" -Common base class for loops browser view classes. +""" Common base class for loops browser view classes. """ -from cgi import parse_qsl #import mimetypes # use more specific assignments from cybertools.text from datetime import date, datetime from logging import getLogger import re from time import strptime -from urllib import urlencode -from urlparse import parse_qs +from urllib.parse import parse_qs, parse_qsl, urlencode from zope import component -from zope.app.form.browser.interfaces import ITerms -from zope.app.i18n.interfaces import ITranslationDomain -from zope.app.security.interfaces import IAuthentication, IUnauthenticatedPrincipal -from zope.app.pagetemplate import ViewPageTemplateFile -from zope.app.security.interfaces import IUnauthenticatedPrincipal -from zope.app.security.interfaces import PrincipalLookupError +from zope.authentication.interfaces import IAuthentication, IUnauthenticatedPrincipal +from zope.authentication.interfaces import IUnauthenticatedPrincipal +from zope.authentication.interfaces import PrincipalLookupError +from zope.browser.interfaces import ITerms +from zope.browserpage import ViewPageTemplateFile from zope.cachedescriptors.property import Lazy from zope.dottedname.resolve import resolve from zope.dublincore.interfaces import IZopeDublinCore from zope.formlib import form from zope.formlib.form import FormFields from zope.formlib.namedtemplate import NamedTemplate -from zope.interface import Interface, implements +from zope.i18n.interfaces import ITranslationDomain +from zope.interface import Interface, implementer from zope.proxy import removeAllProxies from zope.publisher.browser import applySkin from zope.publisher.interfaces.browser import IBrowserSkinType, IBrowserView @@ -1092,13 +1073,12 @@ class LoggedIn(object): # vocabulary stuff +@implementer(ITerms) class SimpleTerms(object): """ Provide the ITerms interface, e.g. for usage in selection lists. """ - implements(ITerms) - def __init__(self, source, request): # the source parameter is a list of tuples (token, title). self.source = source @@ -1113,13 +1093,12 @@ class SimpleTerms(object): return (token, self.terms[token]) +@implementer(ITerms) class LoopsTerms(object): """ Provide the ITerms interface, e.g. for usage in selection lists. """ - implements(ITerms) - def __init__(self, source, request): # the source parameter is a view or adapter of a real context object: self.source = source @@ -1141,12 +1120,11 @@ class LoopsTerms(object): return self.loopsRoot.loopsTraverse(token) +@implementer(ITerms) class InterfaceTerms(object): """ Provide the ITerms interface for source list of interfaces. """ - implements(ITerms) - def __init__(self, source, request): self.source = source self.request = request diff --git a/loops/resource.py b/loops/resource.py index 2da6029..0bf6293 100644 --- a/loops/resource.py +++ b/loops/resource.py @@ -1,33 +1,16 @@ -# -# Copyright (c) 2016 Helmut Merz helmutm@cy55.de -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# +# loops.resource -""" -Definition of the Concept class. +""" Definition of the Concept class. """ -from cStringIO import StringIO +from io import BytesIO from logging import getLogger from persistent import Persistent from zope import component, schema -from zope.app.container.btree import BTreeContainer -from zope.app.container.contained import Contained from zope.app.file.image import Image -from zope.app.security.interfaces import IAuthentication +from zope.authentication.interfaces import IAuthentication +from zope.container.btree import BTreeContainer +from zope.container.contained import Contained from zope.contenttype import guess_content_type from zope.filerepresentation.interfaces import IReadFile, IWriteFile from zope.cachedescriptors.property import Lazy @@ -35,7 +18,7 @@ from zope.component import adapts from zope.dublincore.interfaces import IZopeDublinCore from zope.filerepresentation.interfaces import IFileFactory from zope.i18nmessageid import MessageFactory -from zope.interface import implements +from zope.interface import implementer from zope.size.interfaces import ISized from zope.security.proxy import removeSecurityProxy from zope.traversing.api import getName, getParent @@ -69,10 +52,9 @@ logger = getLogger('loops.resource') _ = MessageFactory('loops') +@implementer(IResourceManager, ILoopsContained) class ResourceManager(BTreeContainer): - implements(IResourceManager, ILoopsContained) - def getLoopsRoot(self): return getParent(self) @@ -86,13 +68,11 @@ class ResourceManager(BTreeContainer): return Jeep() +@implementer(IBaseResource, IResource, IResourceManagerContained, IRelatable, ISized) class Resource(Image, Contained): # TODO: remove dependency on Image - implements(IBaseResource, IResource, IResourceManagerContained, - IRelatable, ISized) - proxyInterface = IMediaAssetView # obsolete! storageName = None @@ -149,7 +129,7 @@ class Resource(Image, Contained): self.resourceType = value def _setData(self, data): - dataFile = StringIO(data) # let File tear it into pieces + dataFile = BytesIO(data) # let File tear it into pieces super(Resource, self)._setData(dataFile) if not self.contentType: self.guessContentType(data) @@ -158,7 +138,7 @@ class Resource(Image, Contained): def guessContentType(self, data): # probably obsolete, use zope.contenttype.guess_content_type() - if not isinstance(data, str): # seems to be a file object + if not isinstance(data, (bytes, str)): # seems to be a file object data = data.read(20) if data.startswith('%PDF'): self.contentType = 'application/pdf' @@ -305,10 +285,9 @@ class Resource(Image, Contained): # Document and MediaAsset are legacy classes, will become obsolete +@implementer(IDocument) class Document(Resource): - implements(IDocument) - proxyInterface = IDocumentView def __init__(self, title=u''): @@ -323,19 +302,19 @@ class Document(Resource): data = property(getData, setData) +@implementer(IMediaAsset) class MediaAsset(Resource): - implements(IMediaAsset) + pass # type adapters +@implementer(IFile) class FileAdapter(ResourceAdapterBase): """ A type adapter for providing file functionality for resources. """ - implements(IFile) - _contextAttributes = list(IFile) + list(IBaseResource) _adapterAttributes = ResourceAdapterBase._adapterAttributes + ('data',) @@ -361,10 +340,9 @@ class FileAdapter(ResourceAdapterBase): storageName = property(getStorageName, setStorageName) +@implementer(IExternalFile) class ExternalFileAdapter(FileAdapter): - implements(IExternalFile) - _adapterAttributes = (FileAdapter._adapterAttributes + ('storageParams', 'externalAddress', 'uniqueAddress', 'processingErrors')) @@ -458,19 +436,19 @@ class DocumentAdapter(ResourceAdapterBase): data = property(getData, setData) +@implementer(ITextDocument) class TextDocumentAdapter(DocumentAdapter): """ A type adapter for providing text document functionality for resources. """ - implements(ITextDocument) _contextAttributes = list(ITextDocument) + list(IBaseResource) +@implementer(INote) class NoteAdapter(DocumentAdapter): """ A note is a short text document with an associated link. """ - implements(INote) _contextAttributes = list(INote) + list(IBaseResource) @property @@ -480,9 +458,9 @@ class NoteAdapter(DocumentAdapter): # other adapters +@implementer(IWriteFile) class DocumentWriteFileAdapter(object): - implements(IWriteFile) adapts(IResource) def __init__(self, context): @@ -502,9 +480,9 @@ class DocumentWriteFileAdapter(object): notify(ObjectModifiedEvent(self.context, Attributes(IResource, 'data'))) +@implementer(IReadFile) class DocumentReadFileAdapter(object): - implements(IReadFile) adapts(IResource) def __init__(self, context): @@ -525,9 +503,9 @@ class DocumentReadFileAdapter(object): return len(self.data) +@implementer(IFileFactory) class ExternalFileFactory(object): - implements(IFileFactory) adapts(IResourceManager) def __init__(self, context): @@ -546,9 +524,9 @@ class ExternalFileFactory(object): return res +@implementer(IIndexAttributes) class IndexAttributes(object): - implements(IIndexAttributes) adapts(IResource) def __init__(self, context): @@ -573,7 +551,7 @@ class IndexAttributes(object): if not actx.contentType.startswith('text'): return u'' data = actx.data - if type(data) != unicode: + if type(data) != str: try: data = data.decode('UTF-8') except UnicodeDecodeError: @@ -590,14 +568,14 @@ class IndexAttributes(object): if transform is not None: rfa = component.queryAdapter(IReadFile, adapted) if rfa is None: - data = transform(StringIO(adapted.data)) + data = transform(BytesOP(adapted.data)) return data else: return transform(rfa) if not context.contentType.startswith('text'): return u'' data = context.data - if type(data) != unicode: + if type(data) != str: data = data.decode('UTF-8') return data @@ -635,10 +613,10 @@ def transformToText(obj, data=None, contentType=None): #rfa = component.queryAdapter(IReadFile, obj) rfa = IReadFile(obj, None) if rfa is None: - if isinstance(data, unicode): + if isinstance(data, str): data = data.encode('UTF-8') try: - return transform(StringIO(data)) + return transform(BytesIO(data)) except: import traceback logger.warn(traceback.format_exc()) @@ -647,10 +625,9 @@ def transformToText(obj, data=None, contentType=None): return transform(rfa) +@implementer(schema.interfaces.IIterableSource) class ResourceTypeSourceList(object): - implements(schema.interfaces.IIterableSource) - def __init__(self, context): self.context = context diff --git a/pyproject.toml b/pyproject.toml index 80c7562..4f3ba1a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,6 +18,7 @@ dependencies = [ "python-dotenv", "zope.app.renderer", "zope.browsermenu", + "zope.i18n", "zope.securitypolicy", "zope.site", "zope.thread",