| 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 | |