Skip to content

Commit 1edef76

Browse files
Use local schemas if available
cache hashable calls to yaml loader if possible
1 parent 7c311d9 commit 1edef76

File tree

4 files changed

+53
-10
lines changed

4 files changed

+53
-10
lines changed

linkml_runtime/__init__.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,25 @@
2525

2626
MAIN_SCHEMA_PATH = SCHEMA_DIRECTORY / "meta.yaml"
2727

28+
LINKML_ANNOTATIONS = SCHEMA_DIRECTORY / "annotations.yaml"
29+
LINKML_ARRAY = SCHEMA_DIRECTORY / "array.yaml"
30+
LINKML_EXTENSIONS = SCHEMA_DIRECTORY / "extensions.yaml"
31+
LINKML_MAPPINGS = SCHEMA_DIRECTORY / "mappings.yaml"
32+
LINKML_TYPES = SCHEMA_DIRECTORY / "types.yaml"
33+
LINKML_UNITS = SCHEMA_DIRECTORY / "units.yaml"
34+
LINKML_VALIDATION = SCHEMA_DIRECTORY / "validation.yaml"
35+
36+
37+
URI_TO_LOCAL = {
38+
'https://w3id.org/linkml/annotations.yaml': str(LINKML_ANNOTATIONS),
39+
'https://w3id.org/linkml/array.yaml': str(LINKML_ARRAY),
40+
'https://w3id.org/linkml/extensions.yaml': str(LINKML_EXTENSIONS),
41+
'https://w3id.org/linkml/mappings.yaml': str(LINKML_MAPPINGS),
42+
'https://w3id.org/linkml/meta.yaml': str(MAIN_SCHEMA_PATH),
43+
'https://w3id.org/linkml/types.yaml': str(LINKML_TYPES),
44+
'https://w3id.org/linkml/units.yaml': str(LINKML_UNITS),
45+
'https://w3id.org/linkml/validation.yaml': str(LINKML_VALIDATION),
46+
}
2847

2948
class MappingError(ValueError):
3049
"""

linkml_runtime/loaders/loader_root.py

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
from abc import ABC, abstractmethod
22
from typing import TextIO, Union, Optional, Callable, Dict, Type, Any, List
3+
from logging import getLogger
4+
from functools import lru_cache
35

46
from pydantic import BaseModel
57
from hbreader import FileInfo, hbread
68
from jsonasobj2 import as_dict, JsonObj
79

810
from linkml_runtime.utils.yamlutils import YAMLRoot
11+
from linkml_runtime import URI_TO_LOCAL
12+
13+
CACHE_SIZE = 1024
14+
915

1016

1117
class Loader(ABC):
@@ -137,20 +143,42 @@ def _construct_target_class(self,
137143
else:
138144
return None
139145

146+
140147
def _read_source(self,
141148
source: Union[str, dict, TextIO],
142149
*,
143150
base_dir: Optional[str] = None,
144151
metadata: Optional[FileInfo] = None,
145152
accept_header: Optional[str] = "text/plain, application/yaml;q=0.9") -> Union[dict, str]:
146-
if metadata is None:
147-
metadata = FileInfo()
148-
if base_dir and not metadata.base_path:
149-
metadata.base_path = base_dir
153+
154+
# avoid instantiating unhashable FileInfo type by getting default base_path, if any
155+
if base_dir is None:
156+
if metadata is not None:
157+
base_dir = str(metadata.base_path) if metadata.base_path is not None else None
158+
else:
159+
base_dir = str(FileInfo().base_path) if FileInfo().base_path is not None else None
160+
elif base_dir is not None:
161+
base_dir = str(base_dir)
150162

151163
if not isinstance(source, dict):
152-
data = hbread(source, metadata, metadata.base_path, accept_header)
164+
# Try to get local version of schema, if one is known to exist
165+
try:
166+
if str(source) in URI_TO_LOCAL.keys():
167+
source = str(URI_TO_LOCAL[str(source)])
168+
except (TypeError, KeyError) as e:
169+
# Fine, use original `source` value
170+
logger = getLogger('linkml_runtime.loaders.Loader')
171+
logger.debug(f"Error converting stringlike source to local linkml file: {source}, got: {e}")
172+
173+
if not isinstance(metadata, FileInfo):
174+
data = self._hashable_read(source, base_dir, accept_header)
175+
else:
176+
data = hbread(source, metadata, base_dir, accept_header)
153177
else:
154178
data = source
155179

156180
return data
181+
182+
@lru_cache(maxsize=CACHE_SIZE)
183+
def _hashable_read(self, source: Union[dict, TextIO], base_dir: Optional[str] = None, accept_header: Optional[str] = None):
184+
return hbread(source, None, base_dir, accept_header)

linkml_runtime/loaders/yaml_loader.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,6 @@ def load_as_dict(self,
2020
*,
2121
base_dir: Optional[str] = None,
2222
metadata: Optional[FileInfo] = None) -> Union[dict, List[dict]]:
23-
if metadata is None:
24-
metadata = FileInfo()
25-
if base_dir and not metadata.base_path:
26-
metadata.base_path = base_dir
2723
data = self._read_source(source, base_dir=base_dir, metadata=metadata, accept_header="text/yaml, application/yaml;q=0.9")
2824
if isinstance(data, str):
2925
data = StringIO(data)

tests/test_issues/input/issue_1040.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,4 @@ classes:
1717
Person:
1818
in_subset:
1919
- a
20-
-
20+
-

0 commit comments

Comments
 (0)