From fd5206bc6aa9f343542756619a8ae0d0dad1786b Mon Sep 17 00:00:00 2001 From: Artifizer Date: Sun, 21 Dec 2025 03:31:02 +0200 Subject: [PATCH] fix: fix recently broken codebase and revert the changes back Signed-off-by: Artifizer --- gts/src/gts/entities.py | 18 +++++---- gts/src/gts/files_reader.py | 18 +++------ gts/src/gts/ops.py | 16 ++++---- gts/src/gts/schema_cast.py | 73 ++++++++++++++++++++++++++++--------- gts/src/gts/store.py | 14 +++---- tests/test_entities.py | 72 ++++++++++++++++++------------------ tests/test_path_resolver.py | 60 +++++++++++++++--------------- tests/test_store.py | 30 +++++++-------- 8 files changed, 168 insertions(+), 133 deletions(-) diff --git a/gts/src/gts/entities.py b/gts/src/gts/entities.py index 1d5e92a..a0bcfe5 100644 --- a/gts/src/gts/entities.py +++ b/gts/src/gts/entities.py @@ -1,12 +1,14 @@ from __future__ import annotations from dataclasses import dataclass, field -from typing import Any, Dict, List, Optional, Set, Tuple +from typing import TYPE_CHECKING, Any, Dict, List, Optional, Set, Tuple from .gts import GtsID -from .path_resolver import GtsPathResolver from .schema_cast import GtsEntityCastResult, SchemaCastError +if TYPE_CHECKING: + from .path_resolver import GtsPathResolver + @dataclass class ValidationError: @@ -166,16 +168,18 @@ def _is_json_schema_entity(self) -> bool: return True return False - def resolve_path(self, path: str) -> JsonPathResolver: - resolver = JsonPathResolver(self.gts_id.id if self.gts_id else "", self.content) + def resolve_path(self, path: str) -> "GtsPathResolver": + from .path_resolver import GtsPathResolver + + resolver = GtsPathResolver(self.gts_id.id if self.gts_id else "", self.content) return resolver.resolve(path) def cast( self, - to_schema: JsonEntity, - from_schema: JsonEntity, + to_schema: "GtsEntity", + from_schema: "GtsEntity", resolver: Optional[Any] = None, - ) -> JsonEntityCastResult: + ) -> GtsEntityCastResult: if self.is_schema: # When casting a schema, from_schema might be a standard JSON Schema (no gts_id) # In that case, skip the sanity check diff --git a/gts/src/gts/files_reader.py b/gts/src/gts/files_reader.py index 1e60e58..10e370b 100644 --- a/gts/src/gts/files_reader.py +++ b/gts/src/gts/files_reader.py @@ -41,7 +41,7 @@ def __init__(self, path: str | List[str], cfg: Optional[GtsConfig] = None) -> No def _collect_files(self) -> None: """Collect all JSON and YAML files from the specified paths, following symlinks.""" - valid_extensions = {'.json', '.jsonc', '.gts', '.yaml', '.yml'} + valid_extensions = {".json", ".jsonc", ".gts", ".yaml", ".yml"} seen: set[str] = set() collected: List[Path] = [] @@ -77,7 +77,7 @@ def _collect_files(self) -> None: def _load_file(self, file_path: Path) -> Any: """Load content from JSON or YAML file.""" with file_path.open("r", encoding="utf-8") as f: - if file_path.suffix.lower() in {'.yaml', '.yml'}: + if file_path.suffix.lower() in {".yaml", ".yml"}: return yaml.safe_load(f) else: return json.load(f) @@ -89,29 +89,21 @@ def _process_file(self, file_path: Path) -> List[GtsEntity]: try: content = self._load_file(file_path) json_file = GtsFile( - path=str(file_path), - name=file_path.name, - content=content + path=str(file_path), name=file_path.name, content=content ) # Handle both single objects and arrays if isinstance(content, list): for idx, item in enumerate(content): entity = GtsEntity( - file=json_file, - list_sequence=idx, - content=item, - cfg=self.cfg + file=json_file, list_sequence=idx, content=item, cfg=self.cfg ) if entity.gts_id: logging.debug(f"- discovered entity: {entity.gts_id.id}") entities.append(entity) else: entity = GtsEntity( - file=json_file, - list_sequence=None, - content=content, - cfg=self.cfg + file=json_file, list_sequence=None, content=content, cfg=self.cfg ) if entity.gts_id: logging.debug(f"- discovered entity: {entity.gts_id.id}") diff --git a/gts/src/gts/ops.py b/gts/src/gts/ops.py index a3d31a3..e1a2512 100644 --- a/gts/src/gts/ops.py +++ b/gts/src/gts/ops.py @@ -314,7 +314,7 @@ def reload_from_path(self, path: str | List[str]) -> None: def add_entity( self, content: Dict[str, Any], validate: bool = False ) -> GtsAddEntityResult: - entity = JsonEntity(content=content, cfg=self.cfg) + entity = GtsEntity(content=content, cfg=self.cfg) if not entity.gts_id: return GtsAddEntityResult( ok=False, error="Unable to detect GTS ID in entity" @@ -433,33 +433,33 @@ def schema_graph(self, gts_id: str) -> GtsSchemaGraphResult: def compatibility( self, old_schema_id: str, new_schema_id: str - ) -> JsonEntityCastResult: + ) -> GtsEntityCastResult: return self.store.is_minor_compatible(old_schema_id, new_schema_id) - def cast(self, from_id: str, to_schema_id: str) -> JsonEntityCastResult: + def cast(self, from_id: str, to_schema_id: str) -> GtsEntityCastResult: try: return self.store.cast(from_id, to_schema_id) except Exception as e: - return JsonEntityCastResult(error=str(e)) + return GtsEntityCastResult(error=str(e)) def query(self, expr: str, limit: int = 100) -> GtsStoreQueryResult: return self.store.query(expr, limit) - def attr(self, gts_with_path: str) -> JsonPathResolver: + def attr(self, gts_with_path: str) -> GtsPathResolver: gts, path = GtsID.split_at_path(gts_with_path) if path is None: - return JsonPathResolver(gts_id=gts, content=None).failure( + return GtsPathResolver(gts_id=gts, content=None).failure( "", "Attribute selector requires '@path' in the identifier" ) entity = self.store.get(gts) if not entity: - return JsonPathResolver(gts_id=gts, content=None).failure( + return GtsPathResolver(gts_id=gts, content=None).failure( path, f"Entity not found: {gts}" ) return entity.resolve_path(path) def extract_id(self, content: Dict[str, Any]) -> GtsExtractIdResult: - entity = JsonEntity(content=content, cfg=self.cfg) + entity = GtsEntity(content=content, cfg=self.cfg) return GtsExtractIdResult( id=entity.gts_id.id if entity.gts_id else "", schema_id=entity.schemaId, diff --git a/gts/src/gts/schema_cast.py b/gts/src/gts/schema_cast.py index 9c56e3f..09dbb89 100644 --- a/gts/src/gts/schema_cast.py +++ b/gts/src/gts/schema_cast.py @@ -295,8 +295,13 @@ def _cast_instance_to_schema( p_type = p_schema.get("type") if p_type == "object" and isinstance(val, dict): nested_schema = GtsEntityCastResult._effective_object_schema(p_schema) - new_obj, add_sub, rem_sub, new_incompatibility_reasons = GtsEntityCastResult._cast_instance_to_schema( - val, nested_schema, base_path=(f"{base_path}.{prop}" if base_path else prop), incompatibility_reasons=incompatibility_reasons + new_obj, add_sub, rem_sub, new_incompatibility_reasons = ( + GtsEntityCastResult._cast_instance_to_schema( + val, + nested_schema, + base_path=(f"{base_path}.{prop}" if base_path else prop), + incompatibility_reasons=incompatibility_reasons, + ) ) result[prop] = new_obj added.extend(add_sub) @@ -304,16 +309,27 @@ def _cast_instance_to_schema( incompatibility_reasons.extend(new_incompatibility_reasons) elif p_type == "array" and isinstance(val, list): items_schema = p_schema.get("items") - if isinstance(items_schema, dict) and items_schema.get("type") == "object": - nested_schema = GtsEntityCastResult._effective_object_schema(items_schema) + if ( + isinstance(items_schema, dict) + and items_schema.get("type") == "object" + ): + nested_schema = GtsEntityCastResult._effective_object_schema( + items_schema + ) new_list: List[Any] = [] for idx, item in enumerate(val): if isinstance(item, dict): - new_item, add_sub, rem_sub, new_incompatibility_reasons = GtsEntityCastResult._cast_instance_to_schema( - item, - nested_schema, - base_path=(f"{base_path}.{prop}[{idx}]" if base_path else f"{prop}[{idx}]"), - incompatibility_reasons=incompatibility_reasons, + new_item, add_sub, rem_sub, new_incompatibility_reasons = ( + GtsEntityCastResult._cast_instance_to_schema( + item, + nested_schema, + base_path=( + f"{base_path}.{prop}[{idx}]" + if base_path + else f"{prop}[{idx}]" + ), + incompatibility_reasons=incompatibility_reasons, + ) ) new_list.append(new_item) added.extend(add_sub) @@ -481,7 +497,12 @@ def _check_constraint_compatibility( if prop_type in ("number", "integer"): errors.extend( GtsEntityCastResult._check_min_max_constraint( - prop, old_prop_schema, new_prop_schema, "minimum", "maximum", check_tightening + prop, + old_prop_schema, + new_prop_schema, + "minimum", + "maximum", + check_tightening, ) ) @@ -489,7 +510,12 @@ def _check_constraint_compatibility( if prop_type == "string": errors.extend( GtsEntityCastResult._check_min_max_constraint( - prop, old_prop_schema, new_prop_schema, "minLength", "maxLength", check_tightening + prop, + old_prop_schema, + new_prop_schema, + "minLength", + "maxLength", + check_tightening, ) ) @@ -497,7 +523,12 @@ def _check_constraint_compatibility( if prop_type == "array": errors.extend( GtsEntityCastResult._check_min_max_constraint( - prop, old_prop_schema, new_prop_schema, "minItems", "maxItems", check_tightening + prop, + old_prop_schema, + new_prop_schema, + "minItems", + "maxItems", + check_tightening, ) ) @@ -588,8 +619,10 @@ def _check_schema_compatibility( # Recursively check nested object properties if old_type == "object" and new_type == "object": - nested_compat, nested_errors = GtsEntityCastResult._check_schema_compatibility( - old_prop_schema, new_prop_schema, check_backward + nested_compat, nested_errors = ( + GtsEntityCastResult._check_schema_compatibility( + old_prop_schema, new_prop_schema, check_backward + ) ) if not nested_compat: for err in nested_errors: @@ -615,7 +648,9 @@ def _check_backward_compatibility( - Cannot add enum values - Cannot tighten constraints (decrease max, increase min, etc.) """ - return GtsEntityCastResult._check_schema_compatibility(old_schema, new_schema, check_backward=True) + return GtsEntityCastResult._check_schema_compatibility( + old_schema, new_schema, check_backward=True + ) @staticmethod def _check_forward_compatibility( @@ -634,7 +669,9 @@ def _check_forward_compatibility( - Cannot remove enum values - Cannot relax constraints (increase max, decrease min, etc.) """ - return GtsEntityCastResult._check_schema_compatibility(old_schema, new_schema, check_backward=False) + return GtsEntityCastResult._check_schema_compatibility( + old_schema, new_schema, check_backward=False + ) @staticmethod def _diff_objects( @@ -697,7 +734,9 @@ def _only_optional_add_remove( ) -> bool: if not isinstance(a, dict) or not isinstance(b, dict): if a != b: - reasons.append(f"{GtsEntityCastResult._path_label(path)}: value changed") + reasons.append( + f"{GtsEntityCastResult._path_label(path)}: value changed" + ) return False return True diff --git a/gts/src/gts/store.py b/gts/src/gts/store.py index dcea80f..0d7a2db 100644 --- a/gts/src/gts/store.py +++ b/gts/src/gts/store.py @@ -115,7 +115,7 @@ def __init__(self, reader: GtsReader) -> None: Args: reader: GtsReader instance to populate entities from """ - self._by_id: Dict[str, JsonEntity] = {} + self._by_id: Dict[str, GtsEntity] = {} self._reader = reader # Populate entities from reader if provided @@ -148,7 +148,7 @@ def register_schema(self, type_id: str, schema: Dict[str, Any]) -> None: raise ValueError("Schema type_id must end with '~'") # parse sanity gts_id = GtsID(type_id) - entity = JsonEntity(content=schema, gts_id=gts_id, is_schema=True) + entity = GtsEntity(content=schema, gts_id=gts_id, is_schema=True) self._by_id[type_id] = entity def get(self, entity_id: str) -> Optional[GtsEntity]: @@ -369,7 +369,7 @@ def is_minor_compatible( new_entity = self.get(new_schema_id) if not old_entity or not new_entity: - return JsonEntityCastResult( + return GtsEntityCastResult( from_id=old_schema_id, to_id=new_schema_id, direction="unknown", @@ -390,16 +390,16 @@ def is_minor_compatible( # Use the cast method's compatibility checking logic is_backward, backward_errors = ( - JsonEntityCastResult._check_backward_compatibility(old_schema, new_schema) + GtsEntityCastResult._check_backward_compatibility(old_schema, new_schema) ) - is_forward, forward_errors = JsonEntityCastResult._check_forward_compatibility( + is_forward, forward_errors = GtsEntityCastResult._check_forward_compatibility( old_schema, new_schema ) # Determine direction - direction = JsonEntityCastResult._infer_direction(old_schema_id, new_schema_id) + direction = GtsEntityCastResult._infer_direction(old_schema_id, new_schema_id) - return JsonEntityCastResult( + return GtsEntityCastResult( from_id=old_schema_id, to_id=new_schema_id, direction=direction, diff --git a/tests/test_entities.py b/tests/test_entities.py index 847a83e..b9fed79 100644 --- a/tests/test_entities.py +++ b/tests/test_entities.py @@ -1,8 +1,8 @@ -"""Tests for JsonEntity and related classes.""" +"""Tests for GtsEntity and related classes.""" from gts.entities import ( - JsonFile, - JsonEntity, + GtsFile, + GtsEntity, ValidationError, ValidationResult, DEFAULT_GTS_CONFIG, @@ -47,13 +47,13 @@ def test_validation_result_with_errors(self): assert len(result.errors) == 1 -class TestJsonFile: - """Tests for JsonFile dataclass.""" +class TestGtsFile: + """Tests for GtsFile dataclass.""" def test_json_file_single_content(self): - """Test JsonFile with single content.""" + """Test GtsFile with single content.""" content = {"name": "test"} - jf = JsonFile(path="/path/to/file.json", name="file.json", content=content) + jf = GtsFile(path="/path/to/file.json", name="file.json", content=content) assert jf.path == "/path/to/file.json" assert jf.name == "file.json" @@ -61,9 +61,9 @@ def test_json_file_single_content(self): assert jf.sequenceContent[0] == content def test_json_file_list_content(self): - """Test JsonFile with list content.""" + """Test GtsFile with list content.""" content = [{"id": 1}, {"id": 2}, {"id": 3}] - jf = JsonFile(path="/path/to/file.json", name="file.json", content=content) + jf = GtsFile(path="/path/to/file.json", name="file.json", content=content) assert jf.sequencesCount == 3 assert jf.sequenceContent[0] == {"id": 1} @@ -82,13 +82,13 @@ def test_default_config(self): assert "gtsType" in DEFAULT_GTS_CONFIG.schema_id_fields -class TestJsonEntity: - """Tests for JsonEntity class.""" +class TestGtsEntity: + """Tests for GtsEntity class.""" def test_entity_with_gts_id(self): """Test entity creation with explicit GTS ID.""" gts_id = GtsID("gts.vendor.package.namespace.type.v1~") - entity = JsonEntity( + entity = GtsEntity( content={"name": "test"}, gts_id=gts_id, ) @@ -98,7 +98,7 @@ def test_entity_with_gts_id(self): def test_entity_schema_detection_http(self): """Test schema detection via http json-schema.org URL.""" - entity = JsonEntity( + entity = GtsEntity( content={ "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", @@ -109,7 +109,7 @@ def test_entity_schema_detection_http(self): def test_entity_schema_detection_https(self): """Test schema detection via https json-schema.org URL.""" - entity = JsonEntity( + entity = GtsEntity( content={ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", @@ -120,7 +120,7 @@ def test_entity_schema_detection_https(self): def test_entity_schema_detection_gts_uri(self): """Test schema detection via gts:// URI.""" - entity = JsonEntity( + entity = GtsEntity( content={ "$schema": "gts://vendor.package.namespace.meta.v1~", "type": "object", @@ -131,7 +131,7 @@ def test_entity_schema_detection_gts_uri(self): def test_entity_schema_detection_gts_prefix(self): """Test schema detection via gts. prefix.""" - entity = JsonEntity( + entity = GtsEntity( content={ "$schema": "gts.vendor.package.namespace.meta.v1~", "type": "object", @@ -142,7 +142,7 @@ def test_entity_schema_detection_gts_prefix(self): def test_entity_not_schema(self): """Test non-schema entity.""" - entity = JsonEntity( + entity = GtsEntity( content={"name": "test", "value": 42}, ) @@ -150,7 +150,7 @@ def test_entity_not_schema(self): def test_entity_id_calculation(self): """Test entity ID calculation from content fields.""" - entity = JsonEntity( + entity = GtsEntity( content={ "$id": "gts.vendor.package.namespace.type.v1~", "name": "test", @@ -164,7 +164,7 @@ def test_entity_id_calculation(self): def test_entity_schema_id_calculation(self): """Test schema ID calculation from content fields.""" - entity = JsonEntity( + entity = GtsEntity( content={ "$schema": "gts.vendor.package.namespace.type.v1~", "name": "test", @@ -177,8 +177,8 @@ def test_entity_schema_id_calculation(self): def test_entity_label_from_file(self): """Test entity label derived from file.""" - jf = JsonFile(path="/path/to/file.json", name="file.json", content={}) - entity = JsonEntity( + jf = GtsFile(path="/path/to/file.json", name="file.json", content={}) + entity = GtsEntity( file=jf, list_sequence=0, content={"name": "test"}, @@ -189,7 +189,7 @@ def test_entity_label_from_file(self): def test_entity_label_from_gts_id(self): """Test entity label derived from GTS ID.""" gts_id = GtsID("gts.vendor.package.namespace.type.v1~") - entity = JsonEntity( + entity = GtsEntity( content={}, gts_id=gts_id, ) @@ -198,7 +198,7 @@ def test_entity_label_from_gts_id(self): def test_entity_description_extraction(self): """Test description extraction from content.""" - entity = JsonEntity( + entity = GtsEntity( content={ "description": "This is a test entity", "name": "test", @@ -209,19 +209,19 @@ def test_entity_description_extraction(self): def test_entity_description_empty(self): """Test empty description when not present.""" - entity = JsonEntity( + entity = GtsEntity( content={"name": "test"}, ) assert entity.description == "" -class TestJsonEntityRefs: - """Tests for GTS reference extraction in JsonEntity.""" +class TestGtsEntityRefs: + """Tests for GTS reference extraction in GtsEntity.""" def test_extract_gts_refs_simple(self): """Test extracting GTS refs from content.""" - entity = JsonEntity( + entity = GtsEntity( content={ "ref": "gts.vendor.package.namespace.other.v1~", }, @@ -233,7 +233,7 @@ def test_extract_gts_refs_simple(self): def test_extract_gts_refs_nested(self): """Test extracting nested GTS refs.""" - entity = JsonEntity( + entity = GtsEntity( content={ "data": {"nested": {"ref": "gts.vendor.package.namespace.deep.v1~"}} }, @@ -244,7 +244,7 @@ def test_extract_gts_refs_nested(self): def test_extract_gts_refs_in_array(self): """Test extracting GTS refs from arrays.""" - entity = JsonEntity( + entity = GtsEntity( content={ "items": [ "gts.vendor.package.namespace.item0.v1~", @@ -260,7 +260,7 @@ def test_extract_gts_refs_in_array(self): def test_extract_schema_refs(self): """Test extracting $ref strings from schema.""" - entity = JsonEntity( + entity = GtsEntity( content={ "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", @@ -276,7 +276,7 @@ def test_extract_schema_refs(self): def test_deduplicate_refs(self): """Test that duplicate refs are deduplicated.""" - entity = JsonEntity( + entity = GtsEntity( content={ "ref1": "gts.vendor.package.namespace.same.v1~", "ref2": "gts.vendor.package.namespace.same.v1~", @@ -287,13 +287,13 @@ def test_deduplicate_refs(self): assert len(entity.gts_refs) == 2 -class TestJsonEntityResolvePath: +class TestGtsEntityResolvePath: """Tests for resolve_path method.""" def test_resolve_path_simple(self): """Test simple path resolution.""" gts_id = GtsID("gts.vendor.package.namespace.type.v1~") - entity = JsonEntity( + entity = GtsEntity( content={"name": "test", "value": 42}, gts_id=gts_id, ) @@ -305,7 +305,7 @@ def test_resolve_path_simple(self): def test_resolve_path_nested(self): """Test nested path resolution.""" gts_id = GtsID("gts.vendor.package.namespace.type.v1~") - entity = JsonEntity( + entity = GtsEntity( content={"data": {"inner": "deep"}}, gts_id=gts_id, ) @@ -315,13 +315,13 @@ def test_resolve_path_nested(self): assert result.value == "deep" -class TestJsonEntityGetGraph: +class TestGtsEntityGetGraph: """Tests for get_graph method.""" def test_get_graph_basic(self): """Test basic graph generation.""" gts_id = GtsID("gts.vendor.package.namespace.type.v1~") - entity = JsonEntity( + entity = GtsEntity( content={ "ref": "gts.vendor.package.namespace.other.v1~", }, diff --git a/tests/test_path_resolver.py b/tests/test_path_resolver.py index c61cea0..2914d20 100644 --- a/tests/test_path_resolver.py +++ b/tests/test_path_resolver.py @@ -1,15 +1,15 @@ -"""Tests for JsonPathResolver.""" +"""Tests for GtsPathResolver.""" -from gts.path_resolver import JsonPathResolver +from gts.path_resolver import GtsPathResolver -class TestJsonPathResolverBasic: +class TestGtsPathResolverBasic: """Basic path resolution tests.""" def test_resolve_simple_key(self): """Test resolving a simple top-level key.""" content = {"name": "test", "value": 42} - resolver = JsonPathResolver("gts.test~", content) + resolver = GtsPathResolver("gts.test~", content) result = resolver.resolve("name") assert result.resolved is True @@ -19,7 +19,7 @@ def test_resolve_simple_key(self): def test_resolve_nested_key(self): """Test resolving a nested key.""" content = {"level1": {"level2": {"level3": "deep_value"}}} - resolver = JsonPathResolver("gts.test~", content) + resolver = GtsPathResolver("gts.test~", content) result = resolver.resolve("level1.level2.level3") assert result.resolved is True @@ -28,7 +28,7 @@ def test_resolve_nested_key(self): def test_resolve_array_index(self): """Test resolving an array index.""" content = {"items": ["first", "second", "third"]} - resolver = JsonPathResolver("gts.test~", content) + resolver = GtsPathResolver("gts.test~", content) result = resolver.resolve("items[1]") assert result.resolved is True @@ -37,7 +37,7 @@ def test_resolve_array_index(self): def test_resolve_nested_array(self): """Test resolving nested array access.""" content = {"matrix": [[1, 2], [3, 4], [5, 6]]} - resolver = JsonPathResolver("gts.test~", content) + resolver = GtsPathResolver("gts.test~", content) result = resolver.resolve("matrix[1][0]") assert result.resolved is True @@ -46,20 +46,20 @@ def test_resolve_nested_array(self): def test_resolve_mixed_path(self): """Test resolving a path with both objects and arrays.""" content = {"users": [{"name": "alice", "age": 30}, {"name": "bob", "age": 25}]} - resolver = JsonPathResolver("gts.test~", content) + resolver = GtsPathResolver("gts.test~", content) result = resolver.resolve("users[1].name") assert result.resolved is True assert result.value == "bob" -class TestJsonPathResolverSlashSyntax: +class TestGtsPathResolverSlashSyntax: """Test slash-based path syntax.""" def test_resolve_slash_path(self): """Test resolving a slash-separated path.""" content = {"level1": {"level2": "value"}} - resolver = JsonPathResolver("gts.test~", content) + resolver = GtsPathResolver("gts.test~", content) result = resolver.resolve("level1/level2") assert result.resolved is True @@ -68,7 +68,7 @@ def test_resolve_slash_path(self): def test_resolve_mixed_slash_and_dot(self): """Test that slashes are normalized to dots.""" content = {"a": {"b": {"c": "value"}}} - resolver = JsonPathResolver("gts.test~", content) + resolver = GtsPathResolver("gts.test~", content) result1 = resolver.resolve("a/b/c") result2 = resolver.resolve("a.b.c") @@ -76,13 +76,13 @@ def test_resolve_mixed_slash_and_dot(self): assert result1.value == result2.value == "value" -class TestJsonPathResolverErrors: +class TestGtsPathResolverErrors: """Error handling tests for path resolution.""" def test_path_not_found(self): """Test handling of non-existent path.""" content = {"name": "test"} - resolver = JsonPathResolver("gts.test~", content) + resolver = GtsPathResolver("gts.test~", content) result = resolver.resolve("nonexistent") assert result.resolved is False @@ -93,7 +93,7 @@ def test_path_not_found(self): def test_index_out_of_range(self): """Test handling of out-of-range array index.""" content = {"items": ["a", "b"]} - resolver = JsonPathResolver("gts.test~", content) + resolver = GtsPathResolver("gts.test~", content) result = resolver.resolve("items[5]") assert result.resolved is False @@ -102,7 +102,7 @@ def test_index_out_of_range(self): def test_invalid_index_format(self): """Test handling of non-integer array index.""" content = {"items": ["a", "b"]} - resolver = JsonPathResolver("gts.test~", content) + resolver = GtsPathResolver("gts.test~", content) result = resolver.resolve("items[abc]") assert result.resolved is False @@ -111,7 +111,7 @@ def test_invalid_index_format(self): def test_descend_into_scalar(self): """Test handling of descending into a scalar value.""" content = {"value": 42} - resolver = JsonPathResolver("gts.test~", content) + resolver = GtsPathResolver("gts.test~", content) result = resolver.resolve("value.subkey") assert result.resolved is False @@ -120,20 +120,20 @@ def test_descend_into_scalar(self): def test_array_index_on_dict(self): """Test handling of array index on dictionary.""" content = {"obj": {"key": "value"}} - resolver = JsonPathResolver("gts.test~", content) + resolver = GtsPathResolver("gts.test~", content) result = resolver.resolve("obj[0]") assert result.resolved is False assert result.error is not None -class TestJsonPathResolverAvailableFields: +class TestGtsPathResolverAvailableFields: """Tests for available_fields feature.""" def test_available_fields_on_dict(self): """Test that available fields are listed for dict.""" content = {"name": "test", "age": 30, "nested": {"inner": "value"}} - resolver = JsonPathResolver("gts.test~", content) + resolver = GtsPathResolver("gts.test~", content) result = resolver.resolve("nonexistent") assert "name" in result.available_fields @@ -144,7 +144,7 @@ def test_available_fields_on_dict(self): def test_available_fields_on_array(self): """Test that available indices are listed for array.""" content = {"items": ["a", "b", "c"]} - resolver = JsonPathResolver("gts.test~", content) + resolver = GtsPathResolver("gts.test~", content) result = resolver.resolve("items.nonexistent") assert "[0]" in result.available_fields @@ -152,13 +152,13 @@ def test_available_fields_on_array(self): assert "[2]" in result.available_fields -class TestJsonPathResolverToDict: +class TestGtsPathResolverToDict: """Tests for to_dict() method.""" def test_to_dict_success(self): """Test to_dict on successful resolution.""" content = {"key": "value"} - resolver = JsonPathResolver("gts.test~", content) + resolver = GtsPathResolver("gts.test~", content) result = resolver.resolve("key") d = result.to_dict() @@ -171,7 +171,7 @@ def test_to_dict_success(self): def test_to_dict_failure(self): """Test to_dict on failed resolution.""" content = {"key": "value"} - resolver = JsonPathResolver("gts.test~", content) + resolver = GtsPathResolver("gts.test~", content) result = resolver.resolve("nonexistent") d = result.to_dict() @@ -180,13 +180,13 @@ def test_to_dict_failure(self): assert "available_fields" in d -class TestJsonPathResolverEdgeCases: +class TestGtsPathResolverEdgeCases: """Edge case tests.""" def test_empty_path(self): """Test resolving empty path returns root content.""" content = {"key": "value"} - resolver = JsonPathResolver("gts.test~", content) + resolver = GtsPathResolver("gts.test~", content) result = resolver.resolve("") assert result.resolved is True @@ -195,7 +195,7 @@ def test_empty_path(self): def test_resolve_null_value(self): """Test resolving a null value.""" content = {"nullable": None} - resolver = JsonPathResolver("gts.test~", content) + resolver = GtsPathResolver("gts.test~", content) result = resolver.resolve("nullable") assert result.resolved is True @@ -204,7 +204,7 @@ def test_resolve_null_value(self): def test_resolve_boolean_false(self): """Test resolving a false boolean.""" content = {"flag": False} - resolver = JsonPathResolver("gts.test~", content) + resolver = GtsPathResolver("gts.test~", content) result = resolver.resolve("flag") assert result.resolved is True @@ -213,7 +213,7 @@ def test_resolve_boolean_false(self): def test_resolve_zero(self): """Test resolving zero value.""" content = {"count": 0} - resolver = JsonPathResolver("gts.test~", content) + resolver = GtsPathResolver("gts.test~", content) result = resolver.resolve("count") assert result.resolved is True @@ -222,7 +222,7 @@ def test_resolve_zero(self): def test_resolve_empty_string(self): """Test resolving empty string.""" content = {"text": ""} - resolver = JsonPathResolver("gts.test~", content) + resolver = GtsPathResolver("gts.test~", content) result = resolver.resolve("text") assert result.resolved is True @@ -231,7 +231,7 @@ def test_resolve_empty_string(self): def test_resolve_empty_array(self): """Test resolving empty array.""" content = {"items": []} - resolver = JsonPathResolver("gts.test~", content) + resolver = GtsPathResolver("gts.test~", content) result = resolver.resolve("items") assert result.resolved is True diff --git a/tests/test_store.py b/tests/test_store.py index 622a851..3b03d29 100644 --- a/tests/test_store.py +++ b/tests/test_store.py @@ -12,29 +12,29 @@ StoreGtsSchemaForInstanceNotFound, StoreGtsCastFromSchemaNotAllowed, ) -from gts.entities import JsonEntity, DEFAULT_GTS_CONFIG +from gts.entities import GtsEntity, DEFAULT_GTS_CONFIG from gts.gts import GtsID class MockGtsReader(GtsReader): """Mock reader for testing.""" - def __init__(self, entities: list[JsonEntity]): + def __init__(self, entities: list[GtsEntity]): self._entities = entities self._index = 0 - def __iter__(self) -> Iterator[JsonEntity]: + def __iter__(self) -> Iterator[GtsEntity]: self._index = 0 return self - def __next__(self) -> JsonEntity: + def __next__(self) -> GtsEntity: if self._index >= len(self._entities): raise StopIteration entity = self._entities[self._index] self._index += 1 return entity - def read_by_id(self, entity_id: str) -> Optional[JsonEntity]: + def read_by_id(self, entity_id: str) -> Optional[GtsEntity]: for entity in self._entities: if entity.gts_id and entity.gts_id.id == entity_id: return entity @@ -56,7 +56,7 @@ def test_store_creation_empty(self): def test_store_population_from_reader(self): """Test store is populated from reader.""" gts_id = GtsID("gts.vendor.package.namespace.type.v1~") - entity = JsonEntity( + entity = GtsEntity( content={"name": "test"}, gts_id=gts_id, is_schema=True, @@ -74,7 +74,7 @@ def test_store_register_entity(self): store = GtsStore(reader) gts_id = GtsID("gts.vendor.package.namespace.type.v1~") - entity = JsonEntity( + entity = GtsEntity( content={"registered": True}, gts_id=gts_id, ) @@ -111,7 +111,7 @@ def test_store_register_schema_invalid_id(self): def test_store_get_schema_content(self): """Test getting schema content.""" gts_id = GtsID("gts.vendor.package.namespace.type.v1~") - entity = JsonEntity( + entity = GtsEntity( content={"type": "object"}, gts_id=gts_id, is_schema=True, @@ -133,7 +133,7 @@ def test_store_get_schema_content_not_found(self): def test_store_items(self): """Test iterating over store items.""" entities = [ - JsonEntity( + GtsEntity( content={"name": f"entity{i}"}, gts_id=GtsID(f"gts.vendor.package.namespace.type{i}.v1~"), ) @@ -152,7 +152,7 @@ class TestGtsStoreQuery: def _create_store_with_entities(self): """Helper to create a store with test entities.""" entities = [ - JsonEntity( + GtsEntity( content={ "$id": "gts.vendor.package.namespace.user.v1~vendor.package.namespace.alice.v1", "name": "alice", @@ -160,7 +160,7 @@ def _create_store_with_entities(self): }, cfg=DEFAULT_GTS_CONFIG, ), - JsonEntity( + GtsEntity( content={ "$id": "gts.vendor.package.namespace.user.v1~vendor.package.namespace.bob.v1", "name": "bob", @@ -168,7 +168,7 @@ def _create_store_with_entities(self): }, cfg=DEFAULT_GTS_CONFIG, ), - JsonEntity( + GtsEntity( content={ "$id": "gts.vendor.package.namespace.order.v1~vendor.package.namespace.order1.v1", "orderId": "order1", @@ -242,7 +242,7 @@ class TestGtsStoreValidation: def _create_store_with_schema_and_instance(self): """Helper to create store with schema and instance.""" - schema = JsonEntity( + schema = GtsEntity( content={ "$schema": "http://json-schema.org/draft-07/schema#", "$id": "gts.vendor.package.namespace.type.v1~", @@ -255,7 +255,7 @@ def _create_store_with_schema_and_instance(self): cfg=DEFAULT_GTS_CONFIG, ) - instance = JsonEntity( + instance = GtsEntity( content={ "$id": "gts.vendor.package.namespace.type.v1~vendor.package.namespace.inst.v1", "gtsType": "gts.vendor.package.namespace.type.v1~", @@ -314,7 +314,7 @@ class TestGtsStoreBuildGraph: def test_build_graph_simple(self): """Test building a simple graph.""" - schema = JsonEntity( + schema = GtsEntity( content={ "$id": "gts.vendor.package.namespace.type.v1~", "$schema": "http://json-schema.org/draft-07/schema#",