bioversions 0.5.320__py3-none-any.whl → 0.7.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 (85) hide show
  1. bioversions/__init__.py +7 -3
  2. bioversions/__main__.py +0 -2
  3. bioversions/charts.py +3 -7
  4. bioversions/cli.py +3 -5
  5. bioversions/py.typed +0 -0
  6. bioversions/resources/__init__.py +18 -7
  7. bioversions/resources/update.py +20 -12
  8. bioversions/resources/versions.json +20536 -0
  9. bioversions/slack_client.py +2 -5
  10. bioversions/sources/__init__.py +45 -17
  11. bioversions/sources/antibodyregistry.py +9 -6
  12. bioversions/sources/bigg.py +5 -7
  13. bioversions/sources/biogrid.py +0 -2
  14. bioversions/sources/cellosaurus.py +3 -5
  15. bioversions/sources/chebi.py +1 -3
  16. bioversions/sources/chembl.py +3 -3
  17. bioversions/sources/chemidplus.py +1 -3
  18. bioversions/sources/civic.py +46 -0
  19. bioversions/sources/complexportal.py +0 -2
  20. bioversions/sources/daily.py +0 -2
  21. bioversions/sources/depmap.py +1 -3
  22. bioversions/sources/dgi.py +9 -12
  23. bioversions/sources/disgenet.py +1 -3
  24. bioversions/sources/drugbank.py +2 -4
  25. bioversions/sources/drugcentral.py +2 -4
  26. bioversions/sources/ensembl.py +4 -6
  27. bioversions/sources/expasy.py +1 -4
  28. bioversions/sources/flybase.py +0 -2
  29. bioversions/sources/gtdb.py +35 -0
  30. bioversions/sources/guidetopharmacology.py +3 -4
  31. bioversions/sources/hgnc.py +13 -14
  32. bioversions/sources/homologene.py +0 -2
  33. bioversions/sources/icd10.py +30 -0
  34. bioversions/sources/icd11.py +30 -0
  35. bioversions/sources/icf.py +30 -0
  36. bioversions/sources/intact.py +0 -2
  37. bioversions/sources/interpro.py +1 -3
  38. bioversions/sources/itis.py +8 -15
  39. bioversions/sources/kegg.py +7 -6
  40. bioversions/sources/mesh.py +10 -5
  41. bioversions/sources/mgi.py +0 -2
  42. bioversions/sources/mirbase.py +13 -7
  43. bioversions/sources/moalmanac.py +0 -2
  44. bioversions/sources/msigdb.py +0 -2
  45. bioversions/sources/ncit.py +1 -4
  46. bioversions/sources/npass.py +0 -2
  47. bioversions/sources/obo.py +4 -6
  48. bioversions/sources/ols.py +6 -8
  49. bioversions/sources/omim.py +33 -0
  50. bioversions/sources/oncotree.py +4 -4
  51. bioversions/sources/pathbank.py +0 -2
  52. bioversions/sources/pathwaycommons.py +0 -2
  53. bioversions/sources/pfam.py +0 -2
  54. bioversions/sources/pombase.py +0 -2
  55. bioversions/sources/pr.py +1 -3
  56. bioversions/sources/pubchem.py +0 -2
  57. bioversions/sources/reactome.py +0 -2
  58. bioversions/sources/rfam.py +0 -2
  59. bioversions/sources/rgd.py +1 -3
  60. bioversions/sources/rhea.py +1 -6
  61. bioversions/sources/rxnorm.py +1 -3
  62. bioversions/sources/sgd.py +0 -2
  63. bioversions/sources/signor.py +36 -0
  64. bioversions/sources/slm.py +4 -3
  65. bioversions/sources/stringdb.py +2 -4
  66. bioversions/sources/umls.py +0 -2
  67. bioversions/sources/uniprot.py +1 -3
  68. bioversions/sources/unversioned.py +0 -2
  69. bioversions/sources/wikipathways.py +0 -2
  70. bioversions/sources/zfin.py +0 -2
  71. bioversions/templates/base.html +28 -0
  72. bioversions/templates/home.html +60 -0
  73. bioversions/twitter_client.py +5 -8
  74. bioversions/utils.py +40 -32
  75. bioversions/version.py +3 -5
  76. bioversions/wsgi.py +2 -4
  77. bioversions-0.7.1.dist-info/METADATA +393 -0
  78. bioversions-0.7.1.dist-info/RECORD +81 -0
  79. bioversions-0.7.1.dist-info/WHEEL +4 -0
  80. {bioversions-0.5.320.dist-info → bioversions-0.7.1.dist-info}/entry_points.txt +1 -0
  81. {bioversions-0.5.320.dist-info → bioversions-0.7.1.dist-info/licenses}/LICENSE +1 -1
  82. bioversions-0.5.320.dist-info/METADATA +0 -166
  83. bioversions-0.5.320.dist-info/RECORD +0 -72
  84. bioversions-0.5.320.dist-info/WHEEL +0 -5
  85. bioversions-0.5.320.dist-info/top_level.txt +0 -1
@@ -1,10 +1,7 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  """Utilities for interacting with Slack."""
4
2
 
5
3
  import logging
6
4
  from functools import lru_cache
7
- from typing import Optional
8
5
 
9
6
  import pystow
10
7
  from slack_sdk import WebClient
@@ -18,14 +15,14 @@ logger = logging.getLogger(__name__)
18
15
 
19
16
 
20
17
  @lru_cache(maxsize=1)
21
- def _get_client(token: Optional[str] = None) -> Optional[WebClient]:
18
+ def _get_client(token: str | None = None) -> WebClient | None:
22
19
  token = pystow.get_config("bioversions", "slack_api_token", passthrough=token)
23
20
  if token is None:
24
21
  return None
25
22
  return WebClient(token=token)
26
23
 
27
24
 
28
- def post(text: str, channel: str = "random", token: Optional[str] = None):
25
+ def post(text: str, channel: str = "random", token: str | None = None):
29
26
  """Post the message to a given Slack channel."""
30
27
  client = _get_client(token)
31
28
  if client is None:
@@ -1,11 +1,13 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  """Sources for Bioversions."""
4
2
 
3
+ from __future__ import annotations
4
+
5
5
  import ftplib
6
6
  import logging
7
+ import traceback
8
+ from collections.abc import Iterable, Mapping
7
9
  from functools import lru_cache
8
- from typing import Iterable, List, Mapping, Optional, Tuple, Type, Union
10
+ from typing import NamedTuple
9
11
 
10
12
  from tqdm import tqdm
11
13
 
@@ -16,6 +18,7 @@ from .cellosaurus import CellosaurusGetter
16
18
  from .chebi import ChEBIGetter
17
19
  from .chembl import ChEMBLGetter
18
20
  from .chemidplus import ChemIDplusGetter
21
+ from .civic import CiVICGetter
19
22
  from .complexportal import ComplexPortalGetter
20
23
  from .daily import NCBIGeneGetter
21
24
  from .depmap import DepMapGetter
@@ -26,9 +29,13 @@ from .drugcentral import DrugCentralGetter
26
29
  from .ensembl import EnsemblGetter
27
30
  from .expasy import ExPASyGetter
28
31
  from .flybase import FlybaseGetter
32
+ from .gtdb import GTDBGetter
29
33
  from .guidetopharmacology import GuideToPharmacologyGetter
30
34
  from .hgnc import HGNCGetter
31
35
  from .homologene import HomoloGeneGetter
36
+ from .icd10 import ICD10Getter
37
+ from .icd11 import ICD11Getter
38
+ from .icf import ICFGetter
32
39
  from .intact import IntActGetter
33
40
  from .interpro import InterProGetter
34
41
  from .itis import ITISGetter
@@ -42,6 +49,7 @@ from .ncit import NCItGetter
42
49
  from .npass import NPASSGetter
43
50
  from .obo import iter_obo_getters
44
51
  from .ols import extend_ols_getters
52
+ from .omim import OMIMGetter
45
53
  from .oncotree import OncoTreeGetter
46
54
  from .pathbank import PathBankGetter
47
55
  from .pathwaycommons import PathwayCommonsGetter
@@ -55,6 +63,7 @@ from .rgd import RGDGetter
55
63
  from .rhea import RheaGetter
56
64
  from .rxnorm import RxNormGetter
57
65
  from .sgd import SgdGetter
66
+ from .signor import SignorGetter
58
67
  from .slm import SwissLipidGetter
59
68
  from .stringdb import StringDBGetter
60
69
  from .umls import UMLSGetter
@@ -64,19 +73,19 @@ from .zfin import ZfinGetter
64
73
  from ..utils import Bioversion, Getter, norm, refresh_daily
65
74
 
66
75
  __all__ = [
67
- "resolve",
68
76
  "get_rows",
69
77
  "get_version",
78
+ "resolve",
70
79
  ]
71
80
 
72
81
  logger = logging.getLogger(__name__)
73
82
 
74
83
 
75
84
  @lru_cache(maxsize=1)
76
- def get_getters() -> List[Type[Getter]]:
85
+ def get_getters() -> list[type[Getter]]:
77
86
  """Get a list of getters."""
78
87
  # TODO replace with entrypoint lookup
79
- getters: List[Type[Getter]] = [
88
+ getters: list[type[Getter]] = [
80
89
  BioGRIDGetter,
81
90
  ChEMBLGetter,
82
91
  ComplexPortalGetter,
@@ -127,6 +136,13 @@ def get_getters() -> List[Type[Getter]]:
127
136
  RGDGetter,
128
137
  CellosaurusGetter,
129
138
  MGIGetter,
139
+ OMIMGetter,
140
+ ICFGetter,
141
+ ICD10Getter,
142
+ ICD11Getter,
143
+ CiVICGetter,
144
+ GTDBGetter,
145
+ SignorGetter,
130
146
  ]
131
147
  getters.extend(iter_obo_getters())
132
148
  extend_ols_getters(getters)
@@ -134,7 +150,7 @@ def get_getters() -> List[Type[Getter]]:
134
150
  return getters
135
151
 
136
152
 
137
- def get_getter_dict() -> Mapping[str, Type[Getter]]:
153
+ def get_getter_dict() -> Mapping[str, type[Getter]]:
138
154
  """Get a dict of getters."""
139
155
  rv = {}
140
156
  for getter in get_getters():
@@ -143,6 +159,9 @@ def get_getter_dict() -> Mapping[str, Type[Getter]]:
143
159
  rv[norm(getter.bioregistry_id)] = getter
144
160
  rv[getter.name] = getter
145
161
  rv[norm(getter.name)] = getter
162
+ for pp in getter.collection or []:
163
+ rv[pp] = getter
164
+ rv[norm(pp)] = getter
146
165
  return rv
147
166
 
148
167
 
@@ -161,7 +180,7 @@ def _resolve_helper_cached(name: str) -> Bioversion:
161
180
 
162
181
  def _resolve_helper(name: str) -> Bioversion:
163
182
  norm_name = norm(name)
164
- getter: Type[Getter] = get_getter_dict()[norm_name]
183
+ getter: type[Getter] = get_getter_dict()[norm_name]
165
184
  return getter.resolve()
166
185
 
167
186
 
@@ -170,31 +189,40 @@ def get_version(name: str) -> str:
170
189
  return resolve(name).version
171
190
 
172
191
 
173
- def get_rows(use_tqdm: Optional[bool] = False) -> List[Bioversion]:
192
+ def get_rows(use_tqdm: bool | None = False) -> list[Bioversion]:
174
193
  """Get the rows, refreshing once per day."""
175
194
  return [
176
195
  bioversion
177
- for bioversion, error in _iter_versions(use_tqdm=use_tqdm)
178
- if error is None and bioversion is not None
196
+ for bioversion in _iter_versions(use_tqdm=use_tqdm)
197
+ if isinstance(bioversion, Bioversion)
179
198
  ]
180
199
 
181
200
 
201
+ class FailureTuple(NamedTuple):
202
+ """Holds information about failures."""
203
+
204
+ name: str
205
+ clstype: str
206
+ message: str
207
+ trace: str
208
+
209
+
182
210
  def _iter_versions(
183
- use_tqdm: Optional[bool] = False,
184
- ) -> Iterable[Union[Tuple[Bioversion, None], Tuple[None, str]]]:
211
+ use_tqdm: bool | None = False,
212
+ ) -> Iterable[Bioversion | FailureTuple]:
185
213
  it = tqdm(get_getters(), disable=not use_tqdm)
186
214
 
187
215
  for cls in it:
188
216
  it.set_postfix(name=cls.name)
189
217
  try:
190
218
  yv = resolve(cls.name)
191
- except (IOError, AttributeError, ftplib.error_perm):
219
+ except (OSError, AttributeError, ftplib.error_perm):
192
220
  msg = f"failed to resolve {cls.name}"
193
221
  tqdm.write(msg)
194
- yield None, msg
222
+ yield FailureTuple(cls.name, cls.__name__, msg, traceback.format_exc())
195
223
  except ValueError as e:
196
224
  msg = f"issue parsing {cls.name}: {e}"
197
225
  tqdm.write(msg)
198
- yield None, msg
226
+ yield FailureTuple(cls.name, cls.__name__, msg, traceback.format_exc())
199
227
  else:
200
- yield yv, None
228
+ yield yv
@@ -1,13 +1,15 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  """A getter for the Antibody Registry."""
4
2
 
5
- from bioversions.utils import Getter, VersionType, get_soup
3
+ import requests
4
+
5
+ from bioversions.utils import Getter, VersionType
6
6
 
7
7
  __all__ = [
8
8
  "AntibodyRegistryGetter",
9
9
  ]
10
10
 
11
+ URL = "https://www.antibodyregistry.org/api/datainfo"
12
+
11
13
 
12
14
  class AntibodyRegistryGetter(Getter):
13
15
  """A getter for the Antibody Registry."""
@@ -15,12 +17,13 @@ class AntibodyRegistryGetter(Getter):
15
17
  bioregistry_id = "antibodyregistry"
16
18
  name = "Antibody Registry"
17
19
  homepage_fmt = "https://antibodyregistry.org/"
18
- version_type = VersionType.semver_minor
20
+ version_type = VersionType.date
19
21
 
20
22
  def get(self):
21
23
  """Get the latest Antibody Registry version number."""
22
- soup = get_soup("https://antibodyregistry.org/")
23
- return soup.find(**{"class": "footer"}).find("a").text.lstrip("v")
24
+ res = requests.get(URL, timeout=3)
25
+ res_json = res.json()
26
+ return res_json["lastupdate"]
24
27
 
25
28
 
26
29
  if __name__ == "__main__":
@@ -1,5 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  """A getter for BiGG."""
4
2
 
5
3
  from datetime import datetime
@@ -23,12 +21,12 @@ class BiGGGetter(Getter):
23
21
 
24
22
  def get(self):
25
23
  """Get the latest BiGG version number."""
26
- res = requests.get(URL).json()
24
+ res = requests.get(URL, timeout=15).json()
27
25
  date = datetime.fromisoformat(res["last_updated"])
28
- return dict(
29
- version=res["bigg_models_version"],
30
- date=date,
31
- )
26
+ return {
27
+ "version": res["bigg_models_version"],
28
+ "date": date,
29
+ }
32
30
 
33
31
 
34
32
  if __name__ == "__main__":
@@ -1,5 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  """A getter for BioGRID."""
4
2
 
5
3
  from ..utils import Getter, VersionType, get_soup
@@ -1,5 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  """A getter for Cellosaurus."""
4
2
 
5
3
  import requests
@@ -24,15 +22,15 @@ class CellosaurusGetter(Getter):
24
22
  # 12:15:2022 12:00
25
23
  def get(self):
26
24
  """Get the latest Cellosaurus version number."""
27
- res = requests.get(URL, stream=True)
25
+ res = requests.get(URL, stream=True, timeout=15)
28
26
  data = {}
29
27
  for line in res.iter_lines(decode_unicode=True):
30
28
  line = line.strip().decode("utf8")
31
29
  if not line:
32
30
  break
33
- key, value = [part.strip() for part in line.split(":", 1)]
31
+ key, value = (part.strip() for part in line.split(":", 1))
34
32
  data[key] = value
35
- return dict(version=data["data-version"], date=data["date"])
33
+ return {"version": data["data-version"], "date": data["date"]}
36
34
 
37
35
 
38
36
  if __name__ == "__main__":
@@ -1,5 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  """A getter for ChEBI."""
4
2
 
5
3
  from bioversions.utils import Getter, VersionType, get_soup
@@ -27,7 +25,7 @@ class ChEBIGetter(Getter):
27
25
  last = list(anchors)[-1]
28
26
  date = last.next_sibling.strip().split()[0]
29
27
  version = last.text.rstrip("/")[len("rel") :]
30
- return dict(version=version, date=date)
28
+ return {"version": version, "date": date}
31
29
 
32
30
 
33
31
  if __name__ == "__main__":
@@ -1,9 +1,8 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  """A getter for ChEMBL."""
4
2
 
5
3
  import ftplib
6
4
  import io
5
+ from typing import ClassVar
7
6
 
8
7
  from bioversions.utils import Getter, VersionType
9
8
 
@@ -23,6 +22,7 @@ class ChEMBLGetter(Getter):
23
22
  homepage_fmt = "ftp://ftp.ebi.ac.uk/pub/databases/chembl/ChEMBLdb/releases/chembl_{version}"
24
23
  date_fmt = "%d/%m/%Y"
25
24
  version_type = VersionType.sequential
25
+ collection: ClassVar[list[str]] = ["chembl", "chembl.target", "chembl.compound", "chembl.cell"]
26
26
 
27
27
  def get(self):
28
28
  """Get the latest ChEMBL version number."""
@@ -39,7 +39,7 @@ class ChEMBLGetter(Getter):
39
39
  date = _removeprefix(line, DATE_PREFIX).strip()
40
40
  if version is None or date is None:
41
41
  raise ValueError
42
- return dict(date=date, version=version)
42
+ return {"date": date, "version": version}
43
43
 
44
44
 
45
45
  def _removeprefix(s, prefix):
@@ -1,5 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  """A getter for ChemIDplus."""
4
2
 
5
3
  import re
@@ -26,7 +24,7 @@ class ChemIDplusGetter(Getter):
26
24
  """Get the latest ChemIDplus version number."""
27
25
  latest_url = "https://ftp.nlm.nih.gov/projects/chemidlease/CurrentChemID.xml"
28
26
  headers = {"Range": "bytes=0-300"} # leave some slack to capture date
29
- r = requests.get(latest_url, headers=headers)
27
+ r = requests.get(latest_url, headers=headers, timeout=15)
30
28
  if r.status_code == 206:
31
29
  result = re.search(r" date=\"([0-9]{4}-[0-9]{2}-[0-9]{2})\">", r.text)
32
30
  if result:
@@ -0,0 +1,46 @@
1
+ """Get the version for CiVIC."""
2
+
3
+ import datetime
4
+ from typing import ClassVar
5
+
6
+ import requests
7
+
8
+ from bioversions.utils import Getter, VersionType
9
+
10
+ URL = "https://civicdb.org/releases/main"
11
+ API = "https://civicdb.org/api/graphql"
12
+ GRAPHQL_QUERY = """\
13
+ query dataReleases {
14
+ dataReleases {
15
+ geneTsv {
16
+ filename
17
+ path
18
+ }
19
+ name
20
+ }
21
+ }
22
+ """
23
+
24
+ # see https://griffithlab.github.io/civic-v2/#query-dataReleases
25
+ # and https://griffithlab.github.io/civic-v2/#definition-DownloadableFile
26
+
27
+
28
+ class CiVICGetter(Getter):
29
+ """A getter for CiVIC."""
30
+
31
+ name = "CiVIC"
32
+ date_fmt = "%d-%b-%Y"
33
+ version_type = VersionType.date
34
+ homepage = "https://civicdb.org"
35
+ collection: ClassVar[list[str]] = ["civic.gid", "civic.eid"]
36
+
37
+ def get(self) -> datetime.datetime:
38
+ """Get the latest ChEMBL version number."""
39
+ res = requests.post(API, json={"query": GRAPHQL_QUERY}, timeout=15)
40
+ # 0 element is always nightly, 1 is latest
41
+ value = res.json()["data"]["dataReleases"][1]["name"]
42
+ return datetime.datetime.strptime(value, "%d-%b-%Y")
43
+
44
+
45
+ if __name__ == "__main__":
46
+ CiVICGetter.print()
@@ -1,5 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  """A getter for Complex Portal."""
4
2
 
5
3
  from bioversions.utils import Getter, VersionType, _get_ftp_date_version
@@ -1,5 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  """A collection of daily updated resources that aren't assigned specific versions."""
4
2
 
5
3
  from bioversions.utils import DailyGetter
@@ -1,5 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  """A getter for DepMap."""
4
2
 
5
3
  import requests
@@ -21,7 +19,7 @@ class DepMapGetter(Getter):
21
19
 
22
20
  def get(self) -> str:
23
21
  """Get the latest DepMap version number."""
24
- res = requests.get(URL)
22
+ res = requests.get(URL, timeout=15)
25
23
  latest = next(release for release in res.json()["releaseData"] if release["isLatest"])
26
24
  return latest["releaseName"][len("DepMap Public ") :]
27
25
 
@@ -1,15 +1,12 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  """A getter for the `Drug Gene Interaction Database (DGI-DB) <http://www.dgidb.org>`_."""
4
2
 
5
- import os
6
-
7
3
  import bs4
4
+ import dateutil.parser
8
5
  import requests
9
6
 
10
7
  from bioversions.utils import Getter, VersionType
11
8
 
12
- DOWNLOADS_PAGE = "https://www.dgidb.org/downloads"
9
+ GITHUB_PAGE = "https://github.com/dgidb/dgidb-v5"
13
10
 
14
11
 
15
12
  class DGIGetter(Getter):
@@ -21,14 +18,14 @@ class DGIGetter(Getter):
21
18
 
22
19
  def get(self):
23
20
  """Get the latest DGI version number."""
24
- res = requests.get(DOWNLOADS_PAGE)
25
- soup = bs4.BeautifulSoup(res.content, parser="lxml", features="lxml")
26
- cells = list(soup.select("table#tsv_downloads tbody tr:first-child td:nth-child(2) a"))
27
- if 1 != len(cells):
21
+ res = requests.get(GITHUB_PAGE, timeout=15)
22
+ soup = bs4.BeautifulSoup(res.content, features="html.parser")
23
+ time_tag = soup.find("relative-time")
24
+ if time_tag is None:
28
25
  raise ValueError
29
- cell = cells[0]
30
- href = cell["href"]
31
- version = os.path.dirname(os.path.relpath(href, "data/monthly_tsvs"))
26
+ datetime_str = time_tag.attrs["datetime"]
27
+ dt_obj = dateutil.parser.parse(datetime_str)
28
+ version = dt_obj.strftime(self.date_version_fmt)
32
29
  return version
33
30
 
34
31
 
@@ -1,5 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  """A getter for DisGeNet."""
4
2
 
5
3
  import requests
@@ -22,7 +20,7 @@ class DisGeNetGetter(Getter):
22
20
 
23
21
  def get(self):
24
22
  """Get the latest DisGeNet version number."""
25
- res = requests.get(URL, params={"format": "json"})
23
+ res = requests.get(URL, params={"format": "json"}, timeout=15)
26
24
  res_json = res.json()
27
25
  version = res_json["database_version"].split()[-1].lstrip("v")
