Skip to content

Commit

Permalink
Drop support for Python 2.7 up to 3.6.
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael Howitz committed Dec 20, 2022
1 parent 8cc379c commit b39348a
Show file tree
Hide file tree
Showing 32 changed files with 250 additions and 496 deletions.
7 changes: 1 addition & 6 deletions setup.py
Expand Up @@ -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',
Expand All @@ -80,7 +76,6 @@
'ExtensionClass >= 4.2.1',
'Persistence >= 3.0a3',
'RestrictedPython >= 5.1',
'six',
'transaction',
'zExceptions',
'zope.component',
Expand All @@ -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={
Expand Down
1 change: 0 additions & 1 deletion src/AccessControl/AuthEncoding.py
Expand Up @@ -11,7 +11,6 @@
#
##############################################################################

from __future__ import absolute_import

import AuthEncoding.AuthEncoding
from zope.deferredimport import deprecated
Expand Down
26 changes: 12 additions & 14 deletions src/AccessControl/ImplPython.py
Expand Up @@ -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
Expand All @@ -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


Expand All @@ -49,7 +48,6 @@
# TODO: implement this in cAccessControl, and have Implementation
# do the indirection.
#
from AccessControl.ZopeSecurityPolicy import getRoles # XXX


LOG = getLogger('ImplPython')
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -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:
Expand Down
1 change: 0 additions & 1 deletion src/AccessControl/Implementation.py
Expand Up @@ -24,7 +24,6 @@
module was introduced.
"""
from __future__ import absolute_import

import os

Expand Down
10 changes: 3 additions & 7 deletions src/AccessControl/PermissionMapping.py
Expand Up @@ -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
Expand All @@ -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:

Expand Down Expand Up @@ -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, '')
Expand Down
4 changes: 2 additions & 2 deletions src/AccessControl/SecurityInfo.py
Expand Up @@ -139,15 +139,15 @@ 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
self._unused_protected_decorators.remove(key)
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

Expand Down
3 changes: 1 addition & 2 deletions src/AccessControl/SecurityManagement.py
Expand Up @@ -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

Expand Down
4 changes: 2 additions & 2 deletions src/AccessControl/SimpleObjectPolicies.py
Expand Up @@ -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,
}

Expand Down
58 changes: 15 additions & 43 deletions src/AccessControl/ZopeGuards.py
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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):
Expand All @@ -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 = {
Expand Down Expand Up @@ -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):
Expand All @@ -284,7 +259,7 @@ def __next__(self):
guard(self.container, ob)
return ob

next = __next__ # Python 2 compat
next = __next__


class NullIter(SafeIter):
Expand All @@ -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):
Expand All @@ -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))
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down
5 changes: 1 addition & 4 deletions src/AccessControl/ZopeSecurityPolicy.py
Expand Up @@ -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
Expand All @@ -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):
Expand Down
14 changes: 1 addition & 13 deletions src/AccessControl/__init__.py
Expand Up @@ -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
Expand Down Expand Up @@ -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',
Expand Down
9 changes: 0 additions & 9 deletions src/AccessControl/_compat.h
Expand Up @@ -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

0 comments on commit b39348a

Please sign in to comment.