Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 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
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
1 change: 0 additions & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ jobs:
config:
# [Python version, tox env]
- ["3.11", "release-check"]
- ["3.9", "py39"]
- ["3.10", "py310"]
- ["3.11", "py311"]
- ["3.12", "py312"]
Expand Down
5 changes: 3 additions & 2 deletions .meta.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# https://github.com/zopefoundation/meta/tree/master/config/pure-python
[meta]
template = "pure-python"
commit-id = "72252845"
commit-id = "9d049229"

[python]
with-pypy = false
Expand All @@ -11,6 +11,7 @@ with-sphinx-doctests = true
with-windows = true
with-future-python = true
with-macos = false
oldest-python = "3.10"

[tox]
use-flake8 = true
Expand Down Expand Up @@ -47,7 +48,7 @@ testenv-additional = [
" coverage combine",
" coverage html",
" coverage report -m --fail-under=100",
"depends = py39,py310,py311,py311-datetime,py312,py313,py314,coverage",
"depends = py310,py311,py311-datetime,py312,py313,py314,coverage",
]
coverage-command = "pytest --cov=src --cov=tests --cov-report= tests {posargs}"
coverage-setenv = [
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ repos:
rev: v3.21.0
hooks:
- id: pyupgrade
args: [--py39-plus]
args: [--py310-plus]
- repo: https://github.com/isidentical/teyit
rev: 0.4.3
hooks:
Expand Down
4 changes: 3 additions & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ Changes
8.2 (unreleased)
----------------

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


8.1 (2025-10-19)
----------------
Expand Down
1 change: 0 additions & 1 deletion docs/contributing/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,6 @@ Technical Backgrounds - Links to External Documentation
* `Python 3.12 AST`_ (EOL 2028-10)
* `Python 3.11 AST`_ (EOL 2027-10)
* `Python 3.10 AST`_ (EOL 2026-10)
* `Python 3.9 AST`_ (EOL 2025-10)

* `AST NodeVistiors Class`_
* `AST NodeTransformer Class`_
Expand Down
7 changes: 5 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,20 @@ def read(*rnames):
'Programming Language :: Python',
'Operating System :: OS Independent',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12',
'Programming Language :: Python :: 3.13',
'Programming Language :: Python :: 3.14',
'Programming Language :: Python :: Implementation :: CPython',
'Topic :: Security',
'Typing :: Typed',
],
keywords='restricted execution security untrusted code',
author='Zope Foundation and Contributors',
author_email='zope-dev@zope.dev',
maintainer='Zope Foundation, Plone Foundation and Contributors',
maintainer_email='security@plone.org',
project_urls={
"Documentation": "https://restrictedpython.readthedocs.io/",
"Source": "https://github.com/zopefoundation/RestrictedPython",
Expand All @@ -60,9 +62,10 @@ def read(*rnames):
packages=find_packages('src'),
package_dir={'': 'src'},
install_requires=[],
python_requires=">=3.9, <3.15",
python_requires=">=3.10, <3.15",
extras_require={
'test': ['pytest', 'pytest-mock'],
'typecheck': ['mypy', 'typeshed'],
'docs': ['Sphinx', 'furo'],
},
include_package_data=True,
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
87 changes: 53 additions & 34 deletions src/RestrictedPython/compile.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,24 @@
from __future__ import annotations

import ast
import warnings
from ast import Expression
from ast import Interactive
from ast import Module
from ast import NodeTransformer
from collections import namedtuple
from os import PathLike
from typing import Any
from typing import Literal
from typing import TypeAlias

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


# Temporary workaround for missing _typeshed
ReadableBuffer: TypeAlias = bytes | bytearray

CompileResult = namedtuple(
'CompileResult', 'code, errors, warnings, used_names')
syntax_error_template = (
Expand All @@ -18,12 +31,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: NodeTransformer = RestrictingNodeTransformer,
) -> CompileResult:

if not IS_CPYTHON:
warnings.warn_explicit(
Expand All @@ -39,13 +53,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
# 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 +92,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: NodeTransformer = RestrictingNodeTransformer,
) -> CompileResult:
"""Compile restricted for the mode `exec`."""
return _compile_restricted_mode(
source,
Expand All @@ -94,11 +109,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: NodeTransformer = RestrictingNodeTransformer,
) -> CompileResult:
"""Compile restricted for the mode `eval`."""
return _compile_restricted_mode(
source,
Expand All @@ -110,11 +126,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: NodeTransformer = RestrictingNodeTransformer,
) -> CompileResult:
"""Compile restricted for the mode `single`."""
return _compile_restricted_mode(
source,
Expand All @@ -128,12 +145,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: ast.NodeTransformer = RestrictingNodeTransformer,
) -> CompileResult:
"""Compile a restricted code object for a function.

Documentation see:
Expand Down Expand Up @@ -181,12 +199,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: NodeTransformer = RestrictingNodeTransformer,
) -> CompileResult:
"""Replacement for the built-in compile() function.

policy ... `ast.NodeTransformer` class defining the restrictions.
Expand Down
Loading