Skip to content

Rhyme module, packaging modernisation, and CI - #6

Merged
neburnodrog merged 6 commits into
mainfrom
refactor/rhyme-module
Sep 22, 2026
Merged

neburnodrog merged 6 commits into
mainfrom
refactor/rhyme-module

Conversation

@neburnodrog

@neburnodrog neburnodrog commented Sep 22, 2026 •

Copy link
Copy Markdown
Owner

Two pieces of work: an architectural refactor with a defect fix, then general project maintenance.

1. The rhyme module

Rhyme derivation lived in six methods on Word and two on Pyverse, all trading hyphenated strings. It is now pyverse/rhyme.py:

@dataclass(frozen=True)
class Rhyme:
    consonant: str
    assonant: str

def rhyme(syllabified: str, accentuation: int) -> Rhyme: ...

One function, one two-field value, importing nothing from word.py, so it is exercised from two literals rather than a constructed Word.

The defect it was hiding. Pyverse.verse_assonant_rhyme_finder reimplemented the vowel filter that Word.assonant_rhyme_finder already applied, and left out the rule that the u in que/qui/gue/gui is silent:

verse ends in before after
porque oue oe
sigue iue ie
averigüe iüe iüe (unchanged, ü is pronounced)

No assonant rhyme was asserted anywhere in the suite, which is why it survived.

  • Word loses six methods and two __init__ attributes, gains one lazy .rhyme. 314 lines to 222.
  • Pyverse loses both finder methods and reads the value off the last word.
  • Drops the docstring claim that atonic words rhyme to None. The code never did, and implementing it would fail the existing assertion that "Estamos en el mundo y" rhymes in i, since y is an atonic monosyllable.
  • Adds CONTEXT.md, since this names a module after a domain concept and the repo had no glossary.

2. Packaging, Python floor, CI

setup.py and Pipfile disagreed: one pinned Click==7.1.2, the other asked for "*". Both are replaced by one PEP 621 pyproject.toml.

  • requires-python >=3.8 becomes >=3.12. The old range spanned two end-of-life versions (3.8 in Oct 2024, 3.9 in Oct 2025). Verified on 3.12, 3.13 and 3.14.
  • Click relaxes from ==7.1.2 to >=8.1. An exact pin in a library makes pyverse uninstallable next to anything using Click 8.
  • numlet gains a >=2.0 floor, the version the suite is verified against.
  • Version 2.0.0: public members were removed, the assonant output changed, and the supported Python range narrows.

CI runs flake8 and pytest on 3.12/3.13/3.14 and uploads coverage. Making lint pass meant replacing silabeador.py's star import of vars with explicit imports, which in turn removed the need for ignore = F405 in .flake8.

__main__.py had no coverage at all. tests/test_cli.py now covers the report format, digit expansion, the argument error, and the silent-u rule reaching the output. It also gains an entry point guard, so python -m pyverse works instead of silently doing nothing.

3. Documentation and metadata

Every README example was wrong, in both language sections: verse.get_syllables() does not exist (it is verse.syllables), the sample output dropped an n from -ber-gan-tín, and it claimed bergantín rhymes in atin/ai rather than in/i. All six examples now execute correctly against the package.

Also corrected: the repository URL said Pyverso, the __main__ docstring claimed v1.0.0 and linked to the old silabizador project, and the codecov badge pointed at the old repository name.

Verification

before after
tests 91 114
flake8 findings 11 0
coverage not measured 99%

Tests and lint green on Python 3.12, 3.13 and 3.14. python -m build and twine check both pass; the wheel installs clean and both pyverse and python -m pyverse produce correct output.

Known, deliberately not fixed

print(vowel_group) at word.py:174 still leaks to stdout for triphthong input, so pyverse "Los leiais" prints i-ai above its report. Left alone by request.

Also untouched, from the same architecture review: the hyphen-encoded syllabification shared across three modules, the synalepha rule split four ways, and the nlt import that makes the package unimportable without it.

🤖 Generated with Claude Code