28
26
  return {
@@ -1,5 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  """A getter for DrugBank."""
4
2
 
5
3
  from operator import itemgetter
@@ -26,10 +24,10 @@ class DrugBankGetter(Getter):
26
24
 
27
25
  def get(self):
28
26
  """Get the latest DrugBank version number."""
29
- res = requests.get(URL)
27
+ res = requests.get(URL, timeout=15)
30
28
  res.raise_for_status()
31
29
  latest = max(res.json(), key=itemgetter("released_on"))
32
- return dict(date=latest["released_on"], version=latest["version"])
30
+ return {"date": latest["released_on"], "version": latest["version"]}
33
31
 
34
32
  @staticmethod
35
33
  def homepage_version_transform(version: str) -> str:
@@ -1,5 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  """A getter for DrugCentral."""
4
2
 
5
3
  from contextlib import closing
@@ -13,9 +11,9 @@ __all__ = [
13
11
  HOST = "unmtid-dbs.net"
14
12
  PORT = 5433
15
13
  USER = "drugman"
16
- PASSWORD = "dosage"
14
+ PASSWORD = "dosage" # noqa:S105
17
15
  DBNAME = "drugcentral"
18
- PARAMS = dict(dbname=DBNAME, user=USER, password=PASSWORD, host=HOST, port=PORT)
16
+ PARAMS = {"dbname": DBNAME, "user": USER, "password": PASSWORD, "host": HOST, "port": PORT}
19
17
 
20
18
 
21
19
  class DrugCentralGetter(Getter):
@@ -1,5 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  """A getter for Ensembl."""
4
2
 
5
3
  from bioversions.utils import Getter, VersionType, get_soup
@@ -12,20 +10,20 @@ URL = "https://useast.ensembl.org/index.html"
12
10
 
13
11
 
14
12
  class EnsemblGetter(Getter):
15
- """A getter for DrugBank."""
13
+ """A getter for Ensembl."""
16
14
 
17
15
  bioregistry_id = "ensembl"
18
16
  name = "Ensembl"
19
17
  homepage_fmt = "https://www.ensembl.org"
20
- date_fmt = "%b %Y"
18
+ date_fmt = "%B %Y"
21
19
  version_type = VersionType.sequential
22
20
 
23
21
  def get(self):
24
22
  """Get the latest Ensembl version number."""
25
- soup = get_soup(URL, verify=False)
23
+ soup = get_soup(URL)
26
24
  manifest = soup.find(**{"class": "box-header"}).text
27
25
  version, date = manifest.rstrip(")").split("(", 1)
28
- return dict(version=version.split()[-1], date=date)
26
+ return {"version": version.split()[-1], "date": date}
29
27
 
30
28
 
31
29
  if __name__ == "__main__":
@@ -1,5 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  """A getter for ExPASy."""
4
2
 
5
3
  from datetime import datetime
@@ -12,7 +10,7 @@ __all__ = [
12
10
  "ExPASyGetter",
13
11
  ]
14
12
 
15
- URL = "ftp://ftp.expasy.org/databases/enzyme/enzuser.txt"
13
+ URL = "https://ftp.expasy.org/databases/enzyme/enzuser.txt"
16
14
 
17
15
 
18
16
  class ExPASyGetter(Getter):
@@ -20,7 +18,6 @@ class ExPASyGetter(Getter):
20
18
 
21
19
  bioregistry_id = "eccode"
22
20
  name = "ExPASy"
23
- # date_version_fmt = "%d-%b-%Y"
24
21
  version_type = VersionType.date
25
22
 
26
23
  def get(self) -> str:
@@ -1,5 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  """A getter for FlyBase."""
4
2
 
5
3
  import ftplib
@@ -0,0 +1,35 @@
1
+ """A getter for GTDB."""
2
+
3
+ import requests
4
+
5
+ from bioversions.utils import Getter, VersionType
6
+
7
+ __all__ = [
8
+ "GTDBGetter",
9
+ ]
10
+
11
+ URL = "https://data.gtdb.ecogenomic.org/releases/latest/VERSION.txt"
12
+
13
+
14
+ class GTDBGetter(Getter):
15
+ """A getter for the Genome Taxonomy Database (GTDB)."""
16
+
17
+ bioregistry_id = "gtdb"
18
+ name = "Genome Taxonomy Database"
19
+ version_type = VersionType.sequential
20
+ date_fmt = "%b %d, %Y" # Format to match "Apr 24, 2024"
21
+ homepage_fmt = "https://gtdb.ecogenomic.org/"
22
+
23
+ def get(self):
24
+ """Get the latest GTDB version number from VERSION.txt."""
25
+ res = requests.get(URL, timeout=15)
26
+ lines = res.text.strip().split("\n")
27
+ # First line contains version like "v220"
28
+ version = lines[0].strip().lstrip("v")
29
+ # Third line contains date like "Released Apr 24, 2024"
30
+ date = lines[2].strip().removeprefix("Released ")
31
+ return {"version": version, "date": date}
32
+
33
+
34
+ if __name__ == "__main__":
35
+ GTDBGetter.print()
@@ -1,10 +1,8 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  """A getter for GuideToPharmacology."""
4
2
 
5
3
  import re
6
4
  from datetime import datetime
7
- from typing import Dict
5
+ from typing import ClassVar
8
6
 
9
7
  from bioversions.utils import Getter, VersionType, get_soup
10
8
 
@@ -23,8 +21,9 @@ class GuideToPharmacologyGetter(Getter):
23
21
  homepage_fmt = "https://www.guidetopharmacology.org/DATA/public_iuphardb_v{version}.zip"
24
22
  date_fmt = "%Y-%m-%d"
25
23
  version_type = VersionType.year_minor
24
+ collection: ClassVar[list[str]] = ["iuphar.family", "iuphar.ligand", "iuphar.receptor"]
26
25
 
27
- def get(self) -> Dict[str, str]:
26
+ def get(self) -> dict[str, str]:
28
27
  """Get the latest Guide to Pharmacology version number."""
29
28
  soup = get_soup(URL)
30
29
  text = soup.findAll("div", {"class": "contentboxfullhelp"})[4].div.ul.li.a.text