diff --git a/CHANGES.rst b/CHANGES.rst index 04b33e647f..1c4d0d833c 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -18,6 +18,10 @@ Features which are deprecated in Python 3.8. (`#476 `_) +Other changes ++++++++++++++ +- full PEP-8 compliance with the exception of import sorting + 4.0b10 (2019-03-08) ------------------- diff --git a/setup.cfg b/setup.cfg index 8f82721f6f..ccd2d54ff2 100644 --- a/setup.cfg +++ b/setup.cfg @@ -34,9 +34,8 @@ ignore = # We should remove the following ignored check codes: T000, C103, - no-accept-encodings = True - +doctests = True exclude = bootstrap.py diff --git a/src/App/ApplicationManager.py b/src/App/ApplicationManager.py index fc942030b8..5c70e9bda4 100644 --- a/src/App/ApplicationManager.py +++ b/src/App/ApplicationManager.py @@ -78,6 +78,7 @@ def __bobo_traverse__(self, request, name): return self[name] return getattr(self, name) + InitializeClass(DatabaseChooser) diff --git a/src/App/Extensions.py b/src/App/Extensions.py index b64f8fbf1f..68b256b67f 100644 --- a/src/App/Extensions.py +++ b/src/App/Extensions.py @@ -33,14 +33,14 @@ def __init__(self, f, im=0): def __eq__(self, other): if not isinstance(other, FuncCode): return False - return ((self.co_argcount, self.co_varnames) == - (other.co_argcount, other.co_varnames)) + return (self.co_argcount, self.co_varnames) == \ + (other.co_argcount, other.co_varnames) def __lt__(self, other): if not isinstance(other, FuncCode): return False - return ((self.co_argcount, self.co_varnames) < - (other.co_argcount, other.co_varnames)) + return (self.co_argcount, self.co_varnames) < \ + (other.co_argcount, other.co_varnames) def _getPath(home, prefix, name, suffixes): @@ -151,6 +151,7 @@ def getPath(prefix, name, checkProduct=1, suffixes=('',), cfg=None): _modules = {} # cache + def getObject(module, name, reload=0): # The use of _modules here is not thread safe, however, there is # no real harm in a race condition here. If two threads @@ -180,7 +181,7 @@ def getObject(module, name, reload=0): execsrc = f.read() except Exception: raise NotFound("The specified module, '%s', " - "couldn't be opened." % module) + "couldn't be opened." % module) module_dict = {} exec_(execsrc, module_dict) diff --git a/src/App/FactoryDispatcher.py b/src/App/FactoryDispatcher.py index f0b60186a7..74da480890 100644 --- a/src/App/FactoryDispatcher.py +++ b/src/App/FactoryDispatcher.py @@ -24,7 +24,6 @@ from Acquisition import aq_base from Acquisition import Implicit from ExtensionClass import Base -from zExceptions import Redirect from OFS.metaconfigure import get_registered_packages @@ -61,11 +60,12 @@ class Product(Base): def __init__(self, id): self.id = id - security.declarePublic('Destination') + @security.public def Destination(self): "Return the destination for factory output" return self + InitializeClass(Product) @@ -117,15 +117,15 @@ def __init__(self, product, dest, REQUEST=None): v = v[:v.rfind('/')] self._u = v[:v.rfind('/')] - security.declarePublic('Destination') + @security.public def Destination(self): "Return the destination for factory output" return self.__dict__['_d'] # we don't want to wrap the result! - security.declarePublic('this') + security.declarePublic('this') # NOQA: D001 this = Destination - security.declarePublic('DestinationURL') + @security.public def DestinationURL(self): "Return the URL for the destination for factory output" url = getattr(self, '_u', None) diff --git a/src/App/ImageFile.py b/src/App/ImageFile.py index 1353322ac6..92bfcc31cd 100644 --- a/src/App/ImageFile.py +++ b/src/App/ImageFile.py @@ -120,7 +120,7 @@ def index_html(self, REQUEST, RESPONSE): return filestream_iterator(self.path, mode='rb') if bbb.HAS_ZSERVER: - security.declarePublic('HEAD') + @security.public def HEAD(self, REQUEST, RESPONSE): """ """ RESPONSE.setHeader('Content-Type', self.content_type) @@ -134,4 +134,5 @@ def __len__(self): def __str__(self): return '' % self.__name__ + InitializeClass(ImageFile) diff --git a/src/App/Management.py b/src/App/Management.py index c885bcf95e..98bf6701d7 100644 --- a/src/App/Management.py +++ b/src/App/Management.py @@ -23,7 +23,6 @@ from App.special_dtml import DTMLFile from ExtensionClass import Base from six.moves.urllib.parse import quote, unquote -from zExceptions import Redirect from zope.interface import implementer import itertools import six @@ -40,12 +39,12 @@ class Tabs(Base): security = ClassSecurityInfo() - security.declarePublic('manage_tabs') + security.declarePublic('manage_tabs') # NOQA: D001 manage_tabs = DTMLFile('dtml/manage_tabs', globals()) manage_options = () - security.declarePublic('filtered_manage_options') + @security.public def filtered_manage_options(self, REQUEST=None): result = [] try: @@ -60,7 +59,7 @@ def filtered_manage_options(self, REQUEST=None): path = d.get('path', None) if path is None: - path = d['action'] + path = d['action'] o = self.restrictedTraverse(path, None) if o is None: @@ -133,6 +132,7 @@ def tabs_path_info(self, script, path): out.append(last) return '/'.join(out) + InitializeClass(Tabs) @@ -142,16 +142,18 @@ class Navigation(Base): security = ClassSecurityInfo() - security.declareProtected(view_management_screens, 'manage') + security.declareProtected(view_management_screens, 'manage') # NOQA: D001 manage = DTMLFile('dtml/manage', globals()) - security.declareProtected(view_management_screens, 'manage_menu') + security.declareProtected(view_management_screens, # NOQA: D001 + 'manage_menu') manage_menu = DTMLFile('dtml/menu', globals()) - security.declareProtected(view_management_screens, 'manage_page_footer') + security.declareProtected(view_management_screens, # NOQA: D001 + 'manage_page_footer') manage_page_footer = DTMLFile('dtml/manage_page_footer', globals()) - security.declarePublic('manage_form_title') + security.declarePublic('manage_form_title') # NOQA: D001 manage_form_title = DTMLFile('dtml/manage_form_title', globals(), form_title='Add Form', help_product=None, @@ -160,7 +162,8 @@ class Navigation(Base): varnames=('form_title', 'help_product', 'help_topic')) _manage_page_header = DTMLFile('dtml/manage_page_header', globals()) - security.declareProtected(view_management_screens, 'manage_page_header') + + @security.protected(view_management_screens) def manage_page_header(self, *args, **kw): """manage_page_header.""" kw['css_urls'] = itertools.chain( @@ -171,13 +174,14 @@ def manage_page_header(self, *args, **kw): self._get_zmi_additionals('zmi_additional_js_paths')) return self._manage_page_header(*args, **kw) - security.declareProtected(view_management_screens, 'manage_navbar') + security.declareProtected(view_management_screens, # NOQA: D001 + 'manage_navbar') manage_navbar = DTMLFile('dtml/manage_navbar', globals()) - security.declarePublic('zope_copyright') + security.declarePublic('zope_copyright') # NOQA: D001 zope_copyright = DTMLFile('dtml/copyright', globals()) - security.declarePublic('manage_zmi_logout') + @security.public def manage_zmi_logout(self, REQUEST, RESPONSE): """Logout current user""" p = getattr(REQUEST, '_logout_path', None) @@ -204,7 +208,7 @@ def _get_zmi_additionals(self, attrib): additionals = (additionals, ) return additionals + # Navigation doesn't have an inherited __class_init__ so doesn't get # initialized automatically. - InitializeClass(Navigation) diff --git a/src/App/Undo.py b/src/App/Undo.py index 3a61a76b5c..c0f0ebff86 100644 --- a/src/App/Undo.py +++ b/src/App/Undo.py @@ -34,7 +34,7 @@ class UndoSupport(Tabs, Implicit): {'label': 'Undo', 'action': 'manage_UndoForm'}, ) - security.declareProtected(undo_changes, 'manage_UndoForm') + security.declareProtected(undo_changes, 'manage_UndoForm') # NOQA: D001 manage_UndoForm = DTMLFile( 'dtml/undo', globals(), @@ -61,7 +61,7 @@ def _get_request_var_or_attr(self, name, default): v = default return v - security.declareProtected(undo_changes, 'undoable_transactions') + @security.protected(undo_changes) def undoable_transactions(self, first_transaction=None, last_transaction=None, PrincipiaUndoBatchSize=None): @@ -98,7 +98,7 @@ def undoable_transactions(self, first_transaction=None, return r - security.declareProtected(undo_changes, 'manage_undo_transactions') + @security.protected(undo_changes) def manage_undo_transactions(self, transaction_info=(), REQUEST=None): """ """ diff --git a/src/App/special_dtml.py b/src/App/special_dtml.py index 0427aef10b..b4d1f2eb50 100644 --- a/src/App/special_dtml.py +++ b/src/App/special_dtml.py @@ -12,7 +12,6 @@ ############################################################################## import os -import sys from logging import getLogger import DocumentTemplate @@ -93,6 +92,7 @@ def __call__(self, *args, **kw): return HTMLFile.inheritedAttribute('__call__')( *(self,) + args[1:], **kw) + defaultBindings = {'name_context': 'context', 'name_container': 'container', 'name_m_self': 'self', diff --git a/src/App/tests/test_getZopeVersion.py b/src/App/tests/test_getZopeVersion.py index eb2172ab89..f8c76b29d6 100644 --- a/src/App/tests/test_getZopeVersion.py +++ b/src/App/tests/test_getZopeVersion.py @@ -18,12 +18,12 @@ from pkg_resources import get_distribution from App.version_txt import getZopeVersion + class Test(unittest.TestCase): def test_major(self): self.assertEqual( getZopeVersion().major, - int(get_distribution("Zope").version.split(".")[0]) - ) + int(get_distribution("Zope").version.split(".")[0])) def test_types(self): zv = getZopeVersion() diff --git a/src/App/version_txt.py b/src/App/version_txt.py index ba9ddd9756..3ed05d43cc 100644 --- a/src/App/version_txt.py +++ b/src/App/version_txt.py @@ -21,8 +21,7 @@ ZopeVersion = collections.namedtuple( "ZopeVersion", - ["major", "minor", "micro", "status", "release"] - ) + ["major", "minor", "micro", "status", "release"]) def _prep_version_data(): @@ -42,16 +41,14 @@ def _prep_version_data(): int(version_dict.get('minor') or -1), int(version_dict.get('micro') or -1), version_dict.get('status') or '', - int(version_dict.get('release') or -1), - ) - - + int(version_dict.get('release') or -1)) def version_txt(): _prep_version_data() return '(%s)' % _version_string + def getZopeVersion(): """return information about the Zope version as a named tuple. diff --git a/src/OFS/Application.py b/src/OFS/Application.py index 12c3ec1907..d6fa7ccc61 100644 --- a/src/OFS/Application.py +++ b/src/OFS/Application.py @@ -339,9 +339,9 @@ def _is_package(product_dir, product_name): return False init_py = os.path.join(package_dir, '__init__.py') - if (not os.path.exists(init_py) and - not os.path.exists(init_py + 'c') and - not os.path.exists(init_py + 'o')): + if not os.path.exists(init_py) and \ + not os.path.exists(init_py + 'c') and \ + not os.path.exists(init_py + 'o'): return False return True diff --git a/src/OFS/Cache.py b/src/OFS/Cache.py index 662749eb90..47ac350bf7 100644 --- a/src/OFS/Cache.py +++ b/src/OFS/Cache.py @@ -58,8 +58,8 @@ def filterCacheManagers(orig, container, name, value, extra): It causes objects to be found only if they are in the list of cache managers. """ - if (hasattr(aq_base(container), ZCM_MANAGERS) and - name in getattr(container, ZCM_MANAGERS)): + if hasattr(aq_base(container), ZCM_MANAGERS) and \ + name in getattr(container, ZCM_MANAGERS): return 1 return 0 diff --git a/src/OFS/DTMLDocument.py b/src/OFS/DTMLDocument.py index 28f326a4b1..2338cdd8fb 100644 --- a/src/OFS/DTMLDocument.py +++ b/src/OFS/DTMLDocument.py @@ -24,11 +24,7 @@ from OFS.DTMLMethod import safe_file_data from OFS.PropertyManager import PropertyManager from six import binary_type -from six import PY2 -from six import PY3 -from six import text_type from six.moves.urllib.parse import quote -from zExceptions import ResourceLockedError from zExceptions.TracebackSupplement import PathTracebackSupplement from zope.contenttype import guess_content_type @@ -45,15 +41,13 @@ class DTMLDocument(PropertyManager, DTMLMethod): zmi_icon = 'far fa-file-alt' _locked_error_text = 'This document has been locked.' - manage_options = ( - DTMLMethod.manage_options[:2] + - PropertyManager.manage_options + - DTMLMethod.manage_options[2:] - ) + manage_options = (DTMLMethod.manage_options[:2] + + PropertyManager.manage_options + + DTMLMethod.manage_options[2:]) # Replace change_dtml_methods by change_dtml_documents __ac_permissions__ = tuple([ - (perms[0] == change_dtml_methods) and + (perms[0] == change_dtml_methods) and # NOQA: W504 (change_dtml_documents, perms[1]) or perms for perms in DTMLMethod.__ac_permissions__]) diff --git a/src/OFS/DTMLMethod.py b/src/OFS/DTMLMethod.py index 0b338f4706..ebd7043e08 100644 --- a/src/OFS/DTMLMethod.py +++ b/src/OFS/DTMLMethod.py @@ -93,10 +93,9 @@ class DTMLMethod( 'label': 'Proxy', 'action': 'manage_proxyForm', }, - ) + - RoleManager.manage_options - + Item_w__name__.manage_options - + Cacheable.manage_options + ) + RoleManager.manage_options + + Item_w__name__.manage_options + + Cacheable.manage_options ) # More reasonable default for content-type for http HEAD requests. @@ -119,8 +118,8 @@ def __call__(self, client=None, REQUEST={}, RESPONSE=None, **kw): if not self._cache_namespace_keys: data = self.ZCacheable_get(default=_marker) if data is not _marker: - if (IStreamIterator.isImplementedBy(data) and - RESPONSE is not None): + if IStreamIterator.isImplementedBy(data) and \ + RESPONSE is not None: # This is a stream iterator and we need to set some # headers now before giving it to medusa headers_get = RESPONSE.headers.get @@ -128,10 +127,10 @@ def __call__(self, client=None, REQUEST={}, RESPONSE=None, **kw): if headers_get('content-length', None) is None: RESPONSE.setHeader('content-length', len(data)) - if (headers_get('content-type', None) is None and - headers_get('Content-type', None) is None): - ct = (self.__dict__.get('content_type') or - self.default_content_type) + if headers_get('content-type', None) is None and \ + headers_get('Content-type', None) is None: + ct = (self.__dict__.get('content_type') + or self.default_content_type) RESPONSE.setHeader('content-type', ct) # Return cached results. @@ -308,7 +307,7 @@ def manage_upload(self, file='', REQUEST=None): self, REQUEST, manage_tabs_message='No file specified', manage_tabs_type='warning') - + self.munge(safe_file_data(file)) self.ZCacheable_invalidate() if REQUEST is not None: @@ -386,7 +385,7 @@ def manage_FTPget(self): InitializeClass(DTMLMethod) -token = "[a-zA-Z0-9!#$%&'*+\-.\\\\^_`|~]+" +token = r"[a-zA-Z0-9!#$%&'*+\-.\\\\^_`|~]+" hdr_start = re.compile(r'(%s):(.*)' % token).match diff --git a/src/OFS/FindSupport.py b/src/OFS/FindSupport.py index 77c4ef9ad6..7fb65e3c2d 100644 --- a/src/OFS/FindSupport.py +++ b/src/OFS/FindSupport.py @@ -137,18 +137,19 @@ def ZopeFindAndApply(self, obj, obj_ids=None, obj_metatypes=None, else: pss = st = '' - if ((not obj_ids or absattr(bs.getId()) in obj_ids) and - (not obj_metatypes or (hasattr(bs, 'meta_type') and - bs.meta_type in obj_metatypes)) and - (not obj_searchterm or - (hasattr(ob, 'PrincipiaSearchSource') and - obj_searchterm in pss) or - (hasattr(ob, 'SearchableText') and obj_searchterm in st) - ) and - (not obj_expr or expr_match(ob, obj_expr)) and - (not obj_mtime or mtime_match(ob, obj_mtime, obj_mspec)) and - ((not obj_permission or not obj_roles) or - role_match(ob, obj_permission, obj_roles))): + if ((not obj_ids or absattr(bs.getId()) in obj_ids) + and (not obj_metatypes + or (hasattr(bs, 'meta_type') + and bs.meta_type in obj_metatypes)) + and (not obj_searchterm + or (hasattr(ob, 'PrincipiaSearchSource') + and obj_searchterm in pss) + or (hasattr(ob, 'SearchableText') + and obj_searchterm in st)) + and (not obj_expr or expr_match(ob, obj_expr)) + and (not obj_mtime or mtime_match(ob, obj_mtime, obj_mspec)) + and ((not obj_permission or not obj_roles) + or role_match(ob, obj_permission, obj_roles))): if apply_func: apply_func(ob, (apply_path + '/' + p)) diff --git a/src/OFS/Image.py b/src/OFS/Image.py index 0b34b6127b..bc3ccf76dc 100644 --- a/src/OFS/Image.py +++ b/src/OFS/Image.py @@ -134,16 +134,12 @@ class File( manage = manage_main = manage_editForm manage_uploadForm = manage_editForm - manage_options = ( - ( - {'label': 'Edit', 'action': 'manage_main'}, - {'label': 'View', 'action': ''}, - ) + - PropertyManager.manage_options + - RoleManager.manage_options + - Item_w__name__.manage_options + - Cacheable.manage_options - ) + manage_options = (({'label': 'Edit', 'action': 'manage_main'}, + {'label': 'View', 'action': ''}) + + PropertyManager.manage_options + + RoleManager.manage_options + + Item_w__name__.manage_options + + Cacheable.manage_options) _properties = ( {'id': 'title', 'type': 'string'}, @@ -308,14 +304,15 @@ def _range_request_handler(self, REQUEST, RESPONSE): boundary = _make_boundary() # Calculate the content length - size = (8 + len(boundary) + # End marker length - len(ranges) * ( # Constant lenght per set - 49 + len(boundary) + len(self.content_type) + - len('%d' % self.size))) + size = (8 + len(boundary) # End marker length + + len(ranges) * ( # Constant lenght per set + 49 + len(boundary) + + len(self.content_type) + + len('%d' % self.size))) for start, end in ranges: # Variable length per set - size = (size + len('%d%d' % (start, end - 1)) + - end - start) + size = (size + len('%d%d' % (start, end - 1)) + + end - start) # Some clients implement an earlier draft of the spec, they # will only accept x-byteranges. @@ -808,8 +805,9 @@ def getImageInfo(data): # See PNG v1.2 spec (http://www.cdrom.com/pub/png/spec/) # Bytes 0-7 are below, 4-byte chunk length, then 'IHDR' # and finally the 4-byte width, height - elif ((size >= 24) and (data[:8] == b'\211PNG\r\n\032\n') and - (data[12:16] == b'IHDR')): + elif (size >= 24 + and data[:8] == b'\211PNG\r\n\032\n' + and data[12:16] == b'IHDR'): content_type = 'image/png' w, h = struct.unpack(">LL", data[16:24]) width = int(w) diff --git a/src/OFS/ObjectManager.py b/src/OFS/ObjectManager.py index 848bcbd1a3..d5d50b8d6e 100644 --- a/src/OFS/ObjectManager.py +++ b/src/OFS/ObjectManager.py @@ -236,8 +236,8 @@ def all_meta_types(self, interfaces=None): # Look at all globally visible meta types. for entry in getattr(Products, 'meta_types', ()): - if ((interfaces is not None) or - (entry.get("visibility", None) == "Global")): + if interfaces is not None or \ + entry.get("visibility", None) == "Global": external_candidates.append(entry) # Filter the list of external candidates based on the @@ -321,10 +321,10 @@ def hasObject(self, id): # This doesn't try to be more intelligent than _getOb, and doesn't # consult _objects (for performance reasons). The common use case # is to check that an object does *not* exist. - if (id in ('.', '..') or - id.startswith('_') or - id.startswith('aq_') or - id.endswith('__')): + if id in ('.', '..') or \ + id.startswith('_') or \ + id.startswith('aq_') or \ + id.endswith('__'): return False return getattr(aq_base(self), id, None) is not None @@ -512,8 +512,7 @@ def superValues(self, t): try: id = i['id'] physicalPath = relativePhysicalPath + (id,) - if ((physicalPath not in seen) and - (i['meta_type'] in t)): + if physicalPath not in seen and i['meta_type'] in t: vals.append(get(id)) seen[physicalPath] = 1 except Exception: @@ -742,8 +741,8 @@ def manage_FTPlist(self, REQUEST): if REQUEST.environ.get('FTP_RECURSIVE', 0) == 1: all_files = copy.copy(files) for f in files: - if (hasattr(aq_base(f[1]), 'isPrincipiaFolderish') and - f[1].isPrincipiaFolderish): + if hasattr(aq_base(f[1]), 'isPrincipiaFolderish') and \ + f[1].isPrincipiaFolderish: all_files.extend(findChildren(f[1])) files = all_files @@ -755,8 +754,8 @@ def manage_FTPlist(self, REQUEST): files.sort() - if not (hasattr(self, 'isTopLevelPrincipiaApplicationObject') and - self.isTopLevelPrincipiaApplicationObject): + if not hasattr(self, 'isTopLevelPrincipiaApplicationObject') and \ + self.isTopLevelPrincipiaApplicationObject: files.insert(0, ('..', aq_parent(self))) files.insert(0, ('.', self)) for k, v in files: @@ -781,8 +780,8 @@ def manage_FTPstat(self, REQUEST): mode = 0o0040000 from AccessControl.User import nobody # check to see if we are acquiring our objectValues or not - if not (len(REQUEST.PARENTS) > 1 and - self.objectValues() == REQUEST.PARENTS[1].objectValues()): + if not len(REQUEST.PARENTS) > 1 and \ + self.objectValues() == REQUEST.PARENTS[1].objectValues(): try: if getSecurityManager().validate( None, self, 'manage_FTPlist', self.manage_FTPlist): @@ -815,8 +814,7 @@ def __getitem__(self, key): request = getattr(self, 'REQUEST', None) if not (isinstance(request, str) or request is None): method = request.get('REQUEST_METHOD', 'GET') - if (request.maybe_webdav_client and - method not in ('GET', 'POST')): + if request.maybe_webdav_client and method not in ('GET', 'POST'): if bbb.HAS_ZSERVER: from webdav.NullResource import NullResource return NullResource(self, key, request).__of__(self) @@ -943,8 +941,8 @@ def findChildren(obj, dirname=''): lst = [] for name, child in obj.objectItems(): - if (hasattr(aq_base(child), 'isPrincipiaFolderish') and - child.isPrincipiaFolderish): + if hasattr(aq_base(child), 'isPrincipiaFolderish') and \ + child.isPrincipiaFolderish: lst.extend(findChildren(child, dirname + obj.id + '/')) else: lst.append((dirname + obj.id + "/" + name, child)) diff --git a/src/OFS/OrderedFolder.py b/src/OFS/OrderedFolder.py index 1ffa6b0ef5..8cb75db5ff 100644 --- a/src/OFS/OrderedFolder.py +++ b/src/OFS/OrderedFolder.py @@ -43,7 +43,4 @@ class OrderedFolder(OrderSupport, Folder): meta_type = 'Folder (Ordered)' zmi_icon = 'far fa-folder zmi-icon-folder-ordered' - manage_options = ( - OrderSupport.manage_options + - Folder.manage_options[1:] - ) + manage_options = OrderSupport.manage_options + Folder.manage_options[1:] diff --git a/src/OFS/PropertyManager.py b/src/OFS/PropertyManager.py index 8ae1825439..52a126e687 100644 --- a/src/OFS/PropertyManager.py +++ b/src/OFS/PropertyManager.py @@ -133,10 +133,12 @@ class PropertyManager(Base): @security.protected(access_contents_information) def valid_property_id(self, id): - if (not id or id[:1] == '_' or (id[:3] == 'aq_') or - (' ' in id) or - hasattr(aq_base(self), id) or - escape(id, True) != id): + if not id or \ + id[:1] == '_' or \ + id[:3] == 'aq_' or \ + ' ' in id or \ + hasattr(aq_base(self), id) or \ + escape(id, True) != id: return 0 return 1 diff --git a/src/OFS/PropertySheets.py b/src/OFS/PropertySheets.py index 322821fa01..f66e4afbbc 100644 --- a/src/OFS/PropertySheets.py +++ b/src/OFS/PropertySheets.py @@ -469,8 +469,8 @@ def items(self): @security.protected(access_contents_information) def get(self, name, default=None): for propset in self.__propsets__(): - if propset.id == name or (hasattr(propset, 'xml_namespace') and - propset.xml_namespace() == name): + if propset.id == name or \ + getattr(propset, 'xml_namespace', None) == name: return propset.__of__(self) return default diff --git a/src/OFS/absoluteurl.py b/src/OFS/absoluteurl.py index 06e60285e4..197d464bb0 100644 --- a/src/OFS/absoluteurl.py +++ b/src/OFS/absoluteurl.py @@ -107,9 +107,9 @@ def breadcrumbs(self): name = context.getId() - if (container is None or - self._isVirtualHostRoot() or - not ITraversable.providedBy(container)): + if container is None or \ + self._isVirtualHostRoot() or \ + not ITraversable.providedBy(container): return ({'name': name, 'url': context.absolute_url()},) view = getMultiAdapter((container, request), IAbsoluteURL) diff --git a/src/OFS/browser/__init__.py b/src/OFS/browser/__init__.py index 6f0e3e9021..b04dcfefa0 100644 --- a/src/OFS/browser/__init__.py +++ b/src/OFS/browser/__init__.py @@ -16,7 +16,7 @@ class StandardErrorMessageView(BrowserView): """ View rendered on SiteError. - + Requires a DTML Method named ``standard_error_message`` """ diff --git a/src/OFS/interfaces.py b/src/OFS/interfaces.py index e815e5f169..23db7b6388 100644 --- a/src/OFS/interfaces.py +++ b/src/OFS/interfaces.py @@ -411,7 +411,7 @@ def __init__(creator, owner, depth=0, timeout='Infinity', of 'Seconds-nnn' where nnn is an integer. The timeout value MUST be less than (2^32)-1. *IF* timeout is the string value 'Infinite', the timeout value will be set to 1800 (30 minutes). - (Timeout is the value in seconds from creation\modification + (Timeout is the value in seconds from creation/modification time until the lock MAY time out). - **locktype** not in set {'write'} *this may expand later* diff --git a/src/OFS/tests/testObjectManager.py b/src/OFS/tests/testObjectManager.py index 53dcdb022f..31e4c8c550 100644 --- a/src/OFS/tests/testObjectManager.py +++ b/src/OFS/tests/testObjectManager.py @@ -1,4 +1,6 @@ # -*- coding: utf-8 -*- +import os + from AccessControl.owner import EmergencyUserCannotOwn from AccessControl.SecurityManagement import newSecurityManager from AccessControl.SecurityManagement import noSecurityManager @@ -503,8 +505,7 @@ def test_list_imports(self): # in skel/import. Tolerate both cases. self.assertIsInstance(om.list_imports(), list) for filename in om.list_imports(): - self.assertTrue(filename.endswith('.zexp') or - filename.endswith('.xml')) + self.assertTrue(os.path.splitext(filename)[1] in ('.zexp', '.xml')) def test_manage_get_sortedObjects_quote_id(self): # manage_get_sortedObjects now returns a urlquoted version @@ -518,6 +519,7 @@ def test_manage_get_sortedObjects_quote_id(self): self.assertEqual(result[0]['id'], hash_id) self.assertEqual(result[0]['quoted_id'], quote(hash_id)) + _marker = object() diff --git a/src/OFS/tests/testSorting.py b/src/OFS/tests/testSorting.py index bc4a9a181d..4a7e9f260f 100644 --- a/src/OFS/tests/testSorting.py +++ b/src/OFS/tests/testSorting.py @@ -26,10 +26,8 @@ def setUp(self): self.browser.login('manager', 'manager_pass') def check_order(self, expect_1_before_2): - found_1_before_2 = ( - self.browser.contents.find('File2') > - self.browser.contents.find('File1') - ) + source = self.browser.contents + found_1_before_2 = source.find('File2') > source.find('File1') self.assertEqual(found_1_before_2, expect_1_before_2) def test_sortby(self): diff --git a/src/OFS/tests/testTraverse.py b/src/OFS/tests/testTraverse.py index 8c1d953af9..e387d63dd1 100644 --- a/src/OFS/tests/testTraverse.py +++ b/src/OFS/tests/testTraverse.py @@ -285,7 +285,7 @@ def testBoboTraverseToNonAttrValue(self): self._setupSecurity(UnitTestSecurityPolicy()) bb = self._makeBoboTraversable() self.assertTrue( - bb.restrictedTraverse('manufactured') is 42) + bb.restrictedTraverse('manufactured') == 42) def testBoboTraverseToAcquiredObject(self): # Verify it's possible to use a __bobo_traverse__ which retrieves @@ -423,7 +423,7 @@ def testTraverseUp(self): def testTraverseToNameStartingWithPlus(self): # Verify it's possible to traverse to a name such as +something self.assertTrue( - self.folder1.unrestrictedTraverse('+something') is 'plus') + self.folder1.unrestrictedTraverse('+something') == 'plus') class SimpleClass(object): @@ -439,7 +439,8 @@ def test_traversable(): >>> from Zope2.App import zcml >>> zcml.load_config("configure.zcml", Products.Five) >>> from Testing.makerequest import makerequest - >>> self.app = makerequest(self.app) + >>> self.app = makerequest(self.app) # NOQA: F821 + >>> folder = self.folder # NOQA: F821 ``SimpleContent`` is a traversable class by default. Its fallback traverser should raise NotFound when traversal fails. (Note: If @@ -448,11 +449,10 @@ def test_traversable(): raises NotFoundError.) >>> from Products.Five.tests.testing import simplecontent - >>> simplecontent.manage_addSimpleContent(self.folder, 'testoid', - ... 'Testoid') + >>> simplecontent.manage_addSimpleContent(folder, 'testoid', 'Testoid') >>> from zExceptions import NotFound >>> try: - ... self.folder.testoid.unrestrictedTraverse('doesntexist') + ... folder.testoid.unrestrictedTraverse('doesntexist') ... except NotFound: ... pass @@ -502,12 +502,12 @@ def test_traversable(): >>> zcml.load_string(configure_zcml) >>> from Products.Five.tests.testing import fancycontent - >>> info = fancycontent.manage_addFancyContent(self.folder, 'fancy', '') + >>> info = fancycontent.manage_addFancyContent(folder, 'fancy', '') In the following test we let the original __bobo_traverse__ method kick in: - >>> self.folder.fancy.unrestrictedTraverse('something-else' + >>> folder.fancy.unrestrictedTraverse('something-else' ... ).index_html({}) 'something-else' @@ -515,23 +515,23 @@ def test_traversable(): takes over. Therefore, unless it raises AttributeError or KeyError, it will be the only way traversal is done. - >>> self.folder.fancy.unrestrictedTraverse('fancyview').index_html({}) + >>> folder.fancy.unrestrictedTraverse('fancyview').index_html({}) 'fancyview' Note that during publishing, if the original __bobo_traverse__ method *does* raise AttributeError or KeyError, we can get normal view look-up. In unrestrictedTraverse, we don't. Maybe we should? Needs discussing. - >>> self.folder.fancy.unrestrictedTraverse( + >>> folder.fancy.unrestrictedTraverse( ... 'raise-attributeerror')() == 'Fancy, fancy' True - >>> self.folder.fancy.unrestrictedTraverse( + >>> folder.fancy.unrestrictedTraverse( ... 'raise-keyerror')() == 'Fancy, fancy' True >>> try: - ... self.folder.fancy.unrestrictedTraverse('raise-valueerror') + ... folder.fancy.unrestrictedTraverse('raise-valueerror') ... except ValueError: ... pass @@ -542,9 +542,9 @@ def test_traversable(): >>> from Products.Five.tests.testing import fancycontent >>> info = fancycontent.manage_addNonTraversableFancyContent( - ... self.folder, 'fancy_zope2', '') - >>> self.folder.fancy_zope2.an_attribute = 'This is an attribute' - >>> self.folder.fancy_zope2.unrestrictedTraverse( + ... folder, 'fancy_zope2', '') + >>> folder.fancy_zope2.an_attribute = 'This is an attribute' + >>> folder.fancy_zope2.unrestrictedTraverse( ... 'an_attribute').index_html({}) 'an_attribute' @@ -552,8 +552,8 @@ def test_traversable(): value 'This is an attribute'. Let's make sure the same thing happens for an object that has been marked traversable: - >>> self.folder.fancy.an_attribute = 'This is an attribute' - >>> self.folder.fancy.unrestrictedTraverse( + >>> folder.fancy.an_attribute = 'This is an attribute' + >>> folder.fancy.unrestrictedTraverse( ... 'an_attribute').index_html({}) 'an_attribute' @@ -561,7 +561,7 @@ def test_traversable(): IAcquirer, it should get acquisition-wrapped so we can acquire attributes implicitly: - >>> acquirer = self.folder.unrestrictedTraverse('acquirer') + >>> acquirer = folder.unrestrictedTraverse('acquirer') >>> acquirer.fancy @@ -621,27 +621,28 @@ def test_view_doesnt_shadow_attribute(): >>> from Zope2.App import zcml >>> zcml.load_config("configure.zcml", Products.Five) >>> zcml.load_string(configure_zcml) + >>> folder = self.folder # NOQA: F821 Then we create a traversable folder... >>> from Products.Five.tests.testing import folder as ftf - >>> ftf.manage_addFiveTraversableFolder(self.folder, 'ftf') + >>> ftf.manage_addFiveTraversableFolder(folder, 'ftf') and add an object called ``eagle`` to it: >>> from Products.Five.tests.testing import simplecontent - >>> simplecontent.manage_addIndexSimpleContent(self.folder.ftf, + >>> simplecontent.manage_addIndexSimpleContent(folder.ftf, ... 'eagle', 'Eagle') When we publish the ``ftf/eagle`` now, we expect the attribute to take precedence over the view during traversal: - >>> self.folder.ftf.unrestrictedTraverse('eagle').index_html({}) + >>> folder.ftf.unrestrictedTraverse('eagle').index_html({}) 'Default index_html called' Of course, unless we explicitly want to lookup the view using @@: - >>> self.folder.ftf.unrestrictedTraverse( + >>> folder.ftf.unrestrictedTraverse( ... '@@eagle')() == 'The eagle has landed' True @@ -649,16 +650,16 @@ def test_view_doesnt_shadow_attribute(): found in OFS.Application, raise NotFound. Five still knows how to deal with this, hence views work there too: - >>> self.app.unrestrictedTraverse( - ... '@@eagle')() == 'The eagle has landed' + >>> res = self.app.unrestrictedTraverse('@@eagle')() # NOQA: F821 + >>> res == 'The eagle has landed' True However, acquired attributes *should* be shadowed. See discussion on http://codespeak.net/pipermail/z3-five/2006q2/001474.html - >>> simplecontent.manage_addIndexSimpleContent(self.folder, + >>> simplecontent.manage_addIndexSimpleContent(folder, ... 'mouse', 'Mouse') - >>> self.folder.ftf.unrestrictedTraverse( + >>> folder.ftf.unrestrictedTraverse( ... 'mouse')() == 'The mouse has been eaten by the eagle' True diff --git a/src/OFS/userfolder.py b/src/OFS/userfolder.py index 6ca4eb63df..629705b703 100644 --- a/src/OFS/userfolder.py +++ b/src/OFS/userfolder.py @@ -51,10 +51,7 @@ class BasicUserFolder( manage_options = (( {'label': 'Contents', 'action': 'manage_main'}, {'label': 'Properties', 'action': 'manage_userFolderProperties'}, - ) + - RoleManager.manage_options + - Item.manage_options - ) + ) + RoleManager.manage_options + Item.manage_options) @security.protected(ManageUsers) @requestmethod('POST') @@ -164,8 +161,8 @@ def _addUser(self, name, password, confirm, roles, domains, REQUEST=None): if not password or not confirm: if not domains: raise BadRequest('Password and confirmation must be specified') - if self.getUser(name) or (self._emergency_user and - name == self._emergency_user.getUserName()): + em_user = self._emergency_user + if self.getUser(name) or (em_user and name == em_user.getUserName()): raise BadRequest('A user with the specified name already exists') if (password or confirm) and (password != confirm): raise BadRequest('Password and confirmation do not match') diff --git a/src/Products/Five/browser/decode.py b/src/Products/Five/browser/decode.py index a44081b220..9f2729f5af 100644 --- a/src/Products/Five/browser/decode.py +++ b/src/Products/Five/browser/decode.py @@ -15,7 +15,6 @@ encoding. """ -import sys from warnings import warn from ZPublisher.HTTPRequest import isCGI_NAMEs diff --git a/src/Products/Five/browser/metaconfigure.py b/src/Products/Five/browser/metaconfigure.py index 01b9f2bf75..86fa998244 100644 --- a/src/Products/Five/browser/metaconfigure.py +++ b/src/Products/Five/browser/metaconfigure.py @@ -76,9 +76,9 @@ def _configure_z2security(_context, new_class, required): ) # Make everything else private private_attrs = [name for name in dir(new_class) - if ((not name.startswith('_')) and - (name not in required) and - is_method(getattr(new_class, name)))] + if ((not name.startswith('_')) + and (name not in required) + and is_method(getattr(new_class, name)))] for attr in private_attrs: _context.action( discriminator=('five:protectName', new_class, attr), @@ -332,17 +332,19 @@ def publishTraverse(self, request, name, def resource(_context, name, layer=IDefaultBrowserLayer, permission='zope.Public', file=None, image=None, template=None): - if ((file and image) or (file and template) or - (image and template) or not (file or image or template)): + if (file and image) or \ + (file and template) or \ + (image and template) or \ + not (file or image or template): raise ConfigurationError( "Must use exactly one of file or image or template" "attributes for resource directives" ) res = file or image or template - res_type = ((file and 'file') or - (image and 'image') or - (template and 'template')) + res_type = (file and 'file') or \ + (image and 'image') or \ + (template and 'template') factory_info = _factory_map.get(res_type) factory_info['count'] += 1 res_factory = factory_info['factory'] diff --git a/src/Products/Five/browser/tests/pages.py b/src/Products/Five/browser/tests/pages.py index 2f0aa20f9f..dc74108c38 100644 --- a/src/Products/Five/browser/tests/pages.py +++ b/src/Products/Five/browser/tests/pages.py @@ -104,19 +104,20 @@ class ProtectedView(object): security = ClassSecurityInfo() - security.declarePublic('public_method') + @security.public def public_method(self): """Docstring""" return u'PUBLIC' - security.declareProtected('View', 'protected_method') + @security.protected('View') def protected_method(self): """Docstring""" return u'PROTECTED' - security.declarePrivate('private_method') + @security.private def private_method(self): """Docstring""" return u'PRIVATE' + InitializeClass(ProtectedView) diff --git a/src/Products/Five/browser/tests/test_absoluteurl.py b/src/Products/Five/browser/tests/test_absoluteurl.py index c904f63815..a010f88769 100644 --- a/src/Products/Five/browser/tests/test_absoluteurl.py +++ b/src/Products/Five/browser/tests/test_absoluteurl.py @@ -24,14 +24,15 @@ def test_absoluteurl(): >>> import Products.Five >>> from Zope2.App import zcml >>> zcml.load_config("configure.zcml", Products.Five) + >>> folder = self.folder # NOQA: F821 >>> from Products.Five.tests.testing import ( ... manage_addFiveTraversableFolder) - >>> manage_addFiveTraversableFolder(self.folder, 'testoid', 'Testoid') + >>> manage_addFiveTraversableFolder(folder, 'testoid', 'Testoid') A simple traversal will yield us the @@absolute_url view: - >>> view = self.folder.unrestrictedTraverse('testoid/@@absolute_url') + >>> view = folder.unrestrictedTraverse('testoid/@@absolute_url') >>> view() 'http://nohost/test_folder_1_/testoid' @@ -52,7 +53,7 @@ def test_absoluteurl(): >>> from zope.interface import alsoProvides, noLongerProvides >>> from OFS.interfaces import IApplication - >>> alsoProvides(self.folder, IApplication) + >>> alsoProvides(folder, IApplication) >>> for crumb in view.breadcrumbs(): ... info = list(crumb.items()) @@ -61,12 +62,12 @@ def test_absoluteurl(): [('name', 'test_folder_1_'), ('url', 'http://nohost/test_folder_1_')] [('name', 'testoid'), ('url', 'http://nohost/test_folder_1_/testoid')] - >>> noLongerProvides(self.folder, IApplication) + >>> noLongerProvides(folder, IApplication) The absolute url view is obviously not affected by virtual hosting: - >>> request = self.app.REQUEST - >>> request['PARENTS'] = [self.folder.test_folder_1_] + >>> request = self.app.REQUEST # NOQA: F821 + >>> request['PARENTS'] = [folder.test_folder_1_] >>> url = request.setServerURL( ... protocol='http', hostname='foo.bar.com', port=80) >>> request.setVirtualRoot('') diff --git a/src/Products/Five/browser/tests/test_defaultview.py b/src/Products/Five/browser/tests/test_defaultview.py index 6bbb4cc191..62659434f9 100644 --- a/src/Products/Five/browser/tests/test_defaultview.py +++ b/src/Products/Five/browser/tests/test_defaultview.py @@ -26,6 +26,8 @@ def test_default_view(): >>> from Zope2.App import zcml >>> zcml.load_config("configure.zcml", Products.Five) >>> zcml.load_config('defaultview.zcml', Products.Five.browser.tests) + >>> folder = self.folder # NOQA: F821 + >>> http = http # NOQA: F821 Now let's add a couple of stub objects: @@ -35,13 +37,13 @@ def test_default_view(): ... manage_addIndexSimpleContent, ... ) - >>> manage_addSimpleContent(self.folder, 'testoid', 'Testoid') - >>> manage_addCallableSimpleContent(self.folder, 'testcall', 'TestCall') - >>> manage_addIndexSimpleContent(self.folder, 'testindex', 'TestIndex') + >>> manage_addSimpleContent(folder, 'testoid', 'Testoid') + >>> manage_addCallableSimpleContent(folder, 'testcall', 'TestCall') + >>> manage_addIndexSimpleContent(folder, 'testindex', 'TestIndex') As a last act of preparation, we create a manager login: - >>> uf = self.folder.acl_users + >>> uf = folder.acl_users >>> _ignored = uf._doAddUser('manager', 'r00t', ['Manager'], []) We can specify another default view with browser:defaultView: @@ -158,7 +160,6 @@ def test_default_method_args_marshalling(): >>> def args(method): ... f = method.__func__ ... c = f.__code__ - ... defaults = f.__defaults__ ... names = c.co_varnames[1:c.co_argcount] ... return names >>> args(view.my_method) diff --git a/src/Products/Five/browser/tests/test_i18n.py b/src/Products/Five/browser/tests/test_i18n.py index d0f32ab260..e9d3f3b3ab 100644 --- a/src/Products/Five/browser/tests/test_i18n.py +++ b/src/Products/Five/browser/tests/test_i18n.py @@ -42,13 +42,15 @@ def test_zpt_i18n(): >>> from Zope2.App import zcml >>> zcml.load_config("configure.zcml", Products.Five) >>> zcml.load_string(configure_zcml) + >>> folder = self.folder # NOQA: F821 + >>> http = http # NOQA: F821 In order to be able to traverse to the PageTemplate view, we need a traversable object: >>> from Products.Five.tests.testing import ( ... manage_addFiveTraversableFolder) - >>> manage_addFiveTraversableFolder(self.folder, 'testoid', 'Testoid') + >>> manage_addFiveTraversableFolder(folder, 'testoid', 'Testoid') We tell Zope to translate the messages by passing the ``Accept-Language`` header which is processed by the diff --git a/src/Products/Five/browser/tests/test_menu.py b/src/Products/Five/browser/tests/test_menu.py index ebf1bed812..5af27415ad 100644 --- a/src/Products/Five/browser/tests/test_menu.py +++ b/src/Products/Five/browser/tests/test_menu.py @@ -38,7 +38,8 @@ def test_menu(): >>> from zope.browsermenu.menu import getMenu >>> request = TestRequest() - >>> menu = getMenu('testmenu', self.folder, request) + >>> folder = self.folder # NOQA: F821 + >>> menu = getMenu('testmenu', folder, request) It should have @@ -91,12 +92,12 @@ def test_menu(): Let's create a manager user account and log in. - >>> uf = self.folder.acl_users + >>> uf = folder.acl_users >>> _ignored = uf._doAddUser('manager', 'r00t', ['Manager'], []) - >>> self.login('manager') + >>> self.login('manager') # NOQA: F821 >>> newInteraction() - >>> menu = getMenu('testmenu', self.folder, request) + >>> menu = getMenu('testmenu', folder, request) We should get the protected menu items now: diff --git a/src/Products/Five/browser/tests/test_pages.py b/src/Products/Five/browser/tests/test_pages.py index 7fb8e34baa..4eb08f71ae 100644 --- a/src/Products/Five/browser/tests/test_pages.py +++ b/src/Products/Five/browser/tests/test_pages.py @@ -36,7 +36,7 @@ def test_view_with_unwrapped_context(): Simple views should work fine without having their contexts wrapped: - >>> eagle = queryMultiAdapter((unwrapped, self.app.REQUEST), + >>> eagle = queryMultiAdapter((unwrapped, self.app.REQUEST), # NOQA: F821 ... Interface, 'eagle.txt') >>> eagle is not None True @@ -49,7 +49,7 @@ def test_view_with_unwrapped_context(): We also want to be able to render the file-based ZPT without requiring that the context be wrapped: - >>> falcon = queryMultiAdapter((unwrapped, self.app.REQUEST), + >>> falcon = queryMultiAdapter((unwrapped, self.app.REQUEST), # NOQA: F821 ... Interface, 'falcon.html') >>> falcon is not None True diff --git a/src/Products/Five/browser/tests/test_pagetemplatefile.py b/src/Products/Five/browser/tests/test_pagetemplatefile.py index e95ca2c4ba..ad314fddaf 100644 --- a/src/Products/Five/browser/tests/test_pagetemplatefile.py +++ b/src/Products/Five/browser/tests/test_pagetemplatefile.py @@ -201,6 +201,7 @@ def _adapt(context, request): mapper = self._makeOne() self.assertTrue(mapper['test'] is self) + _marker = object() @@ -259,6 +260,7 @@ def test___call___wo_real_self_w_args_w_kw(self): self.assertEqual(rendered, '

