Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/icalendar/prop/geo.py: 79%

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

47 statements  

1"""GEO property values from :rfc:`5545`.""" 

2 

3from typing import Any, ClassVar 

4 

5from icalendar.compatibility import Self 

6from icalendar.error import JCalParsingError 

7from icalendar.parser import Parameters 

8 

9 

10class vGeo: 

11 """Geographic Position 

12 

13 Property Name: 

14 GEO 

15 

16 Purpose: 

17 This property specifies information related to the global 

18 position for the activity specified by a calendar component. 

19 

20 Value Type: 

21 FLOAT. The value MUST be two SEMICOLON-separated FLOAT values. 

22 

23 Property Parameters: 

24 IANA and non-standard property parameters can be specified on 

25 this property. 

26 

27 Conformance: 

28 This property can be specified in "VEVENT" or "VTODO" 

29 calendar components. 

30 

31 Description: 

32 This property value specifies latitude and longitude, 

33 in that order (i.e., "LAT LON" ordering). The longitude 

34 represents the location east or west of the prime meridian as a 

35 positive or negative real number, respectively. The longitude and 

36 latitude values MAY be specified up to six decimal places, which 

37 will allow for accuracy to within one meter of geographical 

38 position. Receiving applications MUST accept values of this 

39 precision and MAY truncate values of greater precision. 

40 

41 Example: 

42 

43 .. code-block:: ics 

44 

45 GEO:37.386013;-122.082932 

46 

47 Parse vGeo: 

48 

49 .. code-block:: pycon 

50 

51 >>> from icalendar.prop import vGeo 

52 >>> geo = vGeo.from_ical('37.386013;-122.082932') 

53 >>> geo 

54 (37.386013, -122.082932) 

55 

56 Add a geo location to an event: 

57 

58 .. code-block:: pycon 

59 

60 >>> from icalendar import Event 

61 >>> event = Event() 

62 >>> latitude = 37.386013 

63 >>> longitude = -122.082932 

64 >>> event.add('GEO', (latitude, longitude)) 

65 >>> event['GEO'] 

66 vGeo((37.386013, -122.082932)) 

67 """ 

68 

69 default_value: ClassVar[str] = "FLOAT" 

70 params: Parameters 

71 

72 def __init__( 

73 self, 

74 geo: tuple[float | str | int, float | str | int], 

75 /, 

76 params: dict[str, Any] | None = None, 

77 ): 

78 """Create a new vGeo from a tuple of (latitude, longitude). 

79 

80 Raises: 

81 ValueError: if geo is not a tuple of (latitude, longitude) 

82 """ 

83 try: 

84 latitude, longitude = (geo[0], geo[1]) 

85 latitude = float(latitude) 

86 longitude = float(longitude) 

87 except Exception as e: 

88 raise ValueError( 

89 "Input must be (float, float) for latitude and longitude" 

90 ) from e 

91 self.latitude = latitude 

92 self.longitude = longitude 

93 self.params = Parameters(params) 

94 

95 def to_ical(self) -> str: 

96 return f"{self.latitude};{self.longitude}" 

97 

98 @property 

99 def ical_value(self) -> tuple[float, float]: 

100 """Geographic position as a tuple of (latitude, longitude) according to :rfc:`5545#section-3.8.1.6`.""" 

101 return (self.latitude, self.longitude) 

102 

103 @staticmethod 

104 def from_ical(ical: str) -> tuple[float, float]: 

105 try: 

106 latitude, longitude = ical.split(";") 

107 return (float(latitude), float(longitude)) 

108 except Exception as e: 

109 raise ValueError(f"Expected 'float;float' , got: {ical}") from e 

110 

111 def __eq__(self, other: object) -> bool: 

112 return isinstance(other, vGeo) and self.to_ical() == other.to_ical() 

113 

114 def __hash__(self) -> int: 

115 """Hash of the vGeo object.""" 

116 return hash((self.latitude, self.longitude)) 

117 

118 def __repr__(self) -> str: 

119 """repr(self)""" 

120 return f"{self.__class__.__name__}(({self.latitude}, {self.longitude}))" 

121 

122 def to_jcal(self, name: str) -> list: 

123 """Convert to jCal object.""" 

124 return [ 

125 name, 

126 self.params.to_jcal(), 

127 self.VALUE.lower(), 

128 [self.latitude, self.longitude], 

129 ] 

130 

131 @classmethod 

132 def examples(cls) -> list[Self]: 

133 """Examples of vGeo.""" 

134 return [cls((37.386013, -122.082932))] 

135 

136 from icalendar.param import VALUE 

137 

138 @classmethod 

139 def from_jcal(cls, jcal_property: list) -> Self: 

140 """Parse jCal from :rfc:`7265`. 

141 

142 Parameters: 

143 jcal_property: The jCal property to parse. 

144 

145 Raises: 

146 ~error.JCalParsingError: If the provided jCal is invalid. 

147 """ 

148 JCalParsingError.validate_property(jcal_property, cls) 

149 return cls( 

150 jcal_property[3], 

151 Parameters.from_jcal_property(jcal_property), 

152 ) 

153 

154 

155__all__ = ["vGeo"]