Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/icalendar/prop/geo.py: 80%
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
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
1"""GEO property values from :rfc:`5545`."""
3import math
4from typing import Any, ClassVar
6from icalendar.compatibility import Self
7from icalendar.error import JCalParsingError
8from icalendar.parser import Parameters
11class vGeo:
12 """Geographic Position
14 Property Name:
15 GEO
17 Purpose:
18 This property specifies information related to the global
19 position for the activity specified by a calendar component.
21 Value Type:
22 FLOAT. The value MUST be two SEMICOLON-separated FLOAT values.
24 Property Parameters:
25 IANA and non-standard property parameters can be specified on
26 this property.
28 Conformance:
29 This property can be specified in "VEVENT" or "VTODO"
30 calendar components.
32 Description:
33 This property value specifies latitude and longitude,
34 in that order (i.e., "LAT LON" ordering). The longitude
35 represents the location east or west of the prime meridian as a
36 positive or negative real number, respectively. The longitude and
37 latitude values MAY be specified up to six decimal places, which
38 will allow for accuracy to within one meter of geographical
39 position. Receiving applications MUST accept values of this
40 precision and MAY truncate values of greater precision.
42 Example:
44 .. code-block:: ics
46 GEO:37.386013;-122.082932
48 Parse vGeo:
50 .. code-block:: pycon
52 >>> from icalendar.prop import vGeo
53 >>> geo = vGeo.from_ical('37.386013;-122.082932')
54 >>> geo
55 (37.386013, -122.082932)
57 Add a geo location to an event:
59 .. code-block:: pycon
61 >>> from icalendar import Event
62 >>> event = Event()
63 >>> latitude = 37.386013
64 >>> longitude = -122.082932
65 >>> event.add('GEO', (latitude, longitude))
66 >>> event['GEO']
67 vGeo((37.386013, -122.082932))
68 """
70 default_value: ClassVar[str] = "FLOAT"
71 params: Parameters
73 def __init__(
74 self,
75 geo: tuple[float | str | int, float | str | int],
76 /,
77 params: dict[str, Any] | None = None,
78 ) -> None:
79 """Create a new vGeo from a tuple of (latitude, longitude).
81 Raises:
82 ValueError: if geo is not a tuple of (latitude, longitude)
83 """
84 try:
85 latitude, longitude = (geo[0], geo[1])
86 latitude = float(latitude)
87 longitude = float(longitude)
88 except Exception as e:
89 raise ValueError(
90 "Input must be (float, float) for latitude and longitude"
91 ) from e
92 self.latitude = latitude
93 self.longitude = longitude
94 self.params = Parameters(params)
96 def to_ical(self) -> str:
97 return f"{self.latitude};{self.longitude}"
99 @property
100 def ical_value(self) -> tuple[float, float]:
101 """Geographic position as a tuple of (latitude, longitude) according to :rfc:`5545#section-3.8.1.6`."""
102 return (self.latitude, self.longitude)
104 @staticmethod
105 def from_ical(ical: str) -> tuple[float, float]:
106 try:
107 latitude, longitude = ical.split(";")
108 latitude, longitude = float(latitude), float(longitude)
109 except Exception as e:
110 raise ValueError(f"Expected 'float;float' , got: {ical}") from e
111 if not (math.isfinite(latitude) and math.isfinite(longitude)):
112 raise ValueError(f"Expected finite 'float;float', got: {ical}")
113 return (latitude, longitude)
115 def __eq__(self, other: object) -> bool:
116 return isinstance(other, vGeo) and self.to_ical() == other.to_ical()
118 def __hash__(self) -> int:
119 """Hash of the vGeo object."""
120 return hash((self.latitude, self.longitude))
122 def __repr__(self) -> str:
123 """repr(self)"""
124 return f"{self.__class__.__name__}(({self.latitude}, {self.longitude}))"
126 def to_jcal(self, name: str) -> list:
127 """Convert to jCal object."""
128 return [
129 name,
130 self.params.to_jcal(),
131 self.VALUE.lower(),
132 [self.latitude, self.longitude],
133 ]
135 @classmethod
136 def examples(cls) -> list[Self]:
137 """Examples of vGeo."""
138 return [cls((37.386013, -122.082932))]
140 from icalendar.param import VALUE
142 @classmethod
143 def from_jcal(cls, jcal_property: list) -> Self:
144 """Parse jCal from :rfc:`7265`.
146 Parameters:
147 jcal_property: The jCal property to parse.
149 Raises:
150 ~error.JCalParsingError: If the provided jCal is invalid.
151 """
152 JCalParsingError.validate_property(jcal_property, cls)
153 return cls(
154 jcal_property[3],
155 Parameters.from_jcal_property(jcal_property),
156 )
159__all__ = ["vGeo"]