1"""Common parsing functions based on string."""
2
3import math
4import re
5
6
7def string_to_xsd_float(xsd_float: str) -> float:
8 """Convert an xsd:float to a :class:`float`.
9
10 Returns:
11 The parsed float.
12
13 Raises:
14 ValueError: if the input is not an xsd:float
15 TypeError: if the input is not :class:`str`
16 """
17 if not isinstance(xsd_float, str):
18 raise TypeError("Expected xsd:float. Got None.")
19 try:
20 return float(xsd_float)
21 except (ValueError, TypeError) as e:
22 raise ValueError(f"Expected xsd:float. Got {xsd_float!r}.") from e
23
24
25def xsd_float_to_string(f: float) -> str:
26 """Convert a :class:`float` to an xsd:float."""
27 if math.isnan(f):
28 return "NaN"
29 if math.isfinite(f):
30 return str(f)
31 if f > 0:
32 return "INF"
33 return "-INF"
34
35
36_VALID_XML_CHARACTERS = re.compile(r"[\x00-\x08\x0b\x0c\x0e-\x1f]")
37
38
39def _to_valid_xml_string(string: str) -> str:
40 """Remove all characters that are not valid XML characters.
41
42 Returns:
43
44 A string with all characters that are not valid XML characters removed.
45
46 .. seealso::
47
48 `XML Character Range <https://www.w3.org/TR/REC-xml/#charsets>`_,
49 `~icalendar.prop.text._strip_unsafe_text_chars`,
50 `Issue 1888 <https://github.com/collective/icalendar/issues/1888>`_,
51 """
52 return _VALID_XML_CHARACTERS.sub("", string)
53
54
55__all__ = ["_to_valid_xml_string", "string_to_xsd_float", "xsd_float_to_string"]