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

32 statements  

« prev     ^ index     » next       coverage.py v7.9.1, created at 2025-06-23 02:22 +0000

1import re 

2from datetime import datetime, timedelta 

3from typing import Dict, Optional 

4 

5 

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

7 """ 

8 Returns a datetime object given a timestamp string. 

9 

10 :param str timestamp: The timestamp to parse. 

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

12 """ 

13 if '.' in timestamp: 

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

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

16 

17 

18def extract_recorded_datetime(json_object: Dict) -> Optional[datetime]: 

19 """ 

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

21 

22 :param Dict json_object: An annotation record. 

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

24 """ 

25 if not json_object: 

26 return None 

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

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

29 if timestamp.microsecond >= 500000: 

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

31 return timestamp.replace(microsecond=0) 

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

33 

34 

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

36 """ 

37 Obtains an association value from the annotation data structure. 

38 

39 :param Dict annotation: The complete annotation dictionary. 

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

41 :return dict: The matching value dict. 

42 """ 

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

44 return {} 

45 for association in annotation['associations']: 

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

47 return association 

48 return {} 

49 

50 

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

52 """ 

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

54 

55 :param str annotator: VARS username to format 

56 :return str: Formatted name 

57 """ 

58 if annotator == 'hcarlson': 

59 return 'Harold Carlson' 

60 else: 

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

62 

63 

64def flatten_taxa_tree(tree: Dict, flat: Dict): 

65 """ 

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

67 

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

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

70 """ 

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

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

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

74 return flat