Skip to content

Commit

Permalink
- remove all pre-Python 38 compatibility code
Browse files Browse the repository at this point in the history
  • Loading branch information
dataflake committed Oct 8, 2024
1 parent de42090 commit fd11a24
Show file tree
Hide file tree
Showing 8 changed files with 36 additions and 118 deletions.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ branch = true
source = ["RestrictedPython"]

[tool.coverage.report]
fail_under = 97
fail_under = 97.9
precision = 2
ignore_errors = true
show_missing = true
Expand Down
1 change: 0 additions & 1 deletion src/RestrictedPython/_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@


_version = sys.version_info
IS_PY38_OR_GREATER = _version.major == 3 and _version.minor >= 8
IS_PY310_OR_GREATER = _version.major == 3 and _version.minor >= 10
IS_PY311_OR_GREATER = _version.major == 3 and _version.minor >= 11
IS_PY312_OR_GREATER = _version.major == 3 and _version.minor >= 12
Expand Down
108 changes: 27 additions & 81 deletions src/RestrictedPython/transformer.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,6 @@
import contextlib
import textwrap

from ._compat import IS_PY38_OR_GREATER


# Avoid DeprecationWarnings under Python 3.12 and up
if IS_PY38_OR_GREATER:
astStr = ast.Constant
astNum = ast.Constant
else: # pragma: no cover
astStr = ast.Str
astNum = ast.Num

