From 69c2ca860dce3da054f66515663fb075223fe0fa Mon Sep 17 00:00:00 2001 From: Jens Vagelpohl Date: Tue, 8 Oct 2024 09:09:12 +0200 Subject: [PATCH 01/10] - support Python 3.13 --- .github/workflows/tests.yml | 3 +- .meta.toml | 2 +- CHANGES.rst | 3 +- docs/conf.py | 3 +- docs/contributing/ast/python3_13.ast | 194 +++++++++++++++++++++ docs/contributing/changes_from312to313.rst | 5 + docs/contributing/index.rst | 1 + setup.py | 1 + tox.ini | 6 +- 9 files changed, 209 insertions(+), 9 deletions(-) create mode 100644 docs/contributing/ast/python3_13.ast create mode 100644 docs/contributing/changes_from312to313.rst diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 4217b1b..8ffd275 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -29,7 +29,7 @@ jobs: - ["3.10", "py310"] - ["3.11", "py311"] - ["3.12", "py312"] - - ["3.13.0-alpha - 3.13.0", "py313"] + - ["3.13", "py313"] - ["3.9", "docs"] - ["3.9", "coverage"] - ["3.9", "py39-datetime"] @@ -48,6 +48,7 @@ jobs: uses: actions/setup-python@v4 with: python-version: ${{ matrix.config[0] }} + allow-prereleases: true - name: Pip cache uses: actions/cache@v3 with: diff --git a/.meta.toml b/.meta.toml index af696b7..677aaf9 100644 --- a/.meta.toml +++ b/.meta.toml @@ -47,7 +47,7 @@ testenv-additional = [ " coverage combine", " coverage html", " coverage report -m --fail-under=100", - "depends = py37,py38,py39,py39-datetime,py310,py311,py312,coverage", + "depends = py37,py38,py39,py39-datetime,py310,py311,py312,py313,coverage", ] coverage-basepython = "python3.8" coverage-command = "pytest --cov=src --cov=tests --cov-report= {posargs}" diff --git a/CHANGES.rst b/CHANGES.rst index 71274c6..bf78cd5 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,8 +4,7 @@ Changes 7.4 (unreleased) ---------------- -- Allow to use the package with Python 3.13 -- Caution: No security - audit has been done so far. +- Allow to use the package with Python 3.13. 7.3 (2024-09-30) diff --git a/docs/conf.py b/docs/conf.py index ec291c3..4a0c8e2 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -37,7 +37,7 @@ # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # source_suffix = ['.rst', '.md'] -source_suffix = '.rst' +source_suffix = {'.rst': 'restructuredtext'} # The encoding of source files. # source_encoding = 'utf-8-sig' @@ -113,6 +113,7 @@ 'python310': ('https://docs.python.org/3.10', None), 'python311': ('https://docs.python.org/3.11', None), 'python312': ('https://docs.python.org/3.12', None), + 'python313': ('https://docs.python.org/3.13', None), } # Options for sphinx.ext.todo: diff --git a/docs/contributing/ast/python3_13.ast b/docs/contributing/ast/python3_13.ast new file mode 100644 index 0000000..e23ee03 --- /dev/null +++ b/docs/contributing/ast/python3_13.ast @@ -0,0 +1,194 @@ +-- Python 3.13 AST +-- ASDL's 4 builtin types are: +-- identifier, int, string, constant + +module Python version "3.13" +{ + mod = Module(stmt* body, type_ignore* type_ignores) + | Interactive(stmt* body) + | Expression(expr body) + | FunctionType(expr* argtypes, expr returns) + + stmt = FunctionDef(identifier name, + arguments args, + stmt* body, + expr* decorator_list, + expr? returns, + string? type_comment, + type_param* type_params) + | AsyncFunctionDef(identifier name, + arguments args, + stmt* body, + expr* decorator_list, + expr? returns, + string? type_comment, + type_param* type_params) + + | ClassDef(identifier name, + expr* bases, + keyword* keywords, + stmt* body, + expr* decorator_list, + type_param* type_params) + | Return(expr? value) + + | Delete(expr* targets) + | Assign(expr* targets, expr value, string? type_comment) + | TypeAlias(expr name, type_param* type_params, expr value) + | AugAssign(expr target, operator op, expr value) + -- 'simple' indicates that we annotate simple name without parens + | AnnAssign(expr target, expr annotation, expr? value, int simple) + + -- use 'orelse' because else is a keyword in target languages + | For(expr target, expr iter, stmt* body, stmt* orelse, string? type_comment) + | AsyncFor(expr target, expr iter, stmt* body, stmt* orelse, string? type_comment) + | While(expr test, stmt* body, stmt* orelse) + | If(expr test, stmt* body, stmt* orelse) + | With(withitem* items, stmt* body, string? type_comment) + | AsyncWith(withitem* items, stmt* body, string? type_comment) + + | Match(expr subject, match_case* cases) + + | Raise(expr? exc, expr? cause) + | Try(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody) + | TryStar(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody) + | Assert(expr test, expr? msg) + + | Import(alias* names) + | ImportFrom(identifier? module, alias* names, int? level) + + | Global(identifier* names) + | Nonlocal(identifier* names) + | Expr(expr value) + | Pass + | Break + | Continue + + -- col_offset is the byte offset in the utf8 string the parser uses + attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset) + + -- BoolOp() can use left & right? + expr = BoolOp(boolop op, expr* values) + | NamedExpr(expr target, expr value) + | BinOp(expr left, operator op, expr right) + | UnaryOp(unaryop op, expr operand) + | Lambda(arguments args, expr body) + | IfExp(expr test, expr body, expr orelse) + | Dict(expr* keys, expr* values) + | Set(expr* elts) + | ListComp(expr elt, comprehension* generators) + | SetComp(expr elt, comprehension* generators) + | DictComp(expr key, expr value, comprehension* generators) + | GeneratorExp(expr elt, comprehension* generators) + -- the grammar constrains where yield expressions can occur + | Await(expr value) + | Yield(expr? value) + | YieldFrom(expr value) + -- need sequences for compare to distinguish between + -- x < 4 < 3 and (x < 4) < 3 + | Compare(expr left, cmpop* ops, expr* comparators) + | Call(expr func, expr* args, keyword* keywords) + | FormattedValue(expr value, int conversion, expr? format_spec) + | JoinedStr(expr* values) + | Constant(constant value, string? kind) + + -- the following expression can appear in assignment context + | Attribute(expr value, identifier attr, expr_context ctx) + | Subscript(expr value, expr slice, expr_context ctx) + | Starred(expr value, expr_context ctx) + | Name(identifier id, expr_context ctx) + | List(expr* elts, expr_context ctx) + | Tuple(expr* elts, expr_context ctx) + + -- can appear only in Subscript + | Slice(expr? lower, expr? upper, expr? step) + + -- col_offset is the byte offset in the utf8 string the parser uses + attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset) + + expr_context = Load + | Store + | Del + + boolop = And + | Or + + operator = Add + | Sub + | Mult + | MatMult + | Div + | Mod + | Pow + | LShift + | RShift + | BitOr + | BitXor + | BitAnd + | FloorDiv + + unaryop = Invert + | Not + | UAdd + | USub + + cmpop = Eq + | NotEq + | Lt + | LtE + | Gt + | GtE + | Is + | IsNot + | In + | NotIn + + comprehension = (expr target, expr iter, expr* ifs, int is_async) + + excepthandler = ExceptHandler(expr? type, identifier? name, stmt* body) + attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset) + + arguments = (arg* posonlyargs, + arg* args, + arg? vararg, + arg* kwonlyargs, + expr* kw_defaults, + arg? kwarg, + expr* defaults) + + arg = (identifier arg, expr? annotation, string? type_comment) + attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset) + + -- keyword arguments supplied to call (NULL identifier for **kwargs) + keyword = (identifier? arg, expr value) + attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset) + + -- import name with optional 'as' alias. + alias = (identifier name, identifier? asname) + attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset) + + withitem = (expr context_expr, expr? optional_vars) + + match_case = (pattern pattern, expr? guard, stmt* body) + + pattern = MatchValue(expr value) + | MatchSingleton(constant value) + | MatchSequence(pattern* patterns) + | MatchMapping(expr* keys, pattern* patterns, identifier? rest) + | MatchClass(expr cls, pattern* patterns, identifier* kwd_attrs, pattern* kwd_patterns) + + | MatchStar(identifier? name) + -- The optional "rest" MatchMapping parameter handles capturing extra mapping keys + + | MatchAs(pattern? pattern, identifier? name) + | MatchOr(pattern* patterns) + + attributes (int lineno, int col_offset, int end_lineno, int end_col_offset) + + type_ignore = TypeIgnore(int lineno, string tag) + + type_param = TypeVar(identifier name, expr? bound, expr? default_value) + | ParamSpec(identifier name, expr? default_value) + | TypeVarTuple(identifier name, expr? default_value) + attributes (int lineno, int col_offset, int end_lineno, int end_col_offset) +} diff --git a/docs/contributing/changes_from312to313.rst b/docs/contributing/changes_from312to313.rst new file mode 100644 index 0000000..412082a --- /dev/null +++ b/docs/contributing/changes_from312to313.rst @@ -0,0 +1,5 @@ +Changes from Python 3.12 to Python 3.13 +--------------------------------------- + +.. literalinclude:: ast/python3_13.ast + :diff: ast/python3_12.ast diff --git a/docs/contributing/index.rst b/docs/contributing/index.rst index f88dfa9..fa0e279 100644 --- a/docs/contributing/index.rst +++ b/docs/contributing/index.rst @@ -105,6 +105,7 @@ A (modified style) Copy of all Abstract Grammar Definitions for the Python versi changes_from39to310 changes_from310to311 changes_from311to312 + changes_from312to313 .. _understand: diff --git a/setup.py b/setup.py index 79f9bc3..4e639f5 100644 --- a/setup.py +++ b/setup.py @@ -50,6 +50,7 @@ def read(*rnames): 'Programming Language :: Python :: 3.10', 'Programming Language :: Python :: 3.11', 'Programming Language :: Python :: 3.12', + 'Programming Language :: Python :: 3.13', 'Programming Language :: Python :: Implementation :: CPython', 'Topic :: Security', ], diff --git a/tox.ini b/tox.ini index 0adda1e..1be12d0 100644 --- a/tox.ini +++ b/tox.ini @@ -21,7 +21,6 @@ envlist = usedevelop = true package = wheel wheel_build_env = .pkg -pip_pre = py313: true deps = datetime: DateTime -cconstraints.txt @@ -29,8 +28,6 @@ deps = Sphinx setenv = COVERAGE_FILE=.coverage.{envname} - py312: VIRTUALENV_PIP=23.1.2 - py312: PIP_REQUIRE_VIRTUALENV=0 commands = python -V pytest --cov=src --cov=tests --cov-report= {posargs} @@ -54,7 +51,8 @@ commands = coverage combine coverage html coverage report -m --fail-under=100 -depends = py37,py38,py39,py39-datetime,py310,py311,py312,coverage +depends = py37,py38,py39,py39-datetime,py310,py311,py312,py313,coverage + [testenv:release-check] description = ensure that the distribution is ready to release basepython = python3 From 162e7d4ad9f32dc9ec5630503f8aa4fb97a6a5b0 Mon Sep 17 00:00:00 2001 From: Jens Vagelpohl Date: Tue, 8 Oct 2024 09:26:41 +0200 Subject: [PATCH 02/10] - update to latest meta/config template and drop Python 3.7 support. --- .github/workflows/pre-commit.yml | 33 +++++ .github/workflows/tests.yml | 41 +++--- .meta.toml | 10 +- .pre-commit-config.yaml | 28 ++++ CHANGES.rst | 2 + MANIFEST.in | 1 + docs/conf.py | 8 +- docs/contributing/ast/python3_6.ast | 175 ----------------------- docs/contributing/changes_from36to37.rst | 5 - docs/contributing/index.rst | 1 - pyproject.toml | 21 +++ setup.cfg | 2 - tox.ini | 59 +++----- 13 files changed, 136 insertions(+), 250 deletions(-) create mode 100644 .github/workflows/pre-commit.yml create mode 100644 .pre-commit-config.yaml delete mode 100755 docs/contributing/ast/python3_6.ast delete mode 100644 docs/contributing/changes_from36to37.rst create mode 100644 pyproject.toml diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml new file mode 100644 index 0000000..0f06e16 --- /dev/null +++ b/.github/workflows/pre-commit.yml @@ -0,0 +1,33 @@ +# Generated from: +# https://github.com/zopefoundation/meta/tree/master/config/pure-python +name: pre-commit + +on: + pull_request: + push: + branches: + - master + # Allow to run this workflow manually from the Actions tab + workflow_dispatch: + +env: + FORCE_COLOR: 1 + +jobs: + pre-commit: + name: linting + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: 3.x + - uses: pre-commit/action@v3.0.1 + with: + extra_args: --all-files --show-diff-on-failure + env: + PRE_COMMIT_COLOR: always + - uses: pre-commit-ci/lite-action@v1.0.2 + if: always() + with: + msg: Apply pre-commit code formatting diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 8ffd275..6f69029 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -17,40 +17,37 @@ jobs: fail-fast: false matrix: os: - - ["ubuntu", "ubuntu-20.04"] + - ["ubuntu", "ubuntu-latest"] - ["windows", "windows-latest"] config: # [Python version, tox env] - - ["3.9", "release-check"] - - ["3.9", "lint"] - - ["3.7", "py37"] - - ["3.8", "py38"] - - ["3.9", "py39"] - - ["3.10", "py310"] - - ["3.11", "py311"] - - ["3.12", "py312"] - - ["3.13", "py313"] - - ["3.9", "docs"] - - ["3.9", "coverage"] - - ["3.9", "py39-datetime"] + - ["3.11", "release-check"] + - ["3.8", "py38"] + - ["3.9", "py39"] + - ["3.10", "py310"] + - ["3.11", "py311"] + - ["3.12", "py312"] + - ["3.13", "py313"] + - ["3.11", "docs"] + - ["3.11", "coverage"] + - ["3.11", "py311-datetime"] exclude: - - { os: ["windows", "windows-latest"], config: ["3.9", "release-check"] } - - { os: ["windows", "windows-latest"], config: ["3.9", "lint"] } - - { os: ["windows", "windows-latest"], config: ["3.9", "docs"] } - - { os: ["windows", "windows-latest"], config: ["3.9", "coverage"] } + - { os: ["windows", "windows-latest"], config: ["3.11", "release-check"] } + - { os: ["windows", "windows-latest"], config: ["3.11", "docs"] } + - { os: ["windows", "windows-latest"], config: ["3.11", "coverage"] } runs-on: ${{ matrix.os[1] }} if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name name: ${{ matrix.os[0] }}-${{ matrix.config[1] }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.config[0] }} allow-prereleases: true - name: Pip cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ matrix.config[0] }}-${{ hashFiles('setup.*', 'tox.ini') }} @@ -62,7 +59,11 @@ jobs: python -m pip install --upgrade pip pip install tox - name: Test + if: ${{ !startsWith(runner.os, 'Mac') }} run: tox -e ${{ matrix.config[1] }} + - name: Test (macOS) + if: ${{ startsWith(runner.os, 'Mac') }} + run: tox -e ${{ matrix.config[1] }}-universal2 - name: Coverage if: matrix.config[1] == 'coverage' run: | diff --git a/.meta.toml b/.meta.toml index 677aaf9..4018329 100644 --- a/.meta.toml +++ b/.meta.toml @@ -2,20 +2,20 @@ # https://github.com/zopefoundation/meta/tree/master/config/pure-python [meta] template = "pure-python" -commit-id = "cb0568c7" +commit-id = "d3455844" [python] with-pypy = false with-docs = true with-sphinx-doctests = true with-windows = true -with-future-python = true +with-future-python = false with-macos = false [tox] use-flake8 = true additional-envlist = [ - "py39-datetime", + "py311-datetime", "combined-coverage", ] testenv-deps = [ @@ -47,7 +47,7 @@ testenv-additional = [ " coverage combine", " coverage html", " coverage report -m --fail-under=100", - "depends = py37,py38,py39,py39-datetime,py310,py311,py312,py313,coverage", + "depends = py38,py39,py310,py311,py311-datetime,py312,py313,coverage", ] coverage-basepython = "python3.8" coverage-command = "pytest --cov=src --cov=tests --cov-report= {posargs}" @@ -86,5 +86,5 @@ additional-ignores = [ [github-actions] additional-config = [ - "- [\"3.9\", \"py39-datetime\"]", + "- [\"3.11\", \"py311-datetime\"]", ] diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..7ab398c --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,28 @@ +# Generated from: +# https://github.com/zopefoundation/meta/tree/master/config/pure-python +minimum_pre_commit_version: '3.6' +repos: + - repo: https://github.com/pycqa/isort + rev: "5.13.2" + hooks: + - id: isort + - repo: https://github.com/hhatto/autopep8 + rev: "v2.3.1" + hooks: + - id: autopep8 + args: [--in-place, --aggressive, --aggressive] + - repo: https://github.com/asottile/pyupgrade + rev: v3.17.0 + hooks: + - id: pyupgrade + args: [--py38-plus] + - repo: https://github.com/isidentical/teyit + rev: 0.4.3 + hooks: + - id: teyit + - repo: https://github.com/PyCQA/flake8 + rev: "7.1.1" + hooks: + - id: flake8 + additional_dependencies: + - flake8-debugger == 4.1.2 diff --git a/CHANGES.rst b/CHANGES.rst index bf78cd5..ca3e6af 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -6,6 +6,8 @@ Changes - Allow to use the package with Python 3.13. +- Drop support for Python 3.7. + 7.3 (2024-09-30) ---------------- diff --git a/MANIFEST.in b/MANIFEST.in index 3c482de..7f0aa88 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -5,6 +5,7 @@ include *.rst include *.txt include buildout.cfg include tox.ini +include .pre-commit-config.yaml recursive-include docs *.py recursive-include docs *.rst diff --git a/docs/conf.py b/docs/conf.py index 4a0c8e2..747e25c 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -107,7 +107,6 @@ # Intersphinx Mapping for Links between different Documentations intersphinx_mapping = { 'python3': ('https://docs.python.org/3', None), - 'python37': ('https://docs.python.org/3.7', None), 'python38': ('https://docs.python.org/3.8', None), 'python39': ('https://docs.python.org/3.9', None), 'python310': ('https://docs.python.org/3.10', None), @@ -275,8 +274,11 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - (master_doc, 'restrictedpython', 'RestrictedPython Documentation', [author], 1) -] + (master_doc, + 'restrictedpython', + 'RestrictedPython Documentation', + [author], + 1)] # If true, show URL addresses after external links. # man_show_urls = False diff --git a/docs/contributing/ast/python3_6.ast b/docs/contributing/ast/python3_6.ast deleted file mode 100755 index 8c87864..0000000 --- a/docs/contributing/ast/python3_6.ast +++ /dev/null @@ -1,175 +0,0 @@ --- Python 3.6 AST --- ASDL's 7 builtin types are: --- identifier, int, string, bytes, object, singleton, constant --- --- singleton: None, True or False --- constant can be None, whereas None means "no value" for object. - -module Python version "3.6" -{ - mod = Module(stmt* body) - | Interactive(stmt* body) - | Expression(expr body) - - -- not really an actual node but useful in Jython's typesystem. - | Suite(stmt* body) - - stmt = FunctionDef(identifier name, - arguments args, - stmt* body, - expr* decorator_list, - expr? returns) - | AsyncFunctionDef(identifier name, - arguments args, - stmt* body, - expr* decorator_list, - expr? returns) - - | ClassDef(identifier name, - expr* bases, - keyword* keywords, - stmt* body, - expr* decorator_list) - | Return(expr? value) - - | Delete(expr* targets) - | Assign(expr* targets, expr value) - | AugAssign(expr target, operator op, expr value) - -- 'simple' indicates that we annotate simple name without parens - | AnnAssign(expr target, expr annotation, expr? value, int simple) - - -- use 'orelse' because else is a keyword in target languages - | For(expr target, expr iter, stmt* body, stmt* orelse) - | AsyncFor(expr target, expr iter, stmt* body, stmt* orelse) - | While(expr test, stmt* body, stmt* orelse) - | If(expr test, stmt* body, stmt* orelse) - | With(withitem* items, stmt* body) - | AsyncWith(withitem* items, stmt* body) - - | Raise(expr? exc, expr? cause) - | Try(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody) - | Assert(expr test, expr? msg) - - | Import(alias* names) - | ImportFrom(identifier? module, alias* names, int? level) - - | Global(identifier* names) - | Nonlocal(identifier* names) - | Expr(expr value) - | Pass - | Break - | Continue - - -- XXX Jython will be different - -- col_offset is the byte offset in the utf8 string the parser uses - attributes (int lineno, int col_offset) - - -- BoolOp() can use left & right? - expr = BoolOp(boolop op, expr* values) - | BinOp(expr left, operator op, expr right) - | UnaryOp(unaryop op, expr operand) - | Lambda(arguments args, expr body) - | IfExp(expr test, expr body, expr orelse) - | Dict(expr* keys, expr* values) - | Set(expr* elts) - | ListComp(expr elt, comprehension* generators) - | SetComp(expr elt, comprehension* generators) - | DictComp(expr key, expr value, comprehension* generators) - | GeneratorExp(expr elt, comprehension* generators) - -- the grammar constrains where yield expressions can occur - | Await(expr value) - | Yield(expr? value) - | YieldFrom(expr value) - -- need sequences for compare to distinguish between - -- x < 4 < 3 and (x < 4) < 3 - | Compare(expr left, cmpop* ops, expr* comparators) - | Call(expr func, - expr* args, - keyword* keywords) - | Num(object n) -- a number as a PyObject. - | Str(string s) -- need to specify raw, unicode, etc? - | FormattedValue(expr value, int? conversion, expr? format_spec) - | JoinedStr(expr* values) - | Bytes(bytes s) - | NameConstant(singleton value) - | Ellipsis - | Constant(constant value) - - -- the following expression can appear in assignment context - | Attribute(expr value, identifier attr, expr_context ctx) - | Subscript(expr value, slice slice, expr_context ctx) - | Starred(expr value, expr_context ctx) - | Name(identifier id, expr_context ctx) - | List(expr* elts, expr_context ctx) - | Tuple(expr* elts, expr_context ctx) - - -- col_offset is the byte offset in the utf8 string the parser uses - attributes (int lineno, int col_offset) - - expr_context = Load - | Store - | Del - | AugLoad - | AugStore - | Param - - slice = Slice(expr? lower, expr? upper, expr? step) - | ExtSlice(slice* dims) - | Index(expr value) - - boolop = And - | Or - - operator = Add - | Sub - | Mult - | MatMult - | Div - | Mod - | Pow - | LShift - | RShift - | BitOr - | BitXor - | BitAnd - | FloorDiv - - unaryop = Invert - | Not - | UAdd - | USub - - cmpop = Eq - | NotEq - | Lt - | LtE - | Gt - | GtE - | Is - | IsNot - | In - | NotIn - - comprehension = (expr target, expr iter, expr* ifs, int is_async) - - excepthandler = ExceptHandler(expr? type, identifier? name, stmt* body) - attributes (int lineno, int col_offset) - - arguments = (arg* args, - arg? vararg, - arg* kwonlyargs, - expr* kw_defaults, - arg? kwarg, - expr* defaults) - - arg = (identifier arg, expr? annotation) - attributes (int lineno, int col_offset) - - -- keyword arguments supplied to call (NULL identifier for **kwargs) - keyword = (identifier? arg, expr value) - - -- import name with optional 'as' alias. - alias = (identifier name, identifier? asname) - - withitem = (expr context_expr, expr? optional_vars) -} diff --git a/docs/contributing/changes_from36to37.rst b/docs/contributing/changes_from36to37.rst deleted file mode 100644 index 42160bf..0000000 --- a/docs/contributing/changes_from36to37.rst +++ /dev/null @@ -1,5 +0,0 @@ -Changes from Python 3.6 to Python 3.7 -------------------------------------- - -.. literalinclude:: ast/python3_7.ast - :diff: ast/python3_6.ast diff --git a/docs/contributing/index.rst b/docs/contributing/index.rst index fa0e279..a0fd859 100644 --- a/docs/contributing/index.rst +++ b/docs/contributing/index.rst @@ -99,7 +99,6 @@ A (modified style) Copy of all Abstract Grammar Definitions for the Python versi .. toctree:: :maxdepth: 2 - changes_from36to37 changes_from37to38 changes_from38to39 changes_from39to310 diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..1509743 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,21 @@ +# +# Generated from: +# https://github.com/zopefoundation/meta/tree/master/config/pure-python + +[build-system] +requires = ["setuptools<74"] +build-backend = "setuptools.build_meta" + +[tool.coverage.run] +branch = true +source = ["RestrictedPython"] + +[tool.coverage.report] +fail_under = 98.4 +precision = 2 +ignore_errors = true +show_missing = true +exclude_lines = ["pragma: no cover", "pragma: nocover", "except ImportError:", "raise NotImplementedError", "if __name__ == '__main__':", "self.fail", "raise AssertionError", "raise unittest.Skip"] + +[tool.coverage.html] +directory = "parts/htmlcov" diff --git a/setup.cfg b/setup.cfg index c0470e3..cb939e5 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,7 +1,5 @@ # Generated from: # https://github.com/zopefoundation/meta/tree/master/config/pure-python -[bdist_wheel] -universal = 0 [flake8] doctests = 1 diff --git a/tox.ini b/tox.ini index 1be12d0..5cc78a4 100644 --- a/tox.ini +++ b/tox.ini @@ -5,7 +5,6 @@ minversion = 3.18 envlist = release-check lint - py37 py38 py39 py310 @@ -14,7 +13,7 @@ envlist = py313 docs coverage - py39-datetime + py311-datetime combined-coverage [testenv] @@ -22,10 +21,10 @@ usedevelop = true package = wheel wheel_build_env = .pkg deps = + setuptools <74 datetime: DateTime -cconstraints.txt pytest-cov - Sphinx setenv = COVERAGE_FILE=.coverage.{envname} commands = @@ -51,42 +50,43 @@ commands = coverage combine coverage html coverage report -m --fail-under=100 -depends = py37,py38,py39,py39-datetime,py310,py311,py312,py313,coverage +depends = py38,py39,py310,py311,py311-datetime,py312,py313,coverage + +[testenv:setuptools-latest] +basepython = python3 +deps = + git+https://github.com/pypa/setuptools.git\#egg=setuptools + datetime: DateTime + -cconstraints.txt + pytest-cov [testenv:release-check] description = ensure that the distribution is ready to release basepython = python3 skip_install = true deps = + setuptools <74 twine build check-manifest check-python-versions >= 0.20.0 wheel +commands_pre = commands = check-manifest - check-python-versions + check-python-versions --only setup.py,tox.ini,.github/workflows/tests.yml python -m build --sdist --no-isolation twine check dist/* [testenv:lint] +description = This env runs all linters configured in .pre-commit-config.yaml basepython = python3 skip_install = true deps = - isort - flake8 -commands = - isort --check-only --diff {toxinidir}/src {toxinidir}/setup.py {toxinidir}/tests - flake8 src setup.py tests - -[testenv:isort-apply] -basepython = python3 -skip_install = true + pre-commit commands_pre = -deps = - isort commands = - isort {toxinidir}/src {toxinidir}/setup.py {toxinidir}/tests [] + pre-commit run --all-files --show-diff-on-failure [testenv:docs] basepython = python3 @@ -101,34 +101,15 @@ basepython = python3.8 allowlist_externals = mkdir deps = - coverage + coverage[toml] datetime: DateTime -cconstraints.txt pytest-cov - Sphinx setenv = COVERAGE_FILE=.coverage commands = mkdir -p {toxinidir}/parts/htmlcov pytest --cov=src --cov=tests --cov-report= {posargs} coverage run -a -m sphinx -b doctest -d {envdir}/.cache/doctrees docs {envdir}/.cache/doctest - coverage html --ignore-errors - coverage report --ignore-errors --show-missing --fail-under=98.4 - -[coverage:run] -branch = True -source = RestrictedPython - -[coverage:report] -precision = 2 -exclude_lines = - pragma: no cover - pragma: nocover - except ImportError: - raise NotImplementedError - if __name__ == '__main__': - self.fail - raise AssertionError - -[coverage:html] -directory = parts/htmlcov + coverage html + coverage report From d237c27d29cb645f2b598aebd37a191d9d21a6dc Mon Sep 17 00:00:00 2001 From: Jens Vagelpohl Date: Tue, 8 Oct 2024 09:30:20 +0200 Subject: [PATCH 03/10] - adjust coverage --- .meta.toml | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.meta.toml b/.meta.toml index 4018329..cb844a9 100644 --- a/.meta.toml +++ b/.meta.toml @@ -56,7 +56,7 @@ coverage-setenv = [ ] [coverage] -fail-under = 98.4 +fail-under = 97 [isort] additional-sources = "{toxinidir}/tests" diff --git a/pyproject.toml b/pyproject.toml index 1509743..fe3e43c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,7 +11,7 @@ branch = true source = ["RestrictedPython"] [tool.coverage.report] -fail_under = 98.4 +fail_under = 97 precision = 2 ignore_errors = true show_missing = true From 8eb19b65f729d7a945db41f543b995c219c2624f Mon Sep 17 00:00:00 2001 From: Jens Vagelpohl Date: Tue, 8 Oct 2024 09:33:51 +0200 Subject: [PATCH 04/10] - fix outdated Python version for tox coverage test --- .meta.toml | 1 - tox.ini | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.meta.toml b/.meta.toml index cb844a9..5c9a95d 100644 --- a/.meta.toml +++ b/.meta.toml @@ -49,7 +49,6 @@ testenv-additional = [ " coverage report -m --fail-under=100", "depends = py38,py39,py310,py311,py311-datetime,py312,py313,coverage", ] -coverage-basepython = "python3.8" coverage-command = "pytest --cov=src --cov=tests --cov-report= {posargs}" coverage-setenv = [ "COVERAGE_FILE=.coverage", diff --git a/tox.ini b/tox.ini index 5cc78a4..9c60b53 100644 --- a/tox.ini +++ b/tox.ini @@ -97,7 +97,7 @@ commands = sphinx-build -b doctest -d docs/_build/doctrees docs docs/_build/doctest [testenv:coverage] -basepython = python3.8 +basepython = python3 allowlist_externals = mkdir deps = From de4209061c486683a58b1b27b1400c59e27a9545 Mon Sep 17 00:00:00 2001 From: Jens Vagelpohl Date: Tue, 8 Oct 2024 14:09:22 +0200 Subject: [PATCH 05/10] - specify tests path for pytest so the tests run locally --- .meta.toml | 6 +++--- tox.ini | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.meta.toml b/.meta.toml index 5c9a95d..01c1a49 100644 --- a/.meta.toml +++ b/.meta.toml @@ -28,7 +28,7 @@ testenv-setenv = [ ] testenv-commands = [ "python -V", - "pytest --cov=src --cov=tests --cov-report= {posargs}", + "pytest --cov=src --cov=tests --cov-report= tests {posargs}", ] testenv-additional = [ "", @@ -49,13 +49,13 @@ testenv-additional = [ " coverage report -m --fail-under=100", "depends = py38,py39,py310,py311,py311-datetime,py312,py313,coverage", ] -coverage-command = "pytest --cov=src --cov=tests --cov-report= {posargs}" +coverage-command = "pytest --cov=src --cov=tests --cov-report= tests {posargs}" coverage-setenv = [ "COVERAGE_FILE=.coverage", ] [coverage] -fail-under = 97 +fail-under = 97.9 [isort] additional-sources = "{toxinidir}/tests" diff --git a/tox.ini b/tox.ini index 9c60b53..171abb2 100644 --- a/tox.ini +++ b/tox.ini @@ -29,7 +29,7 @@ setenv = COVERAGE_FILE=.coverage.{envname} commands = python -V - pytest --cov=src --cov=tests --cov-report= {posargs} + pytest --cov=src --cov=tests --cov-report= tests {posargs} sphinx-build -b doctest -d {envdir}/.cache/doctrees docs {envdir}/.cache/doctest extras = test @@ -109,7 +109,7 @@ setenv = COVERAGE_FILE=.coverage commands = mkdir -p {toxinidir}/parts/htmlcov - pytest --cov=src --cov=tests --cov-report= {posargs} + pytest --cov=src --cov=tests --cov-report= tests {posargs} coverage run -a -m sphinx -b doctest -d {envdir}/.cache/doctrees docs {envdir}/.cache/doctest coverage html coverage report From fd11a24dd4abce3af87fa92c189cdb0c812dca89 Mon Sep 17 00:00:00 2001 From: Jens Vagelpohl Date: Tue, 8 Oct 2024 14:09:30 +0200 Subject: [PATCH 06/10] - remove all pre-Python 38 compatibility code --- pyproject.toml | 2 +- src/RestrictedPython/_compat.py | 1 - src/RestrictedPython/transformer.py | 108 +++++-------------- tests/test_NamedExpr.py | 3 - tests/test_compile.py | 5 +- tests/test_compile_restricted_function.py | 7 +- tests/transformer/test_dict_comprehension.py | 21 ++-- tests/transformer/test_fstring.py | 7 -- 8 files changed, 36 insertions(+), 118 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index fe3e43c..75267ab 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -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 diff --git a/src/RestrictedPython/_compat.py b/src/RestrictedPython/_compat.py index 56fe03d..2d85cc4 100644 --- a/src/RestrictedPython/_compat.py +++ b/src/RestrictedPython/_compat.py @@ -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 diff --git a/src/RestrictedPython/transformer.py b/src/RestrictedPython/transformer.py index 9a205cc..2034205 100644 --- a/src/RestrictedPython/transformer.py +++ b/src/RestrictedPython/transformer.py @@ -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 = { @@ -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) @@ -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. @@ -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 @@ -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) @@ -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.""" @@ -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) @@ -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 ], diff --git a/tests/test_NamedExpr.py b/tests/test_NamedExpr.py index 308d0dd..2da22ad 100644 --- a/tests/test_NamedExpr.py +++ b/tests/test_NamedExpr.py @@ -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") diff --git a/tests/test_compile.py b/tests/test_compile.py index 603ad84..c4ea7de 100644 --- a/tests/test_compile.py +++ b/tests/test_compile.py @@ -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 @@ -43,10 +42,8 @@ def test_compile__invalid_syntax(): compile_restricted(INVALID_ASSINGMENT, '', '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(): diff --git a/tests/test_compile_restricted_function.py b/tests/test_compile_restricted_function.py index d5b89b3..0bf0437 100644 --- a/tests/test_compile_restricted_function.py +++ b/tests/test_compile_restricted_function.py @@ -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 @@ -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:" ) diff --git a/tests/transformer/test_dict_comprehension.py b/tests/transformer/test_dict_comprehension.py index 17b8c45..ccc5ce0 100644 --- a/tests/transformer/test_dict_comprehension.py +++ b/tests/transformer/test_dict_comprehension.py @@ -1,4 +1,3 @@ -from RestrictedPython._compat import IS_PY38_OR_GREATER from tests.helper import restricted_exec @@ -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) diff --git a/tests/transformer/test_fstring.py b/tests/transformer/test_fstring.py index 68b1743..2b31c83 100644 --- a/tests/transformer/test_fstring.py +++ b/tests/transformer/test_fstring.py @@ -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 @@ -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( From 0519ef842dae9e1683b0bc3f0782f0a093201530 Mon Sep 17 00:00:00 2001 From: Jens Vagelpohl Date: Wed, 9 Oct 2024 07:18:31 +0200 Subject: [PATCH 07/10] - remove Python3.7 declaration --- setup.py | 1 - 1 file changed, 1 deletion(-) diff --git a/setup.py b/setup.py index 4e639f5..0c91748 100644 --- a/setup.py +++ b/setup.py @@ -44,7 +44,6 @@ def read(*rnames): 'Programming Language :: Python', 'Operating System :: OS Independent', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', From 962204862ff0264d273bf4e1031f5ac160ba4637 Mon Sep 17 00:00:00 2001 From: Jens Vagelpohl Date: Wed, 9 Oct 2024 07:59:48 +0200 Subject: [PATCH 08/10] - fix python_requires --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 0c91748..fa258a4 100644 --- a/setup.py +++ b/setup.py @@ -65,7 +65,7 @@ def read(*rnames): packages=find_packages('src'), package_dir={'': 'src'}, install_requires=[], - python_requires=">=3.7, <3.14", + python_requires=">=3.8, <3.14", extras_require={ 'test': tests_require, 'docs': ['Sphinx', 'sphinx_rtd_theme'], From 89a76f093bfbb3996ad8e8e6a5af92ae083969f7 Mon Sep 17 00:00:00 2001 From: Jens Vagelpohl Date: Wed, 9 Oct 2024 09:23:54 +0200 Subject: [PATCH 09/10] - use furo Sphinx theme and clean up some obsolete docs and settings --- .meta.toml | 1 + docs/conf.py | 13 +++++++++---- docs/contributing/index.rst | 1 - docs/index.rst | 2 -- docs/requirements.txt | 1 + docs/upgrade_dependencies/index.rst | 30 ----------------------------- setup.cfg | 1 + setup.py | 11 +++-------- 8 files changed, 15 insertions(+), 45 deletions(-) delete mode 100644 docs/upgrade_dependencies/index.rst diff --git a/.meta.toml b/.meta.toml index 01c1a49..9814f9a 100644 --- a/.meta.toml +++ b/.meta.toml @@ -81,6 +81,7 @@ additional-ignores = [ "docs/_build/html/_sources/roadmap/*", "docs/_build/html/_sources/upgrade_dependencies/*", "docs/_build/html/_sources/usage/*", + "docs/_build/html/_static/scripts/*", ] [github-actions] diff --git a/docs/conf.py b/docs/conf.py index 747e25c..3ea6a2c 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -16,8 +16,13 @@ # documentation root, use os.path.abspath to make it absolute, like shown here. # sys.path.insert(0, os.path.abspath('.')) +import datetime + + # -- General configuration ------------------------------------------------ +year = datetime.datetime.now().year + # If your documentation needs a minimal Sphinx version, state it here. # needs_sphinx = '1.0' @@ -47,7 +52,7 @@ # General information about the project. project = 'RestrictedPython' -copyright = '2017-2023, Zope Foundation and Contributors' +copyright = f'2017-{year}, Zope Foundation and Contributors' author = 'The Zope & Plone developer community' # The version info for the project you're documenting, acts as replacement for @@ -55,9 +60,9 @@ # built documents. # # The short X.Y version. -version = '7.0' +version = '7.4' # The full version, including alpha/beta/rc tags. -release = '7.0' +release = '7.4' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -123,7 +128,7 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = 'default' +html_theme = 'furo' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the diff --git a/docs/contributing/index.rst b/docs/contributing/index.rst index a0fd859..c9eef77 100644 --- a/docs/contributing/index.rst +++ b/docs/contributing/index.rst @@ -1,7 +1,6 @@ Contributing ============ -.. contents:: Contributing to RestrictedPython -------------------------------- diff --git a/docs/index.rst b/docs/index.rst index e840f5d..7e77a28 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -29,8 +29,6 @@ Contents usage/index usage/api - upgrade_dependencies/index - roadmap/index contributing/index diff --git a/docs/requirements.txt b/docs/requirements.txt index 2806c16..de8fca9 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1 +1,2 @@ Sphinx +furo diff --git a/docs/upgrade_dependencies/index.rst b/docs/upgrade_dependencies/index.rst deleted file mode 100644 index 4d295d1..0000000 --- a/docs/upgrade_dependencies/index.rst +++ /dev/null @@ -1,30 +0,0 @@ -Upgrade from 3.x ----------------- - -For packages that use RestrictedPython the upgrade path differs on the actual usage. -If it uses pure RestrictedPython without any additional checks it should be enough to check the imports. -RestrictedPython did move some of the imports to the base namespace, so you should only import directly from ``RestrictedPython``. - -* compile_restricted methods: - - * ``from RestrictedPython import compile_restricted`` - * ``from RestrictedPython import compile_restricted_eval`` - * ``from RestrictedPython import compile_restricted_exec`` - * ``from RestrictedPython import compile_restricted_function`` - * ``from RestrictedPython import compile_restricted_single`` - -* predefined built-ins: - - * ``from RestrictedPython import safe_globals`` - * ``from RestrictedPython import safe_builtins`` - * ``from RestrictedPython import limited_builtins`` - * ``from RestrictedPython import utility_builtins`` - -* helper methods: - - * ``from RestrictedPython import PrintCollector`` - -Any import from ``RestrictedPython.RCompile`` indicates that there have been advanced checks implemented. -Those advanced checks where implemented via a ``MutatingWalker``. -Any checks needs to be reimplemented as a subclass of -``RestrictingNodeTransformer``. diff --git a/setup.cfg b/setup.cfg index cb939e5..ae12100 100644 --- a/setup.cfg +++ b/setup.cfg @@ -17,6 +17,7 @@ ignore = docs/_build/html/_sources/roadmap/* docs/_build/html/_sources/upgrade_dependencies/* docs/_build/html/_sources/usage/* + docs/_build/html/_static/scripts/* [isort] force_single_line = True diff --git a/setup.py b/setup.py index fa258a4..fb92b3d 100644 --- a/setup.py +++ b/setup.py @@ -24,11 +24,6 @@ def read(*rnames): return f.read() -tests_require = [ - 'pytest', - 'pytest-mock', -] - setup(name='RestrictedPython', version='7.4.dev0', url='https://github.com/zopefoundation/RestrictedPython', @@ -55,7 +50,7 @@ def read(*rnames): ], keywords='restricted execution security untrusted code', author='Zope Foundation and Contributors', - author_email='zope-dev@zope.org', + author_email='zope-dev@zope.dev', project_urls={ "Documentation": "https://restrictedpython.readthedocs.io/", "Source": "https://github.com/zopefoundation/RestrictedPython", @@ -67,8 +62,8 @@ def read(*rnames): install_requires=[], python_requires=">=3.8, <3.14", extras_require={ - 'test': tests_require, - 'docs': ['Sphinx', 'sphinx_rtd_theme'], + 'test': ['pytest', 'pytest-mock'], + 'docs': ['Sphinx', 'furo'], }, include_package_data=True, zip_safe=False) From 49385234b93c365b043c1a8e928b6aefd91f50c1 Mon Sep 17 00:00:00 2001 From: Jens Vagelpohl Date: Wed, 9 Oct 2024 16:33:41 +0000 Subject: [PATCH 10/10] Update tests/transformer/test_dict_comprehension.py Co-authored-by: Michael Howitz --- tests/transformer/test_dict_comprehension.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/transformer/test_dict_comprehension.py b/tests/transformer/test_dict_comprehension.py index ccc5ce0..c573510 100644 --- a/tests/transformer/test_dict_comprehension.py +++ b/tests/transformer/test_dict_comprehension.py @@ -27,7 +27,6 @@ def test_dict_comprehension_with_attrs(mocker): calls = [mocker.call(seq, 'z')] - # Note: Order changed in PEP 572, starting with Python 3.8. calls.extend([ mocker.call(z[0], 'k'), mocker.call(z[1], 'k'),