From bd2c6282a78954d996ecd989f774b18f6e5c4960 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ionel=20Cristian=20M=C4=83rie=C8=99?= Date: Wed, 13 Dec 2023 18:17:28 +0200 Subject: [PATCH 01/33] Update project skel. Drop python 3.7 and add 3.12. --- .bumpversion.cfg | 4 + .cookiecutterrc | 16 +- .github/workflows/github-actions.yml | 307 ++++++++++-------- .gitignore | 58 ++-- .pre-commit-config.yaml | 32 +- .readthedocs.yml | 4 + CONTRIBUTING.rst | 4 +- README.rst | 12 +- ci/bootstrap.py | 78 ++--- .../.github/workflows/github-actions.yml | 42 ++- docs/conf.py | 7 +- pyproject.toml | 54 ++- setup.cfg | 11 - setup.py | 64 ++-- tox.ini | 36 +- 15 files changed, 389 insertions(+), 340 deletions(-) delete mode 100644 setup.cfg diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 486b44f..cde88f5 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -22,3 +22,7 @@ replace = version = release = '{new_version}' [bumpversion:file:src/lazy_object_proxy/__init__.py] search = __version__ = '{current_version}' replace = __version__ = '{new_version}' + +[bumpversion:file:.cookiecutterrc] +search = version: {current_version} +replace = version: {new_version} diff --git a/.cookiecutterrc b/.cookiecutterrc index 4e39e27..c85b08b 100644 --- a/.cookiecutterrc +++ b/.cookiecutterrc @@ -2,13 +2,10 @@ default_context: allow_tests_inside_package: 'no' - appveyor: 'no' c_extension_function: '-' c_extension_module: '-' c_extension_optional: 'yes' c_extension_support: 'yes' - c_extension_test_pypi: 'no' - c_extension_test_pypi_username: '-' codacy: 'no' codacy_projectid: 862e7946eabb4112be6503a667381b71 codeclimate: 'no' @@ -18,39 +15,32 @@ default_context: coveralls: 'yes' distribution_name: lazy-object-proxy email: contact@ionelmc.ro + formatter_quote_style: single full_name: Ionel Cristian Mărieș github_actions: 'yes' github_actions_osx: 'yes' github_actions_windows: 'yes' - legacy_python: 'no' license: BSD 2-Clause License - linter: flake8 package_name: lazy_object_proxy pre_commit: 'yes' - pre_commit_formatter: black project_name: lazy-object-proxy project_short_description: A fast and thorough lazy object proxy. pypi_badge: 'yes' pypi_disable_upload: 'no' - release_date: '2021-12-15' + release_date: '2023-01-04' repo_hosting: github.com repo_hosting_domain: github.com repo_main_branch: master repo_name: python-lazy-object-proxy repo_username: ionelmc - requiresio: 'yes' scrutinizer: 'no' - setup_py_uses_pytest_runner: 'no' setup_py_uses_setuptools_scm: 'yes' sphinx_docs: 'yes' sphinx_docs_hosting: https://python-lazy-object-proxy.readthedocs.io/ sphinx_doctest: 'no' sphinx_theme: sphinx-py3doc-enhanced-theme - test_matrix_configurator: 'no' test_matrix_separate_coverage: 'yes' - travis: 'no' - travis_osx: 'no' - version: 1.7.1 + version: 1.9.0 version_manager: bump2version website: https://blog.ionelmc.ro year_from: '2014' diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml index eb12832..f1366a9 100644 --- a/.github/workflows/github-actions.yml +++ b/.github/workflows/github-actions.yml @@ -10,100 +10,21 @@ jobs: matrix: include: - name: 'check' - python: '3.9' - toxpython: 'python3.9' + python: '3.11' + toxpython: 'python3.11' tox_env: 'check' os: 'ubuntu-latest' - name: 'docs' - python: '3.9' - toxpython: 'python3.9' + python: '3.11' + toxpython: 'python3.11' tox_env: 'docs' os: 'ubuntu-latest' - - name: 'py37-cover (ubuntu/x86_64)' - python: '3.7' - toxpython: 'python3.7' - python_arch: 'x64' - tox_env: 'py37-cover,codecov' - cibw_arch: 'x86_64' - cibw_build: false - os: 'ubuntu-latest' - - name: 'py37-cover (windows/AMD64)' - python: '3.7' - toxpython: 'python3.7' - python_arch: 'x64' - tox_env: 'py37-cover,codecov' - cibw_arch: 'AMD64' - cibw_build: false - os: 'windows-latest' - - name: 'py37-cover (macos/x86_64)' - python: '3.7' - toxpython: 'python3.7' - python_arch: 'x64' - tox_env: 'py37-cover,codecov' - cibw_arch: 'x86_64' - cibw_build: false - os: 'macos-latest' - - name: 'py37-nocov (ubuntu/x86_64/manylinux)' - python: '3.7' - toxpython: 'python3.7' - python_arch: 'x64' - tox_env: 'py37-nocov' - cibw_arch: 'x86_64' - cibw_build: 'cp37-*manylinux*' - os: 'ubuntu-latest' - - name: 'py37-nocov (ubuntu/x86_64/musllinux)' - python: '3.7' - toxpython: 'python3.7' - python_arch: 'x64' - tox_env: 'py37-nocov' - cibw_arch: 'x86_64' - cibw_build: 'cp37-*musllinux*' - os: 'ubuntu-latest' - - name: 'py37-nocov (ubuntu/aarch64/manylinux)' - python: '3.7' - toxpython: 'python3.7' - python_arch: 'x64' - tox_env: 'py37-nocov' - cibw_arch: 'aarch64' - cibw_build: 'cp37-*manylinux*' - os: 'ubuntu-latest' - - name: 'py37-nocov (ubuntu/aarch64/musllinux)' - python: '3.7' - toxpython: 'python3.7' - python_arch: 'x64' - tox_env: 'py37-nocov' - cibw_arch: 'aarch64' - cibw_build: 'cp37-*musllinux*' - os: 'ubuntu-latest' - - name: 'py37-nocov (windows/AMD64)' - python: '3.7' - toxpython: 'python3.7' - python_arch: 'x64' - tox_env: 'py37-nocov' - cibw_arch: 'AMD64' - cibw_build: 'cp37-*' - os: 'windows-latest' - - name: 'py37-nocov (windows/x86)' - python: '3.7' - toxpython: 'python3.7' - python_arch: 'x86' - tox_env: 'py37-nocov' - cibw_arch: 'x86' - cibw_build: 'cp37-*' - os: 'windows-latest' - - name: 'py37-nocov (macos/x86_64)' - python: '3.7' - toxpython: 'python3.7' - python_arch: 'x64' - tox_env: 'py37-nocov' - cibw_arch: 'x86_64' - cibw_build: 'cp37-*' - os: 'macos-latest' - name: 'py38-cover (ubuntu/x86_64)' python: '3.8' toxpython: 'python3.8' python_arch: 'x64' - tox_env: 'py38-cover,codecov' + tox_env: 'py38-cover' + cover: true cibw_arch: 'x86_64' cibw_build: false os: 'ubuntu-latest' @@ -111,7 +32,8 @@ jobs: python: '3.8' toxpython: 'python3.8' python_arch: 'x64' - tox_env: 'py38-cover,codecov' + tox_env: 'py38-cover' + cover: true cibw_arch: 'AMD64' cibw_build: false os: 'windows-latest' @@ -119,7 +41,8 @@ jobs: python: '3.8' toxpython: 'python3.8' python_arch: 'x64' - tox_env: 'py38-cover,codecov' + tox_env: 'py38-cover' + cover: true cibw_arch: 'x86_64' cibw_build: false os: 'macos-latest' @@ -183,7 +106,8 @@ jobs: python: '3.9' toxpython: 'python3.9' python_arch: 'x64' - tox_env: 'py39-cover,codecov' + tox_env: 'py39-cover' + cover: true cibw_arch: 'x86_64' cibw_build: false os: 'ubuntu-latest' @@ -191,7 +115,8 @@ jobs: python: '3.9' toxpython: 'python3.9' python_arch: 'x64' - tox_env: 'py39-cover,codecov' + tox_env: 'py39-cover' + cover: true cibw_arch: 'AMD64' cibw_build: false os: 'windows-latest' @@ -199,7 +124,8 @@ jobs: python: '3.9' toxpython: 'python3.9' python_arch: 'x64' - tox_env: 'py39-cover,codecov' + tox_env: 'py39-cover' + cover: true cibw_arch: 'x86_64' cibw_build: false os: 'macos-latest' @@ -263,7 +189,8 @@ jobs: python: '3.10' toxpython: 'python3.10' python_arch: 'x64' - tox_env: 'py310-cover,codecov' + tox_env: 'py310-cover' + cover: true cibw_arch: 'x86_64' cibw_build: false os: 'ubuntu-latest' @@ -271,7 +198,8 @@ jobs: python: '3.10' toxpython: 'python3.10' python_arch: 'x64' - tox_env: 'py310-cover,codecov' + tox_env: 'py310-cover' + cover: true cibw_arch: 'AMD64' cibw_build: false os: 'windows-latest' @@ -279,7 +207,8 @@ jobs: python: '3.10' toxpython: 'python3.10' python_arch: 'x64' - tox_env: 'py310-cover,codecov' + tox_env: 'py310-cover' + cover: true cibw_arch: 'x86_64' cibw_build: false os: 'macos-latest' @@ -343,7 +272,8 @@ jobs: python: '3.11' toxpython: 'python3.11' python_arch: 'x64' - tox_env: 'py311-cover,codecov' + tox_env: 'py311-cover' + cover: true cibw_arch: 'x86_64' cibw_build: false os: 'ubuntu-latest' @@ -351,7 +281,8 @@ jobs: python: '3.11' toxpython: 'python3.11' python_arch: 'x64' - tox_env: 'py311-cover,codecov' + tox_env: 'py311-cover' + cover: true cibw_arch: 'AMD64' cibw_build: false os: 'windows-latest' @@ -359,7 +290,8 @@ jobs: python: '3.11' toxpython: 'python3.11' python_arch: 'x64' - tox_env: 'py311-cover,codecov' + tox_env: 'py311-cover' + cover: true cibw_arch: 'x86_64' cibw_build: false os: 'macos-latest' @@ -419,59 +351,95 @@ jobs: cibw_arch: 'x86_64' cibw_build: 'cp311-*' os: 'macos-latest' - - name: 'pypy37-cover (ubuntu/x86_64)' - python: 'pypy-3.7' - toxpython: 'pypy3.7' + - name: 'py312-cover (ubuntu/x86_64)' + python: '3.12' + toxpython: 'python3.12' python_arch: 'x64' - tox_env: 'pypy37-cover,codecov' + tox_env: 'py312-cover' + cover: true cibw_arch: 'x86_64' cibw_build: false os: 'ubuntu-latest' - - name: 'pypy37-cover (windows/AMD64)' - python: 'pypy-3.7' - toxpython: 'pypy3.7' + - name: 'py312-cover (windows/AMD64)' + python: '3.12' + toxpython: 'python3.12' python_arch: 'x64' - tox_env: 'pypy37-cover,codecov' + tox_env: 'py312-cover' + cover: true cibw_arch: 'AMD64' cibw_build: false os: 'windows-latest' - - name: 'pypy37-cover (macos/x86_64)' - python: 'pypy-3.7' - toxpython: 'pypy3.7' + - name: 'py312-cover (macos/x86_64)' + python: '3.12' + toxpython: 'python3.12' python_arch: 'x64' - tox_env: 'pypy37-cover,codecov' + tox_env: 'py312-cover' + cover: true cibw_arch: 'x86_64' cibw_build: false os: 'macos-latest' - - name: 'pypy37-nocov (ubuntu/x86_64/manylinux)' - python: 'pypy-3.7' - toxpython: 'pypy3.7' + - name: 'py312-nocov (ubuntu/x86_64/manylinux)' + python: '3.12' + toxpython: 'python3.12' python_arch: 'x64' - tox_env: 'pypy37-nocov' + tox_env: 'py312-nocov' cibw_arch: 'x86_64' - cibw_build: false + cibw_build: 'cp312-*manylinux*' os: 'ubuntu-latest' - - name: 'pypy37-nocov (windows/AMD64)' - python: 'pypy-3.7' - toxpython: 'pypy3.7' + - name: 'py312-nocov (ubuntu/x86_64/musllinux)' + python: '3.12' + toxpython: 'python3.12' python_arch: 'x64' - tox_env: 'pypy37-nocov' + tox_env: 'py312-nocov' + cibw_arch: 'x86_64' + cibw_build: 'cp312-*musllinux*' + os: 'ubuntu-latest' + - name: 'py312-nocov (ubuntu/aarch64/manylinux)' + python: '3.12' + toxpython: 'python3.12' + python_arch: 'x64' + tox_env: 'py312-nocov' + cibw_arch: 'aarch64' + cibw_build: 'cp312-*manylinux*' + os: 'ubuntu-latest' + - name: 'py312-nocov (ubuntu/aarch64/musllinux)' + python: '3.12' + toxpython: 'python3.12' + python_arch: 'x64' + tox_env: 'py312-nocov' + cibw_arch: 'aarch64' + cibw_build: 'cp312-*musllinux*' + os: 'ubuntu-latest' + - name: 'py312-nocov (windows/AMD64)' + python: '3.12' + toxpython: 'python3.12' + python_arch: 'x64' + tox_env: 'py312-nocov' cibw_arch: 'AMD64' - cibw_build: false + cibw_build: 'cp312-*' os: 'windows-latest' - - name: 'pypy37-nocov (macos/x86_64)' - python: 'pypy-3.7' - toxpython: 'pypy3.7' + - name: 'py312-nocov (windows/x86)' + python: '3.12' + toxpython: 'python3.12' + python_arch: 'x86' + tox_env: 'py312-nocov' + cibw_arch: 'x86' + cibw_build: 'cp312-*' + os: 'windows-latest' + - name: 'py312-nocov (macos/x86_64)' + python: '3.12' + toxpython: 'python3.12' python_arch: 'x64' - tox_env: 'pypy37-nocov' + tox_env: 'py312-nocov' cibw_arch: 'x86_64' - cibw_build: false + cibw_build: 'cp312-*' os: 'macos-latest' - name: 'pypy38-cover (ubuntu/x86_64)' python: 'pypy-3.8' toxpython: 'pypy3.8' python_arch: 'x64' - tox_env: 'pypy38-cover,codecov' + tox_env: 'pypy38-cover' + cover: true cibw_arch: 'x86_64' cibw_build: false os: 'ubuntu-latest' @@ -479,7 +447,8 @@ jobs: python: 'pypy-3.8' toxpython: 'pypy3.8' python_arch: 'x64' - tox_env: 'pypy38-cover,codecov' + tox_env: 'pypy38-cover' + cover: true cibw_arch: 'AMD64' cibw_build: false os: 'windows-latest' @@ -487,7 +456,8 @@ jobs: python: 'pypy-3.8' toxpython: 'pypy3.8' python_arch: 'x64' - tox_env: 'pypy38-cover,codecov' + tox_env: 'pypy38-cover' + cover: true cibw_arch: 'x86_64' cibw_build: false os: 'macos-latest' @@ -519,7 +489,8 @@ jobs: python: 'pypy-3.9' toxpython: 'pypy3.9' python_arch: 'x64' - tox_env: 'pypy39-cover,codecov' + tox_env: 'pypy39-cover' + cover: true cibw_arch: 'x86_64' cibw_build: false os: 'ubuntu-latest' @@ -527,7 +498,8 @@ jobs: python: 'pypy-3.9' toxpython: 'pypy3.9' python_arch: 'x64' - tox_env: 'pypy39-cover,codecov' + tox_env: 'pypy39-cover' + cover: true cibw_arch: 'AMD64' cibw_build: false os: 'windows-latest' @@ -535,7 +507,8 @@ jobs: python: 'pypy-3.9' toxpython: 'pypy3.9' python_arch: 'x64' - tox_env: 'pypy39-cover,codecov' + tox_env: 'pypy39-cover' + cover: true cibw_arch: 'x86_64' cibw_build: false os: 'macos-latest' @@ -563,15 +536,66 @@ jobs: cibw_arch: 'x86_64' cibw_build: false os: 'macos-latest' + - name: 'pypy310-cover (ubuntu/x86_64)' + python: 'pypy-3.10' + toxpython: 'pypy3.10' + python_arch: 'x64' + tox_env: 'pypy310-cover' + cover: true + cibw_arch: 'x86_64' + cibw_build: false + os: 'ubuntu-latest' + - name: 'pypy310-cover (windows/AMD64)' + python: 'pypy-3.10' + toxpython: 'pypy3.10' + python_arch: 'x64' + tox_env: 'pypy310-cover' + cover: true + cibw_arch: 'AMD64' + cibw_build: false + os: 'windows-latest' + - name: 'pypy310-cover (macos/x86_64)' + python: 'pypy-3.10' + toxpython: 'pypy3.10' + python_arch: 'x64' + tox_env: 'pypy310-cover' + cover: true + cibw_arch: 'x86_64' + cibw_build: false + os: 'macos-latest' + - name: 'pypy310-nocov (ubuntu/x86_64/manylinux)' + python: 'pypy-3.10' + toxpython: 'pypy3.10' + python_arch: 'x64' + tox_env: 'pypy310-nocov' + cibw_arch: 'x86_64' + cibw_build: false + os: 'ubuntu-latest' + - name: 'pypy310-nocov (windows/AMD64)' + python: 'pypy-3.10' + toxpython: 'pypy3.10' + python_arch: 'x64' + tox_env: 'pypy310-nocov' + cibw_arch: 'AMD64' + cibw_build: false + os: 'windows-latest' + - name: 'pypy310-nocov (macos/x86_64)' + python: 'pypy-3.10' + toxpython: 'pypy3.10' + python_arch: 'x64' + tox_env: 'pypy310-nocov' + cibw_arch: 'x86_64' + cibw_build: false + os: 'macos-latest' steps: - - uses: docker/setup-qemu-action@v2 + - uses: docker/setup-qemu-action@v3 if: matrix.cibw_arch == 'aarch64' with: platforms: arm64 - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - - uses: actions/setup-python@v4 + - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} architecture: ${{ matrix.python_arch }} @@ -611,6 +635,17 @@ jobs: !matrix.cibw_build run: > tox -e ${{ matrix.tox_env }} -v + - uses: coverallsapp/github-action@v2 + if: matrix.cover + continue-on-error: true + with: + parallel: true + flag-name: ${{ matrix.tox_env }} + - uses: codecov/codecov-action@v3 + if: matrix.cover + with: + verbose: true + flags: ${{ matrix.tox_env }} - name: check wheel if: matrix.cibw_build run: twine check wheelhouse/*.whl @@ -619,3 +654,11 @@ jobs: if: matrix.cibw_build with: path: wheelhouse/*.whl + finish: + needs: test + if: ${{ always() }} + runs-on: ubuntu-latest + steps: + - uses: coverallsapp/github-action@v2 + with: + parallel-finished: true diff --git a/.gitignore b/.gitignore index 9fe45cb..a64fe0d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,40 +1,53 @@ *.py[cod] __pycache__ +# Temp files +.*.sw[po] +*~ +*.bak +.DS_Store + # C extensions *.so -# Packages +# Build and package files *.egg *.egg-info -dist -build -eggs +.bootstrap +.build +.cache .eggs -parts +.env +.installed.cfg +.ve bin -var -sdist -wheelhouse +build develop-eggs -.installed.cfg +dist +eggs lib lib64 -venv*/ -pyvenv*/ +parts pip-wheel-metadata/ +pyvenv*/ +sdist +var +venv*/ +wheelhouse # Installer logs pip-log.txt # Unit test / coverage reports +.benchmarks .coverage -.tox .coverage.* +.pytest .pytest_cache/ -nosetests.xml +.tox coverage.xml htmlcov +nosetests.xml # Translations *.mo @@ -43,12 +56,12 @@ htmlcov .mr.developer.cfg # IDE project files +*.iml +*.komodoproject +.idea .project .pydevproject -.idea .vscode -*.iml -*.komodoproject # Complexity output/*.html @@ -57,19 +70,6 @@ output/*/index.html # Sphinx docs/_build -.DS_Store -*~ -.*.sw[po] -.build -.ve -.env -.cache -.pytest -.benchmarks -.bootstrap -.appveyor.token -*.bak - # Mypy Cache .mypy_cache/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 71826c1..0a737a5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,24 +1,22 @@ -# To install the git pre-commit hook run: -# pre-commit install -# To update the pre-commit hooks run: -# pre-commit install-hooks +# To install the git pre-commit hooks run: +# pre-commit install --install-hooks +# To update the versions: +# pre-commit autoupdate exclude: '^(\.tox|ci/templates|\.bumpversion\.cfg)(/|$)' +# Note the order is intentional to avoid multiple passes of the hooks repos: - - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 - hooks: - - id: trailing-whitespace - - id: end-of-file-fixer - - id: debug-statements - - repo: https://github.com/timothycrosley/isort - rev: v5.11.3 + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.1.7 hooks: - - id: isort + - id: ruff + args: [--fix, --exit-non-zero-on-fix, --show-fixes] - repo: https://github.com/psf/black - rev: 22.12.0 + rev: 23.12.0 hooks: - id: black - - repo: https://github.com/pycqa/flake8 - rev: 6.0.0 + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.5.0 hooks: - - id: flake8 + - id: trailing-whitespace + - id: end-of-file-fixer + - id: debug-statements diff --git a/.readthedocs.yml b/.readthedocs.yml index 59ff5c0..009a913 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -3,6 +3,10 @@ version: 2 sphinx: configuration: docs/conf.py formats: all +build: + os: ubuntu-22.04 + tools: + python: "3" python: install: - requirements: docs/requirements.txt diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 2d71d8e..704f0ed 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -49,7 +49,7 @@ To set up `python-lazy-object-proxy` for local development: Now you can make your changes locally. -4. When you're done making changes run all the checks and docs builder with `tox `_ one command:: +4. When you're done making changes run all the checks and docs builder with one command:: tox @@ -73,8 +73,6 @@ For merging, you should: 3. Add a note to ``CHANGELOG.rst`` about the changes. 4. Add yourself to ``AUTHORS.rst``. - - Tips ---- diff --git a/README.rst b/README.rst index c69cba9..96b5b0a 100644 --- a/README.rst +++ b/README.rst @@ -10,7 +10,7 @@ Overview * - docs - |docs| * - tests - - | |github-actions| |requires| + - | |github-actions| | |coveralls| |codecov| * - package - | |version| |wheel| |supported-versions| |supported-implementations| @@ -23,17 +23,13 @@ Overview :alt: GitHub Actions Build Status :target: https://github.com/ionelmc/python-lazy-object-proxy/actions -.. |requires| image:: https://requires.io/github/ionelmc/python-lazy-object-proxy/requirements.svg?branch=master - :alt: Requirements Status - :target: https://requires.io/github/ionelmc/python-lazy-object-proxy/requirements/?branch=master - -.. |coveralls| image:: https://coveralls.io/repos/ionelmc/python-lazy-object-proxy/badge.svg?branch=master&service=github +.. |coveralls| image:: https://coveralls.io/repos/github/ionelmc/python-lazy-object-proxy/badge.svg?branch=master :alt: Coverage Status - :target: https://coveralls.io/r/ionelmc/python-lazy-object-proxy + :target: https://coveralls.io/github/ionelmc/python-lazy-object-proxy?branch=master .. |codecov| image:: https://codecov.io/gh/ionelmc/python-lazy-object-proxy/branch/master/graphs/badge.svg?branch=master :alt: Coverage Status - :target: https://codecov.io/github/ionelmc/python-lazy-object-proxy + :target: https://app.codecov.io/github/ionelmc/python-lazy-object-proxy .. |version| image:: https://img.shields.io/pypi/v/lazy-object-proxy.svg :alt: PyPI Package latest release diff --git a/ci/bootstrap.py b/ci/bootstrap.py index 3ca06b7..f3c9a7e 100755 --- a/ci/bootstrap.py +++ b/ci/bootstrap.py @@ -1,67 +1,57 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - import os +import pathlib import subprocess import sys -from os.path import abspath -from os.path import dirname -from os.path import exists -from os.path import join -from os.path import relpath -base_path = dirname(dirname(abspath(__file__))) -templates_path = join(base_path, "ci", "templates") +base_path: pathlib.Path = pathlib.Path(__file__).resolve().parent.parent +templates_path = base_path / 'ci' / 'templates' def check_call(args): - print("+", *args) + print('+', *args) subprocess.check_call(args) def exec_in_env(): - env_path = join(base_path, ".tox", "bootstrap") - if sys.platform == "win32": - bin_path = join(env_path, "Scripts") + env_path = base_path / '.tox' / 'bootstrap' + if sys.platform == 'win32': + bin_path = env_path / 'Scripts' else: - bin_path = join(env_path, "bin") - if not exists(env_path): + bin_path = env_path / 'bin' + if not env_path.exists(): import subprocess - print("Making bootstrap env in: {0} ...".format(env_path)) + print(f'Making bootstrap env in: {env_path} ...') try: - check_call([sys.executable, "-m", "venv", env_path]) + check_call([sys.executable, '-m', 'venv', env_path]) except subprocess.CalledProcessError: try: - check_call([sys.executable, "-m", "virtualenv", env_path]) + check_call([sys.executable, '-m', 'virtualenv', env_path]) except subprocess.CalledProcessError: - check_call(["virtualenv", env_path]) - print("Installing `jinja2` into bootstrap environment...") - check_call([join(bin_path, "pip"), "install", "jinja2", "tox"]) - python_executable = join(bin_path, "python") - if not os.path.exists(python_executable): - python_executable += '.exe' + check_call(['virtualenv', env_path]) + print('Installing `jinja2` into bootstrap environment...') + check_call([bin_path / 'pip', 'install', 'jinja2', 'tox']) + python_executable = bin_path / 'python' + if not python_executable.exists(): + python_executable = python_executable.with_suffix('.exe') - print("Re-executing with: {0}".format(python_executable)) - print("+ exec", python_executable, __file__, "--no-env") - os.execv(python_executable, [python_executable, __file__, "--no-env"]) + print(f'Re-executing with: {python_executable}') + print('+ exec', python_executable, __file__, '--no-env') + os.execv(python_executable, [python_executable, __file__, '--no-env']) def main(): import jinja2 - print("Project path: {0}".format(base_path)) + print(f'Project path: {base_path}') jinja = jinja2.Environment( - loader=jinja2.FileSystemLoader(templates_path), + loader=jinja2.FileSystemLoader(str(templates_path)), trim_blocks=True, lstrip_blocks=True, keep_trailing_newline=True, ) - tox_environments = [ line.strip() # 'tox' need not be installed globally, but must be importable @@ -72,22 +62,22 @@ def main(): for line in subprocess.check_output([sys.executable, '-m', 'tox', '--listenvs'], universal_newlines=True).splitlines() ] tox_environments = [line for line in tox_environments if line.startswith('py')] - - for root, _, files in os.walk(templates_path): - for name in files: - relative = relpath(root, templates_path) - with open(join(base_path, relative, name), "w") as fh: - fh.write(jinja.get_template(join(relative, name)).render(tox_environments=tox_environments)) - print("Wrote {}".format(name)) - print("DONE.") + for template in templates_path.rglob('*'): + if template.is_file(): + template_path = template.relative_to(templates_path).as_posix() + destination = base_path / template_path + destination.parent.mkdir(parents=True, exist_ok=True) + destination.write_text(jinja.get_template(template_path).render(tox_environments=tox_environments)) + print(f'Wrote {template_path}') + print('DONE.') -if __name__ == "__main__": +if __name__ == '__main__': args = sys.argv[1:] - if args == ["--no-env"]: + if args == ['--no-env']: main() elif not args: exec_in_env() else: - print("Unexpected arguments {0}".format(args), file=sys.stderr) + print(f'Unexpected arguments: {args}', file=sys.stderr) sys.exit(1) diff --git a/ci/templates/.github/workflows/github-actions.yml b/ci/templates/.github/workflows/github-actions.yml index 6f5c1d3..55e98d3 100644 --- a/ci/templates/.github/workflows/github-actions.yml +++ b/ci/templates/.github/workflows/github-actions.yml @@ -10,21 +10,21 @@ jobs: matrix: include: - name: 'check' - python: '3.9' - toxpython: 'python3.9' + python: '3.11' + toxpython: 'python3.11' tox_env: 'check' os: 'ubuntu-latest' - name: 'docs' - python: '3.9' - toxpython: 'python3.9' + python: '3.11' + toxpython: 'python3.11' tox_env: 'docs' os: 'ubuntu-latest' {% for env in tox_environments %} {% set prefix = env.split('-')[0] -%} {% if prefix.startswith('pypy') %} -{% set python %}pypy-{{ prefix[4] }}.{{ prefix[5] }}{% endset %} +{% set python %}pypy-{{ prefix[4] }}.{{ prefix[5:] }}{% endset %} {% set cpython %}pp{{ prefix[4:5] }}{% endset %} -{% set toxpython %}pypy{{ prefix[4] }}.{{ prefix[5] }}{% endset %} +{% set toxpython %}pypy{{ prefix[4] }}.{{ prefix[5:] }}{% endset %} {% else %} {% set python %}{{ prefix[2] }}.{{ prefix[3:] }}{% endset %} {% set cpython %}cp{{ prefix[2:] }}{% endset %} @@ -46,7 +46,10 @@ jobs: python: '{{ python }}' toxpython: '{{ toxpython }}' python_arch: '{{ python_arch }}' - tox_env: '{{ env }}{% if 'cover' in env %},codecov{% endif %}' + tox_env: '{{ env }}' +{% if 'cover' in env %} + cover: true +{% endif %} cibw_arch: '{{ cibw_arch }}' {% if 'nocov' in env and not prefix.startswith('pypy') %} cibw_build: '{{ cpython }}-{{ wheel_arch }}' @@ -58,14 +61,14 @@ jobs: {% endfor %} {% endfor %} steps: - - uses: docker/setup-qemu-action@v2 + - uses: docker/setup-qemu-action@v3 if: matrix.cibw_arch == 'aarch64' with: platforms: arm64 - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - - uses: actions/setup-python@v4 + - uses: actions/setup-python@v5 with: python-version: {{ '${{ matrix.python }}' }} architecture: {{ '${{ matrix.python_arch }}' }} @@ -105,6 +108,17 @@ jobs: !matrix.cibw_build run: > tox -e {{ '${{ matrix.tox_env }}' }} -v + - uses: coverallsapp/github-action@v2 + if: matrix.cover + continue-on-error: true + with: + parallel: true + flag-name: {{ '${{ matrix.tox_env }}' }} + - uses: codecov/codecov-action@v3 + if: matrix.cover + with: + verbose: true + flags: {{ '${{ matrix.tox_env }}' }} - name: check wheel if: matrix.cibw_build run: twine check wheelhouse/*.whl @@ -113,3 +127,11 @@ jobs: if: matrix.cibw_build with: path: wheelhouse/*.whl + finish: + needs: test + if: {{ '${{ always() }}' }} + runs-on: ubuntu-latest + steps: + - uses: coverallsapp/github-action@v2 + with: + parallel-finished: true diff --git a/docs/conf.py b/docs/conf.py index a5077be..c450dd4 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - import traceback import sphinx_py3doc_enhanced_theme @@ -21,7 +18,7 @@ project = 'lazy-object-proxy' year = '2014-2023' author = 'Ionel Cristian Mărieș' -copyright = '{0}, {1}'.format(year, author) +copyright = f'{year}, {author}' try: from pkg_resources import get_distribution @@ -48,7 +45,7 @@ html_sidebars = { '**': ['searchbox.html', 'globaltoc.html', 'sourcelink.html'], } -html_short_title = '%s-%s' % (project, version) +html_short_title = f'{project}-{version}' napoleon_use_ivar = True napoleon_use_rtype = False diff --git a/pyproject.toml b/pyproject.toml index b260f16..fbd17aa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,11 +1,57 @@ [build-system] requires = [ - "wheel", - "setuptools>=45", - "setuptools_scm[toml]>=6.2" + "setuptools>=30.3.0", + "setuptools_scm>=3.3.1", ] +[tool.ruff.per-file-ignores] +"ci/*" = ["S"] + +[tool.ruff] +extend-exclude = ["static", "ci/templates"] +ignore = [ + "RUF001", # ruff-specific rules ambiguous-unicode-character-string + "S101", # flake8-bandit assert + "S308", # flake8-bandit suspicious-mark-safe-usage + "E501", # pycodestyle line-too-long +] +line-length = 140 +select = [ + "B", # flake8-bugbear + "C4", # flake8-comprehensions + "DTZ", # flake8-datetimez + "E", # pycodestyle errors + "EXE", # flake8-executable + "F", # pyflakes + "I", # isort + "INT", # flake8-gettext + "PIE", # flake8-pie + "PLC", # pylint convention + "PLE", # pylint errors + "PT", # flake8-pytest-style + "PTH", # flake8-use-pathlib + "Q", # flake8-quotes + "RSE", # flake8-raise + "RUF", # ruff-specific rules + "S", # flake8-bandit + "UP", # pyupgrade + "W", # pycodestyle warnings +] +src = ["src", "tests"] +target-version = "py38" + +[tool.ruff.flake8-pytest-style] +fixture-parentheses = false +mark-parentheses = false + +[tool.ruff.isort] +forced-separate = ["conftest"] +force-single-line = true + [tool.black] line-length = 140 -target-version = ['py37'] +target-version = ["py38"] skip-string-normalization = true + +[tool.ruff.flake8-quotes] +inline-quotes = "single" diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 3393c72..0000000 --- a/setup.cfg +++ /dev/null @@ -1,11 +0,0 @@ -[flake8] -max-line-length = 140 -exclude = .tox,.eggs,ci/templates,build,dist - -[tool:isort] -force_single_line = True -line_length = 120 -known_first_party = lazy_object_proxy -default_section = THIRDPARTY -forced_separate = test_lazy_object_proxy -skip = .tox,.eggs,ci/templates,build,dist diff --git a/setup.py b/setup.py index 341ae64..adf63d0 100755 --- a/setup.py +++ b/setup.py @@ -1,17 +1,8 @@ #!/usr/bin/env python -# -*- encoding: utf-8 -*- - -import io import os import platform import re -import sys -from glob import glob -from os.path import basename -from os.path import dirname -from os.path import join -from os.path import relpath -from os.path import splitext +from pathlib import Path from setuptools import Extension from setuptools import find_packages @@ -19,7 +10,7 @@ from setuptools.command.build_ext import build_ext from setuptools.dist import Distribution -# Enable code coverage for C code: we can't use CFLAGS=-coverage in tox.ini, since that may mess with compiling +# Enable code coverage for C code: we cannot use CFLAGS=-coverage in tox.ini, since that may mess with compiling # dependencies (e.g. numpy). Therefore we set SETUPPY_CFLAGS=-coverage in tox.ini and copy it to CFLAGS here (after # deps have been safely installed). if 'TOX_ENV_NAME' in os.environ and os.environ.get('SETUPPY_EXT_COVERAGE') == 'yes' and platform.system() == 'Linux': @@ -31,10 +22,14 @@ class OptionalBuildExt(build_ext): - """Allow the building of C extensions to fail.""" + """ + Allow the building of C extensions to fail. + """ def run(self): try: + if os.environ.get('SETUPPY_FORCE_PURE'): + raise Exception('C extensions disabled (SETUPPY_FORCE_PURE)!') super().run() except Exception as e: self._unavailable(e) @@ -43,12 +38,12 @@ def run(self): def _unavailable(self, e): print('*' * 80) print( - '''WARNING: + """WARNING: An optional code optimization (C extension) could not be compiled. Optimizations for this package will not be available! - ''' + """ ) print('CAUSE:') @@ -58,14 +53,16 @@ def _unavailable(self, e): class BinaryDistribution(Distribution): - """Distribution which almost always forces a binary package with platform name""" + """ + Distribution which almost always forces a binary package with platform name + """ def has_ext_modules(self): return super().has_ext_modules() or not os.environ.get('SETUPPY_ALLOW_PURE') def read(*names, **kwargs): - with io.open(join(dirname(__file__), *names), encoding=kwargs.get('encoding', 'utf8')) as fh: + with Path(__file__).parent.joinpath(*names).open(encoding=kwargs.get('encoding', 'utf8')) as fh: return fh.read() @@ -87,8 +84,8 @@ def read(*names, **kwargs): url='https://github.com/ionelmc/python-lazy-object-proxy', packages=find_packages('src'), package_dir={'': 'src'}, - py_modules=[splitext(basename(path))[0] for path in glob('src/*.py')], - include_package_data=False, + py_modules=[path.stem for path in Path('src').glob('*.py')], + include_package_data=True, zip_safe=False, classifiers=[ # complete classifier list: http://pypi.python.org/pypi?%3Aaction=list_classifiers @@ -101,17 +98,17 @@ def read(*names, **kwargs): 'Programming Language :: Python', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3 :: Only', - 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', 'Programming Language :: Python :: 3.11', + 'Programming Language :: Python :: 3.12', 'Programming Language :: Python :: Implementation :: CPython', 'Programming Language :: Python :: Implementation :: PyPy', # uncomment if you test on these interpreters: - # 'Programming Language :: Python :: Implementation :: IronPython', - # 'Programming Language :: Python :: Implementation :: Jython', - # 'Programming Language :: Python :: Implementation :: Stackless', + # "Programming Language :: Python :: Implementation :: IronPython", + # "Programming Language :: Python :: Implementation :: Jython", + # "Programming Language :: Python :: Implementation :: Stackless", 'Topic :: Utilities', ], project_urls={ @@ -120,33 +117,30 @@ def read(*names, **kwargs): 'Issue Tracker': 'https://github.com/ionelmc/python-lazy-object-proxy/issues', }, keywords=[ - # eg: 'keyword1', 'keyword2', 'keyword3', + # eg: "keyword1", "keyword2", "keyword3", ], - python_requires='>=3.7', + python_requires='>=3.8', install_requires=[ - # eg: 'aspectlib==1.1.1', 'six>=1.7', + # eg: "aspectlib==1.1.1", "six>=1.7", ], extras_require={ # eg: - # 'rst': ['docutils>=0.11'], - # ':python_version=="2.6"': ['argparse'], + # "rst": ["docutils>=0.11"], + # ":python_version=="2.6"": ["argparse"], }, setup_requires=[ 'setuptools_scm>=3.3.1', ], cmdclass={'build_ext': OptionalBuildExt}, - ext_modules=[] - if hasattr(sys, 'pypy_version_info') - else [ + ext_modules=[ Extension( - splitext(relpath(path, 'src').replace(os.sep, '.'))[0], - sources=[path], + str(path.relative_to('src').with_suffix('')).replace(os.sep, '.'), + sources=[str(path)], extra_compile_args=CFLAGS.split(), extra_link_args=LFLAGS.split(), - include_dirs=[dirname(path)], + include_dirs=[str(path.parent)], ) - for root, _, _ in os.walk('src') - for path in glob(join(root, '*.c')) + for path in Path('src').glob('**/*.c') ], distclass=BinaryDistribution, ) diff --git a/tox.ini b/tox.ini index 1d82d44..1dec929 100644 --- a/tox.ini +++ b/tox.ini @@ -7,27 +7,27 @@ commands = python ci/bootstrap.py --no-env passenv = * -; a generative tox configuration, see: https://tox.readthedocs.io/en/latest/config.html#generative-envlist +; a generative tox configuration, see: https://tox.wiki/en/latest/user_guide.html#generative-environments [tox] envlist = clean, check, docs, - {py37,py38,py39,py310,py311,pypy37,pypy38,pypy39}-{cover,nocov}, + {py38,py39,py310,py311,py312,pypy38,pypy39,pypy310}-{cover,nocov}, report ignore_basepython_conflict = true [testenv] basepython = - pypy37: {env:TOXPYTHON:pypy3.7} pypy38: {env:TOXPYTHON:pypy3.8} pypy39: {env:TOXPYTHON:pypy3.9} - py37: {env:TOXPYTHON:python3.7} + pypy310: {env:TOXPYTHON:pypy3.10} py38: {env:TOXPYTHON:python3.8} py39: {env:TOXPYTHON:python3.9} py310: {env:TOXPYTHON:python3.10} py311: {env:TOXPYTHON:python3.11} + py312: {env:TOXPYTHON:python3.12} {bootstrap,clean,check,report,docs,codecov,coveralls,extension-coveralls}: {env:TOXPYTHON:python3} setenv = PYTHONPATH={toxinidir}/tests @@ -48,12 +48,12 @@ deps = commands = cover: python setup.py clean --all build_ext --force --inplace nocov: {posargs:pytest -vv --ignore=src} - cover: {posargs:pytest --cov --cov-report=term-missing -vv} + cover: {posargs:pytest --cov --cov-report=term-missing --cov-report=xml -vv} [testenv:check] deps = docutils - flake8 + pre-commit readme-renderer pygments isort @@ -61,8 +61,7 @@ deps = skip_install = true commands = python setup.py check --strict --metadata --restructuredtext - flake8 - isort --verbose --check-only --diff --filter-files . + pre-commit run --all-files --show-diff-on-failure [testenv:docs] usedevelop = true @@ -74,27 +73,6 @@ commands = sphinx-build {posargs:-E} -b html docs dist/docs sphinx-build -b linkcheck docs dist/docs -[testenv:coveralls] -deps = - coveralls -skip_install = true -commands = - coveralls {env:COVERALLS_EXTRAS:--merge=extension-coveralls.json} [] - -[testenv:extension-coveralls] -deps = - cpp-coveralls -skip_install = true -commands = - coveralls --build-root=. --include=src --dump=extension-coveralls.json [] - -[testenv:codecov] -deps = - codecov -skip_install = true -commands = - codecov --gcov-root=. [] - [testenv:report] deps = coverage From ff7459e33f937235bba101baecc917ab18d86f8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ionel=20Cristian=20M=C4=83rie=C8=99?= Date: Wed, 13 Dec 2023 18:18:11 +0200 Subject: [PATCH 02/33] First batch of ruff/black autorefactors/format. --- src/lazy_object_proxy/__init__.py | 2 +- src/lazy_object_proxy/compat.py | 2 +- src/lazy_object_proxy/simple.py | 4 +- src/lazy_object_proxy/slots.py | 12 ++- src/lazy_object_proxy/utils.py | 2 +- tests/conftest.py | 36 ++++---- tests/test_lazy_object_proxy.py | 136 +++++++++++++++--------------- 7 files changed, 95 insertions(+), 99 deletions(-) diff --git a/src/lazy_object_proxy/__init__.py b/src/lazy_object_proxy/__init__.py index 5799885..c431e17 100644 --- a/src/lazy_object_proxy/__init__.py +++ b/src/lazy_object_proxy/__init__.py @@ -20,4 +20,4 @@ except ImportError: __version__ = '1.9.0' -__all__ = ("Proxy",) +__all__ = ('Proxy',) diff --git a/src/lazy_object_proxy/compat.py b/src/lazy_object_proxy/compat.py index 770f2da..90c1cde 100644 --- a/src/lazy_object_proxy/compat.py +++ b/src/lazy_object_proxy/compat.py @@ -3,4 +3,4 @@ def with_metaclass(meta, *bases): """Create a base class with a metaclass.""" - return meta("NewBase", bases, {}) + return meta('NewBase', bases, {}) diff --git a/src/lazy_object_proxy/simple.py b/src/lazy_object_proxy/simple.py index 283894b..abf0587 100644 --- a/src/lazy_object_proxy/simple.py +++ b/src/lazy_object_proxy/simple.py @@ -14,7 +14,7 @@ def proxy_wrapper(self, *args): return proxy_wrapper -class _ProxyMethods(object): +class _ProxyMethods: # We use properties to override the values of __module__ and # __doc__. If we add these in ObjectProxy, the derived class # __dict__ will still be setup to have string variants of these @@ -95,7 +95,7 @@ def __repr__(self, __getattr__=object.__getattribute__): type(self).__name__, id(self), self.__wrapped__, id(self.__wrapped__), self.__factory__ ) else: - return '<{} at 0x{:x} with factory {!r}>'.format(type(self).__name__, id(self), self.__factory__) + return f'<{type(self).__name__} at 0x{id(self):x} with factory {self.__factory__!r}>' def __fspath__(self): wrapped = self.__wrapped__ diff --git a/src/lazy_object_proxy/slots.py b/src/lazy_object_proxy/slots.py index 4b62859..ab20a04 100644 --- a/src/lazy_object_proxy/slots.py +++ b/src/lazy_object_proxy/slots.py @@ -6,7 +6,7 @@ from .utils import identity -class _ProxyMethods(object): +class _ProxyMethods: # We use properties to override the values of __module__ and # __doc__. If we add these in ObjectProxy, the derived class # __dict__ will still be setup to have string variants of these @@ -124,8 +124,8 @@ def __name__(self, value): def __class__(self): return self.__wrapped__.__class__ - @__class__.setter # noqa: F811 - def __class__(self, value): # noqa: F811 + @__class__.setter + def __class__(self, value): self.__wrapped__.__class__ = value @property @@ -149,11 +149,9 @@ def __repr__(self, __getattr__=object.__getattribute__): try: target = __getattr__(self, '__target__') except AttributeError: - return '<{} at 0x{:x} with factory {!r}>'.format(type(self).__name__, id(self), self.__factory__) + return f'<{type(self).__name__} at 0x{id(self):x} with factory {self.__factory__!r}>' else: - return '<{} at 0x{:x} wrapping {!r} at 0x{:x} with factory {!r}>'.format( - type(self).__name__, id(self), target, id(target), self.__factory__ - ) + return f'<{type(self).__name__} at 0x{id(self):x} wrapping {target!r} at 0x{id(target):x} with factory {self.__factory__!r}>' def __fspath__(self): wrapped = self.__wrapped__ diff --git a/src/lazy_object_proxy/utils.py b/src/lazy_object_proxy/utils.py index 99945f4..8e69787 100644 --- a/src/lazy_object_proxy/utils.py +++ b/src/lazy_object_proxy/utils.py @@ -49,7 +49,7 @@ def identity(obj): return obj -class cached_property(object): +class cached_property: def __init__(self, func): self.func = func diff --git a/tests/conftest.py b/tests/conftest.py index 3f7530a..047d72e 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -5,30 +5,30 @@ PYPY = '__pypy__' in sys.builtin_module_names -@pytest.fixture(scope="session") +@pytest.fixture(scope='session') def lop_loader(): def load_implementation(name): class FakeModule: subclass = False kind = name - if name == "slots": + if name == 'slots': from lazy_object_proxy.slots import Proxy - elif name == "simple": + elif name == 'simple': from lazy_object_proxy.simple import Proxy - elif name == "cext": + elif name == 'cext': try: from lazy_object_proxy.cext import Proxy except ImportError: if PYPY: - pytest.skip(reason="C Extension not available.") + pytest.skip(reason='C Extension not available.') else: raise - elif name == "objproxies": - Proxy = pytest.importorskip("objproxies").LazyProxy - elif name == "django": - Proxy = pytest.importorskip("django.utils.functional").SimpleLazyObject + elif name == 'objproxies': + Proxy = pytest.importorskip('objproxies').LazyProxy + elif name == 'django': + Proxy = pytest.importorskip('django.utils.functional').SimpleLazyObject else: - raise RuntimeError("Unsupported param: %r." % name) + raise RuntimeError('Unsupported param: %r.' % name) Proxy @@ -38,11 +38,11 @@ class FakeModule: @pytest.fixture( - scope="session", + scope='session', params=[ - "slots", - "cext", - "simple", + 'slots', + 'cext', + 'simple', # "external-django", "external-objproxies" ], ) @@ -50,20 +50,20 @@ def lop_implementation(request, lop_loader): return lop_loader(request.param) -@pytest.fixture(scope="session", params=[True, False], ids=['subclassed', 'normal']) +@pytest.fixture(scope='session', params=[True, False], ids=['subclassed', 'normal']) def lop_subclass(request, lop_implementation): if request.param: class submod(lop_implementation): subclass = True - Proxy = type("SubclassOf_" + lop_implementation.Proxy.__name__, (lop_implementation.Proxy,), {}) + Proxy = type('SubclassOf_' + lop_implementation.Proxy.__name__, (lop_implementation.Proxy,), {}) return submod else: return lop_implementation -@pytest.fixture(scope="function") +@pytest.fixture(scope='function') def lop(request, lop_subclass): if request.node.get_closest_marker('xfail_subclass'): request.applymarker( @@ -72,6 +72,6 @@ def lop(request, lop_subclass): ) ) if request.node.get_closest_marker('xfail_simple'): - request.applymarker(pytest.mark.xfail(reason="The lazy_object_proxy.simple.Proxy has some limitations.")) + request.applymarker(pytest.mark.xfail(reason='The lazy_object_proxy.simple.Proxy has some limitations.')) return lop_subclass diff --git a/tests/test_lazy_object_proxy.py b/tests/test_lazy_object_proxy.py index fd8274b..e11000b 100644 --- a/tests/test_lazy_object_proxy.py +++ b/tests/test_lazy_object_proxy.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import gc import os import pickle @@ -366,7 +364,7 @@ def function(*args, **kwargs): def test_function_kwargs(lop): _args = () - _kwargs = {"one": 1, "two": 2} + _kwargs = {'one': 1, 'two': 2} def function(*args, **kwargs): return args, kwargs @@ -380,7 +378,7 @@ def function(*args, **kwargs): def test_function_args_plus_kwargs(lop): _args = (1, 2) - _kwargs = {"one": 1, "two": 2} + _kwargs = {'one': 1, 'two': 2} def function(*args, **kwargs): return args, kwargs @@ -396,7 +394,7 @@ def test_instancemethod_no_args(lop): _args = () _kwargs = {} - class Class(object): + class Class: def function(self, *args, **kwargs): return args, kwargs @@ -411,7 +409,7 @@ def test_instancemethod_args(lop): _args = (1, 2) _kwargs = {} - class Class(object): + class Class: def function(self, *args, **kwargs): return args, kwargs @@ -424,9 +422,9 @@ def function(self, *args, **kwargs): def test_instancemethod_kwargs(lop): _args = () - _kwargs = {"one": 1, "two": 2} + _kwargs = {'one': 1, 'two': 2} - class Class(object): + class Class: def function(self, *args, **kwargs): return args, kwargs @@ -439,9 +437,9 @@ def function(self, *args, **kwargs): def test_instancemethod_args_plus_kwargs(lop): _args = (1, 2) - _kwargs = {"one": 1, "two": 2} + _kwargs = {'one': 1, 'two': 2} - class Class(object): + class Class: def function(self, *args, **kwargs): return args, kwargs @@ -456,7 +454,7 @@ def test_instancemethod_via_class_no_args(lop): _args = () _kwargs = {} - class Class(object): + class Class: def function(self, *args, **kwargs): return args, kwargs @@ -471,7 +469,7 @@ def test_instancemethod_via_class_args(lop): _args = (1, 2) _kwargs = {} - class Class(object): + class Class: def function(self, *args, **kwargs): return args, kwargs @@ -484,9 +482,9 @@ def function(self, *args, **kwargs): def test_instancemethod_via_class_kwargs(lop): _args = () - _kwargs = {"one": 1, "two": 2} + _kwargs = {'one': 1, 'two': 2} - class Class(object): + class Class: def function(self, *args, **kwargs): return args, kwargs @@ -499,9 +497,9 @@ def function(self, *args, **kwargs): def test_instancemethod_via_class_args_plus_kwargs(lop): _args = (1, 2) - _kwargs = {"one": 1, "two": 2} + _kwargs = {'one': 1, 'two': 2} - class Class(object): + class Class: def function(self, *args, **kwargs): return args, kwargs @@ -516,7 +514,7 @@ def test_classmethod_no_args(lop): _args = () _kwargs = {} - class Class(object): + class Class: @classmethod def function(cls, *args, **kwargs): return args, kwargs @@ -532,7 +530,7 @@ def test_classmethod_args(lop): _args = (1, 2) _kwargs = {} - class Class(object): + class Class: @classmethod def function(cls, *args, **kwargs): return args, kwargs @@ -546,9 +544,9 @@ def function(cls, *args, **kwargs): def test_classmethod_kwargs(lop): _args = () - _kwargs = {"one": 1, "two": 2} + _kwargs = {'one': 1, 'two': 2} - class Class(object): + class Class: @classmethod def function(cls, *args, **kwargs): return args, kwargs @@ -562,9 +560,9 @@ def function(cls, *args, **kwargs): def test_classmethod_args_plus_kwargs(lop): _args = (1, 2) - _kwargs = {"one": 1, "two": 2} + _kwargs = {'one': 1, 'two': 2} - class Class(object): + class Class: @classmethod def function(cls, *args, **kwargs): return args, kwargs @@ -580,7 +578,7 @@ def test_classmethod_via_class_no_args(lop): _args = () _kwargs = {} - class Class(object): + class Class: @classmethod def function(cls, *args, **kwargs): return args, kwargs @@ -596,7 +594,7 @@ def test_classmethod_via_class_args(lop): _args = (1, 2) _kwargs = {} - class Class(object): + class Class: @classmethod def function(cls, *args, **kwargs): return args, kwargs @@ -610,9 +608,9 @@ def function(cls, *args, **kwargs): def test_classmethod_via_class_kwargs(lop): _args = () - _kwargs = {"one": 1, "two": 2} + _kwargs = {'one': 1, 'two': 2} - class Class(object): + class Class: @classmethod def function(cls, *args, **kwargs): return args, kwargs @@ -626,9 +624,9 @@ def function(cls, *args, **kwargs): def test_classmethod_via_class_args_plus_kwargs(lop): _args = (1, 2) - _kwargs = {"one": 1, "two": 2} + _kwargs = {'one': 1, 'two': 2} - class Class(object): + class Class: @classmethod def function(cls, *args, **kwargs): return args, kwargs @@ -644,7 +642,7 @@ def test_staticmethod_no_args(lop): _args = () _kwargs = {} - class Class(object): + class Class: @staticmethod def function(*args, **kwargs): return args, kwargs @@ -660,7 +658,7 @@ def test_staticmethod_args(lop): _args = (1, 2) _kwargs = {} - class Class(object): + class Class: @staticmethod def function(*args, **kwargs): return args, kwargs @@ -674,9 +672,9 @@ def function(*args, **kwargs): def test_staticmethod_kwargs(lop): _args = () - _kwargs = {"one": 1, "two": 2} + _kwargs = {'one': 1, 'two': 2} - class Class(object): + class Class: @staticmethod def function(*args, **kwargs): return args, kwargs @@ -690,9 +688,9 @@ def function(*args, **kwargs): def test_staticmethod_args_plus_kwargs(lop): _args = (1, 2) - _kwargs = {"one": 1, "two": 2} + _kwargs = {'one': 1, 'two': 2} - class Class(object): + class Class: @staticmethod def function(*args, **kwargs): return args, kwargs @@ -708,7 +706,7 @@ def test_staticmethod_via_class_no_args(lop): _args = () _kwargs = {} - class Class(object): + class Class: @staticmethod def function(*args, **kwargs): return args, kwargs @@ -724,7 +722,7 @@ def test_staticmethod_via_class_args(lop): _args = (1, 2) _kwargs = {} - class Class(object): + class Class: @staticmethod def function(*args, **kwargs): return args, kwargs @@ -738,9 +736,9 @@ def function(*args, **kwargs): def test_staticmethod_via_class_kwargs(lop): _args = () - _kwargs = {"one": 1, "two": 2} + _kwargs = {'one': 1, 'two': 2} - class Class(object): + class Class: @staticmethod def function(*args, **kwargs): return args, kwargs @@ -754,9 +752,9 @@ def function(*args, **kwargs): def test_staticmethod_via_class_args_plus_kwargs(lop): _args = (1, 2) - _kwargs = {"one": 1, "two": 2} + _kwargs = {'one': 1, 'two': 2} - class Class(object): + class Class: @staticmethod def function(*args, **kwargs): return args, kwargs @@ -788,7 +786,7 @@ def test_iter_builtin(lop): def test_context_manager(lop): - class Class(object): + class Class: def __enter__(self): return self @@ -1313,7 +1311,7 @@ def test_hex(lop): def test_index(lop): - class Class(object): + class Class: def __index__(self): return 1 @@ -1563,7 +1561,7 @@ def __getattr__(self, name): def test_proxy_hasattr_call(lop): proxy = lop.Proxy(lambda: None) - assert not hasattr(proxy, '__call__') + assert not callable(proxy) @skipcallable @@ -1583,7 +1581,7 @@ def test_proxy_is_callable(lop): def test_callable_proxy_hasattr_call(lop): proxy = lop.Proxy(lambda: None) - assert hasattr(proxy, '__call__') + assert callable(proxy) @skipcallable @@ -1600,7 +1598,7 @@ def test_callable_proxy_is_callable(lop): def test_class_bytes(lop): - class Class(object): + class Class: def __bytes__(self): return b'BYTES' @@ -1672,7 +1670,7 @@ def make_foo(): def test_raise_attribute_error(lop): def foo(): - raise AttributeError("boom!") + raise AttributeError('boom!') proxy = lop.Proxy(foo) pytest.raises(AttributeError, str, proxy) @@ -1682,7 +1680,7 @@ def foo(): def test_patching_the_factory(lop): def foo(): - raise AttributeError("boom!") + raise AttributeError('boom!') proxy = lop.Proxy(foo) pytest.raises(AttributeError, lambda: proxy.__wrapped__) @@ -1746,15 +1744,15 @@ def test_set_wrapped_regular(lop): @pytest.fixture( params=[ - "pickle", + 'pickle', ] ) def pickler(request): return pytest.importorskip(request.param) -@pytest.mark.parametrize("obj", [1, 1.2, "a", ["b", "c"], {"d": "e"}, date(2015, 5, 1), datetime(2015, 5, 1), Decimal("1.2")]) -@pytest.mark.parametrize("level", range(pickle.HIGHEST_PROTOCOL + 1)) +@pytest.mark.parametrize('obj', [1, 1.2, 'a', ['b', 'c'], {'d': 'e'}, date(2015, 5, 1), datetime(2015, 5, 1), Decimal('1.2')]) +@pytest.mark.parametrize('level', range(pickle.HIGHEST_PROTOCOL + 1)) def test_pickling(lop, obj, pickler, level): proxy = lop.Proxy(lambda: obj) dump = pickler.dumps(proxy, protocol=level) @@ -1762,13 +1760,13 @@ def test_pickling(lop, obj, pickler, level): assert obj == result -@pytest.mark.parametrize("level", range(pickle.HIGHEST_PROTOCOL + 1)) +@pytest.mark.parametrize('level', range(pickle.HIGHEST_PROTOCOL + 1)) def test_pickling_exception(lop, pickler, level): class BadStuff(Exception): pass def trouble_maker(): - raise BadStuff("foo") + raise BadStuff('foo') proxy = lop.Proxy(trouble_maker) pytest.raises(BadStuff, pickler.dumps, proxy, protocol=level) @@ -1780,7 +1778,7 @@ def test_garbage_collection(lop): proxy = lop.Proxy(leaky) leaky.leak = proxy ref = weakref.ref(leaky) - assert proxy == "foobar" + assert proxy == 'foobar' del leaky del proxy gc.collect() @@ -1796,10 +1794,10 @@ def test_garbage_collection_count(lop): assert count == sys.getrefcount(obj) -@pytest.mark.parametrize("name", ["slots", "cext", "simple", "django", "objproxies"]) +@pytest.mark.parametrize('name', ['slots', 'cext', 'simple', 'django', 'objproxies']) def test_perf(benchmark, name, lop_loader): implementation = lop_loader(name) - obj = "foobar" + obj = 'foobar' proxied = implementation.Proxy(lambda: obj) assert benchmark(partial(str, proxied)) == obj @@ -1807,15 +1805,15 @@ def test_perf(benchmark, name, lop_loader): empty = object() -@pytest.fixture(scope="module", params=["SimpleProxy", "LocalsSimpleProxy", "CachedPropertyProxy", "LocalsCachedPropertyProxy"]) +@pytest.fixture(scope='module', params=['SimpleProxy', 'LocalsSimpleProxy', 'CachedPropertyProxy', 'LocalsCachedPropertyProxy']) def prototype(request): from lazy_object_proxy.simple import cached_property name = request.param - if name == "SimpleProxy": + if name == 'SimpleProxy': - class SimpleProxy(object): + class SimpleProxy: def __init__(self, factory): self.factory = factory self.object = empty @@ -1826,9 +1824,9 @@ def __str__(self): return str(self.object) return SimpleProxy - elif name == "CachedPropertyProxy": + elif name == 'CachedPropertyProxy': - class CachedPropertyProxy(object): + class CachedPropertyProxy: def __init__(self, factory): self.factory = factory @@ -1840,9 +1838,9 @@ def __str__(self): return str(self.object) return CachedPropertyProxy - elif name == "LocalsSimpleProxy": + elif name == 'LocalsSimpleProxy': - class LocalsSimpleProxy(object): + class LocalsSimpleProxy: def __init__(self, factory): self.factory = factory self.object = empty @@ -1853,9 +1851,9 @@ def __str__(self, func=str): return func(self.object) return LocalsSimpleProxy - elif name == "LocalsCachedPropertyProxy": + elif name == 'LocalsCachedPropertyProxy': - class LocalsCachedPropertyProxy(object): + class LocalsCachedPropertyProxy: def __init__(self, factory): self.factory = factory @@ -1869,9 +1867,9 @@ def __str__(self, func=str): return LocalsCachedPropertyProxy -@pytest.mark.benchmark(group="prototypes") +@pytest.mark.benchmark(group='prototypes') def test_proto(benchmark, prototype): - obj = "foobar" + obj = 'foobar' proxied = prototype(lambda: obj) assert benchmark(partial(str, proxied)) == obj @@ -1897,7 +1895,7 @@ def __init__(self, func, **lazy_attr): def test_subclassing_dynamic_with_local_attr(lop): if lop.kind == 'cext': - pytest.skip("Not possible.") + pytest.skip('Not possible.') class Foo: pass @@ -1915,12 +1913,12 @@ def __init__(self, func, **lazy_attr): assert not called -class FSPathMock(object): +class FSPathMock: def __fspath__(self): return '/tmp' -@pytest.mark.skipif(not hasattr(os, "fspath"), reason="No os.fspath support.") +@pytest.mark.skipif(not hasattr(os, 'fspath'), reason='No os.fspath support.') def test_fspath(lop): assert os.fspath(lop.Proxy(lambda: '/tmp')) == '/tmp' assert os.fspath(lop.Proxy(FSPathMock)) == '/tmp' From b8e223a2c420156a31a4082fe74f54330a96be01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ionel=20Cristian=20M=C4=83rie=C8=99?= Date: Wed, 13 Dec 2023 19:32:14 +0200 Subject: [PATCH 03/33] Fix a bunch of lint issues. --- pyproject.toml | 12 ++++++++++-- src/lazy_object_proxy/slots.py | 4 ++-- tests/conftest.py | 4 ++-- tests/test_async_py3.py | 2 +- tests/test_lazy_object_proxy.py | 28 +++++++++++++--------------- 5 files changed, 28 insertions(+), 22 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index fbd17aa..f84e2f2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,8 +1,11 @@ [build-system] requires = [ - "setuptools>=30.3.0", - "setuptools_scm>=3.3.1", + "setuptools>=64", + "setuptools_scm>=8", ] +build-backend = "setuptools.build_meta" + +[tool.setuptools_scm] [tool.ruff.per-file-ignores] "ci/*" = ["S"] @@ -14,6 +17,11 @@ ignore = [ "S101", # flake8-bandit assert "S308", # flake8-bandit suspicious-mark-safe-usage "E501", # pycodestyle line-too-long + "DTZ001", + "PT011", + "PT012", + "B004", + "S102", ] line-length = 140 select = [ diff --git a/src/lazy_object_proxy/slots.py b/src/lazy_object_proxy/slots.py index ab20a04..bf035c0 100644 --- a/src/lazy_object_proxy/slots.py +++ b/src/lazy_object_proxy/slots.py @@ -98,8 +98,8 @@ def __wrapped__(self, __getattr__=object.__getattribute__, __setattr__=object.__ except AttributeError: try: factory = __getattr__(self, '__factory__') - except AttributeError: - raise ValueError("Proxy hasn't been initiated: __factory__ is missing.") + except AttributeError as exc: + raise ValueError("Proxy hasn't been initiated: __factory__ is missing.") from exc target = factory() __setattr__(self, '__target__', target) return target diff --git a/tests/conftest.py b/tests/conftest.py index 047d72e..11d0379 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -30,7 +30,7 @@ class FakeModule: else: raise RuntimeError('Unsupported param: %r.' % name) - Proxy + Proxy # noqa: B018 return FakeModule @@ -63,7 +63,7 @@ class submod(lop_implementation): return lop_implementation -@pytest.fixture(scope='function') +@pytest.fixture def lop(request, lop_subclass): if request.node.get_closest_marker('xfail_subclass'): request.applymarker( diff --git a/tests/test_async_py3.py b/tests/test_async_py3.py index 2cf8003..513986f 100644 --- a/tests/test_async_py3.py +++ b/tests/test_async_py3.py @@ -249,7 +249,7 @@ async def foo(): aw = coro.__await__() next(aw) with pytest.raises(ZeroDivisionError): - aw.throw(ZeroDivisionError, None, None) + aw.throw(ZeroDivisionError) assert N == 102 diff --git a/tests/test_lazy_object_proxy.py b/tests/test_lazy_object_proxy.py index e11000b..8741d12 100644 --- a/tests/test_lazy_object_proxy.py +++ b/tests/test_lazy_object_proxy.py @@ -771,7 +771,7 @@ def test_iteration(lop): wrapper = lop.Proxy(lambda: items) - result = [x for x in wrapper] + result = [x for x in wrapper] # noqa: C416 assert result == items @@ -816,13 +816,11 @@ def function1(*args, **kwargs): function2 = lop.Proxy(lambda: function1) - table = dict() - table[function1] = True + table = {function1: True} assert table.get(function2) - table = dict() - table[function2] = True + table = {function2: True} assert table.get(function1) @@ -1458,12 +1456,12 @@ def test_repr_doesnt_consume(lop): def test_derived_new(lop): class DerivedObjectProxy(lop.Proxy): def __new__(cls, wrapped): - instance = super(DerivedObjectProxy, cls).__new__(cls) + instance = super().__new__(cls) instance.__init__(wrapped) return instance def __init__(self, wrapped): - super(DerivedObjectProxy, self).__init__(wrapped) + super().__init__(wrapped) def function(): return 123 @@ -1540,9 +1538,9 @@ class DerivedObjectProxy(lop.Proxy): def __getattr__(self, name): accessed.append(name) try: - __getattr__ = super(DerivedObjectProxy, self).__getattr__ + __getattr__ = super().__getattr__ except AttributeError as e: - raise RuntimeError(str(e)) + raise RuntimeError(str(e)) from e return __getattr__(name) function.attribute = 1 @@ -1884,7 +1882,7 @@ class LazyProxy(lop.Proxy): name = None def __init__(self, func, **lazy_attr): - super(LazyProxy, self).__init__(func) + super().__init__(func) for attr, val in lazy_attr.items(): setattr(self, attr, val) @@ -1904,7 +1902,7 @@ class Foo: class LazyProxy(lop.Proxy): def __init__(self, func, **lazy_attr): - super(LazyProxy, self).__init__(func) + super().__init__(func) for attr, val in lazy_attr.items(): object.__setattr__(self, attr, val) @@ -1915,20 +1913,20 @@ def __init__(self, func, **lazy_attr): class FSPathMock: def __fspath__(self): - return '/tmp' + return '/foobar' @pytest.mark.skipif(not hasattr(os, 'fspath'), reason='No os.fspath support.') def test_fspath(lop): - assert os.fspath(lop.Proxy(lambda: '/tmp')) == '/tmp' - assert os.fspath(lop.Proxy(FSPathMock)) == '/tmp' + assert os.fspath(lop.Proxy(lambda: '/foobar')) == '/foobar' + assert os.fspath(lop.Proxy(FSPathMock)) == '/foobar' with pytest.raises(TypeError) as excinfo: os.fspath(lop.Proxy(lambda: None)) assert '__fspath__() to return str or bytes, not NoneType' in excinfo.value.args[0] def test_fspath_method(lop): - assert lop.Proxy(FSPathMock).__fspath__() == '/tmp' + assert lop.Proxy(FSPathMock).__fspath__() == '/foobar' def test_resolved_new(lop): From f633fd33443b20e3ca7e6713060b88571aa0910c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ionel=20Cristian=20M=C4=83rie=C8=99?= Date: Wed, 13 Dec 2023 19:32:21 +0200 Subject: [PATCH 04/33] Spelling. --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index adf63d0..f7d4f62 100755 --- a/setup.py +++ b/setup.py @@ -11,7 +11,7 @@ from setuptools.dist import Distribution # Enable code coverage for C code: we cannot use CFLAGS=-coverage in tox.ini, since that may mess with compiling -# dependencies (e.g. numpy). Therefore we set SETUPPY_CFLAGS=-coverage in tox.ini and copy it to CFLAGS here (after +# dependencies (e.g. numpy). Therefore, we set SETUPPY_CFLAGS=-coverage in tox.ini and copy it to CFLAGS here (after # deps have been safely installed). if 'TOX_ENV_NAME' in os.environ and os.environ.get('SETUPPY_EXT_COVERAGE') == 'yes' and platform.system() == 'Linux': CFLAGS = os.environ['CFLAGS'] = '-fprofile-arcs -ftest-coverage' From 2f8bed25a2c40ab1eb1f33c0592045f921a4a3e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ionel=20Cristian=20M=C4=83rie=C8=99?= Date: Wed, 13 Dec 2023 19:32:52 +0200 Subject: [PATCH 05/33] Make sure the C ext is not build on PyPy (if it builds it would segfault and be broken) --- setup.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/setup.py b/setup.py index f7d4f62..940b2e9 100755 --- a/setup.py +++ b/setup.py @@ -2,6 +2,7 @@ import os import platform import re +import sys from pathlib import Path from setuptools import Extension @@ -28,6 +29,8 @@ class OptionalBuildExt(build_ext): def run(self): try: + if '__pypy__' in sys.builtin_module_names: + raise Exception('C extensions are broken on PyPy!') if os.environ.get('SETUPPY_FORCE_PURE'): raise Exception('C extensions disabled (SETUPPY_FORCE_PURE)!') super().run() From 4aab40747db4c0cadd8e4ee79d4962dd42add076 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ionel=20Cristian=20M=C4=83rie=C8=99?= Date: Wed, 13 Dec 2023 19:33:16 +0200 Subject: [PATCH 06/33] Manually spec setuptools for that inplace building. --- tox.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tox.ini b/tox.ini index 1dec929..57f7222 100644 --- a/tox.ini +++ b/tox.ini @@ -44,6 +44,7 @@ deps = Django objproxies==0.9.4 hunter + setuptools cover: pytest-cov commands = cover: python setup.py clean --all build_ext --force --inplace @@ -57,6 +58,7 @@ deps = readme-renderer pygments isort + setuptools setuptools-scm skip_install = true commands = From 2ca62affb5c058494520f34669654fac55fdcce1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ionel=20Cristian=20M=C4=83rie=C8=99?= Date: Thu, 14 Dec 2023 02:29:50 +0200 Subject: [PATCH 07/33] Xfail these till I can figure it out. --- tests/test_lazy_object_proxy.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/tests/test_lazy_object_proxy.py b/tests/test_lazy_object_proxy.py index 8741d12..6c5e637 100644 --- a/tests/test_lazy_object_proxy.py +++ b/tests/test_lazy_object_proxy.py @@ -985,19 +985,28 @@ def test_pow(lop): assert three**two == pow(3, 2) assert 3**two == pow(3, 2) + assert pow(3, two) == pow(3, 2) assert three**2 == pow(3, 2) assert pow(three, two) == pow(3, 2) assert pow(3, two) == pow(3, 2) assert pow(three, 2) == pow(3, 2) + assert pow(three, 2, 2) == pow(3, 2, 2) - # Only PyPy implements __rpow__ for ternary pow(). - if PYPY: - assert pow(three, two, 2) == pow(3, 2, 2) - assert pow(3, two, 2) == pow(3, 2, 2) +@pytest.mark.xfail +def test_pow_ternary(lop): + two = lop.Proxy(lambda: 2) + three = lop.Proxy(lambda: 3) - assert pow(three, 2, 2) == pow(3, 2, 2) + assert pow(three, two, 2) == pow(3, 2, 2) + + +@pytest.mark.xfail +def test_rpow_ternary(lop): + two = lop.Proxy(lambda: 2) + + assert pow(3, two, 2) == pow(3, 2, 2) def test_lshift(lop): From dab21f7fe09e9d28c3487606cd44ea289fcfa1ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ionel=20Cristian=20M=C4=83rie=C8=99?= Date: Thu, 14 Dec 2023 02:36:12 +0200 Subject: [PATCH 08/33] Fix broken link. --- AUTHORS.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AUTHORS.rst b/AUTHORS.rst index 6f2cf90..0b972ac 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -5,7 +5,7 @@ Authors * Ionel Cristian Mărieș - https://blog.ionelmc.ro * Alvin Chow - https://github.com/alvinchow86 * Astrum Kuo - https://github.com/xowenx -* Erik M. Bray - http://iguananaut.net +* Erik M. Bray - https://github.com/embray * Ran Benita - https://github.com/bluetech * "hugovk" - https://github.com/hugovk * Sandro Tosi - https://github.com/sandrotosi From 940c8c6bb907cc90322bda2ba33c1893ad611432 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ionel=20Cristian=20M=C4=83rie=C8=99?= Date: Fri, 15 Dec 2023 15:45:31 +0200 Subject: [PATCH 09/33] Bail out early if extensions would be disabled. --- setup.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/setup.py b/setup.py index 940b2e9..4580214 100755 --- a/setup.py +++ b/setup.py @@ -21,6 +21,14 @@ CFLAGS = '' LFLAGS = '' +allow_extensions = True +if '__pypy__' in sys.builtin_module_names: + print('NOTICE: C extensions disabled on PyPy (would be broken)!') + allow_extensions = False +if os.environ.get('SETUPPY_FORCE_PURE'): + print('NOTICE: C extensions disabled (SETUPPY_FORCE_PURE)!') + allow_extensions = False + class OptionalBuildExt(build_ext): """ @@ -29,10 +37,6 @@ class OptionalBuildExt(build_ext): def run(self): try: - if '__pypy__' in sys.builtin_module_names: - raise Exception('C extensions are broken on PyPy!') - if os.environ.get('SETUPPY_FORCE_PURE'): - raise Exception('C extensions disabled (SETUPPY_FORCE_PURE)!') super().run() except Exception as e: self._unavailable(e) @@ -144,6 +148,8 @@ def read(*names, **kwargs): include_dirs=[str(path.parent)], ) for path in Path('src').glob('**/*.c') - ], + ] + if allow_extensions + else [], distclass=BinaryDistribution, ) From 7b32ae58d04ef8d1ced99ebf411b595ffc462d52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ionel=20Cristian=20M=C4=83rie=C8=99?= Date: Fri, 15 Dec 2023 15:49:17 +0200 Subject: [PATCH 10/33] Update changelog. --- CHANGELOG.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 5e844a8..52a4911 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -2,6 +2,13 @@ Changelog ========= +1.10.0 (2023-12-15) +------------------- + +* Added Python 3.12 wheels. +* Dropped support for Python 3.7. +* Applied some reformatting and lint fixes using ruff to the codebase (mostly more Python 2 leftover cleanups). + 1.9.0 (2023-01-04) ------------------ From aa46e846fa2eb7cb845a07e122f2984267551098 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ionel=20Cristian=20M=C4=83rie=C8=99?= Date: Fri, 15 Dec 2023 15:49:30 +0200 Subject: [PATCH 11/33] =?UTF-8?q?Bump=20version:=201.9.0=20=E2=86=92=201.1?= =?UTF-8?q?0.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- .cookiecutterrc | 2 +- README.rst | 4 ++-- docs/conf.py | 2 +- setup.py | 2 +- src/lazy_object_proxy/__init__.py | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index cde88f5..f4dedb1 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 1.9.0 +current_version = 1.10.0 commit = True tag = True diff --git a/.cookiecutterrc b/.cookiecutterrc index c85b08b..29789c1 100644 --- a/.cookiecutterrc +++ b/.cookiecutterrc @@ -40,7 +40,7 @@ default_context: sphinx_doctest: 'no' sphinx_theme: sphinx-py3doc-enhanced-theme test_matrix_separate_coverage: 'yes' - version: 1.9.0 + version: 1.10.0 version_manager: bump2version website: https://blog.ionelmc.ro year_from: '2014' diff --git a/README.rst b/README.rst index 96b5b0a..cac8bba 100644 --- a/README.rst +++ b/README.rst @@ -47,9 +47,9 @@ Overview :alt: Supported implementations :target: https://pypi.org/project/lazy-object-proxy -.. |commits-since| image:: https://img.shields.io/github/commits-since/ionelmc/python-lazy-object-proxy/v1.9.0.svg +.. |commits-since| image:: https://img.shields.io/github/commits-since/ionelmc/python-lazy-object-proxy/v1.10.0.svg :alt: Commits since latest release - :target: https://github.com/ionelmc/python-lazy-object-proxy/compare/v1.9.0...master + :target: https://github.com/ionelmc/python-lazy-object-proxy/compare/v1.10.0...master diff --git a/docs/conf.py b/docs/conf.py index c450dd4..f6d031a 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -25,7 +25,7 @@ version = release = get_distribution('lazy_object_proxy').version except Exception: traceback.print_exc() - version = release = '1.9.0' + version = release = '1.10.0' pygments_style = 'trac' templates_path = ['.'] diff --git a/setup.py b/setup.py index 4580214..30f84c6 100755 --- a/setup.py +++ b/setup.py @@ -78,7 +78,7 @@ def read(*names, **kwargs): use_scm_version={ 'local_scheme': 'dirty-tag', 'write_to': 'src/lazy_object_proxy/_version.py', - 'fallback_version': '1.9.0', + 'fallback_version': '1.10.0', }, license='BSD-2-Clause', description='A fast and thorough lazy object proxy.', diff --git a/src/lazy_object_proxy/__init__.py b/src/lazy_object_proxy/__init__.py index c431e17..50b9cae 100644 --- a/src/lazy_object_proxy/__init__.py +++ b/src/lazy_object_proxy/__init__.py @@ -18,6 +18,6 @@ try: from ._version import version as __version__ except ImportError: - __version__ = '1.9.0' + __version__ = '1.10.0' __all__ = ('Proxy',) From 58b0c8fed178e3c4e1487434711170466994cacf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ionel=20Cristian=20M=C4=83rie=C8=99?= Date: Mon, 12 Aug 2024 18:46:14 +0300 Subject: [PATCH 12/33] Add a tidelift security policy. --- SECURITY.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..da9c516 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,5 @@ +## Security contact information + +To report a security vulnerability, please use the +[Tidelift security contact](https://tidelift.com/security). +Tidelift will coordinate the fix and disclosure. From 29cd77a54e89ad11d029cbe28e41ccc07fb48839 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ionel=20Cristian=20M=C4=83rie=C8=99?= Date: Wed, 20 Nov 2024 16:42:26 +0200 Subject: [PATCH 13/33] Add support for __format__. --- src/lazy_object_proxy/cext.c | 17 +++++++++++++++++ src/lazy_object_proxy/simple.py | 7 ++++--- src/lazy_object_proxy/slots.py | 3 +++ tests/test_lazy_object_proxy.py | 9 +++++++++ 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/src/lazy_object_proxy/cext.c b/src/lazy_object_proxy/cext.c index 17f1098..4bb755f 100644 --- a/src/lazy_object_proxy/cext.c +++ b/src/lazy_object_proxy/cext.c @@ -1182,6 +1182,22 @@ static PyObject *Proxy_aexit( /* ------------------------------------------------------------------------- */ +static PyObject *Proxy_format( + ProxyObject *self, PyObject *args, PyObject *kwds) +{ + PyObject *format_spec = NULL; + + Proxy__ENSURE_WRAPPED_OR_RETURN_NULL(self); + + if (!PyArg_ParseTuple(args, "|O:format", &format_spec)) + return NULL; + + return PyObject_Format(self->wrapped, format_spec); + +} + +/* ------------------------------------------------------------------------- */ + static PyObject *Proxy_await(ProxyObject *self) { Proxy__ENSURE_WRAPPED_OR_RETURN_NULL(self); @@ -1311,6 +1327,7 @@ static PyMethodDef Proxy_methods[] = { { "__round__", (PyCFunction)Proxy_round, METH_NOARGS, 0 }, { "__aenter__", (PyCFunction)Proxy_aenter, METH_NOARGS, 0 }, { "__aexit__", (PyCFunction)Proxy_aexit, METH_VARARGS | METH_KEYWORDS, 0 }, + { "__format__", (PyCFunction)Proxy_format, METH_VARARGS, 0 }, { NULL, NULL }, }; diff --git a/src/lazy_object_proxy/simple.py b/src/lazy_object_proxy/simple.py index abf0587..8009b93 100644 --- a/src/lazy_object_proxy/simple.py +++ b/src/lazy_object_proxy/simple.py @@ -91,9 +91,7 @@ def __wrapped__(self): def __repr__(self, __getattr__=object.__getattribute__): if '__wrapped__' in self.__dict__: - return '<{} at 0x{:x} wrapping {!r} at 0x{:x} with factory {!r}>'.format( - type(self).__name__, id(self), self.__wrapped__, id(self.__wrapped__), self.__factory__ - ) + return f'<{type(self).__name__} at 0x{id(self):x} wrapping {self.__wrapped__!r} at 0x{id(self.__wrapped__):x} with factory {self.__factory__!r}>' else: return f'<{type(self).__name__} at 0x{id(self):x} with factory {self.__factory__!r}>' @@ -249,6 +247,9 @@ def __reduce__(self): def __reduce_ex__(self, protocol): return identity, (self.__wrapped__,) + def __format__(self, format_spec): + return self.__wrapped__.__format__(format_spec) + if await_: from .utils import __aenter__ from .utils import __aexit__ diff --git a/src/lazy_object_proxy/slots.py b/src/lazy_object_proxy/slots.py index bf035c0..eac82cc 100644 --- a/src/lazy_object_proxy/slots.py +++ b/src/lazy_object_proxy/slots.py @@ -429,6 +429,9 @@ def __reduce__(self): def __reduce_ex__(self, protocol): return identity, (self.__wrapped__,) + def __format__(self, format_spec): + return self.__wrapped__.__format__(format_spec) + if await_: from .utils import __aenter__ from .utils import __aexit__ diff --git a/tests/test_lazy_object_proxy.py b/tests/test_lazy_object_proxy.py index 6c5e637..d95aa57 100644 --- a/tests/test_lazy_object_proxy.py +++ b/tests/test_lazy_object_proxy.py @@ -1955,3 +1955,12 @@ def test_resolved_str(lop): assert obj.__resolved__ is False str(obj) assert obj.__resolved__ is True + + +def test_format(lop): + class WithFormat: + def __format__(self, format_spec): + return f'spec({format_spec!r})' + + obj = lop.Proxy(WithFormat) + assert f'{obj:stuff}' == "spec('stuff')" From bdcc696ef07eed5d11ab72d07238c39e53562c08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ionel=20Cristian=20M=C4=83rie=C8=99?= Date: Wed, 20 Nov 2024 16:51:33 +0200 Subject: [PATCH 14/33] Drop EOL python 3.8 and update some CI config. --- .cookiecutterrc | 12 +- .github/workflows/github-actions.yml | 248 +++--------------- .pre-commit-config.yaml | 9 +- LICENSE | 2 +- README.rst | 15 +- ci/requirements.txt | 1 - .../.github/workflows/github-actions.yml | 8 +- docs/conf.py | 19 +- docs/requirements.txt | 2 +- pyproject.toml | 28 +- setup.py | 5 +- tox.ini | 9 +- 12 files changed, 92 insertions(+), 266 deletions(-) diff --git a/.cookiecutterrc b/.cookiecutterrc index 29789c1..1d621f1 100644 --- a/.cookiecutterrc +++ b/.cookiecutterrc @@ -1,9 +1,6 @@ # Generated by cookiepatcher, a small shim around cookiecutter (pip install cookiepatcher) default_context: - allow_tests_inside_package: 'no' - c_extension_function: '-' - c_extension_module: '-' c_extension_optional: 'yes' c_extension_support: 'yes' codacy: 'no' @@ -17,17 +14,19 @@ default_context: email: contact@ionelmc.ro formatter_quote_style: single full_name: Ionel Cristian Mărieș + function_name: compute github_actions: 'yes' github_actions_osx: 'yes' github_actions_windows: 'yes' license: BSD 2-Clause License + module_name: cext package_name: lazy_object_proxy pre_commit: 'yes' project_name: lazy-object-proxy project_short_description: A fast and thorough lazy object proxy. pypi_badge: 'yes' pypi_disable_upload: 'no' - release_date: '2023-01-04' + release_date: '2023-12-15' repo_hosting: github.com repo_hosting_domain: github.com repo_main_branch: master @@ -38,10 +37,11 @@ default_context: sphinx_docs: 'yes' sphinx_docs_hosting: https://python-lazy-object-proxy.readthedocs.io/ sphinx_doctest: 'no' - sphinx_theme: sphinx-py3doc-enhanced-theme + sphinx_theme: furo test_matrix_separate_coverage: 'yes' + tests_inside_package: 'no' version: 1.10.0 version_manager: bump2version website: https://blog.ionelmc.ro year_from: '2014' - year_to: '2023' + year_to: '2024' diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml index f1366a9..a507797 100644 --- a/.github/workflows/github-actions.yml +++ b/.github/workflows/github-actions.yml @@ -1,5 +1,5 @@ name: build -on: [push, pull_request] +on: [push, pull_request, workflow_dispatch] jobs: test: name: ${{ matrix.name }} @@ -19,89 +19,6 @@ jobs: toxpython: 'python3.11' tox_env: 'docs' os: 'ubuntu-latest' - - name: 'py38-cover (ubuntu/x86_64)' - python: '3.8' - toxpython: 'python3.8' - python_arch: 'x64' - tox_env: 'py38-cover' - cover: true - cibw_arch: 'x86_64' - cibw_build: false - os: 'ubuntu-latest' - - name: 'py38-cover (windows/AMD64)' - python: '3.8' - toxpython: 'python3.8' - python_arch: 'x64' - tox_env: 'py38-cover' - cover: true - cibw_arch: 'AMD64' - cibw_build: false - os: 'windows-latest' - - name: 'py38-cover (macos/x86_64)' - python: '3.8' - toxpython: 'python3.8' - python_arch: 'x64' - tox_env: 'py38-cover' - cover: true - cibw_arch: 'x86_64' - cibw_build: false - os: 'macos-latest' - - name: 'py38-nocov (ubuntu/x86_64/manylinux)' - python: '3.8' - toxpython: 'python3.8' - python_arch: 'x64' - tox_env: 'py38-nocov' - cibw_arch: 'x86_64' - cibw_build: 'cp38-*manylinux*' - os: 'ubuntu-latest' - - name: 'py38-nocov (ubuntu/x86_64/musllinux)' - python: '3.8' - toxpython: 'python3.8' - python_arch: 'x64' - tox_env: 'py38-nocov' - cibw_arch: 'x86_64' - cibw_build: 'cp38-*musllinux*' - os: 'ubuntu-latest' - - name: 'py38-nocov (ubuntu/aarch64/manylinux)' - python: '3.8' - toxpython: 'python3.8' - python_arch: 'x64' - tox_env: 'py38-nocov' - cibw_arch: 'aarch64' - cibw_build: 'cp38-*manylinux*' - os: 'ubuntu-latest' - - name: 'py38-nocov (ubuntu/aarch64/musllinux)' - python: '3.8' - toxpython: 'python3.8' - python_arch: 'x64' - tox_env: 'py38-nocov' - cibw_arch: 'aarch64' - cibw_build: 'cp38-*musllinux*' - os: 'ubuntu-latest' - - name: 'py38-nocov (windows/AMD64)' - python: '3.8' - toxpython: 'python3.8' - python_arch: 'x64' - tox_env: 'py38-nocov' - cibw_arch: 'AMD64' - cibw_build: 'cp38-*' - os: 'windows-latest' - - name: 'py38-nocov (windows/x86)' - python: '3.8' - toxpython: 'python3.8' - python_arch: 'x86' - tox_env: 'py38-nocov' - cibw_arch: 'x86' - cibw_build: 'cp38-*' - os: 'windows-latest' - - name: 'py38-nocov (macos/x86_64)' - python: '3.8' - toxpython: 'python3.8' - python_arch: 'x64' - tox_env: 'py38-nocov' - cibw_arch: 'x86_64' - cibw_build: 'cp38-*' - os: 'macos-latest' - name: 'py39-cover (ubuntu/x86_64)' python: '3.9' toxpython: 'python3.9' @@ -120,13 +37,13 @@ jobs: cibw_arch: 'AMD64' cibw_build: false os: 'windows-latest' - - name: 'py39-cover (macos/x86_64)' + - name: 'py39-cover (macos/arm64)' python: '3.9' toxpython: 'python3.9' - python_arch: 'x64' + python_arch: 'arm64' tox_env: 'py39-cover' cover: true - cibw_arch: 'x86_64' + cibw_arch: 'arm64' cibw_build: false os: 'macos-latest' - name: 'py39-nocov (ubuntu/x86_64/manylinux)' @@ -169,20 +86,12 @@ jobs: cibw_arch: 'AMD64' cibw_build: 'cp39-*' os: 'windows-latest' - - name: 'py39-nocov (windows/x86)' + - name: 'py39-nocov (macos/arm64)' python: '3.9' toxpython: 'python3.9' - python_arch: 'x86' + python_arch: 'arm64' tox_env: 'py39-nocov' - cibw_arch: 'x86' - cibw_build: 'cp39-*' - os: 'windows-latest' - - name: 'py39-nocov (macos/x86_64)' - python: '3.9' - toxpython: 'python3.9' - python_arch: 'x64' - tox_env: 'py39-nocov' - cibw_arch: 'x86_64' + cibw_arch: 'arm64' cibw_build: 'cp39-*' os: 'macos-latest' - name: 'py310-cover (ubuntu/x86_64)' @@ -203,13 +112,13 @@ jobs: cibw_arch: 'AMD64' cibw_build: false os: 'windows-latest' - - name: 'py310-cover (macos/x86_64)' + - name: 'py310-cover (macos/arm64)' python: '3.10' toxpython: 'python3.10' - python_arch: 'x64' + python_arch: 'arm64' tox_env: 'py310-cover' cover: true - cibw_arch: 'x86_64' + cibw_arch: 'arm64' cibw_build: false os: 'macos-latest' - name: 'py310-nocov (ubuntu/x86_64/manylinux)' @@ -252,20 +161,12 @@ jobs: cibw_arch: 'AMD64' cibw_build: 'cp310-*' os: 'windows-latest' - - name: 'py310-nocov (windows/x86)' + - name: 'py310-nocov (macos/arm64)' python: '3.10' toxpython: 'python3.10' - python_arch: 'x86' + python_arch: 'arm64' tox_env: 'py310-nocov' - cibw_arch: 'x86' - cibw_build: 'cp310-*' - os: 'windows-latest' - - name: 'py310-nocov (macos/x86_64)' - python: '3.10' - toxpython: 'python3.10' - python_arch: 'x64' - tox_env: 'py310-nocov' - cibw_arch: 'x86_64' + cibw_arch: 'arm64' cibw_build: 'cp310-*' os: 'macos-latest' - name: 'py311-cover (ubuntu/x86_64)' @@ -286,13 +187,13 @@ jobs: cibw_arch: 'AMD64' cibw_build: false os: 'windows-latest' - - name: 'py311-cover (macos/x86_64)' + - name: 'py311-cover (macos/arm64)' python: '3.11' toxpython: 'python3.11' - python_arch: 'x64' + python_arch: 'arm64' tox_env: 'py311-cover' cover: true - cibw_arch: 'x86_64' + cibw_arch: 'arm64' cibw_build: false os: 'macos-latest' - name: 'py311-nocov (ubuntu/x86_64/manylinux)' @@ -335,20 +236,12 @@ jobs: cibw_arch: 'AMD64' cibw_build: 'cp311-*' os: 'windows-latest' - - name: 'py311-nocov (windows/x86)' + - name: 'py311-nocov (macos/arm64)' python: '3.11' toxpython: 'python3.11' - python_arch: 'x86' + python_arch: 'arm64' tox_env: 'py311-nocov' - cibw_arch: 'x86' - cibw_build: 'cp311-*' - os: 'windows-latest' - - name: 'py311-nocov (macos/x86_64)' - python: '3.11' - toxpython: 'python3.11' - python_arch: 'x64' - tox_env: 'py311-nocov' - cibw_arch: 'x86_64' + cibw_arch: 'arm64' cibw_build: 'cp311-*' os: 'macos-latest' - name: 'py312-cover (ubuntu/x86_64)' @@ -369,13 +262,13 @@ jobs: cibw_arch: 'AMD64' cibw_build: false os: 'windows-latest' - - name: 'py312-cover (macos/x86_64)' + - name: 'py312-cover (macos/arm64)' python: '3.12' toxpython: 'python3.12' - python_arch: 'x64' + python_arch: 'arm64' tox_env: 'py312-cover' cover: true - cibw_arch: 'x86_64' + cibw_arch: 'arm64' cibw_build: false os: 'macos-latest' - name: 'py312-nocov (ubuntu/x86_64/manylinux)' @@ -418,72 +311,13 @@ jobs: cibw_arch: 'AMD64' cibw_build: 'cp312-*' os: 'windows-latest' - - name: 'py312-nocov (windows/x86)' + - name: 'py312-nocov (macos/arm64)' python: '3.12' toxpython: 'python3.12' - python_arch: 'x86' + python_arch: 'arm64' tox_env: 'py312-nocov' - cibw_arch: 'x86' + cibw_arch: 'arm64' cibw_build: 'cp312-*' - os: 'windows-latest' - - name: 'py312-nocov (macos/x86_64)' - python: '3.12' - toxpython: 'python3.12' - python_arch: 'x64' - tox_env: 'py312-nocov' - cibw_arch: 'x86_64' - cibw_build: 'cp312-*' - os: 'macos-latest' - - name: 'pypy38-cover (ubuntu/x86_64)' - python: 'pypy-3.8' - toxpython: 'pypy3.8' - python_arch: 'x64' - tox_env: 'pypy38-cover' - cover: true - cibw_arch: 'x86_64' - cibw_build: false - os: 'ubuntu-latest' - - name: 'pypy38-cover (windows/AMD64)' - python: 'pypy-3.8' - toxpython: 'pypy3.8' - python_arch: 'x64' - tox_env: 'pypy38-cover' - cover: true - cibw_arch: 'AMD64' - cibw_build: false - os: 'windows-latest' - - name: 'pypy38-cover (macos/x86_64)' - python: 'pypy-3.8' - toxpython: 'pypy3.8' - python_arch: 'x64' - tox_env: 'pypy38-cover' - cover: true - cibw_arch: 'x86_64' - cibw_build: false - os: 'macos-latest' - - name: 'pypy38-nocov (ubuntu/x86_64/manylinux)' - python: 'pypy-3.8' - toxpython: 'pypy3.8' - python_arch: 'x64' - tox_env: 'pypy38-nocov' - cibw_arch: 'x86_64' - cibw_build: false - os: 'ubuntu-latest' - - name: 'pypy38-nocov (windows/AMD64)' - python: 'pypy-3.8' - toxpython: 'pypy3.8' - python_arch: 'x64' - tox_env: 'pypy38-nocov' - cibw_arch: 'AMD64' - cibw_build: false - os: 'windows-latest' - - name: 'pypy38-nocov (macos/x86_64)' - python: 'pypy-3.8' - toxpython: 'pypy3.8' - python_arch: 'x64' - tox_env: 'pypy38-nocov' - cibw_arch: 'x86_64' - cibw_build: false os: 'macos-latest' - name: 'pypy39-cover (ubuntu/x86_64)' python: 'pypy-3.9' @@ -503,13 +337,13 @@ jobs: cibw_arch: 'AMD64' cibw_build: false os: 'windows-latest' - - name: 'pypy39-cover (macos/x86_64)' + - name: 'pypy39-cover (macos/arm64)' python: 'pypy-3.9' toxpython: 'pypy3.9' - python_arch: 'x64' + python_arch: 'arm64' tox_env: 'pypy39-cover' cover: true - cibw_arch: 'x86_64' + cibw_arch: 'arm64' cibw_build: false os: 'macos-latest' - name: 'pypy39-nocov (ubuntu/x86_64/manylinux)' @@ -528,12 +362,12 @@ jobs: cibw_arch: 'AMD64' cibw_build: false os: 'windows-latest' - - name: 'pypy39-nocov (macos/x86_64)' + - name: 'pypy39-nocov (macos/arm64)' python: 'pypy-3.9' toxpython: 'pypy3.9' - python_arch: 'x64' + python_arch: 'arm64' tox_env: 'pypy39-nocov' - cibw_arch: 'x86_64' + cibw_arch: 'arm64' cibw_build: false os: 'macos-latest' - name: 'pypy310-cover (ubuntu/x86_64)' @@ -554,13 +388,13 @@ jobs: cibw_arch: 'AMD64' cibw_build: false os: 'windows-latest' - - name: 'pypy310-cover (macos/x86_64)' + - name: 'pypy310-cover (macos/arm64)' python: 'pypy-3.10' toxpython: 'pypy3.10' - python_arch: 'x64' + python_arch: 'arm64' tox_env: 'pypy310-cover' cover: true - cibw_arch: 'x86_64' + cibw_arch: 'arm64' cibw_build: false os: 'macos-latest' - name: 'pypy310-nocov (ubuntu/x86_64/manylinux)' @@ -579,12 +413,12 @@ jobs: cibw_arch: 'AMD64' cibw_build: false os: 'windows-latest' - - name: 'pypy310-nocov (macos/x86_64)' + - name: 'pypy310-nocov (macos/arm64)' python: 'pypy-3.10' toxpython: 'pypy3.10' - python_arch: 'x64' + python_arch: 'arm64' tox_env: 'pypy310-nocov' - cibw_arch: 'x86_64' + cibw_arch: 'arm64' cibw_build: false os: 'macos-latest' steps: @@ -606,11 +440,6 @@ jobs: pip --version tox --version pip list --format=freeze - - name: install dependencies (gdb) - if: > - !matrix.cibw_build && matrix.os == 'ubuntu' - run: > - sudo apt-get install gdb - name: cibw build and test if: matrix.cibw_build run: cibuildwheel @@ -662,3 +491,6 @@ jobs: - uses: coverallsapp/github-action@v2 with: parallel-finished: true + - uses: codecov/codecov-action@v3 + with: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0a737a5..2124ee7 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,16 +6,13 @@ exclude: '^(\.tox|ci/templates|\.bumpversion\.cfg)(/|$)' # Note the order is intentional to avoid multiple passes of the hooks repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.1.7 + rev: v0.7.4 hooks: - id: ruff args: [--fix, --exit-non-zero-on-fix, --show-fixes] - - repo: https://github.com/psf/black - rev: 23.12.0 - hooks: - - id: black + - id: ruff-format - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.5.0 + rev: v5.0.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer diff --git a/LICENSE b/LICENSE index 07630f9..b56dc6d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ BSD 2-Clause License -Copyright (c) 2014-2023, Ionel Cristian Mărieș. All rights reserved. +Copyright (c) 2014-2024, Ionel Cristian Mărieș. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/README.rst b/README.rst index cac8bba..e429753 100644 --- a/README.rst +++ b/README.rst @@ -10,13 +10,11 @@ Overview * - docs - |docs| * - tests - - | |github-actions| - | |coveralls| |codecov| + - |github-actions| |coveralls| |codecov| * - package - - | |version| |wheel| |supported-versions| |supported-implementations| - | |commits-since| + - |version| |wheel| |supported-versions| |supported-implementations| |commits-since| .. |docs| image:: https://readthedocs.org/projects/python-lazy-object-proxy/badge/?style=flat - :target: https://python-lazy-object-proxy.readthedocs.io/ + :target: https://readthedocs.org/projects/python-lazy-object-proxy/ :alt: Documentation Status .. |github-actions| image:: https://github.com/ionelmc/python-lazy-object-proxy/actions/workflows/github-actions.yml/badge.svg @@ -91,11 +89,18 @@ Installation pip install lazy-object-proxy +You can also install the in-development version with:: + + pip install https://github.com/ionelmc/python-lazy-object-proxy/archive/master.zip + + Documentation ============= + https://python-lazy-object-proxy.readthedocs.io/ + Development =========== diff --git a/ci/requirements.txt b/ci/requirements.txt index a1708f4..b4f1852 100644 --- a/ci/requirements.txt +++ b/ci/requirements.txt @@ -1,6 +1,5 @@ virtualenv>=16.6.0 pip>=19.1.1 setuptools>=18.0.1 -six>=1.14.0 tox twine diff --git a/ci/templates/.github/workflows/github-actions.yml b/ci/templates/.github/workflows/github-actions.yml index 55e98d3..fb89fec 100644 --- a/ci/templates/.github/workflows/github-actions.yml +++ b/ci/templates/.github/workflows/github-actions.yml @@ -1,5 +1,5 @@ name: build -on: [push, pull_request] +on: [push, pull_request, workflow_dispatch] jobs: test: name: {{ '${{ matrix.name }}' }} @@ -36,8 +36,7 @@ jobs: ['ubuntu', 'x64', 'aarch64', '*manylinux*', False], ['ubuntu', 'x64', 'aarch64', '*musllinux*', False], ['windows', 'x64', 'AMD64', '*', True], - ['windows', 'x86', 'x86', '*', False], - ['macos', 'x64', 'x86_64', '*', True], + ['macos', 'arm64', 'arm64', '*', True], ] %} {% if include_cover or ('nocov' in env and not prefix.startswith('pypy')) %} {% set wheel_suffix = 'nocov' in env and wheel_arch.strip('*') %} @@ -135,3 +134,6 @@ jobs: - uses: coverallsapp/github-action@v2 with: parallel-finished: true + - uses: codecov/codecov-action@v3 + with: + CODECOV_TOKEN: {% raw %}${{ secrets.CODECOV_TOKEN }}{% endraw %} diff --git a/docs/conf.py b/docs/conf.py index f6d031a..18f3f99 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,7 +1,3 @@ -import traceback - -import sphinx_py3doc_enhanced_theme - extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.autosummary', @@ -16,7 +12,7 @@ source_suffix = '.rst' master_doc = 'index' project = 'lazy-object-proxy' -year = '2014-2023' +year = '2014-2024' author = 'Ionel Cristian Mărieș' copyright = f'{year}, {author}' try: @@ -24,17 +20,19 @@ version = release = get_distribution('lazy_object_proxy').version except Exception: + import traceback + traceback.print_exc() version = release = '1.10.0' pygments_style = 'trac' templates_path = ['.'] extlinks = { - 'issue': ('https://github.com/ionelmc/python-lazy-object-proxy/issues/%s', '#'), - 'pr': ('https://github.com/ionelmc/python-lazy-object-proxy/pull/%s', 'PR #'), + 'issue': ('https://github.com/ionelmc/python-lazy-object-proxy/issues/%s', '#%s'), + 'pr': ('https://github.com/ionelmc/python-lazy-object-proxy/pull/%s', 'PR #%s'), } -html_theme = 'sphinx_py3doc_enhanced_theme' -html_theme_path = [sphinx_py3doc_enhanced_theme.get_html_theme_path()] + +html_theme = 'furo' html_theme_options = { 'githuburl': 'https://github.com/ionelmc/python-lazy-object-proxy/', } @@ -42,9 +40,6 @@ html_use_smartypants = True html_last_updated_fmt = '%b %d, %Y' html_split_index = False -html_sidebars = { - '**': ['searchbox.html', 'globaltoc.html', 'sourcelink.html'], -} html_short_title = f'{project}-{version}' napoleon_use_ivar = True diff --git a/docs/requirements.txt b/docs/requirements.txt index 62bc14e..c03e307 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,2 +1,2 @@ sphinx>=1.3 -sphinx-py3doc-enhanced-theme +furo diff --git a/pyproject.toml b/pyproject.toml index f84e2f2..6632079 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,11 +7,16 @@ build-backend = "setuptools.build_meta" [tool.setuptools_scm] -[tool.ruff.per-file-ignores] -"ci/*" = ["S"] - [tool.ruff] extend-exclude = ["static", "ci/templates"] +line-length = 140 +src = ["src", "tests"] +target-version = "py39" + +[tool.ruff.lint.per-file-ignores] +"ci/*" = ["S"] + +[tool.ruff.lint] ignore = [ "RUF001", # ruff-specific rules ambiguous-unicode-character-string "S101", # flake8-bandit assert @@ -23,7 +28,6 @@ ignore = [ "B004", "S102", ] -line-length = 140 select = [ "B", # flake8-bugbear "C4", # flake8-comprehensions @@ -38,28 +42,20 @@ select = [ "PLE", # pylint errors "PT", # flake8-pytest-style "PTH", # flake8-use-pathlib - "Q", # flake8-quotes "RSE", # flake8-raise "RUF", # ruff-specific rules "S", # flake8-bandit "UP", # pyupgrade "W", # pycodestyle warnings ] -src = ["src", "tests"] -target-version = "py38" -[tool.ruff.flake8-pytest-style] +[tool.ruff.lint.flake8-pytest-style] fixture-parentheses = false mark-parentheses = false -[tool.ruff.isort] +[tool.ruff.lint.isort] forced-separate = ["conftest"] force-single-line = true -[tool.black] -line-length = 140 -target-version = ["py38"] -skip-string-normalization = true - -[tool.ruff.flake8-quotes] -inline-quotes = "single" +[tool.ruff.format] +quote-style = "single" diff --git a/setup.py b/setup.py index 30f84c6..d7a0044 100755 --- a/setup.py +++ b/setup.py @@ -105,7 +105,6 @@ def read(*names, **kwargs): 'Programming Language :: Python', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3 :: Only', - 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', 'Programming Language :: Python :: 3.11', @@ -126,14 +125,14 @@ def read(*names, **kwargs): keywords=[ # eg: "keyword1", "keyword2", "keyword3", ], - python_requires='>=3.8', + python_requires='>=3.9', install_requires=[ # eg: "aspectlib==1.1.1", "six>=1.7", ], extras_require={ # eg: # "rst": ["docutils>=0.11"], - # ":python_version=="2.6"": ["argparse"], + # ":python_version=='3.8'": ["backports.zoneinfo"], }, setup_requires=[ 'setuptools_scm>=3.3.1', diff --git a/tox.ini b/tox.ini index 57f7222..37b2254 100644 --- a/tox.ini +++ b/tox.ini @@ -14,16 +14,14 @@ envlist = clean, check, docs, - {py38,py39,py310,py311,py312,pypy38,pypy39,pypy310}-{cover,nocov}, + {py39,py310,py311,py312,pypy39,pypy310}-{cover,nocov}, report ignore_basepython_conflict = true [testenv] basepython = - pypy38: {env:TOXPYTHON:pypy3.8} pypy39: {env:TOXPYTHON:pypy3.9} pypy310: {env:TOXPYTHON:pypy3.10} - py38: {env:TOXPYTHON:python3.8} py39: {env:TOXPYTHON:python3.9} py310: {env:TOXPYTHON:python3.10} py311: {env:TOXPYTHON:python3.11} @@ -84,7 +82,10 @@ commands = coverage html [testenv:clean] -commands = coverage erase +commands = + python setup.py clean + coverage erase skip_install = true deps = + setuptools coverage From d76efe129ee317b2ebd2b807a5fb6509ba86b8bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ionel=20Cristian=20M=C4=83rie=C8=99?= Date: Wed, 20 Nov 2024 16:53:27 +0200 Subject: [PATCH 15/33] Run ruff over. --- .pre-commit-config.yaml | 2 +- tests/conftest.py | 4 +-- tests/test_async_py3.py | 42 +++++++++++++------------- tests/test_lazy_object_proxy.py | 52 ++++++++++++++++----------------- 4 files changed, 50 insertions(+), 50 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2124ee7..0964d05 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -9,7 +9,7 @@ repos: rev: v0.7.4 hooks: - id: ruff - args: [--fix, --exit-non-zero-on-fix, --show-fixes] + args: [--fix, --exit-non-zero-on-fix, --show-fixes, --unsafe-fixes] - id: ruff-format - repo: https://github.com/pre-commit/pre-commit-hooks rev: v5.0.0 diff --git a/tests/conftest.py b/tests/conftest.py index 11d0379..1317faf 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -28,7 +28,7 @@ class FakeModule: elif name == 'django': Proxy = pytest.importorskip('django.utils.functional').SimpleLazyObject else: - raise RuntimeError('Unsupported param: %r.' % name) + raise RuntimeError(f'Unsupported param: {name!r}.') Proxy # noqa: B018 @@ -68,7 +68,7 @@ def lop(request, lop_subclass): if request.node.get_closest_marker('xfail_subclass'): request.applymarker( pytest.mark.xfail( - reason="This test can't work because subclassing disables certain " "features like __doc__ and __module__ proxying." + reason="This test can't work because subclassing disables certain features like __doc__ and __module__ proxying." ) ) if request.node.get_closest_marker('xfail_simple'): diff --git a/tests/test_async_py3.py b/tests/test_async_py3.py index 513986f..63a4e97 100644 --- a/tests/test_async_py3.py +++ b/tests/test_async_py3.py @@ -99,7 +99,7 @@ def test_func_2(lop): async def foo(): raise StopIteration - with pytest.raises(RuntimeError, match="coroutine raised StopIteration"): + with pytest.raises(RuntimeError, match='coroutine raised StopIteration'): run_async(lop.Proxy(foo)) @@ -275,7 +275,7 @@ async def g(): await foo me = lop.Proxy(g) - with pytest.raises(ValueError, match="coroutine already executing"): + with pytest.raises(ValueError, match='coroutine already executing'): me.send(None) @@ -303,7 +303,7 @@ async def coro(): c = lop.Proxy(coro) c.send(None) - with pytest.raises(RuntimeError, match="coroutine ignored GeneratorExit"): + with pytest.raises(RuntimeError, match='coroutine ignored GeneratorExit'): c.close() @@ -498,7 +498,7 @@ def test_await_1(lop): async def foo(): await 1 - with pytest.raises(TypeError, match="object int can.t.*await"): + with pytest.raises(TypeError, match='object int can.t.*await'): run_async(lop.Proxy(foo)) @@ -506,7 +506,7 @@ def test_await_2(lop): async def foo(): await [] - with pytest.raises(TypeError, match="object list can.t.*await"): + with pytest.raises(TypeError, match='object list can.t.*await'): run_async(lop.Proxy(foo)) @@ -536,7 +536,7 @@ def __await__(self): async def foo(): return await lop.Proxy(Awaitable) - with pytest.raises(TypeError, match="__await__.*returned non-iterator of type"): + with pytest.raises(TypeError, match='__await__.*returned non-iterator of type'): run_async(lop.Proxy(foo)) @@ -644,7 +644,7 @@ def __await__(self): async def foo(): return await lop.Proxy(Awaitable) - with pytest.raises(TypeError, match=r"__await__\(\) returned a coroutine"): + with pytest.raises(TypeError, match=r'__await__\(\) returned a coroutine'): run_async(lop.Proxy(foo)) c.close() @@ -658,7 +658,7 @@ def __await__(self): async def foo(): return await lop.Proxy(Awaitable) - with pytest.raises(TypeError, match="__await__.*returned non-iterator of type"): + with pytest.raises(TypeError, match='__await__.*returned non-iterator of type'): run_async(lop.Proxy(foo)) @@ -713,7 +713,7 @@ async def waiter(coro): coro = lop.Proxy(coroutine) coro.send(None) - with pytest.raises(RuntimeError, match="coroutine is being awaited already"): + with pytest.raises(RuntimeError, match='coroutine is being awaited already'): waiter(coro).send(None) @@ -749,7 +749,7 @@ async def __aexit__(self, *args): return True async def foo(): - async with lop.Proxy(lambda: Manager("A")) as a, lop.Proxy(lambda: Manager("B")) as b: + async with lop.Proxy(lambda: Manager('A')) as a, lop.Proxy(lambda: Manager('B')) as b: await lop.Proxy(lambda: AsyncYieldFrom([('managers', a.name, b.name)])) 1 / 0 @@ -769,7 +769,7 @@ async def foo(): ] async def foo(): - async with lop.Proxy(lambda: Manager("A")) as a, lop.Proxy(lambda: Manager("C")) as c: + async with lop.Proxy(lambda: Manager('A')) as a, lop.Proxy(lambda: Manager('C')) as c: await lop.Proxy(lambda: AsyncYieldFrom([('managers', a.name, c.name)])) 1 / 0 @@ -857,7 +857,7 @@ async def foo(): async with lop.Proxy(CM): pass - with pytest.raises(TypeError, match="'async with' received an object from __aenter__ " "that does not implement __await__: int"): + with pytest.raises(TypeError, match="'async with' received an object from __aenter__ " 'that does not implement __await__: int'): # it's important that __aexit__ wasn't called run_async(lop.Proxy(foo)) @@ -879,7 +879,7 @@ async def foo(): try: run_async(lop.Proxy(foo)) except TypeError as exc: - assert re.search("'async with' received an object from __aexit__ " "that does not implement __await__: int", exc.args[0]) + assert re.search("'async with' received an object from __aexit__ " 'that does not implement __await__: int', exc.args[0]) assert exc.__context__ is not None assert isinstance(exc.__context__, ZeroDivisionError) else: @@ -903,7 +903,7 @@ async def foo(): async with lop.Proxy(CM): CNT += 1 - with pytest.raises(TypeError, match="'async with' received an object from __aexit__ " "that does not implement __await__: int"): + with pytest.raises(TypeError, match="'async with' received an object from __aexit__ " 'that does not implement __await__: int'): run_async(lop.Proxy(foo)) assert CNT == 1 @@ -915,7 +915,7 @@ async def foo(): CNT += 1 break - with pytest.raises(TypeError, match="'async with' received an object from __aexit__ " "that does not implement __await__: int"): + with pytest.raises(TypeError, match="'async with' received an object from __aexit__ " 'that does not implement __await__: int'): run_async(lop.Proxy(foo)) assert CNT == 2 @@ -927,7 +927,7 @@ async def foo(): CNT += 1 continue - with pytest.raises(TypeError, match="'async with' received an object from __aexit__ " "that does not implement __await__: int"): + with pytest.raises(TypeError, match="'async with' received an object from __aexit__ " 'that does not implement __await__: int'): run_async(lop.Proxy(foo)) assert CNT == 3 @@ -938,7 +938,7 @@ async def foo(): CNT += 1 return - with pytest.raises(TypeError, match="'async with' received an object from __aexit__ " "that does not implement __await__: int"): + with pytest.raises(TypeError, match="'async with' received an object from __aexit__ " 'that does not implement __await__: int'): run_async(lop.Proxy(foo)) assert CNT == 4 @@ -1224,7 +1224,7 @@ async def main(): I += 1000 with warnings.catch_warnings(): - warnings.simplefilter("error") + warnings.simplefilter('error') # Test that __aiter__ that returns an asynchronous iterator # directly does not throw any warnings. run_async(main()) @@ -1309,7 +1309,7 @@ async def foo(): with pytest.raises(ZeroDivisionError): with warnings.catch_warnings(): - warnings.simplefilter("error") + warnings.simplefilter('error') # Test that if __aiter__ raises an exception it propagates # without any kind of warning. run_async(lop.Proxy(foo)) @@ -1622,7 +1622,7 @@ async def func(): aw.close() -@pytest.mark.skipif("sys.version_info[1] < 8") +@pytest.mark.skipif('sys.version_info[1] < 8') def test_for_assign_raising_stop_async_iteration(lop): class BadTarget: def __setitem__(self, key, value): @@ -1662,7 +1662,7 @@ async def run_gen(): assert run_async(run_gen()) == ([], 'end') -@pytest.mark.skipif("sys.version_info[1] < 8") +@pytest.mark.skipif('sys.version_info[1] < 8') def test_for_assign_raising_stop_async_iteration_2(lop): class BadIterable: def __iter__(self): diff --git a/tests/test_lazy_object_proxy.py b/tests/test_lazy_object_proxy.py index d95aa57..3c881be 100644 --- a/tests/test_lazy_object_proxy.py +++ b/tests/test_lazy_object_proxy.py @@ -1062,13 +1062,13 @@ def test_iadd(lop): assert value == 2 if lop.kind != 'simple': - assert type(value) == lop.Proxy + assert type(value) is lop.Proxy value += one assert value == 3 if lop.kind != 'simple': - assert type(value) == lop.Proxy + assert type(value) is lop.Proxy def test_isub(lop): @@ -1078,13 +1078,13 @@ def test_isub(lop): value -= 1 assert value == 0 if lop.kind != 'simple': - assert type(value) == lop.Proxy + assert type(value) is lop.Proxy value -= one assert value == -1 if lop.kind != 'simple': - assert type(value) == lop.Proxy + assert type(value) is lop.Proxy def test_imul(lop): @@ -1095,13 +1095,13 @@ def test_imul(lop): assert value == 4 if lop.kind != 'simple': - assert type(value) == lop.Proxy + assert type(value) is lop.Proxy value *= two assert value == 8 if lop.kind != 'simple': - assert type(value) == lop.Proxy + assert type(value) is lop.Proxy def test_imatmul(lop): @@ -1122,7 +1122,7 @@ def __imatmul__(self, other): assert value.value == 234 if lop.kind != 'simple': - assert type(value) == lop.Proxy + assert type(value) is lop.Proxy def test_idiv(lop): @@ -1136,13 +1136,13 @@ def test_idiv(lop): assert value == 2 / 2 if lop.kind != 'simple': - assert type(value) == lop.Proxy + assert type(value) is lop.Proxy value /= two assert value == 2 / 2 / 2 if lop.kind != 'simple': - assert type(value) == lop.Proxy + assert type(value) is lop.Proxy def test_ifloordiv(lop): @@ -1153,13 +1153,13 @@ def test_ifloordiv(lop): assert value == 2 // 2 if lop.kind != 'simple': - assert type(value) == lop.Proxy + assert type(value) is lop.Proxy value //= two assert value == 2 // 2 // 2 if lop.kind != 'simple': - assert type(value) == lop.Proxy + assert type(value) is lop.Proxy def test_imod(lop): @@ -1170,13 +1170,13 @@ def test_imod(lop): assert value == 10 % 2 if lop.kind != 'simple': - assert type(value) == lop.Proxy + assert type(value) is lop.Proxy value %= two assert value == 10 % 2 % 2 if lop.kind != 'simple': - assert type(value) == lop.Proxy + assert type(value) is lop.Proxy def test_ipow(lop): @@ -1187,13 +1187,13 @@ def test_ipow(lop): assert value == 10**2 if lop.kind != 'simple': - assert type(value) == lop.Proxy + assert type(value) is lop.Proxy value **= two assert value == 10**2**2 if lop.kind != 'simple': - assert type(value) == lop.Proxy + assert type(value) is lop.Proxy def test_ilshift(lop): @@ -1204,13 +1204,13 @@ def test_ilshift(lop): assert value == 256 << 2 if lop.kind != 'simple': - assert type(value) == lop.Proxy + assert type(value) is lop.Proxy value <<= two assert value == 256 << 2 << 2 if lop.kind != 'simple': - assert type(value) == lop.Proxy + assert type(value) is lop.Proxy def test_irshift(lop): @@ -1221,13 +1221,13 @@ def test_irshift(lop): assert value == 2 >> 2 if lop.kind != 'simple': - assert type(value) == lop.Proxy + assert type(value) is lop.Proxy value >>= two assert value == 2 >> 2 >> 2 if lop.kind != 'simple': - assert type(value) == lop.Proxy + assert type(value) is lop.Proxy def test_iand(lop): @@ -1238,13 +1238,13 @@ def test_iand(lop): assert value == 1 & 2 if lop.kind != 'simple': - assert type(value) == lop.Proxy + assert type(value) is lop.Proxy value &= two assert value == 1 & 2 & 2 if lop.kind != 'simple': - assert type(value) == lop.Proxy + assert type(value) is lop.Proxy def test_ixor(lop): @@ -1255,13 +1255,13 @@ def test_ixor(lop): assert value == 1 ^ 2 if lop.kind != 'simple': - assert type(value) == lop.Proxy + assert type(value) is lop.Proxy value ^= two assert value == 1 ^ 2 ^ 2 if lop.kind != 'simple': - assert type(value) == lop.Proxy + assert type(value) is lop.Proxy def test_ior(lop): @@ -1272,13 +1272,13 @@ def test_ior(lop): assert value == 1 | 2 if lop.kind != 'simple': - assert type(value) == lop.Proxy + assert type(value) is lop.Proxy value |= two assert value == 1 | 2 | 2 if lop.kind != 'simple': - assert type(value) == lop.Proxy + assert type(value) is lop.Proxy def test_neg(lop): @@ -1781,7 +1781,7 @@ def trouble_maker(): @pytest.mark.skipif(platform.python_implementation() != 'CPython', reason="Interpreter doesn't have reference counting") def test_garbage_collection(lop): - leaky = lambda: "foobar" # noqa + leaky = lambda: 'foobar' # noqa proxy = lop.Proxy(leaky) leaky.leak = proxy ref = weakref.ref(leaky) From 47062396a89669e112d6074227a6276c6a9564ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ionel=20Cristian=20M=C4=83rie=C8=99?= Date: Wed, 20 Nov 2024 16:53:47 +0200 Subject: [PATCH 16/33] Up ci conf. --- .github/workflows/github-actions.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml index a507797..5d7d369 100644 --- a/.github/workflows/github-actions.yml +++ b/.github/workflows/github-actions.yml @@ -440,6 +440,11 @@ jobs: pip --version tox --version pip list --format=freeze + - name: install dependencies (gdb) + if: > + !matrix.cibw_build && matrix.os == 'ubuntu' + run: > + sudo apt-get install gdb - name: cibw build and test if: matrix.cibw_build run: cibuildwheel From 499a92bd269546a4b295dd62f039b6fc1e87c1ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ionel=20Cristian=20M=C4=83rie=C8=99?= Date: Wed, 20 Nov 2024 17:06:13 +0200 Subject: [PATCH 17/33] Allow building on 3.13 freetreading python. --- src/lazy_object_proxy/cext.c | 8 ++++++-- tox.ini | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/lazy_object_proxy/cext.c b/src/lazy_object_proxy/cext.c index 4bb755f..f6935e6 100644 --- a/src/lazy_object_proxy/cext.c +++ b/src/lazy_object_proxy/cext.c @@ -1435,8 +1435,12 @@ moduleinit(void) return NULL; Py_INCREF(&Proxy_Type); - PyModule_AddObject(module, "Proxy", - (PyObject *)&Proxy_Type); + PyModule_AddObject(module, "Proxy", (PyObject *)&Proxy_Type); + +#ifdef Py_GIL_DISABLED + PyUnstable_Module_SetGIL(module, Py_MOD_GIL_NOT_USED); +#endif + return module; } diff --git a/tox.ini b/tox.ini index 37b2254..3c6c6af 100644 --- a/tox.ini +++ b/tox.ini @@ -14,7 +14,7 @@ envlist = clean, check, docs, - {py39,py310,py311,py312,pypy39,pypy310}-{cover,nocov}, + {py39,py310,py311,py312,py312t,pypy39,pypy310}-{cover,nocov}, report ignore_basepython_conflict = true @@ -26,6 +26,7 @@ basepython = py310: {env:TOXPYTHON:python3.10} py311: {env:TOXPYTHON:python3.11} py312: {env:TOXPYTHON:python3.12} + py313t: {env:TOXPYTHON:python3.13t} {bootstrap,clean,check,report,docs,codecov,coveralls,extension-coveralls}: {env:TOXPYTHON:python3} setenv = PYTHONPATH={toxinidir}/tests From 54ea75569944a0521b286647e82742c9ba3dd1f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ionel=20Cristian=20M=C4=83rie=C8=99?= Date: Wed, 20 Nov 2024 17:28:43 +0200 Subject: [PATCH 18/33] Add 3.13 to ci. --- .github/workflows/github-actions.yml | 187 ++++++++++++++++++ .../.github/workflows/github-actions.yml | 7 +- setup.py | 1 + tox.ini | 5 +- 4 files changed, 196 insertions(+), 4 deletions(-) diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml index 5d7d369..9a0e520 100644 --- a/.github/workflows/github-actions.yml +++ b/.github/workflows/github-actions.yml @@ -53,6 +53,7 @@ jobs: tox_env: 'py39-nocov' cibw_arch: 'x86_64' cibw_build: 'cp39-*manylinux*' + cibw_ft: 'false' os: 'ubuntu-latest' - name: 'py39-nocov (ubuntu/x86_64/musllinux)' python: '3.9' @@ -61,6 +62,7 @@ jobs: tox_env: 'py39-nocov' cibw_arch: 'x86_64' cibw_build: 'cp39-*musllinux*' + cibw_ft: 'false' os: 'ubuntu-latest' - name: 'py39-nocov (ubuntu/aarch64/manylinux)' python: '3.9' @@ -69,6 +71,7 @@ jobs: tox_env: 'py39-nocov' cibw_arch: 'aarch64' cibw_build: 'cp39-*manylinux*' + cibw_ft: 'false' os: 'ubuntu-latest' - name: 'py39-nocov (ubuntu/aarch64/musllinux)' python: '3.9' @@ -77,6 +80,7 @@ jobs: tox_env: 'py39-nocov' cibw_arch: 'aarch64' cibw_build: 'cp39-*musllinux*' + cibw_ft: 'false' os: 'ubuntu-latest' - name: 'py39-nocov (windows/AMD64)' python: '3.9' @@ -85,6 +89,7 @@ jobs: tox_env: 'py39-nocov' cibw_arch: 'AMD64' cibw_build: 'cp39-*' + cibw_ft: 'false' os: 'windows-latest' - name: 'py39-nocov (macos/arm64)' python: '3.9' @@ -93,6 +98,7 @@ jobs: tox_env: 'py39-nocov' cibw_arch: 'arm64' cibw_build: 'cp39-*' + cibw_ft: 'false' os: 'macos-latest' - name: 'py310-cover (ubuntu/x86_64)' python: '3.10' @@ -128,6 +134,7 @@ jobs: tox_env: 'py310-nocov' cibw_arch: 'x86_64' cibw_build: 'cp310-*manylinux*' + cibw_ft: 'false' os: 'ubuntu-latest' - name: 'py310-nocov (ubuntu/x86_64/musllinux)' python: '3.10' @@ -136,6 +143,7 @@ jobs: tox_env: 'py310-nocov' cibw_arch: 'x86_64' cibw_build: 'cp310-*musllinux*' + cibw_ft: 'false' os: 'ubuntu-latest' - name: 'py310-nocov (ubuntu/aarch64/manylinux)' python: '3.10' @@ -144,6 +152,7 @@ jobs: tox_env: 'py310-nocov' cibw_arch: 'aarch64' cibw_build: 'cp310-*manylinux*' + cibw_ft: 'false' os: 'ubuntu-latest' - name: 'py310-nocov (ubuntu/aarch64/musllinux)' python: '3.10' @@ -152,6 +161,7 @@ jobs: tox_env: 'py310-nocov' cibw_arch: 'aarch64' cibw_build: 'cp310-*musllinux*' + cibw_ft: 'false' os: 'ubuntu-latest' - name: 'py310-nocov (windows/AMD64)' python: '3.10' @@ -160,6 +170,7 @@ jobs: tox_env: 'py310-nocov' cibw_arch: 'AMD64' cibw_build: 'cp310-*' + cibw_ft: 'false' os: 'windows-latest' - name: 'py310-nocov (macos/arm64)' python: '3.10' @@ -168,6 +179,7 @@ jobs: tox_env: 'py310-nocov' cibw_arch: 'arm64' cibw_build: 'cp310-*' + cibw_ft: 'false' os: 'macos-latest' - name: 'py311-cover (ubuntu/x86_64)' python: '3.11' @@ -203,6 +215,7 @@ jobs: tox_env: 'py311-nocov' cibw_arch: 'x86_64' cibw_build: 'cp311-*manylinux*' + cibw_ft: 'false' os: 'ubuntu-latest' - name: 'py311-nocov (ubuntu/x86_64/musllinux)' python: '3.11' @@ -211,6 +224,7 @@ jobs: tox_env: 'py311-nocov' cibw_arch: 'x86_64' cibw_build: 'cp311-*musllinux*' + cibw_ft: 'false' os: 'ubuntu-latest' - name: 'py311-nocov (ubuntu/aarch64/manylinux)' python: '3.11' @@ -219,6 +233,7 @@ jobs: tox_env: 'py311-nocov' cibw_arch: 'aarch64' cibw_build: 'cp311-*manylinux*' + cibw_ft: 'false' os: 'ubuntu-latest' - name: 'py311-nocov (ubuntu/aarch64/musllinux)' python: '3.11' @@ -227,6 +242,7 @@ jobs: tox_env: 'py311-nocov' cibw_arch: 'aarch64' cibw_build: 'cp311-*musllinux*' + cibw_ft: 'false' os: 'ubuntu-latest' - name: 'py311-nocov (windows/AMD64)' python: '3.11' @@ -235,6 +251,7 @@ jobs: tox_env: 'py311-nocov' cibw_arch: 'AMD64' cibw_build: 'cp311-*' + cibw_ft: 'false' os: 'windows-latest' - name: 'py311-nocov (macos/arm64)' python: '3.11' @@ -243,6 +260,7 @@ jobs: tox_env: 'py311-nocov' cibw_arch: 'arm64' cibw_build: 'cp311-*' + cibw_ft: 'false' os: 'macos-latest' - name: 'py312-cover (ubuntu/x86_64)' python: '3.12' @@ -278,6 +296,7 @@ jobs: tox_env: 'py312-nocov' cibw_arch: 'x86_64' cibw_build: 'cp312-*manylinux*' + cibw_ft: 'false' os: 'ubuntu-latest' - name: 'py312-nocov (ubuntu/x86_64/musllinux)' python: '3.12' @@ -286,6 +305,7 @@ jobs: tox_env: 'py312-nocov' cibw_arch: 'x86_64' cibw_build: 'cp312-*musllinux*' + cibw_ft: 'false' os: 'ubuntu-latest' - name: 'py312-nocov (ubuntu/aarch64/manylinux)' python: '3.12' @@ -294,6 +314,7 @@ jobs: tox_env: 'py312-nocov' cibw_arch: 'aarch64' cibw_build: 'cp312-*manylinux*' + cibw_ft: 'false' os: 'ubuntu-latest' - name: 'py312-nocov (ubuntu/aarch64/musllinux)' python: '3.12' @@ -302,6 +323,7 @@ jobs: tox_env: 'py312-nocov' cibw_arch: 'aarch64' cibw_build: 'cp312-*musllinux*' + cibw_ft: 'false' os: 'ubuntu-latest' - name: 'py312-nocov (windows/AMD64)' python: '3.12' @@ -310,6 +332,7 @@ jobs: tox_env: 'py312-nocov' cibw_arch: 'AMD64' cibw_build: 'cp312-*' + cibw_ft: 'false' os: 'windows-latest' - name: 'py312-nocov (macos/arm64)' python: '3.12' @@ -318,6 +341,169 @@ jobs: tox_env: 'py312-nocov' cibw_arch: 'arm64' cibw_build: 'cp312-*' + cibw_ft: 'false' + os: 'macos-latest' + - name: 'py313-cover (ubuntu/x86_64)' + python: '3.13' + toxpython: 'python3.13' + python_arch: 'x64' + tox_env: 'py313-cover' + cover: true + cibw_arch: 'x86_64' + cibw_build: false + os: 'ubuntu-latest' + - name: 'py313-cover (windows/AMD64)' + python: '3.13' + toxpython: 'python3.13' + python_arch: 'x64' + tox_env: 'py313-cover' + cover: true + cibw_arch: 'AMD64' + cibw_build: false + os: 'windows-latest' + - name: 'py313-cover (macos/arm64)' + python: '3.13' + toxpython: 'python3.13' + python_arch: 'arm64' + tox_env: 'py313-cover' + cover: true + cibw_arch: 'arm64' + cibw_build: false + os: 'macos-latest' + - name: 'py313-nocov (ubuntu/x86_64/manylinux)' + python: '3.13' + toxpython: 'python3.13' + python_arch: 'x64' + tox_env: 'py313-nocov' + cibw_arch: 'x86_64' + cibw_build: 'cp313-*manylinux*' + cibw_ft: 'false' + os: 'ubuntu-latest' + - name: 'py313-nocov (ubuntu/x86_64/musllinux)' + python: '3.13' + toxpython: 'python3.13' + python_arch: 'x64' + tox_env: 'py313-nocov' + cibw_arch: 'x86_64' + cibw_build: 'cp313-*musllinux*' + cibw_ft: 'false' + os: 'ubuntu-latest' + - name: 'py313-nocov (ubuntu/aarch64/manylinux)' + python: '3.13' + toxpython: 'python3.13' + python_arch: 'x64' + tox_env: 'py313-nocov' + cibw_arch: 'aarch64' + cibw_build: 'cp313-*manylinux*' + cibw_ft: 'false' + os: 'ubuntu-latest' + - name: 'py313-nocov (ubuntu/aarch64/musllinux)' + python: '3.13' + toxpython: 'python3.13' + python_arch: 'x64' + tox_env: 'py313-nocov' + cibw_arch: 'aarch64' + cibw_build: 'cp313-*musllinux*' + cibw_ft: 'false' + os: 'ubuntu-latest' + - name: 'py313-nocov (windows/AMD64)' + python: '3.13' + toxpython: 'python3.13' + python_arch: 'x64' + tox_env: 'py313-nocov' + cibw_arch: 'AMD64' + cibw_build: 'cp313-*' + cibw_ft: 'false' + os: 'windows-latest' + - name: 'py313-nocov (macos/arm64)' + python: '3.13' + toxpython: 'python3.13' + python_arch: 'arm64' + tox_env: 'py313-nocov' + cibw_arch: 'arm64' + cibw_build: 'cp313-*' + cibw_ft: 'false' + os: 'macos-latest' + - name: 'py313ft-cover (ubuntu/x86_64)' + python: '3.13ft' + toxpython: 'python3.13ft' + python_arch: 'x64-freethreaded' + tox_env: 'py313ft-cover' + cover: true + cibw_arch: 'x86_64' + cibw_build: false + os: 'ubuntu-latest' + - name: 'py313ft-cover (windows/AMD64)' + python: '3.13ft' + toxpython: 'python3.13ft' + python_arch: 'x64-freethreaded' + tox_env: 'py313ft-cover' + cover: true + cibw_arch: 'AMD64' + cibw_build: false + os: 'windows-latest' + - name: 'py313ft-cover (macos/arm64)' + python: '3.13ft' + toxpython: 'python3.13ft' + python_arch: 'arm64-freethreaded' + tox_env: 'py313ft-cover' + cover: true + cibw_arch: 'arm64' + cibw_build: false + os: 'macos-latest' + - name: 'py313ft-nocov (ubuntu/x86_64/manylinux)' + python: '3.13ft' + toxpython: 'python3.13ft' + python_arch: 'x64-freethreaded' + tox_env: 'py313ft-nocov' + cibw_arch: 'x86_64' + cibw_build: 'cp313ftt-*manylinux*' + cibw_ft: 'true' + os: 'ubuntu-latest' + - name: 'py313ft-nocov (ubuntu/x86_64/musllinux)' + python: '3.13ft' + toxpython: 'python3.13ft' + python_arch: 'x64-freethreaded' + tox_env: 'py313ft-nocov' + cibw_arch: 'x86_64' + cibw_build: 'cp313ftt-*musllinux*' + cibw_ft: 'true' + os: 'ubuntu-latest' + - name: 'py313ft-nocov (ubuntu/aarch64/manylinux)' + python: '3.13ft' + toxpython: 'python3.13ft' + python_arch: 'x64-freethreaded' + tox_env: 'py313ft-nocov' + cibw_arch: 'aarch64' + cibw_build: 'cp313ftt-*manylinux*' + cibw_ft: 'true' + os: 'ubuntu-latest' + - name: 'py313ft-nocov (ubuntu/aarch64/musllinux)' + python: '3.13ft' + toxpython: 'python3.13ft' + python_arch: 'x64-freethreaded' + tox_env: 'py313ft-nocov' + cibw_arch: 'aarch64' + cibw_build: 'cp313ftt-*musllinux*' + cibw_ft: 'true' + os: 'ubuntu-latest' + - name: 'py313ft-nocov (windows/AMD64)' + python: '3.13ft' + toxpython: 'python3.13ft' + python_arch: 'x64-freethreaded' + tox_env: 'py313ft-nocov' + cibw_arch: 'AMD64' + cibw_build: 'cp313ftt-*' + cibw_ft: 'true' + os: 'windows-latest' + - name: 'py313ft-nocov (macos/arm64)' + python: '3.13ft' + toxpython: 'python3.13ft' + python_arch: 'arm64-freethreaded' + tox_env: 'py313ft-nocov' + cibw_arch: 'arm64' + cibw_build: 'cp313ftt-*' + cibw_ft: 'true' os: 'macos-latest' - name: 'pypy39-cover (ubuntu/x86_64)' python: 'pypy-3.9' @@ -452,6 +638,7 @@ jobs: TOXPYTHON: '${{ matrix.toxpython }}' CIBW_ARCHS: '${{ matrix.cibw_arch }}' CIBW_BUILD: '${{ matrix.cibw_build }}' + CIBW_FREE_THREADED_SUPPORT: '${{ matrix.cibw_ft }}' CIBW_BUILD_VERBOSITY: '3' CIBW_TEST_REQUIRES: > tox diff --git a/ci/templates/.github/workflows/github-actions.yml b/ci/templates/.github/workflows/github-actions.yml index fb89fec..2735dbd 100644 --- a/ci/templates/.github/workflows/github-actions.yml +++ b/ci/templates/.github/workflows/github-actions.yml @@ -21,6 +21,7 @@ jobs: os: 'ubuntu-latest' {% for env in tox_environments %} {% set prefix = env.split('-')[0] -%} +{% set nogil = 'ft' in env %} {% if prefix.startswith('pypy') %} {% set python %}pypy-{{ prefix[4] }}.{{ prefix[5:] }}{% endset %} {% set cpython %}pp{{ prefix[4:5] }}{% endset %} @@ -44,14 +45,15 @@ jobs: - name: '{{ env }} ({{ os }}/{{ cibw_arch }}{{ name_suffix }})' python: '{{ python }}' toxpython: '{{ toxpython }}' - python_arch: '{{ python_arch }}' + python_arch: '{{ python_arch }}{% if nogil %}-freethreaded{% endif %}' tox_env: '{{ env }}' {% if 'cover' in env %} cover: true {% endif %} cibw_arch: '{{ cibw_arch }}' {% if 'nocov' in env and not prefix.startswith('pypy') %} - cibw_build: '{{ cpython }}-{{ wheel_arch }}' + cibw_build: '{{ cpython }}{% if nogil %}t{% endif %}-{{ wheel_arch }}' + cibw_ft: '{% if nogil %}true{% else %}false{% endif %}' {% else %} cibw_build: false {% endif %} @@ -90,6 +92,7 @@ jobs: TOXPYTHON: '{{ '${{ matrix.toxpython }}' }}' CIBW_ARCHS: '{{ '${{ matrix.cibw_arch }}' }}' CIBW_BUILD: '{{ '${{ matrix.cibw_build }}' }}' + CIBW_FREE_THREADED_SUPPORT: '{{ '${{ matrix.cibw_ft }}' }}' CIBW_BUILD_VERBOSITY: '3' CIBW_TEST_REQUIRES: > tox diff --git a/setup.py b/setup.py index d7a0044..083dc0d 100755 --- a/setup.py +++ b/setup.py @@ -109,6 +109,7 @@ def read(*names, **kwargs): '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', 'Programming Language :: Python :: Implementation :: PyPy', # uncomment if you test on these interpreters: diff --git a/tox.ini b/tox.ini index 3c6c6af..d0c9ff8 100644 --- a/tox.ini +++ b/tox.ini @@ -14,7 +14,7 @@ envlist = clean, check, docs, - {py39,py310,py311,py312,py312t,pypy39,pypy310}-{cover,nocov}, + {py39,py310,py311,py312,py313,py313ft,pypy39,pypy310}-{cover,nocov}, report ignore_basepython_conflict = true @@ -26,7 +26,8 @@ basepython = py310: {env:TOXPYTHON:python3.10} py311: {env:TOXPYTHON:python3.11} py312: {env:TOXPYTHON:python3.12} - py313t: {env:TOXPYTHON:python3.13t} + py313: {env:TOXPYTHON:python3.13} + py313ft: {env:TOXPYTHON:python3.13t} {bootstrap,clean,check,report,docs,codecov,coveralls,extension-coveralls}: {env:TOXPYTHON:python3} setenv = PYTHONPATH={toxinidir}/tests From 49c70b2208bd754997fd5f6de79721d7042d4fb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ionel=20Cristian=20M=C4=83rie=C8=99?= Date: Wed, 20 Nov 2024 17:45:57 +0200 Subject: [PATCH 19/33] I guess I need to wait on https://github.com/actions/python-versions/pull/319 and maybe https://github.com/actions/python-versions/pull/319. --- .github/workflows/github-actions.yml | 81 ------------------- .../.github/workflows/github-actions.yml | 2 + 2 files changed, 2 insertions(+), 81 deletions(-) diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml index 9a0e520..b270c12 100644 --- a/.github/workflows/github-actions.yml +++ b/.github/workflows/github-actions.yml @@ -424,87 +424,6 @@ jobs: cibw_build: 'cp313-*' cibw_ft: 'false' os: 'macos-latest' - - name: 'py313ft-cover (ubuntu/x86_64)' - python: '3.13ft' - toxpython: 'python3.13ft' - python_arch: 'x64-freethreaded' - tox_env: 'py313ft-cover' - cover: true - cibw_arch: 'x86_64' - cibw_build: false - os: 'ubuntu-latest' - - name: 'py313ft-cover (windows/AMD64)' - python: '3.13ft' - toxpython: 'python3.13ft' - python_arch: 'x64-freethreaded' - tox_env: 'py313ft-cover' - cover: true - cibw_arch: 'AMD64' - cibw_build: false - os: 'windows-latest' - - name: 'py313ft-cover (macos/arm64)' - python: '3.13ft' - toxpython: 'python3.13ft' - python_arch: 'arm64-freethreaded' - tox_env: 'py313ft-cover' - cover: true - cibw_arch: 'arm64' - cibw_build: false - os: 'macos-latest' - - name: 'py313ft-nocov (ubuntu/x86_64/manylinux)' - python: '3.13ft' - toxpython: 'python3.13ft' - python_arch: 'x64-freethreaded' - tox_env: 'py313ft-nocov' - cibw_arch: 'x86_64' - cibw_build: 'cp313ftt-*manylinux*' - cibw_ft: 'true' - os: 'ubuntu-latest' - - name: 'py313ft-nocov (ubuntu/x86_64/musllinux)' - python: '3.13ft' - toxpython: 'python3.13ft' - python_arch: 'x64-freethreaded' - tox_env: 'py313ft-nocov' - cibw_arch: 'x86_64' - cibw_build: 'cp313ftt-*musllinux*' - cibw_ft: 'true' - os: 'ubuntu-latest' - - name: 'py313ft-nocov (ubuntu/aarch64/manylinux)' - python: '3.13ft' - toxpython: 'python3.13ft' - python_arch: 'x64-freethreaded' - tox_env: 'py313ft-nocov' - cibw_arch: 'aarch64' - cibw_build: 'cp313ftt-*manylinux*' - cibw_ft: 'true' - os: 'ubuntu-latest' - - name: 'py313ft-nocov (ubuntu/aarch64/musllinux)' - python: '3.13ft' - toxpython: 'python3.13ft' - python_arch: 'x64-freethreaded' - tox_env: 'py313ft-nocov' - cibw_arch: 'aarch64' - cibw_build: 'cp313ftt-*musllinux*' - cibw_ft: 'true' - os: 'ubuntu-latest' - - name: 'py313ft-nocov (windows/AMD64)' - python: '3.13ft' - toxpython: 'python3.13ft' - python_arch: 'x64-freethreaded' - tox_env: 'py313ft-nocov' - cibw_arch: 'AMD64' - cibw_build: 'cp313ftt-*' - cibw_ft: 'true' - os: 'windows-latest' - - name: 'py313ft-nocov (macos/arm64)' - python: '3.13ft' - toxpython: 'python3.13ft' - python_arch: 'arm64-freethreaded' - tox_env: 'py313ft-nocov' - cibw_arch: 'arm64' - cibw_build: 'cp313ftt-*' - cibw_ft: 'true' - os: 'macos-latest' - name: 'pypy39-cover (ubuntu/x86_64)' python: 'pypy-3.9' toxpython: 'pypy3.9' diff --git a/ci/templates/.github/workflows/github-actions.yml b/ci/templates/.github/workflows/github-actions.yml index 2735dbd..c2140ef 100644 --- a/ci/templates/.github/workflows/github-actions.yml +++ b/ci/templates/.github/workflows/github-actions.yml @@ -22,6 +22,7 @@ jobs: {% for env in tox_environments %} {% set prefix = env.split('-')[0] -%} {% set nogil = 'ft' in env %} +{% if not nogil %} {% if prefix.startswith('pypy') %} {% set python %}pypy-{{ prefix[4] }}.{{ prefix[5:] }}{% endset %} {% set cpython %}pp{{ prefix[4:5] }}{% endset %} @@ -60,6 +61,7 @@ jobs: os: '{{ os }}-latest' {% endif %} {% endfor %} +{% endif %} {% endfor %} steps: - uses: docker/setup-qemu-action@v3 From f33913bae9b8fc5d635bec7cffc8e7485844c668 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ionel=20Cristian=20M=C4=83rie=C8=99?= Date: Wed, 20 Nov 2024 17:58:34 +0200 Subject: [PATCH 20/33] Add support for ndigits in __round__. --- src/lazy_object_proxy/cext.c | 18 +++++++++++------- src/lazy_object_proxy/slots.py | 4 ++-- tests/test_lazy_object_proxy.py | 5 +++++ 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/lazy_object_proxy/cext.c b/src/lazy_object_proxy/cext.c index f6935e6..4867c7f 100644 --- a/src/lazy_object_proxy/cext.c +++ b/src/lazy_object_proxy/cext.c @@ -839,24 +839,28 @@ static PyObject *Proxy_reduce( /* ------------------------------------------------------------------------- */ -static PyObject *Proxy_round( - ProxyObject *self, PyObject *args) +static PyObject *Proxy_round(ProxyObject *self, PyObject *args, PyObject *kwds) { PyObject *module = NULL; - PyObject *dict = NULL; PyObject *round = NULL; + PyObject *ndigits = NULL; PyObject *result = NULL; + char *const kwlist[] = { "ndigits", NULL }; + Proxy__ENSURE_WRAPPED_OR_RETURN_NULL(self); + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:ObjectProxy", kwlist, &ndigits)) { + return NULL; + } + module = PyImport_ImportModule("builtins"); if (!module) return NULL; - dict = PyModule_GetDict(module); - round = PyDict_GetItemString(dict, "round"); + round = PyObject_GetAttrString(module, "round"); if (!round) { Py_DECREF(module); @@ -866,7 +870,7 @@ static PyObject *Proxy_round( Py_INCREF(round); Py_DECREF(module); - result = PyObject_CallFunctionObjArgs(round, self->wrapped, NULL); + result = PyObject_CallFunctionObjArgs(round, self->wrapped, ndigits, NULL); Py_DECREF(round); @@ -1324,7 +1328,7 @@ static PyMethodDef Proxy_methods[] = { { "__reduce__", (PyCFunction)Proxy_reduce, METH_NOARGS, 0 }, { "__reduce_ex__", (PyCFunction)Proxy_reduce, METH_O, 0 }, { "__fspath__", (PyCFunction)Proxy_fspath, METH_NOARGS, 0 }, - { "__round__", (PyCFunction)Proxy_round, METH_NOARGS, 0 }, + { "__round__", (PyCFunction)Proxy_round, METH_VARARGS | METH_KEYWORDS, 0 }, { "__aenter__", (PyCFunction)Proxy_aenter, METH_NOARGS, 0 }, { "__aexit__", (PyCFunction)Proxy_aexit, METH_VARARGS | METH_KEYWORDS, 0 }, { "__format__", (PyCFunction)Proxy_format, METH_VARARGS, 0 }, diff --git a/src/lazy_object_proxy/slots.py b/src/lazy_object_proxy/slots.py index eac82cc..ccb4f1c 100644 --- a/src/lazy_object_proxy/slots.py +++ b/src/lazy_object_proxy/slots.py @@ -167,8 +167,8 @@ def __fspath__(self): def __reversed__(self): return reversed(self.__wrapped__) - def __round__(self): - return round(self.__wrapped__) + def __round__(self, ndigits=None): + return round(self.__wrapped__, ndigits) def __lt__(self, other): return self.__wrapped__ < other diff --git a/tests/test_lazy_object_proxy.py b/tests/test_lazy_object_proxy.py index 3c881be..5f88394 100644 --- a/tests/test_lazy_object_proxy.py +++ b/tests/test_lazy_object_proxy.py @@ -35,6 +35,11 @@ def test_round(lop): assert round(proxy) == 1 +def test_round_ndigits(lop): + proxy = lop.Proxy(lambda: 1.49494) + assert round(proxy, 3) == 1.495 + + def test_attributes(lop): def function1(*args, **kwargs): return args, kwargs From 38795452a42a7723cf579657d63634ee8e3f6899 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ionel=20Cristian=20M=C4=83rie=C8=99?= Date: Wed, 16 Apr 2025 16:54:56 +0300 Subject: [PATCH 21/33] Update changelog. Closes #86. --- CHANGELOG.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 52a4911..2199958 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -2,6 +2,13 @@ Changelog ========= +1.11.0 (2025-04-16) +------------------- + +* Added Python 3.13 wheels. +* Added support for ``__format__``. +* Dropped support for Python 3.8. + 1.10.0 (2023-12-15) ------------------- From 49750d7ed988440069133b032a8b88d7dafd3329 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ionel=20Cristian=20M=C4=83rie=C8=99?= Date: Wed, 16 Apr 2025 17:30:03 +0300 Subject: [PATCH 22/33] Bump precommit and some actions. --- .github/workflows/github-actions.yml | 6 +++--- .pre-commit-config.yaml | 2 +- ci/templates/.github/workflows/github-actions.yml | 6 +++--- src/lazy_object_proxy/slots.py | 2 +- src/lazy_object_proxy/utils.py | 3 +-- tests/test_async_py3.py | 12 ++++++------ 6 files changed, 15 insertions(+), 16 deletions(-) diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml index b270c12..92971d0 100644 --- a/.github/workflows/github-actions.yml +++ b/.github/workflows/github-actions.yml @@ -581,7 +581,7 @@ jobs: with: parallel: true flag-name: ${{ matrix.tox_env }} - - uses: codecov/codecov-action@v3 + - uses: codecov/codecov-action@v5 if: matrix.cover with: verbose: true @@ -590,7 +590,7 @@ jobs: if: matrix.cibw_build run: twine check wheelhouse/*.whl - name: upload wheel - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: matrix.cibw_build with: path: wheelhouse/*.whl @@ -602,6 +602,6 @@ jobs: - uses: coverallsapp/github-action@v2 with: parallel-finished: true - - uses: codecov/codecov-action@v3 + - uses: codecov/codecov-action@v5 with: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0964d05..ac13451 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,7 +6,7 @@ exclude: '^(\.tox|ci/templates|\.bumpversion\.cfg)(/|$)' # Note the order is intentional to avoid multiple passes of the hooks repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.7.4 + rev: v0.11.5 hooks: - id: ruff args: [--fix, --exit-non-zero-on-fix, --show-fixes, --unsafe-fixes] diff --git a/ci/templates/.github/workflows/github-actions.yml b/ci/templates/.github/workflows/github-actions.yml index c2140ef..8e84a0b 100644 --- a/ci/templates/.github/workflows/github-actions.yml +++ b/ci/templates/.github/workflows/github-actions.yml @@ -118,7 +118,7 @@ jobs: with: parallel: true flag-name: {{ '${{ matrix.tox_env }}' }} - - uses: codecov/codecov-action@v3 + - uses: codecov/codecov-action@v5 if: matrix.cover with: verbose: true @@ -127,7 +127,7 @@ jobs: if: matrix.cibw_build run: twine check wheelhouse/*.whl - name: upload wheel - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: matrix.cibw_build with: path: wheelhouse/*.whl @@ -139,6 +139,6 @@ jobs: - uses: coverallsapp/github-action@v2 with: parallel-finished: true - - uses: codecov/codecov-action@v3 + - uses: codecov/codecov-action@v5 with: CODECOV_TOKEN: {% raw %}${{ secrets.CODECOV_TOKEN }}{% endraw %} diff --git a/src/lazy_object_proxy/slots.py b/src/lazy_object_proxy/slots.py index ccb4f1c..73bf555 100644 --- a/src/lazy_object_proxy/slots.py +++ b/src/lazy_object_proxy/slots.py @@ -77,7 +77,7 @@ class Proxy(with_metaclass(_ProxyMetaType)): * calls ``__factory__``, saves result to ``__target__`` and returns said result. """ - __slots__ = '__target__', '__factory__' + __slots__ = '__factory__', '__target__' def __init__(self, factory): object.__setattr__(self, '__factory__', factory) diff --git a/src/lazy_object_proxy/utils.py b/src/lazy_object_proxy/utils.py index 8e69787..720d768 100644 --- a/src/lazy_object_proxy/utils.py +++ b/src/lazy_object_proxy/utils.py @@ -16,8 +16,7 @@ def await_(obj): obj_type = type(obj) if ( obj_type is CoroutineType - or obj_type is GeneratorType - and bool(obj.gi_code.co_flags & CO_ITERABLE_COROUTINE) + or (obj_type is GeneratorType and bool(obj.gi_code.co_flags & CO_ITERABLE_COROUTINE)) or isinstance(obj, Awaitable) ): return do_await(obj).__await__() diff --git a/tests/test_async_py3.py b/tests/test_async_py3.py index 63a4e97..0d9450b 100644 --- a/tests/test_async_py3.py +++ b/tests/test_async_py3.py @@ -857,7 +857,7 @@ async def foo(): async with lop.Proxy(CM): pass - with pytest.raises(TypeError, match="'async with' received an object from __aenter__ " 'that does not implement __await__: int'): + with pytest.raises(TypeError, match="'async with' received an object from __aenter__ that does not implement __await__: int"): # it's important that __aexit__ wasn't called run_async(lop.Proxy(foo)) @@ -879,7 +879,7 @@ async def foo(): try: run_async(lop.Proxy(foo)) except TypeError as exc: - assert re.search("'async with' received an object from __aexit__ " 'that does not implement __await__: int', exc.args[0]) + assert re.search("'async with' received an object from __aexit__ that does not implement __await__: int", exc.args[0]) assert exc.__context__ is not None assert isinstance(exc.__context__, ZeroDivisionError) else: @@ -903,7 +903,7 @@ async def foo(): async with lop.Proxy(CM): CNT += 1 - with pytest.raises(TypeError, match="'async with' received an object from __aexit__ " 'that does not implement __await__: int'): + with pytest.raises(TypeError, match="'async with' received an object from __aexit__ that does not implement __await__: int"): run_async(lop.Proxy(foo)) assert CNT == 1 @@ -915,7 +915,7 @@ async def foo(): CNT += 1 break - with pytest.raises(TypeError, match="'async with' received an object from __aexit__ " 'that does not implement __await__: int'): + with pytest.raises(TypeError, match="'async with' received an object from __aexit__ that does not implement __await__: int"): run_async(lop.Proxy(foo)) assert CNT == 2 @@ -927,7 +927,7 @@ async def foo(): CNT += 1 continue - with pytest.raises(TypeError, match="'async with' received an object from __aexit__ " 'that does not implement __await__: int'): + with pytest.raises(TypeError, match="'async with' received an object from __aexit__ that does not implement __await__: int"): run_async(lop.Proxy(foo)) assert CNT == 3 @@ -938,7 +938,7 @@ async def foo(): CNT += 1 return - with pytest.raises(TypeError, match="'async with' received an object from __aexit__ " 'that does not implement __await__: int'): + with pytest.raises(TypeError, match="'async with' received an object from __aexit__ that does not implement __await__: int"): run_async(lop.Proxy(foo)) assert CNT == 4 From e1b16d648e1a581cc8ce8c053fa3c6a695b5aaa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ionel=20Cristian=20M=C4=83rie=C8=99?= Date: Wed, 16 Apr 2025 17:38:54 +0300 Subject: [PATCH 23/33] Add the freethread envs. --- .github/workflows/github-actions.yml | 81 +++++++++++++++++++ .../.github/workflows/github-actions.yml | 2 - 2 files changed, 81 insertions(+), 2 deletions(-) diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml index 92971d0..173b749 100644 --- a/.github/workflows/github-actions.yml +++ b/.github/workflows/github-actions.yml @@ -424,6 +424,87 @@ jobs: cibw_build: 'cp313-*' cibw_ft: 'false' os: 'macos-latest' + - name: 'py313ft-cover (ubuntu/x86_64)' + python: '3.13ft' + toxpython: 'python3.13ft' + python_arch: 'x64-freethreaded' + tox_env: 'py313ft-cover' + cover: true + cibw_arch: 'x86_64' + cibw_build: false + os: 'ubuntu-latest' + - name: 'py313ft-cover (windows/AMD64)' + python: '3.13ft' + toxpython: 'python3.13ft' + python_arch: 'x64-freethreaded' + tox_env: 'py313ft-cover' + cover: true + cibw_arch: 'AMD64' + cibw_build: false + os: 'windows-latest' + - name: 'py313ft-cover (macos/arm64)' + python: '3.13ft' + toxpython: 'python3.13ft' + python_arch: 'arm64-freethreaded' + tox_env: 'py313ft-cover' + cover: true + cibw_arch: 'arm64' + cibw_build: false + os: 'macos-latest' + - name: 'py313ft-nocov (ubuntu/x86_64/manylinux)' + python: '3.13ft' + toxpython: 'python3.13ft' + python_arch: 'x64-freethreaded' + tox_env: 'py313ft-nocov' + cibw_arch: 'x86_64' + cibw_build: 'cp313ftt-*manylinux*' + cibw_ft: 'true' + os: 'ubuntu-latest' + - name: 'py313ft-nocov (ubuntu/x86_64/musllinux)' + python: '3.13ft' + toxpython: 'python3.13ft' + python_arch: 'x64-freethreaded' + tox_env: 'py313ft-nocov' + cibw_arch: 'x86_64' + cibw_build: 'cp313ftt-*musllinux*' + cibw_ft: 'true' + os: 'ubuntu-latest' + - name: 'py313ft-nocov (ubuntu/aarch64/manylinux)' + python: '3.13ft' + toxpython: 'python3.13ft' + python_arch: 'x64-freethreaded' + tox_env: 'py313ft-nocov' + cibw_arch: 'aarch64' + cibw_build: 'cp313ftt-*manylinux*' + cibw_ft: 'true' + os: 'ubuntu-latest' + - name: 'py313ft-nocov (ubuntu/aarch64/musllinux)' + python: '3.13ft' + toxpython: 'python3.13ft' + python_arch: 'x64-freethreaded' + tox_env: 'py313ft-nocov' + cibw_arch: 'aarch64' + cibw_build: 'cp313ftt-*musllinux*' + cibw_ft: 'true' + os: 'ubuntu-latest' + - name: 'py313ft-nocov (windows/AMD64)' + python: '3.13ft' + toxpython: 'python3.13ft' + python_arch: 'x64-freethreaded' + tox_env: 'py313ft-nocov' + cibw_arch: 'AMD64' + cibw_build: 'cp313ftt-*' + cibw_ft: 'true' + os: 'windows-latest' + - name: 'py313ft-nocov (macos/arm64)' + python: '3.13ft' + toxpython: 'python3.13ft' + python_arch: 'arm64-freethreaded' + tox_env: 'py313ft-nocov' + cibw_arch: 'arm64' + cibw_build: 'cp313ftt-*' + cibw_ft: 'true' + os: 'macos-latest' - name: 'pypy39-cover (ubuntu/x86_64)' python: 'pypy-3.9' toxpython: 'pypy3.9' diff --git a/ci/templates/.github/workflows/github-actions.yml b/ci/templates/.github/workflows/github-actions.yml index 8e84a0b..f080595 100644 --- a/ci/templates/.github/workflows/github-actions.yml +++ b/ci/templates/.github/workflows/github-actions.yml @@ -22,7 +22,6 @@ jobs: {% for env in tox_environments %} {% set prefix = env.split('-')[0] -%} {% set nogil = 'ft' in env %} -{% if not nogil %} {% if prefix.startswith('pypy') %} {% set python %}pypy-{{ prefix[4] }}.{{ prefix[5:] }}{% endset %} {% set cpython %}pp{{ prefix[4:5] }}{% endset %} @@ -61,7 +60,6 @@ jobs: os: '{{ os }}-latest' {% endif %} {% endfor %} -{% endif %} {% endfor %} steps: - uses: docker/setup-qemu-action@v3 From 1ebcd22a9dc5112812ce6af961cbd5193326821b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ionel=20Cristian=20M=C4=83rie=C8=99?= Date: Wed, 16 Apr 2025 17:43:33 +0300 Subject: [PATCH 24/33] Do not set binary dist if exts are disabled. --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 083dc0d..df3c0c4 100755 --- a/setup.py +++ b/setup.py @@ -151,5 +151,5 @@ def read(*names, **kwargs): ] if allow_extensions else [], - distclass=BinaryDistribution, + distclass=BinaryDistribution if allow_extensions else None, ) From 9c38dc24ce4960eba3fc01b75e0e7b24c3d5dff5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ionel=20Cristian=20M=C4=83rie=C8=99?= Date: Wed, 16 Apr 2025 17:49:26 +0300 Subject: [PATCH 25/33] Add long_description_content_type. --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index df3c0c4..fdfbd9a 100755 --- a/setup.py +++ b/setup.py @@ -86,6 +86,7 @@ def read(*names, **kwargs): re.compile('^.. start-badges.*^.. end-badges', re.M | re.S).sub('', read('README.rst')), re.sub(':[a-z]+:`~?(.*?)`', r'``\1``', read('CHANGELOG.rst')), ), + long_description_content_type='text/x-rst', author='Ionel Cristian Mărieș', author_email='contact@ionelmc.ro', url='https://github.com/ionelmc/python-lazy-object-proxy', From 28be66870808eeee992b4e1c897a5ecbbf9472eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ionel=20Cristian=20M=C4=83rie=C8=99?= Date: Wed, 16 Apr 2025 17:52:31 +0300 Subject: [PATCH 26/33] Use unique actifact name. --- .github/workflows/github-actions.yml | 70 +++++++++++++++++++ .../.github/workflows/github-actions.yml | 6 ++ 2 files changed, 76 insertions(+) diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml index 173b749..837c44c 100644 --- a/.github/workflows/github-actions.yml +++ b/.github/workflows/github-actions.yml @@ -20,6 +20,7 @@ jobs: tox_env: 'docs' os: 'ubuntu-latest' - name: 'py39-cover (ubuntu/x86_64)' + artifact: 'py39-ubuntu-x86_64' python: '3.9' toxpython: 'python3.9' python_arch: 'x64' @@ -29,6 +30,7 @@ jobs: cibw_build: false os: 'ubuntu-latest' - name: 'py39-cover (windows/AMD64)' + artifact: 'py39-windows-AMD64' python: '3.9' toxpython: 'python3.9' python_arch: 'x64' @@ -38,6 +40,7 @@ jobs: cibw_build: false os: 'windows-latest' - name: 'py39-cover (macos/arm64)' + artifact: 'py39-macos-arm64' python: '3.9' toxpython: 'python3.9' python_arch: 'arm64' @@ -47,6 +50,7 @@ jobs: cibw_build: false os: 'macos-latest' - name: 'py39-nocov (ubuntu/x86_64/manylinux)' + artifact: 'py39-ubuntu-x86_64-manylinux' python: '3.9' toxpython: 'python3.9' python_arch: 'x64' @@ -56,6 +60,7 @@ jobs: cibw_ft: 'false' os: 'ubuntu-latest' - name: 'py39-nocov (ubuntu/x86_64/musllinux)' + artifact: 'py39-ubuntu-x86_64-musllinux' python: '3.9' toxpython: 'python3.9' python_arch: 'x64' @@ -65,6 +70,7 @@ jobs: cibw_ft: 'false' os: 'ubuntu-latest' - name: 'py39-nocov (ubuntu/aarch64/manylinux)' + artifact: 'py39-ubuntu-aarch64-manylinux' python: '3.9' toxpython: 'python3.9' python_arch: 'x64' @@ -74,6 +80,7 @@ jobs: cibw_ft: 'false' os: 'ubuntu-latest' - name: 'py39-nocov (ubuntu/aarch64/musllinux)' + artifact: 'py39-ubuntu-aarch64-musllinux' python: '3.9' toxpython: 'python3.9' python_arch: 'x64' @@ -83,6 +90,7 @@ jobs: cibw_ft: 'false' os: 'ubuntu-latest' - name: 'py39-nocov (windows/AMD64)' + artifact: 'py39-windows-AMD64' python: '3.9' toxpython: 'python3.9' python_arch: 'x64' @@ -92,6 +100,7 @@ jobs: cibw_ft: 'false' os: 'windows-latest' - name: 'py39-nocov (macos/arm64)' + artifact: 'py39-macos-arm64' python: '3.9' toxpython: 'python3.9' python_arch: 'arm64' @@ -101,6 +110,7 @@ jobs: cibw_ft: 'false' os: 'macos-latest' - name: 'py310-cover (ubuntu/x86_64)' + artifact: 'py310-ubuntu-x86_64' python: '3.10' toxpython: 'python3.10' python_arch: 'x64' @@ -110,6 +120,7 @@ jobs: cibw_build: false os: 'ubuntu-latest' - name: 'py310-cover (windows/AMD64)' + artifact: 'py310-windows-AMD64' python: '3.10' toxpython: 'python3.10' python_arch: 'x64' @@ -119,6 +130,7 @@ jobs: cibw_build: false os: 'windows-latest' - name: 'py310-cover (macos/arm64)' + artifact: 'py310-macos-arm64' python: '3.10' toxpython: 'python3.10' python_arch: 'arm64' @@ -128,6 +140,7 @@ jobs: cibw_build: false os: 'macos-latest' - name: 'py310-nocov (ubuntu/x86_64/manylinux)' + artifact: 'py310-ubuntu-x86_64-manylinux' python: '3.10' toxpython: 'python3.10' python_arch: 'x64' @@ -137,6 +150,7 @@ jobs: cibw_ft: 'false' os: 'ubuntu-latest' - name: 'py310-nocov (ubuntu/x86_64/musllinux)' + artifact: 'py310-ubuntu-x86_64-musllinux' python: '3.10' toxpython: 'python3.10' python_arch: 'x64' @@ -146,6 +160,7 @@ jobs: cibw_ft: 'false' os: 'ubuntu-latest' - name: 'py310-nocov (ubuntu/aarch64/manylinux)' + artifact: 'py310-ubuntu-aarch64-manylinux' python: '3.10' toxpython: 'python3.10' python_arch: 'x64' @@ -155,6 +170,7 @@ jobs: cibw_ft: 'false' os: 'ubuntu-latest' - name: 'py310-nocov (ubuntu/aarch64/musllinux)' + artifact: 'py310-ubuntu-aarch64-musllinux' python: '3.10' toxpython: 'python3.10' python_arch: 'x64' @@ -164,6 +180,7 @@ jobs: cibw_ft: 'false' os: 'ubuntu-latest' - name: 'py310-nocov (windows/AMD64)' + artifact: 'py310-windows-AMD64' python: '3.10' toxpython: 'python3.10' python_arch: 'x64' @@ -173,6 +190,7 @@ jobs: cibw_ft: 'false' os: 'windows-latest' - name: 'py310-nocov (macos/arm64)' + artifact: 'py310-macos-arm64' python: '3.10' toxpython: 'python3.10' python_arch: 'arm64' @@ -182,6 +200,7 @@ jobs: cibw_ft: 'false' os: 'macos-latest' - name: 'py311-cover (ubuntu/x86_64)' + artifact: 'py311-ubuntu-x86_64' python: '3.11' toxpython: 'python3.11' python_arch: 'x64' @@ -191,6 +210,7 @@ jobs: cibw_build: false os: 'ubuntu-latest' - name: 'py311-cover (windows/AMD64)' + artifact: 'py311-windows-AMD64' python: '3.11' toxpython: 'python3.11' python_arch: 'x64' @@ -200,6 +220,7 @@ jobs: cibw_build: false os: 'windows-latest' - name: 'py311-cover (macos/arm64)' + artifact: 'py311-macos-arm64' python: '3.11' toxpython: 'python3.11' python_arch: 'arm64' @@ -209,6 +230,7 @@ jobs: cibw_build: false os: 'macos-latest' - name: 'py311-nocov (ubuntu/x86_64/manylinux)' + artifact: 'py311-ubuntu-x86_64-manylinux' python: '3.11' toxpython: 'python3.11' python_arch: 'x64' @@ -218,6 +240,7 @@ jobs: cibw_ft: 'false' os: 'ubuntu-latest' - name: 'py311-nocov (ubuntu/x86_64/musllinux)' + artifact: 'py311-ubuntu-x86_64-musllinux' python: '3.11' toxpython: 'python3.11' python_arch: 'x64' @@ -227,6 +250,7 @@ jobs: cibw_ft: 'false' os: 'ubuntu-latest' - name: 'py311-nocov (ubuntu/aarch64/manylinux)' + artifact: 'py311-ubuntu-aarch64-manylinux' python: '3.11' toxpython: 'python3.11' python_arch: 'x64' @@ -236,6 +260,7 @@ jobs: cibw_ft: 'false' os: 'ubuntu-latest' - name: 'py311-nocov (ubuntu/aarch64/musllinux)' + artifact: 'py311-ubuntu-aarch64-musllinux' python: '3.11' toxpython: 'python3.11' python_arch: 'x64' @@ -245,6 +270,7 @@ jobs: cibw_ft: 'false' os: 'ubuntu-latest' - name: 'py311-nocov (windows/AMD64)' + artifact: 'py311-windows-AMD64' python: '3.11' toxpython: 'python3.11' python_arch: 'x64' @@ -254,6 +280,7 @@ jobs: cibw_ft: 'false' os: 'windows-latest' - name: 'py311-nocov (macos/arm64)' + artifact: 'py311-macos-arm64' python: '3.11' toxpython: 'python3.11' python_arch: 'arm64' @@ -263,6 +290,7 @@ jobs: cibw_ft: 'false' os: 'macos-latest' - name: 'py312-cover (ubuntu/x86_64)' + artifact: 'py312-ubuntu-x86_64' python: '3.12' toxpython: 'python3.12' python_arch: 'x64' @@ -272,6 +300,7 @@ jobs: cibw_build: false os: 'ubuntu-latest' - name: 'py312-cover (windows/AMD64)' + artifact: 'py312-windows-AMD64' python: '3.12' toxpython: 'python3.12' python_arch: 'x64' @@ -281,6 +310,7 @@ jobs: cibw_build: false os: 'windows-latest' - name: 'py312-cover (macos/arm64)' + artifact: 'py312-macos-arm64' python: '3.12' toxpython: 'python3.12' python_arch: 'arm64' @@ -290,6 +320,7 @@ jobs: cibw_build: false os: 'macos-latest' - name: 'py312-nocov (ubuntu/x86_64/manylinux)' + artifact: 'py312-ubuntu-x86_64-manylinux' python: '3.12' toxpython: 'python3.12' python_arch: 'x64' @@ -299,6 +330,7 @@ jobs: cibw_ft: 'false' os: 'ubuntu-latest' - name: 'py312-nocov (ubuntu/x86_64/musllinux)' + artifact: 'py312-ubuntu-x86_64-musllinux' python: '3.12' toxpython: 'python3.12' python_arch: 'x64' @@ -308,6 +340,7 @@ jobs: cibw_ft: 'false' os: 'ubuntu-latest' - name: 'py312-nocov (ubuntu/aarch64/manylinux)' + artifact: 'py312-ubuntu-aarch64-manylinux' python: '3.12' toxpython: 'python3.12' python_arch: 'x64' @@ -317,6 +350,7 @@ jobs: cibw_ft: 'false' os: 'ubuntu-latest' - name: 'py312-nocov (ubuntu/aarch64/musllinux)' + artifact: 'py312-ubuntu-aarch64-musllinux' python: '3.12' toxpython: 'python3.12' python_arch: 'x64' @@ -326,6 +360,7 @@ jobs: cibw_ft: 'false' os: 'ubuntu-latest' - name: 'py312-nocov (windows/AMD64)' + artifact: 'py312-windows-AMD64' python: '3.12' toxpython: 'python3.12' python_arch: 'x64' @@ -335,6 +370,7 @@ jobs: cibw_ft: 'false' os: 'windows-latest' - name: 'py312-nocov (macos/arm64)' + artifact: 'py312-macos-arm64' python: '3.12' toxpython: 'python3.12' python_arch: 'arm64' @@ -344,6 +380,7 @@ jobs: cibw_ft: 'false' os: 'macos-latest' - name: 'py313-cover (ubuntu/x86_64)' + artifact: 'py313-ubuntu-x86_64' python: '3.13' toxpython: 'python3.13' python_arch: 'x64' @@ -353,6 +390,7 @@ jobs: cibw_build: false os: 'ubuntu-latest' - name: 'py313-cover (windows/AMD64)' + artifact: 'py313-windows-AMD64' python: '3.13' toxpython: 'python3.13' python_arch: 'x64' @@ -362,6 +400,7 @@ jobs: cibw_build: false os: 'windows-latest' - name: 'py313-cover (macos/arm64)' + artifact: 'py313-macos-arm64' python: '3.13' toxpython: 'python3.13' python_arch: 'arm64' @@ -371,6 +410,7 @@ jobs: cibw_build: false os: 'macos-latest' - name: 'py313-nocov (ubuntu/x86_64/manylinux)' + artifact: 'py313-ubuntu-x86_64-manylinux' python: '3.13' toxpython: 'python3.13' python_arch: 'x64' @@ -380,6 +420,7 @@ jobs: cibw_ft: 'false' os: 'ubuntu-latest' - name: 'py313-nocov (ubuntu/x86_64/musllinux)' + artifact: 'py313-ubuntu-x86_64-musllinux' python: '3.13' toxpython: 'python3.13' python_arch: 'x64' @@ -389,6 +430,7 @@ jobs: cibw_ft: 'false' os: 'ubuntu-latest' - name: 'py313-nocov (ubuntu/aarch64/manylinux)' + artifact: 'py313-ubuntu-aarch64-manylinux' python: '3.13' toxpython: 'python3.13' python_arch: 'x64' @@ -398,6 +440,7 @@ jobs: cibw_ft: 'false' os: 'ubuntu-latest' - name: 'py313-nocov (ubuntu/aarch64/musllinux)' + artifact: 'py313-ubuntu-aarch64-musllinux' python: '3.13' toxpython: 'python3.13' python_arch: 'x64' @@ -407,6 +450,7 @@ jobs: cibw_ft: 'false' os: 'ubuntu-latest' - name: 'py313-nocov (windows/AMD64)' + artifact: 'py313-windows-AMD64' python: '3.13' toxpython: 'python3.13' python_arch: 'x64' @@ -416,6 +460,7 @@ jobs: cibw_ft: 'false' os: 'windows-latest' - name: 'py313-nocov (macos/arm64)' + artifact: 'py313-macos-arm64' python: '3.13' toxpython: 'python3.13' python_arch: 'arm64' @@ -425,6 +470,7 @@ jobs: cibw_ft: 'false' os: 'macos-latest' - name: 'py313ft-cover (ubuntu/x86_64)' + artifact: 'py313ft-ubuntu-x86_64' python: '3.13ft' toxpython: 'python3.13ft' python_arch: 'x64-freethreaded' @@ -434,6 +480,7 @@ jobs: cibw_build: false os: 'ubuntu-latest' - name: 'py313ft-cover (windows/AMD64)' + artifact: 'py313ft-windows-AMD64' python: '3.13ft' toxpython: 'python3.13ft' python_arch: 'x64-freethreaded' @@ -443,6 +490,7 @@ jobs: cibw_build: false os: 'windows-latest' - name: 'py313ft-cover (macos/arm64)' + artifact: 'py313ft-macos-arm64' python: '3.13ft' toxpython: 'python3.13ft' python_arch: 'arm64-freethreaded' @@ -452,6 +500,7 @@ jobs: cibw_build: false os: 'macos-latest' - name: 'py313ft-nocov (ubuntu/x86_64/manylinux)' + artifact: 'py313ft-ubuntu-x86_64-manylinux' python: '3.13ft' toxpython: 'python3.13ft' python_arch: 'x64-freethreaded' @@ -461,6 +510,7 @@ jobs: cibw_ft: 'true' os: 'ubuntu-latest' - name: 'py313ft-nocov (ubuntu/x86_64/musllinux)' + artifact: 'py313ft-ubuntu-x86_64-musllinux' python: '3.13ft' toxpython: 'python3.13ft' python_arch: 'x64-freethreaded' @@ -470,6 +520,7 @@ jobs: cibw_ft: 'true' os: 'ubuntu-latest' - name: 'py313ft-nocov (ubuntu/aarch64/manylinux)' + artifact: 'py313ft-ubuntu-aarch64-manylinux' python: '3.13ft' toxpython: 'python3.13ft' python_arch: 'x64-freethreaded' @@ -479,6 +530,7 @@ jobs: cibw_ft: 'true' os: 'ubuntu-latest' - name: 'py313ft-nocov (ubuntu/aarch64/musllinux)' + artifact: 'py313ft-ubuntu-aarch64-musllinux' python: '3.13ft' toxpython: 'python3.13ft' python_arch: 'x64-freethreaded' @@ -488,6 +540,7 @@ jobs: cibw_ft: 'true' os: 'ubuntu-latest' - name: 'py313ft-nocov (windows/AMD64)' + artifact: 'py313ft-windows-AMD64' python: '3.13ft' toxpython: 'python3.13ft' python_arch: 'x64-freethreaded' @@ -497,6 +550,7 @@ jobs: cibw_ft: 'true' os: 'windows-latest' - name: 'py313ft-nocov (macos/arm64)' + artifact: 'py313ft-macos-arm64' python: '3.13ft' toxpython: 'python3.13ft' python_arch: 'arm64-freethreaded' @@ -506,6 +560,7 @@ jobs: cibw_ft: 'true' os: 'macos-latest' - name: 'pypy39-cover (ubuntu/x86_64)' + artifact: 'pypy39-ubuntu-x86_64' python: 'pypy-3.9' toxpython: 'pypy3.9' python_arch: 'x64' @@ -515,6 +570,7 @@ jobs: cibw_build: false os: 'ubuntu-latest' - name: 'pypy39-cover (windows/AMD64)' + artifact: 'pypy39-windows-AMD64' python: 'pypy-3.9' toxpython: 'pypy3.9' python_arch: 'x64' @@ -524,6 +580,7 @@ jobs: cibw_build: false os: 'windows-latest' - name: 'pypy39-cover (macos/arm64)' + artifact: 'pypy39-macos-arm64' python: 'pypy-3.9' toxpython: 'pypy3.9' python_arch: 'arm64' @@ -533,6 +590,7 @@ jobs: cibw_build: false os: 'macos-latest' - name: 'pypy39-nocov (ubuntu/x86_64/manylinux)' + artifact: 'pypy39-ubuntu-x86_64-manylinux' python: 'pypy-3.9' toxpython: 'pypy3.9' python_arch: 'x64' @@ -541,6 +599,7 @@ jobs: cibw_build: false os: 'ubuntu-latest' - name: 'pypy39-nocov (windows/AMD64)' + artifact: 'pypy39-windows-AMD64' python: 'pypy-3.9' toxpython: 'pypy3.9' python_arch: 'x64' @@ -549,6 +608,7 @@ jobs: cibw_build: false os: 'windows-latest' - name: 'pypy39-nocov (macos/arm64)' + artifact: 'pypy39-macos-arm64' python: 'pypy-3.9' toxpython: 'pypy3.9' python_arch: 'arm64' @@ -557,6 +617,7 @@ jobs: cibw_build: false os: 'macos-latest' - name: 'pypy310-cover (ubuntu/x86_64)' + artifact: 'pypy310-ubuntu-x86_64' python: 'pypy-3.10' toxpython: 'pypy3.10' python_arch: 'x64' @@ -566,6 +627,7 @@ jobs: cibw_build: false os: 'ubuntu-latest' - name: 'pypy310-cover (windows/AMD64)' + artifact: 'pypy310-windows-AMD64' python: 'pypy-3.10' toxpython: 'pypy3.10' python_arch: 'x64' @@ -575,6 +637,7 @@ jobs: cibw_build: false os: 'windows-latest' - name: 'pypy310-cover (macos/arm64)' + artifact: 'pypy310-macos-arm64' python: 'pypy-3.10' toxpython: 'pypy3.10' python_arch: 'arm64' @@ -584,6 +647,7 @@ jobs: cibw_build: false os: 'macos-latest' - name: 'pypy310-nocov (ubuntu/x86_64/manylinux)' + artifact: 'pypy310-ubuntu-x86_64-manylinux' python: 'pypy-3.10' toxpython: 'pypy3.10' python_arch: 'x64' @@ -592,6 +656,7 @@ jobs: cibw_build: false os: 'ubuntu-latest' - name: 'pypy310-nocov (windows/AMD64)' + artifact: 'pypy310-windows-AMD64' python: 'pypy-3.10' toxpython: 'pypy3.10' python_arch: 'x64' @@ -600,6 +665,7 @@ jobs: cibw_build: false os: 'windows-latest' - name: 'pypy310-nocov (macos/arm64)' + artifact: 'pypy310-macos-arm64' python: 'pypy-3.10' toxpython: 'pypy3.10' python_arch: 'arm64' @@ -674,12 +740,16 @@ jobs: uses: actions/upload-artifact@v4 if: matrix.cibw_build with: + name: wheel-${{ matrix.artifact }} path: wheelhouse/*.whl finish: needs: test if: ${{ always() }} runs-on: ubuntu-latest steps: + - uses: actions/upload-artifact/merge@v4 + with: + name: wheels - uses: coverallsapp/github-action@v2 with: parallel-finished: true diff --git a/ci/templates/.github/workflows/github-actions.yml b/ci/templates/.github/workflows/github-actions.yml index f080595..ffa3f0b 100644 --- a/ci/templates/.github/workflows/github-actions.yml +++ b/ci/templates/.github/workflows/github-actions.yml @@ -43,6 +43,7 @@ jobs: {% set wheel_suffix = 'nocov' in env and wheel_arch.strip('*') %} {% set name_suffix = '/' + wheel_suffix if wheel_suffix else '' %} - name: '{{ env }} ({{ os }}/{{ cibw_arch }}{{ name_suffix }})' + artifact: '{{ env.rsplit('-', 1)[0] }}-{{ os }}-{{ cibw_arch }}{{ name_suffix.replace('/', '-') }}' python: '{{ python }}' toxpython: '{{ toxpython }}' python_arch: '{{ python_arch }}{% if nogil %}-freethreaded{% endif %}' @@ -128,15 +129,20 @@ jobs: uses: actions/upload-artifact@v4 if: matrix.cibw_build with: + name: {{ 'wheel-${{ matrix.artifact }}' }} path: wheelhouse/*.whl finish: needs: test if: {{ '${{ always() }}' }} runs-on: ubuntu-latest steps: + - uses: actions/upload-artifact/merge@v4 + with: + name: wheels - uses: coverallsapp/github-action@v2 with: parallel-finished: true - uses: codecov/codecov-action@v5 with: CODECOV_TOKEN: {% raw %}${{ secrets.CODECOV_TOKEN }}{% endraw %} + From 7090de850e22924ec5c31db5e2f4a870377f7219 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ionel=20Cristian=20M=C4=83rie=C8=99?= Date: Wed, 16 Apr 2025 18:58:56 +0300 Subject: [PATCH 27/33] Fix some variables for freethread builds. --- .github/workflows/github-actions.yml | 102 +++++++++--------- .../.github/workflows/github-actions.yml | 4 +- tox.ini | 2 +- 3 files changed, 54 insertions(+), 54 deletions(-) diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml index 837c44c..4ff02db 100644 --- a/.github/workflows/github-actions.yml +++ b/.github/workflows/github-actions.yml @@ -469,94 +469,94 @@ jobs: cibw_build: 'cp313-*' cibw_ft: 'false' os: 'macos-latest' - - name: 'py313ft-cover (ubuntu/x86_64)' - artifact: 'py313ft-ubuntu-x86_64' - python: '3.13ft' - toxpython: 'python3.13ft' + - name: 'py313-ft-cover (ubuntu/x86_64)' + artifact: 'py313-ft-ubuntu-x86_64' + python: '3.13' + toxpython: 'python3.13t' python_arch: 'x64-freethreaded' - tox_env: 'py313ft-cover' + tox_env: 'py313-ft-cover' cover: true cibw_arch: 'x86_64' cibw_build: false os: 'ubuntu-latest' - - name: 'py313ft-cover (windows/AMD64)' - artifact: 'py313ft-windows-AMD64' - python: '3.13ft' - toxpython: 'python3.13ft' + - name: 'py313-ft-cover (windows/AMD64)' + artifact: 'py313-ft-windows-AMD64' + python: '3.13' + toxpython: 'python3.13t' python_arch: 'x64-freethreaded' - tox_env: 'py313ft-cover' + tox_env: 'py313-ft-cover' cover: true cibw_arch: 'AMD64' cibw_build: false os: 'windows-latest' - - name: 'py313ft-cover (macos/arm64)' - artifact: 'py313ft-macos-arm64' - python: '3.13ft' - toxpython: 'python3.13ft' + - name: 'py313-ft-cover (macos/arm64)' + artifact: 'py313-ft-macos-arm64' + python: '3.13' + toxpython: 'python3.13t' python_arch: 'arm64-freethreaded' - tox_env: 'py313ft-cover' + tox_env: 'py313-ft-cover' cover: true cibw_arch: 'arm64' cibw_build: false os: 'macos-latest' - - name: 'py313ft-nocov (ubuntu/x86_64/manylinux)' - artifact: 'py313ft-ubuntu-x86_64-manylinux' - python: '3.13ft' - toxpython: 'python3.13ft' + - name: 'py313-ft-nocov (ubuntu/x86_64/manylinux)' + artifact: 'py313-ft-ubuntu-x86_64-manylinux' + python: '3.13' + toxpython: 'python3.13t' python_arch: 'x64-freethreaded' - tox_env: 'py313ft-nocov' + tox_env: 'py313-ft-nocov' cibw_arch: 'x86_64' - cibw_build: 'cp313ftt-*manylinux*' + cibw_build: 'cp313t-*manylinux*' cibw_ft: 'true' os: 'ubuntu-latest' - - name: 'py313ft-nocov (ubuntu/x86_64/musllinux)' - artifact: 'py313ft-ubuntu-x86_64-musllinux' - python: '3.13ft' - toxpython: 'python3.13ft' + - name: 'py313-ft-nocov (ubuntu/x86_64/musllinux)' + artifact: 'py313-ft-ubuntu-x86_64-musllinux' + python: '3.13' + toxpython: 'python3.13t' python_arch: 'x64-freethreaded' - tox_env: 'py313ft-nocov' + tox_env: 'py313-ft-nocov' cibw_arch: 'x86_64' - cibw_build: 'cp313ftt-*musllinux*' + cibw_build: 'cp313t-*musllinux*' cibw_ft: 'true' os: 'ubuntu-latest' - - name: 'py313ft-nocov (ubuntu/aarch64/manylinux)' - artifact: 'py313ft-ubuntu-aarch64-manylinux' - python: '3.13ft' - toxpython: 'python3.13ft' + - name: 'py313-ft-nocov (ubuntu/aarch64/manylinux)' + artifact: 'py313-ft-ubuntu-aarch64-manylinux' + python: '3.13' + toxpython: 'python3.13t' python_arch: 'x64-freethreaded' - tox_env: 'py313ft-nocov' + tox_env: 'py313-ft-nocov' cibw_arch: 'aarch64' - cibw_build: 'cp313ftt-*manylinux*' + cibw_build: 'cp313t-*manylinux*' cibw_ft: 'true' os: 'ubuntu-latest' - - name: 'py313ft-nocov (ubuntu/aarch64/musllinux)' - artifact: 'py313ft-ubuntu-aarch64-musllinux' - python: '3.13ft' - toxpython: 'python3.13ft' + - name: 'py313-ft-nocov (ubuntu/aarch64/musllinux)' + artifact: 'py313-ft-ubuntu-aarch64-musllinux' + python: '3.13' + toxpython: 'python3.13t' python_arch: 'x64-freethreaded' - tox_env: 'py313ft-nocov' + tox_env: 'py313-ft-nocov' cibw_arch: 'aarch64' - cibw_build: 'cp313ftt-*musllinux*' + cibw_build: 'cp313t-*musllinux*' cibw_ft: 'true' os: 'ubuntu-latest' - - name: 'py313ft-nocov (windows/AMD64)' - artifact: 'py313ft-windows-AMD64' - python: '3.13ft' - toxpython: 'python3.13ft' + - name: 'py313-ft-nocov (windows/AMD64)' + artifact: 'py313-ft-windows-AMD64' + python: '3.13' + toxpython: 'python3.13t' python_arch: 'x64-freethreaded' - tox_env: 'py313ft-nocov' + tox_env: 'py313-ft-nocov' cibw_arch: 'AMD64' - cibw_build: 'cp313ftt-*' + cibw_build: 'cp313t-*' cibw_ft: 'true' os: 'windows-latest' - - name: 'py313ft-nocov (macos/arm64)' - artifact: 'py313ft-macos-arm64' - python: '3.13ft' - toxpython: 'python3.13ft' + - name: 'py313-ft-nocov (macos/arm64)' + artifact: 'py313-ft-macos-arm64' + python: '3.13' + toxpython: 'python3.13t' python_arch: 'arm64-freethreaded' - tox_env: 'py313ft-nocov' + tox_env: 'py313-ft-nocov' cibw_arch: 'arm64' - cibw_build: 'cp313ftt-*' + cibw_build: 'cp313t-*' cibw_ft: 'true' os: 'macos-latest' - name: 'pypy39-cover (ubuntu/x86_64)' diff --git a/ci/templates/.github/workflows/github-actions.yml b/ci/templates/.github/workflows/github-actions.yml index ffa3f0b..84963c7 100644 --- a/ci/templates/.github/workflows/github-actions.yml +++ b/ci/templates/.github/workflows/github-actions.yml @@ -25,11 +25,11 @@ jobs: {% if prefix.startswith('pypy') %} {% set python %}pypy-{{ prefix[4] }}.{{ prefix[5:] }}{% endset %} {% set cpython %}pp{{ prefix[4:5] }}{% endset %} -{% set toxpython %}pypy{{ prefix[4] }}.{{ prefix[5:] }}{% endset %} +{% set toxpython %}pypy{{ prefix[4] }}.{{ prefix[5:] }}{{ 't' if nogil else '' }}{% endset %} {% else %} {% set python %}{{ prefix[2] }}.{{ prefix[3:] }}{% endset %} {% set cpython %}cp{{ prefix[2:] }}{% endset %} -{% set toxpython %}python{{ prefix[2] }}.{{ prefix[3:] }}{% endset %} +{% set toxpython %}python{{ prefix[2] }}.{{ prefix[3:] }}{{ 't' if nogil else '' }}{% endset %} {% endif %} {% for os, python_arch, cibw_arch, wheel_arch, include_cover in [ ['ubuntu', 'x64', 'x86_64', '*manylinux*', True], diff --git a/tox.ini b/tox.ini index d0c9ff8..dbe24b9 100644 --- a/tox.ini +++ b/tox.ini @@ -14,7 +14,7 @@ envlist = clean, check, docs, - {py39,py310,py311,py312,py313,py313ft,pypy39,pypy310}-{cover,nocov}, + {py39,py310,py311,py312,py313,py313-ft,pypy39,pypy310}-{cover,nocov}, report ignore_basepython_conflict = true From b6ecdc9f92446fa1bd1ddb8b0ebb3adcc82d4294 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ionel=20Cristian=20M=C4=83rie=C8=99?= Date: Wed, 16 Apr 2025 19:13:59 +0300 Subject: [PATCH 28/33] Twine not needed. --- ci/requirements.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/ci/requirements.txt b/ci/requirements.txt index b4f1852..6226712 100644 --- a/ci/requirements.txt +++ b/ci/requirements.txt @@ -2,4 +2,3 @@ virtualenv>=16.6.0 pip>=19.1.1 setuptools>=18.0.1 tox -twine From a210b0c705bb01c139d6b3044319c54b84438a38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ionel=20Cristian=20M=C4=83rie=C8=99?= Date: Wed, 16 Apr 2025 19:18:50 +0300 Subject: [PATCH 29/33] Workaround for twine being uninstalable on freethreaded (cryphtography bad) --- .github/workflows/github-actions.yml | 7 +++++-- ci/templates/.github/workflows/github-actions.yml | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml index 4ff02db..446b4da 100644 --- a/.github/workflows/github-actions.yml +++ b/.github/workflows/github-actions.yml @@ -734,8 +734,11 @@ jobs: verbose: true flags: ${{ matrix.tox_env }} - name: check wheel - if: matrix.cibw_build - run: twine check wheelhouse/*.whl + if: > + !matrix.cibw_ft && matrix.cibw_build + run: + python -mpip install --progress-bar=off twine + twine check wheelhouse/*.whl - name: upload wheel uses: actions/upload-artifact@v4 if: matrix.cibw_build diff --git a/ci/templates/.github/workflows/github-actions.yml b/ci/templates/.github/workflows/github-actions.yml index 84963c7..4b4c7a8 100644 --- a/ci/templates/.github/workflows/github-actions.yml +++ b/ci/templates/.github/workflows/github-actions.yml @@ -123,8 +123,11 @@ jobs: verbose: true flags: {{ '${{ matrix.tox_env }}' }} - name: check wheel - if: matrix.cibw_build - run: twine check wheelhouse/*.whl + if: > + !matrix.cibw_ft && matrix.cibw_build + run: + python -mpip install --progress-bar=off twine + twine check wheelhouse/*.whl - name: upload wheel uses: actions/upload-artifact@v4 if: matrix.cibw_build From 14330a1791fe37f643b133ddc781c1497bd88b27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ionel=20Cristian=20M=C4=83rie=C8=99?= Date: Wed, 16 Apr 2025 19:37:41 +0300 Subject: [PATCH 30/33] =?UTF-8?q?Bump=20version:=201.10.0=20=E2=86=92=201.?= =?UTF-8?q?11.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- .cookiecutterrc | 2 +- README.rst | 4 ++-- docs/conf.py | 2 +- setup.py | 2 +- src/lazy_object_proxy/__init__.py | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index f4dedb1..2024805 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 1.10.0 +current_version = 1.11.0 commit = True tag = True diff --git a/.cookiecutterrc b/.cookiecutterrc index 1d621f1..94d8547 100644 --- a/.cookiecutterrc +++ b/.cookiecutterrc @@ -40,7 +40,7 @@ default_context: sphinx_theme: furo test_matrix_separate_coverage: 'yes' tests_inside_package: 'no' - version: 1.10.0 + version: 1.11.0 version_manager: bump2version website: https://blog.ionelmc.ro year_from: '2014' diff --git a/README.rst b/README.rst index e429753..43d6011 100644 --- a/README.rst +++ b/README.rst @@ -45,9 +45,9 @@ Overview :alt: Supported implementations :target: https://pypi.org/project/lazy-object-proxy -.. |commits-since| image:: https://img.shields.io/github/commits-since/ionelmc/python-lazy-object-proxy/v1.10.0.svg +.. |commits-since| image:: https://img.shields.io/github/commits-since/ionelmc/python-lazy-object-proxy/v1.11.0.svg :alt: Commits since latest release - :target: https://github.com/ionelmc/python-lazy-object-proxy/compare/v1.10.0...master + :target: https://github.com/ionelmc/python-lazy-object-proxy/compare/v1.11.0...master diff --git a/docs/conf.py b/docs/conf.py index 18f3f99..dfa64f0 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -23,7 +23,7 @@ import traceback traceback.print_exc() - version = release = '1.10.0' + version = release = '1.11.0' pygments_style = 'trac' templates_path = ['.'] diff --git a/setup.py b/setup.py index fdfbd9a..2cd958f 100755 --- a/setup.py +++ b/setup.py @@ -78,7 +78,7 @@ def read(*names, **kwargs): use_scm_version={ 'local_scheme': 'dirty-tag', 'write_to': 'src/lazy_object_proxy/_version.py', - 'fallback_version': '1.10.0', + 'fallback_version': '1.11.0', }, license='BSD-2-Clause', description='A fast and thorough lazy object proxy.', diff --git a/src/lazy_object_proxy/__init__.py b/src/lazy_object_proxy/__init__.py index 50b9cae..e91e6c2 100644 --- a/src/lazy_object_proxy/__init__.py +++ b/src/lazy_object_proxy/__init__.py @@ -18,6 +18,6 @@ try: from ._version import version as __version__ except ImportError: - __version__ = '1.10.0' + __version__ = '1.11.0' __all__ = ('Proxy',) From 58a13f326f9cab8be03c56c514e7347546537a9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20G=C3=B3rny?= Date: Fri, 15 Dec 2023 17:45:42 +0100 Subject: [PATCH 31/33] Support SETUPPY_FORCE_PURE in tests Support testing without the C extension if SETUPPY_FORCE_PURE is set. This makes the test suite behavior consistent with setup.py behavior. --- tests/conftest.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/conftest.py b/tests/conftest.py index 1317faf..383289c 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,3 +1,4 @@ +import os import sys import pytest @@ -19,7 +20,7 @@ class FakeModule: try: from lazy_object_proxy.cext import Proxy except ImportError: - if PYPY: + if PYPY or os.environ.get('SETUPPY_FORCE_PURE'): pytest.skip(reason='C Extension not available.') else: raise From 9ba6f66b5959fa9739c7224e3ee3c5505fafc799 Mon Sep 17 00:00:00 2001 From: Michael Simacek Date: Thu, 22 May 2025 14:53:04 +0200 Subject: [PATCH 32/33] Skip C extension build on GraalPy --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 2cd958f..3cbc50e 100755 --- a/setup.py +++ b/setup.py @@ -22,8 +22,8 @@ LFLAGS = '' allow_extensions = True -if '__pypy__' in sys.builtin_module_names: - print('NOTICE: C extensions disabled on PyPy (would be broken)!') +if sys.implementation.name in ('pypy', 'graalpy'): + print('NOTICE: C extensions disabled on PyPy/GraalPy (would be broken)!') allow_extensions = False if os.environ.get('SETUPPY_FORCE_PURE'): print('NOTICE: C extensions disabled (SETUPPY_FORCE_PURE)!') From 4db87e64b26f427d1af5e26f2835110e53544202 Mon Sep 17 00:00:00 2001 From: Michael Simacek Date: Fri, 23 May 2025 18:01:23 +0200 Subject: [PATCH 33/33] Test GraalPy in the CI --- .github/workflows/github-actions.yml | 18 ++++++++++++++++++ tests/conftest.py | 3 ++- tests/test_async_py3.py | 12 ++++++++++++ tests/test_lazy_object_proxy.py | 4 ++++ tox.ini | 3 ++- 5 files changed, 38 insertions(+), 2 deletions(-) diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml index 446b4da..29983d8 100644 --- a/.github/workflows/github-actions.yml +++ b/.github/workflows/github-actions.yml @@ -673,6 +673,24 @@ jobs: cibw_arch: 'arm64' cibw_build: false os: 'macos-latest' + - name: 'graalpy242-nocov (ubuntu/x86_64/manylinux)' + artifact: 'graalpy242-ubuntu-x86_64-manylinux' + python: 'graalpy-24.2' + toxpython: 'graalpy' + python_arch: 'x64' + tox_env: 'graalpy-nocov' + cibw_arch: 'x86_64' + cibw_build: false + os: 'ubuntu-latest' + - name: 'graalpy242-nocov (macos/arm64)' + artifact: 'graalpy242-macos-arm64' + python: 'graalpy-24.2' + toxpython: 'graalpy' + python_arch: 'arm64' + tox_env: 'graalpy-nocov' + cibw_arch: 'arm64' + cibw_build: false + os: 'macos-latest' steps: - uses: docker/setup-qemu-action@v3 if: matrix.cibw_arch == 'aarch64' diff --git a/tests/conftest.py b/tests/conftest.py index 383289c..1289733 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -4,6 +4,7 @@ import pytest PYPY = '__pypy__' in sys.builtin_module_names +GRAALPY = sys.implementation.name == 'graalpy' @pytest.fixture(scope='session') @@ -20,7 +21,7 @@ class FakeModule: try: from lazy_object_proxy.cext import Proxy except ImportError: - if PYPY or os.environ.get('SETUPPY_FORCE_PURE'): + if PYPY or GRAALPY or os.environ.get('SETUPPY_FORCE_PURE'): pytest.skip(reason='C Extension not available.') else: raise diff --git a/tests/test_async_py3.py b/tests/test_async_py3.py index 0d9450b..235cf2f 100644 --- a/tests/test_async_py3.py +++ b/tests/test_async_py3.py @@ -13,6 +13,7 @@ from lazy_object_proxy.utils import await_ pypyxfail = pytest.mark.xfail('hasattr(sys, "pypy_version_info")') +graalpyxfail = pytest.mark.xfail('sys.implementation.name == "graalpy"') class AsyncYieldFrom: @@ -75,6 +76,7 @@ def gen(): assert not hasattr(gen, '__await__') +@graalpyxfail def test_func_1(lop): async def foo(): return 10 @@ -95,6 +97,7 @@ def bar(): assert not bool(bar.__code__.co_flags & inspect.CO_COROUTINE) +@graalpyxfail def test_func_2(lop): async def foo(): raise StopIteration @@ -269,6 +272,7 @@ async def func(): coro.close() +@graalpyxfail def test_func_12(lop): async def g(): i = me.send(None) @@ -279,6 +283,7 @@ async def g(): me.send(None) +@graalpyxfail def test_func_13(lop): async def g(): pass @@ -290,6 +295,7 @@ async def g(): coro.close() +@graalpyxfail def test_func_14(lop): @types.coroutine def gen(): @@ -777,6 +783,7 @@ async def foo(): run_async(lop.Proxy(foo)) +@graalpyxfail def test_with_2(lop): class CM: def __aenter__(self): @@ -845,6 +852,7 @@ async def func(): @pypyxfail +@graalpyxfail def test_with_6(lop): class CM: def __aenter__(self): @@ -863,6 +871,7 @@ async def foo(): @pypyxfail +@graalpyxfail def test_with_7(lop): class CM: async def __aenter__(self): @@ -887,6 +896,7 @@ async def foo(): @pypyxfail +@graalpyxfail def test_with_8(lop): CNT = 0 @@ -990,6 +1000,7 @@ async def foo(): pytest.fail('exception from __aexit__ did not propagate') +@graalpyxfail def test_with_11(lop): CNT = 0 @@ -1032,6 +1043,7 @@ async def foo(): run_async(lop.Proxy(foo)) +@graalpyxfail def test_with_13(lop): CNT = 0 diff --git a/tests/test_lazy_object_proxy.py b/tests/test_lazy_object_proxy.py index 5f88394..4140c10 100644 --- a/tests/test_lazy_object_proxy.py +++ b/tests/test_lazy_object_proxy.py @@ -14,6 +14,8 @@ PYPY = '__pypy__' in sys.builtin_module_names +graalpyxfail = pytest.mark.xfail('sys.implementation.name == "graalpy"') + OBJECTS_CODE = """ class TargetBaseClass(object): "documentation" @@ -223,6 +225,7 @@ def test_function_doc_string(lop): assert wrapper.__doc__ == target.__doc__ +@graalpyxfail def test_class_of_class(lop): # Test preservation of class __class__ attribute. @@ -271,6 +274,7 @@ def test_class_of_instance(lop): assert isinstance(wrapper, objects.TargetBaseClass) +@graalpyxfail def test_class_of_function(lop): # Test preservation of function __class__ attribute. diff --git a/tox.ini b/tox.ini index dbe24b9..56c22c9 100644 --- a/tox.ini +++ b/tox.ini @@ -14,7 +14,7 @@ envlist = clean, check, docs, - {py39,py310,py311,py312,py313,py313-ft,pypy39,pypy310}-{cover,nocov}, + {py39,py310,py311,py312,py313,py313-ft,pypy39,pypy310,graalpy}-{cover,nocov}, report ignore_basepython_conflict = true @@ -28,6 +28,7 @@ basepython = py312: {env:TOXPYTHON:python3.12} py313: {env:TOXPYTHON:python3.13} py313ft: {env:TOXPYTHON:python3.13t} + graalpy: {env:TOXPYTHON:graalpy} {bootstrap,clean,check,report,docs,codecov,coveralls,extension-coveralls}: {env:TOXPYTHON:python3} setenv = PYTHONPATH={toxinidir}/tests pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy