1"""Convenience methods for parsing."""
2
3from __future__ import annotations
4
5from typing import TYPE_CHECKING, TypeVar
6from xml.etree.ElementTree import Element
7
8from icalendar.compatibility import Self # noqa: F401, RUF100, TC001
9from icalendar.parser.xcal.adapter import ElementAdapter
10
11if TYPE_CHECKING:
12 from collections.abc import Callable
13
14 from icalendar.parser.parameter import Parameters
15 from icalendar.parser.xcal.base import XCalParser
16
17VProp = TypeVar("VProp")
18
19# Trying to solve typing issues: https://stackoverflow.com/q/80005905/1320237
20
21
22def from_xcal_wrapper(
23 func: Callable[[type[VProp], XCalParser, Parameters], VProp],
24) -> Callable[[type[VProp], XCalParser | ElementAdapter | Element], VProp]:
25 """Wrap a property's from_xcal() with convenience functions.
26
27 Use it below ``@classmethod`` so that type checkers and linters see
28 a class method.
29 """
30
31 def wrapper(cls: type[VProp], xml: XCalParser | ElementAdapter | Element) -> VProp:
32 if isinstance(xml, (Element, ElementAdapter)):
33 from icalendar.parser.xcal.property import XCalPropertyParser
34
35 xml = XCalPropertyParser(xml)
36 parameters = xml.parse_parameters()
37 return func(cls, xml, parameters)
38
39 # update attributes
40 wrapper.__name__ = func.__name__
41 wrapper.__qualname__ = func.__qualname__
42 wrapper.__doc__ = func.__doc__
43 wrapper.__module__ = func.__module__
44 # now, we only update the return type but not the arguments
45 wrapper.__annotations__["return"] = func.__annotations__.get(
46 "return", "fix your code and properly annotate the return type"
47 )
48
49 return wrapper
50
51
52__all__ = [
53 "from_xcal_wrapper",
54]