Replace assert-based genre validation with ValueError in names.py and voice.py#150
Conversation
Agent-Logs-Url: https://github.com/CyberSecDef/NovelForge/sessions/7b83084a-e47f-4808-b782-8ffa5458e3a9 Co-authored-by: CyberSecDef <17597068+CyberSecDef@users.noreply.github.com>
Agent-Logs-Url: https://github.com/CyberSecDef/NovelForge/sessions/7b83084a-e47f-4808-b782-8ffa5458e3a9 Co-authored-by: CyberSecDef <17597068+CyberSecDef@users.noreply.github.com>
There was a problem hiding this comment.
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_*_genreswithif _missing_*_genres: raise ValueError(...)innames.pyandvoice.py. - Add reload-based tests that monkeypatch
novelforge.validation.ALLOWED_GENRESto simulate missing coverage and assert aValueErroris 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.
| extended = novelforge.validation.ALLOWED_GENRES | {"FakeGenreForTest"} | ||
| monkeypatch.setattr(novelforge.validation, "ALLOWED_GENRES", extended) | ||
| with pytest.raises(ValueError, match="FakeGenreForTest"): |
There was a problem hiding this comment.
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.
| 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, | |
| ) |
| extended = novelforge.validation.ALLOWED_GENRES | {"FakeGenreForTest"} | ||
| monkeypatch.setattr(novelforge.validation, "ALLOWED_GENRES", extended) | ||
| with pytest.raises(ValueError, match="FakeGenreForTest"): |
There was a problem hiding this comment.
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).
| 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 | |
| ) |
assertstatements used for import-time genre coverage validation innames.pyandvoice.pyare silently compiled out underpython -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: Replaceassert not _missing_*_genreswith explicitifguards that raiseValueError, unconditionally enforced regardless of optimization flags:tests/test_names.py/tests/test_voice.py: AddTestNameGenreValidation/TestVoiceGenreValidationclasses that useimportlib.reload+monkeypatchto verifyValueErroris 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/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: