Skip to content

v3.1.0: agent-friendly API, test coverage, and tooling refresh#8

Merged
jlevy merged 3 commits into
masterfrom
claude/strif-v3.1.0
May 23, 2026
Merged

v3.1.0: agent-friendly API, test coverage, and tooling refresh#8
jlevy merged 3 commits into
masterfrom
claude/strif-v3.1.0

Conversation

@jlevy

@jlevy jlevy commented May 23, 2026

Copy link
Copy Markdown
Owner

Summary

Implements the v3.1.0 epic (tbd strif-9nyk). All planned beads except the Windows/macOS CI matrix (strif-dzxb, intentionally deferred to a separate effort per request). Tests: 43 total (up from 26), all green; lint clean. Zero runtime dependencies preserved.

API additions (agent / IDE ergonomics)

  • atomic_write_text() / atomic_write_bytes() — one-call wrappers around atomic_output_file() for the common "write a whole string/bytes atomically" case (replaces the nested-with boilerplate that's awkward for agents).
  • __version__ exposed on the package via importlib.metadata (graceful fallback when run from an uninstalled source tree).
  • Insertion / ReplacementNamedTuple with named fields (offset/text, start/end/text).
  • HashAlgorithm Literal type on hash_string() / hash_file() for autocomplete. Default stays "sha1" (no behavior change; changing the default is deferred to a future major).
  • Removed the unreachable abbreviate_str / abbreviate_list aliases (never exported from the public package).

Tests

  • New tests/test_atomic_var.pyAtomicVar had zero coverage. Covers set/swap/update (returning + in-place), copy vs deepcopy independence, updates() context manager + immutable guard, truthiness, value_is_immutable, and a real concurrency test (10 threads × 1000 increments) that fails without the lock.
  • hash_file — binary content + a >8KB payload to exercise the chunked-read loop (vs hashlib); unsupported-algorithm error.
  • New tests/test_ids.pynew_uid charset + length/bits math; new_timestamped_uid sorts by creation time.
  • atomic_output_file{timestamp} backups don't clobber each other.
  • atomic_write_text/bytes — round-trip, make_parents, backup.
  • Tightened test_string_replace.py to use named constructors and dropped redundant assert messages (per the tbd Python testing guidelines).

Tooling

  • softprops/action-gh-release v2.6.2 → v3.0.0 (Node 24 runtime — clears the Node 20 deprecation warning seen on the v3.0.2 release; deadline was June 2 2026). SHA-pinned.
  • astral-sh/setup-uv v7.6.0 → v8.1.0 in both CI and publish workflows. SHA-pinned.

README

  • Documents atomic_write_text/bytes; adds a "Using strif with LLM Agents" subsection; notes the Insertion/Replacement named fields; updates the version banner (now Python 3.10–3.14).

⚠️ Backward compatibility

  • NamedTuple change is runtime-compatible — positional construction, unpacking, and indexing all still work (NamedTuple subclasses tuple). Static-typing caveat: callers who annotate a value as list[Insertion]/list[Replacement] and assign bare tuple literals will now get a type-checker error and should switch to the named constructors. (This surfaced in our own tests, which I updated.)
  • Removing abbreviate_* breaks only code importing them from the private strif.strif submodule (they were never in the public strif API).

Deferred

  • strif-dzxb: add Windows + macOS to the CI matrix — kept as a separate follow-up since cross-OS os.replace semantics may surface real (fixable) bugs that shouldn't block this release.

Test plan

  • uv run pytest — 43/43 pass
  • uv run python devtools/lint.py — codespell + ruff + basedpyright clean
  • Smoke-tested new API (__version__, atomic_write_*, named tuples, HashAlgorithm)
  • CI green on 3.10–3.14
  • After merge: tag v3.1.0 to trigger the (now Node 24) publish workflow

https://claude.ai/code/session_01Td1N9waEtmcArZh5jNBdLH


Generated by Claude Code

claude added 2 commits May 23, 2026 06:30
Implements the v3.1.0 epic (tbd strif-9nyk). The Windows/macOS CI matrix
bead (strif-dzxb) is intentionally deferred to a separate effort.

API additions (agent/IDE ergonomics):
- atomic_write_text() / atomic_write_bytes(): one-call wrappers around
  atomic_output_file() for the common whole-value write case.
- __version__ exposed on the package via importlib.metadata.
- Insertion / Replacement are now NamedTuples with named fields
  (offset/text and start/end/text). Runtime-compatible with positional
  tuples; see note below on static typing.
- HashAlgorithm Literal type on hash_string()/hash_file() params for
  autocomplete; default stays "sha1" (no behavior change).
- Removed the unreachable abbreviate_str/abbreviate_list aliases (they
  were never exported from the public package).

Tests (43 total, up from 26):
- New tests/test_atomic_var.py: AtomicVar set/swap/update, copy vs
  deepcopy independence, updates() context manager + immutable guard,
  truthiness, value_is_immutable, and a real concurrency test (10
  threads x 1000 increments) that would fail without the lock.
- hash_file: binary content + >8KB chunked-read path vs hashlib;
  unsupported-algorithm error.
- New tests/test_ids.py: new_uid charset/length-bits math; timestamped
  uid sorts by creation time.
- atomic_output_file {timestamp} backups don't clobber each other.
- atomic_write_text/bytes round-trip, make_parents, backup.
- Tightened test_string_replace.py: named-field construction, dropped
  redundant assert messages (per testing guidelines).

Tooling:
- Bump softprops/action-gh-release v2.6.2 -> v3.0.0 (Node 24 runtime;
  clears the Node 20 deprecation warning). SHA-pinned.
- Bump astral-sh/setup-uv v7.6.0 -> v8.1.0 in CI and publish. SHA-pinned.

README:
- Document atomic_write_text/bytes; add "Using strif with LLM Agents"
  subsection; note Insertion/Replacement named fields; version banner.

BACKWARD COMPATIBILITY NOTE: The NamedTuple change is fully
runtime-compatible (NamedTuple subclasses tuple, so positional
construction, unpacking, and indexing all still work). However, callers
who statically type a value as list[Insertion]/list[Replacement] and
assign bare tuple literals will now see a type error and should switch
to the named constructors. Removing the abbreviate_* aliases is a
breaking change only for code importing them from the private
strif.strif submodule.
Was writing to a relative tmp/ dir (gitignored, but pollutes cwd and is
inconsistent with the other tmp_path-based tests in the same file).
Same assertions, cleaner isolation.
@jlevy jlevy marked this pull request as ready for review May 23, 2026 19:31
From external review of PR #8:

- hash_file(): remove the `algorithm not in hashlib.algorithms_available`
  precheck. It rejected valid hashlib spellings like "SHA1" and "sha-1"
  (which are NOT in algorithms_available but DO work via hashlib.new),
  and was inconsistent with hash_string(). hashlib.new() still raises
  ValueError for genuinely unknown algorithms, so the contract is
  unchanged for callers.
- pyproject.toml: add [tool.hatch.build.targets.sdist] exclude so the
  published source distribution no longer ships .claude/.tbd/.github/
  .copier-answers.yml agent+tooling state.
- tests/test_ids.py: make the timestamped-uid test deterministic. Assert
  the sortable timestamp-prefix format and base36 suffix plus uniqueness,
  instead of comparing two rapidly-created ids (which could tie on
  timestamp precision and fall through to the random suffix).
- README.md: fix sf.write -> f.write typo in the backup_suffix example.

Not changed: kept the abbreviate_str/abbreviate_list removal (maintainer
confirmed); will be noted in the v3.1.0 release notes.
@jlevy jlevy merged commit b6858c4 into master May 23, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants