pyobo 0.10.12__py3-none-any.whl → 0.11.1__py3-none-any.whl

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.
Files changed (153) hide show
  1. pyobo/__init__.py +0 -2
  2. pyobo/__main__.py +0 -2
  3. pyobo/api/__init__.py +0 -2
  4. pyobo/api/alts.py +6 -7
  5. pyobo/api/hierarchy.py +14 -15
  6. pyobo/api/metadata.py +3 -4
  7. pyobo/api/names.py +31 -32
  8. pyobo/api/properties.py +6 -7
  9. pyobo/api/relations.py +12 -11
  10. pyobo/api/species.py +5 -6
  11. pyobo/api/typedefs.py +1 -3
  12. pyobo/api/utils.py +61 -5
  13. pyobo/api/xrefs.py +4 -5
  14. pyobo/aws.py +3 -5
  15. pyobo/cli/__init__.py +0 -2
  16. pyobo/cli/aws.py +0 -2
  17. pyobo/cli/cli.py +0 -4
  18. pyobo/cli/database.py +1 -3
  19. pyobo/cli/lookup.py +0 -2
  20. pyobo/cli/utils.py +0 -2
  21. pyobo/constants.py +1 -33
  22. pyobo/getters.py +19 -26
  23. pyobo/gilda_utils.py +19 -17
  24. pyobo/identifier_utils.py +10 -10
  25. pyobo/mocks.py +5 -6
  26. pyobo/normalizer.py +24 -24
  27. pyobo/obographs.py +8 -5
  28. pyobo/plugins.py +3 -4
  29. pyobo/py.typed +0 -0
  30. pyobo/reader.py +19 -21
  31. pyobo/registries/__init__.py +0 -2
  32. pyobo/registries/metaregistry.py +6 -8
  33. pyobo/resource_utils.py +1 -3
  34. pyobo/resources/__init__.py +0 -2
  35. pyobo/resources/ncbitaxon.py +2 -3
  36. pyobo/resources/ro.py +2 -4
  37. pyobo/resources/so.py +55 -0
  38. pyobo/resources/so.tsv +2604 -0
  39. pyobo/sources/README.md +15 -0
  40. pyobo/sources/__init__.py +0 -2
  41. pyobo/sources/agrovoc.py +3 -3
  42. pyobo/sources/antibodyregistry.py +2 -3
  43. pyobo/sources/biogrid.py +4 -4
  44. pyobo/sources/ccle.py +3 -4
  45. pyobo/sources/cgnc.py +1 -3
  46. pyobo/sources/chebi.py +2 -4
  47. pyobo/sources/chembl.py +1 -3
  48. pyobo/sources/civic_gene.py +2 -3
  49. pyobo/sources/complexportal.py +57 -20
  50. pyobo/sources/conso.py +2 -4
  51. pyobo/sources/cpt.py +1 -3
  52. pyobo/sources/credit.py +1 -1
  53. pyobo/sources/cvx.py +1 -3
  54. pyobo/sources/depmap.py +3 -4
  55. pyobo/sources/dictybase_gene.py +15 -12
  56. pyobo/sources/drugbank.py +6 -7
  57. pyobo/sources/drugbank_salt.py +3 -4
  58. pyobo/sources/drugcentral.py +9 -8
  59. pyobo/sources/expasy.py +33 -16
  60. pyobo/sources/famplex.py +3 -5
  61. pyobo/sources/flybase.py +5 -6
  62. pyobo/sources/geonames.py +1 -1
  63. pyobo/sources/gmt_utils.py +5 -6
  64. pyobo/sources/go.py +4 -6
  65. pyobo/sources/gwascentral_phenotype.py +1 -3
  66. pyobo/sources/gwascentral_study.py +2 -3
  67. pyobo/sources/hgnc.py +30 -26
  68. pyobo/sources/hgncgenefamily.py +9 -11
  69. pyobo/sources/icd10.py +3 -4
  70. pyobo/sources/icd11.py +3 -4
  71. pyobo/sources/icd_utils.py +6 -7
  72. pyobo/sources/interpro.py +3 -5
  73. pyobo/sources/itis.py +1 -3
  74. pyobo/sources/kegg/__init__.py +0 -2
  75. pyobo/sources/kegg/api.py +3 -4
  76. pyobo/sources/kegg/genes.py +3 -4
  77. pyobo/sources/kegg/genome.py +19 -9
  78. pyobo/sources/kegg/pathway.py +5 -6
  79. pyobo/sources/mesh.py +19 -21
  80. pyobo/sources/mgi.py +1 -3
  81. pyobo/sources/mirbase.py +13 -9
  82. pyobo/sources/mirbase_constants.py +0 -2
  83. pyobo/sources/mirbase_family.py +1 -3
  84. pyobo/sources/mirbase_mature.py +1 -3
  85. pyobo/sources/msigdb.py +4 -5
  86. pyobo/sources/ncbigene.py +3 -5
  87. pyobo/sources/npass.py +2 -4
  88. pyobo/sources/omim_ps.py +1 -3
  89. pyobo/sources/pathbank.py +35 -28
  90. pyobo/sources/pfam.py +1 -3
  91. pyobo/sources/pfam_clan.py +1 -3
  92. pyobo/sources/pid.py +3 -5
  93. pyobo/sources/pombase.py +7 -6
  94. pyobo/sources/pubchem.py +2 -3
  95. pyobo/sources/reactome.py +30 -11
  96. pyobo/sources/rgd.py +3 -4
  97. pyobo/sources/rhea.py +7 -8
  98. pyobo/sources/ror.py +3 -2
  99. pyobo/sources/selventa/__init__.py +0 -2
  100. pyobo/sources/selventa/schem.py +1 -3
  101. pyobo/sources/selventa/scomp.py +1 -3
  102. pyobo/sources/selventa/sdis.py +1 -3
  103. pyobo/sources/selventa/sfam.py +1 -3
  104. pyobo/sources/sgd.py +1 -3
  105. pyobo/sources/slm.py +29 -17
  106. pyobo/sources/umls/__init__.py +0 -2
  107. pyobo/sources/umls/__main__.py +0 -2
  108. pyobo/sources/umls/get_synonym_types.py +1 -1
  109. pyobo/sources/umls/umls.py +2 -4
  110. pyobo/sources/uniprot/__init__.py +0 -2
  111. pyobo/sources/uniprot/uniprot.py +11 -10
  112. pyobo/sources/uniprot/uniprot_ptm.py +6 -5
  113. pyobo/sources/utils.py +3 -5
  114. pyobo/sources/wikipathways.py +1 -3
  115. pyobo/sources/zfin.py +20 -9
  116. pyobo/ssg/__init__.py +3 -2
  117. pyobo/struct/__init__.py +0 -2
  118. pyobo/struct/reference.py +22 -23
  119. pyobo/struct/struct.py +132 -116
  120. pyobo/struct/typedef.py +14 -10
  121. pyobo/struct/utils.py +0 -2
  122. pyobo/utils/__init__.py +0 -2
  123. pyobo/utils/cache.py +14 -6
  124. pyobo/utils/io.py +9 -10
  125. pyobo/utils/iter.py +5 -6
  126. pyobo/utils/misc.py +1 -3
  127. pyobo/utils/ndex_utils.py +6 -7
  128. pyobo/utils/path.py +4 -5
  129. pyobo/version.py +3 -5
  130. pyobo/xrefdb/__init__.py +0 -2
  131. pyobo/xrefdb/canonicalizer.py +27 -18
  132. pyobo/xrefdb/priority.py +0 -2
  133. pyobo/xrefdb/sources/__init__.py +3 -4
  134. pyobo/xrefdb/sources/biomappings.py +0 -2
  135. pyobo/xrefdb/sources/cbms2019.py +0 -2
  136. pyobo/xrefdb/sources/chembl.py +0 -2
  137. pyobo/xrefdb/sources/compath.py +1 -3
  138. pyobo/xrefdb/sources/famplex.py +3 -5
  139. pyobo/xrefdb/sources/gilda.py +0 -2
  140. pyobo/xrefdb/sources/intact.py +5 -5
  141. pyobo/xrefdb/sources/ncit.py +1 -3
  142. pyobo/xrefdb/sources/pubchem.py +2 -5
  143. pyobo/xrefdb/sources/wikidata.py +2 -4
  144. pyobo/xrefdb/xrefs_pipeline.py +15 -16
  145. {pyobo-0.10.12.dist-info → pyobo-0.11.1.dist-info}/LICENSE +1 -1
  146. pyobo-0.11.1.dist-info/METADATA +711 -0
  147. pyobo-0.11.1.dist-info/RECORD +173 -0
  148. {pyobo-0.10.12.dist-info → pyobo-0.11.1.dist-info}/WHEEL +1 -1
  149. pyobo-0.11.1.dist-info/entry_points.txt +2 -0
  150. pyobo-0.10.12.dist-info/METADATA +0 -499
  151. pyobo-0.10.12.dist-info/RECORD +0 -169
  152. pyobo-0.10.12.dist-info/entry_points.txt +0 -15
  153. {pyobo-0.10.12.dist-info → pyobo-0.11.1.dist-info}/top_level.txt +0 -0
pyobo/__init__.py CHANGED
@@ -1,5 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  """A python package for handling and generating OBO."""
4
2
 
5
3
  from .api import ( # noqa: F401
pyobo/__main__.py CHANGED
@@ -1,5 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  """CLI for PyOBO."""
4
2
 
5
3
  from .cli import main
pyobo/api/__init__.py CHANGED
@@ -1,5 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  """High-level API for accessing content."""
4
2
 
5
3
  from .alts import ( # noqa: F401
pyobo/api/alts.py CHANGED
@@ -1,10 +1,9 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  """High-level API for alternative identifiers."""
4
2
 
5
3
  import logging
4
+ from collections.abc import Mapping
6
5
  from functools import lru_cache
7
- from typing import List, Mapping, Optional
6
+ from typing import Optional
8
7
 
9
8
  from .utils import get_version
10
9
  from ..getters import get_ontology
@@ -26,11 +25,11 @@ NO_ALTS = {
26
25
  }
27
26
 
28
27
 
29
- @lru_cache()
28
+ @lru_cache
30
29
  @wrap_norm_prefix
31
30
  def get_id_to_alts(
32
31
  prefix: str, *, force: bool = False, version: Optional[str] = None
33
- ) -> Mapping[str, List[str]]:
32
+ ) -> Mapping[str, list[str]]:
34
33
  """Get alternate identifiers."""
35
34
  if prefix in NO_ALTS:
36
35
  return {}
@@ -41,7 +40,7 @@ def get_id_to_alts(
41
40
  header = [f"{prefix}_id", "alt_id"]
42
41
 
43
42
  @cached_multidict(path=path, header=header, force=force)
44
- def _get_mapping() -> Mapping[str, List[str]]:
43
+ def _get_mapping() -> Mapping[str, list[str]]:
45
44
  if force:
46
45
  logger.info(f"[{prefix}] forcing reload for alts")
47
46
  else:
@@ -52,7 +51,7 @@ def get_id_to_alts(
52
51
  return _get_mapping()
53
52
 
54
53
 
55
- @lru_cache()
54
+ @lru_cache
56
55
  @wrap_norm_prefix
57
56
  def get_alts_to_id(
58
57
  prefix: str, *, force: bool = False, version: Optional[str] = None
pyobo/api/hierarchy.py CHANGED
@@ -1,10 +1,9 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  """High-level API for hierarchies."""
4
2
 
5
3
  import logging
4
+ from collections.abc import Iterable
6
5
  from functools import lru_cache
7
- from typing import Iterable, Optional, Set, Tuple
6
+ from typing import Optional
8
7
 
9
8
  import networkx as nx
10
9
 
@@ -70,13 +69,13 @@ def get_hierarchy(
70
69
  )
71
70
 
72
71
 
73
- @lru_cache()
72
+ @lru_cache
74
73
  @wrap_norm_prefix
75
74
  def _get_hierarchy_helper(
76
75
  prefix: str,
77
76
  *,
78
- extra_relations: Tuple[TypeDef, ...],
79
- properties: Tuple[str, ...],
77
+ extra_relations: tuple[TypeDef, ...],
78
+ properties: tuple[str, ...],
80
79
  include_part_of: bool,
81
80
  include_has_member: bool,
82
81
  use_tqdm: bool,
@@ -161,13 +160,13 @@ def is_descendent(
161
160
 
162
161
  Check that go:0070246 ! natural killer cell apoptotic process is a
163
162
  descendant of go:0006915 ! apoptotic process::
164
- >>> assert is_descendent('go', '0070246', 'go', '0006915')
163
+ >>> assert is_descendent("go", "0070246", "go", "0006915")
165
164
  """
166
165
  descendants = get_descendants(ancestor_prefix, ancestor_identifier, version=version)
167
166
  return descendants is not None and f"{prefix}:{identifier}" in descendants
168
167
 
169
168
 
170
- @lru_cache()
169
+ @lru_cache
171
170
  def get_descendants(
172
171
  prefix: str,
173
172
  identifier: Optional[str] = None,
@@ -176,7 +175,7 @@ def get_descendants(
176
175
  use_tqdm: bool = False,
177
176
  force: bool = False,
178
177
  **kwargs,
179
- ) -> Optional[Set[str]]:
178
+ ) -> Optional[set[str]]:
180
179
  """Get all the descendants (children) of the term as CURIEs."""
181
180
  curie, prefix, identifier = _pic(prefix, identifier)
182
181
  hierarchy = get_hierarchy(
@@ -192,7 +191,7 @@ def get_descendants(
192
191
  return nx.ancestors(hierarchy, curie) # note this is backwards
193
192
 
194
193
 
195
- def _pic(prefix, identifier=None) -> Tuple[str, str, str]:
194
+ def _pic(prefix, identifier=None) -> tuple[str, str, str]:
196
195
  if identifier is None:
197
196
  curie = prefix
198
197
  prefix, identifier = prefix.split(":")
@@ -201,7 +200,7 @@ def _pic(prefix, identifier=None) -> Tuple[str, str, str]:
201
200
  return curie, prefix, identifier
202
201
 
203
202
 
204
- @lru_cache()
203
+ @lru_cache
205
204
  def get_children(
206
205
  prefix: str,
207
206
  identifier: Optional[str] = None,
@@ -210,7 +209,7 @@ def get_children(
210
209
  use_tqdm: bool = False,
211
210
  force: bool = False,
212
211
  **kwargs,
213
- ) -> Optional[Set[str]]:
212
+ ) -> Optional[set[str]]:
214
213
  """Get all the descendants (children) of the term as CURIEs."""
215
214
  curie, prefix, identifier = _pic(prefix, identifier)
216
215
  hierarchy = get_hierarchy(
@@ -232,13 +231,13 @@ def has_ancestor(
232
231
  """Check that the first identifier has the second as an ancestor.
233
232
 
234
233
  Check that go:0008219 ! cell death is an ancestor of go:0006915 ! apoptotic process::
235
- >>> assert has_ancestor('go', '0006915', 'go', '0008219')
234
+ >>> assert has_ancestor("go", "0006915", "go", "0008219")
236
235
  """
237
236
  ancestors = get_ancestors(prefix, identifier, version=version)
238
237
  return ancestors is not None and f"{ancestor_prefix}:{ancestor_identifier}" in ancestors
239
238
 
240
239
 
241
- @lru_cache()
240
+ @lru_cache
242
241
  def get_ancestors(
243
242
  prefix: str,
244
243
  identifier: Optional[str] = None,
@@ -247,7 +246,7 @@ def get_ancestors(
247
246
  use_tqdm: bool = False,
248
247
  force: bool = False,
249
248
  **kwargs,
250
- ) -> Optional[Set[str]]:
249
+ ) -> Optional[set[str]]:
251
250
  """Get all the ancestors (parents) of the term as CURIEs."""
252
251
  curie, prefix, identifier = _pic(prefix, identifier)
253
252
  hierarchy = get_hierarchy(
pyobo/api/metadata.py CHANGED
@@ -1,10 +1,9 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  """High-level API for metadata."""
4
2
 
5
3
  import logging
4
+ from collections.abc import Mapping
6
5
  from functools import lru_cache
7
- from typing import Mapping, Optional
6
+ from typing import Optional
8
7
 
9
8
  from .utils import get_version
10
9
  from ..getters import get_ontology
@@ -19,7 +18,7 @@ __all__ = [
19
18
  logger = logging.getLogger(__name__)
20
19
 
21
20
 
22
- @lru_cache()
21
+ @lru_cache
23
22
  @wrap_norm_prefix
24
23
  def get_metadata(
25
24
  prefix: str, *, force: bool = False, version: Optional[str] = None
pyobo/api/names.py CHANGED
@@ -1,19 +1,18 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  """High-level API for nomenclature."""
4
2
 
5
3
  from __future__ import annotations
6
4
 
7
5
  import logging
8
6
  import subprocess
7
+ from collections.abc import Mapping
9
8
  from functools import lru_cache
10
- from typing import Callable, List, Mapping, Optional, Set, TypeVar
9
+ from typing import Callable, TypeVar
11
10
 
12
11
  from curies import Reference, ReferenceTuple
13
12
 
14
13
  from .alts import get_primary_identifier
15
14
  from .utils import get_version
16
- from ..getters import NoBuild, get_ontology
15
+ from ..getters import NoBuildError, get_ontology
17
16
  from ..identifier_utils import normalize_curie, wrap_norm_prefix
18
17
  from ..utils.cache import cached_collection, cached_mapping, cached_multidict
19
18
  from ..utils.path import prefix_cache_join
@@ -34,7 +33,7 @@ __all__ = [
34
33
  logger = logging.getLogger(__name__)
35
34
 
36
35
 
37
- def get_name_by_curie(curie: str, *, version: Optional[str] = None) -> Optional[str]:
36
+ def get_name_by_curie(curie: str, *, version: str | None = None) -> str | None:
38
37
  """Get the name for a CURIE, if possible."""
39
38
  if version is None:
40
39
  version = get_version(curie.split(":")[0])
@@ -46,8 +45,8 @@ def get_name_by_curie(curie: str, *, version: Optional[str] = None) -> Optional[
46
45
 
47
46
  X = TypeVar("X")
48
47
 
49
- NO_BUILD_PREFIXES: Set[str] = set()
50
- NO_BUILD_LOGGED: Set = set()
48
+ NO_BUILD_PREFIXES: set[str] = set()
49
+ NO_BUILD_LOGGED: set = set()
51
50
 
52
51
 
53
52
  def _help_get(
@@ -56,12 +55,12 @@ def _help_get(
56
55
  identifier: str,
57
56
  force: bool = False,
58
57
  strict: bool = False,
59
- version: Optional[str] = None,
60
- ) -> Optional[X]:
58
+ version: str | None = None,
59
+ ) -> X | None:
61
60
  """Get the result for an entity based on a mapping maker function ``f``."""
62
61
  try:
63
62
  mapping = f(prefix, force=force, strict=strict, version=version) # type:ignore
64
- except NoBuild:
63
+ except NoBuildError:
65
64
  if prefix not in NO_BUILD_PREFIXES:
66
65
  logger.warning("[%s] unable to look up results with %s", prefix, f)
67
66
  NO_BUILD_PREFIXES.add(prefix)
@@ -85,22 +84,22 @@ def _help_get(
85
84
  @wrap_norm_prefix
86
85
  def get_name(
87
86
  prefix: str | Reference | ReferenceTuple,
88
- identifier: Optional[str] = None,
87
+ identifier: str | None = None,
89
88
  /,
90
89
  *,
91
- version: Optional[str] = None,
92
- ) -> Optional[str]:
90
+ version: str | None = None,
91
+ ) -> str | None:
93
92
  """Get the name for an entity."""
94
93
  if isinstance(prefix, (ReferenceTuple, Reference)):
95
94
  prefix, identifier = prefix.prefix, prefix.identifier
96
95
  return _help_get(get_id_name_mapping, prefix, identifier, version=version) # type:ignore
97
96
 
98
97
 
99
- @lru_cache()
98
+ @lru_cache
100
99
  @wrap_norm_prefix
101
100
  def get_ids(
102
- prefix: str, *, force: bool = False, strict: bool = False, version: Optional[str] = None
103
- ) -> Set[str]:
101
+ prefix: str, *, force: bool = False, strict: bool = False, version: str | None = None
102
+ ) -> set[str]:
104
103
  """Get the set of identifiers for this prefix."""
105
104
  if prefix == "ncbigene":
106
105
  from ..sources.ncbigene import get_ncbigene_ids
@@ -115,7 +114,7 @@ def get_ids(
115
114
  path = prefix_cache_join(prefix, name="ids.tsv", version=version)
116
115
 
117
116
  @cached_collection(path=path, force=force)
118
- def _get_ids() -> Set[str]:
117
+ def _get_ids() -> set[str]:
119
118
  if force:
120
119
  logger.info("[%s v%s] forcing reload for names", prefix, version)
121
120
  else:
@@ -128,10 +127,10 @@ def get_ids(
128
127
  return set(_get_ids())
129
128
 
130
129
 
131
- @lru_cache()
130
+ @lru_cache
132
131
  @wrap_norm_prefix
133
132
  def get_id_name_mapping(
134
- prefix: str, *, force: bool = False, strict: bool = False, version: Optional[str] = None
133
+ prefix: str, *, force: bool = False, strict: bool = False, version: str | None = None
135
134
  ) -> Mapping[str, str]:
136
135
  """Get an identifier to name mapping for the OBO file."""
137
136
  if prefix == "ncbigene":
@@ -157,7 +156,7 @@ def get_id_name_mapping(
157
156
 
158
157
  try:
159
158
  return _get_id_name_mapping()
160
- except NoBuild:
159
+ except NoBuildError:
161
160
  logger.debug("[%s] no build", prefix)
162
161
  return {}
163
162
  except (Exception, subprocess.CalledProcessError) as e:
@@ -165,10 +164,10 @@ def get_id_name_mapping(
165
164
  return {}
166
165
 
167
166
 
168
- @lru_cache()
167
+ @lru_cache
169
168
  @wrap_norm_prefix
170
169
  def get_name_id_mapping(
171
- prefix: str, *, force: bool = False, version: Optional[str] = None
170
+ prefix: str, *, force: bool = False, version: str | None = None
172
171
  ) -> Mapping[str, str]:
173
172
  """Get a name to identifier mapping for the OBO file."""
174
173
  id_name = get_id_name_mapping(prefix=prefix, force=force, version=version)
@@ -177,8 +176,8 @@ def get_name_id_mapping(
177
176
 
178
177
  @wrap_norm_prefix
179
178
  def get_definition(
180
- prefix: str, identifier: str | None = None, *, version: Optional[str] = None
181
- ) -> Optional[str]:
179
+ prefix: str, identifier: str | None = None, *, version: str | None = None
180
+ ) -> str | None:
182
181
  """Get the definition for an entity."""
183
182
  if identifier is None:
184
183
  prefix, _, identifier = prefix.rpartition(":")
@@ -190,7 +189,7 @@ def get_id_definition_mapping(
190
189
  *,
191
190
  force: bool = False,
192
191
  strict: bool = False,
193
- version: Optional[str] = None,
192
+ version: str | None = None,
194
193
  ) -> Mapping[str, str]:
195
194
  """Get a mapping of descriptions."""
196
195
  if version is None:
@@ -213,15 +212,15 @@ def get_obsolete(
213
212
  *,
214
213
  force: bool = False,
215
214
  strict: bool = False,
216
- version: Optional[str] = None,
217
- ) -> Set[str]:
215
+ version: str | None = None,
216
+ ) -> set[str]:
218
217
  """Get the set of obsolete local unique identifiers."""
219
218
  if version is None:
220
219
  version = get_version(prefix)
221
220
  path = prefix_cache_join(prefix, name="obsolete.tsv", version=version)
222
221
 
223
222
  @cached_collection(path=path, force=force)
224
- def _get_obsolete() -> Set[str]:
223
+ def _get_obsolete() -> set[str]:
225
224
  ontology = get_ontology(prefix, force=force, strict=strict, version=version)
226
225
  return ontology.get_obsolete()
227
226
 
@@ -229,7 +228,7 @@ def get_obsolete(
229
228
 
230
229
 
231
230
  @wrap_norm_prefix
232
- def get_synonyms(prefix: str, identifier: str) -> Optional[List[str]]:
231
+ def get_synonyms(prefix: str, identifier: str) -> list[str] | None:
233
232
  """Get the synonyms for an entity."""
234
233
  return _help_get(get_id_synonyms_mapping, prefix, identifier)
235
234
 
@@ -240,15 +239,15 @@ def get_id_synonyms_mapping(
240
239
  *,
241
240
  force: bool = False,
242
241
  strict: bool = False,
243
- version: Optional[str] = None,
244
- ) -> Mapping[str, List[str]]:
242
+ version: str | None = None,
243
+ ) -> Mapping[str, list[str]]:
245
244
  """Get the OBO file and output a synonym dictionary."""
246
245
  if version is None:
247
246
  version = get_version(prefix)
248
247
  path = prefix_cache_join(prefix, name="synonyms.tsv", version=version)
249
248
 
250
249
  @cached_multidict(path=path, header=[f"{prefix}_id", "synonym"], force=force)
251
- def _get_multidict() -> Mapping[str, List[str]]:
250
+ def _get_multidict() -> Mapping[str, list[str]]:
252
251
  logger.info("[%s v%s] no cached synonyms found. getting from OBO loader", prefix, version)
253
252
  ontology = get_ontology(prefix, force=force, strict=strict, version=version)
254
253
  return ontology.get_id_synonyms_mapping()
pyobo/api/properties.py CHANGED
@@ -1,10 +1,9 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  """High-level API for properties."""
4
2
 
5
3
  import logging
6
4
  import os
7
- from typing import List, Mapping, Optional
5
+ from collections.abc import Mapping
6
+ from typing import Optional
8
7
 
9
8
  import pandas as pd
10
9
 
@@ -105,7 +104,7 @@ def get_filtered_properties_multimapping(
105
104
  use_tqdm: bool = False,
106
105
  force: bool = False,
107
106
  version: Optional[str] = None,
108
- ) -> Mapping[str, List[str]]:
107
+ ) -> Mapping[str, list[str]]:
109
108
  """Extract multiple properties for each term as a dictionary.
110
109
 
111
110
  :param prefix: the resource to load
@@ -120,7 +119,7 @@ def get_filtered_properties_multimapping(
120
119
  all_properties_path = prefix_cache_join(prefix, name="properties.tsv", version=version)
121
120
 
122
121
  @cached_multidict(path=path, header=[f"{prefix}_id", prop], force=force)
123
- def _mapping_getter() -> Mapping[str, List[str]]:
122
+ def _mapping_getter() -> Mapping[str, list[str]]:
124
123
  if os.path.exists(all_properties_path):
125
124
  logger.info("[%s] loading pre-cached properties", prefix)
126
125
  df = pd.read_csv(all_properties_path, sep="\t")
@@ -144,7 +143,7 @@ def get_property(prefix: str, identifier: str, prop: str, **kwargs) -> Optional[
144
143
  :returns: The single value for the property. If multiple are expected, use :func:`get_properties`
145
144
 
146
145
  >>> import pyobo
147
- >>> pyobo.get_property('chebi', '132964', 'http://purl.obolibrary.org/obo/chebi/smiles')
146
+ >>> pyobo.get_property("chebi", "132964", "http://purl.obolibrary.org/obo/chebi/smiles")
148
147
  "C1(=CC=C(N=C1)OC2=CC=C(C=C2)O[C@@H](C(OCCCC)=O)C)C(F)(F)F"
149
148
  """
150
149
  filtered_properties_mapping = get_filtered_properties_mapping(
@@ -153,7 +152,7 @@ def get_property(prefix: str, identifier: str, prop: str, **kwargs) -> Optional[
153
152
  return filtered_properties_mapping.get(identifier)
154
153
 
155
154
 
156
- def get_properties(prefix: str, identifier: str, prop: str, **kwargs) -> Optional[List[str]]:
155
+ def get_properties(prefix: str, identifier: str, prop: str, **kwargs) -> Optional[list[str]]:
157
156
  """Extract a set of properties for the given entity.
158
157
 
159
158
  :param prefix: the resource to load
pyobo/api/relations.py CHANGED
@@ -1,11 +1,10 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  """High-level API for relations."""
4
2
 
5
3
  import logging
6
4
  import os
5
+ from collections.abc import Mapping
7
6
  from functools import lru_cache
8
- from typing import List, Mapping, Optional
7
+ from typing import Optional
9
8
 
10
9
  import networkx as nx
11
10
  import pandas as pd
@@ -121,7 +120,7 @@ def get_id_multirelations_mapping(
121
120
  use_tqdm: bool = False,
122
121
  force: bool = False,
123
122
  version: Optional[str] = None,
124
- ) -> Mapping[str, List[Reference]]:
123
+ ) -> Mapping[str, list[Reference]]:
125
124
  """Get the OBO file and output a synonym dictionary."""
126
125
  if version is None:
127
126
  version = get_version(prefix)
@@ -129,7 +128,7 @@ def get_id_multirelations_mapping(
129
128
  return ontology.get_id_multirelations_mapping(typedef=typedef, use_tqdm=use_tqdm)
130
129
 
131
130
 
132
- @lru_cache()
131
+ @lru_cache
133
132
  @wrap_norm_prefix
134
133
  def get_relation_mapping(
135
134
  prefix: str,
@@ -147,9 +146,9 @@ def get_relation_mapping(
147
146
  Example usage: get homology between HGNC and MGI:
148
147
 
149
148
  >>> import pyobo
150
- >>> human_mapt_hgnc_id = '6893'
151
- >>> mouse_mapt_mgi_id = '97180'
152
- >>> hgnc_mgi_orthology_mapping = pyobo.get_relation_mapping('hgnc', 'ro:HOM0000017', 'mgi')
149
+ >>> human_mapt_hgnc_id = "6893"
150
+ >>> mouse_mapt_mgi_id = "97180"
151
+ >>> hgnc_mgi_orthology_mapping = pyobo.get_relation_mapping("hgnc", "ro:HOM0000017", "mgi")
153
152
  >>> assert mouse_mapt_mgi_id == hgnc_mgi_orthology_mapping[human_mapt_hgnc_id]
154
153
  """
155
154
  if version is None:
@@ -178,9 +177,11 @@ def get_relation(
178
177
  Example usage: get homology between MAPT in HGNC and MGI:
179
178
 
180
179
  >>> import pyobo
181
- >>> human_mapt_hgnc_id = '6893'
182
- >>> mouse_mapt_mgi_id = '97180'
183
- >>> assert mouse_mapt_mgi_id == pyobo.get_relation('hgnc', human_mapt_hgnc_id, 'ro:HOM0000017', 'mgi')
180
+ >>> human_mapt_hgnc_id = "6893"
181
+ >>> mouse_mapt_mgi_id = "97180"
182
+ >>> assert mouse_mapt_mgi_id == pyobo.get_relation(
183
+ ... "hgnc", human_mapt_hgnc_id, "ro:HOM0000017", "mgi"
184
+ ... )
184
185
  """
185
186
  relation_mapping = get_relation_mapping(
186
187
  prefix=prefix,
pyobo/api/species.py CHANGED
@@ -1,14 +1,13 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  """High-level API for species."""
4
2
 
5
3
  import logging
4
+ from collections.abc import Mapping
6
5
  from functools import lru_cache
7
- from typing import Mapping, Optional
6
+ from typing import Optional
8
7
 
9
8
  from .alts import get_primary_identifier
10
9
  from .utils import get_version
11
- from ..getters import NoBuild, get_ontology
10
+ from ..getters import NoBuildError, get_ontology
12
11
  from ..identifier_utils import wrap_norm_prefix
13
12
  from ..utils.cache import cached_mapping
14
13
  from ..utils.path import prefix_cache_join
@@ -29,7 +28,7 @@ def get_species(prefix: str, identifier: str, *, version: Optional[str] = None)
29
28
 
30
29
  try:
31
30
  id_species = get_id_species_mapping(prefix, version=version)
32
- except NoBuild:
31
+ except NoBuildError:
33
32
  logger.warning("unable to look up species for prefix %s", prefix)
34
33
  return None
35
34
 
@@ -41,7 +40,7 @@ def get_species(prefix: str, identifier: str, *, version: Optional[str] = None)
41
40
  return id_species.get(primary_id)
42
41
 
43
42
 
44
- @lru_cache()
43
+ @lru_cache
45
44
  @wrap_norm_prefix
46
45
  def get_id_species_mapping(
47
46
  prefix: str,
pyobo/api/typedefs.py CHANGED
@@ -1,5 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  """High-level API for typedefs."""
4
2
 
5
3
  import logging
@@ -21,7 +19,7 @@ __all__ = [
21
19
  logger = logging.getLogger(__name__)
22
20
 
23
21
 
24
- @lru_cache()
22
+ @lru_cache
25
23
  @wrap_norm_prefix
26
24
  def get_typedef_df(
27
25
  prefix: str, *, force: bool = False, version: Optional[str] = None
pyobo/api/utils.py CHANGED
@@ -1,20 +1,24 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  """Utilities for high-level API."""
4
2
 
5
3
  import json
4
+ import logging
5
+ import os
6
+ from functools import lru_cache
6
7
  from typing import Optional
7
8
 
8
9
  import bioversions
9
10
 
10
- from ..constants import VERSION_PINS
11
11
  from ..utils.path import prefix_directory_join
12
12
 
13
13
  __all__ = [
14
+ "safe_get_version",
14
15
  "get_version",
16
+ "get_version_pins",
15
17
  "VersionError",
16
18
  ]
17
19
 
20
+ logger = logging.getLogger(__name__)
21
+
18
22
 
19
23
  class VersionError(ValueError):
20
24
  """A catch-all for version getting failure."""
@@ -26,8 +30,8 @@ def get_version(prefix: str) -> Optional[str]:
26
30
  :param prefix: the resource name
27
31
  :return: The version if available else None
28
32
  """
29
- # Prioritize loaded environmental variable VERSION_PINS dictionary
30
- version = VERSION_PINS.get(prefix)
33
+ # Prioritize loaded environment variable PYOBO_VERSION_PINS dictionary
34
+ version = get_version_pins().get(prefix)
31
35
  if version:
32
36
  return version
33
37
  try:
@@ -46,3 +50,55 @@ def get_version(prefix: str) -> Optional[str]:
46
50
  return data["version"]
47
51
 
48
52
  return None
53
+
54
+
55
+ def safe_get_version(prefix: str) -> str:
56
+ """Get the version."""
57
+ v = get_version(prefix)
58
+ if v is None:
59
+ raise ValueError
60
+ return v
61
+
62
+
63
+ @lru_cache(1)
64
+ def get_version_pins() -> dict[str, str]:
65
+ """Retrieve user-defined resource version pins.
66
+
67
+ To set your own resource pins, set your machine's environmental variable
68
+ "PYOBO_VERSION_PINS" to a JSON string containing string resource prefixes
69
+ as keys and string versions of their respective resource as values.
70
+ Constraining version pins will make PyOBO rely on cached versions of a resource.
71
+ A user might want to pin resource versions that are used by PyOBO due to
72
+ the fact that PyOBO will download the latest version of a resource if it is
73
+ not pinned. This downloading process can lead to a slow-down in downstream
74
+ applications that rely on PyOBO.
75
+ """
76
+ version_pins_str = os.getenv("PYOBO_VERSION_PINS")
77
+ if not version_pins_str:
78
+ return {}
79
+
80
+ try:
81
+ version_pins = json.loads(version_pins_str)
82
+ except ValueError as e:
83
+ logger.error(
84
+ "The value for the environment variable PYOBO_VERSION_PINS "
85
+ "must be a valid JSON string: %s",
86
+ e,
87
+ )
88
+ return {}
89
+
90
+ for prefix, version in list(version_pins.items()):
91
+ if not isinstance(prefix, str) or not isinstance(version, str):
92
+ logger.error(f"The prefix:{prefix} and version:{version} name must both be strings")
93
+ del version_pins[prefix]
94
+
95
+ logger.debug(
96
+ f"These are the resource versions that are pinned.\n"
97
+ f"{version_pins}. "
98
+ f"\nPyobo will download the latest version of a resource if it's "
99
+ f"not pinned.\nIf you want to use a specific version of a "
100
+ f"resource, edit your PYOBO_VERSION_PINS environmental "
101
+ f"variable which is a JSON string to include a prefix and version "
102
+ f"name."
103
+ )
104
+ return version_pins
pyobo/api/xrefs.py CHANGED
@@ -1,10 +1,9 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  """High-level API for synonyms."""
4
2
 
5
3
  import logging
4
+ from collections.abc import Mapping
6
5
  from functools import lru_cache
7
- from typing import List, Mapping, Optional, Tuple, Union
6
+ from typing import Optional, Union
8
7
 
9
8
  import pandas as pd
10
9
  from tqdm.auto import tqdm
@@ -43,7 +42,7 @@ def get_xref(
43
42
  return filtered_xrefs.get(identifier)
44
43
 
45
44
 
46
- @lru_cache()
45
+ @lru_cache
47
46
  @wrap_norm_prefix
48
47
  def get_filtered_xrefs(
49
48
  prefix: str,
@@ -147,7 +146,7 @@ def get_sssom_df(
147
146
  prefix = prefix.ontology
148
147
  else:
149
148
  df = get_xrefs_df(prefix=prefix, **kwargs)
150
- rows: List[Tuple[str, ...]] = []
149
+ rows: list[tuple[str, ...]] = []
151
150
  with logging_redirect_tqdm():
152
151
  for source_id, target_prefix, target_id in tqdm(
153
152
  df.values, unit="mapping", unit_scale=True, desc=f"[{prefix}] SSSOM"