77import logging
88import zipfile
99from collections .abc import Iterable
10+ from functools import lru_cache
1011from pathlib import Path
1112from typing import Any , Literal , NamedTuple , TypeAlias
1213
2728 see_also ,
2829)
2930
31+ __all__ = [
32+ "OrganizationType" ,
33+ "RORStatus" ,
34+ "get_ror_records" ,
35+ "get_ror_status" ,
36+ "get_ror_to_country_geonames" ,
37+ ]
38+
3039logger = logging .getLogger (__name__ )
3140PREFIX = "ror"
3241ROR_ZENODO_RECORD_ID = "17953395"
@@ -61,7 +70,7 @@ class RORGetter(Obo):
6170 root_terms = [CITY_CLASS , ORG_CLASS ]
6271
6372 def __post_init__ (self ):
64- self .data_version , _url , _path = _get_info ()
73+ self .data_version , _url , _path = get_ror_status ()
6574 super ().__post_init__ ()
6675
6776 def iter_terms (self , force : bool = False ) -> Iterable [Term ]:
@@ -226,11 +235,11 @@ def _get_description(record: Record) -> str | None:
226235
227236def iterate_ror_terms (* , force : bool = False ) -> Iterable [Term ]:
228237 """Iterate over terms in ROR."""
229- _version , _source_uri , records = get_latest (force = force )
238+ status , records = get_ror_records (force = force )
230239 unhandled_xref_prefixes : set [str ] = set ()
231240
232241 seen_geonames_references = set ()
233- for record in tqdm (records , unit_scale = True , unit = "record" , desc = f"{ PREFIX } v{ _version } " ):
242+ for record in tqdm (records , unit_scale = True , unit = "record" , desc = f"{ PREFIX } v{ status . version } " ):
234243 identifier = record .id .removeprefix ("https://ror.org/" )
235244
236245 primary_name = record .get_preferred_label ()
@@ -330,20 +339,22 @@ def iterate_ror_terms(*, force: bool = False) -> Iterable[Term]:
330339 yield geonames_term
331340
332341
333- class InfoTuple (NamedTuple ):
342+ class RORStatus (NamedTuple ):
334343 """A version information tuple."""
335344
336345 version : str
337346 url : str
338347 path : Path
339348
340349
341- def _get_info (* , force : bool = False ) -> InfoTuple :
350+ def get_ror_status (* , force : bool = False , authenticate_zenodo : bool = True ) -> RORStatus :
342351 """Ensure the latest ROR record, metadata, and filepath.
343352
344353 :param force: Should the record be downloaded again? This almost
345354 never needs to be true, since the data doesn't change for
346355 a given version
356+ :param authenticate_zenodo: Should Zenodo be authenticated?
357+ This isn't required, but can help avoid rate limits
347358 :return: A version information tuple
348359
349360 .. note::
@@ -354,29 +365,34 @@ def _get_info(*, force: bool = False) -> InfoTuple:
354365 for :data:`ROR_ZENODO_RECORD_ID`
355366 """
356367 client = zenodo_client .Zenodo ()
357- latest_record_id = client .get_latest_record (ROR_ZENODO_RECORD_ID )
358- response = client .get_record (latest_record_id )
368+ latest_record_id = client .get_latest_record (
369+ ROR_ZENODO_RECORD_ID , authenticate = authenticate_zenodo
370+ )
371+ response = client .get_record (latest_record_id , authenticate = authenticate_zenodo )
359372 response_json = response .json ()
360373 version = response_json ["metadata" ]["version" ].lstrip ("v" )
361374 file_record = response_json ["files" ][0 ]
362375 name = file_record ["key" ]
363376 url = file_record ["links" ]["self" ]
364377 path = client .download (latest_record_id , name = name , force = force )
365- return InfoTuple (version = version , url = url , path = path )
378+ return RORStatus (version = version , url = url , path = path )
366379
367380
368- def get_latest (* , force : bool = False ) -> tuple [str , str , list [Record ]]:
381+ @lru_cache
382+ def get_ror_records (
383+ * , force : bool = False , authenticate_zenodo : bool = True
384+ ) -> tuple [RORStatus , list [Record ]]:
369385 """Get the latest ROR metadata and records."""
370- version_info = _get_info (force = force )
371- with zipfile .ZipFile (version_info .path ) as zf :
386+ status = get_ror_status (force = force , authenticate_zenodo = authenticate_zenodo )
387+ with zipfile .ZipFile (status .path ) as zf :
372388 for zip_info in zf .filelist :
373389 if zip_info .filename .endswith (".json" ):
374390 with zf .open (zip_info ) as file :
375391 records = [
376392 Record .model_validate (record )
377393 for record in tqdm (json .load (file ), unit_scale = True )
378394 ]
379- return version_info . version , version_info . url , records
395+ return status , records
380396 raise FileNotFoundError
381397
382398
0 commit comments