Skip to content

Commit 0400912

Browse files
committed
fix(client,graph,notebooks): property validation, schema fallback, rustup via urllib
- _build_property_definitions(): validate properties is list/tuple before iterating; passes None→[] early, raises clear TypeError on dict input instead of confusing 'Property at index 0 must be a dict; got str' error - CoordinodeGraph.refresh_schema(): wrap get_schema_text() in try/except so a failing custom client method degrades to empty schema text instead of aborting before the structured-API / _parse_schema() fallback can run; clarify docstring - CoordinodeGraph.refresh_schema() docstring: note that relationships may still be inferred via Cypher even when property metadata is unavailable - demo notebooks (all 4): replace curl|sh pipeline (shell=True) with urllib.request + NamedTemporaryFile + explicit /bin/sh invocation; removes shell=True with untrusted content; uses Python default ssl context (TLS 1.2+, cert-verified) — equivalent security to the former --tlsv1.2 curl flags - notebooks 01 (LlamaIndex) and 02 (LangChain): add explicit 'coordinode' to pip install list (was only a transitive dep via framework packages; now explicit) - notebook 00_seed_data: _label() now validates against all three known sets (src_names, tech_names, company_names) and raises ValueError for unknown names instead of silently defaulting to 'Company' - notebook 03_langgraph_agent: update query_facts docstring to document both accepted session-scope forms; merge implicitly concatenated error strings
1 parent 83bf591 commit 0400912

6 files changed

Lines changed: 293 additions & 9 deletions

File tree

coordinode/coordinode/client.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,8 +416,12 @@ def _build_property_definitions(
416416
"list": property_type_cls.PROPERTY_TYPE_LIST,
417417
"map": property_type_cls.PROPERTY_TYPE_MAP,
418418
}
419+
if properties is None:
420+
return []
421+
if not isinstance(properties, (list, tuple)):
422+
raise ValueError(f"'properties' must be a list of property dicts or None; got {type(properties).__name__}")
419423
result = []
420-
for idx, p in enumerate(properties or []):
424+
for idx, p in enumerate(properties):
421425
if not isinstance(p, dict):
422426
raise ValueError(f"Property at index {idx} must be a dict; got {p!r}")
423427
name = p.get("name")

