Skip to content

Refuse an odd keyword count in createPairs - #22

Merged
dmccoystephenson merged 1 commit into
mainfrom
feature/odd-pairs-and-debugpy
Sep 25, 2026
Merged

dmccoystephenson merged 1 commit into
mainfrom
feature/odd-pairs-and-debugpy

Conversation

@dmccoystephenson

Copy link
Copy Markdown
Member

Summary

  • createPairs() now raises ValueError ("keywords must have an even count to be paired, got N") when self.keywords has an odd length, instead of reading past the end of the list with an unguarded keywords[i+1] and raising IndexError.
  • The count is checked before any pair is built, so a refused call leaves self.pairs empty rather than half-filled.
  • This matches the decision already made in Replace the ordinal ladder and make the keyword count a parameter #20, where the constructor refuses an odd numKeywords with a ValueError: an unpartnered keyword is treated as an error in both places, rather than being silently dropped or turned into a one-element pair.
  • The existing characterization test testOddKeywordCountRaisesIndexError is replaced by testOddKeywordCountRaisesValueError, and testOddKeywordCountCreatesNoPairs is added.

The CLI path is unaffected: getKeywords() always collects an even numKeywords, so an odd list only reaches createPairs() when it is called directly.

Closes #9

Test plan

  • python3 -m py_compile src/collide.py src/ideaCollisionGenerator.py src/usage_reporting.py src/trace_client.py — clean
  • python3 -m unittest discover -s tests (Python 3.8.10) — Ran 61 tests ... OK
  • Regression evidence, via git stash push -- src/ideaCollisionGenerator.py then python3 -m unittest tests.test_ideaCollisionGenerator.TestCreatePairs:
    • fix stashed: Ran 5 tests ... FAILED (errors=2), both new tests erroring with IndexError: list index out of range at pair.append(self.keywords[i+1])
    • fix restored: Ran 5 tests ... OK
  • End-to-end redirected-stdin run: running src/collide.py locally was denied by the session's command classifier, so this step is covered only by the CI workflow's "Run the program end to end" step (15-line fixture on stdin, 5 written lines asserted).

Deferred

This PR description was drafted during a Gardener session (https://github.com/Stephenson-Software/gardener).

🤖 Generated with Claude Code


drafted by Claude on behalf of Daniel Stephenson

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dmccoystephenson

Copy link
Copy Markdown
Member Author

Self-review rubric (scored against the diff, the local test runs, and CI run 36119039250):

  • Scope: PASS — two files changed, both needed for createPairs() raises IndexError when the keyword count is odd #9: the guard in createPairs() and its tests. No renames, reformatting, or comment churn elsewhere.
  • Tests-new: PASS — no new public method was added. The new behavior is covered by testOddKeywordCountRaisesValueError and testOddKeywordCountCreatesNoPairs.
  • Tests-fix: PASS — the stash-and-run was done. With src/ideaCollisionGenerator.py stashed, TestCreatePairs gave Ran 5 tests ... FAILED (errors=2) with IndexError: list index out of range at pair.append(self.keywords[i+1]). With the fix restored it gave Ran 5 tests ... OK. The replaced assertion (IndexError → ValueError) also records the change on its own.
  • Sibling structure / renames: PASS — the new tests follow the testCamelCase naming and the comment style of the other TestCreatePairs cases. Nothing was renamed.
  • Docs: PASS — README.md does not describe how createPairs() handles an odd count, and the CLI path it documents is unchanged. No other source of truth mentions this behavior.
  • Issue resolution: PASS — createPairs() raises IndexError when the keyword count is odd #9 asked for an explicit decision plus a direct-call test. The decision is to refuse the odd count, matching the constructor's ValueError from Replace the ordinal ladder and make the keyword count a parameter #20.
  • Manual validation: PASS, with one gap. Locally, py_compile ran clean over all four modules and unittest discover gave Ran 61 tests ... OK on Python 3.8.10. Running src/collide.py directly with redirected stdin was denied by the session's command classifier, so the end-to-end check comes only from CI's "Run the program end to end" step (15-line fixture, 5 written lines asserted). That step passed on 3.8 and 3.13, and CI also reported Ran 61 tests.
  • Ran, not read: PASS — every output quoted in the PR body comes from a run in this session or from the CI log.
  • Stdin always redirected: PASS — no new invocation of the entry point was added.
  • camelCase preserved / Stdlib only / Python 3.8-safe: PASS — there are no new imports. The only new code is string concatenation with + and a modulo check, and CI passed on 3.8.
  • Output contract / prompt strings: PASS — neither was changed.
  • License claims / artifacts / inflation: PASS — no license file, generated file, or new directory is in the diff.

Judgment call noted for the owner: tests/test_ideaCollisionGenerator.py:130 — testOddKeywordCountCreatesNoPairs also checks the ValueError, which overlaps with the previous test. It is kept because its real claim, that pairs stays empty, depends on the check running before the loop. Without the fix, the old code appended ['a', 'b'] before raising.

Summary: no do-not-auto-merge path is touched, and the regression evidence was confirmed by actually running the tests with the fix removed and then restored.

This review comment was drafted during a Gardener session (https://github.com/Stephenson-Software/gardener).


drafted by Claude on behalf of Daniel Stephenson

@dmccoystephenson
dmccoystephenson merged commit 275c6e9 into main Sep 25, 2026
2 checks passed
@dmccoystephenson
dmccoystephenson deleted the feature/odd-pairs-and-debugpy branch September 25, 2026 09:33
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.

createPairs() raises IndexError when the keyword count is odd

1 participant