Skip to content

Commit cccaa27

Browse files
committed
Adapt upstream Onya changes
1 parent d60cfbb commit cccaa27

File tree

6 files changed

+81
-12
lines changed

6 files changed

+81
-12
lines changed

demo/kgraph/README.md

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ Basic `.onya` format example:
3333
```onya
3434
# @docheader
3535
* @document: http://example.org/mydata
36-
* @base: http://example.org/entities/
36+
* @nodebase: http://example.org/entities/
37+
* @schema: https://schema.org/
38+
* @language: en
3739
3840
# Alice [Person]
3941
* name: Alice Smith
@@ -45,7 +47,7 @@ Basic `.onya` format example:
4547
* occupation: Data Scientist
4648
```
4749

48-
There is a document header which declares namespaces and base IRIs (URIs). Node definitions are marked with `# NodeID [Type]`. The node ID is resolved against `@document` and the type against
50+
There is a document header which declares namespaces and base IRIs (URIs). Node definitions are marked with `# NodeID [Type]`. Node IDs are resolved against `@nodebase`, while types and property labels are resolved against `@schema`.
4951
- **Properties**: Listed with `* property: value`
5052
- **Types**: Entities can have one or more types
5153

@@ -61,12 +63,14 @@ There is a document header which declares namespaces and base IRIs (URIs). Node
6163
cat > my_knowledge/people.onya << 'EOF'
6264
# @docheader
6365
* @document: http://example.org/mykg
64-
* @base: http://example.org/
66+
* @nodebase: http://example.org/
67+
* @schema: https://schema.org/
68+
* @language: en
6569
6670
# Person1 [Person]
6771
* name: Your Name
68-
* role: Your Role
69-
* expertise: Your Expertise
72+
* jobTitle: Your Role
73+
* knowsAbout: Your Expertise
7074
EOF
7175
```
7276

pylib/retrieval/graph.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,37 @@ def _matches(self, value: str) -> bool:
172172

173173
return False
174174

175+
@staticmethod
176+
def _localname(iri_or_label: str) -> str:
177+
'''
178+
Best-effort extraction of a "local name" from an IRI.
179+
180+
Examples:
181+
- "https://schema.org/bio" -> "bio"
182+
- "http://example.org/people/Person" -> "Person"
183+
- "name" -> "name"
184+
'''
185+
s = str(iri_or_label)
186+
if '#' in s:
187+
s = s.rsplit('#', 1)[-1]
188+
if '/' in s:
189+
s = s.rsplit('/', 1)[-1]
190+
return s
191+
192+
def _property_label_matches(self, prop_label: object) -> bool:
193+
'''
194+
Allow matching properties regardless of whether labels are stored as
195+
local names ("bio") or full IRIs ("https://schema.org/bio").
196+
'''
197+
want = str(self.property_label)
198+
have = str(prop_label)
199+
if have == want:
200+
return True
201+
# If caller provided a local name, compare against localname(have)
202+
if '://' not in want and not want.startswith('urn:'):
203+
return self._localname(have) == want
204+
return False
205+
175206
async def execute(
176207
self,
177208
query: str,
@@ -208,7 +239,7 @@ async def execute(
208239

209240
# Check properties
210241
for prop in node.properties:
211-
if prop.label == self.property_label:
242+
if self._property_label_matches(prop.label):
212243
if self._matches(prop.value):
213244
matched = True
214245
break

pylib/store/kgraph/onya_store.py

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ async def setup(self) -> None:
131131

132132
# Parse into graph
133133
doc_iri = literate_lex.parse(onya_text, self._graph)
134+
134135
self._loaded_files.append({
135136
'path': str(onya_file),
136137
'doc_iri': str(doc_iri) if doc_iri else None,
@@ -265,7 +266,30 @@ async def search_by_type(
265266
if not self._initialized:
266267
raise RuntimeError(f'KB {self.name} not initialized. Call setup() first.')
267268

268-
matched_nodes = list(self._graph.typematch(type_iri))
269+
type_iri_str = str(type_iri)
270+
type_iri_str_lower = type_iri_str.lower()
271+
272+
def _is_relative_iri(s: str) -> bool:
273+
return '://' not in s and not s.startswith('urn:')
274+
275+
def _matches_type(t: Any) -> bool:
276+
t_str = str(t)
277+
if t_str == type_iri_str:
278+
return True
279+
# Back-compat: if Onya returns relative types (e.g. "Person") but the
280+
# caller passes a full IRI, allow matching by localname.
281+
if _is_relative_iri(t_str) and type_iri_str_lower.endswith(('/' + t_str.lower(), '#' + t_str.lower())):
282+
return True
283+
return False
284+
285+
matched_nodes = [
286+
node
287+
for node in self._graph.values()
288+
if any(
289+
_matches_type(t)
290+
for t in getattr(node, 'types', ())
291+
)
292+
]
269293

270294
# Apply limit
271295
if limit > 0:
@@ -317,11 +341,19 @@ async def get_node(self, node_iri: str) -> dict | None:
317341
return None
318342

319343
# Convert to dict representation
344+
def _localname(iri_or_label: str) -> str:
345+
s = str(iri_or_label)
346+
if '#' in s:
347+
s = s.rsplit('#', 1)[-1]
348+
if '/' in s:
349+
s = s.rsplit('/', 1)[-1]
350+
return s
351+
320352
return {
321353
'id': str(node.id),
322354
'types': [str(t) for t in node.types],
323355
'properties': {
324-
prop.label: prop.value
356+
_localname(prop.label): prop.value
325357
for prop in node.properties
326358
}
327359
}

test/resource/onya/companies.onya

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# @docheader
22
* @document: http://example.org/companies
3-
* @base: http://example.org/companies/
3+
* @nodebase: http://example.org/companies/
4+
* @schema: http://example.org/companies/
45

56
# TechCorp [Organization]
67
* name: TechCorp Inc.

test/resource/onya/people.onya

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# @docheader
22
* @document: http://example.org/people
3-
* @base: http://example.org/people/
3+
* @nodebase: http://example.org/people/
4+
* @schema: http://example.org/people/
45

56
# Alice [Person]
67
* name: Alice Smith

test/store/kgraph/test_onya_store.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,10 @@ async def test_onya_kb_setup():
3333
loaded_files = kb.get_loaded_files()
3434
assert len(loaded_files) == 2
3535

36-
# Should have multiple nodes
36+
# Should have multiple nodes (includes 2 document nodes from Onya)
3737
node_count = kb.count_nodes()
3838
assert node_count > 0
39-
assert node_count == 5 # 3 people + 2 companies
39+
assert node_count == 7 # 3 people + 2 companies + 2 document nodes
4040

4141
await kb.cleanup()
4242

0 commit comments

Comments
 (0)