demo/notebooks/00_seed_data.ipynb

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,51 @@
4040
"id": "a1b2c3d4-0000-0000-0000-000000000003",
4141
"metadata": {},
4242
"outputs": [],
43-
"source": "import sys, subprocess\n\nIN_COLAB = \"google.colab\" in sys.modules\n\n# Always install coordinode-embedded so it's available as a local fallback.\nif IN_COLAB:\n # Install Rust toolchain via rustup (https://rustup.rs).\n # Colab's apt packages ship rustc ≤1.75, which cannot build coordinode-embedded\n # (requires Rust ≥1.80 for maturin/pyo3). apt-get is not a viable alternative here.\n # Security: `--proto \"=https\" --tlsv1.2` limits the connection to HTTPS with\n # TLS 1.2 minimum; rustup.rs is the official Rust Foundation installer endpoint.\n subprocess.run('curl --proto \"=https\" --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y -q', shell=True, check=True)\n subprocess.run([sys.executable, \"-m\", \"pip\", \"install\", \"-q\", \"maturin\"], check=True)\n\nsubprocess.run(\n [\n sys.executable,\n \"-m\",\n \"pip\",\n \"install\",\n \"-q\",\n \"coordinode\",\n \"git+https://github.com/structured-world/coordinode-python.git#subdirectory=coordinode-embedded\",\n \"nest_asyncio\",\n ],\n check=True,\n)\n\nimport nest_asyncio\n\nnest_asyncio.apply()\n\nprint(\"Ready\")"
43+
"source": [
44+
"import os, sys, subprocess\n",
45+
"\n",
46+
"IN_COLAB = \"google.colab\" in sys.modules\n",
47+
"\n",
48+
"# Always install coordinode-embedded so it's available as a local fallback.\n",
49+
"if IN_COLAB:\n",
50+
" # Install Rust toolchain via rustup (https://rustup.rs).\n",
51+
" # Colab's apt packages ship rustc ≤1.75, which cannot build coordinode-embedded\n",
52+
" # (requires Rust ≥1.80 for maturin/pyo3). apt-get is not a viable alternative here.\n",
53+
" # Download the installer to a temp file and execute it explicitly — this avoids\n",
54+
" # piping remote content directly into a shell while maintaining HTTPS/TLS security\n",
55+
" # through Python's default ssl context (cert-verified, TLS 1.2+).\n",
56+
" import ssl as _ssl, tempfile as _tmp, urllib.request as _ur\n",
57+
" _ctx = _ssl.create_default_context()\n",
58+
" with _tmp.NamedTemporaryFile(mode=\"wb\", suffix=\".sh\", delete=False) as _f:\n",
59+
" with _ur.urlopen(\"https://sh.rustup.rs\", context=_ctx) as _r:\n",
60+
" _f.write(_r.read())\n",
61+
" _rustup_path = _f.name\n",
62+
" try:\n",
63+
" subprocess.run([\"/bin/sh\", _rustup_path, \"-s\", \"--\", \"-y\", \"-q\"], check=True)\n",
64+
" finally:\n",
65+
" os.unlink(_rustup_path)\n",
66+
" subprocess.run([sys.executable, \"-m\", \"pip\", \"install\", \"-q\", \"maturin\"], check=True)\n",
67+
"\n",
68+
"subprocess.run(\n",
69+
" [\n",
70+
" sys.executable,\n",
71+
" \"-m\",\n",
72+
" \"pip\",\n",
73+
" \"install\",\n",
74+
" \"-q\",\n",
75+
" \"coordinode\",\n",
76+
" \"git+https://github.com/structured-world/coordinode-python.git#subdirectory=coordinode-embedded\",\n",
77+
" \"nest_asyncio\",\n",
78+
" ],\n",
79+
" check=True,\n",
80+
")\n",
81+
"\n",
82+
"import nest_asyncio\n",
83+
"\n",
84+
"nest_asyncio.apply()\n",
85+
"\n",
86+
"print(\"Ready\")"
87+
]
4488
},
4589
{
4690
"cell_type": "markdown",
@@ -252,7 +296,9 @@
252296
" return \"Person\"\n",
253297
" if name in tech_names:\n",
254298
" return \"Technology\"\n",
255-
" return \"Company\"\n",
299+
" if name in company_names:\n",
300+
" return \"Company\"\n",
301+
" raise ValueError(f\"Unknown edge endpoint: {name!r}\"\n",
256302
"\n",
257303
"\n",
258304
"for src, rel, dst, props in edges:\n",

demo/notebooks/01_llama_index_property_graph.ipynb

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,55 @@
3939
"id": "b2c3d4e5-0001-0000-0000-000000000003",
4040
"metadata": {},
4141
"outputs": [],
42-
"source": "import sys, subprocess\n\nIN_COLAB = \"google.colab\" in sys.modules\n\n# Always install coordinode-embedded so it's available as a local fallback.\n# In Colab, build from source (~5 min first run, cached after).\n# Locally, it installs in seconds if a pre-built wheel is cached.\nif IN_COLAB:\n # Install Rust toolchain via rustup (https://rustup.rs).\n # Colab's apt packages ship rustc ≤1.75, which cannot build coordinode-embedded\n # (requires Rust ≥1.80 for maturin/pyo3). apt-get is not a viable alternative here.\n # Security: `--proto \"=https\" --tlsv1.2` limits the connection to HTTPS with\n # TLS 1.2 minimum; rustup.rs is the official Rust Foundation installer endpoint.\n subprocess.run('curl --proto \"=https\" --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y -q', shell=True, check=True)\n subprocess.run([sys.executable, \"-m\", \"pip\", \"install\", \"-q\", \"maturin\"], check=True)\n\nsubprocess.run(\n [\n sys.executable,\n \"-m\",\n \"pip\",\n \"install\",\n \"-q\",\n \"git+https://github.com/structured-world/coordinode-python.git#subdirectory=coordinode-embedded\",\n \"llama-index-graph-stores-coordinode\",\n \"llama-index-core\",\n \"nest_asyncio\",\n ],\n check=True,\n)\n\nimport nest_asyncio\n\nnest_asyncio.apply()\n\nprint(\"SDK installed\")"
42+
"source": [
43+
"import os, sys, subprocess\n",
44+
"\n",
45+
"IN_COLAB = \"google.colab\" in sys.modules\n",
46+
"\n",
47+
"# Always install coordinode-embedded so it's available as a local fallback.\n",
48+
"# In Colab, build from source (~5 min first run, cached after).\n",
49+
"# Locally, it installs in seconds if a pre-built wheel is cached.\n",
50+
"if IN_COLAB:\n",
51+
" # Install Rust toolchain via rustup (https://rustup.rs).\n",
52+
" # Colab's apt packages ship rustc ≤1.75, which cannot build coordinode-embedded\n",
53+
" # (requires Rust ≥1.80 for maturin/pyo3). apt-get is not a viable alternative here.\n",
54+
" # Download the installer to a temp file and execute it explicitly — this avoids\n",
55+
" # piping remote content directly into a shell while maintaining HTTPS/TLS security\n",
56+
" # through Python's default ssl context (cert-verified, TLS 1.2+).\n",
57+
" import ssl as _ssl, tempfile as _tmp, urllib.request as _ur\n",
58+
" _ctx = _ssl.create_default_context()\n",
59+
" with _tmp.NamedTemporaryFile(mode=\"wb\", suffix=\".sh\", delete=False) as _f:\n",
60+
" with _ur.urlopen(\"https://sh.rustup.rs\", context=_ctx) as _r:\n",
61+
" _f.write(_r.read())\n",
62+
" _rustup_path = _f.name\n",
63+
" try:\n",
64+
" subprocess.run([\"/bin/sh\", _rustup_path, \"-s\", \"--\", \"-y\", \"-q\"], check=True)\n",
65+
" finally:\n",
66+
" os.unlink(_rustup_path)\n",
67+
" subprocess.run([sys.executable, \"-m\", \"pip\", \"install\", \"-q\", \"maturin\"], check=True)\n",
68+
"\n",
69+
"subprocess.run(\n",
70+
" [\n",
71+
" sys.executable,\n",
72+
" \"-m\",\n",
73+
" \"pip\",\n",
74+
" \"install\",\n",
75+
" \"-q\",\n",
76+
" \"coordinode\",\n",
77+
" \"git+https://github.com/structured-world/coordinode-python.git#subdirectory=coordinode-embedded\",\n",
78+
" \"llama-index-graph-stores-coordinode\",\n",
79+
" \"llama-index-core\",\n",
80+
" \"nest_asyncio\",\n",
81+
" ],\n",
82+
" check=True,\n",
83+
")\n",
84+
"\n",
85+
"import nest_asyncio\n",
86+
"\n",
87+
"nest_asyncio.apply()\n",
88+
"\n",
89+
"print(\"SDK installed\")"
90+
]
4391
},
4492
{
4593
"cell_type": "markdown",

demo/notebooks/02_langchain_graph_chain.ipynb

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,49 @@
3636
"id": "c3d4e5f6-0002-0000-0000-000000000003",
3737
"metadata": {},
3838
"outputs": [],
39-
"source": "import sys, subprocess\n\nIN_COLAB = \"google.colab\" in sys.modules\n\n# Always install coordinode-embedded so it's available as a local fallback.\nif IN_COLAB:\n # Install Rust toolchain via rustup (https://rustup.rs).\n # Colab's apt packages ship rustc ≤1.75, which cannot build coordinode-embedded\n # (requires Rust ≥1.80 for maturin/pyo3). apt-get is not a viable alternative here.\n # Security: `--proto \"=https\" --tlsv1.2` limits the connection to HTTPS with\n # TLS 1.2 minimum; rustup.rs is the official Rust Foundation installer endpoint.\n subprocess.run('curl --proto \"=https\" --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y -q', shell=True, check=True)\n subprocess.run([sys.executable, \"-m\", \"pip\", \"install\", \"-q\", \"maturin\"], check=True)\n\nsubprocess.run(\n [\n sys.executable,\n \"-m\",\n \"pip\",\n \"install\",\n \"-q\",\n \"git+https://github.com/structured-world/coordinode-python.git#subdirectory=coordinode-embedded\",\n \"langchain-coordinode\",\n \"langchain-community\",\n \"langchain-openai\",\n ],\n check=True,\n)\n\nprint(\"SDK installed\")"
39+
"source": [
40+
"import os, sys, subprocess\n",
41+
"\n",
42+
"IN_COLAB = \"google.colab\" in sys.modules\n",
43+
"\n",
44+
"# Always install coordinode-embedded so it's available as a local fallback.\n",
45+
"if IN_COLAB:\n",
46+
" # Install Rust toolchain via rustup (https://rustup.rs).\n",
47+
" # Colab's apt packages ship rustc ≤1.75, which cannot build coordinode-embedded\n",
48+
" # (requires Rust ≥1.80 for maturin/pyo3). apt-get is not a viable alternative here.\n",
49+
" # Download the installer to a temp file and execute it explicitly — this avoids\n",
50+
" # piping remote content directly into a shell while maintaining HTTPS/TLS security\n",
51+
" # through Python's default ssl context (cert-verified, TLS 1.2+).\n",
52+
" import ssl as _ssl, tempfile as _tmp, urllib.request as _ur\n",
53+
" _ctx = _ssl.create_default_context()\n",
54+
" with _tmp.NamedTemporaryFile(mode=\"wb\", suffix=\".sh\", delete=False) as _f:\n",
55+
" with _ur.urlopen(\"https://sh.rustup.rs\", context=_ctx) as _r:\n",
56+
" _f.write(_r.read())\n",
57+
" _rustup_path = _f.name\n",
58+
" try:\n",
59+
" subprocess.run([\"/bin/sh\", _rustup_path, \"-s\", \"--\", \"-y\", \"-q\"], check=True)\n",
60+
" finally:\n",
61+
" os.unlink(_rustup_path)\n",
62+
" subprocess.run([sys.executable, \"-m\", \"pip\", \"install\", \"-q\", \"maturin\"], check=True)\n",
63+
"\n",
64+
"subprocess.run(\n",
65+
" [\n",
66+
" sys.executable,\n",
67+
" \"-m\",\n",
68+
" \"pip\",\n",
69+
" \"install\",\n",
70+
" \"-q\",\n",
71+
" \"coordinode\",\n",
72+
" \"git+https://github.com/structured-world/coordinode-python.git#subdirectory=coordinode-embedded\",\n",
73+
" \"langchain-coordinode\",\n",
74+
" \"langchain-community\",\n",
75+
" \"langchain-openai\",\n",
76+
" ],\n",
77+
" check=True,\n",
78+
")\n",
79+
"\n",
80+
"print(\"SDK installed\")"
81+
]
4082
},
4183
{
4284
"cell_type": "markdown",

0 commit comments

Comments
 (0)