Dummy

') self.assertEqual(pt._called_with, ('abc', ('def',), {'foo': 'bar'})) + DIRPAGE1 = """\

This is page 1

diff --git a/src/Products/Five/browser/tests/test_scriptsecurity.py b/src/Products/Five/browser/tests/test_scriptsecurity.py index 076971185f..ec85dc73d0 100644 --- a/src/Products/Five/browser/tests/test_scriptsecurity.py +++ b/src/Products/Five/browser/tests/test_scriptsecurity.py @@ -43,10 +43,11 @@ def test_resource_restricted_code(): >>> zcml.load_config("configure.zcml", Products.Five) >>> zcml.load_config('resource.zcml', ... package=Products.Five.browser.tests) + >>> folder = self.folder # NOQA: F821 >>> from Products.Five.tests.testing import ( ... manage_addFiveTraversableFolder) - >>> manage_addFiveTraversableFolder(self.folder, 'testoid', 'Testoid') + >>> manage_addFiveTraversableFolder(folder, 'testoid', 'Testoid') >>> import os, glob >>> _prefix = os.path.dirname(Products.Five.browser.tests.__file__) @@ -67,7 +68,7 @@ def test_resource_restricted_code(): >>> for resource in resource_names: ... checkUnauthorized( - ... self.folder, + ... folder, ... 'context.restrictedTraverse("testoid/++resource++%s")()' % ... resource) @@ -75,19 +76,19 @@ def test_resource_restricted_code(): >>> for resource in dir_resource_names: ... path = base % resource ... checkUnauthorized( - ... self.folder, 'context.restrictedTraverse("%s")' % path) + ... folder, 'context.restrictedTraverse("%s")' % path) Now let's create a manager user account and log in: - >>> uf = self.folder.acl_users + >>> uf = folder.acl_users >>> _ignored = uf._doAddUser('manager', 'r00t', ['Manager'], []) - >>> self.login('manager') + >>> self.login('manager') # NOQA: F821 We can now view them all: >>> for resource in resource_names: ... checkRestricted( - ... self.folder, + ... folder, ... 'context.restrictedTraverse("testoid/++resource++%s")()' % ... resource) @@ -95,16 +96,16 @@ def test_resource_restricted_code(): >>> for resource in dir_resource_names: ... path = base % resource ... checkRestricted( - ... self.folder, 'context.restrictedTraverse("%s")' %path) + ... folder, 'context.restrictedTraverse("%s")' %path) Let's make sure restrictedTraverse() works directly, too. It used to get tripped up on subdirectories due to missing security declarations. - >>> self.folder.restrictedTraverse( + >>> folder.restrictedTraverse( ... '++resource++fivetest_resources/resource.txt') is not None True - >>> self.folder.restrictedTraverse( + >>> folder.restrictedTraverse( ... '++resource++fivetest_resources/resource_subdir/resource.txt' ... ) is not None True @@ -124,19 +125,20 @@ def test_view_restricted_code(): >>> from Zope2.App import zcml >>> zcml.load_config("configure.zcml", Products.Five) >>> zcml.load_config('pages.zcml', package=Products.Five.browser.tests) + >>> folder = self.folder # NOQA: F821 Let's add a test object that we view most of the pages off of: >>> from Products.Five.tests.testing.simplecontent import ( ... manage_addSimpleContent) - >>> manage_addSimpleContent(self.folder, 'testoid', 'Testoid') + >>> manage_addSimpleContent(folder, 'testoid', 'Testoid') We also need to create a stub user account and login; otherwise we wouldn't have all the rights to do traversal etc.: - >>> uf = self.folder.acl_users + >>> uf = folder.acl_users >>> _ignored = uf._doAddUser('manager', 'r00t', ['Manager'], []) - >>> self.login('manager') + >>> self.login('manager') # NOQA: F821 >>> protected_view_names = [ ... 'eagle.txt', 'falcon.html', 'owl.html', 'flamingo.html', @@ -157,34 +159,34 @@ def test_view_restricted_code(): As long as we're not authenticated, we should get Unauthorized for protected views, but we should be able to view the public ones: - >>> self.logout() + >>> self.logout() # NOQA: F821 >>> for view_name in protected_view_names: ... checkUnauthorized( - ... self.folder, + ... folder, ... 'context.restrictedTraverse("testoid/%s")()' % view_name) >>> for view_name in public_view_names: ... checkRestricted( - ... self.folder, + ... folder, ... 'context.restrictedTraverse("testoid/%s")()' % view_name) - >>> self.login('manager') + >>> self.login('manager') # NOQA: F821 Being logged in as a manager again, we find that the protected pages are accessible to us: >>> for view_name in protected_view_names: ... checkRestricted( - ... self.folder, + ... folder, ... 'context.restrictedTraverse("testoid/%s")()' % view_name) >>> checkRestricted( - ... self.folder, + ... folder, ... 'context.restrictedTraverse("testoid/eagle.method").eagle()') Even when logged in though the private methods should not be accessible: >>> checkUnauthorized( - ... self.folder, + ... folder, ... 'context.restrictedTraverse("testoid/eagle.method").mouse()') Cleanup: diff --git a/src/Products/Five/browser/tests/test_traversable.py b/src/Products/Five/browser/tests/test_traversable.py index 2d8c63325f..430f013287 100644 --- a/src/Products/Five/browser/tests/test_traversable.py +++ b/src/Products/Five/browser/tests/test_traversable.py @@ -26,6 +26,8 @@ def test_traversable(): >>> import Products.Five >>> from Zope2.App import zcml >>> zcml.load_config("configure.zcml", Products.Five) + >>> folder = self.folder # NOQA: F821 + >>> http = http # NOQA: F821 ``SimpleContent`` is a traversable class by default. Its fallback traverser should raise NotFound when traversal fails. (Note: If @@ -35,7 +37,7 @@ def test_traversable(): >>> from Products.Five.tests.testing.simplecontent import ( ... manage_addSimpleContent) - >>> manage_addSimpleContent(self.folder, 'testoid', 'Testoid') + >>> manage_addSimpleContent(folder, 'testoid', 'Testoid') >>> print(http(r''' ... GET /test_folder_1_/testoid/doesntexist HTTP/1.1 ... ''')) @@ -82,7 +84,7 @@ def test_traversable(): >>> from Products.Five.tests.testing.fancycontent import ( ... manage_addFancyContent) - >>> info = manage_addFancyContent(self.folder, 'fancy', '') + >>> info = manage_addFancyContent(folder, 'fancy', '') In the following test we let the original __bobo_traverse__ method kick in: @@ -140,8 +142,8 @@ def test_traversable(): >>> from Products.Five.tests.testing.fancycontent import ( ... manage_addNonTraversableFancyContent) >>> info = manage_addNonTraversableFancyContent( - ... self.folder, 'fancy_zope2', '') - >>> self.folder.fancy_zope2.an_attribute = 'This is an attribute' + ... folder, 'fancy_zope2', '') + >>> folder.fancy_zope2.an_attribute = 'This is an attribute' >>> print(http(r''' ... GET /test_folder_1_/fancy_zope2/an_attribute HTTP/1.1 ... ''')) @@ -153,7 +155,7 @@ def test_traversable(): value 'This is an attribute'. Let's make sure the same thing happens for an object that has been marked traversable by Five: - >>> self.folder.fancy.an_attribute = 'This is an attribute' + >>> folder.fancy.an_attribute = 'This is an attribute' >>> print(http(r''' ... GET /test_folder_1_/fancy/an_attribute HTTP/1.1 ... ''')) @@ -218,18 +220,20 @@ def test_view_doesnt_shadow_attribute(): >>> from Zope2.App import zcml >>> zcml.load_config("configure.zcml", Products.Five) >>> zcml.load_string(configure_zcml) + >>> folder = self.folder # NOQA: F821 + >>> http = http # NOQA: F821 Then we create a traversable folder... >>> from Products.Five.tests.testing.folder import ( ... manage_addFiveTraversableFolder) - >>> manage_addFiveTraversableFolder(self.folder, 'ftf') + >>> manage_addFiveTraversableFolder(folder, 'ftf') and add an object called ``eagle`` to it: >>> from Products.Five.tests.testing.simplecontent import ( ... manage_addIndexSimpleContent) - >>> manage_addIndexSimpleContent(self.folder.ftf, 'eagle', 'Eagle') + >>> manage_addIndexSimpleContent(folder.ftf, 'eagle', 'Eagle') When we publish the ``ftf/eagle`` now, we expect the attribute to take precedence over the view during traversal: @@ -274,7 +278,7 @@ def test_view_doesnt_shadow_attribute(): However, acquired attributes *should* be shadowed. See discussion on http://codespeak.net/pipermail/z3-five/2006q2/001474.html - >>> manage_addIndexSimpleContent(self.folder, 'mouse', 'Mouse') + >>> manage_addIndexSimpleContent(folder, 'mouse', 'Mouse') >>> print(http(r''' ... GET /test_folder_1_/ftf/mouse HTTP/1.1 ... ''')) diff --git a/src/Products/Five/browser/tests/test_zope3security.py b/src/Products/Five/browser/tests/test_zope3security.py index 81a525d4c6..bc895c9b1c 100644 --- a/src/Products/Five/browser/tests/test_zope3security.py +++ b/src/Products/Five/browser/tests/test_zope3security.py @@ -26,13 +26,14 @@ def test_check_permission(): >>> from Zope2.App import zcml >>> zcml.load_config("configure.zcml", Products.Five) >>> zcml.load_string(configure_zcml) + >>> folder = self.folder # NOQA: F821 In order to be able to traverse to the PageTemplate view, we need a traversable object: >>> from Products.Five.tests.testing import ( ... manage_addFiveTraversableFolder) - >>> manage_addFiveTraversableFolder(self.folder, 'testoid', 'Testoid') + >>> manage_addFiveTraversableFolder(folder, 'testoid', 'Testoid') Now we access a page that uses zope.security.management.checkPermission(). We see it works as diff --git a/src/Products/Five/component/__init__.py b/src/Products/Five/component/__init__.py index cdb0525243..e4cfc7a88f 100644 --- a/src/Products/Five/component/__init__.py +++ b/src/Products/Five/component/__init__.py @@ -30,6 +30,8 @@ # Hook up custom component architecture calls from zope.component.hooks import setHooks + + setHooks() @@ -59,6 +61,7 @@ class LocalSiteHook(ExtensionClass.Base): def __call__(self, container, request): zope.event.notify(BeforeTraverseEvent(container, request)) + HOOK_NAME = '__local_site_hook__' diff --git a/src/Products/Five/skin/tests/test_standardmacros.py b/src/Products/Five/skin/tests/test_standardmacros.py index 9ff55676b0..e4e2f8d314 100644 --- a/src/Products/Five/skin/tests/test_standardmacros.py +++ b/src/Products/Five/skin/tests/test_standardmacros.py @@ -18,13 +18,14 @@ def test_standard_macros(): """Test standard macros - >>> uf = self.folder.acl_users + >>> folder = self.folder # NOQA: F821 + >>> uf = folder.acl_users >>> _ignored = uf._doAddUser('manager', 'r00t', ['Manager'], []) - >>> self.login('manager') + >>> self.login('manager') # NOQA: F821 >>> from Products.Five.tests.testing import ( ... manage_addFiveTraversableFolder) - >>> manage_addFiveTraversableFolder(self.folder, 'testoid', 'Testoid') + >>> manage_addFiveTraversableFolder(folder, 'testoid', 'Testoid') >>> import Products.Five.skin.tests >>> from Zope2.App import zcml @@ -34,7 +35,7 @@ def test_standard_macros(): Test macro access through our flavour of StandardMacros. First, when looking up a non-existing macro, we get a KeyError: - >>> view = self.folder.unrestrictedTraverse('testoid/@@fivetest_macros') + >>> view = folder.unrestrictedTraverse('testoid/@@fivetest_macros') >>> view['non-existing-macro'] Traceback (most recent call last): ... @@ -60,7 +61,7 @@ def test_standard_macros(): >>> base = 'testoid/@@fivetest_macros/%s' >>> for macro in ('birdmacro', 'dogmacro', 'flying', 'walking'): - ... view = self.folder.unrestrictedTraverse(base % macro) + ... view = folder.unrestrictedTraverse(base % macro) ... view is not None True True diff --git a/src/Products/Five/tests/test_directives.py b/src/Products/Five/tests/test_directives.py index f946c0be91..3a33689af8 100644 --- a/src/Products/Five/tests/test_directives.py +++ b/src/Products/Five/tests/test_directives.py @@ -58,7 +58,7 @@ def test_directives(): Check the result of the directives - >>> from Products.Five.tests.classes import One, Two, IOne, ITwo + >>> from Products.Five.tests.classes import One, IOne, ITwo >>> IOne.implementedBy(One) True >>> ITwo.implementedBy(One) diff --git a/src/Products/Five/tests/test_i18n.py b/src/Products/Five/tests/test_i18n.py index 0a27bf240b..b044f9fa40 100644 --- a/src/Products/Five/tests/test_i18n.py +++ b/src/Products/Five/tests/test_i18n.py @@ -14,7 +14,8 @@ """Unit tests for the i18n framework """ -from zope.component.testing import setUp, tearDown +from zope.component.testing import setUp +from zope.component.testing import tearDown def test_directive(): @@ -48,7 +49,7 @@ def test_directive(): >>> translate(msg) == u'This is an explicit message' True - >>> translate(msg, target_language='de') == u'Dies ist eine explizite Nachricht' + >>> translate(msg, target_language='de') == u'Dies ist eine explizite Nachricht' # NOQA: E501 True """ diff --git a/src/Products/Five/tests/test_size.py b/src/Products/Five/tests/test_size.py index d95c185916..1b5de53938 100644 --- a/src/Products/Five/tests/test_size.py +++ b/src/Products/Five/tests/test_size.py @@ -79,6 +79,7 @@ def test_size(): >>> from Zope2.App import zcml >>> zcml.load_config('meta.zcml', Products.Five) >>> zcml.load_string(configure_zcml) + >>> folder = self.folder # NOQA: F821 >>> from Products.Five.tests.testing.simplecontent import ( ... manage_addSimpleContent) @@ -87,14 +88,14 @@ def test_size(): We have registered an ``ISized`` adapter for SimpleContent: - >>> n = manage_addSimpleContent(self.folder, 'simple', 'Simple') - >>> self.folder.simple.get_size() + >>> n = manage_addSimpleContent(folder, 'simple', 'Simple') + >>> folder.simple.get_size() 42 Fancy content already has a ``get_size`` method - >>> n = manage_addFancyContent(self.folder, 'fancy', 'Fancy') - >>> self.folder.fancy.get_size() + >>> n = manage_addFancyContent(folder, 'fancy', 'Fancy') + >>> folder.fancy.get_size() 43 Clean up: diff --git a/src/Products/Five/tests/testing/fancycontent.py b/src/Products/Five/tests/testing/fancycontent.py index 7292958af6..a6bf20622c 100644 --- a/src/Products/Five/tests/testing/fancycontent.py +++ b/src/Products/Five/tests/testing/fancycontent.py @@ -35,11 +35,12 @@ def __init__(self, name): security = ClassSecurityInfo() - security.declarePublic('index_html') + @security.public def index_html(self, REQUEST): """Doc test fanatics""" return self.name + InitializeClass(FancyAttribute) @@ -66,6 +67,7 @@ def __bobo_traverse__(self, REQUEST, name): def get_size(self): return 43 + InitializeClass(FancyContent) @@ -92,6 +94,7 @@ def __bobo_traverse__(self, REQUEST, name): def get_size(self): return 43 + InitializeClass(NonTraversableFancyContent) diff --git a/src/Products/Five/tests/testing/simplecontent.py b/src/Products/Five/tests/testing/simplecontent.py index 54a91bcb78..43e5008b7d 100644 --- a/src/Products/Five/tests/testing/simplecontent.py +++ b/src/Products/Five/tests/testing/simplecontent.py @@ -44,16 +44,17 @@ def __init__(self, id, title): self.id = id self.title = title - security.declarePublic('mymethod') + @security.public def mymethod(self): return "Hello world" - security.declarePublic('direct') + @security.public def direct(self): """Should be able to traverse directly to this as there is no view. """ return "Direct traversal worked" + InitializeClass(SimpleContent) @@ -67,6 +68,7 @@ def __call__(self, *args, **kw): """ """ return "Default __call__ called" + InitializeClass(CallableSimpleContent) @@ -80,6 +82,7 @@ def index_html(self, *args, **kw): """ """ return "Default index_html called" + InitializeClass(IndexSimpleContent) diff --git a/src/Products/Five/utilities/marker.py b/src/Products/Five/utilities/marker.py index aa8ab3bd26..23ec165617 100644 --- a/src/Products/Five/utilities/marker.py +++ b/src/Products/Five/utilities/marker.py @@ -40,6 +40,7 @@ def mark(ob, interface): def erase(ob, interface): directlyProvides(ob, directlyProvidedBy(ob) - interface) + mark = interfaceStringCheck(mark) erase = interfaceStringCheck(erase) @@ -74,8 +75,8 @@ def getAvailableInterfaces(self): todo.append(base) markers = self._getDirectMarkersOf(interface) for interface in markers: - if (interface not in results and - not interface.providedBy(self.context)): + if interface not in results and \ + not interface.providedBy(self.context): results.append(interface) todo += markers return tuple(results) diff --git a/src/Products/Five/viewlet/manager.py b/src/Products/Five/viewlet/manager.py index a2c5ab4bdf..ac39f776bb 100644 --- a/src/Products/Five/viewlet/manager.py +++ b/src/Products/Five/viewlet/manager.py @@ -93,12 +93,12 @@ def ViewletManager(name, interface, template=None, bases=()): if ViewletManagerBase not in bases: # Make sure that we do not get a default viewlet manager mixin, if the # provided base is already a full viewlet manager implementation. - if not (len(bases) == 1 and - interfaces.IViewletManager.implementedBy(bases[0])): + if not (len(bases) == 1 + and interfaces.IViewletManager.implementedBy(bases[0])): bases = bases + (ViewletManagerBase,) ViewletManager = type( '' % interface.getName(), bases, attrDict) - zope.interface.classImplements(ViewletManager, interface) + zope.interface.classImplements(ViewletManager, interface) # NOQA: D001 return ViewletManager diff --git a/src/Products/Five/viewlet/viewlet.py b/src/Products/Five/viewlet/viewlet.py index 62fc7923fe..459c44243f 100644 --- a/src/Products/Five/viewlet/viewlet.py +++ b/src/Products/Five/viewlet/viewlet.py @@ -15,7 +15,9 @@ """ import os + import six + import zope.viewlet.viewlet from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile @@ -27,6 +29,7 @@ class ViewletBase(zope.viewlet.viewlet.ViewletBase): class SimpleAttributeViewlet(zope.viewlet.viewlet.SimpleAttributeViewlet): pass + class simple(zope.viewlet.viewlet.simple): # We need to ensure that the proper __init__ is called. if six.PY2: diff --git a/src/Products/PageTemplates/Expressions.py b/src/Products/PageTemplates/Expressions.py index f44e48fa1c..759f4d8b52 100644 --- a/src/Products/PageTemplates/Expressions.py +++ b/src/Products/PageTemplates/Expressions.py @@ -424,6 +424,7 @@ def createTrustedZopeEngine(): e.types['python'] = PythonExpr return e + _engine = createZopeEngine() diff --git a/src/Products/PageTemplates/PageTemplateFile.py b/src/Products/PageTemplates/PageTemplateFile.py index 6ca5e25d0f..fab0e6b020 100644 --- a/src/Products/PageTemplates/PageTemplateFile.py +++ b/src/Products/PageTemplates/PageTemplateFile.py @@ -54,9 +54,11 @@ def guess_type(filename, body): return sniff_type(body) or 'text/html' -# REFACT: Make this a subclass of zope.pagetemplate.pagetemplatefile.PageTemplateFile -# That class has been forked off of this code and now we have duplication. They already -# share a common superclass (zope.pagetemplate.pagetemplate.PageTemplate). +# REFACT: Make this a subclass of +# zope.pagetemplate.pagetemplatefile.PageTemplateFile +# That class has been forked off of this code and now we have duplication. +# They already share a common superclass +# zope.pagetemplate.pagetemplate.PageTemplate class PageTemplateFile(SimpleItem, Script, PageTemplate, Traversable): """Zope 2 implementation of a PageTemplate loaded from a file.""" @@ -234,4 +236,5 @@ def __getstate__(self): raise StorageError("Instance of AntiPersistent class %s " "cannot be stored." % self.__class__.__name__) + InitializeClass(PageTemplateFile) diff --git a/src/Products/PageTemplates/ZRPythonExpr.py b/src/Products/PageTemplates/ZRPythonExpr.py index 5415c5d33e..4ab3ffeea1 100644 --- a/src/Products/PageTemplates/ZRPythonExpr.py +++ b/src/Products/PageTemplates/ZRPythonExpr.py @@ -15,8 +15,6 @@ Handler for Python expressions that uses the RestrictedPython package. """ -import sys - from AccessControl import safe_builtins from AccessControl.ZopeGuards import guarded_getattr, get_safe_globals from DocumentTemplate.DT_Util import TemplateDict, InstanceDict diff --git a/src/Products/PageTemplates/ZopePageTemplate.py b/src/Products/PageTemplates/ZopePageTemplate.py index 8d83aa55fb..afeb63a53b 100644 --- a/src/Products/PageTemplates/ZopePageTemplate.py +++ b/src/Products/PageTemplates/ZopePageTemplate.py @@ -14,7 +14,6 @@ """ import os -import sys from AccessControl.class_init import InitializeClass from AccessControl.Permissions import change_page_templates @@ -40,12 +39,11 @@ from Products.PageTemplates.PageTemplate import PageTemplate from Products.PageTemplates.PageTemplateFile import PageTemplateFile from Products.PageTemplates.PageTemplateFile import guess_type -from Products.PageTemplates.utils import encodingFromXMLPreamble -from Products.PageTemplates.utils import charsetFromMetaEquiv from Products.PageTemplates.utils import convertToUnicode from six import text_type, binary_type + preferred_encodings = ['utf-8', 'iso-8859-15'] if 'ZPT_PREFERRED_ENCODING' in os.environ: preferred_encodings.insert(0, os.environ['ZPT_PREFERRED_ENCODING']) @@ -67,6 +65,7 @@ def __call__(self, REQUEST, RESPONSE): " " return self.document_src(REQUEST) + InitializeClass(Src) @@ -103,8 +102,8 @@ class ZopePageTemplate(Script, PageTemplate, Cacheable, security.declareObjectProtected(view) # protect methods from base class(es) - security.declareProtected(view, '__call__') - security.declareProtected(view_management_screens, + security.declareProtected(view, '__call__') # NOQA: D001 + security.declareProtected(view_management_screens, # NOQA: D001 'read', 'ZScriptHTML_tryForm') def __init__(self, id, text=None, content_type='text/html', strict=True, @@ -120,12 +119,12 @@ def __init__(self, id, text=None, content_type='text/html', strict=True, content_type = 'text/html' self.pt_edit(text, content_type) - security.declareProtected(change_page_templates, 'pt_edit') + @security.protected(change_page_templates) def pt_edit(self, text, content_type, keep_output_encoding=False): if not isinstance(text, text_type): - text_decoded, source_encoding = convertToUnicode(text, - content_type, - preferred_encodings) + (text_decoded, + source_encoding) = convertToUnicode(text, content_type, + preferred_encodings) output_encoding = source_encoding else: text_decoded = text @@ -148,7 +147,7 @@ def pt_edit(self, text, content_type, keep_output_encoding=False): source_dot_xml = Src() - security.declareProtected(change_page_templates, 'pt_editAction') + @security.protected(change_page_templates) def pt_editAction(self, REQUEST, title, text, content_type, expand=0): """Change the title and document.""" @@ -170,7 +169,7 @@ def pt_editAction(self, REQUEST, title, text, content_type, expand=0): % '
'.join(self._v_warnings)) return self.pt_editForm(manage_tabs_message=message) - security.declareProtected(change_page_templates, 'pt_setTitle') + @security.protected(change_page_templates) def pt_setTitle(self, title, encoding='utf-8'): if not isinstance(title, text_type): title = title.decode(encoding) @@ -181,7 +180,7 @@ def _setPropValue(self, id, value): PropertyManager._setPropValue(self, id, value) self.ZCacheable_invalidate() - security.declareProtected(change_page_templates, 'pt_upload') + @security.protected(change_page_templates) def pt_upload(self, REQUEST, file='', encoding='utf-8'): """Replace the document with the text in file.""" @@ -201,9 +200,9 @@ def pt_upload(self, REQUEST, file='', encoding='utf-8'): if isinstance(text, binary_type): content_type = guess_type(filename, text) - text, source_encoding = convertToUnicode(text, - content_type, - preferred_encodings) + (text, + source_encoding) = convertToUnicode(text, content_type, + preferred_encodings) elif isinstance(text, text_type): content_type = guess_type(filename, text.encode('utf-8')) @@ -281,7 +280,7 @@ def _exec(self, bound_names, args, kw): security.removeContext(self) if bbb.HAS_ZSERVER: - security.declareProtected(change_page_templates, 'PUT') + @security.protected(change_page_templates) def PUT(self, REQUEST, RESPONSE): """ Handle HTTP PUT requests """ @@ -293,7 +292,8 @@ def PUT(self, REQUEST, RESPONSE): RESPONSE.setStatus(204) return RESPONSE - security.declareProtected(change_page_templates, 'manage_FTPput') + security.declareProtected(change_page_templates, # NOQA: D001 + 'manage_FTPput') manage_FTPput = PUT @security.protected(ftp_access) @@ -302,23 +302,23 @@ def manage_FTPget(self): result = self.read() return result.encode(self.output_encoding) - security.declareProtected(view_management_screens, 'html') + @security.protected(view_management_screens) def html(self): return self.content_type == 'text/html' - security.declareProtected(view_management_screens, 'get_size') + @security.protected(view_management_screens) def get_size(self): return len(self.read()) - security.declareProtected(view_management_screens, 'getSize') + security.declareProtected(view_management_screens, 'getSize') # NOQA: D001 getSize = get_size - security.declareProtected(view_management_screens, 'PrincipiaSearchSource') + @security.protected(view_management_screens) def PrincipiaSearchSource(self): "Support for searching - the document's contents are searched." return self.read() - security.declareProtected(view_management_screens, 'document_src') + @security.protected(view_management_screens) def document_src(self, REQUEST=None, RESPONSE=None): """Return expanded document source.""" if RESPONSE is not None: @@ -327,7 +327,7 @@ def document_src(self, REQUEST=None, RESPONSE=None): return self._text return self.read() - security.declareProtected(view, 'pt_source_file') + @security.protected(view) def pt_source_file(self): """Returns a file name to be compiled into the TAL code.""" try: diff --git a/src/Products/PageTemplates/expression.py b/src/Products/PageTemplates/expression.py index b80c299b10..158008f4eb 100644 --- a/src/Products/PageTemplates/expression.py +++ b/src/Products/PageTemplates/expression.py @@ -80,8 +80,8 @@ def __call__(self, base, econtext, call, path_items): if call is False: return base - if (getattr(base, '__call__', _marker) is not _marker or - callable(base)): + if getattr(base, '__call__', _marker) is not _marker or \ + callable(base): base = render(base, econtext) return base @@ -100,8 +100,8 @@ def __call__(self, base, econtext, call, path_items): if call is False: return base - if (getattr(base, '__call__', _marker) is not _marker or - isinstance(base, class_types)): + if getattr(base, '__call__', _marker) is not _marker or \ + isinstance(base, class_types): return base() return base diff --git a/src/Products/PageTemplates/tests/testZopePageTemplate.py b/src/Products/PageTemplates/tests/testZopePageTemplate.py index 9913c5f2e2..d597305b02 100644 --- a/src/Products/PageTemplates/tests/testZopePageTemplate.py +++ b/src/Products/PageTemplates/tests/testZopePageTemplate.py @@ -5,7 +5,6 @@ Ensures that adding a page template works correctly. """ -import codecs import unittest import transaction @@ -32,6 +31,7 @@ from six import text_type + ascii_binary = b'hello world' iso885915_binary = u'üöäÜÖÄß'.encode('iso-8859-15') utf8_text = iso885915_binary.decode('iso-8859-15').encode('utf-8') @@ -56,7 +56,8 @@ ''' -html_binary_iso_8859_15_w_header = (html_template_w_header % 'iso-8859-15').encode('iso-8859-15') +html_binary_iso_8859_15_w_header = ( + html_template_w_header % 'iso-8859-15').encode('iso-8859-15') html_binary_utf8_w_header = (html_template_w_header % 'utf-8').encode('utf-8') html_template_wo_header = u''' @@ -162,9 +163,9 @@ def testUTF8WrongPreferredCharset(self): self.assertFalse(result.startswith(u'
üöä
')) def testStructureWithAccentedChars(self): + raw = u'
' manage_addPageTemplate(self.app, 'test', - text=((u'
').encode('iso-8859-15')), + text=raw.encode('iso-8859-15'), encoding='iso-8859-15') zpt = self.app['test'] self.app.REQUEST.set('HTTP_ACCEPT_CHARSET', 'iso-8859-15,utf-8') @@ -172,9 +173,9 @@ def testStructureWithAccentedChars(self): self.assertTrue(result.startswith(u'
üöä
')) def testBug151020(self): + raw = u'
' manage_addPageTemplate(self.app, 'test', - text=((u'
').encode('iso-8859-15')), + text=raw.encode('iso-8859-15'), encoding='iso-8859-15') zpt = self.app['test'] self.app.REQUEST.set('HTTP_ACCEPT_CHARSET', @@ -260,7 +261,8 @@ def testPT_RenderWithISO885915(self): zpt = self.app['test'] result = zpt.pt_render() # use startswith() because the renderer appends a trailing \n - self.assertTrue(result.encode('iso-8859-15').startswith(iso885915_binary)) + res_encoded = result.encode('iso-8859-15') + self.assertTrue(res_encoded.startswith(iso885915_binary)) self.assertEqual(zpt.output_encoding, 'utf-8') def testPT_RenderWithUTF8(self): @@ -281,7 +283,8 @@ def testWriteAcceptsUnicode(self): self.assertEqual(isinstance(zpt.read(), text_type), True) def testEditWithContentTypeCharset(self): - manage_addPageTemplate(self.app, 'test', xml_binary_utf8, encoding='utf-8') + manage_addPageTemplate(self.app, 'test', xml_binary_utf8, + encoding='utf-8') zpt = self.app['test'] xml_unicode = xml_binary_utf8.decode('utf-8').strip() zpt.pt_edit(xml_unicode, 'text/xml') @@ -500,6 +503,7 @@ def test___call__(self): response = object() self.assertEqual(src(request, response), 'TESTING') + class ZPTBrowserTests(FunctionalTestCase): """Browser testing ZopePageTemplate""" diff --git a/src/Products/PageTemplates/tests/test_persistenttemplate.py b/src/Products/PageTemplates/tests/test_persistenttemplate.py index 5989b4fde7..3cfe711890 100644 --- a/src/Products/PageTemplates/tests/test_persistenttemplate.py +++ b/src/Products/PageTemplates/tests/test_persistenttemplate.py @@ -94,6 +94,7 @@ def generate_capture_source(names): for name in names) return options_capture_update_base % (params,) + textarea_content_search = re.compile( r']*>([^<]+)', re.IGNORECASE | re.MULTILINE @@ -105,6 +106,7 @@ def get_editable_content(template): editable_text = textarea_content_search(edit_form).group(1) return editable_text + _marker = object() diff --git a/src/Products/PageTemplates/tests/test_ptfile.py b/src/Products/PageTemplates/tests/test_ptfile.py index 2b8af2b012..ed64d5789e 100644 --- a/src/Products/PageTemplates/tests/test_ptfile.py +++ b/src/Products/PageTemplates/tests/test_ptfile.py @@ -101,7 +101,9 @@ def test_sniffer_xml_utf16_le(self): def test_sniffer_html_ascii(self): self.check_content_type( - b"", + (b""), "text/html") self.check_content_type( b"sample document", diff --git a/src/Products/PageTemplates/tests/test_viewpagetemplatefile.py b/src/Products/PageTemplates/tests/test_viewpagetemplatefile.py index be307a9123..d8202d291f 100644 --- a/src/Products/PageTemplates/tests/test_viewpagetemplatefile.py +++ b/src/Products/PageTemplates/tests/test_viewpagetemplatefile.py @@ -66,7 +66,8 @@ def test_locals(self): self.assertTrue('here==container:True' in result) self.assertTrue("root:(\'\',)" in result) self.assertTrue("nothing:" in result) - self.assertTrue("parse" in result) # this tests for the existence of the cgi.parse function + # test for the existence of the cgi.parse function + self.assertTrue("parse" in result) def test_options(self): view = OptionsView(self.folder, self.folder.REQUEST) diff --git a/src/Products/PageTemplates/tests/util.py b/src/Products/PageTemplates/tests/util.py index 436e8c6d54..a4adc61ddd 100644 --- a/src/Products/PageTemplates/tests/util.py +++ b/src/Products/PageTemplates/tests/util.py @@ -44,8 +44,7 @@ def __len__(self): return 7 def __getitem__(self, index): - if (isinstance(index, int) and - (index < 0 or index > 6)): + if isinstance(index, int) and (index < 0 or index > 6): raise IndexError(index) return self @@ -54,6 +53,7 @@ def __getattr__(self, name): raise AttributeError(name) return self + bruce = Bruce() diff --git a/src/Products/PageTemplates/unicodeconflictresolver.py b/src/Products/PageTemplates/unicodeconflictresolver.py index 2636854063..4284091caa 100644 --- a/src/Products/PageTemplates/unicodeconflictresolver.py +++ b/src/Products/PageTemplates/unicodeconflictresolver.py @@ -21,7 +21,7 @@ from zope.i18n.interfaces import IUserPreferredCharsets import ZPublisher -from six import text_type, binary_type +from six import text_type default_encoding = sys.getdefaultencoding() @@ -38,6 +38,7 @@ def resolve(self, context, text, expression): return text return text.decode('ascii') + DefaultUnicodeEncodingConflictResolver = \ DefaultUnicodeEncodingConflictResolver() diff --git a/src/Products/SiteAccess/VirtualHostMonster.py b/src/Products/SiteAccess/VirtualHostMonster.py index 47a9e3c577..4ca84bab60 100644 --- a/src/Products/SiteAccess/VirtualHostMonster.py +++ b/src/Products/SiteAccess/VirtualHostMonster.py @@ -38,14 +38,14 @@ class VirtualHostMonster(Persistent, Item, Implicit): {'label': 'Mappings', 'action': 'manage_edit'}, ) - security.declareProtected(View, 'manage_main') + security.declareProtected(View, 'manage_main') # NOQA: D001 manage_main = DTMLFile('www/VirtualHostMonster', globals(), __name__='manage_main') - security.declareProtected('Add Site Roots', 'manage_edit') + security.declareProtected('Add Site Roots', 'manage_edit') # NOQA: D001 manage_edit = DTMLFile('www/manage_edit', globals()) - security.declareProtected('Add Site Roots', 'set_map') + @security.protected('Add Site Roots') def set_map(self, map_text, RESPONSE=None): "Set domain to path mappings." lines = map_text.split('\n') @@ -61,7 +61,7 @@ def set_map(self, map_text, RESPONSE=None): line = line.split('://')[-1] try: host, path = [x.strip() for x in line.split('/', 1)] - except: + except Exception: raise ValueError( 'Line needs a slash between host and path: %s' % line) pp = filter(None, path.split('/')) @@ -78,7 +78,7 @@ def set_map(self, map_text, RESPONSE=None): if obpath: try: ob = self.unrestrictedTraverse(obpath) - except: + except Exception: raise ValueError( 'Path not found: %s' % obpath) if not getattr(ob.aq_base, 'isAnObjectManager', 0): @@ -174,7 +174,7 @@ def __call__(self, client, request, response=None): stack.insert(ii, '/') ii += 1 if '*' in stack: - stack[stack.index('*')] = host.split('.')[0] + stack[stack.index('*')] = host.split('.')[0] path = stack[:ii] # If the directive is on top of the stack, go ahead # and process it right away. @@ -201,8 +201,8 @@ def __call__(self, client, request, response=None): request['VIRTUAL_URL'] = '/'.join(vup) # new ACTUAL_URL - add = (path and - request['ACTUAL_URL'].endswith('/')) and '/' or '' + add = path and \ + request['ACTUAL_URL'].endswith('/') and '/' or '' request['ACTUAL_URL'] = request['VIRTUAL_URL'] + add return @@ -247,6 +247,7 @@ def __bobo_traverse__(self, request, name): request.setVirtualRoot([]) return parents.pop() # He'll get put back on + InitializeClass(VirtualHostMonster) @@ -261,6 +262,7 @@ def manage_addVirtualHostMonster(self, id=None, REQUEST=None, **ignored): qs = 'manage_tabs_message=Virtual+Host+Monster+added.' REQUEST['RESPONSE'].redirect('%s?%s' % (goto, qs)) + constructors = ( ('manage_addVirtualHostMonster', manage_addVirtualHostMonster), ) diff --git a/src/Products/SiteAccess/tests/testVirtualHostMonster.py b/src/Products/SiteAccess/tests/testVirtualHostMonster.py index 60af3d1eb0..761cea6ee0 100644 --- a/src/Products/SiteAccess/tests/testVirtualHostMonster.py +++ b/src/Products/SiteAccess/tests/testVirtualHostMonster.py @@ -100,7 +100,7 @@ def test_actual_url_w_VHR_no_doc_no_trailing_slash(self): def testWildcardRewrite(self): ob = self.traverse('/VirtualHostBase/http/doc.example.com:80' - '/folder/*/VirtualHostRoot') + '/folder/*/VirtualHostRoot') self.assertEqual(self.app.REQUEST['ACTUAL_URL'], 'http://doc.example.com/') self.assertEqual(ob.getPhysicalPath(), ('', 'folder', 'doc')) @@ -146,6 +146,7 @@ def test(self, vaddr=vaddr, vr=vr, _vh=_vh, p=p, ubase=ubase): setattr(VHMRegressions, 'testTraverse%s' % i, test) + class VHMPort(unittest.TestCase): def setUp(self): @@ -154,7 +155,7 @@ def setUp(self): from Testing.ZopeTestCase.ZopeLite import app transaction.begin() self.app = makerequest(app()) - if 'virtual_hosting' not in self.app.objectIds(): + if 'virtual_hosting' not in self.app.objectIds(): # If ZopeLite was imported, we have no default virtual # host monster from Products.SiteAccess.VirtualHostMonster \ diff --git a/src/Shared/DC/Scripts/Bindings.py b/src/Shared/DC/Scripts/Bindings.py index 44aab24e27..a8a873ed03 100644 --- a/src/Shared/DC/Scripts/Bindings.py +++ b/src/Shared/DC/Scripts/Bindings.py @@ -211,13 +211,13 @@ class Bindings(object): _Bindings_client = None - security.declareProtected('Change bindings', 'ZBindings_edit') + @security.protected('Change bindings') def ZBindings_edit(self, mapping): self._setupBindings(mapping) self._prepareBindCode() self._editedBindings() - security.declareProtected('Change bindings', 'ZBindings_setClient') + @security.protected('Change bindings') def ZBindings_setClient(self, clientname): '''Name the binding to be used as the "client". @@ -233,7 +233,7 @@ def _setupBindings(self, names={}): self._bind_names = names = NameAssignments(names) return names - security.declareProtected(view_management_screens, 'getBindingAssignments') + @security.protected(view_management_screens) def getBindingAssignments(self): if not hasattr(self, '_bind_names'): self._setupBindings() @@ -242,8 +242,8 @@ def getBindingAssignments(self): def __before_publishing_traverse__(self, self2, request): path = request['TraversalRequestNameStack'] names = self.getBindingAssignments() - if (not names.isNameAssigned('name_subpath') or - (path and hasattr(aq_base(self), path[-1]))): + if not names.isNameAssigned('name_subpath') or \ + (path and hasattr(aq_base(self), path[-1])): return subpath = path[:] path[:] = [] @@ -368,4 +368,5 @@ def _bindAndExec(self, args, kw, caller_namespace): finally: security.removeContext(self) + InitializeClass(Bindings) diff --git a/src/Shared/DC/Scripts/BindingsUI.py b/src/Shared/DC/Scripts/BindingsUI.py index 7ba1fe93e2..a3a243e760 100644 --- a/src/Shared/DC/Scripts/BindingsUI.py +++ b/src/Shared/DC/Scripts/BindingsUI.py @@ -26,11 +26,11 @@ class BindingsUI(Bindings): {'label': 'Bindings', 'action': 'ZBindingsHTML_editForm'}, ) - security.declareProtected(view_management_screens, + security.declareProtected(view_management_screens, # NOQA: D001 'ZBindingsHTML_editForm') ZBindingsHTML_editForm = DTMLFile('dtml/scriptBindings', globals()) - security.declareProtected('Change bindings', 'ZBindingsHTML_editAction') + @security.protected('Change bindings') def ZBindingsHTML_editAction(self, REQUEST): '''Changes binding names. ''' @@ -38,4 +38,5 @@ def ZBindingsHTML_editAction(self, REQUEST): message = "Bindings changed." return self.manage_main(self, REQUEST, manage_tabs_message=message) + InitializeClass(BindingsUI) diff --git a/src/Shared/DC/Scripts/Script.py b/src/Shared/DC/Scripts/Script.py index 93da28934f..e517eaeb66 100644 --- a/src/Shared/DC/Scripts/Script.py +++ b/src/Shared/DC/Scripts/Script.py @@ -43,7 +43,8 @@ class Script(SimpleItem, BindingsUI): _Bindings_ns_class = TemplateDict - security.declareProtected(view_management_screens, 'ZScriptHTML_tryForm') + security.declareProtected(view_management_screens, # NOQA: D001 + 'ZScriptHTML_tryForm') ZScriptHTML_tryForm = DTMLFile('dtml/scriptTry', globals()) def ZScriptHTML_tryAction(self, REQUEST, argvars): @@ -57,4 +58,5 @@ def ZScriptHTML_tryAction(self, REQUEST, argvars): from .Signature import _setFuncSignature + InitializeClass(Script) diff --git a/src/Shared/DC/Scripts/Signature.py b/src/Shared/DC/Scripts/Signature.py index 24fcc437a2..0fab24a463 100644 --- a/src/Shared/DC/Scripts/Signature.py +++ b/src/Shared/DC/Scripts/Signature.py @@ -32,13 +32,13 @@ def __init__(self, varnames=(), argcount=-1): def __eq__(self, other): if not isinstance(other, FuncCode): return False - return ((self.co_argcount, self.co_varnames) == + return ((self.co_argcount, self.co_varnames) == # NOQA: W504 (other.co_argcount, other.co_varnames)) def __lt__(self, other): if not isinstance(other, FuncCode): return False - return ((self.co_argcount, self.co_varnames) < + return ((self.co_argcount, self.co_varnames) < # NOQA: W504 (other.co_argcount, other.co_varnames)) diff --git a/src/Testing/ZopeTestCase/ZopeLite.py b/src/Testing/ZopeTestCase/ZopeLite.py index ab78ef9b22..bca57b73d6 100644 --- a/src/Testing/ZopeTestCase/ZopeLite.py +++ b/src/Testing/ZopeTestCase/ZopeLite.py @@ -62,6 +62,7 @@ def _exec(cmd): exec_(cmd) _print('(%.3fs)' % (time.time() - start)) + _write('Loading Zope, please stand by ') _start = time.time() @@ -94,6 +95,7 @@ def _configure_client_cache(): config.zeo_client_name = None App.config.setConfiguration(config) + _configure_logging() _configure_debug_mode() _configure_client_cache() @@ -146,6 +148,7 @@ def null_load_zcml(): global _patched _patched = True + _apply_patches() _theApp = None @@ -156,6 +159,7 @@ def _startup(): global _theApp _theApp = Zope2.app() + # Start ZopeLite _startup() @@ -236,6 +240,7 @@ def _installPackage(name, quiet=0): if not quiet: _print('Installing %s ... NOT FOUND\n' % name) + installProduct('OFSP', 1) # So people can use ZopeLite.app() @@ -248,6 +253,7 @@ def _installPackage(name, quiet=0): def startup(): pass + Zope = Zope2 active = _patched @@ -262,4 +268,5 @@ def sandbox(base=None): storage = DemoStorage(base=base._storage) return ZODB.DB(storage) + _write(' done (%.3fs)\n' % (time.time() - _start)) diff --git a/src/Testing/ZopeTestCase/layer.py b/src/Testing/ZopeTestCase/layer.py index 4ccf5c7a3a..b7b18e0698 100644 --- a/src/Testing/ZopeTestCase/layer.py +++ b/src/Testing/ZopeTestCase/layer.py @@ -15,6 +15,7 @@ from Testing.ZopeTestCase import utils + _deferred_setup = [] @@ -38,6 +39,7 @@ def tearDown(cls): See zope.testrunner-layers-ntd.txt ''' + ZopeLiteLayer = ZopeLite diff --git a/src/Testing/ZopeTestCase/placeless.py b/src/Testing/ZopeTestCase/placeless.py index 523234b2e0..795074e88c 100644 --- a/src/Testing/ZopeTestCase/placeless.py +++ b/src/Testing/ZopeTestCase/placeless.py @@ -51,6 +51,7 @@ def tearDown(doctesttest=None): tearDown_() return tearDown + tearDown = tearDown() del ps diff --git a/src/Testing/ZopeTestCase/sandbox.py b/src/Testing/ZopeTestCase/sandbox.py index ffa7a80d22..112cc752d0 100644 --- a/src/Testing/ZopeTestCase/sandbox.py +++ b/src/Testing/ZopeTestCase/sandbox.py @@ -75,5 +75,5 @@ def load_app(module_info): if not hasattr(ZPublisher.WSGIPublisher, '__old_load_app__'): - ZPublisher.WSGIPublisher.__old_load_app__ = ZPublisher.WSGIPublisher.load_app + ZPublisher.WSGIPublisher.__old_load_app__ = ZPublisher.WSGIPublisher.load_app # NOQA: E501 ZPublisher.WSGIPublisher.load_app = load_app diff --git a/src/Testing/ZopeTestCase/testFunctional.py b/src/Testing/ZopeTestCase/testFunctional.py index 21abcdfbd7..02d7faeaa7 100644 --- a/src/Testing/ZopeTestCase/testFunctional.py +++ b/src/Testing/ZopeTestCase/testFunctional.py @@ -27,6 +27,7 @@ from Testing.ZopeTestCase import user_name from Testing.ZopeTestCase import user_password + SET_COOKIE_DTML = '''\ ''' @@ -48,10 +49,10 @@ def afterSetUp(self): self.folder.secret_html.manage_permission(view, ['Owner']) # A method redirecting to the Zope root - url = self.app.absolute_url() + url = self.app.absolute_url().encode('ascii') self.folder.addDTMLMethod( 'redirect', - file=b'' % url.encode('ascii')) + file=b'' % url) # A method setting a cookie self.folder.addDTMLMethod('set_cookie', file=SET_COOKIE_DTML) diff --git a/src/Testing/ZopeTestCase/tests.py b/src/Testing/ZopeTestCase/tests.py index 58d08f1e60..d6dd44832a 100644 --- a/src/Testing/ZopeTestCase/tests.py +++ b/src/Testing/ZopeTestCase/tests.py @@ -13,16 +13,17 @@ """Test runner that works with zope.testrunner """ -import unittest import os +import unittest + import Testing.ZopeTestCase + suite = unittest.TestSuite() names = os.listdir(os.path.dirname(__file__)) tests = [x[:-3] for x in names - if x.startswith('test') and x.endswith('.py') and - x != 'tests.py'] + if x.startswith('test') and x.endswith('.py') and x != 'tests.py'] for test in tests: m = __import__('Testing.ZopeTestCase.%s' % test) diff --git a/src/Testing/ZopeTestCase/zopedoctest/functional.py b/src/Testing/ZopeTestCase/zopedoctest/functional.py index 7d308ac717..576517cb6b 100644 --- a/src/Testing/ZopeTestCase/zopedoctest/functional.py +++ b/src/Testing/ZopeTestCase/zopedoctest/functional.py @@ -15,6 +15,9 @@ import doctest import email.parser +from doctest import ELLIPSIS +from doctest import REPORT_NDIFF +from doctest import NORMALIZE_WHITESPACE from functools import partial from io import BytesIO import re @@ -146,9 +149,9 @@ def http(request_string, handle_errors=True): request_string = request_string.lstrip() # Split off and parse the command line - l = request_string.find('\n') - command_line = request_string[:l].rstrip() - request_string = request_string[l + 1:] + newline = request_string.find('\n') + command_line = request_string[:newline].rstrip() + request_string = request_string[newline + 1:] method, path, protocol = command_line.split() path = unquote(path) @@ -309,8 +312,7 @@ def tearDown(test): def setup_optionflags(self): if 'optionflags' not in self._kw: - self._kw['optionflags'] = ( - doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE) + self._kw['optionflags'] = (ELLIPSIS | NORMALIZE_WHITESPACE) class FunctionalSuiteFactory(ZopeSuiteFactory): @@ -343,8 +345,7 @@ def setup_test_class(self): def setup_optionflags(self): if 'optionflags' not in self._kw: self._kw['optionflags'] = ( - doctest.ELLIPSIS | doctest.REPORT_NDIFF | - doctest.NORMALIZE_WHITESPACE) + ELLIPSIS | REPORT_NDIFF | NORMALIZE_WHITESPACE) def ZopeDocTestSuite(module=None, **kw): diff --git a/src/Testing/ZopeTestCase/zopedoctest/testFunctionalDocTest.py b/src/Testing/ZopeTestCase/zopedoctest/testFunctionalDocTest.py index da9cb16df2..74d72ddd68 100644 --- a/src/Testing/ZopeTestCase/zopedoctest/testFunctionalDocTest.py +++ b/src/Testing/ZopeTestCase/zopedoctest/testFunctionalDocTest.py @@ -97,6 +97,7 @@ def test___str___w_headers(self): def setUp(self): '''This method will run after the test_class' setUp. + >>> http = http # NOQA: F821 >>> response = http(r""" ... GET /test_folder_1_/index_html HTTP/1.1 ... """) @@ -108,7 +109,7 @@ def setUp(self): >>> response.getBody() == b'index' True - >>> foo + >>> foo # NOQA: F821 1 ''' from Testing.ZopeTestCase.testFunctional import CHANGE_TITLE_DTML diff --git a/src/Testing/ZopeTestCase/zopedoctest/testLayerExtraction.py b/src/Testing/ZopeTestCase/zopedoctest/testLayerExtraction.py index b26a231822..32717cc00a 100644 --- a/src/Testing/ZopeTestCase/zopedoctest/testLayerExtraction.py +++ b/src/Testing/ZopeTestCase/zopedoctest/testLayerExtraction.py @@ -26,7 +26,7 @@ class TestLayer(layer.ZopeLite): If the layer is extracted properly, we should see the following variable - >>> getattr(self.app, 'LAYER_EXTRACTED', False) + >>> getattr(self.app, 'LAYER_EXTRACTED', False) # NOQA: F821 True """ diff --git a/src/Testing/ZopeTestCase/zopedoctest/testZopeDocTest.py b/src/Testing/ZopeTestCase/zopedoctest/testZopeDocTest.py index 6e85471fe2..e525fa2d0f 100644 --- a/src/Testing/ZopeTestCase/zopedoctest/testZopeDocTest.py +++ b/src/Testing/ZopeTestCase/zopedoctest/testZopeDocTest.py @@ -21,10 +21,10 @@ def setUp(self): '''This method will run after the test_class' setUp. - >>> 'object' in folder.objectIds() + >>> 'object' in self.folder.objectIds() # NOQA: F821 True - >>> foo + >>> foo # NOQA: F821 1 ''' self.folder.manage_addFolder('object', '') diff --git a/src/Testing/custom_zodb.py b/src/Testing/custom_zodb.py index 586151e816..11cbccd2cb 100644 --- a/src/Testing/custom_zodb.py +++ b/src/Testing/custom_zodb.py @@ -1,5 +1,6 @@ -import os import logging +import os + LOG = logging.getLogger('Testing') @@ -32,4 +33,5 @@ def getStorage(): LOG.info('Using DemoStorage') return DemoStorage() + Storage = getStorage() diff --git a/src/Testing/tests/test_testbrowser.py b/src/Testing/tests/test_testbrowser.py index b0d75aa209..d885b523d0 100644 --- a/src/Testing/tests/test_testbrowser.py +++ b/src/Testing/tests/test_testbrowser.py @@ -23,7 +23,6 @@ from OFS.SimpleItem import Item from Testing.testbrowser import Browser -from Testing.testbrowser import WSGITestApp from Testing.ZopeTestCase import ( FunctionalTestCase, user_name, diff --git a/src/ZPublisher/BaseRequest.py b/src/ZPublisher/BaseRequest.py index f6d41a5d02..4999f6d72a 100644 --- a/src/ZPublisher/BaseRequest.py +++ b/src/ZPublisher/BaseRequest.py @@ -388,8 +388,8 @@ def traverse(self, path, response=None, validated_hook=None): # Probably a browser no_acquire_flag = 0 - if (method in ('GET', 'POST', 'PURGE') and - not is_xmlrpc_response(response)): + if method in ('GET', 'POST', 'PURGE') and \ + not is_xmlrpc_response(response): # index_html is still the default method, only any object can # override it by implementing its own __browser_default__ method method = 'index_html' @@ -466,9 +466,10 @@ def traverse(self, path, response=None, validated_hook=None): # This is webdav support. The last object in the path # should not be acquired. Instead, a NullResource should # be given if it doesn't exist: - if (NullResource is not None and no_acquire_flag and - hasattr(object, 'aq_base') and - not hasattr(object, '__bobo_traverse__')): + if NullResource is not None and \ + no_acquire_flag and \ + hasattr(object, 'aq_base') and \ + not hasattr(object, '__bobo_traverse__'): if (object.__parent__ is not aq_inner(object).__parent__): @@ -495,9 +496,10 @@ def traverse(self, path, response=None, validated_hook=None): continue else: entry_name = default_path[0] - elif (method and hasattr(object, method) and - entry_name != method and - getattr(object, method) is not None): + elif (method + and hasattr(object, method) + and entry_name != method + and getattr(object, method) is not None): request._hacked_path = 1 entry_name = method method = 'index_html' @@ -517,8 +519,8 @@ def traverse(self, path, response=None, validated_hook=None): try: subobject = self.traverseName(object, entry_name) - if (hasattr(object, '__bobo_traverse__') or - hasattr(object, entry_name)): + if hasattr(object, '__bobo_traverse__') or \ + hasattr(object, entry_name): check_name = entry_name else: check_name = None @@ -555,9 +557,9 @@ def traverse(self, path, response=None, validated_hook=None): # an object 'test' existed above it in the # hierarchy -- you'd always get the # existing object :( - if (no_acquire_flag and - hasattr(parents[1], 'aq_base') and - not hasattr(parents[1], '__bobo_traverse__')): + if no_acquire_flag and \ + hasattr(parents[1], 'aq_base') and \ + not hasattr(parents[1], '__bobo_traverse__'): base = aq_base(parents[1]) if not hasattr(base, entry_name): try: diff --git a/src/ZPublisher/BeforeTraverse.py b/src/ZPublisher/BeforeTraverse.py index fa258fa081..d1ddf14182 100644 --- a/src/ZPublisher/BeforeTraverse.py +++ b/src/ZPublisher/BeforeTraverse.py @@ -122,7 +122,8 @@ class NameCaller(object): attribute from the container and calls it. If the name is not found, it fails silently. - >>> registerBeforeTraverse(folder, NameCaller('preop'), 'XApp') + >>> registerBeforeTraverse(self.folder, # NOQA: F821 + ... NameCaller('preop'), 'XApp') """ def __init__(self, name=''): diff --git a/src/ZPublisher/HTTPRequest.py b/src/ZPublisher/HTTPRequest.py index 02bc1b203b..18ad30ba20 100644 --- a/src/ZPublisher/HTTPRequest.py +++ b/src/ZPublisher/HTTPRequest.py @@ -133,7 +133,6 @@ def splitport(url): return hostname, parsed.port - @implementer(IBrowserRequest) class HTTPRequest(BaseRequest): """ Model HTTP request data. @@ -370,8 +369,8 @@ def __init__(self, stdin, environ, response, clean=0): if 'REMOTE_ADDR' in environ: self._client_addr = environ['REMOTE_ADDR'] - if ('HTTP_X_FORWARDED_FOR' in environ and - self._client_addr in trusted_proxies): + if 'HTTP_X_FORWARDED_FOR' in environ and \ + self._client_addr in trusted_proxies: # REMOTE_ADDR is one of our trusted local proxies. # Not really very remote at all. The proxy can tell us the # IP of the real remote client in the forwarded-for header @@ -412,8 +411,7 @@ def __init__(self, stdin, environ, response, clean=0): https_environ = environ.get('HTTPS', False) if https_environ and https_environ in ('on', 'ON', '1'): protocol = 'https' - elif ('SERVER_PORT_SECURE' in environ and - environ['SERVER_PORT_SECURE'] == "1"): + elif environ.get('SERVER_PORT_SECURE', None) == 1: protocol = 'https' else: protocol = 'http' @@ -531,9 +529,8 @@ def processInputs( if 'HTTP_SOAPACTION' in environ: # Stash XML request for interpretation by a SOAP-aware view other['SOAPXML'] = fs.value - elif (method == 'POST' and - ('content-type' in fs.headers and - 'text/xml' in fs.headers['content-type'])): + elif (method == 'POST' + and 'text/xml' in fs.headers.get('content-type', '')): # Ye haaa, XML-RPC! meth, self.args = xmlrpc.parse_input(fs.value) response = xmlrpc.response(response) @@ -555,13 +552,10 @@ def processInputs( if key is None: continue - if (hasattr(item, 'file') and hasattr(item, 'filename') and - hasattr(item, 'headers')): - if (item.file and - (item.filename is not None - # RFC 1867 says that all fields get a content-type. - # or 'content-type' in map(lower, item.headers.keys()) - )): + if hasattr(item, 'file') and \ + hasattr(item, 'filename') and \ + hasattr(item, 'headers'): + if item.file and item.filename is not None: item = FileUpload(item) isFileUpload = 1 else: @@ -581,17 +575,17 @@ def processInputs( # do a string search, and then we'll check it with # a re search. - l = key.rfind(':') - if l >= 0: - mo = search_type(key, l) + delim = key.rfind(':') + if delim >= 0: + mo = search_type(key, delim) if mo: - l = mo.start(0) + delim = mo.start(0) else: - l = -1 + delim = -1 - while l >= 0: - type_name = key[l + 1:] - key = key[:l] + while delim >= 0: + type_name = key[delim + 1:] + key = key[:delim] c = get_converter(type_name, None) if c is not None: @@ -604,14 +598,14 @@ def processInputs( tuple_items[key] = 1 flags = flags | SEQUENCE elif (type_name == 'method' or type_name == 'action'): - if l: + if delim: meth = key else: meth = item - elif (type_name == 'default_method' or - type_name == 'default_action'): + elif (type_name == 'default_method' + or type_name == 'default_action'): if not meth: - if l: + if delim: meth = key else: meth = item @@ -627,14 +621,14 @@ def processInputs( elif has_codec(type_name): character_encoding = type_name - l = key.rfind(':') - if l < 0: + delim = key.rfind(':') + if delim < 0: break - mo = search_type(key, l) + mo = search_type(key, delim) if mo: - l = mo.start(0) + delim = mo.start(0) else: - l = -1 + delim = -1 # Filter out special names from form: if key in isCGI_NAMEs or key.startswith('HTTP_'): @@ -688,7 +682,8 @@ def processInputs( # Flag potentially unsafe values if converter_type in ('string', 'required', 'text', 'ustring', 'utext'): - if not isFileUpload and should_be_tainted(item): + if not isFileUpload and \ + should_be_tainted(item): tainted = taint_string(item) elif converter_type in ('tokens', 'lines', 'utokens', 'ulines'): @@ -702,8 +697,9 @@ def processInputs( tainted = None except Exception: - if (not item and not (flags & DEFAULT) and - key in defaults): + if not item and \ + not (flags & DEFAULT) and \ + key in defaults: item = defaults[key] if flags & RECORD: item = getattr(item, attr) @@ -1026,9 +1022,9 @@ def processInputs( elif isinstance(value, list): # the default value is a list - l = form[key] - if not isinstance(l, list): - l = [l] + val = form[key] + if not isinstance(val, list): + val = [val] # First deal with tainted copies if tainted_key in taintedform: @@ -1053,7 +1049,7 @@ def processInputs( try: for k, v in \ defitem.__dict__.items(): - for origitem in l: + for origitem in val: if not hasattr( origitem, k): missesdefault = 1 @@ -1061,11 +1057,11 @@ def processInputs( except NestedLoopExit: break else: - if defitem not in l: + if defitem not in val: missesdefault = 1 break if missesdefault: - tainted = deepcopy(l) + tainted = deepcopy(val) for defitem in tdefault: if isinstance(defitem, record): for k, v in ( @@ -1089,7 +1085,7 @@ def processInputs( # attribute and value in # the record - for y in l: + for y in val: # loop through each # record in the form @@ -1102,9 +1098,9 @@ def processInputs( setattr(y, k, v) else: # x is not a record - if x not in l: - l.append(x) - form[key] = l + if x not in val: + val.append(x) + form[key] = val else: # The form has the key, the key is not mapped # to a record or sequence so do nothing @@ -1447,8 +1443,8 @@ def keys(self, returnTaints=0): keys.update(self._lazies) for key in self.environ.keys(): - if ((key in isCGI_NAMEs or key[:5] == 'HTTP_') and - (key not in hide_key)): + if (key in isCGI_NAMEs or key[:5] == 'HTTP_') and \ + (key not in hide_key): keys[key] = 1 # Cache URLN and BASEN in self.other. @@ -1750,7 +1746,7 @@ def parse_cookie(text, if mo_q: # Match quoted correct cookies - l = len(mo_q.group(1)) + c_len = len(mo_q.group(1)) name = mo_q.group(2) value = mo_q.group(3) @@ -1759,14 +1755,14 @@ def parse_cookie(text, mo_p = parmre.match(text) if mo_p: - l = len(mo_p.group(1)) + c_len = len(mo_p.group(1)) name = mo_p.group(2) value = mo_p.group(3) else: # Broken Cookie without = nor value. broken_p = paramlessre.match(text) if broken_p: - l = len(broken_p.group(1)) + c_len = len(broken_p.group(1)) name = broken_p.group(2) value = '' else: @@ -1775,7 +1771,7 @@ def parse_cookie(text, if name not in result: result[name] = unquote(value) - return parse_cookie(text[l:], result) + return parse_cookie(text[c_len:], result) class record(object): diff --git a/src/ZPublisher/HTTPResponse.py b/src/ZPublisher/HTTPResponse.py index 9308a143e0..064afca371 100644 --- a/src/ZPublisher/HTTPResponse.py +++ b/src/ZPublisher/HTTPResponse.py @@ -77,10 +77,9 @@ start_of_header_search = re.compile('(]*>)', re.IGNORECASE).search base_re_search = re.compile('()', re.I).search bogus_str_search = re.compile(b" [a-fA-F0-9]+>$").search -charset_re_match = re.compile( - r'(?:application|text)/[-+0-9a-z]+\s*;\s*' + - r'charset=([-_0-9a-z]+' + - r')(?:(?:\s*;)|\Z)', re.IGNORECASE).match +charset_re_str = (r'(?:application|text)/[-+0-9a-z]+\s*;\s*' + r'charset=([-_0-9a-z]+)(?:(?:\s*;)|\Z)') +charset_re_match = re.compile(charset_re_str, re.IGNORECASE).match absuri_match = re.compile(r'\w+://[\w\.]+').match tag_search = re.compile('[a-zA-Z]>').search @@ -226,8 +225,7 @@ def setStatus(self, status, reason=None, lock=None): # It has already been determined. return - if (isinstance(status, class_types) and - issubclass(status, Exception)): + if isinstance(status, class_types) and issubclass(status, Exception): status = status.__name__ if isinstance(status, str): @@ -433,13 +431,9 @@ def insertBase(self): index = match.start(0) + len(match.group(0)) ibase = base_re_search(text) if ibase is None: - text = ( - text[:index] + - '\n\n' + - text[index:] - ) + text = (text[:index] + '\n\n' + + text[index:]) self.text = text self.setHeader('content-length', len(self.body)) @@ -452,8 +446,8 @@ def isHTML(self, text): text = text.lstrip() # Note that the string can be big, so text.lower().startswith() # is more expensive than s[:n].lower(). - if (text[:6].lower() == '' or - text[:14].lower() == '' or \ + text[:14].lower() == ' 0: return True @@ -511,9 +505,11 @@ def setBody(self, body, title='', is_error=False, lock=None): body = self._encode_unicode(text_type(body)) # At this point body is always binary - l = len(body) - if ((l < 200) and body[:1] == b'<' and body.find(b'>') == l - 1 and - bogus_str_search(body) is not None): + b_len = len(body) + if b_len < 200 and \ + body[:1] == b'<' and \ + body.find(b'>') == b_len - 1 and \ + bogus_str_search(body) is not None: self.notFoundError(body[1:-1].decode(self.charset)) else: if title: @@ -536,8 +532,8 @@ def setBody(self, body, title='', is_error=False, lock=None): content_type = 'text/plain; charset=%s' % self.charset self.setHeader('content-type', content_type) else: - if (content_type.startswith('text/') and - 'charset=' not in content_type): + if content_type.startswith('text/') and \ + 'charset=' not in content_type: content_type = '%s; charset=%s' % (content_type, self.charset) self.setHeader('content-type', content_type) @@ -546,8 +542,8 @@ def setBody(self, body, title='', is_error=False, lock=None): self.insertBase() - if (self.use_HTTP_content_compression and - self.headers.get('content-encoding', 'gzip') == 'gzip'): + if self.use_HTTP_content_compression and \ + self.headers.get('content-encoding', 'gzip') == 'gzip': # use HTTP content encoding to compress body contents unless # this response already has another type of content encoding if content_type.split('/')[0] not in uncompressableMimeMajorTypes: @@ -622,8 +618,7 @@ def enableHTTPCompression(self, REQUEST={}, force=0, disable=0, query=0): # compression is off self.use_HTTP_content_compression = 0 - elif (force or - (REQUEST.get('HTTP_ACCEPT_ENCODING', '').find('gzip') != -1)): + elif force or 'gzip' in REQUEST.get('HTTP_ACCEPT_ENCODING', ''): if force: self.use_HTTP_content_compression = 2 else: @@ -636,10 +631,8 @@ def _encode_unicode(self, text): # to the charset specified in the content-type header. if text.startswith('') # right end of the XML preamble - text = ('' + - text[pos_right + 2:]) + text = ('' + text[pos_right + 2:]) # Encode the text data using the response charset text = text.encode(self.charset, 'replace') @@ -797,12 +790,9 @@ def notFoundError(self, entry='Unknown'): self.setStatus(404) raise NotFound(self._error_html( "Resource not found", - "Sorry, the requested resource does not exist." + - "

Check the URL and try again.

" + - "

Resource: " + - escape(entry) + - "

" - )) + ("Sorry, the requested resource does not exist." + "

Check the URL and try again.

" + "

Resource: " + escape(entry) + "

"))) # If a resource is forbidden, why reveal that it exists? forbiddenError = notFoundError @@ -810,10 +800,8 @@ def notFoundError(self, entry='Unknown'): def debugError(self, entry): raise NotFound(self._error_html( "Debugging Notice", - "Zope has encountered a problem publishing your object.

" - "\n" + - entry + - "

")) + ("Zope has encountered a problem publishing your object.

" + "\n" + entry + "

"))) def badRequestError(self, name): self.setStatus(400) @@ -824,13 +812,10 @@ def badRequestError(self, name): raise BadRequest(self._error_html( "Invalid request", - "The parameter, " + - name + - ", " + - "was omitted from the request.

" + - "Make sure to specify all required parameters, " + - "and try the request again.

" - )) + ("The parameter, " + name + ", " + "was omitted from the request.

" + "Make sure to specify all required parameters, " + "and try the request again.

"))) def unauthorized(self): m = "You are not authorized to access this resource." @@ -891,8 +876,8 @@ def exception(self, fatal=0, info=None, abort=1): if fatal and t is SystemExit and v.code == 0: body = self.setBody( (text_type(t), - 'Zope has exited normally.

' + - self._traceback(t, v, tb) + '

'), + 'Zope has exited normally.

' + + self._traceback(t, v, tb) + '

'), is_error=True) else: try: @@ -903,8 +888,8 @@ def exception(self, fatal=0, info=None, abort=1): if match is None: body = self.setBody( (text_type(t), - 'Sorry, a site error occurred.

' + - self._traceback(t, v, tb) + '

'), + 'Sorry, a site error occurred.

' + + self._traceback(t, v, tb) + '

'), is_error=True) elif self.isHTML(b): # error is an HTML document, not just a snippet of html @@ -925,8 +910,8 @@ def finalize(self): """ Set headers required by various parts of protocol. """ body = self.body - if ('content-length' not in self.headers and - 'transfer-encoding' not in self.headers): + if 'content-length' not in self.headers and \ + 'transfer-encoding' not in self.headers: self.setHeader('content-length', len(body)) return "%d %s" % (self.status, self.errmsg), self.listHeaders() @@ -1029,9 +1014,10 @@ def exception(self, fatal=0, info=None, abort=1): def finalize(self): # Set 204 (no content) status if 200 and response is empty # and not streaming. - if ('content-type' not in self.headers and - 'content-length' not in self.headers and - not self._streaming and self.status == 200): + if 'content-type' not in self.headers and \ + 'content-length' not in self.headers and \ + not self._streaming and \ + self.status == 200: self.setStatus('nocontent') # Add content length if not streaming. diff --git a/src/ZPublisher/WSGIPublisher.py b/src/ZPublisher/WSGIPublisher.py index 93d4587577..2a3c4ae406 100644 --- a/src/ZPublisher/WSGIPublisher.py +++ b/src/ZPublisher/WSGIPublisher.py @@ -106,8 +106,7 @@ def _exc_view_created_response(exc, request, response): name=u'standard_error_message') root_parent = parents[0] try: - standard_error_message = aq_acquire(root_parent, - 'standard_error_message') + aq_acquire(root_parent, 'standard_error_message') except (AttributeError, KeyError): view = None @@ -294,7 +293,7 @@ def publish_module(environ, start_response, with transaction_pubevents(request, response): response = _publish(request, new_mod_info) break - except TransientError as exc: + except TransientError: if request.supports_retry(): new_request = request.retry() new_response = new_request.response @@ -308,8 +307,8 @@ def publish_module(environ, start_response, status, headers = response.finalize() start_response(status, headers) - if (isinstance(response.body, _FILE_TYPES) or - IUnboundStreamIterator.providedBy(response.body)): + if isinstance(response.body, _FILE_TYPES) or \ + IUnboundStreamIterator.providedBy(response.body): result = response.body else: # If somebody used response.write, that data will be in the diff --git a/src/ZPublisher/tests/testHTTPRequest.py b/src/ZPublisher/tests/testHTTPRequest.py index 4ae19714a2..d78900eb93 100644 --- a/src/ZPublisher/tests/testHTTPRequest.py +++ b/src/ZPublisher/tests/testHTTPRequest.py @@ -204,16 +204,16 @@ def _noFormValuesInOther(self, req): def _onlyTaintedformHoldsTaintedStrings(self, req): for key, val in list(req.taintedform.items()): self.assertTrue( - self._valueIsOrHoldsTainted(key) or - self._valueIsOrHoldsTainted(val), + self._valueIsOrHoldsTainted(key) + or self._valueIsOrHoldsTainted(val), 'Tainted form holds item %s that is not tainted' % key) for key, val in list(req.form.items()): if key in req.taintedform: continue self.assertFalse( - self._valueIsOrHoldsTainted(key) or - self._valueIsOrHoldsTainted(val), + self._valueIsOrHoldsTainted(key) + or self._valueIsOrHoldsTainted(val), 'Normal form holds item %s that is tainted' % key) def _taintedKeysAlsoInForm(self, req): @@ -307,12 +307,12 @@ def test_processInputs_w_unicode_conversions(self): reg_char = '\xae' inputs = (('ustring:ustring:utf8', 'test' + reg_char), - ('utext:utext:utf8', 'test' + reg_char + - '\ntest' + reg_char + '\n'), - ('utokens:utokens:utf8', 'test' + reg_char + - ' test' + reg_char), - ('ulines:ulines:utf8', 'test' + reg_char + - '\ntest' + reg_char), + ('utext:utext:utf8', + 'test' + reg_char + '\ntest' + reg_char + '\n'), + ('utokens:utokens:utf8', + 'test' + reg_char + ' test' + reg_char), + ('ulines:ulines:utf8', + 'test' + reg_char + '\ntest' + reg_char), ('nouconverter:string:utf8', 'test' + reg_char)) req = self._processInputs(inputs) @@ -993,7 +993,7 @@ def test_locale_fallback(self): provideAdapter(BrowserLanguages, [IHTTPRequest], IUserPreferredLanguages) - env = {'HTTP_ACCEPT_LANGUAGE': 'en', 'HTTP_ACCEPT_LANGUAGE': 'xx'} + env = {'HTTP_ACCEPT_LANGUAGE': 'xx'} # Now test for non-existant locale fallback request = self._makeOne(environ=env) diff --git a/src/ZPublisher/tests/testHTTPResponse.py b/src/ZPublisher/tests/testHTTPResponse.py index 1e645bd5fb..e1843b694b 100644 --- a/src/ZPublisher/tests/testHTTPResponse.py +++ b/src/ZPublisher/tests/testHTTPResponse.py @@ -1,11 +1,9 @@ # -*- coding: utf-8 -*- from io import BytesIO -import sys import traceback import unittest -from six import PY3 from zExceptions import ( BadRequest, Forbidden, @@ -783,8 +781,8 @@ def test__encode_unicode_w_content_type_w_charset_xml_preamble(self): response = self._makeOne() response.setHeader('Content-Type', 'text/html; charset=latin1') self.assertEqual(response._encode_unicode(UNICODE), - b'\n' + - ELEMENT.encode('latin-1')) + b'\n' + + ELEMENT.encode('latin-1')) response.getHeader('Content-Type', 'text/html; charset=latin1') def test_quoteHTML(self): diff --git a/src/ZPublisher/tests/test_WSGIPublisher.py b/src/ZPublisher/tests/test_WSGIPublisher.py index 70c1ffcd77..f59bb616ce 100644 --- a/src/ZPublisher/tests/test_WSGIPublisher.py +++ b/src/ZPublisher/tests/test_WSGIPublisher.py @@ -314,11 +314,13 @@ def test_publish_returns_data_witten_to_response_before_body(self): from ZPublisher.HTTPResponse import WSGIResponse environ = self._makeEnviron() start_response = DummyCallable() + def _publish(request, mod_info): response = WSGIResponse() response.write(b'WRITTEN') response.body = b'BODY' return response + app_iter = self._callFUT(environ, start_response, _publish) self.assertEqual(app_iter, (b'WRITTEN', b'BODY')) @@ -458,6 +460,7 @@ def _request_factory(stdin, environ, response): def test_handle_ConflictError(self): environ = self._makeEnviron() start_response = DummyCallable() + def _publish(request, module_info): if request.retry_count < 1: raise ConflictError @@ -467,7 +470,7 @@ def _publish(request, module_info): try: from ZPublisher.HTTPRequest import HTTPRequest - original_retry_max_count = HTTPRequest.retry_max_count + original_retry_max_count = HTTPRequest.retry_max_count HTTPRequest.retry_max_count = 1 # After the retry the request has a filled `other` dict, thus the # new request is not closed before processing it: @@ -517,7 +520,8 @@ def _request_factory(stdin, environ, response): # In the end the error view is rendered, but the request should # have been retried up to retry_max_count times - self.assertTrue(app_iter[1].startswith('Exception View: ConflictError')) + self.assertTrue(app_iter[1].startswith( + 'Exception View: ConflictError')) self.assertEqual(_request.retry_count, _request.retry_max_count) unregisterExceptionView(Exception) @@ -758,7 +762,8 @@ def __call__(self): self.__parent__.__class__.__name__)) -def registerExceptionView(for_, factory=CustomExceptionView, name=u'index.html'): +def registerExceptionView(for_, factory=CustomExceptionView, + name=u'index.html'): from zope.interface import Interface from zope.component import getGlobalSiteManager from zope.publisher.interfaces.browser import IDefaultBrowserLayer @@ -770,6 +775,7 @@ def registerExceptionView(for_, factory=CustomExceptionView, name=u'index.html') name=name, ) + def unregisterExceptionView(for_, factory=CustomExceptionView, name=u'index.html'): from zope.interface import Interface diff --git a/src/ZPublisher/tests/test_pubevents.py b/src/ZPublisher/tests/test_pubevents.py index c66698df89..dfd926b159 100644 --- a/src/ZPublisher/tests/test_pubevents.py +++ b/src/ZPublisher/tests/test_pubevents.py @@ -169,7 +169,7 @@ def testStreaming(self): class ExceptionView(object): def __init__(self, context, request): - self.context = context # exception instance + self.context = context # exception instance self.__parent__ = None self.request = request @@ -230,7 +230,7 @@ def pub_event(self, event): exception_type, exception_instance, traceback = event.exc_info self.assertIsInstance(exception_instance, exception_type) self.assertIsInstance(exception_instance, - self.expected_exception_type) + self.expected_exception_type) def test_all_pub_events_have_access_to_valid_global_request(self): self.folder.addDTMLDocument('index_html', file='index') @@ -249,7 +249,7 @@ def test_unauthorized_exception_is_handled_as_other_exceptions(self): self.assertEqual(response._response.events, ['PubStart', 'PubBeforeAbort', 'PubFailure']) - def test_BeforeAbort_and_Failure_events_can_access_zope_globalRequest(self): + def test_BeforeAbort_and_Failure_events_can_access_zope_globalReq(self): self.expected_exception_type = zExceptions.NotFound response = self.publish('/notexisting') self.assertEqual(response.getStatus(), 404) @@ -267,7 +267,8 @@ def test_BeforeAbort_and_Failure_events_are_called_after_exc_view(self): self.assertEqual(response.getStatus(), 404) self.assertEqual( response.getBody(), - b"Exception: \nRequest: ") + (b"Exception: \n" + b"Request: ")) def test_exception_views_and_event_handlers_get_upgraded_exceptions(self): self.expected_exception_type = zExceptions.HTTPVersionNotSupported @@ -278,8 +279,10 @@ class HTTPVersionNotSupported(Exception): pass raise HTTPVersionNotSupported() self.folder.__class__.index_html = raiser + def cleanup(): del self.folder.__class__.index_html + self.addCleanup(cleanup) from zope.publisher.interfaces.http import IHTTPException @@ -291,7 +294,9 @@ def cleanup(): self.assertEqual(response.getStatus(), 505) self.assertEqual( response.getBody(), - b"Exception: \nRequest: ") + (b"Exception: \n" + b"Request: ")) def _succeed(): @@ -347,5 +352,6 @@ def close(self): # override to get rid of the 'EndRequestEvent' notification pass + # define things necessary for publication bobo_application = _Application() diff --git a/src/ZPublisher/utils.py b/src/ZPublisher/utils.py index 0fbac8c9e5..2c0f912c55 100644 --- a/src/ZPublisher/utils.py +++ b/src/ZPublisher/utils.py @@ -20,6 +20,7 @@ from six import text_type import transaction + AC_LOGGER = logging.getLogger('event.AccessControl') @@ -36,8 +37,7 @@ def recordMetaData(object, request): to_append = (object.__name__,) object = object.__self__ - while (object is not None and - not hasattr(object, 'getPhysicalPath')): + while object is not None and not hasattr(object, 'getPhysicalPath'): if getattr(object, '__name__', None) is None: object = None break diff --git a/src/ZPublisher/xmlrpc.py b/src/ZPublisher/xmlrpc.py index e0481b4cb5..96c9e41390 100644 --- a/src/ZPublisher/xmlrpc.py +++ b/src/ZPublisher/xmlrpc.py @@ -160,7 +160,7 @@ def setBody(self, body, title='', is_error=0, bogus_str_search=None): (body,), methodresponse=1, allow_none=True) except ConflictError: raise - except: + except Exception: self.exception() return # Set our body to the XML-RPC message, and fix our MIME type. diff --git a/src/ZTUtils/Batch.py b/src/ZTUtils/Batch.py index 3c40f3632c..01a6843c6e 100644 --- a/src/ZTUtils/Batch.py +++ b/src/ZTUtils/Batch.py @@ -36,8 +36,8 @@ def __of__(self, parent): class LazySequenceLength(Base): def __of__(self, parent): - parent.sequence_length = l = len(parent._sequence) - return l + parent.sequence_length = psl = len(parent._sequence) + return psl class Batch(Base): diff --git a/src/ZTUtils/Lazy.py b/src/ZTUtils/Lazy.py index ea0e3dcb00..fcb728be99 100644 --- a/src/ZTUtils/Lazy.py +++ b/src/ZTUtils/Lazy.py @@ -41,14 +41,14 @@ def __len__(self): # This is a worst-case len, subclasses should try to do better if self._len is not _marker: return self._len - l = len(self._data) + dl = len(self._data) while 1: try: - self[l] - l = l + 1 + self[dl] + dl += 1 except Exception: - self._len = l - return l + self._len = dl + return dl def __add__(self, other): if not isinstance(other, Lazy): @@ -162,14 +162,14 @@ def __len__(self): # of its underlying sequences if self._len is not _marker: return self._len - l = 0 + ld = 0 try: for s in self._seq: - l += len(s) + ld += len(s) except AttributeError: - l = len(self._data) - self._len = l - return l + ld = len(self._data) + self._len = ld + return ld class LazyMap(Lazy): diff --git a/src/ZTUtils/Tree.py b/src/ZTUtils/Tree.py index 3fa6f4acdf..2b51807b4d 100644 --- a/src/ZTUtils/Tree.py +++ b/src/ZTUtils/Tree.py @@ -62,6 +62,7 @@ def __getitem__(self, index): def __len__(self): return len(self._child_list) + _marker = [] @@ -162,7 +163,6 @@ def getId(self, object): def node(self, object): node = TreeNode() node.object = object - obid = self.getId(object) node.id = b2a(self.getId(object)) return node @@ -190,8 +190,7 @@ def getChildren(self, object): return self._values_function(object) children = getattr(object, self._values) - if not (isinstance(children, list) or - isinstance(children, tuple)): + if not isinstance(children, (list, tuple)): # Assume callable; result not useful anyway otherwise. children = children() @@ -229,6 +228,7 @@ def tree(self, root, expanded=None, subtree=0): _SIMPLE_TYPES = set([type(u''), type(b''), type(0), type(0.0), type(None)]) + def simple_type(ob): return type(ob) in _SIMPLE_TYPES @@ -270,7 +270,7 @@ def encodeExpansion(nodes, compress=1): last_depth = node.depth if dd > 0: steps.append('_' * dd) - steps.append(node.id) # id is bytes + steps.append(node.id) # id is bytes node.expansion_number = n result = b':'.join(steps) if compress and len(result) > 2: diff --git a/src/ZTUtils/tests/testTree.py b/src/ZTUtils/tests/testTree.py index 75c54fe991..902d7b8fff 100644 --- a/src/ZTUtils/tests/testTree.py +++ b/src/ZTUtils/tests/testTree.py @@ -67,9 +67,10 @@ def test_flat_non_empty(self): def test_walk_empty(self): node = self._makeOne() _called_with = [] - datum = object() + def _func(a_node, data=None): _called_with.append((a_node, data)) + node.walk(_func) self.assertEqual(_called_with, [(node, None)]) @@ -81,8 +82,10 @@ def test_walk_nonempty_w_data(self): child._add_child(grand) _called_with = [] datum = object() + def _func(a_node, data): _called_with.append((a_node, data)) + node.walk(_func, datum) self.assertEqual( _called_with, diff --git a/src/Zope2/App/patches/publishing.py b/src/Zope2/App/patches/publishing.py index 5b04c08314..169982fbbd 100644 --- a/src/Zope2/App/patches/publishing.py +++ b/src/Zope2/App/patches/publishing.py @@ -64,7 +64,7 @@ def apply_patches(): for klass in [Element, Attribute, Interface, Method]: try: del klass.__doc__ - except: + except Exception: pass for method_name in element_methods: delete_method_docstring(klass, method_name) diff --git a/src/Zope2/App/tests/test_safe_formatter.py b/src/Zope2/App/tests/test_safe_formatter.py index 75987fddb2..32195ad366 100644 --- a/src/Zope2/App/tests/test_safe_formatter.py +++ b/src/Zope2/App/tests/test_safe_formatter.py @@ -3,8 +3,6 @@ from Testing.ZopeTestCase import FunctionalTestCase from zExceptions import Unauthorized -import unittest - try: from html import escape import functools @@ -24,7 +22,8 @@

""" BAD_KEY_UNICODE = """ -

+

""" BAD_ITEM_STR = """

@@ -65,6 +64,8 @@ def validate(self, *args, **kw): class FormatterFunctionalTest(FunctionalTestCase): + maxDiff = None + def test_cook_zope2_page_templates_bad_attr_str(self): from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate pt = ZopePageTemplate('mytemplate', BAD_ATTR_STR) @@ -131,18 +132,6 @@ def test_cook_zope2_page_templates_good_format_attr_unicode(self): pt.pt_render().strip(), '

title of <Application at > is Zope

') -class UnauthorizedSecurityPolicy(object): - """Policy which denies every access.""" - - def validate(self, *args, **kw): - from AccessControl.unauthorized import Unauthorized - raise Unauthorized('Nothing is allowed!') - - -class FormatterFunctionalTest(FunctionalTestCase): - - maxDiff = None - def test_access_to_private_content_not_allowed_via_any_attribute(self): from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate # If access to _delObject would be allowed, it would still only say @@ -284,34 +273,6 @@ def test_cook_zope2_page_templates_bad_item_unicode(self): "You are not allowed to access 'test_folder_1_' in this context", str(err.exception)) - def assert_is_checked_via_security_manager(self, pt_content): - from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate - from AccessControl.SecurityManager import setSecurityPolicy - from AccessControl.SecurityManagement import noSecurityManager - from AccessControl.SecurityManagement import getSecurityManager - - pt = ZopePageTemplate('mytemplate', pt_content) - noSecurityManager() - old_security_policy = setSecurityPolicy(UnauthorizedSecurityPolicy()) - try: - hack_pt(pt, context=self.app) - with self.assertRaises(Unauthorized) as err: - pt.pt_render() - self.assertEqual( - 'Nothing is allowed!', - str(err.exception)) - finally: - setSecurityPolicy(old_security_policy) - - def test_getattr_access_is_checked_via_security_manager(self): - self.assert_is_checked_via_security_manager( - """

""") - - def test_getitem_access_is_checked_via_security_manager(self): - self.assert_is_checked_via_security_manager( - """

""" - ) - def test_key_access_is_checked_via_security_manager(self): self.assert_is_checked_via_security_manager( """

""" diff --git a/src/Zope2/Startup/serve.py b/src/Zope2/Startup/serve.py index c83c981e7a..7c23d99502 100644 --- a/src/Zope2/Startup/serve.py +++ b/src/Zope2/Startup/serve.py @@ -20,8 +20,8 @@ import re import sys -from paste.deploy import loadserver from paste.deploy import loadapp +from paste.deploy import loadserver try: import configparser @@ -215,5 +215,6 @@ def main(argv=sys.argv, quiet=False): command = ServeCommand(argv, quiet=quiet) return command.run() + if __name__ == '__main__': sys.exit(main() or 0) diff --git a/src/Zope2/utilities/adduser.py b/src/Zope2/utilities/adduser.py index 764cdc3225..205ae65b41 100644 --- a/src/Zope2/utilities/adduser.py +++ b/src/Zope2/utilities/adduser.py @@ -13,6 +13,7 @@ """ Add a Zope management user to the root Zope user folder """ import sys + from Zope2.utilities.finder import ZopeFinder @@ -41,5 +42,6 @@ def main(argv=sys.argv): print("Maybe the user already exists and nothing is done then.") print("Or the implementation does not give info when it succeeds.") + if __name__ == '__main__': main() diff --git a/src/Zope2/utilities/mkwsgiinstance.py b/src/Zope2/utilities/mkwsgiinstance.py index 3143ee68c9..f7ce314b2b 100644 --- a/src/Zope2/utilities/mkwsgiinstance.py +++ b/src/Zope2/utilities/mkwsgiinstance.py @@ -30,13 +30,11 @@ import os import subprocess import sys -from . import copyzopeskel -if sys.version_info > (3, ): - raw_input = input - from configparser import RawConfigParser -else: - from ConfigParser import RawConfigParser +from six.moves import input +from six.moves.configparser import RawConfigParser + +from . import copyzopeskel def main(): @@ -119,8 +117,9 @@ def main(): pythonexe = os.path.join(exedir, 'python.exe') pythonwexe = os.path.join(exedir, 'pythonw.exe') - if (os.path.isfile(pythonwexe) and os.path.isfile(pythonexe) and - (python in [pythonwexe, pythonexe])): + if os.path.isfile(pythonwexe) and \ + os.path.isfile(pythonexe) and \ + python in [pythonwexe, pythonexe]: # we're using a Windows build with both python.exe and pythonw.exe # in the same directory PYTHON = pythonexe @@ -158,7 +157,7 @@ def get_skeltarget(): print('Zope "instance home" files such as database files, configuration') print('files, etc.\n') while 1: - skeltarget = raw_input("Directory: ").strip() + skeltarget = input("Directory: ").strip() if skeltarget == '': print('You must specify a directory') continue @@ -172,7 +171,7 @@ def get_inituser(): print('Please choose a username and password for the initial user.') print('These will be the credentials you use to initially manage') print('your new Zope instance.\n') - user = raw_input("Username: ").strip() + user = input("Username: ").strip() if user == '': return None, None while 1: @@ -191,12 +190,7 @@ def write_inituser(fn, user, password): from hashlib import sha1 as sha pw = binascii.b2a_base64(sha(password.encode('utf-8')).digest())[:-1] with open(fn, "wb") as fp: - fp.write( - user.encode('utf-8') + - b':{SHA}' + - pw + - b'\n' - ) + fp.write(user.encode('utf-8') + b':{SHA}' + pw + b'\n') os.chmod(fn, 0o644) diff --git a/src/zmi/styles/subscriber.py b/src/zmi/styles/subscriber.py index 3e0ddcc5f2..9a2fcc73f1 100644 --- a/src/zmi/styles/subscriber.py +++ b/src/zmi/styles/subscriber.py @@ -20,5 +20,4 @@ def js_paths(context): '/++resource++zmi/bootstrap-4.1.1/bootstrap.bundle.min.js', '/++resource++zmi/ace.ajax.org/ace.js', '/++resource++zmi/zmi_base.js', - ) diff --git a/tox.ini b/tox.ini index 619a8cc5da..714bb4d16c 100644 --- a/tox.ini +++ b/tox.ini @@ -90,8 +90,8 @@ deps = commands = mkdir -p {toxinidir}/_build/flake8 - isort --check-only --recursive {toxinidir}/src setup.py - - flake8 --format=html --htmldir={toxinidir}/_build/flake8 --doctests src tests setup.py - flake8 src tests setup.py --doctests + - flake8 --format=html --htmldir={toxinidir}/_build/flake8 src tests setup.py + flake8 src tests setup.py whitelist_externals = mkdir