neburnodrog and others added 5 commits September 22, 2026 13:12
Pyverse.verse_assonant_rhyme_finder reimplemented the vowel filter that
Word.assonant_rhyme_finder already applies, and left out the rule that
the u in que/qui/gue/gui is silent. Any verse ending in one of those
syllables reported a wrong assonant rhyme from the package interface and
from the CLI: "porque" gave "oue" instead of "oe".

Delegate to the last word instead. No assonant rhyme was asserted
anywhere in the suite, which is why the divergence survived; the new
tests pin both the rule and the agreement between verse and last word.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Rhyme derivation was six methods on Word plus two on Pyverse, all
trading hyphenated strings between them. The interface was as wide as
the implementation, and three of the six helpers had no test at all.

pyverse/rhyme.py now holds it: one function taking a syllabified word
and its accentuation, returning a Rhyme with the consonant and assonant
forms. It imports nothing from word.py, so it is exercised from two
literals rather than a constructed Word.

Word drops six methods and two __init__ attributes for a single lazy
.rhyme; Pyverse drops verse_consonant_rhyme_finder and
verse_assonant_rhyme_finder and reads the value off the last word. The
seven tests on the deleted Pyverse method now assert the published
attribute instead.

Also drops the docstring claim that atonic words rhyme to None. The
code never did that, and implementing it would fail the existing
assertion that "Estamos en el mundo y" rhymes in "i", since "y" is an
atonic monosyllable.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Names the domain terms the README already uses, plus Rhyme, which the
previous commit introduced as a module.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Packaging moves from setup.py plus Pipfile to a single PEP 621
pyproject.toml. The two files declared dependencies differently: setup.py
pinned Click==7.1.2 while the Pipfile asked for "*".

- requires-python >=3.12. The old >=3.8 spanned two versions that reached
  end of life (3.8 in Oct 2024, 3.9 in Oct 2025). Verified on 3.12, 3.13
  and 3.14.
- Click relaxes from ==7.1.2 to >=8.1. An exact pin in a library makes
  pyverse uninstallable next to anything using Click 8.
- numlet gains a >=2.0 floor, the version the suite is verified against.
- Version 2.0.0: the rhyme refactor removed public members and changed
  the assonant rhyme output, and the supported Python range narrows.

CI runs flake8 and pytest on 3.12, 3.13 and 3.14 and uploads coverage.
That meant making flake8 pass, which it did not: silabeador.py imported
vars with a star and .flake8 carried ignore = F405 to silence the
fallout. The imports are now explicit, so neither the star nor the
suppression is needed, and dropping the ignore line restores flake8's own
defaults for W503.

__main__.py had no coverage at all. tests/test_cli.py now covers the
report format, digit expansion, the argument error and the silent-u rule
reaching the output. It also gains an entry point guard, so python -m
pyverse works rather than silently doing nothing.

Stale metadata corrected: the repository URL said "Pyverso", the
__main__ docstring claimed v1.0.0 and linked to the old silabizador
project, and the README's codecov badge pointed at the old repository
name. The docstring's version line is removed rather than corrected,
since a hardcoded version there drifts on every release.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Every example in the README was wrong, in both language sections:

- verse.get_syllables() does not exist and never did. The attribute is
  verse.syllables.
- The CLI sample output dropped an 'n': "-ber-ga-tín" should be
  "-ber-gan-tín".
- It claimed "bergantín" rhymes in "atin" / "ai". It rhymes in "in" / "i",
  because the rhyme starts at the last stressed vowel.

The examples now match what the package prints, and state the Python
requirement.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@neburnodrog neburnodrog changed the title Extract rhyme derivation into one module Rhyme module, packaging modernisation, and CI Sep 22, 2026
actions/checkout@v4 and actions/setup-python@v5 target Node 20, which
GitHub deprecated; runners were already forcing them onto Node 24.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@neburnodrog
neburnodrog merged commit 248df72 into main Sep 22, 2026
3 checks passed
@neburnodrog
neburnodrog deleted the refactor/rhyme-module branch September 22, 2026 13:23
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