Skip to content

Replace assert-based genre validation with ValueError in names.py and voice.py#150

Merged
CyberSecDef merged 3 commits into
mainfrom
copilot/fix-assertion-genre-validation
Apr 8, 2026
Merged

Replace assert-based genre validation with ValueError in names.py and voice.py#150
CyberSecDef merged 3 commits into
mainfrom
copilot/fix-assertion-genre-validation

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 8, 2026

assert statements used for import-time genre coverage validation in names.py and voice.py are silently compiled out under python -O, allowing unmapped genres to pass through without error—causing fallback to "contemporary" name pools or unweighted voice selection.

Changes

  • novelforge/names.py / novelforge/voice.py: Replace assert not _missing_*_genres with explicit if guards that raise ValueError, unconditionally enforced regardless of optimization flags:
# Before
assert not _missing_name_genres, (
    f"Genres missing from _GENRE_GROUP in names.py: {sorted(_missing_name_genres)}. ..."
)

# After
if _missing_name_genres:
    raise ValueError(
        f"Genres missing from _GENRE_GROUP in names.py: {sorted(_missing_name_genres)}. ..."
    )
  • tests/test_names.py / tests/test_voice.py: Add TestNameGenreValidation / TestVoiceGenreValidation classes that use importlib.reload + monkeypatch to verify ValueError is raised when a genre is absent from the mapping, and that no error occurs when coverage is complete.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • api.openai.com
    • Triggering command: /usr/bin/python python -m pytest --tb=short -q --cov=. --cov-report=term-missing --cov-fail-under=85 (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI requested review from Copilot and removed request for Copilot April 8, 2026 19:51
Copilot AI linked an issue Apr 8, 2026 that may be closed by this pull request
Copilot AI requested review from Copilot and removed request for Copilot April 8, 2026 19:55
Copilot AI requested review from Copilot and removed request for Copilot April 8, 2026 19:57
Copilot AI changed the title [WIP] Fix assertion-based genre validation disabled by Python -O flag Replace assert-based genre validation with ValueError in names.py and voice.py Apr 8, 2026
Copilot AI requested a review from CyberSecDef April 8, 2026 19:58
@CyberSecDef CyberSecDef marked this pull request as ready for review April 8, 2026 20:05
Copilot AI review requested due to automatic review settings April 8, 2026 20:05
@CyberSecDef CyberSecDef merged commit 9a30ad3 into main Apr 8, 2026
10 checks passed
@CyberSecDef CyberSecDef deleted the copilot/fix-assertion-genre-validation branch April 8, 2026 20:06
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR makes genre→mapping coverage checks in novelforge/names.py and novelforge/voice.py robust under python -O by replacing assert-based import-time validation with unconditional ValueError guards, and adds tests to confirm the behavior via importlib.reload().

Changes:

  • Replace assert not _missing_*_genres with if _missing_*_genres: raise ValueError(...) in names.py and voice.py.
  • Add reload-based tests that monkeypatch novelforge.validation.ALLOWED_GENRES to simulate missing coverage and assert a ValueError is raised.
  • Add “no error when coverage is complete” reload tests for both modules.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
novelforge/names.py Switch import-time genre coverage validation from assert to ValueError to avoid -O silencing.
novelforge/voice.py Same as above for voice-weight genre coverage.
tests/test_names.py Add reload-based tests to ensure missing genre coverage raises ValueError.
tests/test_voice.py Add reload-based tests to ensure missing genre coverage raises ValueError.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/test_names.py
Comment on lines +185 to +187
extended = novelforge.validation.ALLOWED_GENRES | {"FakeGenreForTest"}
monkeypatch.setattr(novelforge.validation, "ALLOWED_GENRES", extended)
with pytest.raises(ValueError, match="FakeGenreForTest"):
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The failing importlib.reload(novelforge.names) leaves novelforge.names in a partially re-executed state for the remainder of the test session (reload reuses the existing module dict and does not roll back on exceptions). That can create order-dependent behavior if any later test imports/uses novelforge.names expecting a clean module state. Consider reloading the module back to a known-good state in a finally block (after restoring ALLOWED_GENRES) or using a fixture that always reloads novelforge.names with the standard ALLOWED_GENRES after this test.

Suggested change
extended = novelforge.validation.ALLOWED_GENRES | {"FakeGenreForTest"}
monkeypatch.setattr(novelforge.validation, "ALLOWED_GENRES", extended)
with pytest.raises(ValueError, match="FakeGenreForTest"):
original_allowed_genres = novelforge.validation.ALLOWED_GENRES
extended = original_allowed_genres | {"FakeGenreForTest"}
monkeypatch.setattr(novelforge.validation, "ALLOWED_GENRES", extended)
try:
with pytest.raises(ValueError, match="FakeGenreForTest"):
importlib.reload(novelforge.names)
finally:
monkeypatch.setattr(
novelforge.validation,
"ALLOWED_GENRES",
original_allowed_genres,
)

Copilot uses AI. Check for mistakes.
Comment thread tests/test_voice.py
Comment on lines +230 to +232
extended = novelforge.validation.ALLOWED_GENRES | {"FakeGenreForTest"}
monkeypatch.setattr(novelforge.validation, "ALLOWED_GENRES", extended)
with pytest.raises(ValueError, match="FakeGenreForTest"):
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to names.py: when importlib.reload(novelforge.voice) raises, the module is left partially re-executed (no rollback), which can leak state into later tests and make outcomes order-dependent. It’s safer to restore a clean module state after the assertion (e.g., reload again after monkeypatch is undone, or wrap the reload in try/except + finally that reloads with the original ALLOWED_GENRES).

Suggested change
extended = novelforge.validation.ALLOWED_GENRES | {"FakeGenreForTest"}
monkeypatch.setattr(novelforge.validation, "ALLOWED_GENRES", extended)
with pytest.raises(ValueError, match="FakeGenreForTest"):
original_allowed_genres = novelforge.validation.ALLOWED_GENRES
extended = original_allowed_genres | {"FakeGenreForTest"}
monkeypatch.setattr(novelforge.validation, "ALLOWED_GENRES", extended)
try:
with pytest.raises(ValueError, match="FakeGenreForTest"):
importlib.reload(novelforge.voice)
finally:
monkeypatch.setattr(
novelforge.validation, "ALLOWED_GENRES", original_allowed_genres
)

Copilot uses AI. Check for mistakes.
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.

Assertion-Based Genre Validation Disabled by Python -O Flag

3 participants