diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 5010029..1962dd1 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.5.0.post1 +current_version = 0.5.1 commit = True tag = True @@ -22,3 +22,5 @@ search = version = "{current_version}" replace = version = "{new_version}" [bumpversion:file:.github/workflows/conda_ci.yml] +search = ={current_version}=py_1 +replace = ={new_version}=py_1 diff --git a/.dependabot/config.yml b/.dependabot/config.yml deleted file mode 100644 index 4584924..0000000 --- a/.dependabot/config.yml +++ /dev/null @@ -1,9 +0,0 @@ -# This file is managed by 'repo_helper'. Don't edit it directly. ---- -version: 1 -update_configs: -- package_manager: python - directory: / - update_schedule: weekly - default_reviewers: - - domdfcoding diff --git a/.github/actions_build_conda.sh b/.github/actions_build_conda.sh deleted file mode 100755 index 1c8409e..0000000 --- a/.github/actions_build_conda.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash -# This file is managed by 'repo_helper'. Don't edit it directly. - -set -e -x - -python -m mkrecipe --type wheel || exit 1 - -# Switch to miniconda -source "/home/runner/miniconda/etc/profile.d/conda.sh" -hash -r -conda activate base -conda config --set always_yes yes --set changeps1 no -conda install conda=4.8.5 conda-build=3.18.11 -conda info -a - -conda config --add channels conda-forge || exit 1 -conda config --add channels domdfcoding || exit 1 -conda config --remove channels defaults - -conda build conda -c conda-forge -c domdfcoding --output-folder conda/dist --skip-existing - -exit 0 diff --git a/.github/actions_deploy_conda.sh b/.github/actions_deploy_conda.sh deleted file mode 100755 index 35aff28..0000000 --- a/.github/actions_deploy_conda.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash -# This file is managed by 'repo_helper'. Don't edit it directly. - -set -e -x - -# Switch to miniconda -source "/home/runner/miniconda/etc/profile.d/conda.sh" -hash -r -conda activate base -conda config --set always_yes yes --set changeps1 no -conda install conda=4.8.5 anaconda-client -conda info -a - -for f in conda/dist/noarch/flake8-encodings-*.tar.bz2; do - [ -e "$f" ] || continue - echo "$f" - conda install "$f" || exit 1 - echo "Deploying to Anaconda.org..." - anaconda -t "$ANACONDA_TOKEN" upload "$f" || exit 1 - echo "Successfully deployed to Anaconda.org." -done - -exit 0 diff --git a/.github/dependabot.yml b/.github/dependabot.yml index e769ad3..454225a 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -6,5 +6,6 @@ updates: directory: / schedule: interval: weekly + open-pull-requests-limit: 0 reviewers: - domdfcoding diff --git a/.github/stale.yml b/.github/stale.yml index e5625b7..bb7fa62 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -7,7 +7,7 @@ daysUntilStale: 180 # Number of days of inactivity before an Issue or Pull Request with the stale label is closed. # Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale. -daysUntilClose: 180 +daysUntilClose: false # Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled) onlyLabels: [] @@ -31,10 +31,10 @@ exemptAssignees: false staleLabel: stale # Comment to post when marking as stale. Set to `false` to disable -markComment: > - This issue has been automatically marked as stale because it has not had - recent activity. It will be closed if no further activity occurs. Thank you - for your contributions. +markComment: false +# This issue has been automatically marked as stale because it has not had +# recent activity. It will be closed if no further activity occurs. Thank you +# for your contributions. # Comment to post when removing the stale label. # unmarkComment: > diff --git a/.github/workflows/conda_ci.yml b/.github/workflows/conda_ci.yml index b5ede68..9b3fbc7 100644 --- a/.github/workflows/conda_ci.yml +++ b/.github/workflows/conda_ci.yml @@ -12,25 +12,28 @@ permissions: jobs: tests: name: "Conda" - runs-on: ubuntu-18.04 + runs-on: ubuntu-22.04 defaults: run: shell: bash -l {0} steps: - name: Checkout 🛎️ - uses: "actions/checkout@v2" + uses: "actions/checkout@v4" - name: Setup Python 🐍 - uses: "actions/setup-python@v2" + uses: "actions/setup-python@v5" with: - python-version: "3.8" + python-version: "3.11" - name: Setup Conda - uses: conda-incubator/setup-miniconda@v2 + uses: conda-incubator/setup-miniconda@v2.1.1 with: activate-environment: env - conda-build-version: 3.21.0 + conda-build-version: 3.28.4 + miniconda-version: py311_24.1.2-0 + python-version: "3.11" + miniforge-variant: Mambaforge - name: Install dependencies 🔧 run: | @@ -39,6 +42,7 @@ jobs: python -m pip install --upgrade pip setuptools wheel python -m pip install --upgrade "whey-conda" "whey" # $CONDA is an environment variable pointing to the root of the miniconda directory + $CONDA/bin/conda update -n base conda $CONDA/bin/conda config --add channels conda-forge $CONDA/bin/conda config --add channels domdfcoding @@ -54,7 +58,7 @@ jobs: - name: "Install package" run: | - $CONDA/bin/conda install -c file://$(pwd)/conda-bld flake8-encodings=0.5.0.post1=py_1 -y || exit 1 + $CONDA/bin/conda install -c file://$(pwd)/conda-bld flake8-encodings=0.5.1=py_1 -y || exit 1 - name: "Run Tests" run: | diff --git a/.github/workflows/docs_test_action.yml b/.github/workflows/docs_test_action.yml index bd2510e..8f60ba5 100644 --- a/.github/workflows/docs_test_action.yml +++ b/.github/workflows/docs_test_action.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout 🛎️ - uses: "actions/checkout@v2" + uses: "actions/checkout@v4" - name: Check for changed files uses: dorny/paths-filter@v2 diff --git a/.github/workflows/flake8.yml b/.github/workflows/flake8.yml index 84e9436..5e67c5c 100644 --- a/.github/workflows/flake8.yml +++ b/.github/workflows/flake8.yml @@ -16,11 +16,11 @@ permissions: jobs: Run: name: "Flake8" - runs-on: "ubuntu-18.04" + runs-on: "ubuntu-22.04" steps: - name: Checkout 🛎️ - uses: "actions/checkout@v2" + uses: "actions/checkout@v4" - name: Check for changed files uses: dorny/paths-filter@v2 @@ -33,9 +33,9 @@ jobs: - name: Setup Python 🐍 if: steps.changes.outputs.code == 'true' - uses: "actions/setup-python@v2" + uses: "actions/setup-python@v5" with: - python-version: "3.6" + python-version: "3.9" - name: Install dependencies 🔧 if: steps.changes.outputs.code == 'true' @@ -43,7 +43,7 @@ jobs: python -VV python -m site python -m pip install --upgrade pip setuptools wheel - python -m pip install tox + python -m pip install tox~=3.0 - name: "Run Flake8" if: steps.changes.outputs.code == 'true' diff --git a/.github/workflows/mypy.yml b/.github/workflows/mypy.yml index 5a7324b..4c22a52 100644 --- a/.github/workflows/mypy.yml +++ b/.github/workflows/mypy.yml @@ -20,12 +20,12 @@ jobs: strategy: matrix: - os: ['ubuntu-20.04', 'windows-2019'] + os: ['ubuntu-22.04', 'windows-2022'] fail-fast: false steps: - name: Checkout 🛎️ - uses: "actions/checkout@v2" + uses: "actions/checkout@v4" - name: Check for changed files uses: dorny/paths-filter@v2 @@ -38,16 +38,16 @@ jobs: - name: Setup Python 🐍 if: steps.changes.outputs.code == 'true' - uses: "actions/setup-python@v2" + uses: "actions/setup-python@v5" with: - python-version: "3.6" + python-version: "3.9" - name: Install dependencies 🔧 run: | python -VV python -m site python -m pip install --upgrade pip setuptools wheel - python -m pip install --upgrade tox virtualenv + python -m pip install --upgrade tox~=3.0 virtualenv!=20.16.0 - name: "Run mypy" if: steps.changes.outputs.code == 'true' diff --git a/.github/workflows/python_ci.yml b/.github/workflows/python_ci.yml index bb2372c..ca858d8 100644 --- a/.github/workflows/python_ci.yml +++ b/.github/workflows/python_ci.yml @@ -18,29 +18,30 @@ permissions: jobs: tests: - name: "windows-2019 / Python ${{ matrix.config.python-version }}" - runs-on: "windows-2019" + name: "windows-2022 / Python ${{ matrix.config.python-version }}" + runs-on: "windows-2022" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-alpha.5,pypy-3.6,pypy-3.7,pypy-3.8' + USING_COVERAGE: '3.7,3.8,3.9,3.10,3.11,3.12,3.13,pypy-3.7,pypy-3.8,pypy-3.9' strategy: fail-fast: False matrix: config: - - {python-version: "3.6", testenvs: "py36,build", experimental: False} - {python-version: "3.7", testenvs: "py37,build", experimental: False} - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - {python-version: "3.10", testenvs: "py310,build", experimental: False} - - {python-version: "3.11.0-alpha.5", testenvs: "py311-dev,build", experimental: True} - - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} - - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} - - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: True} + - {python-version: "3.11", testenvs: "py311,build", experimental: False} + - {python-version: "3.12", testenvs: "py312,build", experimental: False} + - {python-version: "3.13", testenvs: "py313,build", experimental: True} + - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: False} + - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: False} + - {python-version: "pypy-3.9-v7.3.15", testenvs: "pypy39,build", experimental: True} steps: - name: Checkout 🛎️ - uses: "actions/checkout@v2" + uses: "actions/checkout@v4" - name: Check for changed files if: startsWith(github.ref, 'refs/tags/') != true @@ -55,7 +56,7 @@ jobs: - name: Setup Python 🐍 id: setup-python if: ${{ steps.changes.outputs.code == 'true' || steps.changes.outcome == 'skipped' }} - uses: "actions/setup-python@v2" + uses: "actions/setup-python@v5" with: python-version: "${{ matrix.config.python-version }}" @@ -65,15 +66,16 @@ jobs: python -VV python -m site python -m pip install --upgrade pip setuptools wheel - python -m pip install --upgrade tox virtualenv + python -m pip install --upgrade tox~=3.0 virtualenv!=20.16.0 - name: "Run Tests for Python ${{ matrix.config.python-version }}" if: steps.setup-python.outcome == 'success' run: python -m tox -e "${{ matrix.config.testenvs }}" -s false - name: "Upload Coverage 🚀" - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 if: ${{ always() && steps.setup-python.outcome == 'success' }} with: name: "coverage-${{ matrix.config.python-version }}" path: .coverage + include-hidden-files: true diff --git a/.github/workflows/python_ci_linux.yml b/.github/workflows/python_ci_linux.yml index e394b48..01edd6b 100644 --- a/.github/workflows/python_ci_linux.yml +++ b/.github/workflows/python_ci_linux.yml @@ -19,29 +19,30 @@ permissions: jobs: tests: - name: "ubuntu-20.04 / Python ${{ matrix.config.python-version }}" - runs-on: "ubuntu-20.04" + name: "ubuntu-22.04 / Python ${{ matrix.config.python-version }}" + runs-on: "ubuntu-22.04" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-alpha.5,pypy-3.6,pypy-3.7,pypy-3.8' + USING_COVERAGE: '3.7,3.8,3.9,3.10,3.11,3.12,3.13,pypy-3.7,pypy-3.8,pypy-3.9' strategy: fail-fast: False matrix: config: - - {python-version: "3.6", testenvs: "py36,build", experimental: False} - {python-version: "3.7", testenvs: "py37,build", experimental: False} - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - {python-version: "3.10", testenvs: "py310,build", experimental: False} - - {python-version: "3.11.0-alpha.5", testenvs: "py311-dev,build", experimental: True} - - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} - - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} - - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: True} + - {python-version: "3.11", testenvs: "py311,build", experimental: False} + - {python-version: "3.12", testenvs: "py312,build", experimental: False} + - {python-version: "3.13", testenvs: "py313,build", experimental: True} + - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: False} + - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: False} + - {python-version: "pypy-3.9", testenvs: "pypy39,build", experimental: True} steps: - name: Checkout 🛎️ - uses: "actions/checkout@v2" + uses: "actions/checkout@v4" - name: Check for changed files if: startsWith(github.ref, 'refs/tags/') != true @@ -56,7 +57,7 @@ jobs: - name: Setup Python 🐍 id: setup-python if: ${{ steps.changes.outputs.code == 'true' || steps.changes.outcome == 'skipped' }} - uses: "actions/setup-python@v2" + uses: "actions/setup-python@v5" with: python-version: "${{ matrix.config.python-version }}" @@ -66,7 +67,7 @@ jobs: python -VV python -m site python -m pip install --upgrade pip setuptools wheel - python -m pip install --upgrade tox virtualenv + python -m pip install --upgrade tox~=3.0 virtualenv!=20.16.0 python -m pip install --upgrade coverage_pyver_pragma - name: "Run Tests for Python ${{ matrix.config.python-version }}" @@ -74,22 +75,23 @@ jobs: run: python -m tox -e "${{ matrix.config.testenvs }}" -s false - name: "Upload Coverage 🚀" - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 if: ${{ always() && steps.setup-python.outcome == 'success' }} with: name: "coverage-${{ matrix.config.python-version }}" path: .coverage + include-hidden-files: true Coverage: needs: tests - runs-on: "ubuntu-20.04" + runs-on: "ubuntu-22.04" steps: - name: Checkout 🛎️ - uses: "actions/checkout@v2" + uses: "actions/checkout@v4" - name: Setup Python 🐍 - uses: "actions/setup-python@v2" + uses: "actions/setup-python@v5" with: python-version: 3.8 @@ -99,7 +101,7 @@ jobs: python -m pip install --upgrade "coveralls>=3.0.0" coverage_pyver_pragma - name: "Download Coverage 🪂" - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v4 with: path: coverage @@ -117,10 +119,11 @@ jobs: - name: "Upload Combined Coverage Artefact 🚀" if: ${{ steps.show.outcome != 'failure' }} - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: "combined-coverage" path: .coverage + include-hidden-files: true - name: "Upload Combined Coverage to Coveralls" if: ${{ steps.show.outcome != 'failure' }} @@ -132,14 +135,14 @@ jobs: Deploy: needs: tests - runs-on: "ubuntu-20.04" + runs-on: "ubuntu-22.04" steps: - name: Checkout 🛎️ - uses: "actions/checkout@v2" + uses: "actions/checkout@v4" if: startsWith(github.ref, 'refs/tags/') - name: Setup Python 🐍 - uses: "actions/setup-python@v2" + uses: "actions/setup-python@v5" if: startsWith(github.ref, 'refs/tags/') with: python-version: 3.8 @@ -148,7 +151,7 @@ jobs: if: startsWith(github.ref, 'refs/tags/') run: | python -m pip install --upgrade pip setuptools wheel - python -m pip install --upgrade tox + python -m pip install --upgrade tox~=3.0 - name: Build distributions 📦 if: startsWith(github.ref, 'refs/tags/') @@ -176,33 +179,61 @@ jobs: Conda: needs: deploy - runs-on: "ubuntu-18.04" + runs-on: ubuntu-22.04 if: startsWith(github.ref, 'refs/tags/') || (startsWith(github.event.head_commit.message, 'Bump version') != true) steps: - name: Checkout 🛎️ - uses: "actions/checkout@v2" + uses: "actions/checkout@v4" - name: Setup Python 🐍 - uses: "actions/setup-python@v2" + uses: "actions/setup-python@v5" with: - python-version: 3.8 + python-version: 3.11 + + - name: Setup Conda + uses: conda-incubator/setup-miniconda@v2.1.1 + with: + activate-environment: env + conda-build-version: 3.28.4 + miniconda-version: py311_24.1.2-0 + python-version: "3.11" + miniforge-variant: Mambaforge - name: Install dependencies 🔧 run: | + python -VV + python -m site python -m pip install --upgrade pip setuptools wheel python -m pip install --upgrade "mkrecipe" "whey" + # $CONDA is an environment variable pointing to the root of the miniconda directory + $CONDA/bin/conda config --set always_yes yes --set changeps1 no + $CONDA/bin/conda update -n base conda + $CONDA/bin/conda info -a + $CONDA/bin/conda install conda-forge::py-lief=0.14.1 + $CONDA/bin/conda config --add channels conda-forge + $CONDA/bin/conda config --add channels domdfcoding - wget https://repo.anaconda.com/miniconda/Miniconda3-py38_4.10.3-Linux-x86_64.sh -O miniconda.sh - bash miniconda.sh -b -p $HOME/miniconda + $CONDA/bin/conda config --remove channels defaults - - name: Build Conda 📦 + - name: Build Conda Package 📦 run: | - chmod +x .github/actions_build_conda.sh - bash .github/actions_build_conda.sh + python -m mkrecipe --type wheel || exit 1 + $CONDA/bin/conda build conda -c conda-forge -c domdfcoding --output-folder conda/dist - - name: Deploy Conda 🚀 + - name: Deploy Conda Package 🚀 + if: startsWith(github.ref, 'refs/tags/') run: | - chmod +x .github/actions_deploy_conda.sh - bash .github/actions_deploy_conda.sh + $CONDA/bin/conda config --set always_yes yes --set changeps1 no + $CONDA/bin/conda install anaconda-client + $CONDA/bin/conda info -a + + for f in conda/dist/noarch/flake8-encodings-*.tar.bz2; do + [ -e "$f" ] || continue + echo "$f" + conda install "$f" || exit 1 + echo "Deploying to Anaconda.org..." + $CONDA/bin/anaconda -t "$ANACONDA_TOKEN" upload "$f" || exit 1 + echo "Successfully deployed to Anaconda.org." + done env: ANACONDA_TOKEN: ${{ secrets.ANACONDA_TOKEN }} diff --git a/.github/workflows/python_ci_macos.yml b/.github/workflows/python_ci_macos.yml index c72ebe9..280a25b 100644 --- a/.github/workflows/python_ci_macos.yml +++ b/.github/workflows/python_ci_macos.yml @@ -18,28 +18,30 @@ permissions: jobs: tests: - name: "macos-latest / Python ${{ matrix.config.python-version }}" - runs-on: "macos-latest" + name: "macos-${{ matrix.config.os-ver }} / Python ${{ matrix.config.python-version }}" + runs-on: "macos-${{ matrix.config.os-ver }}" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-alpha.5,pypy-3.7,pypy-3.8' + USING_COVERAGE: '3.7,3.8,3.9,3.10,3.11,3.12,3.13,pypy-3.7,pypy-3.8,pypy-3.9' strategy: fail-fast: False matrix: config: - - {python-version: "3.6", testenvs: "py36,build", experimental: False} - - {python-version: "3.7", testenvs: "py37,build", experimental: False} - - {python-version: "3.8", testenvs: "py38,build", experimental: False} - - {python-version: "3.9", testenvs: "py39,build", experimental: False} - - {python-version: "3.10", testenvs: "py310,build", experimental: False} - - {python-version: "3.11.0-alpha.5", testenvs: "py311-dev,build", experimental: True} - - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} - - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: True} + - {python-version: "3.7", os-ver: "13", testenvs: "py37,build", experimental: False} + - {python-version: "3.8", os-ver: "14", testenvs: "py38,build", experimental: False} + - {python-version: "3.9", os-ver: "14", testenvs: "py39,build", experimental: False} + - {python-version: "3.10", os-ver: "14", testenvs: "py310,build", experimental: False} + - {python-version: "3.11", os-ver: "14", testenvs: "py311,build", experimental: False} + - {python-version: "3.12", os-ver: "14", testenvs: "py312,build", experimental: False} + - {python-version: "3.13", os-ver: "14", testenvs: "py313,build", experimental: True} + - {python-version: "pypy-3.7", os-ver: "13", testenvs: "pypy37,build", experimental: False} + - {python-version: "pypy-3.8", os-ver: "14", testenvs: "pypy38,build", experimental: False} + - {python-version: "pypy-3.9", os-ver: "14", testenvs: "pypy39,build", experimental: True} steps: - name: Checkout 🛎️ - uses: "actions/checkout@v2" + uses: "actions/checkout@v4" - name: Check for changed files if: startsWith(github.ref, 'refs/tags/') != true @@ -54,7 +56,7 @@ jobs: - name: Setup Python 🐍 id: setup-python if: ${{ steps.changes.outputs.code == 'true' || steps.changes.outcome == 'skipped' }} - uses: "actions/setup-python@v2" + uses: "actions/setup-python@v5" with: python-version: "${{ matrix.config.python-version }}" @@ -64,15 +66,16 @@ jobs: python -VV python -m site python -m pip install --upgrade pip setuptools wheel - python -m pip install --upgrade tox virtualenv + python -m pip install --upgrade tox~=3.0 virtualenv!=20.16.0 - name: "Run Tests for Python ${{ matrix.config.python-version }}" if: steps.setup-python.outcome == 'success' run: python -m tox -e "${{ matrix.config.testenvs }}" -s false - name: "Upload Coverage 🚀" - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 if: ${{ always() && steps.setup-python.outcome == 'success' }} with: name: "coverage-${{ matrix.config.python-version }}" path: .coverage + include-hidden-files: true diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ff8fc63..5e5cd22 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,9 +3,12 @@ exclude: ^$ +ci: + autoupdate_schedule: quarterly + repos: - repo: https://github.com/repo-helper/pyproject-parser - rev: v0.4.2 + rev: v0.13.0 hooks: - id: reformat-pyproject @@ -30,7 +33,7 @@ repos: - id: end-of-file-fixer - repo: https://github.com/domdfcoding/pre-commit-hooks - rev: v0.3.0 + rev: v0.4.0 hooks: - id: requirements-txt-sorter args: @@ -39,19 +42,19 @@ repos: exclude: ^(doc-source/conf|__pkginfo__|setup|tests/.*)\.py$ - id: bind-requirements - - repo: https://github.com/domdfcoding/flake8-dunder-all - rev: v0.1.8 + - repo: https://github.com/python-formate/flake8-dunder-all + rev: v0.4.1 hooks: - id: ensure-dunder-all files: ^flake8_encodings/.*\.py$ - repo: https://github.com/domdfcoding/flake2lint - rev: v0.4.1 + rev: v0.4.3 hooks: - id: flake2lint - repo: https://github.com/pre-commit/pygrep-hooks - rev: v1.9.0 + rev: v1.10.0 hooks: - id: python-no-eval - id: rst-backticks @@ -67,24 +70,24 @@ repos: - --keep-runtime-typing - repo: https://github.com/Lucas-C/pre-commit-hooks - rev: v1.1.11 + rev: v1.5.1 hooks: - id: remove-crlf - id: forbid-crlf - repo: https://github.com/python-formate/snippet-fmt - rev: v0.1.4 + rev: v0.1.5 hooks: - id: snippet-fmt - repo: https://github.com/python-formate/formate - rev: v0.4.9 + rev: v0.8.0 hooks: - id: formate exclude: ^(doc-source/conf|__pkginfo__|setup)\.(_)?py$ - - repo: https://github.com/domdfcoding/dep_checker - rev: v0.6.2 + - repo: https://github.com/python-coincidence/dep_checker + rev: v0.8.0 hooks: - id: dep_checker args: diff --git a/.readthedocs.yml b/.readthedocs.yml index 797133e..2dee4b5 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -9,11 +9,16 @@ formats: - pdf - htmlzip python: - version: 3.8 install: - requirements: requirements.txt - requirements: doc-source/requirements.txt - - method: pip - path: . - extra_requirements: - - classes +build: + os: ubuntu-22.04 + tools: + python: '3.9' + jobs: + post_create_environment: + - pip install .[classes] + post_install: + - pip install sphinxcontrib-applehelp==1.0.4 sphinxcontrib-devhelp==1.0.2 sphinxcontrib-htmlhelp==2.0.1 + sphinxcontrib-jsmath==1.0.1 sphinxcontrib-qthelp==1.0.3 sphinxcontrib-serializinghtml==1.1.5 diff --git a/README.rst b/README.rst index 46d1f68..81f8207 100644 --- a/README.rst +++ b/README.rst @@ -58,8 +58,8 @@ flake8-encodings :target: https://github.com/python-formate/flake8-encodings/actions?query=workflow%3A%22mypy%22 :alt: mypy status -.. |requires| image:: https://dependency-dash.herokuapp.com/github/python-formate/flake8-encodings/badge.svg - :target: https://dependency-dash.herokuapp.com/github/python-formate/flake8-encodings/ +.. |requires| image:: https://dependency-dash.repo-helper.uk/github/python-formate/flake8-encodings/badge.svg + :target: https://dependency-dash.repo-helper.uk/github/python-formate/flake8-encodings/ :alt: Requirements Status .. |coveralls| image:: https://img.shields.io/coveralls/github/python-formate/flake8-encodings/master?logo=coveralls @@ -101,7 +101,7 @@ flake8-encodings .. |language| image:: https://img.shields.io/github/languages/top/python-formate/flake8-encodings :alt: GitHub top language -.. |commits-since| image:: https://img.shields.io/github/commits-since/python-formate/flake8-encodings/v0.5.0.post1 +.. |commits-since| image:: https://img.shields.io/github/commits-since/python-formate/flake8-encodings/v0.5.1 :target: https://github.com/python-formate/flake8-encodings/pulse :alt: GitHub commits since tagged version @@ -109,7 +109,7 @@ flake8-encodings :target: https://github.com/python-formate/flake8-encodings/commit/master :alt: GitHub last commit -.. |maintained| image:: https://img.shields.io/maintenance/yes/2022 +.. |maintained| image:: https://img.shields.io/maintenance/yes/2025 :alt: Maintenance .. |pypi-downloads| image:: https://img.shields.io/pypi/dm/flake8-encodings @@ -149,7 +149,7 @@ To install with ``conda``: .. end installation -In version 0.5.0.post1 and above the functionality for checking classes +In version 0.5.1 and above the functionality for checking classes (``configparser.ConfigParser`` and ``pathlib.Path`` for now) requires the ``classes`` extra to be installed: diff --git a/doc-source/_static/style.css b/doc-source/_static/style.css index 7077a55..a6b8e4d 100644 --- a/doc-source/_static/style.css +++ b/doc-source/_static/style.css @@ -13,3 +13,7 @@ div.versionchanged ul, div.versionremoved ul { margin-left: 20px; margin-top: 0; } + +.longtable.autosummary { + width: 100%; +} diff --git a/doc-source/conf.py b/doc-source/conf.py index 13e8a3f..8eb3017 100644 --- a/doc-source/conf.py +++ b/doc-source/conf.py @@ -27,7 +27,8 @@ slug = re.sub(r'\W+', '-', project.lower()) release = version = config.version -todo_include_todos = bool(os.environ.get("SHOW_TODOS", 0)) +sphinx_builder = os.environ.get("SPHINX_BUILDER", "html").lower() +todo_include_todos = int(os.environ.get("SHOW_TODOS", 0)) and sphinx_builder != "latex" intersphinx_mapping = { "python": ("https://docs.python.org/3/", None), @@ -70,11 +71,39 @@ } +# Fix for pathlib issue with sphinxemoji on Python 3.9 and Sphinx 4.x +def copy_asset_files(app, exc): + # 3rd party + from domdf_python_tools.compat import importlib_resources + from sphinx.util.fileutil import copy_asset + + if exc: + return + + asset_files = ["twemoji.js", "twemoji.css"] + for path in asset_files: + path_str = os.fspath(importlib_resources.files("sphinxemoji") / path) + copy_asset(path_str, os.path.join(app.outdir, "_static")) + + def setup(app): # 3rd party from sphinx_toolbox.latex import better_header_layout + from sphinxemoji import sphinxemoji app.connect("config-inited", lambda app, config: better_header_layout(config)) - - + app.connect("build-finished", copy_asset_files) + app.add_js_file("https://unpkg.com/twemoji@latest/dist/twemoji.min.js") + app.add_js_file("twemoji.js") + app.add_css_file("twemoji.css") + app.add_transform(sphinxemoji.EmojiSubstitutions) + + +needspace_amount = r"5\baselineskip" +favicons = [{ + "rel": "icon", + "href": "https://python-formate.github.io/assets/formate.ico", + "sizes": "48x48", + "type": "image/vnd.microsoft.icon" + }] nitpicky = True diff --git a/doc-source/index.rst b/doc-source/index.rst index 800db2f..b436d89 100644 --- a/doc-source/index.rst +++ b/doc-source/index.rst @@ -64,8 +64,8 @@ flake8-encodings :workflow: mypy :alt: mypy status - .. |requires| image:: https://dependency-dash.herokuapp.com/github/python-formate/flake8-encodings/badge.svg - :target: https://dependency-dash.herokuapp.com/github/python-formate/flake8-encodings/ + .. |requires| image:: https://dependency-dash.repo-helper.uk/github/python-formate/flake8-encodings/badge.svg + :target: https://dependency-dash.repo-helper.uk/github/python-formate/flake8-encodings/ :alt: Requirements Status .. |coveralls| coveralls-shield:: @@ -111,14 +111,14 @@ flake8-encodings :alt: GitHub top language .. |commits-since| github-shield:: - :commits-since: v0.5.0.post1 + :commits-since: v0.5.1 :alt: GitHub commits since tagged version .. |commits-latest| github-shield:: :last-commit: :alt: GitHub last commit - .. |maintained| maintained-shield:: 2022 + .. |maintained| maintained-shield:: 2025 :alt: Maintenance .. |pypi-downloads| pypi-shield:: @@ -143,7 +143,7 @@ Installation .. latex:vspace:: 20px -In version 0.5.0.post1 and above the functionality for checking classes +In version 0.5.1 and above the functionality for checking classes (:class:`~configparser.ConfigParser` and :class:`~.pathlib.Path` for now) requires the ``classes`` extra to be installed: diff --git a/doc-source/requirements.txt b/doc-source/requirements.txt index b37b827..3a34638 100644 --- a/doc-source/requirements.txt +++ b/doc-source/requirements.txt @@ -1,21 +1,21 @@ -git+https://github.com/sphinx-toolbox/sphinx-toolbox-experimental -default-values>=0.5.0 -extras-require>=0.2.0 -furo>=2020.11.19b18 -html-section>=0.1.0 -pyyaml>=5.3.1 -repo-helper-sphinx-theme>=0.0.2 -seed-intersphinx-mapping>=0.3.1 +default-values>=0.6.0 +extras-require>=0.5.0 +furo==2021.06.18b36 +html-section>=0.3.0 +seed-intersphinx-mapping>=1.2.2 sphinx>=3.0.3 sphinx-copybutton>=0.2.12 -sphinx-debuginfo>=0.1.0 -sphinx-licenseinfo>=0.1.1 +sphinx-debuginfo>=0.2.2 +sphinx-favicon>=0.2 +sphinx-licenseinfo>=0.3.1 sphinx-notfound-page>=0.7.1 -sphinx-prompt>=1.1.0 sphinx-pyproject>=0.1.0 -sphinx-tabs>=1.1.13 -sphinx-toolbox>=2.13.0 -sphinxcontrib-httpdomain>=1.7.0 +sphinx-toolbox>=3.5.0 +sphinxcontrib-applehelp==1.0.4 +sphinxcontrib-devhelp==1.0.2 +sphinxcontrib-htmlhelp==2.0.1 +sphinxcontrib-jsmath==1.0.1 +sphinxcontrib-qthelp==1.0.3 +sphinxcontrib-serializinghtml==1.1.5 sphinxemoji>=0.1.6 -tabulate>=0.8.7 -toctree-plus>=0.5.0 +toctree-plus>=0.6.1 diff --git a/doc-source/usage.rst b/doc-source/usage.rst index 3e2c9a5..e118e94 100644 --- a/doc-source/usage.rst +++ b/doc-source/usage.rst @@ -93,4 +93,4 @@ See `pre-commit `_ for instructions Sample ``.pre-commit-config.yaml``: -.. pre-commit:flake8:: 0.5.0.post1 +.. pre-commit:flake8:: 0.5.1 diff --git a/flake8_encodings/__init__.py b/flake8_encodings/__init__.py index c5cd8f9..76d0317 100644 --- a/flake8_encodings/__init__.py +++ b/flake8_encodings/__init__.py @@ -38,6 +38,7 @@ import ast import configparser import pathlib +import sys import tempfile from typing import TYPE_CHECKING, Callable, Iterator, List, Optional, Tuple, Type @@ -49,13 +50,13 @@ if TYPE_CHECKING: # 3rd party - from jedi import Script # type: ignore - from jedi.api.classes import Name # type: ignore + from jedi import Script # type: ignore[import-untyped] + from jedi.api.classes import Name # type: ignore[import-untyped] __author__: str = "Dominic Davis-Foster" __copyright__: str = "2020-2021 Dominic Davis-Foster" __license__: str = "MIT License" -__version__: str = "0.5.0.post1" +__version__: str = "0.5.1" __email__: str = "dominic@davis-foster.co.uk" __all__ = ["Visitor", "ClassVisitor", "Plugin"] @@ -92,10 +93,20 @@ def mode_is_binary(mode: ast.AST) -> Optional[bool]: if isinstance(mode, ast.Constant): # pragma: no cover ( None: """ Check the call represented by the given AST node is using encodings correctly. @@ -135,13 +146,13 @@ def check_open_encoding(self, node: ast.Call): if "encoding" not in kwargs: self.report_error(node, ENC003 if unknown_mode else ENC001) - elif isinstance(kwargs["encoding"], (ast.Constant, ast.NameConstant)): + elif isinstance(kwargs["encoding"], _constant_nameconstant): if kwargs["encoding"].value is None: self.report_error(node, ENC004 if unknown_mode else ENC002) check_encoding = check_open_encoding # deprecated - def visit_Call(self, node: ast.Call): # noqa: D102 + def visit_Call(self, node: ast.Call) -> None: # noqa: D102 if isinstance(node.func, ast.Name): @@ -157,11 +168,12 @@ def visit_Call(self, node: ast.Call): # noqa: D102 self.check_open_encoding(node) return - if isinstance(node.func.value, ast.Str): # pragma: no cover - # Attribute on a string - return self.generic_visit(node) + if not _skip_312_deprecations: # pragma: no cover (py312+) + if isinstance(node.func.value, ast.Str): # pragma: no cover + # Attribute on a string + return self.generic_visit(node) - elif isinstance(node.func.value, ast.BinOp): # pragma: no cover + if isinstance(node.func.value, ast.BinOp): # pragma: no cover # TODO # Expressions such as (tmp_pathplus / "code.py").write_text(example_source) return self.generic_visit(node) @@ -174,7 +186,7 @@ def visit_Call(self, node: ast.Call): # noqa: D102 self.generic_visit(node) -class ClassVisitor(Visitor): +class ClassVisitor(Visitor): # pragma: no cover (py313+) """ AST visitor to identify incorrect use of encodings, with support for :class:`pathlib.Path` and :class:`configparser.ConfigParser`. @@ -195,7 +207,7 @@ def __init__(self): self.filename = PathPlus("") self.jedi_script = jedi.Script('') - def first_visit(self, node: ast.AST, filename: PathPlus): + def first_visit(self, node: ast.AST, filename: PathPlus) -> None: """ Like :meth:`ast.NodeVisitor.visit`, but configures type inference. @@ -212,7 +224,7 @@ def first_visit(self, node: ast.AST, filename: PathPlus): self.jedi_script = jedi.Script(self.filename.read_text(), path=self.filename) self.visit(node) - def check_configparser_encoding(self, node: ast.Call): + def check_configparser_encoding(self, node: ast.Call) -> None: """ Check the call represented by the given AST node is using encodings correctly. @@ -226,11 +238,11 @@ def check_configparser_encoding(self, node: ast.Call): if "encoding" not in kwargs: self.report_error(node, ENC011) - elif isinstance(kwargs["encoding"], (ast.Constant, ast.NameConstant)): + elif isinstance(kwargs["encoding"], _constant_nameconstant): if kwargs["encoding"].value is None: self.report_error(node, ENC012) - def check_pathlib_encoding(self, node: ast.Call, method_name: str): + def check_pathlib_encoding(self, node: ast.Call, method_name: str) -> None: """ Check the call represented by the given AST node is using encodings correctly. @@ -275,11 +287,11 @@ def check_pathlib_encoding(self, node: ast.Call, method_name: str): if "encoding" not in kwargs: self.report_error(node, no_encoding) - elif isinstance(kwargs["encoding"], (ast.Constant, ast.NameConstant)): + elif isinstance(kwargs["encoding"], _constant_nameconstant): if kwargs["encoding"].value is None: self.report_error(node, encoding_none) - def visit_Call(self, node: ast.Call): # noqa: D102 + def visit_Call(self, node: ast.Call) -> None: # noqa: D102 if isinstance(node.func, ast.Name): @@ -295,11 +307,12 @@ def visit_Call(self, node: ast.Call): # noqa: D102 self.check_open_encoding(node) return - if isinstance(node.func.value, ast.Str): # pragma: no cover - # Attribute on a string - return self.generic_visit(node) + if not _skip_312_deprecations: # pragma: no cover (py312+) + if isinstance(node.func.value, ast.Str): # pragma: no cover + # Attribute on a string + return self.generic_visit(node) - elif isinstance(node.func.value, ast.BinOp): # pragma: no cover + if isinstance(node.func.value, ast.BinOp): # pragma: no cover # TODO # Expressions such as (tmp_pathplus / "code.py").write_text(example_source) return self.generic_visit(node) @@ -348,7 +361,7 @@ def __init__(self, tree: ast.AST, filename: PathLike): def run(self) -> Iterator[Tuple[int, int, str, Type["Plugin"]]]: # noqa: D102 - try: + try: # pragma: no cover (py313+) # 3rd party import jedi @@ -375,7 +388,7 @@ def run(self) -> Iterator[Tuple[int, int, str, Type["Plugin"]]]: # noqa: D102 yield line, col, msg, type(self) -def is_configparser_read(class_name: str, method_name: str) -> bool: +def is_configparser_read(class_name: str, method_name: str) -> bool: # pragma: no cover (py313+) """ Returns :py:obj:`True` if method is :meth:`configparser.ConfigParser.read` or :meth:`configparser.RawConfigParser.read`. @@ -395,7 +408,7 @@ def is_configparser_read(class_name: str, method_name: str) -> bool: return True -def is_pathlib_method(class_name: str, method_name: str) -> bool: +def is_pathlib_method(class_name: str, method_name: str) -> bool: # pragma: no cover (py313+) """ Returns :py:obj:`True` if method is :meth:`pathlib.Path.open`, :meth:`read_text() ` or :meth:`write_text() `. @@ -415,7 +428,7 @@ def is_pathlib_method(class_name: str, method_name: str) -> bool: return True -def get_inferred_types(jedi_script: "Script", node: ast.Call) -> List[str]: +def get_inferred_types(jedi_script: "Script", node: ast.Call) -> List[str]: # pragma: no cover (py313+) """ Returns a list of types inferred by ``jedi`` for the given call node. diff --git a/formate.toml b/formate.toml index d85fcd5..a2e27c5 100644 --- a/formate.toml +++ b/formate.toml @@ -6,21 +6,17 @@ noqa-reformat = 60 ellipsis-reformat = 70 squish_stubs = 80 -[config] -indent = "\t" -line_length = 115 - [hooks.yapf] priority = 30 -[hooks.isort] -priority = 50 - [hooks.yapf.kwargs] yapf_style = ".style.yapf" +[hooks.isort] +priority = 50 + [hooks.isort.kwargs] -indent = "\t\t" +indent = " " multi_line_output = 8 import_heading_stdlib = "stdlib" import_heading_thirdparty = "3rd party" @@ -52,4 +48,8 @@ known_third_party = [ "pytest_timeout", "requests", ] -known_first_party = "flake8_encodings" +known_first_party = [ "flake8_encodings",] + +[config] +indent = " " +line_length = 115 diff --git a/justfile b/justfile new file mode 100644 index 0000000..e8ed871 --- /dev/null +++ b/justfile @@ -0,0 +1,22 @@ +default: lint + +pdf-docs: latex-docs + make -C doc-source/build/latex/ + +latex-docs: + SPHINX_BUILDER=latex tox -e docs + +unused-imports: + tox -e lint -- --select F401 + +incomplete-defs: + tox -e lint -- --select MAN + +vdiff: + git diff $(repo-helper show version -q)..HEAD + +bare-ignore: + greppy '# type:? *ignore(?!\[|\w)' -s + +lint: unused-imports incomplete-defs bare-ignore + tox -n qa diff --git a/pyproject.toml b/pyproject.toml index 37ce7a8..4858e2d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,26 +4,28 @@ build-backend = "whey" [project] name = "flake8-encodings" -version = "0.5.0.post1" +version = "0.5.1" description = "A Flake8 plugin to identify incorrect use of encodings." readme = "README.rst" keywords = [ "encodings", "flake8", "pep597", "unicode",] dynamic = [ "requires-python", "classifiers", "dependencies",] +[project.license] +file = "LICENSE" + [[project.authors]] name = "Dominic Davis-Foster" email = "dominic@davis-foster.co.uk" - -[project.license] -file = "LICENSE" - [project.urls] Homepage = "https://github.com/python-formate/flake8-encodings" "Issue Tracker" = "https://github.com/python-formate/flake8-encodings/issues" "Source Code" = "https://github.com/python-formate/flake8-encodings" Documentation = "https://flake8-encodings.readthedocs.io/en/latest" +[project.entry-points."flake8.extension"] +ENC0 = "flake8_encodings:Plugin" + [project.optional-dependencies] classes = [ "jedi>=0.18.0",] all = [ "jedi>=0.18.0",] @@ -36,7 +38,7 @@ base-classifiers = [ "Topic :: Utilities", "Typing :: Typed", ] -python-versions = [ "3.6", "3.7", "3.8", "3.9", "3.10",] +python-versions = [ "3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13",] python-implementations = [ "CPython", "PyPy",] platforms = [ "Windows", "macOS", "Linux",] license-key = "MIT" @@ -60,26 +62,24 @@ extensions = [ "sphinx_toolbox.more_autosummary", "sphinx_toolbox.documentation_summary", "sphinx_toolbox.tweaks.param_dash", + "sphinxcontrib.toctree_plus", "sphinx_toolbox.tweaks.latex_layout", "sphinx_toolbox.tweaks.latex_toc", "sphinx.ext.intersphinx", "sphinx.ext.mathjax", "sphinxcontrib.extras_require", "sphinx.ext.todo", - "sphinxemoji.sphinxemoji", "notfound.extension", "sphinx_copybutton", "sphinxcontrib.default_values", - "sphinxcontrib.toctree_plus", "sphinx_debuginfo", "sphinx_licenseinfo", "seed_intersphinx_mapping", "html_section", "sphinx_toolbox.pre_commit", "sphinx_toolbox.flake8", - "sphinx_toolbox_experimental.needspace", + "sphinx_favicon", ] -sphinxemoji_style = "twemoji" gitstamp_fmt = "%d %b %Y" templates_path = [ "_templates",] html_static_path = [ "_static",] @@ -129,7 +129,7 @@ autodoc_exclude_members = [ ] [tool.mypy] -python_version = "3.6" +python_version = "3.9" namespace_packages = true check_untyped_defs = true warn_unused_ignores = true @@ -139,8 +139,15 @@ show_error_codes = true [tool.snippet-fmt] directives = [ "code-block",] -[project.entry-points."flake8.extension"] -ENC0 = "flake8_encodings:Plugin" +[tool.snippet-fmt.languages.python] +reformat = true + +[tool.snippet-fmt.languages.TOML] +reformat = true + +[tool.snippet-fmt.languages.ini] + +[tool.snippet-fmt.languages.json] [tool.dependency-dash."requirements.txt"] order = 10 @@ -152,13 +159,3 @@ include = false [tool.dependency-dash."doc-source/requirements.txt"] order = 30 include = false - -[tool.snippet-fmt.languages.python] -reformat = true - -[tool.snippet-fmt.languages.TOML] -reformat = true - -[tool.snippet-fmt.languages.ini] - -[tool.snippet-fmt.languages.json] diff --git a/repo_helper.yml b/repo_helper.yml index f047be7..cfba98e 100644 --- a/repo_helper.yml +++ b/repo_helper.yml @@ -4,7 +4,7 @@ modname: flake8-encodings copyright_years: "2020-2022" author: "Dominic Davis-Foster" email: "dominic@davis-foster.co.uk" -version: "0.5.0.post1" +version: "0.5.1" username: "python-formate" assignee: "domdfcoding" primary_conda_channel: "domdfcoding" @@ -13,7 +13,8 @@ short_desc: "A Flake8 plugin to identify incorrect use of encodings." min_coverage: 94 use_whey: true -python_deploy_version: 3.6 +mypy_version: 1.16 +python_deploy_version: 3.9 docs_fail_on_warning: true tox_testenv_extras: classes sphinx_html_theme: furo @@ -23,15 +24,17 @@ conda_channels: # Versions to run tests for python_versions: - - '3.6' - - '3.7' - - '3.8' - - '3.9' - - "3.10" - - 3.11-dev - - pypy36 - - pypy37 - - pypy38 + 3.7: + 3.8: + 3.9: + "3.10": + 3.11: + 3.12: + 3.13: + experimental: true + pypy37: + pypy38: + pypy39: classifiers: - 'Development Status :: 4 - Beta' @@ -42,7 +45,7 @@ classifiers: extra_sphinx_extensions: - sphinx_toolbox.pre_commit - sphinx_toolbox.flake8 - - sphinx_toolbox_experimental.needspace + - sphinx_favicon entry_points: flake8.extension: @@ -55,6 +58,8 @@ keywords: - unicode sphinx_conf_epilogue: + - needspace_amount = r"5\baselineskip" + - 'favicons = [{"rel": "icon", "href": "https://python-formate.github.io/assets/formate.ico", "sizes": "48x48", "type": "image/vnd.microsoft.icon"}]' - nitpicky = True extras_require: @@ -63,6 +68,7 @@ extras_require: tox_unmanaged: - testenv + - testenv:py313 exclude_files: - contributing diff --git a/tests/test_plugin.py b/tests/test_plugin.py index e53d12d..e940c0f 100644 --- a/tests/test_plugin.py +++ b/tests/test_plugin.py @@ -12,7 +12,7 @@ try: # 3rd party - import jedi # type: ignore + import jedi # type: ignore[import-untyped] # noqa: F401 has_jedi = True except ImportError: has_jedi = False @@ -27,7 +27,11 @@ pytest.param(False, id="no_jedi", marks=pytest.mark.skipif(has_jedi, reason=skip_reason)), ] ) -def test_plugin(tmp_pathplus: PathPlus, advanced_data_regression: AdvancedDataRegressionFixture, has_jedi): +def test_plugin( + tmp_pathplus: PathPlus, + advanced_data_regression: AdvancedDataRegressionFixture, + has_jedi: bool, + ): (tmp_pathplus / "code.py").write_text(example_source) plugin = Plugin(ast.parse(example_source), filename=str(tmp_pathplus / "code.py")) diff --git a/tests/test_visitor.py b/tests/test_visitor.py index 5bd59d5..3d21116 100644 --- a/tests/test_visitor.py +++ b/tests/test_visitor.py @@ -12,7 +12,7 @@ try: # 3rd party - import jedi # type: ignore + import jedi # type: ignore[import-untyped] # noqa: F401 has_jedi = True except ImportError: has_jedi = False diff --git a/tox.ini b/tox.ini index c90bdb3..cab0e44 100644 --- a/tox.ini +++ b/tox.ini @@ -2,9 +2,14 @@ # You may add new sections, but any changes made to the following sections will be lost: # * tox # * envlists +# * testenv:.package +# * testenv:py313-dev +# * testenv:py312-dev +# * testenv:py312 # * testenv:docs # * testenv:build # * testenv:lint +# * testenv:perflint # * testenv:mypy # * testenv:pyup # * testenv:coverage @@ -16,30 +21,45 @@ [tox] envlist = - py36 py37 py38 py39 py310 - py311-dev - pypy36 + py311 + py312 + py313 pypy37 pypy38 + pypy39 mypy build skip_missing_interpreters = True isolated_build = True requires = - pip>=21 + pip>=21,!=22.2 tox-envlist>=0.2.1 + tox~=3.0 + virtualenv!=20.16.0 [envlists] -test = py36, py37, py38, py39, py310, py311-dev, pypy36, pypy37, pypy38 +test = py37, py38, py39, py310, py311, py312, py313, pypy37, pypy38, pypy39 qa = mypy, lint -cov = py36, coverage +cov = py39, coverage + +[testenv:.package] +setenv = + PYTHONDEVMODE=1 + PIP_DISABLE_PIP_VERSION_CHECK=1 + +[testenv:py312] +download = True +setenv = + PYTHONDEVMODE=1 + PIP_DISABLE_PIP_VERSION_CHECK=1 [testenv:docs] setenv = SHOW_TODOS = 1 +passenv = SPHINX_BUILDER basepython = python3.8 changedir = {toxinidir}/doc-source extras = classes @@ -47,33 +67,39 @@ deps = -r{toxinidir}/doc-source/requirements.txt commands = sphinx-build -M {env:SPHINX_BUILDER:html} . ./build {posargs} [testenv:build] +setenv = + PYTHONDEVMODE=1 + PIP_DISABLE_PIP_VERSION_CHECK=1 + PIP_PREFER_BINARY=1 + UNSAFE_PYO3_SKIP_VERSION_CHECK=1 skip_install = True changedir = {toxinidir} deps = build[virtualenv]>=0.3.1 check-wheel-contents>=0.1.0 twine>=3.2.0 + cryptography<40; implementation_name == "pypy" and python_version <= "3.7" commands = python -m build --sdist --wheel "{toxinidir}" twine check dist/*.tar.gz dist/*.whl check-wheel-contents dist/ [testenv:lint] -basepython = python3.6 +basepython = python3.9 changedir = {toxinidir} ignore_errors = True skip_install = False deps = - flake8>=3.8.2 + flake8>=3.8.2,<5 flake8-2020>=1.6.0 flake8-builtins>=1.5.3 flake8-docstrings>=1.5.0 flake8-dunder-all>=0.1.1 flake8-encodings>=0.1.0 flake8-github-actions>=0.1.0 - flake8-noqa>=1.1.0 - flake8-pyi>=20.10.0 - flake8-pytest-style>=1.3.0 + flake8-noqa>=1.1.0,<=1.2.2 + flake8-pyi>=20.10.0,<=22.8.0 + flake8-pytest-style>=1.3.0,<2 flake8-quotes>=3.3.0 flake8-slots>=0.1.0 flake8-sphinx-links>=0.0.4 @@ -82,24 +108,33 @@ deps = git+https://github.com/domdfcoding/flake8-rst-docstrings-sphinx.git git+https://github.com/domdfcoding/flake8-rst-docstrings.git git+https://github.com/python-formate/flake8-unused-arguments.git@magic-methods - pydocstyle>=6.0.0 + git+https://github.com/python-formate/flake8-missing-annotations.git + git+https://github.com/domdfcoding/pydocstyle.git@stub-functions pygments>=2.7.1 importlib_metadata<4.5.0; python_version<'3.8' commands = python3 -m flake8_rst_docstrings_sphinx flake8_encodings tests --allow-toolbox {posargs} +[testenv:perflint] +basepython = python3.9 +changedir = {toxinidir} +ignore_errors = True +skip_install = True +deps = perflint +commands = python3 -m perflint flake8_encodings {posargs} + [testenv:mypy] -basepython = python3.6 +basepython = python3.9 ignore_errors = True changedir = {toxinidir} extras = classes deps = - mypy==0.931 + mypy==1.16 -r{toxinidir}/tests/requirements.txt -r{toxinidir}/stubs.txt commands = mypy flake8_encodings tests {posargs} [testenv:pyup] -basepython = python3.6 +basepython = python3.9 skip_install = True ignore_errors = True changedir = {toxinidir} @@ -108,7 +143,7 @@ extras = classes commands = pyup_dirs flake8_encodings tests --py36-plus --recursive [testenv:coverage] -basepython = python3.6 +basepython = python3.9 skip_install = True ignore_errors = True whitelist_externals = /bin/bash @@ -116,6 +151,7 @@ passenv = COV_PYTHON_VERSION COV_PLATFORM COV_PYTHON_IMPLEMENTATION + * changedir = {toxinidir} deps = coverage>=5 @@ -127,7 +163,7 @@ commands = [flake8] max-line-length = 120 -select = E111 E112 E113 E121 E122 E125 E127 E128 E129 E131 E133 E201 E202 E203 E211 E222 E223 E224 E225 E225 E226 E227 E228 E231 E241 E242 E251 E261 E262 E265 E271 E272 E303 E304 E306 E402 E502 E703 E711 E712 E713 E714 E721 W291 W292 W293 W391 W504 YTT101 YTT102 YTT103 YTT201 YTT202 YTT203 YTT204 YTT301 YTT302 YTT303 STRFTIME001 STRFTIME002 SXL001 PT001 PT002 PT003 PT006 PT007 PT008 PT009 PT010 PT011 PT012 PT013 PT014 PT015 PT016 PT017 PT018 PT019 PT020 PT021 RST201 RST202 RST203 RST204 RST205 RST206 RST207 RST208 RST210 RST211 RST212 RST213 RST214 RST215 RST216 RST217 RST218 RST219 RST299 RST301 RST302 RST303 RST304 RST305 RST306 RST399 RST401 RST499 RST900 RST901 RST902 RST903 Q001 Q002 Q003 A001 A002 A003 TYP001 TYP002 TYP003 TYP004 TYP005 TYP006 ENC001 ENC002 ENC003 ENC004 ENC011 ENC012 ENC021 ENC022 ENC023 ENC024 ENC025 ENC026 Y001,Y002 Y003 Y004 Y005 Y006 Y007 Y008 Y009 Y010 Y011 Y012 Y013 Y014 Y015 Y090 Y091 NQA001 NQA002 NQA003 NQA004 NQA005 NQA102 NQA103 E301 E302 E305 D100 D101 D102 D103 D104 D106 D201 D204 D207 D208 D209 D210 D211 D212 D213 D214 D215 D300 D301 D400 D402 D403 D404 D415 D417 DALL000 SLOT000 SLOT001 SLOT002 +select = E111 E112 E113 E121 E122 E125 E127 E128 E129 E131 E133 E201 E202 E203 E211 E222 E223 E224 E225 E225 E226 E227 E228 E231 E241 E242 E251 E261 E262 E265 E271 E272 E303 E304 E306 E402 E502 E703 E711 E712 E713 E714 E721 W291 W292 W293 W391 W504 YTT101 YTT102 YTT103 YTT201 YTT202 YTT203 YTT204 YTT301 YTT302 YTT303 STRFTIME001 STRFTIME002 SXL001 PT001 PT002 PT003 PT006 PT007 PT008 PT009 PT010 PT011 PT012 PT013 PT014 PT015 PT016 PT017 PT018 PT019 PT020 PT021 RST201 RST202 RST203 RST204 RST205 RST206 RST207 RST208 RST210 RST211 RST212 RST213 RST214 RST215 RST216 RST217 RST218 RST219 RST299 RST301 RST302 RST303 RST304 RST305 RST306 RST399 RST401 RST499 RST900 RST901 RST902 RST903 Q001 Q002 Q003 A001 A002 TYP001 TYP002 TYP003 TYP004 TYP005 TYP006 ENC001 ENC002 ENC003 ENC004 ENC011 ENC012 ENC021 ENC022 ENC023 ENC024 ENC025 ENC026 Y001,Y002 Y003 Y004 Y005 Y006 Y007 Y008 Y009 Y010 Y011 Y012 Y013 Y014 Y015 Y090 Y091 NQA001 NQA002 NQA003 NQA004 NQA005 NQA102 NQA103 E301 E302 E305 D100 D101 D102 D103 D104 D106 D201 D204 D207 D208 D209 D210 D211 D212 D213 D214 D215 D300 D301 D400 D402 D403 D404 D415 D417 DALL000 SLOT000 SLOT001 SLOT002 extend-exclude = doc-source,old,build,dist,__pkginfo__.py,setup.py,venv rst-directives = TODO @@ -144,7 +180,7 @@ inline-quotes = " multiline-quotes = """ docstring-quotes = """ count = True -min_python_version = 3.6.1 +min_python_version = 3.7 unused-arguments-ignore-abstract-functions = True unused-arguments-ignore-overload-functions = True unused-arguments-ignore-magic-methods = True @@ -155,13 +191,14 @@ plugins = coverage_pyver_pragma [coverage:report] fail_under = 94 +show_missing = True exclude_lines = raise AssertionError raise NotImplementedError if 0: if False: - if TYPE_CHECKING: - if typing.TYPE_CHECKING: + if TYPE_CHECKING + if typing.TYPE_CHECKING if __name__ == .__main__.: [check-wheel-contents] @@ -176,8 +213,22 @@ filterwarnings = error ignore:can't resolve package from __spec__ or __package__, falling back on __name__ and __path__:ImportWarning +[testenv:py313] +download = True +setenv = + PYTHONDEVMODE=1 + PIP_DISABLE_PIP_VERSION_CHECK=1 + UNSAFE_PYO3_SKIP_VERSION_CHECK=1 +commands = + python --version + python -m pip uninstall jedi -y + python -m pytest --cov=flake8_encodings -r aR tests/ --cov-append {posargs} + [testenv] -setenv = PYTHONDEVMODE = 1 +setenv = + PYTHONDEVMODE=1 + PIP_DISABLE_PIP_VERSION_CHECK=1 + SETUPTOOLS_USE_DISTUTILS=stdlib deps = -r{toxinidir}/tests/requirements.txt ignore_errors = True commands =