Skip to content

Commit 0e57b89

Browse files
committed
annotate_schema: follow $anchor-style $refs during property traversal
The $ref guard in process_subschema only followed refs starting with '#/' (JSON Pointer) or '<location>#/' — silently skipping $anchor refs like '#item'. When an array property's items.$ref used a $anchor, the $defs entry was never visited with the inner @context of that property, so its sub-properties ended up unannotated (leaking into x-jsonld-extra-terms instead). Fix: broaden the condition to startswith('#') / startswith('<location>#') so $anchor refs are also followed. SchemaResolver already handles them correctly via _find_anchors / _get_branch. Adds test_anchor_ref_inner_context to cover this case.
1 parent aef11d2 commit 0e57b89

4 files changed

Lines changed: 56 additions & 1 deletion

File tree

ogc/na/annotate_schema.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -727,7 +727,7 @@ def process_subschema(subschema, context_stack, from_schema: ReferencedSchema, l
727727
if '$ref' in subschema and id(subschema) not in updated_refs:
728728
if self._ref_mapper:
729729
subschema['$ref'] = self._ref_mapper(subschema['$ref'], subschema)
730-
if subschema['$ref'].startswith('#/') or subschema['$ref'].startswith(f"{from_schema.location}#/"):
730+
if subschema['$ref'].startswith('#') or subschema['$ref'].startswith(f"{from_schema.location}#"):
731731
target_schema = self.schema_resolver.resolve_schema(subschema['$ref'], from_schema)
732732
if target_schema:
733733
new_terms = process_subschema(target_schema.subschema, context_stack,
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"@context": {
3+
"ex": "http://example.com/",
4+
"name": "ex:name",
5+
"items": {
6+
"@id": "ex:items",
7+
"@container": "@set",
8+
"@context": {
9+
"itemCode": "ex:code",
10+
"itemLabel": "ex:label"
11+
}
12+
}
13+
}
14+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
$schema: https://json-schema.org/draft/2020-12/schema
2+
x-jsonld-context: context.jsonld
3+
type: object
4+
$defs:
5+
item:
6+
$anchor: item
7+
type: object
8+
properties:
9+
itemCode:
10+
type: string
11+
itemLabel:
12+
type: string
13+
properties:
14+
name:
15+
type: string
16+
items:
17+
type: array
18+
items:
19+
$ref: '#item'

test/test_annotate_schema.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,28 @@ def test_defs_annotation(self):
156156
self.assertEqual(deep_get(schema, '$defs', 'objectB', 'properties', 'propB', 'x-jsonld-id'),
157157
vocab + 'b')
158158

159+
def test_anchor_ref_inner_context(self):
160+
# Regression: $ref: "#anchor" (a $anchor-style ref, not a JSON Pointer #/ ref)
161+
# was not followed during property traversal, so $defs entries referenced this way
162+
# were never annotated with the inner @context of the containing array property.
163+
# The properties ended up in x-jsonld-extra-terms instead of on the $defs schema.
164+
annotator = SchemaAnnotator()
165+
schema = annotator.process_schema(
166+
DATA_DIR / 'anchor-ref-inner-context/schema.yaml').schema
167+
168+
# Top-level property with inner @context
169+
self.assertEqual(deep_get(schema, 'properties', 'items', 'x-jsonld-id'),
170+
'http://example.com/items')
171+
# $defs/item properties must be annotated via the inner @context of 'items'
172+
self.assertEqual(deep_get(schema, '$defs', 'item', 'properties', 'itemCode', 'x-jsonld-id'),
173+
'http://example.com/code')
174+
self.assertEqual(deep_get(schema, '$defs', 'item', 'properties', 'itemLabel', 'x-jsonld-id'),
175+
'http://example.com/label')
176+
# Must not leak into extra-terms
177+
extra = schema.get('x-jsonld-extra-terms', {})
178+
self.assertNotIn('itemCode', extra)
179+
self.assertNotIn('itemLabel', extra)
180+
159181
def test_nested_context_file_ref(self):
160182
# Bug: resolve_inner uses the outer `ctx` closure variable instead of `inner_ctx`
161183
# when a context term's @context is a file path reference to a different file.

0 commit comments

Comments
 (0)