Coverage for portality / lib / coerce.py: 86%

71 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-05-05 00:09 +0100

1# ~~Coerce:Library~~ 

2from portality.lib import dates 

3from datetime import date, datetime 

4from portality.lib import seamless 

5from portality.datasets import get_country_code, get_currency_code 

6from portality.lib.dates import FMT_DATETIME_MS_STD, FMT_DATE_STD 

7 

8 

9def to_datestamp(in_format=None): 

10 def stampify(val): 

11 return dates.parse(val, format=in_format) 

12 

13 return stampify 

14 

15 

16def date_str(in_format=None, out_format=None): 

17 def datify(val): 

18 if val is None or val == "": 

19 return None 

20 if isinstance(val, date) or isinstance(val, datetime): 

21 return dates.format(val, format=out_format) 

22 else: 

23 return dates.reformat(val, in_format=in_format, out_format=out_format) 

24 

25 return datify 

26 

27 

28def to_isolang(output_format=None, fail_if_not_found=True): 

29 """ 

30 :param output_format: format from input source to putput. Must be one of: 

31 * alpha3 

32 * alt3 

33 * alpha2 

34 * name 

35 * fr 

36 Can be a list in order of preference, too 

37 :param fail_if_not_found: Whether to raise ValueError if there's no match or return the input unchanged 

38 ~~-> Languages:Data~~ 

39 :return: 

40 """ 

41 # delayed import, since we may not always want to load the whole dataset for a dataobj 

42 from portality.lib import isolang as dataset 

43 

44 # sort out the output format list 

45 if output_format is None: 

46 output_format = ["alpha3"] 

47 if not isinstance(output_format, list): 

48 output_format = [output_format] 

49 

50 def isolang(val): 

51 if val is None: 

52 return None 

53 l = dataset.find(val) 

54 

55 # If we didn't find the language, either raise an error or return the provided value 

56 if l is None: 

57 if fail_if_not_found is True: 

58 raise ValueError("Unable to find iso code for language {x}".format(x=val)) 

59 else: 

60 return val 

61 

62 # Retrieve the correct output format from a successful match 

63 for f in output_format: 

64 v = l.get(f) 

65 if v is None or v == "": 

66 continue 

67 return v.upper() 

68 

69 return isolang 

70 

71 

72def to_currency_code(fail_if_not_found=True): 

73 """ 

74 ~~-> Currencies:Data~~ 

75 :param val: 

76 :param fail_if_not_found: 

77 :return: 

78 """ 

79 

80 def codify(val): 

81 if val is None: 

82 return None 

83 nv = get_currency_code(val, fail_if_not_found=fail_if_not_found) 

84 if nv is None: 

85 raise ValueError("Unable to convert {x} to a valid currency code".format(x=val)) 

86 uc = seamless.to_utf8_unicode 

87 return uc(nv) 

88 

89 return codify 

90 

91 

92def to_country_code(val): 

93 """ 

94 ~~-> Countries:Data~~ 

95 :param val: 

96 :return: 

97 """ 

98 if val is None: 

99 return None 

100 nv = get_country_code(val, fail_if_not_found=True) 

101 if nv is None: 

102 raise ValueError("Unable to convert {x} to a valid country code".format(x=val)) 

103 uc = seamless.to_utf8_unicode 

104 return uc(nv) 

105 

106 

107def to_issn(issn): 

108 if len(issn) > 9 or issn == '': 

109 raise ValueError("Unable to normalise {x} to valid ISSN".format(x=issn)) 

110 

111 issn = issn.upper() 

112 if len(issn) == 9: 

113 return issn 

114 

115 if len(issn) == 8: 

116 if "-" in issn: 

117 return "0" + issn 

118 else: 

119 return issn[:4] + "-" + issn[4:] 

120 

121 if len(issn) < 8: 

122 if "-" in issn: 

123 return ("0" * (9 - len(issn))) + issn 

124 else: 

125 issn = ("0" * (8 - len(issn))) + issn 

126 return issn[:4] + "-" + issn[4:] 

127 

128 

129# ~~-> Seamless:Library~~ 

130COERCE_MAP = { 

131 "unicode": seamless.to_utf8_unicode, 

132 "unicode_upper": seamless.to_unicode_upper, 

133 "unicode_lower": seamless.to_unicode_lower, 

134 "integer": seamless.intify, 

135 "float": seamless.floatify, 

136 "url": seamless.to_url, 

137 "bool": seamless.to_bool, 

138 "datetime": seamless.to_datetime, 

139 "utcdatetime": date_str(), 

140 "utcdatetimemicros": date_str(out_format=FMT_DATETIME_MS_STD), 

141 "bigenddate": date_str(out_format=FMT_DATE_STD), 

142 "isolang": to_isolang(), 

143 "isolang_2letter_strict": to_isolang(output_format="alpha2", fail_if_not_found=True), 

144 "isolang_2letter_lax": to_isolang(output_format="alpha2", fail_if_not_found=False), 

145 "country_code": to_country_code, 

146 "issn": to_issn, 

147 "currency_code_strict": to_currency_code(fail_if_not_found=True), 

148 "currency_code_lax": to_currency_code(fail_if_not_found=False) 

149}