From bfe7de6b4f8e2803f911d469c8177d4ac95f49f0 Mon Sep 17 00:00:00 2001 From: Rick van Hattem Date: Mon, 6 Jul 2026 09:17:37 +0200 Subject: [PATCH 1/7] ci(tooling): gate formatting with ruff format --check, retire black - tox.ini [testenv:ruff]: add `ruff format --check` so formatting is a CI gate rather than an in-place reformat. - Delete [testenv:black]; drop black from the tox envlist and the main.yml CI matrix. ruff format is now the single formatter. - Remove [tool.black] from pyproject.toml. ruff format was already clean, so no separate reformatting commit is needed. --- .github/workflows/main.yml | 2 -- pyproject.toml | 4 ---- tox.ini | 8 +------- 3 files changed, 1 insertion(+), 13 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2ac2716..4ef9f01 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -53,8 +53,6 @@ jobs: experimental: true - python-version: '3.14' tox-env: docs - - python-version: '3.14' - tox-env: black - python-version: '3.14' tox-env: ruff diff --git a/pyproject.toml b/pyproject.toml index 230ee53..2299397 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -136,10 +136,6 @@ tests = [ [dependency-groups] dev = ['progressbar2[docs,tests]'] -[tool.black] -line-length = 79 -skip-string-normalization = true - [tool.codespell] skip = '*/htmlcov,./docs/_build,*.asc' ignore-words-list = 'datas,numbert' diff --git a/tox.ini b/tox.ini index 3f485a1..c05d603 100644 --- a/tox.ini +++ b/tox.ini @@ -7,7 +7,6 @@ envlist = py314 py315 docs - black ruff ; mypy ; codespell @@ -28,11 +27,6 @@ basepython = python3 deps = mypy commands = mypy {toxinidir}/progressbar -[testenv:black] -basepython = python3 -deps = black -commands = black --skip-string-normalization --line-length 79 {toxinidir}/progressbar - [testenv:docs] changedir = basepython = python3 @@ -54,7 +48,7 @@ commands = [testenv:ruff] commands = ruff check - ruff format + ruff format --check deps = ruff skip_install = true From 99bdc09a37784c6c46ef5077e49c4b985cfa24e5 Mon Sep 17 00:00:00 2001 From: Rick van Hattem Date: Mon, 6 Jul 2026 09:18:41 +0200 Subject: [PATCH 2/7] ci(tooling): fix codespell env, gate it in CI, drop tox3 leftovers - tox.ini [testenv:codespell]: remove the stray `command = codespell` key. toxs real setting is `commands`; the singular typo was silently ignored. The valid `commands = codespell .` block is kept. - Add codespell to the tox envlist and the main.yml CI matrix so spelling is now enforced. Local run is clean; no findings to fix. - tox.ini [testenv:docs]: drop the `whitelist_externals` block (removed in tox 4; the still-present `allowlist_externals` already lists rm/mkdir) along with its unused `cd` entry. mypy is intentionally left out of CI: PR 4 documented 11 non-gating precision errors, so it remains a local-only convenience env (no envlist entry). --- .github/workflows/main.yml | 2 ++ tox.ini | 10 +++------- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4ef9f01..40f1e31 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -55,6 +55,8 @@ jobs: tox-env: docs - python-version: '3.14' tox-env: ruff + - python-version: '3.14' + tox-env: codespell steps: - uses: actions/checkout@v6 diff --git a/tox.ini b/tox.ini index c05d603..e2d227a 100644 --- a/tox.ini +++ b/tox.ini @@ -8,8 +8,9 @@ envlist = py315 docs ruff -; mypy -; codespell + codespell +; mypy is intentionally excluded: 11 non-gating precision errors are +; documented (see PR 4); it stays a local-only convenience env. skip_missing_interpreters = True [testenv] @@ -34,10 +35,6 @@ deps = -r{toxinidir}/docs/requirements.txt allowlist_externals = rm mkdir -whitelist_externals = - rm - cd - mkdir commands = rm -f docs/modules.rst mkdir -p docs/_static @@ -57,4 +54,3 @@ changedir = {toxinidir} commands = codespell . deps = codespell skip_install = true -command = codespell From 29dbfee5ff2920da9e748ebd8c6374a8f6ffc081 Mon Sep 17 00:00:00 2001 From: Rick van Hattem Date: Mon, 6 Jul 2026 09:19:38 +0200 Subject: [PATCH 3/7] ci(hygiene): scope triggers, add concurrency and least-privilege perms - main.yml: restrict the `push` trigger to `branches: [develop]` so feature-branch pushes no longer double-run alongside their PR (the `pull_request` trigger still fires for every PR, including this one). - main.yml: add a top-level concurrency group keyed on workflow + ref with cancel-in-progress, so a superseded push or PR update cancels the stale run instead of queueing a duplicate. - main.yml: add top-level `permissions: {contents: read}`. Both jobs only check out and run tests/tox and never post PR comments, so no job needs write scopes. - stale.yml: grant the stale job `issues: write` + `pull-requests: write` (the only scopes actions/stale needs to label/close stale items); the default token is otherwise read-only under hardened defaults. --- .github/workflows/main.yml | 8 ++++++++ .github/workflows/stale.yml | 3 +++ 2 files changed, 11 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 40f1e31..3c8f387 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -2,9 +2,17 @@ name: tox on: push: + branches: [develop] pull_request: workflow_dispatch: +concurrency: + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + +permissions: + contents: read + jobs: perf-budget: name: Performance budget diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 5c47a9d..f4af50a 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -8,6 +8,9 @@ on: jobs: stale: runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write steps: - uses: actions/stale@v8 with: From 7abb1f16659d06f8632d8d138000bcafa36c9511 Mon Sep 17 00:00:00 2001 From: Rick van Hattem Date: Mon, 6 Jul 2026 09:21:57 +0200 Subject: [PATCH 4/7] ci(windows): add windows-latest py312 job, retire CircleCI + AppVeyor - main.yml: add a dedicated `windows` job (windows-latest, Python 3.12, `tox -e py312`). It passes the `--no-cov` posarg because the 100% coverage gate is unreachable on Windows: POSIX-only branches never execute there and os_specific/posix is already coverage-omitted. The Linux matrix still enforces full coverage. - Set PYTHONUTF8=1 on the job so the unicode-marker tests survive pytests fd-level capture against the legacy Windows code page. The suite is otherwise Windows-aware (tests self-clear TERM and branch on os.name), so no TERM/terminal env is required. - Delete circle.yml (dead CircleCI 1.0 config) and appveyor.yml in the same commit; the new windows job is AppVeyors replacement. --- .github/workflows/main.yml | 24 ++++++++++++++++++++++++ appveyor.yml | 26 -------------------------- circle.yml | 8 -------- 3 files changed, 24 insertions(+), 34 deletions(-) delete mode 100644 appveyor.yml delete mode 100644 circle.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 3c8f387..baa93cf 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -82,3 +82,27 @@ jobs: # showing the failing step in the logs continue-on-error: ${{ matrix.experimental || false }} run: tox -e ${{ matrix.tox-env }} + + windows: + name: tox (windows / py312) + runs-on: windows-latest + timeout-minutes: 10 + env: + # Force UTF-8 I/O so unicode-marker tests (e.g. test_unicode) don't + # hit UnicodeEncodeError against the legacy Windows code page under + # pytest's fd-level capture. + PYTHONUTF8: '1' + steps: + - uses: actions/checkout@v6 + - name: Set up Python 3.12 + uses: actions/setup-python@v6 + with: + python-version: '3.12' + - name: Install dependencies + run: | + python -m pip install --upgrade pip tox + - name: Test with tox + # The 100% coverage gate cannot be met on Windows: POSIX-only + # branches never execute there, so run without the coverage gate + # (`--no-cov` posarg). Linux jobs still enforce full coverage. + run: tox -e py312 -- --no-cov diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 91ffa33..0000000 --- a/appveyor.yml +++ /dev/null @@ -1,26 +0,0 @@ -image: Visual Studio 2022 -environment: - matrix: - - PYTHON: "C:\\Python310-x64" - TOX_ENV: "py310" - - PYTHON: "C:\\Python311-x64" - TOX_ENV: "py311" - - PYTHON: "C:\\Python312-x64" - TOX_ENV: "py312" - - PYTHON: "C:\\Python313-x64" - TOX_ENV: "py313" - - PYTHON: "C:\\Python314-x64" - TOX_ENV: "py314" - - -init: - - "%PYTHON%\\python -V" - - "%PYTHON%\\python -c \"import struct;print(8 * struct.calcsize('P'))\"" - -install: - - "%PYTHON%\\python -m pip install --upgrade pip tox" - -build: false # Not a C# project, build stuff at the test step instead. - -test_script: - - "%PYTHON%\\python -m tox -e %TOX_ENV%" diff --git a/circle.yml b/circle.yml deleted file mode 100644 index cd50d56..0000000 --- a/circle.yml +++ /dev/null @@ -1,8 +0,0 @@ -dependencies: - pre: - - pip install -r tests/requirements.txt - -test: - override: - - py.test - From 577aca172ee4c2a63d31e8116b31e8f588cff17b Mon Sep 17 00:00:00 2001 From: Rick van Hattem Date: Mon, 6 Jul 2026 09:22:27 +0200 Subject: [PATCH 5/7] ci(codeql): bump actions to v3/v6 and drop the javascript matrix - github/codeql-action/{init,autobuild,analyze}: @v2 -> @v3 (v2 is deprecated and stops receiving updates). - actions/checkout: @v3 -> @v6 to match main.yml. - Drop `javascript` from the language matrix: the repo tracks zero JS, so that leg only ever produced an empty analysis. The autobuild `if` is simplified to the sole remaining python language. --- .github/workflows/codeql.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 44ccfb2..b634a35 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -20,23 +20,23 @@ jobs: strategy: fail-fast: false matrix: - language: [ python, javascript ] + language: [ python ] steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v6 - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} queries: +security-and-quality - name: Autobuild - uses: github/codeql-action/autobuild@v2 - if: ${{ matrix.language == 'python' || matrix.language == 'javascript' }} + uses: github/codeql-action/autobuild@v3 + if: ${{ matrix.language == 'python' }} - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 with: category: "/language:${{ matrix.language }}" From 2523a93ddfa878be7a21adccd634e971bf601b32 Mon Sep 17 00:00:00 2001 From: Rick van Hattem Date: Mon, 6 Jul 2026 09:24:30 +0200 Subject: [PATCH 6/7] ci(pre-commit): modernize hooks to ruff-pre-commit + current revs - Replace the defunct GitLab flake8 mirror and the 2019-era pre-commit-hooks (v2.4.0) with: - pre-commit/pre-commit-hooks v6.0.0 (end-of-file-fixer, trailing-whitespace, check-yaml, check-added-large-files) - astral-sh/ruff-pre-commit v0.15.20 (ruff-check + ruff-format), matching the pinned ruff and the tox/CI formatter gate. - Apply the resulting auto-fixes: normalize end-of-file newlines across several tracked files and trim trailing whitespace in README.rst. `pre-commit run --all-files` is now green and idempotent. --- .github/workflows/stale.yml | 1 - .pre-commit-config.yaml | 10 ++++++---- AGENTS.md | 2 +- ISSUE_TEMPLATE | 1 - LICENSE | 1 - README.rst | 2 +- benchmarks/results.json | 2 +- docs/examples.rst | 1 - docs/index.rst | 1 - docs/usage.rst | 1 - ruff.toml | 1 - 11 files changed, 9 insertions(+), 14 deletions(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index f4af50a..eb76940 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -17,4 +17,3 @@ jobs: days-before-issue-stale: 30 exempt-issue-labels: in-progress,help-wanted,pinned,security,enhancement exempt-all-assignees: true - diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e226ea9..1d38c79 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,13 +2,15 @@ # See https://pre-commit.com/hooks.html for more hooks repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v2.4.0 + rev: v6.0.0 hooks: + - id: end-of-file-fixer - id: trailing-whitespace - id: check-yaml - id: check-added-large-files -- repo: https://gitlab.com/pycqa/flake8 - rev: 3.7.9 +- repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.15.20 hooks: - - id: flake8 + - id: ruff-check + - id: ruff-format diff --git a/AGENTS.md b/AGENTS.md index 66808cd..36b8633 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -13,4 +13,4 @@ Stats: 1 obs (414t read) | 19,980t work | 98% savings 2388 12:04a ✅ CI/tox config updated to test Python 3.10–3.15 Access 20k tokens of past work via get_observations([IDs]) or mem-search skill. - \ No newline at end of file + diff --git a/ISSUE_TEMPLATE b/ISSUE_TEMPLATE index ac4e32d..856248d 100644 --- a/ISSUE_TEMPLATE +++ b/ISSUE_TEMPLATE @@ -12,4 +12,3 @@ If applicable, code to reproduce the issue and/or the stacktrace of the issue - Python distribution/environment: CPython/Anaconda/IPython/IDLE - Operating System: Windows 10, Ubuntu Linux, etc. - Package version: `import progressbar; print(progressbar.__version__)` - diff --git a/LICENSE b/LICENSE index 38887b7..06ba389 100644 --- a/LICENSE +++ b/LICENSE @@ -25,4 +25,3 @@ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - diff --git a/README.rst b/README.rst index f0d7b1f..c42b5c1 100644 --- a/README.rst +++ b/README.rst @@ -5,7 +5,7 @@ Text progress bar library for Python. Build status: .. image:: https://github.com/WoLpH/python-progressbar/actions/workflows/main.yml/badge.svg - :alt: python-progressbar test status + :alt: python-progressbar test status :target: https://github.com/WoLpH/python-progressbar/actions Coverage: diff --git a/benchmarks/results.json b/benchmarks/results.json index 8c402aa..b8a8141 100644 --- a/benchmarks/results.json +++ b/benchmarks/results.json @@ -104,4 +104,4 @@ } } } -} \ No newline at end of file +} diff --git a/docs/examples.rst b/docs/examples.rst index 769c4d4..39b974e 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -2,4 +2,3 @@ Examples =================== .. literalinclude:: ../examples.py - diff --git a/docs/index.rst b/docs/index.rst index 58b16d5..c8ff0e9 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -25,4 +25,3 @@ Indices and tables * :ref:`genindex` * :ref:`modindex` * :ref:`search` - diff --git a/docs/usage.rst b/docs/usage.rst index 6aa0330..6bbebe2 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -67,4 +67,3 @@ Bar with custom widgets ]) for i in bar(range(20)): time.sleep(0.1) - diff --git a/ruff.toml b/ruff.toml index a105697..eb46755 100644 --- a/ruff.toml +++ b/ruff.toml @@ -113,4 +113,3 @@ max-line-length = 79 [lint.flake8-pytest-style] mark-parentheses = true - From f3e4e30702f440edb4c1050151e710b40367542c Mon Sep 17 00:00:00 2001 From: Rick van Hattem Date: Mon, 6 Jul 2026 09:36:13 +0200 Subject: [PATCH 7/7] build(packaging): tidy pytest/pyproject/MANIFEST, relocate issue template Coverage flags: - pytest.ini: move all --cov* flags out of addopts into the tox [testenv] commands so a bare `pytest -k foo` runs without coverage instrumentation. CI still enforces the 100% gate through tox (verified: the full suite reaches 100.00% and the gate fires via the explicit-cov command; no workflow consumes coverage.xml directly). python_files: - pytest.ini: restrict python_files to tests/*.py (drop progressbar/*.py). Verified --doctest-modules still collects the same 13 progressbar doctests and total collection is unchanged (586 items). - Removing progressbar modules from test-module collection also stops pytests assertion-rewrite temporaries (@py_assert1/@py_assert2) from leaking into progressbar.utils namespace, which had been captured in the API-surface snapshot. Drop those two bogus entries from tests/api_surface_snapshot.json; they were never real public API. Dependencies / build: - pyproject.toml: drop unused tests extras: flake8 (linting is ruff now), pytest-mypy (mypy is local-only), and sphinx (already provided by the docs extra; nothing under tests/ imports it). - pyproject.toml: KEEP setuptools-scm in build-system.requires. The audit flagged it as unused, but an sdist-parity check proved it provides the git file-finder that ships docs/, tests/ data, tox.ini and .github/; dropping it shrinks the sdist 152 -> 90 files and omits the test harness. Added a comment so it is not removed again. MANIFEST.in: - Drop includes for nonexistent files (AUTHORS.rst, requirements.txt, Makefile) and the malformed `recursive-exclude *.html`. The sdist file list is identical before/after this edit. Issue template: - git mv ISSUE_TEMPLATE -> .github/ISSUE_TEMPLATE.md (canonical GitHub location for the default issue template). --- ISSUE_TEMPLATE => .github/ISSUE_TEMPLATE.md | 0 MANIFEST.in | 4 ---- pyproject.toml | 9 ++++++--- pytest.ini | 11 ++++------- tests/api_surface_snapshot.json | 2 -- tox.ini | 2 +- 6 files changed, 11 insertions(+), 17 deletions(-) rename ISSUE_TEMPLATE => .github/ISSUE_TEMPLATE.md (100%) diff --git a/ISSUE_TEMPLATE b/.github/ISSUE_TEMPLATE.md similarity index 100% rename from ISSUE_TEMPLATE rename to .github/ISSUE_TEMPLATE.md diff --git a/MANIFEST.in b/MANIFEST.in index f387924..e44ef18 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,12 +1,8 @@ recursive-exclude *.pyc recursive-exclude *.pyo -recursive-exclude *.html -include AUTHORS.rst include CHANGES.rst include CONTRIBUTING.rst include LICENSE include README.rst include examples.py -include requirements.txt -include Makefile include pytest.ini diff --git a/pyproject.toml b/pyproject.toml index 2299397..54f1aaa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,11 @@ [build-system] build-backend = 'setuptools.build_meta' +# setuptools-scm is required at build time: its setuptools file-finder +# entry point is what populates the sdist with the full set of +# git-tracked files (docs/, tests/ data, tox.ini, .github/, ...). +# Dropping it silently shrinks the sdist and omits the test harness, so +# it must stay even though the version itself is static (see +# tool.setuptools.dynamic below). requires = ['setuptools', 'setuptools-scm'] [project] @@ -124,12 +130,9 @@ docs = [ ] tests = [ 'dill>=0.3.6', - 'flake8>=3.7.7', 'freezegun>=0.3.11', 'pytest-cov>=2.6.1', - 'pytest-mypy', 'pytest>=4.6.9', - 'sphinx>=1.8.5', 'pywin32; sys_platform == "win32"', ] diff --git a/pytest.ini b/pytest.ini index 1f00ecb..6cec559 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,15 +1,12 @@ [pytest] python_files = - progressbar/*.py tests/*.py +# Coverage flags intentionally live in the tox [testenv] commands, not +# here, so a bare `pytest -k foo` stays fast. CI enforces the 100% gate +# via tox. `--doctest-modules` still collects progressbar/*.py doctests +# regardless of `python_files` (which only scopes test-module collection). addopts = - --cov progressbar - --cov-report=html - --cov-report=term-missing - --cov-report=xml - --cov-config=./pyproject.toml - --no-cov-on-fail --doctest-modules norecursedirs = diff --git a/tests/api_surface_snapshot.json b/tests/api_surface_snapshot.json index e0b19d3..05405e2 100644 --- a/tests/api_surface_snapshot.json +++ b/tests/api_surface_snapshot.json @@ -456,8 +456,6 @@ "annotations": "_Feature" }, "progressbar.utils": { - "@py_assert1": "NoneType", - "@py_assert2": "NoneType", "AttributeDict": "classsignature-unavailable", "Iterable": "re-export", "Iterator": "re-export", diff --git a/tox.ini b/tox.ini index e2d227a..12c7e62 100644 --- a/tox.ini +++ b/tox.ini @@ -19,7 +19,7 @@ deps = pyright commands = pyright - py.test --basetemp="{envtmpdir}" --confcutdir=.. {posargs} + py.test --cov progressbar --cov-report=html --cov-report=term-missing --cov-report=xml --cov-config=./pyproject.toml --no-cov-on-fail --basetemp="{envtmpdir}" --confcutdir=.. {posargs} skip_install = true [testenv:mypy]