Skip to content
Draft
Show file tree
Hide file tree
Changes from 38 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
7876a87
Type Annotations for RestrictedPython
loechel Oct 18, 2025
1cd6198
isinstance check with ExtSlice and Tuple as for older Python Versions
loechel Oct 18, 2025
e2599ab
liniting
loechel Oct 18, 2025
4915d8e
Remove Python 3.9 as it end of life
loechel Oct 18, 2025
3299a8b
Remove License Cassifier, as they are deprecated
loechel Oct 18, 2025
4d56e39
Add Comment for TryStar Annotation
loechel Oct 18, 2025
935a960
Add Comment for TryStar Annotation
loechel Oct 18, 2025
e67da67
Add Comment for TryStar Annotation
loechel Oct 18, 2025
2a3d728
Add Changelog Entry
loechel Oct 18, 2025
3373795
Base for Python 3.14 Updates
loechel Oct 18, 2025
f86d895
Update docs for Python 3.14
loechel Oct 18, 2025
b4ceb35
add provisional visit_TempalteStr and visit_Interpolation to transfor…
loechel Oct 18, 2025
43941ee
Disable t-strings
loechel Oct 18, 2025
f0e2a06
Apply pre-commit code formatting
pre-commit-ci-lite[bot] Oct 18, 2025
26a218c
reactivate Template-Strings
loechel Oct 18, 2025
a4e189e
Update Documentation for TemplateStr and Interploation
loechel Oct 18, 2025
fd0328a
Apply pre-commit code formatting
pre-commit-ci-lite[bot] Oct 18, 2025
aceca07
conditional import
loechel Oct 18, 2025
3533c0f
fix coverage numbers
loechel Oct 18, 2025
e750331
readd Python 3.9 support
loechel Oct 18, 2025
44f9842
Merge branch 'master' into typing
dataflake Oct 19, 2025
5b8285c
- updating package files with zope/meta and fixing tests
dataflake Oct 19, 2025
ac53335
- fix last test
dataflake Oct 19, 2025
6ecdf5a
Merge branch 'master' into typing
dataflake Oct 20, 2025
0e1408c
- expand change log entry to be more clear.
dataflake Oct 20, 2025
1ce3ce1
Merge branch 'master' into typing
zedzhen May 13, 2026
652776e
Merge branch 'master' into typing
zedzhen Jun 2, 2026
0a292d3
fix return type
zedzhen Jun 2, 2026
444760e
style update (autopep8)
zedzhen Jun 2, 2026
0e92a0b
add type hints for RestrictingNodeTransformer attributes
zedzhen Jun 2, 2026
be5ad38
update type hints for RestrictingNodeTransformer methods
zedzhen Jun 2, 2026
37a4bec
update type hint for `policy` argument
zedzhen Jun 2, 2026
55985ad
add type hints for RestrictingNodeTransformer.visit_Interpolation
zedzhen Jun 2, 2026
99fd0be
update CHANGES.rst
zedzhen Jun 2, 2026
fd28e28
add types to CompileResult
zedzhen Jun 2, 2026
501299a
fix type hint for used_names
zedzhen Jun 2, 2026
b56ad85
add None to the return type hints
zedzhen Jun 2, 2026
2dd1fb5
add py.typed
zedzhen Jun 2, 2026
ea394dc
use "normal import"
zedzhen Jun 3, 2026
b1d1303
add list[ast.AST] to the return type hints
zedzhen Jun 3, 2026
23ec481
add config for mypy
zedzhen Jun 3, 2026
838d222
replace `compile(flags=ast.PyCF_ONLY_AST)` to `ast.parse`
zedzhen Jun 3, 2026
2913cb6
update type hints
zedzhen Jun 3, 2026
22ced90
add mypy check in pre-commit
zedzhen Jun 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ Changes
8.3 (unreleased)
----------------

- Nothing changed yet.
- Add type annotations to the package code.
For clarification, restricted Python code does not support type annotations.


8.3a1.dev0 (2026-05-29)
Expand Down
5 changes: 5 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ classifiers = [
"Programming Language :: Python :: 3.14",
"Programming Language :: Python :: Implementation :: CPython",
"Topic :: Security",
"Typing :: Typed",
]
dynamic = ["readme"]
requires-python = ">=3.10, <3.16"
Expand All @@ -50,6 +51,10 @@ docs = [
"Sphinx",
"furo",
]
typecheck = [
"mypy",
"typeshed",
]

[project.urls]
Comment thread
zedzhen marked this conversation as resolved.
Documentation = "https://restrictedpython.readthedocs.io/"
Expand Down
4 changes: 3 additions & 1 deletion src/RestrictedPython/Utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import math
import random
import string
from collections.abc import Iterable


utility_builtins = {}
Expand Down Expand Up @@ -75,7 +76,8 @@ def test(*args):
utility_builtins['test'] = test


def reorder(s, with_=None, without=()):
def reorder(s: Iterable, with_: Iterable | None = None,
without: Iterable = ()) -> Iterable:
# s, with_, and without are sequences treated as sets.
# The result is subtract(intersect(s, with_), without),
# unless with_ is None, in which case it is subtract(s, without).
Expand Down
104 changes: 66 additions & 38 deletions src/RestrictedPython/compile.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,35 @@
from __future__ import annotations

import ast
import warnings
from collections import namedtuple
from ast import Expression
from ast import Interactive
from ast import Module
from ast import NodeTransformer
from collections.abc import Mapping
from collections.abc import Sequence
from os import PathLike
from types import CodeType
from typing import Any
from typing import Literal
from typing import NamedTuple
from typing import TypeAlias
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not like these from imports, below in the code it is unclear where a name comes from, please stick to normal imports.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@icemac Is it allowed to use import typing as t?


