Skip to content

Release 0.2.1: reject booleans, and stop overstating the retries - #5

Merged
neosergio merged 1 commit into
mainfrom
fix/v0.2.1
Jul 13, 2026
Merged

Release 0.2.1: reject booleans, and stop overstating the retries#5
neosergio merged 1 commit into
mainfrom
fix/v0.2.1

Conversation

@neosergio

@neosergio neosergio commented Jul 13, 2026

Copy link
Copy Markdown
Owner

bool subclasses int, so True reached the integer branch of _normalize_source and returned the reference belonging to 1, and False the one belonging to 0. A caller who passed a flag where an identifier was meant got a real, valid-looking reference that belonged to a different record. Both raise TypeError now.

A type checker will not catch that call, and cannot: bool subclasses int in the type system exactly as it does at runtime, so SourceIdentifier admits True and mypy is content. Python has no way to spell "int but not bool". The guard is therefore a runtime one, the docstring says so, and the tests carry no suppression on those calls because none is possible.

expected_collisions() documented itself as an error rate -- "the number of writes per bucket a caller should expect to retry". It is not, and the gap is not academic. It returns expected colliding pairs, and a suffix drawn k times is k * (k - 1) / 2 pairs but only k - 1 rejected inserts, so the two agree while a bucket is sparse and part company once it fills. Simulated: two thousand references over three digits is 1999 pairs and about 1135 rejected inserts, so the old wording overstated the retries by more than half, exactly where a crowded caller would be reading it.

The behaviour was always right; only the claim about it was wrong. The docstring and README now say it counts pairs, warn against sizing a retry budget with it, and a test pins the divergence so the claim cannot quietly return. The function people actually want -- the expected number of rejected inserts, n - space * (1 - (1 - 1/space)**n), which tracks the simulation exactly -- is additive, and belongs in 0.3.0 rather than a patch.

References produced by 0.2.0 are unchanged.

Summary by CodeRabbit

  • Bug Fixes

    • Boolean inputs are now rejected instead of being interpreted as integers.
    • Error handling now consistently distinguishes invalid types from invalid values.
  • Documentation

    • Clarified that collision estimates represent expected colliding pairs, not rejected inserts or retry counts.
    • Added guidance for comparing suffix formats and avoiding incorrectly sized retry budgets.
  • Release

    • Updated the package to version 0.2.1.

bool subclasses int, so True reached the integer branch of
_normalize_source and returned the reference belonging to 1, and False the
one belonging to 0. A caller who passed a flag where an identifier was
meant got a real, valid-looking reference that belonged to a different
record. Both raise TypeError now.

A type checker will not catch that call, and cannot: bool subclasses int
in the type system exactly as it does at runtime, so SourceIdentifier
admits True and mypy is content. Python has no way to spell "int but not
bool". The guard is therefore a runtime one, the docstring says so, and
the tests carry no suppression on those calls because none is possible.

expected_collisions() documented itself as an error rate -- "the number of
writes per bucket a caller should expect to retry". It is not, and the
gap is not academic. It returns expected colliding *pairs*, and a suffix
drawn k times is k * (k - 1) / 2 pairs but only k - 1 rejected inserts, so
the two agree while a bucket is sparse and part company once it fills.
Simulated: two thousand references over three digits is 1999 pairs and
about 1135 rejected inserts, so the old wording overstated the retries by
more than half, exactly where a crowded caller would be reading it.

The behaviour was always right; only the claim about it was wrong. The
docstring and README now say it counts pairs, warn against sizing a retry
budget with it, and a test pins the divergence so the claim cannot quietly
return. The function people actually want -- the expected number of
rejected inserts, n - space * (1 - (1 - 1/space)**n), which tracks the
simulation exactly -- is additive, and belongs in 0.3.0 rather than a
patch.

References produced by 0.2.0 are unchanged.
@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a153044b-f674-40d4-8027-c1ab5e9d652d

📥 Commits

Reviewing files that changed from the base of the PR and between 8992ac9 and 622e0ec.

📒 Files selected for processing (6)
  • CHANGELOG.md
  • README.md
  • pyproject.toml
  • src/compactref/__init__.py
  • src/compactref/core.py
  • tests/test_core.py

📝 Walkthrough

Walkthrough

The change rejects boolean reference sources, clarifies expected_collisions() as a colliding-pair metric, adds validation and regression tests, and bumps package metadata to version 0.2.1.

Changes

Input validation and collision semantics

Layer / File(s) Summary
Boolean source validation
src/compactref/core.py, tests/test_core.py
Boolean inputs now raise TypeError, with tests covering boolean handling and the TypeError/ValueError contract.
Expected collision pair semantics
src/compactref/core.py, tests/test_core.py, README.md
Documentation and tests define expected colliding pairs separately from rejected inserts and retry attempts.
Version and release notes
pyproject.toml, src/compactref/__init__.py, CHANGELOG.md
Package version metadata and the 0.2.1 release notes are updated.

Estimated code review effort: 2 (Simple) | ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main changes: boolean rejection and correcting the retries/collision semantics in the 0.2.1 release.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/v0.2.1

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@neosergio
neosergio merged commit 523241b into main Jul 13, 2026
8 checks passed
@neosergio
neosergio deleted the fix/v0.2.1 branch July 13, 2026 17:23
@coderabbitai coderabbitai Bot mentioned this pull request Jul 14, 2026
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.

1 participant