Skip to content

Commit 9045b86

Browse files
Merge pull request #205 from joshmoore/csv-test
csv testing and bug fixes
2 parents ff268a3 + 1f9636f commit 9045b86

File tree

10 files changed

+592
-702
lines changed

10 files changed

+592
-702
lines changed

linkml_runtime/loaders/rdflib_loader.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,8 @@ def from_rdf_graph(
164164
v = namespaces.curie_for(o)
165165
for enum_name in enum_names:
166166
e = schemaview.get_enum(enum_name)
167+
if e is None:
168+
raise ValueError(f"no enum found for {slot.range}: {o} (ns={v})")
167169
for pv in e.permissible_values.values():
168170
if v == pv.meaning or str(o) == pv.meaning:
169171
v = pv.text
@@ -206,9 +208,16 @@ def from_rdf_graph(
206208
# Step 2: replace inline pointers with object dicts
207209
def repl(v):
208210
if isinstance(v, Pointer):
209-
v2 = obj_map[v.obj]
211+
v2 = obj_map.get(v.obj)
210212
if v2 is None:
211-
raise Exception(f"No mapping for pointer {v}")
213+
msg = f"No mapping for pointer {v}. Triples:"
214+
for s, p, o in graph.triples((None, None, v.obj)):
215+
for s2, p2, o2 in graph.triples((None, None, s)):
216+
msg += f"\n{s2} {p2} {o2}."
217+
msg += f"\n{s} {p} {o}."
218+
for s, p, o in graph.triples((v.obj, None, None)):
219+
msg += f"\n{s} {p} {o}."
220+
raise Exception(msg)
212221
return v2
213222
else:
214223
return v
@@ -236,6 +245,8 @@ def repl(v):
236245
def _get_id_dict(self, node: VALID_SUBJECT, schemaview: SchemaView, cn: ClassDefinitionName) -> ANYDICT:
237246
id_slot = schemaview.get_identifier_slot(cn)
238247
if not isinstance(node, BNode):
248+
if id_slot is None:
249+
raise Exception(f"no slot found for {cn}: bnode={node}")
239250
id_val = self._uri_to_id(node, id_slot, schemaview)
240251
# id_val = schemaview.namespaces().curie_for(node)
241252
if id_val is None:

linkml_runtime/utils/yamlutils.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@ def __post_init__(self, *args: list[str], **kwargs):
4545
for k in kwargs.keys():
4646
v = repr(kwargs[k])[:40].replace("\n", "\\n")
4747
messages.append(f"{TypedNode.yaml_loc(k)} Unknown argument: {k} = {v}")
48-
raise ValueError("\n".join(messages))
48+
msg = f"Unknown arguments for: {self}\n"
49+
msg += "\n".join(messages)
50+
raise ValueError(msg)
4951

5052
def _default(self, obj, filtr: Callable[[dict], dict] = None):
5153
"""JSON serializer callback.

pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ dependencies = [
5656
dev = [
5757
"coverage >=6.2",
5858
"requests-cache >=1.2.0",
59+
"tox>=4",
60+
"ruff==0.11.13",
5961
]
6062

6163
[project.scripts]
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
columnA columnB columnB columnC
2+
table:row1 first value second value something else
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
columnA objectB columnC
2+
table:row1 {\"name\": \"foo\", \"value\": \"bar\"} something else
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
# Auto generated from table.yaml by pythongen.py version: 0.9.0
2+
# Generation date: 2022-10-10T16:55:54
3+
# Schema: table
4+
#
5+
# id: https://w3id.org/linkml/examples/table
6+
# description: Represent a table in linkml
7+
# license: https://creativecommons.org/publicdomain/zero/1.0/
8+
9+
import dataclasses
10+
import sys
11+
import re
12+
from jsonasobj2 import JsonObj, as_dict
13+
from typing import Optional, List, Union, Dict, ClassVar, Any
14+
from dataclasses import dataclass
15+
from linkml_runtime.linkml_model.meta import EnumDefinition, PermissibleValue, PvFormulaOptions
16+
17+
from linkml_runtime.utils.slot import Slot
18+
from linkml_runtime.utils.metamodelcore import empty_list, empty_dict, bnode
19+
from linkml_runtime.utils.yamlutils import YAMLRoot, extended_str, extended_float, extended_int
20+
from linkml_runtime.utils.dataclass_extensions_376 import dataclasses_init_fn_with_kwargs
21+
from linkml_runtime.utils.formatutils import camelcase, underscore, sfx
22+
from linkml_runtime.utils.enumerations import EnumDefinitionImpl
23+
from rdflib import Namespace, URIRef
24+
from linkml_runtime.utils.curienamespace import CurieNamespace
25+
from linkml_runtime.linkml_model.types import String, Uriorcurie
26+
from linkml_runtime.utils.metamodelcore import URIorCURIE
27+
28+
metamodel_version = "1.7.0"
29+
version = None
30+
31+
# Overwrite dataclasses _init_fn to add **kwargs in __init__
32+
dataclasses._init_fn = dataclasses_init_fn_with_kwargs
33+
34+
# Namespaces
35+
LINKML = CurieNamespace("linkml", "https://w3id.org/linkml/")
36+
TABLE = CurieNamespace("table", "https://w3id.org/linkml/examples/table/")
37+
DEFAULT_ = TABLE
38+
39+
40+
# Types
41+
42+
43+
# Class references
44+
class RowColumnA(URIorCURIE):
45+
pass
46+
47+
48+
@dataclass
49+
class Object(YAMLRoot):
50+
"""
51+
An object (bnode) which needs embedding in a single row
52+
"""
53+
54+
_inherited_slots: ClassVar[List[str]] = []
55+
56+
class_class_uri: ClassVar[URIRef] = TABLE.Object
57+
class_class_curie: ClassVar[str] = "table:Object"
58+
class_name: ClassVar[str] = "Object"
59+
class_model_uri: ClassVar[URIRef] = TABLE.Object
60+
61+
name: Optional[str] = None
62+
value: Optional[str] = None
63+
64+
def __post_init__(self, *_: List[str], **kwargs: Dict[str, Any]):
65+
if self.name is not None and not isinstance(self.name, str):
66+
self.name = str(self.name)
67+
68+
if self.value is not None and not isinstance(self.value, str):
69+
self.value = str(self.value)
70+
71+
super().__post_init__(**kwargs)
72+
73+
74+
@dataclass
75+
class Row(YAMLRoot):
76+
"""
77+
A single data point made up of columns.
78+
"""
79+
80+
_inherited_slots: ClassVar[List[str]] = []
81+
82+
class_class_uri: ClassVar[URIRef] = TABLE.Row
83+
class_class_curie: ClassVar[str] = "table:Row"
84+
class_name: ClassVar[str] = "Row"
85+
class_model_uri: ClassVar[URIRef] = TABLE.Row
86+
87+
columnA: Union[str, RowColumnA] = None
88+
objectB: Optional[Union[dict, Object]] = None
89+
columnC: Optional[str] = None
90+
91+
def __post_init__(self, *_: List[str], **kwargs: Dict[str, Any]):
92+
if self._is_empty(self.columnA):
93+
self.MissingRequiredField("columnA")
94+
if not isinstance(self.columnA, RowColumnA):
95+
self.columnA = RowColumnA(self.columnA)
96+
97+
if self.objectB is not None and not isinstance(self.objectB, Object):
98+
self.objectB = Object(**as_dict(self.objectB))
99+
100+
if self.columnC is not None and not isinstance(self.columnC, str):
101+
self.columnC = str(self.columnC)
102+
103+
super().__post_init__(**kwargs)
104+
105+
106+
@dataclass
107+
class Table(YAMLRoot):
108+
"""
109+
Container of rows.
110+
"""
111+
112+
_inherited_slots: ClassVar[List[str]] = []
113+
114+
class_class_uri: ClassVar[URIRef] = TABLE.Table
115+
class_class_curie: ClassVar[str] = "table:Table"
116+
class_name: ClassVar[str] = "Table"
117+
class_model_uri: ClassVar[URIRef] = TABLE.Table
118+
119+
rows: Optional[Union[Dict[Union[str, RowColumnA], Union[dict, Row]], List[Union[dict, Row]]]] = empty_dict()
120+
121+
def __post_init__(self, *_: List[str], **kwargs: Dict[str, Any]):
122+
self._normalize_inlined_as_list(slot_name="rows", slot_type=Row, key_name="columnA", keyed=True)
123+
124+
super().__post_init__(**kwargs)
125+
126+
127+
# Enumerations
128+
129+
130+
# Slots
131+
class slots:
132+
pass
133+
134+
135+
slots.rows = Slot(
136+
uri=TABLE.rows,
137+
name="rows",
138+
curie=TABLE.curie("rows"),
139+
model_uri=TABLE.rows,
140+
domain=None,
141+
range=Optional[Union[Dict[Union[str, RowColumnA], Union[dict, Row]], List[Union[dict, Row]]]],
142+
)
143+
144+
slots.columnA = Slot(
145+
uri=TABLE.columnA, name="columnA", curie=TABLE.curie("columnA"), model_uri=TABLE.columnA, domain=None, range=URIRef
146+
)
147+
148+
slots.objectB = Slot(
149+
uri=TABLE.objectB,
150+
name="objectB",
151+
curie=TABLE.curie("objectB"),
152+
model_uri=TABLE.objectB,
153+
domain=None,
154+
range=Optional[Union[dict, Object]],
155+
)
156+
157+
slots.columnC = Slot(
158+
uri=TABLE.columnC,
159+
name="columnC",
160+
curie=TABLE.curie("columnC"),
161+
model_uri=TABLE.columnC,
162+
domain=None,
163+
range=Optional[str],
164+
)
165+
166+
slots.name = Slot(
167+
uri=TABLE.name, name="name", curie=TABLE.curie("name"), model_uri=TABLE.name, domain=None, range=Optional[str]
168+
)
169+
170+
slots.value = Slot(
171+
uri=TABLE.value, name="value", curie=TABLE.curie("value"), model_uri=TABLE.value, domain=None, range=Optional[str]
172+
)
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
id: https://w3id.org/linkml/examples/table
2+
name: table
3+
description: |-
4+
Represent a table in linkml
5+
license: https://creativecommons.org/publicdomain/zero/1.0/
6+
imports:
7+
- linkml:types
8+
prefixes:
9+
table: https://w3id.org/linkml/examples/table/
10+
linkml: https://w3id.org/linkml/
11+
default_prefix: table
12+
default_range: string
13+
14+
classes:
15+
16+
Object:
17+
description: |-
18+
An object (bnode) which needs embedding in a single row
19+
slots:
20+
- name
21+
- value
22+
23+
Row:
24+
description: |-
25+
A single data point made up of columns.
26+
slots:
27+
- columnA
28+
- objectB
29+
- columnC
30+
31+
Table:
32+
description: |-
33+
Container of rows.
34+
tree_root: true
35+
slots:
36+
- rows
37+
38+
slots:
39+
rows:
40+
range: Row
41+
inlined: true
42+
inlined_as_list: true
43+
multivalued: true
44+
columnA:
45+
range: uriorcurie
46+
identifier: true
47+
objectB:
48+
range: Object
49+
inlined: true
50+
columnC:
51+
range: string
52+
multivalued: false
53+
name:
54+
range: string
55+
value:
56+
range: string

0 commit comments

Comments
 (0)