Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/sqlalchemy_utils/primitives/country.py: 52%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

44 statements  

1from functools import total_ordering 

2 

3from .. import i18n 

4from ..utils import str_coercible 

5 

6 

7@total_ordering 

8@str_coercible 

9class Country: 

10 """ 

11 Country class wraps a 2 to 3 letter country code. It provides various 

12 convenience properties and methods. 

13 

14 :: 

15 

16 from babel import Locale 

17 from sqlalchemy_utils import Country, i18n 

18 

19 

20 # First lets add a locale getter for testing purposes 

21 i18n.get_locale = lambda: Locale('en') 

22 

23 

24 Country('FI').name # Finland 

25 Country('FI').code # FI 

26 

27 Country(Country('FI')).code # 'FI' 

28 

29 Country always validates the given code if you use at least the optional 

30 dependency list 'babel', otherwise no validation are performed. 

31 

32 :: 

33 

34 Country(None) # raises TypeError 

35 

36 Country('UnknownCode') # raises ValueError 

37 

38 

39 Country supports equality operators. 

40 

41 :: 

42 

43 Country('FI') == Country('FI') 

44 Country('FI') != Country('US') 

45 

46 

47 Country objects are hashable. 

48 

49 

50 :: 

51 

52 assert hash(Country('FI')) == hash('FI') 

53 

54 """ 

55 

56 def __init__(self, code_or_country): 

57 if isinstance(code_or_country, Country): 

58 self.code = code_or_country.code 

59 elif isinstance(code_or_country, str): 

60 self.validate(code_or_country) 

61 self.code = code_or_country 

62 else: 

63 raise TypeError( 

64 "Country() argument must be a string or a country, not '{}'".format( 

65 type(code_or_country).__name__ 

66 ) 

67 ) 

68 

69 @property 

70 def name(self): 

71 return i18n.get_locale().territories[self.code] 

72 

73 @classmethod 

74 def validate(self, code): 

75 try: 

76 i18n.babel.Locale('en').territories[code] 

77 except KeyError: 

78 raise ValueError(f'Could not convert string to country code: {code}') 

79 except AttributeError: 

80 # As babel is optional, we may raise an AttributeError accessing it 

81 pass 

82 

83 def __eq__(self, other): 

84 if isinstance(other, Country): 

85 return self.code == other.code 

86 elif isinstance(other, str): 

87 return self.code == other 

88 else: 

89 return NotImplemented 

90 

91 def __hash__(self): 

92 return hash(self.code) 

93 

94 def __ne__(self, other): 

95 return not (self == other) 

96 

97 def __lt__(self, other): 

98 if isinstance(other, Country): 

99 return self.code < other.code 

100 elif isinstance(other, str): 

101 return self.code < other 

102 return NotImplemented 

103 

104 def __repr__(self): 

105 return f'{self.__class__.__name__}({self.code!r})' 

106 

107 def __unicode__(self): 

108 return self.name