diff --git a/.gitchangelog.rc b/.gitchangelog.rc index c658c92a..4790956f 100644 --- a/.gitchangelog.rc +++ b/.gitchangelog.rc @@ -64,6 +64,7 @@ ignore_regexps = [ r'@wip', r'!wip', r'^([cC]hg|[fF]ix|[nN]ew)\s*:\s*[p|P]kg:', r'^([cC]hg|[fF]ix|[nN]ew)\s*:\s*[d|D]ev:', + r'^([cC]i)\s*:', r'^(.{3,3}\s*:)?\s*[fF]irst commit.?\s*$', r'^$', ## ignore commits with empty messages ] @@ -85,16 +86,17 @@ section_regexps = [ ('New', [ r'^[nN]ew\s*:\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$', ]), + ('Features', [ + r'^([nN]ew|[fF]eat)\s*:\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$', + ]), ('Changes', [ r'^[cC]hg\s*:\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$', ]), - ('Fix', [ + ('Fixes', [ r'^[fF]ix\s*:\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$', ]), - ('Other', None ## Match all lines ), - ] @@ -150,7 +152,9 @@ subject_process = (strip | ## ## Tags that will be used for the changelog must match this regexp. ## -tag_filter_regexp = r'^[0-9]+\.[0-9]+(\.[0-9]+)?$' +#tag_filter_regexp = r'^v?[0-9]+\.[0-9]+(\.[0-9]+)?$' +#tag_filter_regexp = r'^[0-9]+\.[0-9]+(\.[0-9]+)?$' +tag_filter_regexp = r'.*?$' # accept funky tag strings ## ``unreleased_version_label`` is a string or a callable that outputs a string @@ -160,7 +164,9 @@ tag_filter_regexp = r'^[0-9]+\.[0-9]+(\.[0-9]+)?$' #unreleased_version_label = "(unreleased)" unreleased_version_label = lambda: swrap( ["git", "describe", "--tags"], -shell=False) + shell=False, +) + ## ``output_engine`` is a callable ## @@ -227,7 +233,7 @@ include_merge = True ## Outputs directly to standard output ## (This is the default) ## -## - FileInsertAtFirstRegexMatch(file, pattern, idx=lamda m: m.start()) +## - FileInsertAtFirstRegexMatch(file, pattern, idx=lamda m: m.start(), flags) ## ## Creates a callable that will parse given file for the given ## regex pattern and will insert the output in the file. @@ -242,7 +248,7 @@ include_merge = True ## take care of everything and might be more complex. Check the README ## for a complete copy-pastable example. ## -# publish = FileInsertIntoFirstRegexMatch( +# publish = FileInsertAtFirstRegexMatch( # "CHANGELOG.rst", # r'/(?P[0-9]+\.[0-9]+(\.[0-9]+)?)\s+\([0-9]+-[0-9]{2}-[0-9]{2}\)\n--+\n/', # idx=lambda m: m.start(1) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 893fe71e..5ce3ce51 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,6 +9,7 @@ on: jobs: python_wheels: + name: Python wheels for ${{ matrix.python-version }} on ${{ matrix.os }} runs-on: ${{ matrix.os }} defaults: run: @@ -16,12 +17,13 @@ jobs: env: OS: ${{ matrix.os }} PYTHON: ${{ matrix.python-version }} + PYTHONIOENCODING: utf-8 PIP_DOWNLOAD_CACHE: ${{ github.workspace }}/../.pip_download_cache strategy: fail-fast: false matrix: os: [ubuntu-22.04] - python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"] + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] steps: - uses: actions/checkout@v4 @@ -38,21 +40,16 @@ jobs: pip install tox tox-gh-actions - name: Install Ubuntu build deps - if: runner.os == 'Linux' run: | sudo apt-get -qq update - sudo apt-get install -y software-properties-common - sudo add-apt-repository -y -s ppa:nerdboy/embedded - sudo apt-get install -y pybind11-dev libre2-dev ninja-build + sudo apt-get install -y libre2-dev - - name: Test in place + - name: Test using pip install run: | - tox -e dev -# -# - name: Build dist pkgs -# run: | -# tox -e deploy -# -# - name: Check wheel + tox + env: + PLATFORM: ${{ matrix.os }} + +# - name: Build sdist and wheel pkgs # run: | -# tox -e check +# tox -e build,check diff --git a/.github/workflows/conda-dev.yml b/.github/workflows/conda-dev.yml new file mode 100644 index 00000000..3e3cb9d3 --- /dev/null +++ b/.github/workflows/conda-dev.yml @@ -0,0 +1,68 @@ +name: CondaDev + +on: + workflow_dispatch: + push: + branches: + - master + pull_request: + +jobs: + build: + name: Test on Python ${{ matrix.python-version }} and ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: ['ubuntu-22.04', 'macos-13'] + python-version: ['3.9', '3.10', '3.11', '3.12'] + env: + OS: ${{ matrix.os }} + PYTHON: ${{ matrix.python-version }} + PYTHONIOENCODING: utf-8 + + steps: + - uses: actions/checkout@v4 + + - uses: conda-incubator/setup-miniconda@v3 + env: + PY_VER: ${{ matrix.python-version }} + with: + activate-environment: pyre2 + channels: conda-forge + allow-softlinks: true + channel-priority: flexible + show-channel-urls: true + + - name: Cache conda packages + id: cache + uses: actions/cache@v4 + env: + # Increase this value to reset cache and rebuild the env during the PR + CACHE_NUMBER: 0 + with: + path: /home/runner/conda_pkgs_dir + key: + ${{ runner.os }}-conda-${{ env.CACHE_NUMBER }}-python-${{ matrix.python }}-${{hashFiles('environment.devenv.yml') }} + restore-keys: | + ${{ runner.os }}-conda-${{ env.CACHE_NUMBER }}-python-${{ matrix.python }}- + ${{ runner.os }}-conda-${{ env.CACHE_NUMBER }}- + + - name: Configure condadev environment + shell: bash -el {0} + env: + PY_VER: ${{ matrix.python-version }} + run: | + conda config --set always_yes yes --set changeps1 no + conda config --add channels conda-forge + conda install conda-devenv + conda devenv + + - name: Build and test + shell: bash -el {0} + env: + PY_VER: ${{ matrix.python-version }} + run: | + source activate pyre2 + python -m pip install .[test] -vv + python -m pytest -v . diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 69ef00f1..5a521ea5 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -3,18 +3,33 @@ name: Build on: workflow_dispatch: pull_request: - push: - branches: - - master + #push: + #branches: + #- master jobs: - build_wheels: - name: Build wheels on ${{ matrix.os }} for Python + cibw_wheels: runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - os: [ubuntu-22.04, macos-latest, windows-latest] + include: + - os: "ubuntu-22.04" + arch: "x86_64" + - os: "ubuntu-22.04" + arch: "aarch64" + - os: "macos-13" + arch: "x86_64" + macosx_deployment_target: "13.0" + - os: "macos-14" + arch: "arm64" + macosx_deployment_target: "14.0" + - os: "windows-latest" + arch: "auto64" + triplet: "x64-windows" + - os: "windows-latest" + arch: "auto32" + triplet: "x86-windows" steps: - uses: actions/checkout@v4 @@ -26,43 +41,39 @@ jobs: with: python-version: '3.12' - - name: Prepare compiler environment for Windows - if: runner.os == 'Windows' - uses: ilammy/msvc-dev-cmd@v1 + - name: Set up QEMU + if: runner.os == 'Linux' + uses: docker/setup-qemu-action@v3 with: - arch: amd64 - - - name: Install cibuildwheel - run: | - python -m pip install --upgrade pip - python -m pip install -r requirements-cibw.txt + platforms: all - name: Build wheels + uses: pypa/cibuildwheel@v2.20 env: - CIBW_BUILD: cp37-* cp38-* cp39-* cp310-* cp311-* cp312-* - CIBW_ARCHS_MACOS: "universal2" - CIBW_ARCHS_LINUX: "auto64" - CIBW_ARCHS_WINDOWS: "auto64" - CIBW_SKIP: "*musllinux*" + # configure cibuildwheel to build native archs ('auto'), and some + # emulated ones, plus cross-compile on macos + CIBW_ARCHS: ${{ matrix.arch }} + CIBW_TEST_SKIP: "*_arm64 *universal2:arm64 *linux_i686" + CIBW_MANYLINUX_X86_64_IMAGE: manylinux2014 + CIBW_MANYLINUX_I686_IMAGE: manylinux2010 + CIBW_BUILD: cp38-* cp39-* cp310-* cp311-* cp312-* + CIBW_SKIP: "*musllinux* *i686" CIBW_BEFORE_ALL_LINUX: > - yum -y -q --enablerepo=extras install epel-release - && yum install -y re2-devel ninja-build - CIBW_REPAIR_WHEEL_COMMAND_LINUX: "auditwheel show {wheel} && auditwheel repair -w {dest_dir} {wheel}" + yum -y update && yum -y install epel-release && yum install -y re2-devel ninja-build CIBW_BEFORE_ALL_MACOS: > - brew install re2 pybind11 ninja - CIBW_ENVIRONMENT_MACOS: MACOSX_DEPLOYMENT_TARGET=10.15 - CIBW_REPAIR_WHEEL_COMMAND_MACOS: "pip uninstall -y delocate && pip install delocate && delocate-listdeps {wheel} && delocate-wheel -w {dest_dir} -v {wheel}" + brew install re2 pybind11 + # macos target should be at least 10.13 to get full c++17 + CIBW_ENVIRONMENT_MACOS: MACOSX_DEPLOYMENT_TARGET=${{ matrix.macosx_deployment_target }} CIBW_BEFORE_ALL_WINDOWS: > - vcpkg install re2:x64-windows + vcpkg install pkgconf:${{ matrix.triplet }} re2:${{ matrix.triplet }} && vcpkg integrate install CIBW_ENVIRONMENT_WINDOWS: 'CMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake' - CIBW_TEST_COMMAND: python -c "import re2" - run: | - python -m cibuildwheel --output-dir wheelhouse + CIBW_TEST_REQUIRES: "" + CIBW_TEST_COMMAND: "" - uses: actions/upload-artifact@v4 with: - name: dist-${{ matrix.os }} + name: wheels-${{ matrix.os }}-${{ matrix.arch }} path: ./wheelhouse/*.whl build_sdist: @@ -78,8 +89,8 @@ jobs: - name: Build sdist run: | - pip install pep517 - python -m pep517.build -s . + pip install build + python -m build -s . - uses: actions/upload-artifact@v4 with: @@ -87,19 +98,18 @@ jobs: path: dist/*.tar.gz check_artifacts: - needs: [build_sdist, build_wheels] + needs: [build_sdist, cibw_wheels] defaults: run: shell: bash name: Check artifacts are correct runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v4 - uses: actions/download-artifact@v4 with: - pattern: dist-* merge-multiple: true - path: dist - # note wheels should be in subdirectory + path: artifacts + + # note wheels should be in subdirectories named - name: Check number of downloaded artifacts - run: ls -R + run: ls -l artifacts/ diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6880929a..919b5654 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,23 @@ jobs: strategy: fail-fast: true matrix: - os: [ubuntu-22.04, macos-latest, windows-latest] + include: + - os: "ubuntu-22.04" + arch: "x86_64" + - os: "ubuntu-22.04" + arch: "aarch64" + - os: "macos-13" + arch: "x86_64" + macosx_deployment_target: "13.0" + - os: "macos-14" + arch: "arm64" + macosx_deployment_target: "14.0" + - os: "windows-latest" + arch: "auto64" + triplet: "x64-windows" + - os: "windows-latest" + arch: "auto32" + triplet: "x86-windows" steps: - uses: actions/checkout@v4 @@ -22,45 +38,41 @@ jobs: - uses: actions/setup-python@v5 name: Install Python with: - python-version: '3.12' + python-version: '3.9' - - name: Prepare compiler environment for Windows - if: runner.os == 'Windows' - uses: ilammy/msvc-dev-cmd@v1 + - name: Set up QEMU + if: runner.os == 'Linux' + uses: docker/setup-qemu-action@v3 with: - arch: amd64 - - - name: Install cibuildwheel - run: | - python -m pip install --upgrade pip - python -m pip install -r requirements-cibw.txt + platforms: all - name: Build wheels + uses: pypa/cibuildwheel@v2.20 env: - CIBW_BUILD: cp37-* cp38-* cp39-* cp310-* cp311-* cp312-* - CIBW_ARCHS_MACOS: "universal2" - CIBW_ARCHS_LINUX: "auto64" - CIBW_ARCHS_WINDOWS: "auto64" - CIBW_SKIP: "*musllinux*" + # configure cibuildwheel to build native archs ('auto'), and some + # emulated ones, plus cross-compile on macos + CIBW_ARCHS: ${{ matrix.arch }} + CIBW_TEST_SKIP: "*_arm64 *universal2:arm64 *linux_i686" + CIBW_MANYLINUX_X86_64_IMAGE: manylinux2014 + CIBW_MANYLINUX_I686_IMAGE: manylinux2010 + CIBW_BUILD: cp38-* cp39-* cp310-* cp311-* cp312-* + CIBW_SKIP: "*musllinux* *i686" CIBW_BEFORE_ALL_LINUX: > - yum -y -q --enablerepo=extras install epel-release - && yum install -y re2-devel ninja-build - CIBW_REPAIR_WHEEL_COMMAND_LINUX: "auditwheel show {wheel} && auditwheel repair -w {dest_dir} {wheel}" + yum -y update && yum -y install epel-release && yum install -y re2-devel ninja-build CIBW_BEFORE_ALL_MACOS: > - brew install re2 pybind11 ninja - CIBW_ENVIRONMENT_MACOS: MACOSX_DEPLOYMENT_TARGET=10.15 - CIBW_REPAIR_WHEEL_COMMAND_MACOS: "pip uninstall -y delocate && pip install delocate && delocate-listdeps {wheel} && delocate-wheel -w {dest_dir} -v {wheel}" + brew install re2 pybind11 + # macos target should be at least 10.13 to get full c++17 + CIBW_ENVIRONMENT_MACOS: MACOSX_DEPLOYMENT_TARGET=${{ matrix.macosx_deployment_target }} CIBW_BEFORE_ALL_WINDOWS: > - vcpkg install re2:x64-windows + vcpkg install pkgconf:${{ matrix.triplet }} re2:${{ matrix.triplet }} && vcpkg integrate install CIBW_ENVIRONMENT_WINDOWS: 'CMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake' - CIBW_TEST_COMMAND: python -c "import re2" - run: | - python -m cibuildwheel --output-dir wheelhouse + CIBW_TEST_REQUIRES: "" + CIBW_TEST_COMMAND: "" - uses: actions/upload-artifact@v4 with: - name: dist-${{ matrix.os }} + name: wheels-${{ matrix.os }}-${{ matrix.arch }} path: ./wheelhouse/*.whl build_sdist: @@ -76,8 +88,8 @@ jobs: - name: Build sdist run: | - pip install pep517 - python -m pep517.build -s . + pip install build + python -m build -s . - uses: actions/upload-artifact@v4 with: @@ -96,18 +108,19 @@ jobs: echo ${{ env.VERSION }} - uses: actions/checkout@v4 + with: + fetch-depth: 0 - uses: actions/setup-python@v5 name: Install Python with: - python-version: '3.12' + python-version: 3.12 - # download all artifacts to project dir + # download all artifacts to artifacts dir - uses: actions/download-artifact@v4 with: - pattern: dist-* merge-multiple: true - path: dist + path: artifacts - name: Generate changes file uses: sarnold/gitchangelog-action@master @@ -116,7 +129,7 @@ jobs: - name: Create draft release id: create_release - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@main env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: @@ -126,7 +139,7 @@ jobs: draft: false prerelease: false # uncomment below to upload wheels to github releases - files: dist/cibw-wheels/pyre2-updated*.whl + files: artifacts/pyre2* - uses: pypa/gh-action-pypi-publish@release/v1 if: ${{ github.actor == github.repository_owner && startsWith(github.ref, 'refs/tags') }} diff --git a/.github/workflows/sphinx.yml b/.github/workflows/sphinx.yml new file mode 100644 index 00000000..46811883 --- /dev/null +++ b/.github/workflows/sphinx.yml @@ -0,0 +1,59 @@ +name: Docs +on: + workflow_dispatch: + pull_request: + push: + branches: + - master + +permissions: + contents: write + +jobs: + build: + runs-on: ubuntu-22.04 + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Install Ubuntu build deps + run: | + sudo apt-get -qq update + sudo apt-get install -y libre2-dev + + - uses: actions/setup-python@v5 + with: + python-version: '3.9' + + - name: Add python requirements + run: | + python -m pip install --upgrade pip + pip install tox + + - name: Install Ubuntu build deps + run: | + sudo apt-get -qq update + sudo apt-get install -y libre2-dev + + - name: Build docs + run: | + tox -e ldocs,docs + + - uses: actions/upload-artifact@v4 + with: + name: ApiDocsHTML + path: "docs/_build/html/" + + - name: set nojekyll for github + run: | + touch docs/_build/html/.nojekyll + + - name: Deploy docs to gh-pages + if: ${{ github.event_name == 'push' }} + uses: JamesIves/github-pages-deploy-action@v4 + with: + branch: gh-pages + folder: docs/_build/html/ + single-commit: true diff --git a/.gitignore b/.gitignore index 4d4ff6ee..16d42f88 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,54 @@ src/*.html tests/*.so tests/access.log *~ -*.so *.pyc *.swp *.egg-info + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Sphinx documentation +docs/_build/ +docs/source/api/ + diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 0e1cb859..61ffc108 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,20 +1,172 @@ +Changelog +========= + + +v0.3.6-29-g1465367 +------------------ + +Changes +~~~~~~~ +- Switch conda workflow to condadev environment. [Stephen Arnold] +- Swap out flake8 for cython-lint, update setup files, remove pep8 cfg. + [Stephen Arnold] + +Fixes +~~~~~ +- Cleanup tests and fix a raw string test, enable more win32. [Stephen + Arnold] + + * split all runners into separate arch via matrix + * macos does need macos-14 to get a proper arm64 build +- Apply emptygroups fix and remove conda-only patch, also. [Stephen L + Arnold] + + * release workflow: restrict pypi upload to repo owner + * tox.ini: replace deprecated pep517 module, update deploy url + +Other +~~~~~ +- Fix #42. [Andreas van Cranenburgh] +- Include current notification level in cache key. [Andreas van + Cranenburgh] + + this prevents a cached regular expression being used that was created + with a different notification level. + + For example, the following now generates the expected warning:: + + In [1]: import re2 + In [2]: re2.compile('a*+') + Out[2]: re.compile('a*+') + In [3]: re2.set_fallback_notification(re2.FALLBACK_WARNING) + In [4]: re2.compile('a*+') + :1: UserWarning: WARNING: Using re module. Reason: bad repetition operator: *+ + re2.compile('a*+') + Out[4]: re.compile('a*+') +- Support fallback to Python re for possessive quantifiers. [Andreas van + Cranenburgh] +- Document lack of support for possessive quantifiers and atomic groups. + [Andreas van Cranenburgh] +- Make tests pass on my system; if this behavior turns out to be + inconsistent across versions/platforms, maybe the test should be + disabled altogether. #27. [Andreas van Cranenburgh] +- Add NOFLAGS and RegexFlags constants; #41. [Andreas van Cranenburgh] +- Remove python versions for make valgrind. [Andreas van Cranenburgh] +- Merge pull request #33 from sarnold/conda-patch. [Andreas van + Cranenburgh] + + Conda patch for None vs empty string change +- Merge pull request #32 from JustAnotherArchivist/match-getitem. + [Andreas van Cranenburgh] + + Make Match objects subscriptable +- Add test for Match subscripting. [JustAnotherArchivist] +- Make Match objects subscriptable. [JustAnotherArchivist] + + Fixes #31 + + +v0.3.6 (2021-05-05) +------------------- +- Merge pull request #30 from sarnold/release-pr. [Andreas van + Cranenburgh] + + workflow updates +- Add missing sdist job and artifact check to workflows, bump version. + [Stephen L Arnold] +- Bump version again. [Andreas van Cranenburgh] +- Merge pull request #28 from sarnold/use-action. [Andreas van + Cranenburgh] + + Workflow cleanup +- Move pypi upload to end of release.yml, use gitchangelog action. + [Stephen L Arnold] + + +v0.3.4 (2021-04-10) +------------------- + +Changes +~~~~~~~ +- Ci: update workflows and tox cfg (use tox for smoke test) [Stephen L + Arnold] +- Rename imported test helpers to avoid any discovery issues. [Stephen L + Arnold] + +Fixes +~~~~~ +- Apply test patch, cleanup tox and pytest args. [Stephen L Arnold] +- Handle invalid escape sequence warnings, revert path changes. [Stephen + L Arnold] + +Other +~~~~~ +- Bump version. [Andreas van Cranenburgh] +- Improve fix for #26. [Andreas van Cranenburgh] +- Add test for #26. [Andreas van Cranenburgh] +- Fix infinite loop on substitutions of empty matches; fixes #26. + [Andreas van Cranenburgh] +- Fix "make test" and "make test2" [Andreas van Cranenburgh] +- Merge pull request #25 from sarnold/last-moves. [Andreas van + Cranenburgh] + + Last moves +- Another one. [Andreas van Cranenburgh] +- Fix fix of conda patch. [Andreas van Cranenburgh] +- Fix conda patch. [Andreas van Cranenburgh] +- Fix "make test"; rename doctest files for autodetection. [Andreas van + Cranenburgh] +- Fix narrow unicode detection. [Andreas van Cranenburgh] +- Merge pull request #24 from sarnold/tst-cleanup. [Andreas van + Cranenburgh] + + Test cleanup +- Fix Python 2 compatibility. [Andreas van Cranenburgh] +- Use pytest; fixes #23. [Andreas van Cranenburgh] +- Tweak order of badges. [Andreas van Cranenburgh] +- Makefile: default to Python 3. [Andreas van Cranenburgh] +- Update README, fix Makefile. [Andreas van Cranenburgh] +- Merge pull request #22 from sarnold/missing-tests. [Andreas van + Cranenburgh] + + add missing tests to sdist package, update readme and ci worflows (#1) +- Fix pickle_test (tests.test_re.ReTests) ... ERROR (run tests with + nose) [Stephen L Arnold] +- Update changelog (and trigger ci rebuild) [Stephen L Arnold] +- Add missing tests to sdist package, update readme and ci worflows (#1) + [Steve Arnold] + + readme: update badges, merge install sections, fix some rendering issues + + v0.3.3 (2021-01-26) ------------------- +Changes +~~~~~~~ +- Add .gitchangelog.rc and generated CHANGELOG.rst (keep HISTORY) + [Stephen L Arnold] +- Ci: update wheel builds for Linux, Macos, and Windows. [Stephen L + Arnold] + +Fixes +~~~~~ +- Ci: make sure wheel path is correct for uploading. [Stephen L Arnold] + +Other +~~~~~ - Bump version. [Andreas van Cranenburgh] - Update README.rst. fixes #21. [Andreas van Cranenburgh] - Merge pull request #20 from freepn/new-bld. [Andreas van Cranenburgh] New cmake and pybind11 build setup -- Add .gitchangelog.rc and generated CHANGELOG.rst (keep HISTORY) - [Stephen L Arnold] -- Update wheel builds for Linux, Macos, and Windows. [Stephen L Arnold] v0.3.2 (2020-12-16) ------------------- - Bump version. [Andreas van Cranenburgh] -- Merge pull request #18 from freepn/github-ci. [Andreas van Cranenburgh] +- Merge pull request #18 from freepn/github-ci. [Andreas van + Cranenburgh] workaroud for manylinux dependency install error plus release automation @@ -28,7 +180,8 @@ v0.3.1 (2020-10-27) v0.3 (2020-10-27) ----------------- - Bump version. [Andreas van Cranenburgh] -- Merge pull request #14 from yoav-orca/master. [Andreas van Cranenburgh] +- Merge pull request #14 from yoav-orca/master. [Andreas van + Cranenburgh] Support building wheels automatically using github actions - Creating github actions for building wheels. [Yoav Alon] @@ -194,3 +347,254 @@ v0.3 (2020-10-27) - Add Python 3 support. [Tarashish Mishra] - Version bump. [Michael Axiak] + +release/0.2.22 (2015-05-15) +--------------------------- +- Version bump. [Michael Axiak] +- Merge pull request #22 from socketpair/release_gil_on_compile. + [Michael Axiak] + + Release GIL during regex compilation. +- Release GIL during regex compilation. [Коренберг Марк] + + (src/re2.cpp is not regenerated in this commit) + + +release/0.2.21 (2015-05-14) +--------------------------- +- Release bump. [Michael Axiak] +- Merge pull request #18 from offlinehacker/master. [Michael Axiak] + + setup.py: Continue with default lib paths if not detected automatically +- Setup.py: Continue with default lib paths if not detected + automatically. [Jaka Hudoklin] +- Fix issue #11. [Michael Axiak] +- Remove spurious print statement. [Michael Axiak] +- Added version check in setup.py to prevent people from shooting + themselves in the foot trying to compile with an old cython version. + [Michael Axiak] + + +release/0.2.20 (2011-11-15) +--------------------------- +- Version bump to 0.2.20. [Michael Axiak] +- Version bump to 0.2.18 and use MANIFEST.in since python broke how + sdist works in 2.7.1 (but fixes it in 2.7.3...) [Michael Axiak] + + +release/0.2.16 (2011-11-08) +--------------------------- + +Fixes +~~~~~ +- Unmatched group span (-1,-1) caused exception in _convert_pos. [Israel + Tsadok] +- Last item in qualified split included the item before last. [Israel + Tsadok] +- Exception in callback would cause a memory leak. [Israel Tsadok] +- Group spans need to be translated to their relative decoded positions. + [Israel Tsadok] +- This is not what verbose means in this context. [Israel Tsadok] +- Findall used group(0) instead of group(1) when there was a group. + [Israel Tsadok] +- Dangling reference when _subn_callback breaks on limit. [Israel + Tsadok] +- Infinite loop in pathological case of findall(".*", "foo") [Israel + Tsadok] + +Other +~~~~~ +- Version bump to 0.2.16. [Michael Axiak] +- Merged itsadok's changes to fix treatment of \D and \W. Added tests to + reflection issue #4. [Michael Axiak] +- Fixed issue #5, support \W, \S and \D. [Israel Tsadok] +- Fixed issue #3, changed code to work with new re2 api. [Michael Axiak] +- Merge branch 'itsadok-master' [Michael Axiak] +- Merge branch 'master' of https://github.com/itsadok/pyre2 into + itsadok-master. [Michael Axiak] +- Failing tests for pos and endpos. [Israel Tsadok] +- Set default notification to FALLBACK_QUIETLY, as per the + documentation. [Israel Tsadok] +- Get rid of deprecation warning. [Israel Tsadok] +- Fix hang on findall('', 'x') [Israel Tsadok] +- Allow weak reference to Pattern object. [Israel Tsadok] +- Allow named groups in span(), convert all unicode positions in one + scan. [Israel Tsadok] +- Added failing test for named groups. [Israel Tsadok] +- Fix lastgroup and lastindex. [Israel Tsadok] +- Verify that flags do not get silently ignored with compiled patterns. + [Israel Tsadok] +- Had to cheat on a test, since we can't support arbitrary bytes. + [Israel Tsadok] +- Fix lastindex. [Israel Tsadok] +- Pass some more tests - added pos, endpos, regs, re attributes to Match + object. [Israel Tsadok] +- Added max_mem parameter, bumped version to 0.2.13. [Michael Axiak] +- Remove spurious get_authors() call. [Michael Axiak] +- Added Alex to the authors file. [Michael Axiak] +- Version bumped to 0.2.11. [Michael Axiak] +- Added difference in version to changelist, added AUTHORS parsing to + setup.py. [Michael Axiak] +- Added check for array, added synonym 'error' for RegexError to help + pass more python tests. [Michael Axiak] +- Made make test run a little nicer. [Michael Axiak] +- Added note about copyright assignment to authors. [Michael Axiak] +- Fix test_re_match. [Israel Tsadok] +- Fix test_bug_1140. [Israel Tsadok] +- Update readme. [Israel Tsadok] +- Preprocess pattern to match re2 quirks. Fixes several bugs. [Israel + Tsadok] +- Re2 doesn't like when you escape non-ascii chars. [Israel Tsadok] +- Merge remote branch 'moreati/master' [Israel Tsadok] +- Merge from axiak/HEAD. [Alex Willmer] +- Merge from axiak/master. [Alex Willmer] +- Pass ErrorBadEscape patterns to re.compile(). Have re.compile() accept + SRE objects. [Alex Willmer] +- Ignore .swp files. [Alex Willmer] +- Remove superfluous differences to axiak/master. [Alex Willmer] +- Merge remote branch 'upstream/master' [Alex Willmer] +- Merge changes from axiak master. [Alex Willmer] +- Fix previous additions to setup.py. [Alex Willmer] +- Add url to setup.py. [Alex Willmer] +- Remove #! line from re.py module, since it isn't a script. [Alex + Willmer] +- Add classifers and long description to setup.py. [Alex Willmer] +- Add MANIFEST.in. [Alex Willmer] +- Merge branch 'master' of git://github.com/facebook/pyre2. [Alex + Willmer] + + Conflicts: + re2.py +- Ignore byte compiled python files. [Alex Willmer] +- Add copyright, license, and three convenience functions to re2.py. + [Alex Willmer] +- Switch re2.h include to angle brackets. [Alex Willmer] +- Handle \n in replace template, since re2 doesn't. [Israel Tsadok] +- Import escape function as it from re. [Israel Tsadok] +- The unicode char classes never worked. TIL testing is important. + [Israel Tsadok] +- Make unicode stickyness rules like in re module. [Israel Tsadok] +- Return an iterator from finditer. [Israel Tsadok] +- Have re.compile() accept SRE objects. (copied from moreati's fork) + [Israel Tsadok] +- Fix var name mixup. [Israel Tsadok] +- Added self to authors. [Israel Tsadok] +- Fix memory leak. [Israel Tsadok] +- Added re unit test from python2.6. [Israel Tsadok] +- Make match group allocation more RAII style. [Israel Tsadok] +- Use None for unused groups in split. [Israel Tsadok] +- Change split to match sre.c implementation, and handle empty matches. + [Israel Tsadok] +- Match delete[] to new[] calls. [Israel Tsadok] +- Added group property to match re API. [Israel Tsadok] +- Use appropriate char classes in case of re.UNICODE. [Israel Tsadok] +- Fall back on re in case of back references. [Israel Tsadok] +- Use unmangled pattern in case of fallback to re. [Israel Tsadok] +- Simplistic cache, copied from re.py. [Israel Tsadok] +- Fix some memory leaks. [Israel Tsadok] +- Allow multiple arguments to group() [Israel Tsadok] +- Allow multiple arguments to group() [Israel Tsadok] +- Fixed path issues. [Michael Axiak] +- Added flags to pattern object, bumped version number. [Michael Axiak] +- Change import path to fix include dirs. [Michael Axiak] +- Updated manifest and changelog. [Michael Axiak] +- Added .expand() to group objects. [Michael Axiak] +- Removed the excessive thanks. [Michael Axiak] +- Added regex module to performance tests. [Michael Axiak] +- Pattern objects should be able to return the input pattern. [Alec + Berryman] + + I'm just storing the original object passed in (found it could be str or + unicode - thanks, unicode tests!). It could be calculated if important + to save space. +- Further findall fix: one-match finds. [Alec Berryman] + + I read the spec more carefully this time. +- Added changelist file for future releases. [Michael Axiak] +- Added alec to AUTHORS. Bumped potential version number. Fixed findall + support to work without closures. [Michael Axiak] +- Make pyre2 64-bit safe. [Alec Berryman] + + Now compiles on a 64-bit system; previously, complained that you might + have a string size that couldn't fit into an int. Py_ssize_t is + required instead of plain size_t because Python's is signed. +- Fix findall behavior to match re. [Alec Berryman] + + findall is to return a list of strings or tuples of strings, while + finditer is to return an iterator of match objects; previously both were + returning lists of match objects. findall was fixed, but finditer is + still returning a list. + + New tests. +- Makefile: test target. [Alec Berryman] +- Note Cython 0.13 dependency. [Alec Berryman] +- Moved to my own license. I can do that since I started the code from + scratch. [Michael Axiak] +- Fix formatting of table. [Michael Axiak] +- Added number of trials, fixed some wording. [Michael Axiak] +- Added missing files to MANIFEST. [Michael Axiak] +- Added performance testing, bumped version number. [Michael Axiak] +- Added readme data. [Michael Axiak] +- Updated installation language. [Michael Axiak] +- Incremented version number. [Michael Axiak] +- Fixed split regression with missing unicode translation. [Michael + Axiak] +- Maybe utf8 works? [Michael Axiak] +- Got unicode to past broken test. [Michael Axiak] +- Added debug message for issue with decoding. [Michael Axiak] +- Added more utf8 stuff. [Michael Axiak] +- Delay group construction for faster match testing. [Michael Axiak] +- Got utf8 support to work. [Michael Axiak] +- Starting to add unicode support... BROKEN. [Michael Axiak] +- Added fallback and notification. [Michael Axiak] +- Added runtime library path to fix /usr/local/ bug for installation of + re2 library. [Michael Axiak] +- Fixed setup and updated readme. [Michael Axiak] +- Added more setup.py antics. [Michael Axiak] +- Added ancillary stuff. [Michael Axiak] +- Added sub, subn, findall, finditer, split. Bam. [Michael Axiak] +- Added finditer along with tests. [Michael Axiak] +- Fix rst. [Michael Axiak] +- Added contact link to readme. [Michael Axiak] +- Fixed formatting for readme. [Michael Axiak] +- Added lastindex, lastgroup, and updated README file. [Michael Axiak] +- Added some simple tests. Got match() to work, named groups to work. + spanning to work. pretty much at the same level as pyre2 proper. + [Michael Axiak] +- Added more things to gitignore, another compile. [Michael Axiak] +- Move code to src directory for better sanity. [Michael Axiak] +- Updated re2 module to use Cython instead, got matching working almost + completely with minimal flag support. [Michael Axiak] +- Suppress logging of failed pattern compilation. [David Reiss] + + This isn't necessary in Python since errors are reported by exceptions. + Use a slightly more verbose form to allow easier setting of more options + later. +- Don't define tp_new for regexps and matches. [David Reiss] + + It turns out that these are not required to use PyObject_New. They are + only required to allow Python code to call the type to create a new + instance, which I don't want to allow. Remove them. +- Fix a segfault by initializing attr_dict to NULL. [David Reiss] + + I thought PyObject_New would call my tp_new, which is set to + PyType_GenericNew, which NULLs out all user-defined fields (actually + memset, but the docs say NULL). However, this appears to not be the + case. Explicitly NULL out attr_dict in create_regexp to avoid segfaults + when compiling a bad pattern. Do it for create_match too for future + safety, even though it is not required with the current code. +- Add struct tags for easier debugging with gdb. [David Reiss] + + See http://sourceware.org/ml/archer/2009-q1/msg00085.html for a little + more information. +- Add some convenience functions to re2.py. [Alex Willmer] +- Add a copyright and license comment to re2.py. [David Reiss] + + This is to prepare for adding some not-totally-trivial code to it. +- Use PEP-8-compliant 4-space indent in re2.py. [David Reiss] +- Use angle-brackets for the re2.h include. [Alex Willmer] +- Add build information to the README. [David Reiss] +- Add contact info to README. [David Reiss] +- Initial commit of pyre2. [David Reiss] + + diff --git a/CMakeLists.txt b/CMakeLists.txt index 356f72d6..eea96df3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,16 +1,16 @@ -cmake_minimum_required(VERSION 3.18) +cmake_minimum_required(VERSION 3.15...3.28) project(re2 LANGUAGES CXX C) option(PY_DEBUG "Set if python being linked is a Py_DEBUG build" OFF) -set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_CXX_EXTENSIONS ON) if(CMAKE_CXX_COMPILER_ID STREQUAL Clang) - set(CLANG_DEFAULT_CXX_STDLIB libc++) - set(CLANG_DEFAULT_RTLIB compiler-rt) + set(CLANG_DEFAULT_CXX_STDLIB libc++) + set(CLANG_DEFAULT_RTLIB compiler-rt) endif() if(NOT CMAKE_BUILD_TYPE) @@ -20,27 +20,31 @@ endif() include(GNUInstallDirs) +# get rid of FindPython old warnings, refactor FindCython module +set(CMP0148 NEW) + +set(PYBIND11_FINDPYTHON ON) find_package(pybind11 CONFIG) if(pybind11_FOUND) - message(STATUS "System pybind11 found") + message(STATUS "System pybind11 found") else() - message(STATUS "Fetching pybind11 from github") - # Fetch pybind11 - include(FetchContent) - - FetchContent_Declare( - pybind11 - GIT_REPOSITORY https://github.com/pybind/pybind11 - GIT_TAG v2.11.1 - ) - FetchContent_MakeAvailable(pybind11) + message(STATUS "Fetching pybind11 from github") + # Fetch pybind11 + include(FetchContent) + + FetchContent_Declare( + pybind11 + GIT_REPOSITORY https://github.com/pybind/pybind11 + GIT_TAG v2.12.0 + ) + FetchContent_MakeAvailable(pybind11) endif() find_package(Threads REQUIRED) if (${PYTHON_IS_DEBUG}) - set(PY_DEBUG ON) + set(PY_DEBUG ON) endif() set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 305a4445..00000000 --- a/MANIFEST.in +++ /dev/null @@ -1,8 +0,0 @@ -global-include CMakeLists.txt *.cmake -include AUTHORS README.rst HISTORY CHANGELOG.rst LICENSE -graft src -graft tests -global-exclude *.py[cod] __pycache__ -recursive-exclude .tox * -recursive-exclude .github * -recursive-exclude vcpkg * diff --git a/Makefile b/Makefile deleted file mode 100644 index 4dd82fcf..00000000 --- a/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -install: - python3 setup.py install --user - -test: install - pytest - -clean: - rm -rf build pyre2.egg-info &>/dev/null - rm -f *.so src/*.so src/re2.cpp src/*.html &>/dev/null - -distclean: clean - rm -rf .tox/ dist/ .pytest_cache/ - -valgrind: - python3.12-dbg setup.py install --user && \ - (cd tests && valgrind --tool=memcheck --suppressions=../valgrind-python.supp \ - --leak-check=full --show-leak-kinds=definite \ - python3.12-dbg test_re.py) - -valgrind2: - python3.12-dbg setup.py install --user && \ - (cd tests && valgrind --tool=memcheck --suppressions=../valgrind-python.supp \ - --leak-check=full --show-leak-kinds=definite \ - python3.12-dbg re2_test.py) diff --git a/README.rst b/README.rst index f468fcb1..bd7f8c0f 100644 --- a/README.rst +++ b/README.rst @@ -83,8 +83,10 @@ That being said, there are features of the ``re`` module that this module may never have; these will be handled through fallback to the original ``re`` module: * lookahead assertions ``(?!...)`` -* backreferences (``\\n`` in search pattern) -* \W and \S not supported inside character classes +* backreferences, e.g., ``\\1`` in search pattern +* possessive quantifiers ``*+, ++, ?+, {m,n}+`` +* atomic groups ``(?>...)`` +* ``\W`` and ``\S`` not supported inside character classes On the other hand, unicode character classes are supported (e.g., ``\p{Greek}``). Syntax reference: https://github.com/google/re2/wiki/Syntax diff --git a/cmake/modules/FindCython.cmake b/cmake/modules/FindCython.cmake index 04aed1f8..83ac106e 100644 --- a/cmake/modules/FindCython.cmake +++ b/cmake/modules/FindCython.cmake @@ -2,7 +2,7 @@ # # This code sets the following variables: # -# CYTHON_EXECUTABLE +# Cython_EXECUTABLE # # See also UseCython.cmake @@ -24,21 +24,21 @@ # Use the Cython executable that lives next to the Python executable # if it is a local installation. -find_package( PythonInterp ) -if( PYTHONINTERP_FOUND ) - get_filename_component( _python_path ${PYTHON_EXECUTABLE} PATH ) - find_program( CYTHON_EXECUTABLE +find_package(Python) +if( Python_FOUND ) + get_filename_component( _python_path ${Python_EXECUTABLE} PATH ) + find_program( Cython_EXECUTABLE NAMES cython cython.bat cython3 HINTS ${_python_path} ) else() - find_program( CYTHON_EXECUTABLE + find_program( Cython_EXECUTABLE NAMES cython cython.bat cython3 ) endif() include( FindPackageHandleStandardArgs ) -FIND_PACKAGE_HANDLE_STANDARD_ARGS( Cython REQUIRED_VARS CYTHON_EXECUTABLE ) +FIND_PACKAGE_HANDLE_STANDARD_ARGS( Cython REQUIRED_VARS Cython_EXECUTABLE ) -mark_as_advanced( CYTHON_EXECUTABLE ) +mark_as_advanced( Cython_EXECUTABLE ) diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 00000000..abc576af --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,19 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 00000000..d806eb7f --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,36 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=. +set BUILDDIR=_build +set SPHINXPROJ=MAVConn + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% + +:end +popd diff --git a/docs/source/CHANGELOG.rst b/docs/source/CHANGELOG.rst new file mode 120000 index 00000000..bfa394db --- /dev/null +++ b/docs/source/CHANGELOG.rst @@ -0,0 +1 @@ +../../CHANGELOG.rst \ No newline at end of file diff --git a/docs/source/README.rst b/docs/source/README.rst new file mode 120000 index 00000000..c768ff7d --- /dev/null +++ b/docs/source/README.rst @@ -0,0 +1 @@ +../../README.rst \ No newline at end of file diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 00000000..3b7cbf45 --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,179 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +import os +import sys + +if sys.version_info < (3, 8): + from importlib_metadata import version +else: + from importlib.metadata import version + + +sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))) + +# -- Project information ----------------------------------------------------- + +project = 'pyre2' +copyright = '2024, Andreas van Cranenburgh' +author = 'Andreas van Cranenburgh' + +# The full version, including alpha/beta/rc tags +release = version('pyre2') +# The short X.Y version. +version = '.'.join(release.split('.')[:2]) + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinxcontrib.apidoc', + 'sphinx.ext.doctest', + 'sphinx.ext.intersphinx', + 'sphinx.ext.todo', + 'sphinx.ext.coverage', + 'sphinx.ext.viewcode', +] + +apidoc_module_dir = '../../src/' +apidoc_output_dir = 'api' +apidoc_excluded_paths = ['tests'] +apidoc_separate_modules = True + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The master toctree document. +master_doc = 'index' + +# Brief project description +# +description = 'Python RE2 wrapper for linear-time regular expressions' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = 'en' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This patterns also effect to html_static_path and html_extra_path +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = True + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'sphinx_rtd_theme' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +# html_theme_options = {} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +#html_static_path = ['_static'] + +# Custom sidebar templates, must be a dictionary that maps document names +# to template names. +# +# This is required for the alabaster theme +# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars +html_sidebars = { + '**': [ + 'relations.html', # needs 'show_related': True theme option to display + 'searchbox.html', + ] +} + + +# -- Options for HTMLHelp output ------------------------------------------ + +# Output file base name for HTML help builder. +htmlhelp_basename = 'pyre2doc' + + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'pyre2.tex', 'pyre2 Documentation', + [author], 'manual'), +] + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'pyre2', 'pyre2 Documentation', + [author], 1) +] + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'pyre2', 'pyre2 Documentation', + [author], 'pyre2', description, + 'Miscellaneous'), +] + diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 00000000..00061805 --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,17 @@ +Welcome to the Pyre2 documentation! +=================================== + +.. toctree:: + :caption: Contents: + :maxdepth: 3 + + README + api/modules + CHANGELOG + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` diff --git a/environment.devenv.yml b/environment.devenv.yml new file mode 100644 index 00000000..95fd733c --- /dev/null +++ b/environment.devenv.yml @@ -0,0 +1,22 @@ +name: pyre2 + +dependencies: + - cmake>=3.18 + - ninja + - ccache + - re2 + - clangxx_osx-64 # [osx] + - gxx_linux-64 # [linux] + - pybind11-abi + - pybind11-stubgen + - vs2019_win-64 # [win] + - pkgconfig # [win] + - python ={{ get_env("PY_VER", default="3.9") }} + - cython + - pybind11 + - pip + - pytest + - regex + # these two need to be newer than broken runner packages, 3.12 only + - urllib3 + - six diff --git a/pyproject.toml b/pyproject.toml index 7ae635df..2b24a200 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,17 +1,24 @@ [build-system] requires = [ "setuptools>=42", - "wheel", - "Cython>=3.0.8", - "pybind11>=2.11.1", + "setuptools_scm[toml]>=6.2", + "Cython>=0.20", + "pybind11>=2.12", "ninja; sys_platform != 'Windows'", "cmake>=3.18", ] build-backend = "setuptools.build_meta" +[tool.setuptools_scm] + [tool.pytest.ini_options] minversion = "6.0" testpaths = [ "tests", ] + +[tool.cython-lint] +max-line-length = 110 +ignore = ['E225','E226','E227','E402','E703','E999'] +# exclude = 'my_project/excluded_cython_file.pyx' diff --git a/requirements-cibw.txt b/requirements-cibw.txt index 4e097272..ccd6d87e 100644 --- a/requirements-cibw.txt +++ b/requirements-cibw.txt @@ -1 +1 @@ -cibuildwheel==2.16.5 \ No newline at end of file +cibuildwheel==2.16.5 diff --git a/setup.cfg b/setup.cfg index c71972e4..6380f00f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -9,9 +9,7 @@ license = BSD license_files = LICENSE classifiers = License :: OSI Approved :: BSD License - Programming Language :: Cython - Programming Language :: Python :: 3.7 - Programming Language :: Python :: 3.8 + Programming Language :: Cython Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 Programming Language :: Python :: 3.11 @@ -20,22 +18,31 @@ classifiers = Topic :: Software Development :: Libraries :: Python Modules [options] -python_requires = >=3.7 +python_requires = >=3.8 -zip_safe = False +setup_requires = + setuptools_scm[toml] [options.extras_require] +doc = + sphinx + sphinx_rtd_theme + sphinxcontrib-apidoc + test = pytest perf = regex -[flake8] -# these error codes interfere with Black -ignore = E203, E231, E501, W503, B950 -select = C,E,F,W,B,B9 +[check] +metadata = true +restructuredtext = true +strict = false -[egg_info] -tag_build = -tag_date = 0 +[check-manifest] +ignore = + .gitattributes + .gitchangelog.rc + .gitignore + conda/** diff --git a/setup.py b/setup.py index 7053ca1e..75203307 100755 --- a/setup.py +++ b/setup.py @@ -2,8 +2,10 @@ # import os -import sys +import re import subprocess +import sys +from pathlib import Path from setuptools import setup, Extension from setuptools.command.build_ext import build_ext @@ -20,21 +22,19 @@ "win-arm64": "ARM64", } + # A CMakeExtension needs a sourcedir instead of a file list. class CMakeExtension(Extension): - def __init__(self, name, sourcedir=""): - Extension.__init__(self, name, sources=[], libraries=['re2']) - self.sourcedir = os.path.abspath(sourcedir) + def __init__(self, name: str, sourcedir: str = "") -> None: + super().__init__(name, sources=[], libraries=['re2']) + self.sourcedir = os.fspath(Path(sourcedir).resolve()) class CMakeBuild(build_ext): - - def build_extension(self, ext): - extdir = os.path.abspath(os.path.dirname(self.get_ext_fullpath(ext.name))) - - # required for auto-detection of auxiliary "native" libs - if not extdir.endswith(os.path.sep): - extdir += os.path.sep + def build_extension(self, ext: CMakeExtension) -> None: + # Must be in this form due to bug in .resolve() only fixed in Python 3.10+ + ext_fullpath = Path.cwd() / self.get_ext_fullpath(ext.name) + extdir = ext_fullpath.parent.resolve() # Set a sensible default build type for packaging if "CMAKE_BUILD_OVERRIDE" not in os.environ: @@ -42,38 +42,57 @@ def build_extension(self, ext): else: cfg = os.environ.get("CMAKE_BUILD_OVERRIDE", "") + # Set a coverage flag if provided + if "WITH_COVERAGE" not in os.environ: + coverage = "OFF" + else: + coverage = os.environ.get("WITH_COVERAGE", "") + # CMake lets you override the generator - we need to check this. # Can be set with Conda-Build, for example. cmake_generator = os.environ.get("CMAKE_GENERATOR", "") # Set Python_EXECUTABLE instead if you use PYBIND11_FINDPYTHON - # SCM_VERSION_INFO shows you how to pass a value into the C++ code + # EXAMPLE_VERSION_INFO shows you how to pass a value into the C++ code # from Python. cmake_args = [ - "-DCMAKE_LIBRARY_OUTPUT_DIRECTORY={}".format(extdir), - "-DPYTHON_EXECUTABLE={}".format(sys.executable), - "-DSCM_VERSION_INFO={}".format(__version__), - "-DCMAKE_BUILD_TYPE={}".format(cfg), # not used on MSVC, but no harm + f"-DCMAKE_LIBRARY_OUTPUT_DIRECTORY={extdir}{os.sep}", + f"-DPython_EXECUTABLE={sys.executable}", + f"-DCMAKE_BUILD_TYPE={cfg}", # not used on MSVC, but no harm ] build_args = ["--verbose"] + # Add CMake arguments set as environment variable + if "CMAKE_ARGS" in os.environ: + cmake_args += [item for item in os.environ["CMAKE_ARGS"].split(" ") if item] + # CMake also lets you provide a toolchain file. # Can be set in CI build environments for example. cmake_toolchain_file = os.environ.get("CMAKE_TOOLCHAIN_FILE", "") if cmake_toolchain_file: cmake_args += ["-DCMAKE_TOOLCHAIN_FILE={}".format(cmake_toolchain_file)] + cmake_args += [f"-DSCM_VERSION_INFO={self.distribution.get_version()}"] + if self.compiler.compiler_type != "msvc": # Using Ninja-build since it a) is available as a wheel and b) # multithreads automatically. MSVC would require all variables be # exported for Ninja to pick it up, which is a little tricky to do. # Users can override the generator with CMAKE_GENERATOR in CMake # 3.15+. - if not cmake_generator: - cmake_args += ["-GNinja"] + if not cmake_generator or cmake_generator == "Ninja": + try: + import ninja # noqa: F401 + + ninja_executable_path = Path(ninja.BIN_DIR) / "ninja" + cmake_args += [ + "-GNinja", + f"-DCMAKE_MAKE_PROGRAM:FILEPATH={ninja_executable_path}", + ] + except ImportError: + pass else: - # Single config generators are handled "normally" single_config = any(x in cmake_generator for x in {"NMake", "Ninja"}) @@ -89,10 +108,16 @@ def build_extension(self, ext): # Multi-config generators have a different way to specify configs if not single_config: cmake_args += [ - "-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{}={}".format(cfg.upper(), extdir) + f"-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{cfg.upper()}={extdir}" ] build_args += ["--config", cfg] + if sys.platform.startswith("darwin"): + # Cross-compile support for macOS - respect ARCHFLAGS if set + archs = re.findall(r"-arch (\S+)", os.environ.get("ARCHFLAGS", "")) + if archs: + cmake_args += ["-DCMAKE_OSX_ARCHITECTURES={}".format(";".join(archs))] + # Set CMAKE_BUILD_PARALLEL_LEVEL to control the parallel build level # across all generators. if "CMAKE_BUILD_PARALLEL_LEVEL" not in os.environ: @@ -100,22 +125,21 @@ def build_extension(self, ext): # using -j in the build_ext call, not supported by pip or PyPA-build. if hasattr(self, "parallel") and self.parallel: # CMake 3.12+ only. - build_args += ["-j{}".format(self.parallel)] + build_args += [f"-j{self.parallel}"] - if not os.path.exists(self.build_temp): - os.makedirs(self.build_temp) + build_temp = Path(self.build_temp) / ext.name + if not build_temp.exists(): + build_temp.mkdir(parents=True) - subprocess.check_call( - ["cmake", ext.sourcedir] + cmake_args, cwd=self.build_temp + subprocess.run( + ["cmake", ext.sourcedir, *cmake_args], cwd=build_temp, check=True ) - subprocess.check_call( - ["cmake", "--build", "."] + build_args, cwd=self.build_temp + subprocess.run( + ["cmake", "--build", ".", *build_args], cwd=build_temp, check=True ) setup( - version=__version__, ext_modules=[CMakeExtension('re2')], cmdclass={'build_ext': CMakeBuild}, - zip_safe=False, ) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 61d63aa3..18b42fc8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -12,7 +12,7 @@ file(GLOB cy_srcs *.pyx *.pxi *.h) # .pyx -> .cpp add_custom_command(OUTPUT ${cython_output} - COMMAND ${CYTHON_EXECUTABLE} + COMMAND ${Cython_EXECUTABLE} -a -3 --fast-fail --cplus -I ${re2_include_dir} @@ -21,25 +21,22 @@ add_custom_command(OUTPUT ${cython_output} DEPENDS ${cy_srcs} COMMENT "Cythonizing extension ${cython_src}") -add_library(${cython_module} MODULE ${cython_output}) +pybind11_add_module(${cython_module} MODULE ${cython_output}) -set_target_properties(${cython_module} - PROPERTIES PREFIX "${PYTHON_MODULE_PREFIX}" - SUFFIX "${PYTHON_MODULE_EXTENSION}") - -target_include_directories(${cython_module} PUBLIC - ${PYTHON_INCLUDE_DIRS}) - -target_compile_definitions(${cython_module} PRIVATE VERSION_INFO=${SCM_VERSION_INFO}) +target_compile_definitions( + ${cython_module} PRIVATE VERSION_INFO=${SCM_VERSION_INFO} +) # here we get to jump through some hoops to find libre2 on the manylinux # docker CI images, etc -find_package(re2 CONFIG NAMES re2) +if(NOT MSVC) + find_package(re2 CONFIG NAMES re2) +endif() if(re2_FOUND) message(STATUS "System re2 found") target_link_libraries(${cython_module} PRIVATE re2::re2) -elseif(NOT MSVC) +else() message(STATUS "Trying PkgConfig") find_package(PkgConfig REQUIRED) pkg_check_modules(RE2 IMPORTED_TARGET re2) @@ -57,12 +54,12 @@ endif() if(APPLE) # macos/appleclang needs this - target_link_libraries(${cython_module} PRIVATE pybind11::module) - target_link_libraries(${cython_module} PRIVATE pybind11::python_link_helper) + target_link_libraries(${cython_module} PUBLIC pybind11::module) + target_link_libraries(${cython_module} PUBLIC pybind11::python_link_helper) endif() if(MSVC) - target_compile_options(${cython_module} PRIVATE /utf-8) - target_link_libraries(${cython_module} PRIVATE ${PYTHON_LIBRARIES}) - target_link_libraries(${cython_module} PRIVATE pybind11::windows_extras) + target_compile_options(${cython_module} PUBLIC /utf-8) + target_link_libraries(${cython_module} PUBLIC ${Python_LIBRARIES}) + target_link_libraries(${cython_module} PUBLIC pybind11::windows_extras) endif() diff --git a/src/compile.pxi b/src/compile.pxi index 887a2778..588584fd 100644 --- a/src/compile.pxi +++ b/src/compile.pxi @@ -1,6 +1,6 @@ def compile(pattern, int flags=0, int max_mem=8388608): - cachekey = (type(pattern), pattern, flags) + cachekey = (type(pattern), pattern, flags, current_notification) if cachekey in _cache: return _cache[cachekey] p = _compile(pattern, flags, max_mem) @@ -87,7 +87,7 @@ def _compile(object pattern, int flags=0, int max_mem=8388608): raise RegexError(error_msg) elif error_code not in (ErrorBadPerlOp, ErrorRepeatSize, # ErrorBadEscape, - ErrorPatternTooLarge): + ErrorRepeatOp, ErrorPatternTooLarge): # Raise an error because these will not be fixed by using the # ``re`` module. raise RegexError(error_msg) diff --git a/src/re2.pyx b/src/re2.pyx index a8bc264e..d679540e 100644 --- a/src/re2.pyx +++ b/src/re2.pyx @@ -121,8 +121,27 @@ UNICODE = re.UNICODE VERBOSE = re.VERBOSE LOCALE = re.LOCALE DEBUG = re.DEBUG +NOFLAG = 0 # Python 3.11 ASCII = 256 # Python 3 +if sys.version_info[:2] >= (3, 11): + import enum + + @enum.global_enum + @enum._simple_enum(enum.IntFlag, boundary=enum.KEEP) + class RegexFlag: + NOFLAG = 0 + ASCII = A = re.ASCII # assume ascii "locale" + IGNORECASE = I = re.IGNORECASE # ignore case + LOCALE = L = re.LOCALE # assume current 8-bit locale + UNICODE = U = re.UNICODE # assume unicode "locale" + MULTILINE = M = re.MULTILINE # make anchors look for newline + DOTALL = S = re.DOTALL # make dot match newline + VERBOSE = X = re.VERBOSE # ignore whitespace and comments + DEBUG = re.DEBUG # dump pattern after compilation + __str__ = object.__str__ + _numeric_repr_ = hex + FALLBACK_QUIETLY = 0 FALLBACK_WARNING = 1 FALLBACK_EXCEPTION = 2 @@ -456,6 +475,7 @@ __all__ = [ 'FALLBACK_EXCEPTION', 'FALLBACK_QUIETLY', 'FALLBACK_WARNING', 'DEBUG', 'S', 'DOTALL', 'I', 'IGNORECASE', 'L', 'LOCALE', 'M', 'MULTILINE', 'U', 'UNICODE', 'X', 'VERBOSE', 'VERSION', 'VERSION_HEX', + 'NOFLAG', 'RegexFlag', # classes 'Match', 'Pattern', 'SREPattern', # functions diff --git a/tests/re_utils.py b/tests/re_utils.py index 348c3ce9..6ddecd9b 100644 --- a/tests/re_utils.py +++ b/tests/re_utils.py @@ -550,8 +550,9 @@ # lookbehind: split by : but not if it is escaped by -. ('(? updated for py311+ + # by removing one backslash from each set of 3 + (r'(?>> re2.search(r'((.*)+.)', 'a').groups() ('a', '') + >>> re.search(r'((.*)*.)', 'a').groups() + ('a', '') + >>> re2.search(r'((.*)*.)', 'a').groups() + ('a', '') The following show different behavior for re and re2: @@ -28,11 +32,4 @@ The following show different behavior for re and re2: >>> re2.search(r'((.*)*.)', 'Hello').groups() ('Hello', 'Hell') -This one was formerly a None vs empty string difference until July 2021: - - >>> re.search(r'((.*)*.)', 'a').groups() - ('a', '') - >>> re2.search(r'((.*)*.)', 'a').groups() - ('a', '') - >>> re2.set_fallback_notification(re2.FALLBACK_QUIETLY) diff --git a/tests/test_re.py b/tests/test_re.py index 57992778..9fd541ed 100644 --- a/tests/test_re.py +++ b/tests/test_re.py @@ -1,14 +1,19 @@ from __future__ import print_function -try: - from test.test_support import verbose -except ImportError: - from test.support import verbose -import re2 as re -from re import Scanner + import os import sys import traceback from weakref import proxy + +import re2 as re +from re import Scanner + +try: + from test import support + from test.support import verbose +except ImportError: # import error on Windows + verbose = re.VERBOSE + if sys.version_info[0] > 2: unicode = str unichr = chr @@ -254,11 +259,10 @@ def test_re_match(self): # A single group m = re.match('(a)', 'a') self.assertEqual(m.group(0), 'a') - self.assertEqual(m.group(0), 'a') self.assertEqual(m.group(1), 'a') + self.assertEqual(m.group(0, 0), ('a', 'a')) self.assertEqual(m.group(1, 1), ('a', 'a')) - self.assertEqual(m[0], 'a') - self.assertEqual(m[1], 'a') + self.assertEqual(m.groups(), ('a',)) pat = re.compile('(?:(?Pa)|(?Pb))(?Pc)?') self.assertEqual(pat.match('a').group(1, 2, 3), ('a', None, None)) @@ -690,9 +694,9 @@ def test_dealloc(self): def test_re_suite(): try: - from tests.re_utils import benchmarks, tests, SUCCEED, FAIL, SYNTAX_ERROR + from tests.re_utils import tests, SUCCEED, FAIL, SYNTAX_ERROR except ImportError: - from re_utils import benchmarks, tests, SUCCEED, FAIL, SYNTAX_ERROR + from re_utils import tests, SUCCEED, FAIL, SYNTAX_ERROR if verbose: print('\nRunning test_re_suite ...') diff --git a/tox.ini b/tox.ini index 4059b7a5..3c3e8215 100644 --- a/tox.ini +++ b/tox.ini @@ -5,15 +5,43 @@ isolated_build = true skipsdist=True [gh-actions] -3.7 = py37 -3.8 = py38 -3.9 = py39 -3.10 = py310 -3.11 = py311 -3.12 = py312 + 3.8: py38 +python = + 3.7: py37 + 3.8: py38 + 3.9: py39 + 3.10: py310 + 3.11: py311 + 3.12: py312 + +[gh-actions:env] +PLATFORM = + ubuntu-22.04: linux + macos-latest: macos + windows-latest: windows + +[base] +deps = + pip>=21.1 + setuptools_scm[toml] + +[build] +deps = + pip>=21.1 + build + twine [testenv] +skip_install = true + +setenv = + PYTHONPATH = {toxinidir} + passenv = + HOME + USERNAME + USER + XDG_* CI CC CXX @@ -22,19 +50,24 @@ passenv = CMAKE_GENERATOR PIP_DOWNLOAD_CACHE +allowlist_externals = + bash + deps = - pip>=24 - path + {[base]deps} + .[test] commands = - python -c "import path; path.Path('build').rmtree_p()" - pip install -e .[test] pytest -v . [testenv:dev] skip_install = true passenv = + HOME + USERNAME + USER + XDG_* CI CC CXX @@ -44,18 +77,16 @@ passenv = PIP_DOWNLOAD_CACHE setenv = - PYTHONPATH=. + PYTHONPATH = {toxinidir} deps = - pip>=24 - cython>=3.0.8 - path - pytest - setuptools + {[base]deps} + #-r requirements-dev.txt + -e .[test] commands = - python -c "import path; path.Path('build').rmtree_p()" - python setup.py build_ext --inplace + # this is deprecated => _DeprecatedInstaller warning from setuptools + #python setup.py build_ext --inplace # use --capture=no to see all the doctest output python -m pytest -v --ignore=tests/test_re.py --doctest-glob=*.txt . python -m pytest -v tests/test_re.py @@ -71,15 +102,41 @@ passenv = PIP_DOWNLOAD_CACHE deps = - pip>=24 - path + {[base]deps} + .[perf] commands = - python -c "import path; path.Path('build').rmtree_p()" - pip install .[perf] python tests/performance.py -[testenv:deploy] +[testenv:{docs,ldocs,cdocs}] +# these tox env cmds share a virtual env using the following plugin +# https://github.com/masenf/tox-ignore-env-name-mismatch +envdir = {toxworkdir}/docs +runner = ignore_env_name_mismatch +skip_install = true + +description = + docs: Build the docs using sphinx + ldocs: Lint the docs (mainly link checking) + cdocs: Clean the docs build artifacts + changes: Generate full or partial changelog; use git delta syntax for changes-since + +allowlist_externals = + make + bash + +deps = + {[base]deps} + gitchangelog @ https://github.com/sarnold/gitchangelog/releases/download/3.2.0/gitchangelog-3.2.0.tar.gz + -e .[doc] # using editable here is the "best" equivalent to build_ext --inplace + +commands = + docs: make -C docs html + ldocs: make -C docs linkcheck + cdocs: make -C docs clean + changes: bash -c 'gitchangelog {posargs} > CHANGELOG.rst' + +[testenv:build] passenv = pythonLocation CI @@ -93,17 +150,11 @@ passenv = allowlist_externals = bash deps = - pip>=24 - build - twine - path + {[build]deps} commands = - python -c "import path; path.Path('build').rmtree_p()" python -m build . twine check dist/* - python -m pip install https://github.com/sarnold/gitchangelog/archive/3.1.2.tar.gz - bash -c 'gitchangelog $(git describe --abbrev=0)..' [testenv:check] skip_install = true @@ -113,10 +164,31 @@ passenv = allowlist_externals = bash deps = - pip>=24 - pytest + pip>=20.0.1 commands = pip install pyre2-updated --force-reinstall --prefer-binary -f dist/ python -m unittest discover -f -s . - #pytest --doctest-glob="*.txt" + +[testenv:style] +envdir = {toxworkdir}/tests + +passenv = + {[testenv:tests]passenv} + +deps = + pip>=23.1 + cython-lint + +commands = + cython-lint src/ +[testenv:clean] +skip_install = true +allowlist_externals = + bash + +deps = + pip>=21.1 + +commands = + bash -c 'rm -rf src/*.egg-info re2*.so src/re2*.so src/re2.cpp *coverage.* tests/__pycache__ dist/ build/' diff --git a/toxfile.py b/toxfile.py new file mode 100644 index 00000000..ae19a7b6 --- /dev/null +++ b/toxfile.py @@ -0,0 +1,77 @@ +""" +https://github.com/masenf/tox-ignore-env-name-mismatch + +MIT License +Copyright (c) 2023 Masen Furer +""" +from contextlib import contextmanager +from typing import Any, Iterator, Optional, Sequence, Tuple + +from tox.plugin import impl +from tox.tox_env.api import ToxEnv +from tox.tox_env.info import Info +from tox.tox_env.python.virtual_env.runner import VirtualEnvRunner +from tox.tox_env.register import ToxEnvRegister + + +class FilteredInfo(Info): + """Subclass of Info that optionally filters specific keys during compare().""" + + def __init__( + self, + *args: Any, + filter_keys: Optional[Sequence[str]] = None, + filter_section: Optional[str] = None, + **kwargs: Any, + ): + """ + :param filter_keys: key names to pop from value + :param filter_section: if specified, only pop filter_keys when the compared section matches + + All other args and kwargs are passed to super().__init__ + """ + self.filter_keys = filter_keys + self.filter_section = filter_section + super().__init__(*args, **kwargs) + + @contextmanager + def compare( + self, + value: Any, + section: str, + sub_section: Optional[str] = None, + ) -> Iterator[Tuple[bool, Optional[Any]]]: + """Perform comparison and update cached info after filtering `value`.""" + if self.filter_section is None or section == self.filter_section: + try: + value = value.copy() + except AttributeError: # pragma: no cover + pass + else: + for fkey in self.filter_keys or []: + value.pop(fkey, None) + with super().compare(value, section, sub_section) as rv: + yield rv + + +class IgnoreEnvNameMismatchVirtualEnvRunner(VirtualEnvRunner): + """EnvRunner that does NOT save the env name as part of the cached info.""" + + @staticmethod + def id() -> str: + return "ignore_env_name_mismatch" + + @property + def cache(self) -> Info: + """Return a modified Info class that does NOT pass "name" key to `Info.compare`.""" + return FilteredInfo( + self.env_dir, + filter_keys=["name"], + filter_section=ToxEnv.__name__, + ) + + +@impl +def tox_register_tox_env(register: ToxEnvRegister) -> None: + """tox4 entry point: add IgnoreEnvNameMismatchVirtualEnvRunner to registry.""" + register.add_run_env(IgnoreEnvNameMismatchVirtualEnvRunner)