Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,22 @@ jobs:
test-build:
runs-on: ubuntu-latest
timeout-minutes: 10
strategy:
matrix:
python-version: ["3.8", "3.13"]
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
with:
version: "0.8.8"
python-version: "3.12"
python-version: ${{ matrix.python-version }}
enable-cache: false
- name: Run tests
run: uv run --no-project --python 3.12 --with pytest==8.3.5 pytest -q
run: uv run --no-project --python "${{ matrix.python-version }}" --with pytest==8.3.5 pytest -q
- name: Build package
run: uv build --python 3.12
run: uv build --python "${{ matrix.python-version }}"
- name: Require package artifacts
run: |
test -f dist/isbn_utils-0.1.tar.gz
Expand Down
87 changes: 87 additions & 0 deletions agent-notes/modernize/task6-isbn_utils.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Goal

Reject incorrect lengths in the existing public ISBN-10 and ISBN-13 validators.
The feature adds two length guards (four source lines), regressions in the
existing test file and the authorized pytest>=8.3.5 development dependency.
This follow-up only corrects one long-input fixture and updates this note;
no product source, API, dependency, workflow or support change.

# State

Origin `git@github.com:accessibleapps/isbn_utils.git`; open draft PR #1 is
published at 18081494e23071d5f429a1cf8f20e498f6b9cba5. Its base is landed CI
prerequisite #2 at 99ae1d0ef945fbf422d3aa0da2f2e4bc8f9c8cc2. That feature
head's hosted Python 3.8/3.13 tests and package builds passed in run
39517940869. No tracked lock exists; the pytest dev declaration is present.

This isolated follow-up branch repair/task6-isbn-utils-fixture starts from
that exact published head. Separate archive/task6-isbn-utils-fixture-local
and archive/task6-isbn-utils-fixture-published refs preserve it. Original
worktrees and the earlier note-only-ahead 47bf7690eea6fc2b05e36237e3caf2536613b440
tip/archive remain untouched, including canonical untracked uv.lock/caches.

# Decisions and why

README exposes both validators directly; existing direct validator tests reject
malformed text. isbn10_valid iterates without a length check and stops after ten
characters, accepting empty/short zero input and ignoring suffixes. isbn13_valid
indexes the last character without first establishing the required length.
Use existing exact valid README/test examples and malformed lengths; preserve
all valid inputs, normalization and checksum algorithms.
README documents uv run pytest, uv run pyright and uv run ruff check.
The hosted workflow now runs the existing pytest suite and package build on
Python 3.8 and 3.13/Linux; no tracked lock exists. Historical local checks below
were authorized before that CI prerequisite landed, not rerun for this follow-up.

Original supported-environment red proof: uv run pytest -q test_isbn_utils.py reproduced
7 failed / 5 passed before guards, using the newly declared pytest8.3.5.
After guards, full uv run pytest passes12 tests on Python3.8.20/pytest8.3.5
(0.04s) and Python3.13.15/pytest9.1.1 (0.14s). Full uv run pyright reports
0 errors/warnings; uv run ruff check passes. A prior strict-Pyright failure
on the new test parameters was fixed by annotating those two parameters.
Final dependency uses pytest>=8.3.5, with no upper/exact pin. A selective
uv lock --upgrade-package pytest on the task-generated untracked lock selected
8.3.5 for<3.9, 8.4.2 for3.9, and9.1.1 for>=3.10; other existing dev tools
resolved to pyright1.1.414 and ruff0.17.1 in that initial isolated environment.
No canonical manifest, lock or environment was synchronized.
Final manifest SHA256:961AD1580A7600FA6E8B73DA1531F5350E65F8AED3C3E1A458D75D51AF2F637A.
Generated untracked lock SHA256:20DBB24CE588A7EC52289A0F75D7068ACAF0F81142A2C8B13189D29CB5EA365B.
Whitespace check passes with per-command core.whitespace=cr-at-eol, preserving
the tracked source/test CRLF convention. No custom hook is configured.

# Surprises

Canonical venv lacks pytest; the first exact uv run pytest fell back to a
global pytest, and Pyright then failed to resolve the undeclared pytest import.
Earlier borrowed-runtime red/green runs are diagnostic only (7 failed/5 passed,
then 12 passed), not supported-command evidence. Coordinator authorized one
pytest dev declaration to make the existing README command reproducible.
Primary PyPI JSON metadata: pytest 8.3.5 requires Python >=3.8, 8.4.0 >=3.9,
9.0.1 >=3.10. Declare >=8.3.5 so uv retains older-Python compatibility while
allowing current pytest on newer interpreters. That manifest line is already
present; no tracked lock exists, so do not commit the generated local
lock or environment. Reverted only this worker's four guard lines before
reproducing red under the corrected supported test environment.
Pytest cannot update its task-generated cache due mixed sandbox/Q ownership;
test executions pass with cache-only PermissionError warnings. Do not change
permissions or security settings; retain that limitation in the private report.

# Next step

The prior 14-digit fixture 97807434885870 already returned False on the
baseline: its final 0 differs from the computed check digit 7. The corrected
97807434885877 is wrongly accepted by that baseline and rejected by the
existing exact-length guard, so it exercises the long-input regression.

On Python 3.12/pytest 8.3.5, baseline source loaded directly from 99ae1d0e
in memory returned False for the old fixture and True for the replacement.
The edited long-input test case failed against that baseline (1 failed in
0.42s), then the complete actively edited test file passed against unchanged
guarded source (12 passed in 0.05s). No full local CI or build was run.

Return this complete two-file diff/head for coordinator review before a
guarded update to the already-published PR. Fresh actual Claude review and
green hosted results must cover the final published head before merge.
No model calls, comments/descriptions, merge, full local CI or unrelated
changes are authorized here. The unchanged CI covers Linux on Python 3.8 and
3.13; other runtimes/platforms remain outside that hosted evidence.
4 changes: 4 additions & 0 deletions isbn_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@


def isbn10_valid(isbn: str) -> bool:
if len(isbn) != 10:
return False
sum = 0
for i, digit in enumerate(isbn):
if digit in ("x", "X"):
Expand All @@ -19,6 +21,8 @@ def isbn10_valid(isbn: str) -> bool:


def isbn13_valid(isbn: str) -> bool:
if len(isbn) != 13:
return False
for digit in isbn:
if digit not in string.digits:
return False
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ classifiers = [

[dependency-groups]
dev = [
"pytest>=8.3.5",
"pyright>=1.1.0",
"ruff>=0.8.0",
]
Expand Down
12 changes: 12 additions & 0 deletions test_isbn_utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import pytest

import isbn_utils


Expand All @@ -12,6 +14,16 @@ def test_isbn13_valid():
assert isbn_utils.isbn13_valid("9780743488587")


@pytest.mark.parametrize("isbn", ["", "0", "000000000", "074348858X0"])
def test_isbn10_rejects_incorrect_length(isbn: str) -> None:
assert not isbn_utils.isbn10_valid(isbn)


@pytest.mark.parametrize("isbn", ["", "0", "000000000000", "97807434885877"])
def test_isbn13_rejects_incorrect_length(isbn: str) -> None:
assert not isbn_utils.isbn13_valid(isbn)


assert not isbn_utils.isbn13_valid("test")


Expand Down
Loading