from RestrictedPython._compat import IS_CPYTHON
from RestrictedPython.transformer import RestrictingNodeTransformer


CompileResult = namedtuple(
'CompileResult', 'code, errors, warnings, used_names')
# Temporary workaround for missing _typeshed
ReadableBuffer: TypeAlias = bytes | bytearray


class CompileResult(NamedTuple):
code: CodeType | None
errors: Sequence[str]
warnings: Sequence[str]
used_names: Mapping[str, bool]


syntax_error_template = (
'Line {lineno}: {type}: {msg} at statement: {statement!r}')

Expand All @@ -18,12 +40,13 @@


def _compile_restricted_mode(
source,
filename='<string>',
mode="exec",
flags=0,
dont_inherit=False,
policy=RestrictingNodeTransformer):
source: str | ReadableBuffer | Module | Expression | Interactive,
filename: str | ReadableBuffer | PathLike[Any] = '<string>',
mode: Literal["exec", "eval", "single"] = "exec",
flags: int = 0,
dont_inherit: bool = False,
policy: type[NodeTransformer] | None = RestrictingNodeTransformer,
) -> CompileResult:

if not IS_CPYTHON:
warnings.warn_explicit(
Expand All @@ -39,13 +62,13 @@ def _compile_restricted_mode(
dont_inherit=dont_inherit)
elif issubclass(policy, RestrictingNodeTransformer):
c_ast = None
allowed_source_types = [str, ast.Module]
allowed_source_types = [str, Module]
if not issubclass(type(source), tuple(allowed_source_types)):
raise TypeError('Not allowed source type: '
'"{0.__class__.__name__}".'.format(source))
c_ast = None
Comment thread
zedzhen marked this conversation as resolved.
Outdated
# workaround for pypy issue https://bitbucket.org/pypy/pypy/issues/2552
if isinstance(source, ast.Module):
if isinstance(source, Module):
c_ast = source
else:
try:
Expand Down Expand Up @@ -78,11 +101,12 @@ def _compile_restricted_mode(


def compile_restricted_exec(
source,
filename='<string>',
flags=0,
dont_inherit=False,
policy=RestrictingNodeTransformer):
source: str | ReadableBuffer | Module | Expression | Interactive,
filename: str | ReadableBuffer | PathLike[Any] = '<string>',
flags: int = 0,
dont_inherit: bool = False,
policy: type[NodeTransformer] | None = RestrictingNodeTransformer,
) -> CompileResult:
"""Compile restricted for the mode `exec`."""
return _compile_restricted_mode(
source,
Expand All @@ -94,11 +118,12 @@ def compile_restricted_exec(


def compile_restricted_eval(
source,
filename='<string>',
flags=0,
dont_inherit=False,
policy=RestrictingNodeTransformer):
source: str | ReadableBuffer | Module | Expression | Interactive,
filename: str | ReadableBuffer | PathLike[Any] = '<string>',
flags: int = 0,
dont_inherit: bool = False,
policy: type[NodeTransformer] | None = RestrictingNodeTransformer,
) -> CompileResult:
"""Compile restricted for the mode `eval`."""
return _compile_restricted_mode(
source,
Expand All @@ -110,11 +135,12 @@ def compile_restricted_eval(


def compile_restricted_single(
source,
filename='<string>',
flags=0,
dont_inherit=False,
policy=RestrictingNodeTransformer):
source: str | ReadableBuffer | Module | Expression | Interactive,
filename: str | ReadableBuffer | PathLike[Any] = '<string>',
flags: int = 0,
dont_inherit: bool = False,
policy: type[NodeTransformer] | None = RestrictingNodeTransformer,
) -> CompileResult:
"""Compile restricted for the mode `single`."""
return _compile_restricted_mode(
source,
Expand All @@ -128,12 +154,13 @@ def compile_restricted_single(
def compile_restricted_function(
p, # parameters
body,
name,
filename='<string>',
name: str,
filename: str | ReadableBuffer | PathLike[Any] = '<string>',
globalize=None, # List of globals (e.g. ['here', 'context', ...])
flags=0,
dont_inherit=False,
policy=RestrictingNodeTransformer):
flags: int = 0,
dont_inherit: bool = False,
policy: type[NodeTransformer] | None = RestrictingNodeTransformer,
) -> CompileResult:
"""Compile a restricted code object for a function.

Documentation see:
Expand All @@ -149,7 +176,7 @@ def compile_restricted_function(
msg=v.msg,
statement=v.text.strip() if v.text else None)
return CompileResult(
code=None, errors=(error,), warnings=(), used_names=())
code=None, errors=(error,), warnings=(), used_names={})

# The compiled code is actually executed inside a function
# (that is called when the code is called) so reading and assigning to a
Expand Down Expand Up @@ -181,12 +208,13 @@ def compile_restricted_function(


def compile_restricted(
source,
filename='<unknown>',
mode='exec',
flags=0,
dont_inherit=False,
policy=RestrictingNodeTransformer):
source: str | ReadableBuffer | Module | Expression | Interactive,
filename: str | ReadableBuffer | PathLike[Any] = '<unknown>',
mode: str = 'exec',
flags: int = 0,
dont_inherit: bool = False,
policy: type[NodeTransformer] | None = RestrictingNodeTransformer,
) -> CodeType:
Comment thread
zedzhen marked this conversation as resolved.
Outdated
"""Replacement for the built-in compile() function.

policy ... `ast.NodeTransformer` class defining the restrictions.
Expand Down
Empty file added src/RestrictedPython/py.typed
Empty file.
Loading
Loading