# For AugAssign the operator must be converted to a string.
IOPERATOR_TO_STR = {
Expand Down Expand Up @@ -127,16 +117,14 @@ def copy_locations(new_node, old_node):
assert 'lineno' in new_node._attributes
new_node.lineno = old_node.lineno

if IS_PY38_OR_GREATER:
assert 'end_lineno' in new_node._attributes
new_node.end_lineno = old_node.end_lineno
assert 'end_lineno' in new_node._attributes
new_node.end_lineno = old_node.end_lineno

assert 'col_offset' in new_node._attributes
new_node.col_offset = old_node.col_offset

if IS_PY38_OR_GREATER:
assert 'end_col_offset' in new_node._attributes
new_node.end_col_offset = old_node.end_col_offset
assert 'end_col_offset' in new_node._attributes
new_node.end_col_offset = old_node.end_col_offset

ast.fix_missing_locations(new_node)

Expand Down Expand Up @@ -280,7 +268,7 @@ def gen_unpack_spec(self, tpl):
"""
spec = ast.Dict(keys=[], values=[])

spec.keys.append(astStr('childs'))
spec.keys.append(ast.Constant('childs'))
spec.values.append(ast.Tuple([], ast.Load()))

# starred elements in a sequence do not contribute into the min_len.
Expand All @@ -300,12 +288,12 @@ def gen_unpack_spec(self, tpl):

elif isinstance(val, ast.Tuple):
el = ast.Tuple([], ast.Load())
el.elts.append(astNum(idx - offset))
el.elts.append(ast.Constant(idx - offset))
el.elts.append(self.gen_unpack_spec(val))
spec.values[0].elts.append(el)

spec.keys.append(astStr('min_len'))
spec.values.append(astNum(min_len))
spec.keys.append(ast.Constant('min_len'))
spec.values.append(ast.Constant(min_len))

return spec

Expand Down Expand Up @@ -492,9 +480,8 @@ def inject_print_collector(self, node, position=0):
if isinstance(node, ast.Module):
_print.lineno = position
_print.col_offset = position
if IS_PY38_OR_GREATER:
_print.end_lineno = position
_print.end_col_offset = position
_print.end_lineno = position
_print.end_col_offset = position
ast.fix_missing_locations(_print)
else:
copy_locations(_print, node)
Expand Down Expand Up @@ -535,63 +522,22 @@ def node_contents_visit(self, node):

# ast for Literals

if IS_PY38_OR_GREATER:

def visit_Constant(self, node):
"""Allow constant literals with restriction for Ellipsis.
Constant replaces Num, Str, Bytes, NameConstant and Ellipsis in
Python 3.8+.
:see: https://docs.python.org/dev/whatsnew/3.8.html#deprecated
"""
if node.value is Ellipsis:
# Deny using `...`.
# Special handling necessary as ``self.not_allowed(node)``
# would return the Error Message:
# 'Constant statements are not allowed.'
# which is only partial true.
self.error(node, 'Ellipsis statements are not allowed.')
return
return self.node_contents_visit(node)

else:

def visit_Num(self, node):
"""Allow integer numbers without restrictions.
Replaced by Constant in Python 3.8.
"""
return self.node_contents_visit(node)

def visit_Str(self, node):
"""Allow string literals without restrictions.
Replaced by Constant in Python 3.8.
"""
return self.node_contents_visit(node)
def visit_Constant(self, node):
"""Allow constant literals with restriction for Ellipsis.
def visit_Bytes(self, node):
"""Allow bytes literals without restrictions.
Replaced by Constant in Python 3.8.
"""
return self.node_contents_visit(node)

def visit_Ellipsis(self, node):
"""Deny using `...`.
Replaced by Constant in Python 3.8.
"""
return self.not_allowed(node)

def visit_NameConstant(self, node):
"""Allow constant literals (True, False, None) without ...
restrictions.
Replaced by Constant in Python 3.8.
"""
return self.node_contents_visit(node)
Constant replaces Num, Str, Bytes, NameConstant and Ellipsis in
Python 3.8+.
:see: https://docs.python.org/dev/whatsnew/3.8.html#deprecated
"""
if node.value is Ellipsis:
# Deny using `...`.
# Special handling necessary as ``self.not_allowed(node)``
# would return the Error Message:
# 'Constant statements are not allowed.'
# which is only partial true.
self.error(node, 'Ellipsis statements are not allowed.')
return
return self.node_contents_visit(node)

def visit_Interactive(self, node):
"""Allow single mode without restrictions."""
Expand Down Expand Up @@ -915,7 +861,7 @@ def visit_Attribute(self, node):
node = self.node_contents_visit(node)
new_node = ast.Call(
func=ast.Name('_getattr_', ast.Load()),
args=[node.value, astStr(node.attr)],
args=[node.value, ast.Constant(node.attr)],
keywords=[])

copy_locations(new_node, node)
Expand Down Expand Up @@ -1119,7 +1065,7 @@ def visit_AugAssign(self, node):
value=ast.Call(
func=ast.Name('_inplacevar_', ast.Load()),
args=[
astStr(IOPERATOR_TO_STR[type(node.op)]),
ast.Constant(IOPERATOR_TO_STR[type(node.op)]),
ast.Name(node.target.id, ast.Load()),
node.value
],
Expand Down
3 changes: 0 additions & 3 deletions tests/test_NamedExpr.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,11 @@
from ast import NodeTransformer
from ast import parse
from unittest import TestCase
from unittest import skipUnless

from RestrictedPython import compile_restricted
from RestrictedPython import safe_globals
from RestrictedPython._compat import IS_PY38_OR_GREATER


@skipUnless(IS_PY38_OR_GREATER, "Feature available for Python 3.8+")
class TestNamedExpr(TestCase):
def test_works(self):
code, gs = compile_str("if x:= x + 1: True\n")
Expand Down
5 changes: 1 addition & 4 deletions tests/test_compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
from RestrictedPython import compile_restricted_eval
from RestrictedPython import compile_restricted_exec
from RestrictedPython import compile_restricted_single
from RestrictedPython._compat import IS_PY38_OR_GREATER
from RestrictedPython._compat import IS_PY310_OR_GREATER
from RestrictedPython._compat import IS_PY311_OR_GREATER
from tests.helper import restricted_eval
Expand Down Expand Up @@ -43,10 +42,8 @@ def test_compile__invalid_syntax():
compile_restricted(INVALID_ASSINGMENT, '<string>', 'exec')
if IS_PY310_OR_GREATER:
assert "SyntaxError: cannot assign to literal here." in str(err.value)
elif IS_PY38_OR_GREATER:
assert "cannot assign to literal at statement:" in str(err.value)
else:
assert "can't assign to literal at statement:" in str(err.value)
assert "cannot assign to literal at statement:" in str(err.value)


def test_compile__compile_restricted_exec__1():
Expand Down
7 changes: 1 addition & 6 deletions tests/test_compile_restricted_function.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from RestrictedPython import PrintCollector
from RestrictedPython import compile_restricted_function
from RestrictedPython import safe_builtins
from RestrictedPython._compat import IS_PY38_OR_GREATER
from RestrictedPython._compat import IS_PY310_OR_GREATER


Expand Down Expand Up @@ -242,11 +241,7 @@ def test_compile_restricted_function_invalid_syntax():
assert error_msg.startswith(
"Line 1: SyntaxError: cannot assign to literal here. Maybe "
)
elif IS_PY38_OR_GREATER:
assert error_msg.startswith(
"Line 1: SyntaxError: cannot assign to literal at statement:"
)
else:
assert error_msg.startswith(
"Line 1: SyntaxError: can't assign to literal at statement:"
"Line 1: SyntaxError: cannot assign to literal at statement:"
)
21 changes: 6 additions & 15 deletions tests/transformer/test_dict_comprehension.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from RestrictedPython._compat import IS_PY38_OR_GREATER
from tests.helper import restricted_exec


Expand Down Expand Up @@ -29,19 +28,11 @@ def test_dict_comprehension_with_attrs(mocker):
calls = [mocker.call(seq, 'z')]

# Note: Order changed in PEP 572, starting with Python 3.8.
if IS_PY38_OR_GREATER:
calls.extend([
mocker.call(z[0], 'k'),
mocker.call(z[1], 'k'),
mocker.call(z[1], 'k'),
mocker.call(z[1], 'v'),
])
else:
calls.extend([
mocker.call(z[0], 'k'),
mocker.call(z[1], 'k'),
mocker.call(z[1], 'v'),
mocker.call(z[1], 'k'),
])
calls.extend([
mocker.call(z[0], 'k'),
mocker.call(z[1], 'k'),
mocker.call(z[1], 'k'),
mocker.call(z[1], 'v'),
])

_getattr_.assert_has_calls(calls)
7 changes: 0 additions & 7 deletions tests/transformer/test_fstring.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import pytest

from RestrictedPython import compile_restricted_exec
from RestrictedPython._compat import IS_PY38_OR_GREATER
from RestrictedPython.PrintCollector import PrintCollector


Expand Down Expand Up @@ -37,10 +34,6 @@ def test_visit_invalid_variable_name():
"""


@pytest.mark.skipif(
not IS_PY38_OR_GREATER,
reason="f-string self-documenting expressions added in Python 3.8.",
)
def test_f_string_self_documenting_expressions():
"""Checks if f-string self-documenting expressions is checked."""
result = compile_restricted_exec(
Expand Down

0 comments on commit fd11a24

Please sign in to comment.