Skip to content

Commit 6b69045

Browse files
committed
fix(client): validate property name in _build_property_definitions; sync docstring types
- _build_property_definitions: raise ValueError with index when property entry is not a dict with a non-empty 'name' key (was KeyError) - LabelInfo.schema_mode inline annotation: 0=unspecified (not 0=unspecified/strict) - create_label docstring: add "list" and "map" to the type strings list - _first_label docstring: clarify min() is intentional for determinism; labels(n)[0] is unstable due to non-guaranteed label ordering
1 parent 0464697 commit 6b69045

2 files changed

Lines changed: 11 additions & 7 deletions

File tree

coordinode/coordinode/client.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ def __init__(self, proto_label: Any) -> None:
105105
self.name: str = proto_label.name
106106
self.version: int = proto_label.version
107107
self.properties: list[PropertyDefinitionInfo] = [PropertyDefinitionInfo(p) for p in proto_label.properties]
108-
# schema_mode: 0=unspecified/strict, 1=strict, 2=validated, 3=flexible
108+
# schema_mode: 0=unspecified, 1=strict, 2=validated, 3=flexible
109109
self.schema_mode: int = getattr(proto_label, "schema_mode", 0)
110110

111111
def __repr__(self) -> str:
@@ -391,12 +391,14 @@ def _build_property_definitions(
391391
"map": PropertyType.PROPERTY_TYPE_MAP,
392392
}
393393
result = []
394-
for p in properties or []:
394+
for idx, p in enumerate(properties or []):
395+
name = p.get("name") if isinstance(p, dict) else None
396+
if not isinstance(name, str) or not name:
397+
raise ValueError(f"Property at index {idx} must be a dict with a non-empty 'name' key; got {p!r}")
395398
type_str = str(p.get("type", "string")).lower()
396399
if type_str not in type_map:
397400
raise ValueError(
398-
f"Unknown property type {type_str!r} for property {p['name']!r}. "
399-
f"Expected one of: {sorted(type_map)}"
401+
f"Unknown property type {type_str!r} for property {name!r}. Expected one of: {sorted(type_map)}"
400402
)
401403
result.append(
402404
PropertyDefinition(
@@ -423,7 +425,7 @@ async def create_label(
423425
``name`` (str), ``type`` (str), ``required`` (bool),
424426
``unique`` (bool). Type strings: ``"string"``,
425427
``"int64"``, ``"float64"``, ``"bool"``, ``"bytes"``,
426-
``"timestamp"``, ``"vector"``.
428+
``"timestamp"``, ``"vector"``, ``"list"``, ``"map"``.
427429
schema_mode: ``"strict"`` (default — reject undeclared props),
428430
``"validated"`` (allow extra props without interning),
429431
``"flexible"`` (no enforcement).

langchain-coordinode/langchain_coordinode/graph.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -285,8 +285,10 @@ def _first_label(labels: Any) -> str | None:
285285
possible. ``min()`` gives a deterministic result regardless of how many
286286
labels are present.
287287
288-
TODO: replace with ``labels(n)[0]`` in Cypher once subscript-on-function
289-
lands in the published Docker image.
288+
Note: once subscript-on-function support lands in the published Docker
289+
image (tracked in G010 / GAPS.md), this Python helper could be replaced
290+
by an inline Cypher expression — but keep the deterministic ``min()``
291+
rule rather than index 0, since label ordering is not guaranteed stable.
290292
"""
291293
if isinstance(labels, list) and labels:
292294
return str(min(labels))

0 commit comments

Comments
 (0)