1
+ from __future__ import annotations
2
+
1
3
from abc import ABC , abstractmethod
2
4
from logging import getLogger
3
- from pathlib import Path
4
- from typing import Any , Callable , Optional , TextIO , Union
5
+ from typing import TYPE_CHECKING , Any , TextIO
5
6
6
7
from hbreader import FileInfo , hbread
7
8
from jsonasobj2 import JsonObj , as_dict
10
11
from linkml_runtime import URI_TO_LOCAL
11
12
from linkml_runtime .utils .yamlutils import YAMLRoot
12
13
14
+ if TYPE_CHECKING :
15
+ from collections .abc import Callable
16
+ from pathlib import Path
17
+
13
18
CACHE_SIZE = 1024
14
19
15
20
@@ -41,12 +46,12 @@ def _is_empty(o) -> bool:
41
46
42
47
def load_source (
43
48
self ,
44
- source : Union [ str , dict , TextIO ] ,
45
- loader : Callable [[Union [ str , dict ] , FileInfo ], Optional [ Union [ dict , list ]] ],
46
- target_class : Union [ type [YAMLRoot ], type [ BaseModel ] ],
47
- accept_header : Optional [ str ] = "text/plain, application/yaml;q=0.9" ,
48
- metadata : Optional [ FileInfo ] = None ,
49
- ) -> Optional [ Union [ BaseModel , YAMLRoot , list [BaseModel ], list [YAMLRoot ]]] :
49
+ source : str | dict | TextIO ,
50
+ loader : Callable [[str | dict , FileInfo ], dict | list | None ],
51
+ target_class : type [YAMLRoot | BaseModel ],
52
+ accept_header : str | None = "text/plain, application/yaml;q=0.9" ,
53
+ metadata : FileInfo | None = None ,
54
+ ) -> BaseModel | YAMLRoot | list [BaseModel ] | list [YAMLRoot ] | None :
50
55
"""Base loader - convert a file, url, string, open file handle or dictionary into an instance
51
56
of target_class
52
57
@@ -63,7 +68,7 @@ def load_source(
63
68
data_as_dict = loader (data , metadata )
64
69
return self ._construct_target_class (data_as_dict , target_class = target_class )
65
70
66
- def load (self , * args , ** kwargs ) -> Union [ BaseModel , YAMLRoot ] :
71
+ def load (self , * args , ** kwargs ) -> BaseModel | YAMLRoot :
67
72
"""
68
73
Load source as an instance of target_class
69
74
@@ -77,22 +82,22 @@ def load(self, *args, **kwargs) -> Union[BaseModel, YAMLRoot]:
77
82
results = self .load_any (* args , ** kwargs )
78
83
if isinstance (results , (BaseModel , YAMLRoot )):
79
84
return results
80
- else :
81
- raise ValueError (f"Result is not an instance of BaseModel or YAMLRoot: { type ( results ) } " )
85
+ msg = f"Result is not an instance of BaseModel or YAMLRoot: { type ( results ) } "
86
+ raise ValueError (msg )
82
87
83
- def load_as_dict (self , * args , ** kwargs ) -> Union [ dict , list [dict ] ]:
88
+ def load_as_dict (self , * args , ** kwargs ) -> dict | list [dict ]:
84
89
raise NotImplementedError ()
85
90
86
91
@abstractmethod
87
92
def load_any (
88
93
self ,
89
- source : Union [ str , dict , TextIO , Path ] ,
90
- target_class : type [Union [ BaseModel , YAMLRoot ] ],
94
+ source : str | dict | TextIO | Path ,
95
+ target_class : type [BaseModel | YAMLRoot ],
91
96
* ,
92
- base_dir : Optional [ str ] = None ,
93
- metadata : Optional [ FileInfo ] = None ,
97
+ base_dir : str | None = None ,
98
+ metadata : FileInfo | None = None ,
94
99
** _ ,
95
- ) -> Union [ BaseModel , YAMLRoot , list [BaseModel ], list [YAMLRoot ] ]:
100
+ ) -> BaseModel | YAMLRoot | list [BaseModel ] | list [YAMLRoot ]:
96
101
"""
97
102
Load source as an instance of target_class, or list of instances of target_class
98
103
@@ -106,8 +111,8 @@ def load_any(
106
111
raise NotImplementedError ()
107
112
108
113
def loads_any (
109
- self , source : str , target_class : type [Union [ BaseModel , YAMLRoot ]] , * , metadata : Optional [ FileInfo ] = None , ** _
110
- ) -> Union [ BaseModel , YAMLRoot , list [BaseModel ], list [YAMLRoot ] ]:
114
+ self , source : str , target_class : type [BaseModel | YAMLRoot ], * , metadata : FileInfo | None = None , ** _
115
+ ) -> BaseModel | YAMLRoot | list [BaseModel ] | list [YAMLRoot ]:
111
116
"""
112
117
Load source as a string as an instance of target_class, or list of instances of target_class
113
118
@param source: source
@@ -119,8 +124,8 @@ def loads_any(
119
124
return self .load_any (source , target_class , metadata = metadata )
120
125
121
126
def loads (
122
- self , source : str , target_class : type [Union [ BaseModel , YAMLRoot ]] , * , metadata : Optional [ FileInfo ] = None , ** _
123
- ) -> Union [ BaseModel , YAMLRoot ] :
127
+ self , source : str , target_class : type [BaseModel | YAMLRoot ], * , metadata : FileInfo | None = None , ** _
128
+ ) -> BaseModel | YAMLRoot :
124
129
"""
125
130
Load source as a string
126
131
:param source: source
@@ -132,53 +137,52 @@ def loads(
132
137
return self .load (source , target_class , metadata = metadata )
133
138
134
139
def _construct_target_class (
135
- self , data_as_dict : Union [ dict , list [dict ]] , target_class : Union [ type [YAMLRoot ], type [ BaseModel ] ]
136
- ) -> Optional [ Union [ BaseModel , YAMLRoot , list [BaseModel ], list [YAMLRoot ]]] :
140
+ self , data_as_dict : dict | list [dict ], target_class : type [YAMLRoot | BaseModel ]
141
+ ) -> BaseModel | YAMLRoot | list [BaseModel ] | list [YAMLRoot ] | None :
137
142
if data_as_dict :
138
143
if isinstance (data_as_dict , list ):
139
144
if issubclass (target_class , YAMLRoot ):
140
145
return [target_class (** as_dict (x )) for x in data_as_dict ]
141
- elif issubclass (target_class , BaseModel ):
146
+ if issubclass (target_class , BaseModel ):
142
147
return [target_class .model_validate (as_dict (x )) for x in data_as_dict ]
143
- else :
144
- raise ValueError (f"Cannot load list of { target_class } " )
145
- elif isinstance (data_as_dict , dict ):
148
+ msg = f"Cannot load list of { target_class } "
149
+ raise ValueError (msg )
150
+ if isinstance (data_as_dict , dict ):
146
151
if issubclass (target_class , BaseModel ):
147
152
return target_class .model_validate (data_as_dict )
148
153
return target_class (** data_as_dict )
149
154
150
155
if isinstance (data_as_dict , JsonObj ):
151
156
return [target_class (** as_dict (x )) for x in data_as_dict ]
152
- else :
153
- raise ValueError (f"Unexpected type { data_as_dict } " )
154
- else :
155
- return None
157
+
158
+ msg = f"Unexpected type { data_as_dict } "
159
+ # should really be a TypeError
160
+ raise ValueError (msg )
161
+ return None
156
162
157
163
def _read_source (
158
164
self ,
159
- source : Union [ str , dict , TextIO ] ,
165
+ source : str | dict | TextIO ,
160
166
* ,
161
- base_dir : Optional [ str ] = None ,
162
- metadata : Optional [ FileInfo ] = None ,
163
- accept_header : Optional [ str ] = "text/plain, application/yaml;q=0.9" ,
164
- ) -> Union [ dict , str ] :
167
+ base_dir : str | None = None ,
168
+ metadata : FileInfo | None = None ,
169
+ accept_header : str | None = "text/plain, application/yaml;q=0.9" ,
170
+ ) -> dict | str :
165
171
if metadata is None :
166
172
metadata = FileInfo ()
167
173
if base_dir and not metadata .base_path :
168
174
metadata .base_path = base_dir
169
175
170
- if not isinstance (source , dict ):
171
- # Try to get local version of schema, if one is known to exist
172
- try :
173
- if str (source ) in URI_TO_LOCAL :
174
- source = str (URI_TO_LOCAL [str (source )])
175
- except (TypeError , KeyError ) as e :
176
- # Fine, use original `source` value
177
- logger = getLogger ("linkml_runtime.loaders.Loader" )
178
- logger .debug (f"Error converting stringlike source to local linkml file: { source } , got: { e } " )
179
-
180
- data = hbread (source , metadata , base_dir , accept_header )
181
- else :
182
- data = source
183
-
184
- return data
176
+ if isinstance (source , dict ):
177
+ return source
178
+
179
+ # Try to get local version of schema, if one is known to exist
180
+ try :
181
+ if str (source ) in URI_TO_LOCAL :
182
+ source = str (URI_TO_LOCAL [str (source )])
183
+ except (TypeError , KeyError ) as e :
184
+ # Fine, use original `source` value
185
+ logger = getLogger ("linkml_runtime.loaders.Loader" )
186
+ logger .debug (f"Error converting stringlike source to local linkml file: { source } , got: { e } " )
187
+
188
+ return hbread (source , metadata , base_dir , accept_header )
0 commit comments