Skip to content

Commit 7876a87

Browse files
committed
Type Annotations for RestrictedPython
1 parent f208c0c commit 7876a87

File tree

7 files changed

+184
-156
lines changed

7 files changed

+184
-156
lines changed

.meta.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ testenv-additional = [
4747
" coverage combine",
4848
" coverage html",
4949
" coverage report -m --fail-under=100",
50-
"depends = py39,py310,py311,py311-datetime,py312,py313,py314,coverage",
50+
"depends = py39,py310,py311,py312,py313,py314,py314-datetime,coverage",
5151
]
5252
coverage-command = "pytest --cov=src --cov=tests --cov-report= tests {posargs}"
5353
coverage-setenv = [

setup.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,20 @@ def read(*rnames):
3939
'Programming Language :: Python',
4040
'Operating System :: OS Independent',
4141
'Programming Language :: Python :: 3',
42-
'Programming Language :: Python :: 3.9',
4342
'Programming Language :: Python :: 3.10',
4443
'Programming Language :: Python :: 3.11',
4544
'Programming Language :: Python :: 3.12',
4645
'Programming Language :: Python :: 3.13',
46+
'Programming Language :: Python :: 3.14',
4747
'Programming Language :: Python :: Implementation :: CPython',
4848
'Topic :: Security',
49+
'Typing :: Typed',
4950
],
5051
keywords='restricted execution security untrusted code',
5152
author='Zope Foundation and Contributors',
5253
author_email='[email protected]',
54+
maintainer='Zope Foundation, Plone Foundation and Contributors',
55+
maintainer_email='[email protected]',
5356
project_urls={
5457
"Documentation": "https://restrictedpython.readthedocs.io/",
5558
"Source": "https://github.com/zopefoundation/RestrictedPython",
@@ -59,9 +62,10 @@ def read(*rnames):
5962
packages=find_packages('src'),
6063
package_dir={'': 'src'},
6164
install_requires=[],
62-
python_requires=">=3.9, <3.15",
65+
python_requires=">=3.10, <3.15",
6366
extras_require={
6467
'test': ['pytest', 'pytest-mock'],
68+
'typecheck': ['mypy', 'typeshed'],
6569
'docs': ['Sphinx', 'furo'],
6670
},
6771
include_package_data=True,

src/RestrictedPython/Utilities.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import math
1515
import random
1616
import string
17+
from collections.abc import Iterable
1718

1819

1920
utility_builtins = {}
@@ -75,7 +76,8 @@ def test(*args):
7576
utility_builtins['test'] = test
7677

7778

78-
def reorder(s, with_=None, without=()):
79+
def reorder(s: Iterable, with_: Iterable | None = None,
80+
without: Iterable | None = None) -> Iterable:
7981
# s, with_, and without are sequences treated as sets.
8082
# The result is subtract(intersect(s, with_), without),
8183
# unless with_ is None, in which case it is subtract(s, without).

src/RestrictedPython/_compat.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,7 @@
66
IS_PY310_OR_GREATER = _version.major == 3 and _version.minor >= 10
77
IS_PY311_OR_GREATER = _version.major == 3 and _version.minor >= 11
88
IS_PY312_OR_GREATER = _version.major == 3 and _version.minor >= 12
9+
IS_PY313_OR_GREATER = _version.major == 3 and _version.minor >= 13
10+
IS_PY314_OR_GREATER = _version.major == 3 and _version.minor >= 14
911

1012
IS_CPYTHON = platform.python_implementation() == 'CPython'

src/RestrictedPython/compile.py

Lines changed: 40 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
import ast
22
import warnings
33
from collections import namedtuple
4+
from os import PathLike
5+
from typing import Any
6+
from typing import Literal
7+
from typing import TypeAlias
48

59
from RestrictedPython._compat import IS_CPYTHON
610
from RestrictedPython.transformer import RestrictingNodeTransformer
711

812

13+
# Temporary workaround for missing _typeshed
14+
ReadableBuffer: TypeAlias = bytes | bytearray
15+
16+
917
CompileResult = namedtuple(
1018
'CompileResult', 'code, errors, warnings, used_names')
1119
syntax_error_template = (
@@ -18,12 +26,12 @@
1826

1927

2028
def _compile_restricted_mode(
21-
source,
22-
filename='<string>',
23-
mode="exec",
24-
flags=0,
25-
dont_inherit=False,
26-
policy=RestrictingNodeTransformer):
29+
source: str | ReadableBuffer | ast.Module | ast.Expression | ast.Interactive,
30+
filename: str | ReadableBuffer | PathLike[Any] = '<string>',
31+
mode: Literal["exec", "eval", "single"] = "exec",
32+
flags: int = 0,
33+
dont_inherit: bool = False,
34+
policy: ast.NodeTransformer = RestrictingNodeTransformer) -> CompileResult:
2735

2836
if not IS_CPYTHON:
2937
warnings.warn_explicit(
@@ -78,11 +86,11 @@ def _compile_restricted_mode(
7886

7987

8088
def compile_restricted_exec(
81-
source,
82-
filename='<string>',
83-
flags=0,
84-
dont_inherit=False,
85-
policy=RestrictingNodeTransformer):
89+
source: str | ReadableBuffer | ast.Module | ast.Expression | ast.Interactive,
90+
filename: str | ReadableBuffer | PathLike[Any] = '<string>',
91+
flags: int = 0,
92+
dont_inherit: bool = False,
93+
policy: ast.NodeTransformer = RestrictingNodeTransformer) -> CompileResult:
8694
"""Compile restricted for the mode `exec`."""
8795
return _compile_restricted_mode(
8896
source,
@@ -94,11 +102,11 @@ def compile_restricted_exec(
94102

95103

96104
def compile_restricted_eval(
97-
source,
98-
filename='<string>',
99-
flags=0,
100-
dont_inherit=False,
101-
policy=RestrictingNodeTransformer):
105+
source: str | ReadableBuffer | ast.Module | ast.Expression | ast.Interactive,
106+
filename: str | ReadableBuffer | PathLike[Any] = '<string>',
107+
flags: int = 0,
108+
dont_inherit: bool = False,
109+
policy: ast.NodeTransformer = RestrictingNodeTransformer) -> CompileResult:
102110
"""Compile restricted for the mode `eval`."""
103111
return _compile_restricted_mode(
104112
source,
@@ -110,11 +118,11 @@ def compile_restricted_eval(
110118

111119

112120
def compile_restricted_single(
113-
source,
114-
filename='<string>',
115-
flags=0,
116-
dont_inherit=False,
117-
policy=RestrictingNodeTransformer):
121+
source: str | ReadableBuffer | ast.Module | ast.Expression | ast.Interactive,
122+
filename: str | ReadableBuffer | PathLike[Any] = '<string>',
123+
flags: int = 0,
124+
dont_inherit: bool = False,
125+
policy: ast.NodeTransformer = RestrictingNodeTransformer) -> CompileResult:
118126
"""Compile restricted for the mode `single`."""
119127
return _compile_restricted_mode(
120128
source,
@@ -128,12 +136,12 @@ def compile_restricted_single(
128136
def compile_restricted_function(
129137
p, # parameters
130138
body,
131-
name,
132-
filename='<string>',
139+
name: str,
140+
filename: str | ReadableBuffer | PathLike[Any] = '<string>',
133141
globalize=None, # List of globals (e.g. ['here', 'context', ...])
134-
flags=0,
135-
dont_inherit=False,
136-
policy=RestrictingNodeTransformer):
142+
flags: int = 0,
143+
dont_inherit: bool = False,
144+
policy: ast.NodeTransformer = RestrictingNodeTransformer) -> CompileResult:
137145
"""Compile a restricted code object for a function.
138146
139147
Documentation see:
@@ -181,12 +189,12 @@ def compile_restricted_function(
181189

182190

183191
def compile_restricted(
184-
source,
185-
filename='<unknown>',
186-
mode='exec',
187-
flags=0,
188-
dont_inherit=False,
189-
policy=RestrictingNodeTransformer):
192+
source: str | ReadableBuffer | ast.Module | ast.Expression | ast.Interactive,
193+
filename: str | ReadableBuffer | PathLike[Any] = '<unknown>',
194+
mode: str = 'exec',
195+
flags: int = 0,
196+
dont_inherit: bool = False,
197+
policy: ast.NodeTransformer = RestrictingNodeTransformer) -> CompileResult:
190198
"""Replacement for the built-in compile() function.
191199
192200
policy ... `ast.NodeTransformer` class defining the restrictions.

0 commit comments

Comments
 (0)