Skip to content

Commit e43ba0a

Browse files
wmaynerclaude
andcommitted
Add flexible JSON version validation with VALIDATE_JSON_VERSION config
The previous JSON version check required exact version matches, which caused issues when loading data saved with different dev builds (e.g., 1.2.1.dev1534+g12345 vs 1.2.1.dev1600+gabcde from hatch-vcs). This change: - Adds VALIDATE_JSON_VERSION config option to disable version checking - Allows compatible versions with matching base but different dev suffixes - Improves error message to say "incompatible" instead of "different" Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 68e29f6 commit e43ba0a

3 files changed

Lines changed: 50 additions & 7 deletions

File tree

pyphi/conf.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -762,6 +762,15 @@ def always_zero(a, b):
762762
independent.""",
763763
)
764764

765+
VALIDATE_JSON_VERSION = Option(
766+
True,
767+
type=bool,
768+
doc="""
769+
Controls whether PyPhi validates that JSON data was saved with a compatible
770+
version. If set to ``False``, JSON from any version can be loaded, which
771+
may cause errors if the data format changed between versions.""",
772+
)
773+
765774
SINGLE_MICRO_NODES_WITH_SELFLOOPS_HAVE_PHI = Option(
766775
True,
767776
type=bool,

pyphi/conf.pyi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ class PyphiConfig(Config):
8484
PROGRESS_BARS: bool
8585
VALIDATE_SUBSYSTEM_STATES: bool
8686
VALIDATE_CONDITIONAL_INDEPENDENCE: bool
87+
VALIDATE_JSON_VERSION: bool
8788
SINGLE_MICRO_NODES_WITH_SELFLOOPS_HAVE_PHI: bool
8889
PRINT_FRACTIONS: bool
8990
SYSTEM_PARTITION_INCLUDE_COMPLETE: bool

pyphi/jsonify.py

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,21 @@ def from_json(cls, json):
5151

5252
PYPHI_VERSION = get_version("pyphi")
5353

54+
55+
def _parse_version(version_str: str) -> tuple[str, str | None]:
56+
"""Parse version into (base_version, dev_suffix).
57+
58+
Examples:
59+
"2.0.0a1" -> ("2.0.0a1", None)
60+
"1.2.1.dev1534+g12345" -> ("1.2.1", "dev1534+g12345")
61+
"""
62+
# Check for .dev suffix pattern (common with hatch-vcs)
63+
if ".dev" in version_str:
64+
parts = version_str.split(".dev", 1)
65+
return parts[0], "dev" + parts[1]
66+
return version_str, None
67+
68+
5469
# TODO: extend to `macro` objects
5570
# TODO: resolve schema issues with `vphi` and other external consumers
5671
# TODO: somehow check schema instead of version?
@@ -251,13 +266,31 @@ def dump(obj, fp, **user_kwargs):
251266
return json.dump(obj, fp, **_encoder_kwargs(user_kwargs))
252267

253268

254-
def _check_version(version):
255-
"""Check whether the JSON version matches the PyPhi version."""
256-
if version != PYPHI_VERSION:
257-
raise pyphi.exceptions.JSONVersionError( # pyright: ignore[reportAttributeAccessIssue]
258-
"Cannot load JSON from a different version of PyPhi. "
259-
f"JSON version = {version}, current version = {PYPHI_VERSION}."
260-
)
269+
def _check_version(version: str) -> None:
270+
"""Check whether the JSON version is compatible with current PyPhi version.
271+
272+
The check can be disabled via config.VALIDATE_JSON_VERSION. When enabled,
273+
versions are considered compatible if:
274+
1. They match exactly, OR
275+
2. Their base versions match (ignoring .dev suffixes from hatch-vcs)
276+
"""
277+
if not pyphi.config.VALIDATE_JSON_VERSION:
278+
return
279+
280+
if version == PYPHI_VERSION:
281+
return
282+
283+
json_base, _ = _parse_version(version)
284+
current_base, _ = _parse_version(PYPHI_VERSION)
285+
286+
if json_base == current_base:
287+
# Same base version, just different dev builds
288+
return
289+
290+
raise pyphi.exceptions.JSONVersionError( # pyright: ignore[reportAttributeAccessIssue]
291+
f"Cannot load JSON from incompatible PyPhi version. "
292+
f"JSON version = {version}, current version = {PYPHI_VERSION}."
293+
)
261294

262295

263296
def _is_loadable_model_object(obj):

0 commit comments

Comments
 (0)