obographs 0.0.3__tar.gz → 0.0.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {obographs-0.0.3 → obographs-0.0.5}/PKG-INFO +6 -22
- {obographs-0.0.3 → obographs-0.0.5}/README.md +4 -10
- {obographs-0.0.3 → obographs-0.0.5}/pyproject.toml +51 -8
- obographs-0.0.5/src/obographs/__init__.py +73 -0
- {obographs-0.0.3 → obographs-0.0.5}/src/obographs/model.py +72 -29
- obographs-0.0.5/src/obographs/standardized.py +701 -0
- {obographs-0.0.3 → obographs-0.0.5}/src/obographs/version.py +1 -1
- obographs-0.0.3/src/obographs/__init__.py +0 -33
- obographs-0.0.3/src/obographs/standardized.py +0 -294
- {obographs-0.0.3 → obographs-0.0.5}/LICENSE +0 -0
- {obographs-0.0.3 → obographs-0.0.5}/src/obographs/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: obographs
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.5
|
|
4
4
|
Summary: A python data model for OBO Graphs
|
|
5
5
|
Keywords: snekpack,cookiecutter
|
|
6
6
|
Author: Charles Tapley Hoyt
|
|
@@ -23,15 +23,8 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
23
23
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
24
24
|
Classifier: Typing :: Typed
|
|
25
25
|
Requires-Dist: pydantic
|
|
26
|
-
Requires-Dist: curies>=0.10.
|
|
26
|
+
Requires-Dist: curies>=0.10.19
|
|
27
27
|
Requires-Dist: typing-extensions
|
|
28
|
-
Requires-Dist: sphinx>=8 ; extra == 'docs'
|
|
29
|
-
Requires-Dist: sphinx-rtd-theme>=3.0 ; extra == 'docs'
|
|
30
|
-
Requires-Dist: sphinx-automodapi ; extra == 'docs'
|
|
31
|
-
Requires-Dist: autodoc-pydantic ; extra == 'docs'
|
|
32
|
-
Requires-Dist: requests ; extra == 'network'
|
|
33
|
-
Requires-Dist: pytest ; extra == 'tests'
|
|
34
|
-
Requires-Dist: coverage[toml] ; extra == 'tests'
|
|
35
28
|
Maintainer: Charles Tapley Hoyt
|
|
36
29
|
Maintainer-email: Charles Tapley Hoyt <cthoyt@gmail.com>
|
|
37
30
|
Requires-Python: >=3.10
|
|
@@ -40,9 +33,6 @@ Project-URL: Documentation, https://obographs.readthedocs.io
|
|
|
40
33
|
Project-URL: Funding, https://github.com/sponsors/cthoyt
|
|
41
34
|
Project-URL: Homepage, https://github.com/cthoyt/obographs
|
|
42
35
|
Project-URL: Repository, https://github.com/cthoyt/obographs.git
|
|
43
|
-
Provides-Extra: docs
|
|
44
|
-
Provides-Extra: network
|
|
45
|
-
Provides-Extra: tests
|
|
46
36
|
Description-Content-Type: text/markdown
|
|
47
37
|
|
|
48
38
|
<!--
|
|
@@ -129,18 +119,15 @@ $ python3 -m pip install obographs
|
|
|
129
119
|
The most recent code and data can be installed directly from GitHub with uv:
|
|
130
120
|
|
|
131
121
|
```console
|
|
132
|
-
$ uv
|
|
122
|
+
$ uv pip install git+https://github.com/cthoyt/obographs.git
|
|
133
123
|
```
|
|
134
124
|
|
|
135
125
|
or with pip:
|
|
136
126
|
|
|
137
127
|
```console
|
|
138
|
-
$
|
|
128
|
+
$ python3 -m pip install git+https://github.com/cthoyt/obographs.git
|
|
139
129
|
```
|
|
140
130
|
|
|
141
|
-
Note that this requires setting `UV_PREVIEW` mode enabled until the uv build
|
|
142
|
-
backend becomes a stable feature.
|
|
143
|
-
|
|
144
131
|
## 👐 Contributing
|
|
145
132
|
|
|
146
133
|
Contributions, whether filing an issue, making a pull request, or forking, are
|
|
@@ -203,18 +190,15 @@ To install in development mode, use the following:
|
|
|
203
190
|
```console
|
|
204
191
|
$ git clone git+https://github.com/cthoyt/obographs.git
|
|
205
192
|
$ cd obographs
|
|
206
|
-
$ uv
|
|
193
|
+
$ uv pip install -e .
|
|
207
194
|
```
|
|
208
195
|
|
|
209
196
|
Alternatively, install using pip:
|
|
210
197
|
|
|
211
198
|
```console
|
|
212
|
-
$
|
|
199
|
+
$ python3 -m pip install -e .
|
|
213
200
|
```
|
|
214
201
|
|
|
215
|
-
Note that this requires setting `UV_PREVIEW` mode enabled until the uv build
|
|
216
|
-
backend becomes a stable feature.
|
|
217
|
-
|
|
218
202
|
### Updating Package Boilerplate
|
|
219
203
|
|
|
220
204
|
This project uses `cruft` to keep boilerplate (i.e., configuration, contribution
|
|
@@ -82,18 +82,15 @@ $ python3 -m pip install obographs
|
|
|
82
82
|
The most recent code and data can be installed directly from GitHub with uv:
|
|
83
83
|
|
|
84
84
|
```console
|
|
85
|
-
$ uv
|
|
85
|
+
$ uv pip install git+https://github.com/cthoyt/obographs.git
|
|
86
86
|
```
|
|
87
87
|
|
|
88
88
|
or with pip:
|
|
89
89
|
|
|
90
90
|
```console
|
|
91
|
-
$
|
|
91
|
+
$ python3 -m pip install git+https://github.com/cthoyt/obographs.git
|
|
92
92
|
```
|
|
93
93
|
|
|
94
|
-
Note that this requires setting `UV_PREVIEW` mode enabled until the uv build
|
|
95
|
-
backend becomes a stable feature.
|
|
96
|
-
|
|
97
94
|
## 👐 Contributing
|
|
98
95
|
|
|
99
96
|
Contributions, whether filing an issue, making a pull request, or forking, are
|
|
@@ -156,18 +153,15 @@ To install in development mode, use the following:
|
|
|
156
153
|
```console
|
|
157
154
|
$ git clone git+https://github.com/cthoyt/obographs.git
|
|
158
155
|
$ cd obographs
|
|
159
|
-
$ uv
|
|
156
|
+
$ uv pip install -e .
|
|
160
157
|
```
|
|
161
158
|
|
|
162
159
|
Alternatively, install using pip:
|
|
163
160
|
|
|
164
161
|
```console
|
|
165
|
-
$
|
|
162
|
+
$ python3 -m pip install -e .
|
|
166
163
|
```
|
|
167
164
|
|
|
168
|
-
Note that this requires setting `UV_PREVIEW` mode enabled until the uv build
|
|
169
|
-
backend becomes a stable feature.
|
|
170
|
-
|
|
171
165
|
### Updating Package Boilerplate
|
|
172
166
|
|
|
173
167
|
This project uses `cruft` to keep boilerplate (i.e., configuration, contribution
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
[build-system]
|
|
2
|
-
requires = ["
|
|
3
|
-
|
|
4
|
-
# with the 0.5.0 release. See also https://github.com/astral-sh/uv/issues/3957 for tracking.
|
|
5
|
-
build-backend = "uv"
|
|
2
|
+
requires = ["uv_build>=0.6.6,<0.7"]
|
|
3
|
+
build-backend = "uv_build"
|
|
6
4
|
|
|
7
5
|
[project]
|
|
8
6
|
name = "obographs"
|
|
9
|
-
version = "0.0.
|
|
7
|
+
version = "0.0.5"
|
|
10
8
|
description = "A python data model for OBO Graphs"
|
|
11
9
|
readme = "README.md"
|
|
12
10
|
authors = [
|
|
@@ -52,11 +50,12 @@ license-files = [
|
|
|
52
50
|
requires-python = ">=3.10"
|
|
53
51
|
dependencies = [
|
|
54
52
|
"pydantic",
|
|
55
|
-
"curies>=0.10.
|
|
53
|
+
"curies>=0.10.19",
|
|
56
54
|
"typing-extensions",
|
|
57
55
|
]
|
|
58
56
|
|
|
59
|
-
|
|
57
|
+
# see https://peps.python.org/pep-0735/ and https://docs.astral.sh/uv/concepts/dependencies/#dependency-groups
|
|
58
|
+
[dependency-groups]
|
|
60
59
|
tests = [
|
|
61
60
|
"pytest",
|
|
62
61
|
"coverage[toml]",
|
|
@@ -67,10 +66,51 @@ docs = [
|
|
|
67
66
|
"sphinx_automodapi",
|
|
68
67
|
"autodoc_pydantic",
|
|
69
68
|
]
|
|
69
|
+
lint = [
|
|
70
|
+
"ruff",
|
|
71
|
+
]
|
|
72
|
+
typing = [
|
|
73
|
+
{ include-group = "tests" },
|
|
74
|
+
"mypy",
|
|
75
|
+
"pydantic",
|
|
76
|
+
"types-requests",
|
|
77
|
+
]
|
|
78
|
+
docs-lint = [
|
|
79
|
+
{ include-group = "docs" },
|
|
80
|
+
"doc8",
|
|
81
|
+
]
|
|
82
|
+
format-docs = [
|
|
83
|
+
{ include-group = "docs" },
|
|
84
|
+
"docstrfmt",
|
|
85
|
+
]
|
|
86
|
+
doctests = [
|
|
87
|
+
"xdoctest",
|
|
88
|
+
"pygments",
|
|
89
|
+
]
|
|
90
|
+
pyroma = [
|
|
91
|
+
"pyroma",
|
|
92
|
+
"pygments",
|
|
93
|
+
]
|
|
94
|
+
# follow https://github.com/astral-sh/uv/issues/6298 for switching to a uv-based version bump workflow
|
|
95
|
+
bump = [
|
|
96
|
+
"bump-my-version",
|
|
97
|
+
]
|
|
98
|
+
build = [
|
|
99
|
+
"uv",
|
|
100
|
+
"uv-build",
|
|
101
|
+
]
|
|
102
|
+
release = [
|
|
103
|
+
{ include-group = "build" },
|
|
104
|
+
"uv",
|
|
105
|
+
"keyring",
|
|
106
|
+
]
|
|
70
107
|
network = [
|
|
71
108
|
"requests",
|
|
72
109
|
]
|
|
73
110
|
|
|
111
|
+
# see https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#dependencies-optional-dependencies
|
|
112
|
+
# [project.optional-dependencies]
|
|
113
|
+
|
|
74
114
|
# See https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#urls
|
|
75
115
|
# and also https://packaging.python.org/en/latest/specifications/well-known-project-urls/
|
|
76
116
|
[project.urls]
|
|
@@ -114,6 +154,9 @@ source = [
|
|
|
114
154
|
omit = [
|
|
115
155
|
"tests/*",
|
|
116
156
|
"docs/*",
|
|
157
|
+
"src/obographs/version.py",
|
|
158
|
+
"src/obographs/__main__.py",
|
|
159
|
+
"src/obographs/cli.py",
|
|
117
160
|
]
|
|
118
161
|
|
|
119
162
|
[tool.coverage.paths]
|
|
@@ -189,7 +232,7 @@ known-first-party = [
|
|
|
189
232
|
docstring-code-format = true
|
|
190
233
|
|
|
191
234
|
[tool.bumpversion]
|
|
192
|
-
current_version = "0.0.
|
|
235
|
+
current_version = "0.0.5"
|
|
193
236
|
parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)(?:-(?P<release>[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*))?(?:\\+(?P<build>[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*))?"
|
|
194
237
|
serialize = [
|
|
195
238
|
"{major}.{minor}.{patch}-{release}+{build}",
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"""A python data model for OBO Graphs."""
|
|
2
|
+
|
|
3
|
+
from .model import (
|
|
4
|
+
Definition,
|
|
5
|
+
DomainRangeAxiom,
|
|
6
|
+
Edge,
|
|
7
|
+
EquivalentNodeSet,
|
|
8
|
+
ExistentialRestrictionExpression,
|
|
9
|
+
Graph,
|
|
10
|
+
GraphDocument,
|
|
11
|
+
LogicalDefinition,
|
|
12
|
+
Meta,
|
|
13
|
+
Node,
|
|
14
|
+
NodeType,
|
|
15
|
+
Property,
|
|
16
|
+
PropertyChainAxiom,
|
|
17
|
+
PropertyType,
|
|
18
|
+
Synonym,
|
|
19
|
+
Xref,
|
|
20
|
+
read,
|
|
21
|
+
)
|
|
22
|
+
from .standardized import (
|
|
23
|
+
StandardizedBaseModel,
|
|
24
|
+
StandardizedDefinition,
|
|
25
|
+
StandardizedDomainRangeAxiom,
|
|
26
|
+
StandardizedEdge,
|
|
27
|
+
StandardizedEquivalentNodeSet,
|
|
28
|
+
StandardizedExistentialRestriction,
|
|
29
|
+
StandardizedGraph,
|
|
30
|
+
StandardizedGraphDocument,
|
|
31
|
+
StandardizedLogicalDefinition,
|
|
32
|
+
StandardizedMeta,
|
|
33
|
+
StandardizedNode,
|
|
34
|
+
StandardizedProperty,
|
|
35
|
+
StandardizedPropertyChainAxiom,
|
|
36
|
+
StandardizedSynonym,
|
|
37
|
+
StandardizedXref,
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
__all__ = [
|
|
41
|
+
"Definition",
|
|
42
|
+
"DomainRangeAxiom",
|
|
43
|
+
"Edge",
|
|
44
|
+
"EquivalentNodeSet",
|
|
45
|
+
"ExistentialRestrictionExpression",
|
|
46
|
+
"Graph",
|
|
47
|
+
"GraphDocument",
|
|
48
|
+
"LogicalDefinition",
|
|
49
|
+
"Meta",
|
|
50
|
+
"Node",
|
|
51
|
+
"NodeType",
|
|
52
|
+
"Property",
|
|
53
|
+
"PropertyChainAxiom",
|
|
54
|
+
"PropertyType",
|
|
55
|
+
"StandardizedBaseModel",
|
|
56
|
+
"StandardizedDefinition",
|
|
57
|
+
"StandardizedDomainRangeAxiom",
|
|
58
|
+
"StandardizedEdge",
|
|
59
|
+
"StandardizedEquivalentNodeSet",
|
|
60
|
+
"StandardizedExistentialRestriction",
|
|
61
|
+
"StandardizedGraph",
|
|
62
|
+
"StandardizedGraphDocument",
|
|
63
|
+
"StandardizedLogicalDefinition",
|
|
64
|
+
"StandardizedMeta",
|
|
65
|
+
"StandardizedNode",
|
|
66
|
+
"StandardizedProperty",
|
|
67
|
+
"StandardizedPropertyChainAxiom",
|
|
68
|
+
"StandardizedSynonym",
|
|
69
|
+
"StandardizedXref",
|
|
70
|
+
"Synonym",
|
|
71
|
+
"Xref",
|
|
72
|
+
"read",
|
|
73
|
+
]
|
|
@@ -9,27 +9,35 @@
|
|
|
9
9
|
|
|
10
10
|
from __future__ import annotations
|
|
11
11
|
|
|
12
|
+
import gzip
|
|
12
13
|
import json
|
|
13
14
|
import logging
|
|
14
15
|
from collections import defaultdict
|
|
15
16
|
from pathlib import Path
|
|
16
|
-
from typing import TYPE_CHECKING,
|
|
17
|
+
from typing import TYPE_CHECKING, Literal, TypeAlias, overload
|
|
17
18
|
|
|
19
|
+
import curies
|
|
20
|
+
from curies.vocabulary import SynonymScopeOIO
|
|
18
21
|
from pydantic import BaseModel, Field
|
|
19
22
|
|
|
20
23
|
if TYPE_CHECKING:
|
|
21
|
-
import curies
|
|
22
|
-
|
|
23
24
|
from .standardized import StandardizedGraph
|
|
24
25
|
|
|
25
26
|
__all__ = [
|
|
26
27
|
"Definition",
|
|
28
|
+
"DomainRangeAxiom",
|
|
27
29
|
"Edge",
|
|
30
|
+
"EquivalentNodeSet",
|
|
31
|
+
"ExistentialRestrictionExpression",
|
|
28
32
|
"Graph",
|
|
29
33
|
"GraphDocument",
|
|
34
|
+
"LogicalDefinition",
|
|
30
35
|
"Meta",
|
|
31
36
|
"Node",
|
|
37
|
+
"NodeType",
|
|
32
38
|
"Property",
|
|
39
|
+
"PropertyChainAxiom",
|
|
40
|
+
"PropertyType",
|
|
33
41
|
"Synonym",
|
|
34
42
|
"Xref",
|
|
35
43
|
"read",
|
|
@@ -40,24 +48,12 @@ logger = logging.getLogger(__name__)
|
|
|
40
48
|
OBO_URI_PREFIX = "http://purl.obolibrary.org/obo/"
|
|
41
49
|
OBO_URI_PREFIX_LEN = len(OBO_URI_PREFIX)
|
|
42
50
|
|
|
43
|
-
SynonymPredicate: TypeAlias = Literal[
|
|
44
|
-
"hasExactSynonym",
|
|
45
|
-
"hasBroadSynonym",
|
|
46
|
-
"hasNarrowSynonym",
|
|
47
|
-
"hasRelatedSynonym",
|
|
48
|
-
]
|
|
49
51
|
NodeType: TypeAlias = Literal["CLASS", "PROPERTY", "INDIVIDUAL"]
|
|
50
52
|
|
|
51
|
-
|
|
53
|
+
#: When node type is ``PROPERTY``, this is extra information
|
|
54
|
+
PropertyType: TypeAlias = Literal["ANNOTATION", "OBJECT", "DATA"]
|
|
52
55
|
|
|
53
|
-
|
|
54
|
-
#: identifiers. See https://owlcollab.github.io/oboformat/doc/GO.format.obo-1_4.html
|
|
55
|
-
OBO_SYNONYM_TO_OIO: dict[str, SynonymPredicate] = {
|
|
56
|
-
"EXACT": "hasExactSynonym",
|
|
57
|
-
"BROAD": "hasBroadSynonym",
|
|
58
|
-
"NARROW": "hasNarrowSynonym",
|
|
59
|
-
"RELATED": "hasRelatedSynonym",
|
|
60
|
-
}
|
|
56
|
+
TimeoutHint = int | float | None
|
|
61
57
|
|
|
62
58
|
|
|
63
59
|
class Property(BaseModel):
|
|
@@ -91,7 +87,7 @@ class Synonym(BaseModel):
|
|
|
91
87
|
"""Represents a synonym inside an object meta."""
|
|
92
88
|
|
|
93
89
|
val: str | None = Field(default=None)
|
|
94
|
-
pred:
|
|
90
|
+
pred: SynonymScopeOIO = Field(default="hasExactSynonym")
|
|
95
91
|
synonymType: str | None = Field(None, examples=["OMO:0003000"]) # noqa:N815
|
|
96
92
|
xrefs: list[str] = Field(
|
|
97
93
|
default_factory=list,
|
|
@@ -129,6 +125,51 @@ class Node(BaseModel):
|
|
|
129
125
|
lbl: str | None = Field(None, description="The name of the node")
|
|
130
126
|
meta: Meta | None = None
|
|
131
127
|
type: NodeType | None = Field(None, description="Type of node")
|
|
128
|
+
propertyType: PropertyType | None = Field( # noqa:N815
|
|
129
|
+
None, description="Type of property, if the node type is a property"
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
class DomainRangeAxiom(BaseModel):
|
|
134
|
+
"""Represents a domain/range axiom."""
|
|
135
|
+
|
|
136
|
+
predicateId: str # noqa:N815
|
|
137
|
+
domainClassIds: list[str] | None = None # noqa:N815
|
|
138
|
+
rangeClassIds: list[str] | None = None # noqa:N815
|
|
139
|
+
allValuesFromEdges: list[Edge] | None = None # noqa:N815
|
|
140
|
+
meta: Meta | None = None
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
class PropertyChainAxiom(BaseModel):
|
|
144
|
+
"""Represents a property chain axiom."""
|
|
145
|
+
|
|
146
|
+
predicateId: str # noqa:N815
|
|
147
|
+
chainPredicateIds: list[str] # noqa:N815
|
|
148
|
+
meta: Meta | None = None
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
class ExistentialRestrictionExpression(BaseModel):
|
|
152
|
+
"""Represents an existential restriction."""
|
|
153
|
+
|
|
154
|
+
propertyId: str # noqa:N815
|
|
155
|
+
fillerId: str # noqa:N815
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
class LogicalDefinition(BaseModel):
|
|
159
|
+
"""Represents a logical definition chain axiom."""
|
|
160
|
+
|
|
161
|
+
definedClassId: str # noqa:N815
|
|
162
|
+
genusIds: list[str] | None = None # noqa:N815
|
|
163
|
+
restrictions: list[ExistentialRestrictionExpression] | None = None
|
|
164
|
+
meta: Meta | None = None
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
class EquivalentNodeSet(BaseModel):
|
|
168
|
+
"""Represents a set of equivalent nodes."""
|
|
169
|
+
|
|
170
|
+
representativeNodeId: str # noqa:N815
|
|
171
|
+
nodeIds: list[str] # noqa:N815
|
|
172
|
+
meta: Meta | None = None
|
|
132
173
|
|
|
133
174
|
|
|
134
175
|
class Graph(BaseModel):
|
|
@@ -138,10 +179,10 @@ class Graph(BaseModel):
|
|
|
138
179
|
meta: Meta | None = None
|
|
139
180
|
nodes: list[Node] = Field(default_factory=list)
|
|
140
181
|
edges: list[Edge] = Field(default_factory=list)
|
|
141
|
-
equivalentNodesSets: list[
|
|
142
|
-
logicalDefinitionAxioms: list[
|
|
143
|
-
domainRangeAxioms: list[
|
|
144
|
-
propertyChainAxioms: list[
|
|
182
|
+
equivalentNodesSets: list[EquivalentNodeSet] = Field(default_factory=list) # noqa:N815
|
|
183
|
+
logicalDefinitionAxioms: list[LogicalDefinition] = Field(default_factory=list) # noqa:N815
|
|
184
|
+
domainRangeAxioms: list[DomainRangeAxiom] = Field(default_factory=list) # noqa:N815
|
|
185
|
+
propertyChainAxioms: list[PropertyChainAxiom] = Field(default_factory=list) # noqa:N815
|
|
145
186
|
|
|
146
187
|
def standardize(self, converter: curies.Converter) -> StandardizedGraph:
|
|
147
188
|
"""Standardize the graph."""
|
|
@@ -210,12 +251,14 @@ def read(
|
|
|
210
251
|
|
|
211
252
|
elif isinstance(source, str | Path):
|
|
212
253
|
path = Path(source).expanduser().resolve()
|
|
213
|
-
if path.is_file():
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
254
|
+
if not path.is_file():
|
|
255
|
+
raise FileNotFoundError
|
|
256
|
+
if path.suffix.endswith(".gz"):
|
|
257
|
+
with gzip.open(path, mode="rt") as file:
|
|
258
|
+
graph_document = GraphDocument.model_validate(json.load(file))
|
|
259
|
+
else:
|
|
260
|
+
with path.open() as file:
|
|
261
|
+
graph_document = GraphDocument.model_validate(json.load(file))
|
|
219
262
|
else:
|
|
220
263
|
raise TypeError(f"Unhandled source: {source}")
|
|
221
264
|
|