Coverage for application / util / functions.py: 97%

31 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-03-23 05:22 +0000

1import re 

2from datetime import datetime, timedelta 

3 

4 

5def parse_datetime(timestamp: str) -> datetime: 

6 """ 

7 Returns a datetime object given a timestamp string. 

8 

9 :param str timestamp: The timestamp to parse. 

10 :return datetime: The timestamp parsed as a datetime object. 

11 """ 

12 if '.' in timestamp: 

13 return datetime.strptime(timestamp, '%Y-%m-%dT%H:%M:%S.%fZ') 

14 return datetime.strptime(timestamp, '%Y-%m-%dT%H:%M:%SZ') 

15 

16 

17def extract_recorded_datetime(json_object: dict) -> datetime | None: 

18 """ 

19 Returns a datetime object of the recorded timestamp given a JSON annotation record. 

20 

21 :param Dict json_object: An annotation record. 

22 :return datetime: A datetime object of the timestamp from the json object. 

23 """ 

24 if not json_object: 

25 return None 

26 if '.' in json_object['recorded_timestamp']: 

27 timestamp = datetime.strptime(json_object['recorded_timestamp'], '%Y-%m-%dT%H:%M:%S.%fZ') 

28 if timestamp.microsecond >= 500000: 

29 return timestamp.replace(microsecond=0) + timedelta(seconds=1) 

30 return timestamp.replace(microsecond=0) 

31 return datetime.strptime(json_object['recorded_timestamp'], '%Y-%m-%dT%H:%M:%SZ') 

32 

33 

34def get_association(annotation: dict, link_name: str) -> dict: 

35 """ 

36 Obtains an association value from the annotation data structure. 

37 

38 :param Dict annotation: The complete annotation dictionary. 

39 :param str link_name: The specific key we want to get the value for. 

40 :return dict: The matching value dict. 

41 """ 

42 if 'associations' not in annotation.keys(): 

43 return {} 

44 for association in annotation['associations']: 

45 if association['link_name'] == link_name: 

46 return association 

47 return {} 

48 

49 

50def format_annotator(annotator: str) -> str: 

51 """ 

52 Format VARS annotator name. Most are formatted as "FirstnameLastname", with some exceptions. 

53 

54 :param str annotator: VARS username to format 

55 :return str: Formatted name 

56 """ 

57 if annotator == 'hcarlson': 

58 return 'Harold Carlson' 

59 else: 

60 return re.sub('([a-zA-Z]+)([A-Z])', r'\1 \2', annotator) 

61 

62 

63def flatten_taxa_tree(tree: dict, flat: dict): 

64 """ 

65 Recursive function taking a taxonomy tree returned from WoRMS API and flattening it into a single dictionary. 

66 

67 :param Dict tree: The nested taxon tree from WoRMS. 

68 :param Dict flat: The newly created flat taxon tree. 

69 """ 

70 flat[tree['rank'].lower()] = tree['scientificname'] 

71 if tree['child'] is not None: 

72 flatten_taxa_tree(tree['child'], flat) 

73 return flat