Skip to content

Validate loaded save data against schemas; wire Config into Player/SaveFileManager#115

Merged
dmccoystephenson merged 1 commit into
mainfrom
feature/wire-config-and-validate-save-schemas
Jul 19, 2026
Merged

Validate loaded save data against schemas; wire Config into Player/SaveFileManager#115
dmccoystephenson merged 1 commit into
mainfrom
feature/wire-config-and-validate-save-schemas

Conversation

@dmccoystephenson

Copy link
Copy Markdown
Member

Summary

  • Add a validate_against_schema() helper (src/validation/schemaValidator.py) and call it from each *JsonReaderWriter's create*FromJson, after the existing .get()-with-defaults fallback runs — so a save missing keys still loads fine (backwards compatibility is untouched), but an out-of-range or wrong-type value that was present (e.g. energy: -500, homeTier: 99, a stringified stat) is now rejected with a jsonschema.exceptions.ValidationError instead of silently loading and surfacing later as an uncaught ValueError deep in housing.py/business.py.
  • Catch that ValidationError in FishE.loadPlayer/loadStats/loadTimeService the same way IOError/JSONDecodeError are already caught — falls back to a fresh default object plus the existing warning print, no new failure mode.
  • Construct a Config() in FishE.__init__ and thread it through: SaveFileManager(data_directory=config.dataDirectory), and an optional Player(config=None) parameter that seeds money/fishCount/moneyInBank/fishMultiplier/priceForBait from it (defaulting to today's literals when omitted, so every existing caller/test is unaffected). This turns Config from dead code into an actual session-level override, matching the pattern Player.operatorMode already uses for FISHE_OPERATOR_MODE.
    • energy is deliberately not sourced from Config.initialEnergy — the housing ladder (housing.HOUSING_TIERS[0]["maxEnergy"], currently 60) is the real source of truth for starting energy, and Config.initialEnergy (100) predates/ignores that and would let a configured player start above the Homeless cap. See the comment in Player.__init__.

Closes #111
Closes #109

Test plan

  • python3 -m compileall -q src tests
  • Full suite green: pytest --verbose -vv --cov=src --cov-report=term-missing --cov-report=xml:cov.xml → 345 passed, 100% coverage on all newly-touched modules (schemaValidator.py, the three *JsonReaderWriters)
  • Backend-only change — no front-end-visible menu/dialogue, so no console/pygame/web parity work needed
  • New tests: out-of-range/wrong-type values raise ValidationError in each reader/writer; FishE.loadPlayer recovers gracefully from an out-of-range save; Player(config) seeds from a custom Config while Player() is unaffected; FishE.__init__ wires self.config into SaveFileManager and Player
  • Self-review performed per project convention (no configured reviewer)

…/SaveFileManager

Closes #111
Closes #109

- Add a validate_against_schema() helper and call it from each
  *JsonReaderWriter's create*FromJson after applying the existing
  .get()-with-defaults fallback, so a save missing keys still loads
  (backwards compatibility), while out-of-range/wrong-type values that
  were present are rejected with a jsonschema ValidationError instead of
  surfacing later as e.g. a ValueError deep in housing.py.
- Catch that ValidationError in FishE.loadPlayer/loadStats/loadTimeService
  the same way IOError/JSONDecodeError are already caught, falling back to
  a fresh default object.
- Construct a Config in FishE.__init__ and thread it into SaveFileManager's
  data_directory and Player's starting money/fishCount/moneyInBank/
  fishMultiplier/priceForBait, turning Config from dead code into an
  actual session-level override (energy deliberately stays governed by
  the housing ladder, not Config.initialEnergy - see the comment in
  Player.__init__).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@dmccoystephenson

Copy link
Copy Markdown
Member Author

{
"body": "Self-review: no issues found. Verified backwards compatibility (missing-key saves still load via the existing .get()-with-defaults fallback; validation only runs against the reconstructed object, not the raw input, so it cannot reject a save merely for omitting optional keys). Verified Config.initialEnergy (100) intentionally is not wired into Player, since it would let a configured player exceed the Homeless housing tier's real energy cap (60) - see the comment in Player.init. Confirmed this is backend-only (no front-end-visible menu/dialogue), so no console/pygame/web parity work is needed. Full suite green (345 passed) with 100% coverage on every newly-touched module.",
"event": "COMMENT",
"comments": []
}

@dmccoystephenson

Copy link
Copy Markdown
Member Author

Self-review: no issues found. Verified backwards compatibility (missing-key saves still load via the existing .get()-with-defaults fallback; validation only runs against the reconstructed object, not the raw input, so it cannot reject a save merely for omitting optional keys). Verified Config.initialEnergy (100) intentionally is not wired into Player, since it would let a configured player exceed the Homeless housing tier's real energy cap (60) - see the comment in Player.init. Confirmed this is backend-only (no front-end-visible menu/dialogue), so no console/pygame/web parity work is needed. Full suite green (345 passed) with 100% coverage on every newly-touched module.

@dmccoystephenson

Copy link
Copy Markdown
Member Author

(Ignore the raw-JSON comment above - it was an artifact from an earlier attempt to post this same self-review through the reviews API; the review content is in the comment below it.)

@dmccoystephenson
dmccoystephenson merged commit 1770f7f into main Jul 19, 2026
1 check passed
@dmccoystephenson
dmccoystephenson deleted the feature/wire-config-and-validate-save-schemas branch July 19, 2026 05:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant