diff --git a/setup.py b/setup.py index 2a62cb3..534e133 100644 --- a/setup.py +++ b/setup.py @@ -59,11 +59,7 @@ 'License :: OSI Approved :: Zope Public License', 'Operating System :: OS Independent', 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.5', - 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', @@ -80,7 +76,6 @@ 'ExtensionClass >= 4.2.1', 'Persistence >= 3.0a3', 'RestrictedPython >= 5.1', - 'six', 'transaction', 'zExceptions', 'zope.component', @@ -93,7 +88,7 @@ 'zope.testing', 'funcsigs;python_version<"3.3"', ], - python_requires='>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*', + python_requires='>=3.7', include_package_data=True, zip_safe=False, extras_require={ diff --git a/src/AccessControl/AuthEncoding.py b/src/AccessControl/AuthEncoding.py index efbca6d..fd93334 100644 --- a/src/AccessControl/AuthEncoding.py +++ b/src/AccessControl/AuthEncoding.py @@ -11,7 +11,6 @@ # ############################################################################## -from __future__ import absolute_import import AuthEncoding.AuthEncoding from zope.deferredimport import deprecated diff --git a/src/AccessControl/ImplPython.py b/src/AccessControl/ImplPython.py index 492befa..1a7788b 100644 --- a/src/AccessControl/ImplPython.py +++ b/src/AccessControl/ImplPython.py @@ -13,11 +13,17 @@ # isort:skip_file """Python implementation of the access control machinery.""" +from AccessControl.ZopeSecurityPolicy import getRoles # XXX +from AccessControl.unauthorized import Unauthorized +from AccessControl.SimpleObjectPolicies import _noroles +from AccessControl.SimpleObjectPolicies import Containers +from AccessControl.SecurityManagement import getSecurityManager +from AccessControl.Permission import getPermissionIdentifier +from AccessControl.interfaces import ISecurityPolicy +from AccessControl.interfaces import ISecurityManager import os from logging import getLogger -from six import string_types - from Acquisition import aq_acquire from Acquisition import aq_base from Acquisition import aq_inContextOf @@ -33,13 +39,6 @@ else: from AccessControl.cAccessControl import _what_not_even_god_should_do -from AccessControl.interfaces import ISecurityManager -from AccessControl.interfaces import ISecurityPolicy -from AccessControl.Permission import getPermissionIdentifier -from AccessControl.SecurityManagement import getSecurityManager -from AccessControl.SimpleObjectPolicies import Containers -from AccessControl.SimpleObjectPolicies import _noroles -from AccessControl.unauthorized import Unauthorized from AccessControl.ZopeGuards import guarded_getitem # NOQA @@ -49,7 +48,6 @@ # TODO: implement this in cAccessControl, and have Implementation # do the indirection. # -from AccessControl.ZopeSecurityPolicy import getRoles # XXX LOG = getLogger('ImplPython') @@ -315,7 +313,7 @@ def validate(self, accessed, container, name, value, context, if not isinstance(p, (bool, int)): if isinstance(p, dict): - if isinstance(name, string_types): + if isinstance(name, str): p = p.get(name) else: p = 1 @@ -487,7 +485,7 @@ def validate(self, accessed, container, name, value, context, def checkPermission(self, permission, object, context): roles = rolesForPermissionOn(permission, object) - if isinstance(roles, string_types): + if isinstance(roles, str): roles = [roles] # check executable owner and proxy roles @@ -795,7 +793,7 @@ def raiseVerbose(msg, accessed, container, name, value, context, ): """Raises an Unauthorized error with a verbose explanation.""" - s = '%s. Access to %s of %s' % ( + s = '{}. Access to {} of {}'.format( msg, repr(name), item_repr(container)) if aq_base(container) is not aq_base(accessed): s += ', acquired through %s,' % item_repr(accessed) @@ -806,7 +804,7 @@ def raiseVerbose(msg, accessed, container, name, value, context, ufolder = '/'.join(aq_parent(aq_inner(user)).getPhysicalPath()) except: # noqa: E722 do not use bare 'except' ufolder = '(unknown)' - info.append('Your user account, %s, exists at %s.' % ( + info.append('Your user account, {}, exists at {}.'.format( str(user), ufolder)) if required_roles is not None: diff --git a/src/AccessControl/Implementation.py b/src/AccessControl/Implementation.py index 638a5a0..05bfbad 100644 --- a/src/AccessControl/Implementation.py +++ b/src/AccessControl/Implementation.py @@ -24,7 +24,6 @@ module was introduced. """ -from __future__ import absolute_import import os diff --git a/src/AccessControl/PermissionMapping.py b/src/AccessControl/PermissionMapping.py index 1df4dd0..b71e536 100644 --- a/src/AccessControl/PermissionMapping.py +++ b/src/AccessControl/PermissionMapping.py @@ -17,6 +17,8 @@ need the object's ordinary permissions intact so we can manage it. """ +from html import escape + from Acquisition import ImplicitAcquisitionWrapper from ExtensionClass import Base from zope.interface import implementer @@ -28,12 +30,6 @@ from AccessControl.requestmethod import requestmethod -try: - from html import escape -except ImportError: # PY2 - from cgi import escape - - @implementer(IPermissionMappingSupport) class RoleManager: @@ -113,7 +109,7 @@ def _isBeingUsedAsAMethod(self, REQUEST=None, wannaBe=0): InitializeClass(RoleManager) -def getPermissionMapping(name, obj, st=type('')): +def getPermissionMapping(name, obj, st=str): obj = getattr(obj, 'aq_base', obj) name = getPermissionIdentifier(name) r = getattr(obj, name, '') diff --git a/src/AccessControl/SecurityInfo.py b/src/AccessControl/SecurityInfo.py index f3a6479..ed87984 100644 --- a/src/AccessControl/SecurityInfo.py +++ b/src/AccessControl/SecurityInfo.py @@ -139,7 +139,7 @@ def protected(self, permission_name): # the decorator returned is remembered in a set and will # remove itself upon call. self.apply will check for an empty # set and raise an AssertionError otherwise. - key = "'%s':%s" % (permission_name, id(lambda x: x)) + key = "'{}':{}".format(permission_name, id(lambda x: x)) def decor(func): self.declareProtected(permission_name, func.__name__) # NOQA: D001 @@ -147,7 +147,7 @@ def decor(func): return func # make sure our key algo creates unique-enough keys if key in self._unused_protected_decorators: - raise KeyError("Duplicate key: %s" % (key,)) + raise KeyError("Duplicate key: {}".format(key)) self._unused_protected_decorators.add(key) return decor diff --git a/src/AccessControl/SecurityManagement.py b/src/AccessControl/SecurityManagement.py index 405cfc2..fac99a1 100644 --- a/src/AccessControl/SecurityManagement.py +++ b/src/AccessControl/SecurityManagement.py @@ -12,9 +12,8 @@ ############################################################################## """Security management """ -from __future__ import absolute_import -from six.moves._thread import get_ident +from _thread import get_ident from AccessControl import SpecialUsers diff --git a/src/AccessControl/SimpleObjectPolicies.py b/src/AccessControl/SimpleObjectPolicies.py index 4cfc310..b74025b 100644 --- a/src/AccessControl/SimpleObjectPolicies.py +++ b/src/AccessControl/SimpleObjectPolicies.py @@ -86,8 +86,8 @@ # calling the function with the object and the attribute name. ContainerAssertions = { type(()): 1, - type(b''): 1, - type(u''): 1, + bytes: 1, + str: 1, range: 1, } diff --git a/src/AccessControl/ZopeGuards.py b/src/AccessControl/ZopeGuards.py index 4b41a6e..84c2e9e 100644 --- a/src/AccessControl/ZopeGuards.py +++ b/src/AccessControl/ZopeGuards.py @@ -11,15 +11,11 @@ # ############################################################################## -from __future__ import absolute_import import math import random import string -import warnings - -import six -from six.moves import reduce +from functools import reduce import RestrictedPython from RestrictedPython.Eval import RestrictionCapableEval @@ -43,16 +39,6 @@ safe_builtins = safe_builtins.copy() safe_builtins.update(utility_builtins) -# Allow access to unprotected attributes (don't show deprecation warning). -with warnings.catch_warnings(): - warnings.simplefilter("ignore") - try: - import sets - except ImportError: - pass - else: - sets.__allow_access_to_unprotected_subobjects__ = 1 - # Allow access to unprotected attributes string.__allow_access_to_unprotected_subobjects__ = 1 math.__allow_access_to_unprotected_subobjects__ = 1 @@ -174,20 +160,10 @@ def guarded_pop(index=-1): 'update': 1, } -if six.PY3: - _dict_white_list.update({ - 'keys': get_iter, - 'values': get_iter, - }) -else: - _dict_white_list.update({ - 'has_key': 1, - 'iteritems': 1, - 'iterkeys': get_iter, - 'itervalues': get_iter, - 'keys': 1, - 'values': 1, - }) +_dict_white_list.update({ + 'keys': get_iter, + 'values': get_iter, +}) def _check_dict_access(name, value): @@ -206,11 +182,10 @@ def _check_dict_access(name, value): ContainerAssertions[type({})] = _check_dict_access -if six.PY3: - # Allow iteration over the result of `dict.{keys, values, items}` - d = {} - for attr in ("keys", "values", "items"): - allow_type(type(getattr(d, attr)())) +# Allow iteration over the result of `dict.{keys, values, items}` +d = {} +for attr in ("keys", "values", "items"): + allow_type(type(getattr(d, attr)())) _list_white_list = { @@ -267,7 +242,7 @@ def guarded_next(iterator, default=_marker): safe_builtins['next'] = guarded_next -class SafeIter(object): +class SafeIter: __allow_access_to_unprotected_subobjects__ = 1 def __init__(self, ob, container=None): @@ -284,7 +259,7 @@ def __next__(self): guard(self.container, ob) return ob - next = __next__ # Python 2 compat + next = __next__ class NullIter(SafeIter): @@ -294,7 +269,7 @@ def __init__(self, ob): def __next__(self): return next(self._iter) - next = __next__ # Python 2 compat + next = __next__ def _error(index): @@ -307,7 +282,7 @@ def guarded_iter(*args): # Don't double-wrap if isinstance(i, SafeIter): return i - if not isinstance(i, six.moves.range): + if not isinstance(i, range): return SafeIter(i) # Other call styles / targets don't need to be guarded return NullIter(iter(*args)) @@ -402,10 +377,7 @@ def guarded_zip(*seqs): safe_builtins['zip'] = guarded_zip -if six.PY3: - import_default_level = 0 -else: - import_default_level = -1 +import_default_level = 0 def guarded_import(mname, globals=None, locals=None, fromlist=None, @@ -482,7 +454,7 @@ def load_module(module, mname, mnameparts, validate, globals, locals): if mname is None: mname = nextname else: - mname = '%s.%s' % (mname, nextname) + mname = '{}.{}'.format(mname, nextname) # import (if not already imported) and check for MSI nextmodule = secureModule(mname, globals, locals) if nextmodule is None: # not allowed diff --git a/src/AccessControl/ZopeSecurityPolicy.py b/src/AccessControl/ZopeSecurityPolicy.py index 6d27a00..8373943 100644 --- a/src/AccessControl/ZopeSecurityPolicy.py +++ b/src/AccessControl/ZopeSecurityPolicy.py @@ -12,12 +12,9 @@ ############################################################################## """Define Zope's default security policy """ -from __future__ import absolute_import from types import MethodType -from six import string_types - # AccessControl.Implementation inserts: # ZopeSecurityPolicy, getRoles, rolesForPermissionOn from AccessControl.SimpleObjectPolicies import _noroles @@ -37,7 +34,7 @@ def getRoles(container, name, value, default): roles = getattr(value, '__roles__', _noroles) if roles is _noroles: - if not name or not isinstance(name, string_types): + if not name or not isinstance(name, str): return default if isinstance(value, MethodType): diff --git a/src/AccessControl/__init__.py b/src/AccessControl/__init__.py index 010a48d..afba2a9 100644 --- a/src/AccessControl/__init__.py +++ b/src/AccessControl/__init__.py @@ -11,9 +11,6 @@ # ############################################################################## - -import six - # This has to happen early so things get initialized properly from AccessControl.Implementation import setImplementation from AccessControl.safe_formatter import safe_format @@ -45,19 +42,10 @@ # We want to allow all methods on string type except "format". # That one needs special handling to avoid access to attributes. -rules = dict([(m, True) for m in dir(str) if not m.startswith('_')]) +rules = {m: True for m in dir(str) if not m.startswith('_')} rules['format'] = safe_format allow_type(str, rules) -if six.PY2: - # Same for unicode instead on Python 2: - rules = dict([(m, True) for m in dir(six.text_type) if - not m.startswith('_')]) - rules['format'] = safe_format - allow_type(six.text_type, rules) - -del six - zodbupdate_decode_dict = { 'AccessControl.users User name': 'utf-8', 'AccessControl.users User __': 'utf-8', diff --git a/src/AccessControl/_compat.h b/src/AccessControl/_compat.h index 7b6d9ab..86b16cc 100644 --- a/src/AccessControl/_compat.h +++ b/src/AccessControl/_compat.h @@ -14,14 +14,5 @@ #include "Python.h" -#if PY_MAJOR_VERSION >= 3 -#define PY3K -#endif - -#ifdef PY3K #define NATIVE_FORMAT PyUnicode_Format #define NATIVE_GET_SIZE PyUnicode_GET_SIZE -#else -#define NATIVE_FORMAT PyString_Format -#define NATIVE_GET_SIZE PyString_GET_SIZE -#endif diff --git a/src/AccessControl/cAccessControl.c b/src/AccessControl/cAccessControl.c index b4dbf6e..33e763b 100644 --- a/src/AccessControl/cAccessControl.c +++ b/src/AccessControl/cAccessControl.c @@ -3,26 +3,26 @@ ** ** Access control acceleration routines - Copyright (c) 2001, Zope Foundation and Contributors. + Copyright (c) 2001, Zope Foundation and Contributors. All rights reserved. - + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - + o Redistributions of source code must retain the above copyright notice, this list of conditions, and the disclaimer that follows. - + o Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. - + o Neither the name of Digital Creations nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. - - + + THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A @@ -38,10 +38,10 @@ If you have questions regarding this software, contact: - - Digital Creations L.C. + + Digital Creations L.C. info@digicool.com - + (540) 371-6909 */ @@ -104,8 +104,8 @@ callfunction2(PyObject *function, PyObject *arg0, PyObject *arg1) } static PyObject * -callfunction3(PyObject *function, - PyObject *arg0, PyObject *arg1, +callfunction3(PyObject *function, + PyObject *arg0, PyObject *arg1, PyObject *arg2 ) { @@ -125,9 +125,9 @@ callfunction3(PyObject *function, } static PyObject * -callfunction4(PyObject *function, - PyObject *arg0, PyObject *arg1, - PyObject *arg2, PyObject *arg3 +callfunction4(PyObject *function, + PyObject *arg0, PyObject *arg1, + PyObject *arg2, PyObject *arg3 ) { PyObject *t, *r; @@ -148,9 +148,9 @@ callfunction4(PyObject *function, } static PyObject * -callfunction5(PyObject *function, - PyObject *arg0, PyObject *arg1, - PyObject *arg2, PyObject *arg3, PyObject *arg4 +callfunction5(PyObject *function, + PyObject *arg0, PyObject *arg1, + PyObject *arg2, PyObject *arg3, PyObject *arg4 ) { PyObject *t, *r; @@ -173,8 +173,8 @@ callfunction5(PyObject *function, } static PyObject * -callfunction6(PyObject *function, - PyObject *arg0, PyObject *arg1, +callfunction6(PyObject *function, + PyObject *arg0, PyObject *arg1, PyObject *arg2, PyObject *arg3, PyObject *arg4, PyObject *arg5 ) @@ -200,14 +200,14 @@ callfunction6(PyObject *function, return r; } -static int -unpacktuple2(PyObject *args, char *name, int min, +static int +unpacktuple2(PyObject *args, char *name, int min, PyObject **a0, PyObject **a1) -{ +{ int l; l=PyTuple_Size(args); if (l < 0) return -1; - if (l < min) + if (l < min) { PyErr_Format(PyExc_TypeError, "expected %d arguments, got %d", min, l); return -1; @@ -217,14 +217,14 @@ unpacktuple2(PyObject *args, char *name, int min, return 0; } -static int -unpacktuple3(PyObject *args, char *name, int min, +static int +unpacktuple3(PyObject *args, char *name, int min, PyObject **a0, PyObject **a1, PyObject **a2) -{ +{ int l; l=PyTuple_Size(args); if (l < 0) return -1; - if (l < min) + if (l < min) { PyErr_Format(PyExc_TypeError, "expected %d arguments, got %d", min, l); return -1; @@ -235,14 +235,14 @@ unpacktuple3(PyObject *args, char *name, int min, return 0; } -static int -unpacktuple4(PyObject *args, char *name, int min, +static int +unpacktuple4(PyObject *args, char *name, int min, PyObject **a0, PyObject **a1, PyObject **a2, PyObject **a3) -{ +{ int l; l=PyTuple_Size(args); if (l < 0) return -1; - if (l < min) + if (l < min) { PyErr_Format(PyExc_TypeError, "expected %d arguments, got %d", min, l); return -1; @@ -254,15 +254,15 @@ unpacktuple4(PyObject *args, char *name, int min, return 0; } -static int -unpacktuple5(PyObject *args, char *name, int min, - PyObject **a0, PyObject **a1, PyObject **a2, +static int +unpacktuple5(PyObject *args, char *name, int min, + PyObject **a0, PyObject **a1, PyObject **a2, PyObject **a3, PyObject **a4) -{ +{ int l; l=PyTuple_Size(args); if (l < 0) return -1; - if (l < min) + if (l < min) { PyErr_Format(PyExc_TypeError, "expected %d arguments, got %d", min, l); return -1; @@ -275,15 +275,15 @@ unpacktuple5(PyObject *args, char *name, int min, return 0; } -static int -unpacktuple6(PyObject *args, char *name, int min, - PyObject **a0, PyObject **a1, PyObject **a2, +static int +unpacktuple6(PyObject *args, char *name, int min, + PyObject **a0, PyObject **a1, PyObject **a2, PyObject **a3, PyObject **a4, PyObject **a5) -{ +{ int l; l=PyTuple_Size(args); if (l < 0) return -1; - if (l < min) + if (l < min) { PyErr_Format(PyExc_TypeError, "expected %d arguments, got %d", min, l); return -1; @@ -300,7 +300,7 @@ unpacktuple6(PyObject *args, char *name, int min, /* -** Structures +** Structures */ typedef struct { @@ -384,17 +384,17 @@ static getattrofunc ExtensionClassGetattro; */ static PyMethodDef cAccessControl_methods[] = { - {"rolesForPermissionOn", + {"rolesForPermissionOn", (PyCFunction)rolesForPermissionOn, METH_VARARGS, "" }, - {"guarded_getattr", + {"guarded_getattr", (PyCFunction)module_guarded_getattr, METH_VARARGS, "" - }, - {"aq_validate", + }, + {"aq_validate", (PyCFunction)module_aq_validate, METH_VARARGS, "" @@ -693,7 +693,7 @@ static int authenticated = 1; ** elsewhere... (e.g. imports) */ -static int +static int ZopeSecurityPolicy_setup(void) { UNLESS (NoSequenceFormat = NATIVE_FROM_STRING( "'%s' passed as roles" @@ -757,8 +757,8 @@ convert_name(PyObject *name) /* ** unauthErr ** -** Generate the unauthorized error -*/ +** Generate the unauthorized error +*/ static void unauthErr(PyObject *name, PyObject *value) { @@ -810,7 +810,7 @@ static PyObject *ZopeSecurityPolicy_validate(PyObject *self, PyObject *args) { PyObject *name = NULL; PyObject *value = NULL; PyObject *context = NULL; - PyObject *roles = NULL; + PyObject *roles = NULL; /* Import from SimpleObject Policy._noroles */ /* Note that _noroles means missing roles, spelled with a NULL in C. Jim. */ @@ -833,14 +833,14 @@ static PyObject *ZopeSecurityPolicy_validate(PyObject *self, PyObject *args) { */ if (unpacktuple6(args, "validate", 5, &accessed, &container, - &name, &value, &context, &roles) < 0) + &name, &value, &context, &roles) < 0) return NULL; /*| # Provide special rules for acquisition attributes **| if type(name) in (StringType, UnicodeType): **| if name[:3] == 'aq_' and name not in valid_aq_: **| raise Unauthorized(name, value) - */ + */ if (NATIVE_CHECK(name) || PyUnicode_Check(name)) { char *sname = NULL; @@ -854,7 +854,7 @@ static PyObject *ZopeSecurityPolicy_validate(PyObject *self, PyObject *args) { * to do then. It's arguably conservative to raise Unauthorized * in this case. */ - if (sname == NULL || + if (sname == NULL || /* or starts with "aq_" */ (sname[0] == 'a' && sname[1] == 'q' && sname[2] == '_' && /* and isn't aq_{parent, inner, explicit} */ @@ -884,7 +884,7 @@ static PyObject *ZopeSecurityPolicy_validate(PyObject *self, PyObject *args) { containerbase = aq_base(container); if (containerbase == NULL) goto err; - + if (aq_isWrapper(accessed)) accessedbase = aq_base(accessed); else { @@ -910,7 +910,7 @@ static PyObject *ZopeSecurityPolicy_validate(PyObject *self, PyObject *args) { } /*| # We still might not have any roles - **| + **| **| if roles is _noroles: */ @@ -952,7 +952,7 @@ static PyObject *ZopeSecurityPolicy_validate(PyObject *self, PyObject *args) { unauthErr(name, value); goto err; } - } + } else { roles = aq_acquire(container, __roles__); if (roles == NULL) { @@ -992,7 +992,7 @@ static PyObject *ZopeSecurityPolicy_validate(PyObject *self, PyObject *args) { if (p == Py_None) { ASSIGN(p, PyObject_GetAttr(container, __allow_access_to_unprotected_subobjects__)); - if (p == NULL) + if (p == NULL) PyErr_Clear(); } @@ -1009,11 +1009,11 @@ static PyObject *ZopeSecurityPolicy_validate(PyObject *self, PyObject *args) { **| p = p(name, value) */ - if (p) + if (p) { if (! INT_CHECK(p)) { - if (PyDict_Check(p)) + if (PyDict_Check(p)) { if (NATIVE_CHECK(name) || PyUnicode_Check(name)) { @@ -1027,8 +1027,8 @@ static PyObject *ZopeSecurityPolicy_validate(PyObject *self, PyObject *args) { if (p == NULL) goto err; } - } - else + } + else { ASSIGN(p, callfunction2(p, name, value)); if (p == NULL) @@ -1040,7 +1040,7 @@ static PyObject *ZopeSecurityPolicy_validate(PyObject *self, PyObject *args) { /*| if not p: **| raise Unauthorized, cleanupName(name, value) */ - + if (p == NULL || ! PyObject_IsTrue(p)) { Py_XDECREF(p); unauthErr(name, value); @@ -1059,7 +1059,7 @@ static PyObject *ZopeSecurityPolicy_validate(PyObject *self, PyObject *args) { /*| # We are going to need a security-aware object to pass **| # to allowed(). We'll use the container - **| + **| **| value = container */ @@ -1072,7 +1072,7 @@ static PyObject *ZopeSecurityPolicy_validate(PyObject *self, PyObject *args) { **| if roles is None or 'Anonymous' in roles: return 1 **| except TypeError: **| LOG.warn('"%s' passed as roles" - **| " during validation of '%s' is not a sequence." % + **| " during validation of '%s' is not a sequence." % **| ('roles', name)) **| raise */ @@ -1097,7 +1097,7 @@ static PyObject *ZopeSecurityPolicy_validate(PyObject *self, PyObject *args) { if (!PyErr_ExceptionMatches(PyExc_TypeError)) goto err; PyErr_Fetch(&t, &v, &tb); - + m=PyObject_Repr(roles); if (m) ASSIGN(m, Py_BuildValue("OO", m, name)); if (m) ASSIGN(m, NATIVE_FORMAT(NoSequenceFormat, m)); @@ -1125,7 +1125,7 @@ static PyObject *ZopeSecurityPolicy_validate(PyObject *self, PyObject *args) { **| # If the executable had an owner, can it execute? **| owner = eo.getOwner() **| if (owner is not None) and not owner.allowed(value, roles) - **| # We don't want someone to acquire if they can't + **| # We don't want someone to acquire if they can't **| # get an unacquired! **| raise Unauthorized, ('You are not authorized to' **| 'access %s.' % cleanupName(name, value)) @@ -1138,7 +1138,7 @@ static PyObject *ZopeSecurityPolicy_validate(PyObject *self, PyObject *args) { owner = PyObject_GetAttr(eo, getOwner_str); if (owner) ASSIGN(owner, PyObject_CallObject(owner, NULL)); - if (owner ==NULL) + if (owner ==NULL) { Py_DECREF(eo); goto err; @@ -1171,14 +1171,14 @@ static PyObject *ZopeSecurityPolicy_validate(PyObject *self, PyObject *args) { **| if proxy_roles: **| # Verify that the owner actually can state the proxy role **| # in the context of the accessed item; users in subfolders - **| # should not be able to use proxy roles to access items + **| # should not be able to use proxy roles to access items **| # above their subfolder! **| owner = eo.getWrappedOwner() - **| + **| **| if owner is not None: **| if container is not containerbase: **| if not owner._check_context(container): - **| # container is higher up than the owner, + **| # container is higher up than the owner, **| # deny access **| raise Unauthorized(name, value) **| @@ -1190,12 +1190,12 @@ static PyObject *ZopeSecurityPolicy_validate(PyObject *self, PyObject *args) { */ proxy_roles = PyObject_GetAttr(eo, _proxy_roles_str); - if (proxy_roles == NULL) + if (proxy_roles == NULL) { Py_DECREF(eo); PyErr_Clear(); } - else if (PyObject_IsTrue(proxy_roles)) + else if (PyObject_IsTrue(proxy_roles)) { method = PyObject_GetAttr(eo, getWrappedOwner_str); @@ -1243,7 +1243,7 @@ static PyObject *ZopeSecurityPolicy_validate(PyObject *self, PyObject *args) { contains = 0; - if (PyTuple_Check(proxy_roles)) + if (PyTuple_Check(proxy_roles)) { l=PyTuple_GET_SIZE(proxy_roles); for (i=0; i < l; i++) @@ -1253,7 +1253,7 @@ static PyObject *ZopeSecurityPolicy_validate(PyObject *self, PyObject *args) { break; } } - else + else { l=PySequence_Size(proxy_roles); if (l < 0) contains = -1; @@ -1266,7 +1266,7 @@ static PyObject *ZopeSecurityPolicy_validate(PyObject *self, PyObject *args) { } else contains = -1; - if (contains < 0) + if (contains < 0) break; } } @@ -1358,37 +1358,37 @@ static void ZopeSecurityPolicy_dealloc(ZopeSecurityPolicy *self) { static PyObject * SecurityManager_validate(SecurityManager *self, PyObject *args) { - PyObject *accessed=Py_None, *container=Py_None, *name=Py_None, + PyObject *accessed=Py_None, *container=Py_None, *name=Py_None, *value=Py_None, *roles=NULL; - + if (unpacktuple5(args, "validate", 0, &accessed, &container, &name, &value, &roles) < 0) return NULL; CHECK_SECURITY_MANAGER_STATE(self, NULL); GET_SECURITY_MANAGER_VALIDATE(self, NULL); - + if (roles== NULL) - return callfunction5(self->validate, + return callfunction5(self->validate, accessed, container, name, value, self->context); - return callfunction6(self->validate, + return callfunction6(self->validate, accessed, container, name, value, self->context, roles); } static PyObject * SecurityManager_DTMLValidate(SecurityManager *self, PyObject *args) { - PyObject *accessed=Py_None, *container=Py_None, *name=Py_None, + PyObject *accessed=Py_None, *container=Py_None, *name=Py_None, *value=Py_None, *md=NULL; - + if (unpacktuple5(args, "DTMLValidate", 0, &accessed, &container, &name, &value, &md) < 0) return NULL; CHECK_SECURITY_MANAGER_STATE(self, NULL); GET_SECURITY_MANAGER_VALIDATE(self, NULL); - - return callfunction5(self->validate, + + return callfunction5(self->validate, accessed, container, name, value, self->context); } @@ -1396,21 +1396,21 @@ static PyObject * SecurityManager_checkPermission(SecurityManager *self, PyObject *args) { PyObject *permission, *object; - + if (unpacktuple2(args, "checkPermission", 2, &permission, &object) < 0) return NULL; CHECK_SECURITY_MANAGER_STATE(self, NULL); - if (self->checkPermission == NULL && - ((self->checkPermission = PyObject_GetAttr(self->policy, - checkPermission_str)) + if (self->checkPermission == NULL && + ((self->checkPermission = PyObject_GetAttr(self->policy, + checkPermission_str)) == NULL)) return NULL; - return callfunction3(self->checkPermission, + return callfunction3(self->checkPermission, permission, object, self->context); } -static void +static void SecurityManager_dealloc(SecurityManager *self) { Py_XDECREF(self->thread_id); @@ -1461,7 +1461,7 @@ SecurityManager_getattro(SecurityManager *self, PyObject *name) return Py_FindAttr(OBJECT(self), name); } -static int +static int SecurityManager_setattro(SecurityManager *self, PyObject *name, PyObject *v) { PyObject *name_as_bytes = NULL; @@ -1535,7 +1535,7 @@ static PyObject *PermissionRole_init(PermissionRole *self, PyObject *args) { **| self.__name__ = name **| self._p = "_" + string.translate(name, name_trans) + "_Permission" **| self._d = default - */ + */ if (unpacktuple2(args, "__init__", 1, &name, &deflt) < 0) return NULL; @@ -1580,7 +1580,7 @@ PermissionRole_of(PermissionRole *self, PyObject *parent) { r->_pa = parent; Py_INCREF(parent); - + /*| r._d = self._d */ @@ -1666,7 +1666,7 @@ PermissionRole_getattro(PermissionRole *self, PyObject *name) { if (name_s == NULL) PyErr_Clear(); /* defer to ExtensionClassGetattro */ else if (name_s[0] == '_') { - if (! strcmp(name_s, "__name__")) + if (! strcmp(name_s, "__name__")) result = self->__name__; else if (! strcmp(name_s, "__roles__")) result = self->__roles__; @@ -1796,7 +1796,7 @@ static void imPermissionRole_dealloc(imPermissionRole *self) { /* ** rolesForPermissionOn -*/ +*/ static PyObject *rolesForPermissionOn(PyObject *self, PyObject *args) { PyObject *perm = NULL; @@ -1809,19 +1809,19 @@ static PyObject *rolesForPermissionOn(PyObject *self, PyObject *args) { **| """Return the roles that have the permisson on the given object""" */ - if (unpacktuple4(args, "rolesForPermissionOn", 2, + if (unpacktuple4(args, "rolesForPermissionOn", 2, &perm, &object, &deflt, &n) < 0) return NULL; return c_rolesForPermissionOn(perm, object, deflt, n); } -/* +/* def rolesForPermissionOn(perm, object, default=_default_roles, n=None): """Return the roles that have the given permission on the given object """ */ static PyObject * -c_rolesForPermissionOn(PyObject *perm, PyObject *object, +c_rolesForPermissionOn(PyObject *perm, PyObject *object, PyObject *_default_roles, PyObject *n) { PyObject *r, *result = NULL; @@ -1923,14 +1923,14 @@ c_rolesForPermissionOn(PyObject *perm, PyObject *object, goto end; } } - + /* elif roles: if r is None: r = list(roles) else: r = r + list(roles) */ - else + else { int roles_is_true = PyObject_IsTrue(roles); if (roles_is_true < 0) @@ -1962,7 +1962,7 @@ c_rolesForPermissionOn(PyObject *perm, PyObject *object, else /* roles == NULL */ PyErr_Clear(); - + /* object = aq_inner(object) if object is None: @@ -1971,16 +1971,16 @@ c_rolesForPermissionOn(PyObject *perm, PyObject *object, */ { PyObject *tobj = aq_inner(object); - if (tobj == NULL) + if (tobj == NULL) goto end; Py_DECREF(object); object = tobj; - - if (object == Py_None) + + if (object == Py_None) break; tobj = aq_parent(object); - if (tobj == NULL) + if (tobj == NULL) goto end; Py_DECREF(object); object = tobj; @@ -2005,13 +2005,13 @@ c_rolesForPermissionOn(PyObject *perm, PyObject *object, Py_INCREF(r); result = r; - + end: Py_DECREF(n); Py_DECREF(object); Py_DECREF(r); return result; -} +} /* @@ -2062,7 +2062,7 @@ static PyObject *permissionName(PyObject *name) { /* def guarded_getattr(inst, name, default=_marker): */ static PyObject * -guarded_getattr(PyObject *inst, PyObject *name, PyObject *default_, +guarded_getattr(PyObject *inst, PyObject *name, PyObject *default_, PyObject *validate) { PyObject *v=0, *t=0; @@ -2129,13 +2129,13 @@ guarded_getattr(PyObject *inst, PyObject *name, PyObject *default_, if (PyDict_Check(t)) { PyObject *attrv; - + attrv = PyDict_GetItem(t, name); if (attrv != NULL) { i=PyObject_IsTrue(attrv); if (i < 0) goto err; - if (i) + if (i) { if (Py_TYPE(attrv)->tp_call) { @@ -2166,7 +2166,7 @@ guarded_getattr(PyObject *inst, PyObject *name, PyObject *default_, PyObject *factory; factory = callfunction2(t, name, v); - if (factory == NULL) + if (factory == NULL) goto err; if (PyCallable_Check(factory)) @@ -2179,13 +2179,13 @@ guarded_getattr(PyObject *inst, PyObject *name, PyObject *default_, return v; } - /* + /* # See if we can get the value doing a filtered acquire. # aq_acquire will either return the same value as held by # v or it will return an Unauthorized raised by validate. validate = SecurityManagement.getSecurityManager().validate aq_acquire(inst, name, aq_validate, validate) - + return v */ @@ -2198,7 +2198,7 @@ guarded_getattr(PyObject *inst, PyObject *name, PyObject *default_, Py_DECREF(t); return v; - + unauthErr(name, v); err: Py_DECREF(v); @@ -2282,8 +2282,8 @@ dtml_guarded_getattr(PyObject *self, PyObject *args) if (unpacktuple3(args, "guarded_getattr", 2, &ob, &name, &default_) < 0) return NULL; - - UNLESS (validate = PyObject_GetAttr(self, validate_str)) + + UNLESS (validate = PyObject_GetAttr(self, validate_str)) { /* This section is pure paranoia at this point. It was necessary while debugging. */ @@ -2301,7 +2301,7 @@ dtml_guarded_getattr(PyObject *self, PyObject *args) static struct PyMethodDef dtml_methods[] = { - {"guarded_getattr", (PyCFunction)dtml_guarded_getattr, + {"guarded_getattr", (PyCFunction)dtml_guarded_getattr, METH_VARARGS|METH_KEYWORDS, "" }, {NULL, NULL} }; @@ -2314,7 +2314,6 @@ static struct PyMethodDef dtml_methods[] = { #define IMPORT(module, name) if ((module = PyImport_ImportModule(name)) == NULL) return NULL; #define GETATTR(module, name) if ((name = PyObject_GetAttrString(module, #name)) == NULL) return NULL; -#ifdef PY3K static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, @@ -2327,7 +2326,6 @@ static struct PyModuleDef moduledef = NULL, /* m_clear */ NULL, /* m_free */ }; -#endif static PyObject* module_init(void) { @@ -2345,14 +2343,7 @@ module_init(void) { ExtensionClassGetattro= Py_FindAttr; - #ifdef PY3K - module = PyModule_Create(&moduledef); - #else - module = Py_InitModule3( - "cAccessControl", - cAccessControl_methods, - "cAccessControl.c\n"); - #endif + module = PyModule_Create(&moduledef); aq_init(); /* For Python <= 2.1.1, aq_init() should be after Py_InitModule(). */ @@ -2377,7 +2368,7 @@ module_init(void) { PyExtensionClass_Export(dict, "imPermissionRole", imPermissionRoleType); - imPermissionRoleObj = PyMapping_GetItemString(dict, + imPermissionRoleObj = PyMapping_GetItemString(dict, "imPermissionRole"); aq_validate = PyMapping_GetItemString(dict, "aq_validate"); @@ -2428,14 +2419,7 @@ module_init(void) { return module; } -#ifdef PY3K PyMODINIT_FUNC PyInit_cAccessControl(void) { return module_init(); } -#else -PyMODINIT_FUNC initcAccessControl(void) -{ - module_init(); -} -#endif diff --git a/src/AccessControl/class_init.py b/src/AccessControl/class_init.py index 3d1a1d8..c95e0d3 100644 --- a/src/AccessControl/class_init.py +++ b/src/AccessControl/class_init.py @@ -36,7 +36,8 @@ def InitializeClass(self): if name != oldname: # Tried to implicitly assign a different name! try: - classname = '%s.%s' % (self.__module__, self.__name__) + classname = '{}.{}'.format( + self.__module__, self.__name__) except AttributeError: classname = repr(self) logging.getLogger("Init").warning( diff --git a/src/AccessControl/interfaces.py b/src/AccessControl/interfaces.py index 29a17f2..ea5899f 100644 --- a/src/AccessControl/interfaces.py +++ b/src/AccessControl/interfaces.py @@ -291,7 +291,7 @@ class ISecurityManager(Interface): """Check access and manages executable context and policies. """ - _policy = Attribute(u'Current Security Policy') + _policy = Attribute('Current Security Policy') def validate(accessed=None, container=None, diff --git a/src/AccessControl/requestmethod.py b/src/AccessControl/requestmethod.py index 393fe13..d82dcc8 100644 --- a/src/AccessControl/requestmethod.py +++ b/src/AccessControl/requestmethod.py @@ -11,20 +11,13 @@ # ############################################################################## -import six +from inspect import getfullargspec +from inspect import signature from zExceptions import Forbidden from zope.publisher.interfaces.browser import IBrowserRequest -if six.PY3: - from inspect import getfullargspec - from inspect import signature -else: # Python 2 - from inspect import getargspec as getfullargspec - - from funcsigs import signature - _default = [] @@ -42,9 +35,9 @@ def buildfacade(name, method, docstring): parts = str(v).split('=') args.append( parts[0] if len(parts) == 1 else - '{}=_default'.format(parts[0])) # NOQA: 43 + f'{parts[0]}=_default') # NOQA: 43 callargs.append(parts[0]) - return 'def %s(%s):\n """%s"""\n return _curried(%s)' % ( + return 'def {}({}):\n """{}"""\n return _curried({})'.format( name, ', '.join(args), docstring, ', '.join(callargs)) diff --git a/src/AccessControl/rolemanager.py b/src/AccessControl/rolemanager.py index 588fb14..2764462 100644 --- a/src/AccessControl/rolemanager.py +++ b/src/AccessControl/rolemanager.py @@ -14,6 +14,7 @@ """ from base64 import urlsafe_b64encode +from html import escape from Acquisition import Acquired from Acquisition import aq_base @@ -30,12 +31,6 @@ from AccessControl.Permissions import change_permissions -try: - from html import escape -except ImportError: # PY2 - from cgi import escape - - DEFAULTMAXLISTUSERS = 250 @@ -111,7 +106,7 @@ def permission_settings(self, permission=None): 'acquire': isinstance(roles, list) and 'CHECKED' or '', 'roles': tuple(map( lambda ir, roles=roles, valid=valid, ip=ip: - {'name': "permission_%srole_%s" % ( + {'name': "permission_{}role_{}".format( _string_hash(permission_name), _string_hash(valid[ir])), 'checked': (valid[ir] in roles) and 'CHECKED' or ''}, diff --git a/src/AccessControl/safe_formatter.py b/src/AccessControl/safe_formatter.py index 3d6239c..e777c97 100644 --- a/src/AccessControl/safe_formatter.py +++ b/src/AccessControl/safe_formatter.py @@ -1,28 +1,14 @@ import string +from collections.abc import Mapping -import six +import _string from AccessControl.ZopeGuards import guarded_getattr from AccessControl.ZopeGuards import guarded_getitem -try: - # Python 3 - import _string -except ImportError: - pass - -if six.PY3: - from collections.abc import Mapping -else: - from collections import Mapping - - def formatter_field_name_split(field_name): - if six.PY3: - return _string.formatter_field_name_split(field_name) - else: - return field_name._formatter_field_name_split() + return _string.formatter_field_name_split(field_name) class _MagicFormatMapping(Mapping): @@ -63,7 +49,7 @@ class SafeFormatter(string.Formatter): def __init__(self, value): self.value = value - super(SafeFormatter, self).__init__() + super().__init__() def get_field(self, field_name, args, kwargs): """Get the field value using guarded methods.""" diff --git a/src/AccessControl/security.py b/src/AccessControl/security.py index d9fbf2f..c3ce272 100644 --- a/src/AccessControl/security.py +++ b/src/AccessControl/security.py @@ -14,8 +14,6 @@ """Security handling """ -import six - from zope.component import getUtility from zope.component import queryUtility from zope.component.zcml import utility @@ -80,8 +78,8 @@ def checkPermission(permission, object, interaction=None): permission is CheckerPublic: return True - if isinstance(permission, six.string_types): - permission = queryUtility(IPermission, six.u(permission)) + if isinstance(permission, str): + permission = queryUtility(IPermission, permission) if permission is None: return False diff --git a/src/AccessControl/tainted.py b/src/AccessControl/tainted.py index 9d5fc17..eaebff2 100644 --- a/src/AccessControl/tainted.py +++ b/src/AccessControl/tainted.py @@ -19,14 +19,7 @@ """ from functools import total_ordering - -import six - - -try: - from html import escape -except ImportError: # PY2 - from cgi import escape +from html import escape def should_be_tainted(value): @@ -34,10 +27,7 @@ def should_be_tainted(value): # ord('<') is 60 return 60 == value elif isinstance(value, bytes): - if six.PY2: - return b'<' in value - else: - return 60 in value + return 60 in value else: return '<' in value @@ -50,7 +40,7 @@ def taint_string(value): @total_ordering -class TaintedString(object): +class TaintedString: def __init__(self, value): self._value = value @@ -61,10 +51,6 @@ def __str__(self): def __repr__(self): return repr(self.quoted()) - if six.PY2: - def __cmp__(self, o): - return cmp(self._value, o) # noqa - def __eq__(self, o): return self._value == o @@ -112,10 +98,6 @@ def __int__(self): def __float__(self): return float(self._value) - if six.PY2: - def __long__(self): - return long(self._value) # NOQA - def __getstate__(self): # If an object tries to store a TaintedString, it obviously wasn't # aware that it was playing with untrusted data. Complain acordingly. @@ -128,10 +110,6 @@ def __getattr__(self, a): # for string methods support other than those defined below return getattr(self._value, a) - # Python 2.2 only. - def decode(self, *args): - return self.__class__(self._value.decode(*args)) - def encode(self, *args): return self.__class__(self._value.encode(*args)) @@ -199,16 +177,12 @@ def __init__(self, value): if isinstance(value, bytes): self._value = value elif isinstance(value, int): - if six.PY2: - raise ValueError( - "Constructing from a single character as an int " - "is valid only with Python 3.") value = bytes([value]) self._value = value else: raise ValueError( "Can be constructed only from bytes " - "(or a single int with Python3).") + "(or a single int).") def quoted(self): result = escape(self._value.decode('utf8'), 1) diff --git a/src/AccessControl/tests/actual_python.py b/src/AccessControl/tests/actual_python.py index b8a72ef..3405b8e 100644 --- a/src/AccessControl/tests/actual_python.py +++ b/src/AccessControl/tests/actual_python.py @@ -9,12 +9,7 @@ def f1(): - try: - range_ = xrange - except NameError: # Py3 - range_ = range - - iterator = iter(range_(3)) + iterator = iter(range(3)) assert next(iterator) == 0 assert next(iterator) == 1 assert next(iterator) == 2 @@ -120,16 +115,6 @@ def f7(): methods = [('keys', 'k'), ('items', 'i'), ('values', 'v')] - try: - {}.iterkeys - except AttributeError: - pass - else: - # Python 2 only: - methods.extend([ - ('iterkeys', 'k'), - ('iteritems', 'i'), - ('itervalues', 'v')]) expected = {'k': [1, 3], 'v': [2, 4], diff --git a/src/AccessControl/tests/testImplementation.py b/src/AccessControl/tests/testImplementation.py index b9f04ce..e77b1b4 100644 --- a/src/AccessControl/tests/testImplementation.py +++ b/src/AccessControl/tests/testImplementation.py @@ -61,4 +61,5 @@ def tearDown(self): def test_suite(): - return unittest.makeSuite(AccessControlImplementationTest) + return unittest.defaultTestLoader.loadTestsFromTestCase( + AccessControlImplementationTest) diff --git a/src/AccessControl/tests/testPermissionRole.py b/src/AccessControl/tests/testPermissionRole.py index 8a1107b..725e16b 100644 --- a/src/AccessControl/tests/testPermissionRole.py +++ b/src/AccessControl/tests/testPermissionRole.py @@ -80,7 +80,7 @@ def assertPRoles(ob, permission, expect): expected[r] = 1 if got == expected: # Dict compare does the Right Thing. same = 1 - assert same, 'Expected roles: %r, got: %r' % (expect, roles) + assert same, 'Expected roles: {!r}, got: {!r}'.format(expect, roles) class PermissionRoleTests (unittest.TestCase): diff --git a/src/AccessControl/tests/testZCML.py b/src/AccessControl/tests/testZCML.py index f5a7dc8..9d412a5 100644 --- a/src/AccessControl/tests/testZCML.py +++ b/src/AccessControl/tests/testZCML.py @@ -42,7 +42,7 @@ def foo(): @implementer(IDummy) -class Dummy1(object): +class Dummy1: def foo(self): pass @@ -72,19 +72,19 @@ class Dummy2(Dummy1): class IDummy3(Interface): - attr = TextLine(title=u"Attribute") + attr = TextLine(title="Attribute") @implementer(IDummy3) -class Dummy3(object): +class Dummy3: attr = None -class Dummy4(object): +class Dummy4: foo = None -class Dummy5(object): +class Dummy5: pass @@ -132,7 +132,7 @@ def test_security_equivalence(self): # ZCML declarations for ``Dummy1``: from io import StringIO - configure_zcml = StringIO(u''' + configure_zcml = StringIO(''' @@ -483,6 +483,7 @@ def test_register_permission_with_non_default_roles(): def test_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(TestSecurity)) + suite.addTest( + unittest.defaultTestLoader.loadTestsFromTestCase(TestSecurity)) suite.addTest(doctest.DocTestSuite(optionflags=doctest.ELLIPSIS)) return suite diff --git a/src/AccessControl/tests/testZopeGuards.py b/src/AccessControl/tests/testZopeGuards.py index 1ac61ce..3f459a0 100644 --- a/src/AccessControl/tests/testZopeGuards.py +++ b/src/AccessControl/tests/testZopeGuards.py @@ -21,8 +21,6 @@ import sys import unittest -import six - from AccessControl.ZopeGuards import guarded_all from AccessControl.ZopeGuards import guarded_any from AccessControl.ZopeGuards import guarded_getattr @@ -153,7 +151,7 @@ def test_simple_object_policies(self): orig_value = self.__sm.reject self.__sm.reject = True try: - items = [b'a ', u'a '] + items = [b'a ', 'a '] for item in items: self.assertEqual(guarded_getattr(item, 'strip')(), item.strip()) @@ -259,44 +257,11 @@ def test_pop_validates(self): self.setSecurityManager(old) self.assertTrue(sm.calls) - @unittest.skipIf(six.PY3, "iter... is Python 2 only") - def test_iterkeys_simple(self): - from AccessControl.ZopeGuards import get_iter - d = { - 'foo': 1, - 'bar': 2, - 'baz': 3, - } - iterkeys = get_iter(d, 'iterkeys') - keys = d.keys() - keys.sort() - ikeys = sorted(iterkeys()) - self.assertEqual(keys, ikeys) - - @unittest.skipIf(six.PY3, "iter... is Python 2 only") - def test_iterkeys_empty(self): - from AccessControl.ZopeGuards import get_iter - iterkeys = get_iter({}, 'iterkeys') - self.assertEqual(list(iterkeys()), []) - - @unittest.skipIf(six.PY2, "keys() is only in Python 3 a generator") def test_keys_empty(self): from AccessControl.ZopeGuards import get_iter keys = get_iter({}, 'keys') self.assertEqual(list(keys()), []) - @unittest.skipIf(six.PY3, "iter... is Python 2 only") - def test_iterkeys_validates(self): - sm = SecurityManager() - old = self.setSecurityManager(sm) - iterkeys = guarded_getattr({GuardTestCase: 1}, 'iterkeys') - try: - next(iterkeys()) - finally: - self.setSecurityManager(old) - self.assertTrue(sm.calls) - - @unittest.skipIf(six.PY2, "keys() is only in Python 3 a generator") def test_keys_validates(self): sm = SecurityManager() old = self.setSecurityManager(sm) @@ -307,44 +272,11 @@ def test_keys_validates(self): self.setSecurityManager(old) self.assertTrue(sm.calls) - @unittest.skipIf(six.PY3, "iter... is Python 2 only") - def test_itervalues_simple(self): - from AccessControl.ZopeGuards import get_iter - d = { - 'foo': 1, - 'bar': 2, - 'baz': 3, - } - itervalues = get_iter(d, 'itervalues') - values = d.values() - values.sort() - ivalues = sorted(itervalues()) - self.assertEqual(values, ivalues) - - @unittest.skipIf(six.PY3, "iter... is Python 2 only") - def test_itervalues_empty(self): - from AccessControl.ZopeGuards import get_iter - itervalues = get_iter({}, 'itervalues') - self.assertEqual(list(itervalues()), []) - - @unittest.skipIf(six.PY2, "values() is only in Python 3 a generator") def test_values_empty(self): from AccessControl.ZopeGuards import get_iter values = get_iter({}, 'values') self.assertEqual(list(values()), []) - @unittest.skipIf(six.PY3, "iter... is Python 2 only") - def test_itervalues_validates(self): - sm = SecurityManager() - old = self.setSecurityManager(sm) - itervalues = guarded_getattr({GuardTestCase: 1}, 'itervalues') - try: - next(itervalues()) - finally: - self.setSecurityManager(old) - self.assertTrue(sm.calls) - - @unittest.skipIf(six.PY2, "values() is only in Python 3 a generator") def test_values_validates(self): sm = SecurityManager() old = self.setSecurityManager(sm) @@ -1077,5 +1009,5 @@ def test_suite(): TestRestrictedPythonApply, TestActualPython, ): - suite.addTest(unittest.makeSuite(cls)) + suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(cls)) return suite diff --git a/src/AccessControl/tests/testZopeSecurityPolicy.py b/src/AccessControl/tests/testZopeSecurityPolicy.py index 1188a2a..9b12a0f 100644 --- a/src/AccessControl/tests/testZopeSecurityPolicy.py +++ b/src/AccessControl/tests/testZopeSecurityPolicy.py @@ -11,12 +11,13 @@ # ############################################################################## +import _thread as thread import os import sys import unittest from doctest import DocTestSuite - -from six.moves import _thread as thread +from sys import getswitchinterval +from sys import setswitchinterval from Acquisition import Explicit from Acquisition import Implicit @@ -27,14 +28,6 @@ from AccessControl.userfolder import UserFolder -try: - from sys import getswitchinterval - from sys import setswitchinterval -except ImportError: # Python 2 - from sys import getcheckinterval as getswitchinterval - from sys import setcheckinterval as setswitchinterval - - user_roles = ('RoleOfUser',) eo_roles = ('RoleOfExecutableOwner',) sysadmin_roles = ('RoleOfSysAdmin',) @@ -295,10 +288,10 @@ def testAccessToStringModule(self): def testUnicodeAttributeLookups(self): item = self.item r_item = self.a.r_item - self.assertPolicyAllows(item, u'public_prop') - self.assertPolicyDenies(r_item, u'private_prop') - self.assertPolicyAllows(item, u'public_m') - self.assertPolicyDenies(item, u'dangerous_m') + self.assertPolicyAllows(item, 'public_prop') + self.assertPolicyDenies(r_item, 'private_prop') + self.assertPolicyAllows(item, 'public_m') + self.assertPolicyDenies(item, 'dangerous_m') def testRolesForPermission(self): # Test of policy.checkPermission(). @@ -361,10 +354,10 @@ def test_checkPermission_proxy_role_scope(self): def testUnicodeRolesForPermission(self): r_item = self.a.r_item context = self.context - v = self.policy.checkPermission(u'View', r_item, context) + v = self.policy.checkPermission('View', r_item, context) self.assertTrue(not v, '_View_Permission should deny access to user') o_context = SecurityContext(self.uf.getUserById('theowner')) - v = self.policy.checkPermission(u'View', r_item, o_context) + v = self.policy.checkPermission('View', r_item, o_context) self.assertTrue(v, '_View_Permission should grant access to theowner') def testContainersContextManager(self): @@ -448,7 +441,7 @@ def testUnicodeName(self): # overridden to disallow some access of str.format. So we temporarily # restore the default of allowing all access. with override_containers(str, 1): - assert policy.validate('', '', u'foo', '', None) + assert policy.validate('', '', 'foo', '', None) if 0: # This test purposely generates a log entry. @@ -527,11 +520,11 @@ def _makeContext(self): def _makeEO(self): # create a faux executable whose owner forbids access - class Owner(object): + class Owner: def allowed(self, obj, roles): return False - class EO(object): + class EO: def getOwner(self): return Owner() @@ -737,17 +730,17 @@ def tearDown(self): def testGetRolesWithMultiThread(self): from AccessControl.ZopeSecurityPolicy import getRoles - class C(object): + class C: pass - class V1(object): - class __roles__(object): + class V1: + class __roles__: @staticmethod def rolesForPermissionOn(ob): return ['Member'] - class V2(object): - class __roles__(object): + class V2: + class __roles__: @staticmethod def rolesForPermissionOn(ob): return ['User'] @@ -775,11 +768,16 @@ def loop(): def test_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(Python_ZSPTests)) - suite.addTest(unittest.makeSuite(Python_SMTests)) + suite.addTest( + unittest.defaultTestLoader.loadTestsFromTestCase(Python_ZSPTests)) + suite.addTest( + unittest.defaultTestLoader.loadTestsFromTestCase(Python_SMTests)) if not os.environ.get('PURE_PYTHON'): - suite.addTest(unittest.makeSuite(C_ZSPTests)) - suite.addTest(unittest.makeSuite(C_SMTests)) + suite.addTest( + unittest.defaultTestLoader.loadTestsFromTestCase(C_ZSPTests)) + suite.addTest( + unittest.defaultTestLoader.loadTestsFromTestCase(C_SMTests)) suite.addTest(DocTestSuite()) - suite.addTest(unittest.makeSuite(GetRolesWithMultiThreadTest)) + suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase( + GetRolesWithMultiThreadTest)) return suite diff --git a/src/AccessControl/tests/test_owner.py b/src/AccessControl/tests/test_owner.py index 312db78..2ef46c4 100644 --- a/src/AccessControl/tests/test_owner.py +++ b/src/AccessControl/tests/test_owner.py @@ -197,7 +197,7 @@ class OwnershipChangeTests(unittest.TestCase): def setUp(self): from AccessControl.owner import UnownableOwner from AccessControl.userfolder import UserFolder - super(OwnershipChangeTests, self).setUp() + super().setUp() self.root = FauxRoot() self.root.acl_users = UserFolder() diff --git a/src/AccessControl/tests/test_safe_formatter.py b/src/AccessControl/tests/test_safe_formatter.py index 4e75a08..68f8408 100644 --- a/src/AccessControl/tests/test_safe_formatter.py +++ b/src/AccessControl/tests/test_safe_formatter.py @@ -17,7 +17,7 @@ def __init__(self, id, private=False): self.__roles__ = ['Anonymous'] def __repr__(self): - return ''.format(self.id) + return f'' class Folder(Persistent): @@ -41,13 +41,9 @@ def __getitem__(self, key): if isinstance(key, SliceType): return self.item_list[key] # Is this numeric (integer) access or string access? - # We could use isinstance(key, (int, long)), but long - # is not defined in Python 3. - try: - key = int(key) - except (ValueError, TypeError): - return self.item_dict[key] - return self.item_list[key] + if isinstance(key, int): + return self.item_list[key] + return self.item_dict[key] class FormatterTest(unittest.TestCase): @@ -100,21 +96,21 @@ def test_prevents_bad_unicode_formatting_attribute(self): from AccessControl.safe_formatter import SafeFormatter # Accessing basic Python attributes on a basic Python type is fine. - formatted = SafeFormatter(u'{0.upper}').safe_format('foo') + formatted = SafeFormatter('{0.upper}').safe_format('foo') self.assertTrue(formatted.startswith('') - self.assertEqual(SafeFormatter(u'{0.public2}').safe_format(folder), + self.assertEqual(SafeFormatter('{0.public2}').safe_format(folder), '') # But not the private item: self.assertRaises(Unauthorized, - SafeFormatter(u'{0.private}').safe_format, + SafeFormatter('{0.private}').safe_format, folder) def test_prevents_bad_string_formatting_item(self): @@ -141,18 +137,18 @@ def test_prevents_bad_unicode_formatting_item(self): # Accessing basic Python types in a basic Python dict is fine. foo = {'bar': 'Can you see me?'} - self.assertEqual(SafeFormatter(u'{0[bar]}').safe_format(foo), + self.assertEqual(SafeFormatter('{0[bar]}').safe_format(foo), 'Can you see me?') # But for non-basic items or non-basic lists, we want run checks. folder = self._create_folder_with_mixed_contents() # We can get the public items just fine: - self.assertEqual(SafeFormatter(u'{0[public1]}').safe_format(folder), + self.assertEqual(SafeFormatter('{0[public1]}').safe_format(folder), '') - self.assertEqual(SafeFormatter(u'{0[public2]}').safe_format(folder), + self.assertEqual(SafeFormatter('{0[public2]}').safe_format(folder), '') # But not the private item: self.assertRaises(Unauthorized, - SafeFormatter(u'{0[private]}').safe_format, + SafeFormatter('{0[private]}').safe_format, folder) def test_prevents_bad_string_formatting_key(self): @@ -194,15 +190,15 @@ def test_prevents_bad_unicode_formatting_key(self): # Accessing basic Python types in a basic Python list is fine. foo = list(['bar']) self.assertEqual(SafeFormatter('{0[0]}').safe_format(foo), - u'bar') + 'bar') # But for non-basic items or non-basic lists, we want run checks. folder = self._create_folder_with_mixed_contents() # We can get the public items just fine: - self.assertEqual(SafeFormatter(u'{0[0]}').safe_format(folder), + self.assertEqual(SafeFormatter('{0[0]}').safe_format(folder), '') - self.assertEqual(SafeFormatter(u'{0[2]}').safe_format(folder), + self.assertEqual(SafeFormatter('{0[2]}').safe_format(folder), '') # But not the private item: self.assertRaises(Unauthorized, - SafeFormatter(u'{0[1]}').safe_format, + SafeFormatter('{0[1]}').safe_format, folder) diff --git a/src/AccessControl/tests/test_tainted.py b/src/AccessControl/tests/test_tainted.py index 9c51b36..ec5fbfe 100644 --- a/src/AccessControl/tests/test_tainted.py +++ b/src/AccessControl/tests/test_tainted.py @@ -15,8 +15,6 @@ import unittest -import six - class TestFunctions(unittest.TestCase): @@ -177,11 +175,6 @@ def testStringMethods(self): unquoted.translate(transtable)) self.assertTrue(isinstance(self._getClass()('<').translate(transtable), self._getClass())) - if six.PY2: - # Translate no longer supports a second argument - kls = self._getClass()('<') - self.assertFalse(isinstance(kls.translate(transtable, '<'), - self._getClass())) def testQuoted(self): self.assertEqual(self.tainted.quoted(), self.quoted) @@ -210,7 +203,7 @@ def testGetItem(self): self.assertTrue(isinstance(self.tainted[0], self._getClass())) self.assertEqual(self.tainted[0], self._getClass()(b'<')) self.assertFalse(isinstance(self.tainted[-1], self._getClass())) - self.assertEqual(self.tainted[-1], 62 if six.PY3 else b'>') + self.assertEqual(self.tainted[-1], 62) def testStr(self): self.assertEqual(str(self.tainted), self.unquoted.decode('utf8')) @@ -294,27 +287,16 @@ def testStringMethods(self): self.assertTrue(isinstance(lines[1], self._getClass())) self.assertFalse(isinstance(lines[0], self._getClass())) - if six.PY3: - transtable = bytes(range(256)) - else: - transtable = ''.join(map(chr, range(256))) + transtable = bytes(range(256)) self.assertEqual(tainted.translate(transtable), unquoted.translate(transtable)) kls = self._getClass()(b'<') self.assertTrue(isinstance(kls.translate(transtable), self._getClass())) - if six.PY2: - # Translate no longer supports a second argument - kls = self._getClass()(b'<') - self.assertFalse(isinstance(kls.translate(transtable, b'<'), - self._getClass())) def testConstructor(self): from AccessControl.tainted import TaintedBytes - if six.PY2: - self.assertRaises(ValueError, TaintedBytes, [60]) - if six.PY3: - self.assertEqual(TaintedBytes(60), b'<') - self.assertEqual(TaintedBytes(32), b' ') + self.assertEqual(TaintedBytes(60), b'<') + self.assertEqual(TaintedBytes(32), b' ') self.assertEqual(TaintedBytes(b'abc'), b'abc') - self.assertRaises(ValueError, TaintedBytes, u"abc") + self.assertRaises(ValueError, TaintedBytes, "abc") diff --git a/src/AccessControl/tests/test_users.py b/src/AccessControl/tests/test_users.py index 3de366c..02df44c 100644 --- a/src/AccessControl/tests/test_users.py +++ b/src/AccessControl/tests/test_users.py @@ -62,7 +62,7 @@ def test_getRolesInContext_no_aq_no_local_roles(self): self.assertEqual(derived.getRolesInContext(self), ['Manager']) def test_getRolesInContext_no_aq_w_local_roles_as_dict(self): - class Target(object): + class Target: __ac_local_roles__ = {'user': ['Other']} derived = self._makeDerived() @@ -72,7 +72,7 @@ class Target(object): ['Manager', 'Other']) def test_getRolesInContext_no_aq_w_local_roles_as_callable(self): - class Context(object): + class Context: def __ac_local_roles__(self): return {'user': ['Other']} @@ -83,7 +83,7 @@ def __ac_local_roles__(self): ['Manager', 'Other']) def test_getRolesInContext_w_aq(self): - class Context(object): + class Context: pass derived = self._makeDerived() @@ -95,10 +95,10 @@ class Context(object): target.__ac_local_roles__ = {'user': ['Other']} target.__parent__ = parent self.assertEqual(set(derived.getRolesInContext(target)), - set(['Manager', 'Other', 'Another'])) + {'Manager', 'Other', 'Another'}) def test_getRolesInContext_w_method(self): - class Context(object): + class Context: __ac_local_roles__ = {'user': ['Other']} def method(self): diff --git a/src/AccessControl/userfolder.py b/src/AccessControl/userfolder.py index bd06c05..8405ef5 100644 --- a/src/AccessControl/userfolder.py +++ b/src/AccessControl/userfolder.py @@ -13,12 +13,7 @@ """User folders. """ -try: - from base64 import decodebytes -except ImportError: - from base64 import decodestring as decodebytes - -import six +from base64 import decodebytes from Acquisition import Implicit from Acquisition import aq_base @@ -115,7 +110,7 @@ def _doDelUsers(self, names): raise NotImplementedError def identify(self, auth): - if isinstance(auth, six.text_type): + if isinstance(auth, str): auth = auth.encode('UTF-8') if auth and auth.lower().startswith(b'basic '): diff --git a/src/AccessControl/users.py b/src/AccessControl/users.py index f246f02..8ce2edb 100644 --- a/src/AccessControl/users.py +++ b/src/AccessControl/users.py @@ -13,7 +13,6 @@ """Access control package. """ -from __future__ import absolute_import import os import re @@ -252,7 +251,7 @@ def __str__(self): return self.getUserName() def __repr__(self): - return '<%s %r>' % (self.__class__.__name__, self.getUserName()) + return '<{} {!r}>'.format(self.__class__.__name__, self.getUserName()) class SimpleUser(BasicUser): @@ -371,7 +370,7 @@ def readUserAccessFile(filename): try: with open(os.path.join(instancehome, filename), 'rb') as f: line = f.readline() - except IOError: + except OSError: return None if line: