1 | use crate::sync::GILOnceCell; |
2 | use crate::types::PyAnyMethods; |
3 | use crate::{Bound, DowncastError, PyAny, PyErr, PyObject, PyResult, Python}; |
4 | |
5 | pub(crate) struct DatetimeTypes { |
6 | pub(crate) date: PyObject, |
7 | pub(crate) datetime: PyObject, |
8 | pub(crate) time: PyObject, |
9 | pub(crate) timedelta: PyObject, |
10 | pub(crate) timezone: PyObject, |
11 | pub(crate) timezone_utc: PyObject, |
12 | pub(crate) tzinfo: PyObject, |
13 | } |
14 | |
15 | impl DatetimeTypes { |
16 | pub(crate) fn get(py: Python<'_>) -> &Self { |
17 | Self::try_get(py).expect(msg:"failed to load datetime module" ) |
18 | } |
19 | |
20 | pub(crate) fn try_get(py: Python<'_>) -> PyResult<&Self> { |
21 | static TYPES: GILOnceCell<DatetimeTypes> = GILOnceCell::new(); |
22 | TYPES.get_or_try_init(py, || { |
23 | let datetime: Bound<'_, PyModule> = py.import(name:"datetime" )?; |
24 | let timezone: Bound<'_, PyAny> = datetime.getattr(attr_name:"timezone" )?; |
25 | Ok::<_, PyErr>(Self { |
26 | date: datetime.getattr(attr_name:"date" )?.into(), |
27 | datetime: datetime.getattr(attr_name:"datetime" )?.into(), |
28 | time: datetime.getattr(attr_name:"time" )?.into(), |
29 | timedelta: datetime.getattr(attr_name:"timedelta" )?.into(), |
30 | timezone_utc: timezone.getattr(attr_name:"utc" )?.into(), |
31 | timezone: timezone.into(), |
32 | tzinfo: datetime.getattr(attr_name:"tzinfo" )?.into(), |
33 | }) |
34 | }) |
35 | } |
36 | } |
37 | |
38 | pub(crate) fn timezone_utc(py: Python<'_>) -> Bound<'_, PyAny> { |
39 | DatetimeTypes::get(py).timezone_utc.bind(py).clone() |
40 | } |
41 | |
42 | pub(crate) fn check_type( |
43 | value: &Bound<'_, PyAny>, |
44 | t: &PyObject, |
45 | type_name: &'static str, |
46 | ) -> PyResult<()> { |
47 | if !value.is_instance(ty:t.bind(value.py()))? { |
48 | return Err(DowncastError::new(from:value, to:type_name).into()); |
49 | } |
50 | Ok(()) |
51 | } |
52 | |