ffi: support PyDateTime_TimeZone_UTC
This commit is contained in:
parent
eed1b1ad26
commit
e95e73b55e
|
@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||||
- Add FFI definition `Py_IS_TYPE`. [#1429](https://github.com/PyO3/pyo3/pull/1429)
|
- Add FFI definition `Py_IS_TYPE`. [#1429](https://github.com/PyO3/pyo3/pull/1429)
|
||||||
- Add FFI definition `_Py_InitializeMain`. [#1473](https://github.com/PyO3/pyo3/pull/1473)
|
- Add FFI definition `_Py_InitializeMain`. [#1473](https://github.com/PyO3/pyo3/pull/1473)
|
||||||
- Add tuple and unit struct support for `#[pyclass]` macro. [#1504](https://github.com/PyO3/pyo3/pull/1504)
|
- Add tuple and unit struct support for `#[pyclass]` macro. [#1504](https://github.com/PyO3/pyo3/pull/1504)
|
||||||
|
- Add FFI definition `PyDateTime_TimeZone_UTC`. [#1572](https://github.com/PyO3/pyo3/pull/1572)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Change `PyTimeAcces::get_fold()` to return a `bool` instead of a `u8`. [#1397](https://github.com/PyO3/pyo3/pull/1397)
|
- Change `PyTimeAcces::get_fold()` to return a `bool` instead of a `u8`. [#1397](https://github.com/PyO3/pyo3/pull/1397)
|
||||||
|
|
|
@ -399,13 +399,11 @@ pub struct PyDateTime_CAPI {
|
||||||
pub TimeZone_FromTimeZone:
|
pub TimeZone_FromTimeZone:
|
||||||
unsafe extern "C" fn(offset: *mut PyObject, name: *mut PyObject) -> *mut PyObject,
|
unsafe extern "C" fn(offset: *mut PyObject, name: *mut PyObject) -> *mut PyObject,
|
||||||
|
|
||||||
// Defined for PyPy as `PyDateTime_FromTimestamp`
|
|
||||||
pub DateTime_FromTimestamp: unsafe extern "C" fn(
|
pub DateTime_FromTimestamp: unsafe extern "C" fn(
|
||||||
cls: *mut PyTypeObject,
|
cls: *mut PyTypeObject,
|
||||||
args: *mut PyObject,
|
args: *mut PyObject,
|
||||||
kwargs: *mut PyObject,
|
kwargs: *mut PyObject,
|
||||||
) -> *mut PyObject,
|
) -> *mut PyObject,
|
||||||
// Defined for PyPy as `PyDate_FromTimestamp`
|
|
||||||
pub Date_FromTimestamp:
|
pub Date_FromTimestamp:
|
||||||
unsafe extern "C" fn(cls: *mut PyTypeObject, args: *mut PyObject) -> *mut PyObject,
|
unsafe extern "C" fn(cls: *mut PyTypeObject, args: *mut PyObject) -> *mut PyObject,
|
||||||
#[cfg(not(PyPy))]
|
#[cfg(not(PyPy))]
|
||||||
|
@ -447,6 +445,17 @@ pub static PyDateTimeAPI: _PyDateTimeAPI_impl = _PyDateTimeAPI_impl {
|
||||||
inner: GILOnceCell::new(),
|
inner: GILOnceCell::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Safe wrapper around the Python C-API global `PyDateTime_TimeZone_UTC`. This follows a similar
|
||||||
|
/// strategy as [`PyDateTimeAPI`]: the Python datetime C-API will automatically be imported if this
|
||||||
|
/// type is deferenced.
|
||||||
|
///
|
||||||
|
/// The type obtained by dereferencing this object is `&'static PyObject`. This may change in the
|
||||||
|
/// future to be a more specific type representing that this is a `datetime.timezone` object.
|
||||||
|
#[cfg(all(Py_3_7, not(PyPy)))]
|
||||||
|
pub static PyDateTime_TimeZone_UTC: _PyDateTime_TimeZone_UTC_impl = _PyDateTime_TimeZone_UTC_impl {
|
||||||
|
inner: &PyDateTimeAPI,
|
||||||
|
};
|
||||||
|
|
||||||
/// Populates the `PyDateTimeAPI` object
|
/// Populates the `PyDateTimeAPI` object
|
||||||
///
|
///
|
||||||
/// Unlike in C, this does *not* need to be actively invoked in Rust, which
|
/// Unlike in C, this does *not* need to be actively invoked in Rust, which
|
||||||
|
@ -559,6 +568,16 @@ pub unsafe fn PyTZInfo_CheckExact(op: *mut PyObject) -> c_int {
|
||||||
// skipped non-limited PyTimeZone_FromOffset
|
// skipped non-limited PyTimeZone_FromOffset
|
||||||
// skipped non-limited PyTimeZone_FromOffsetAndName
|
// skipped non-limited PyTimeZone_FromOffsetAndName
|
||||||
|
|
||||||
|
#[cfg(not(PyPy))]
|
||||||
|
pub unsafe fn PyDateTime_FromTimestamp(args: *mut PyObject) -> *mut PyObject {
|
||||||
|
(PyDateTimeAPI.DateTime_FromTimestamp)(PyDateTimeAPI.DateTimeType, args, std::ptr::null_mut())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(PyPy))]
|
||||||
|
pub unsafe fn PyDate_FromTimestamp(args: *mut PyObject) -> *mut PyObject {
|
||||||
|
(PyDateTimeAPI.Date_FromTimestamp)(PyDateTimeAPI.DateType, args)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(PyPy)]
|
#[cfg(PyPy)]
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#[link_name = "PyPyDate_FromTimestamp"]
|
#[link_name = "PyPyDate_FromTimestamp"]
|
||||||
|
@ -566,6 +585,7 @@ extern "C" {
|
||||||
#[link_name = "PyPyDateTime_FromTimestamp"]
|
#[link_name = "PyPyDateTime_FromTimestamp"]
|
||||||
pub fn PyDateTime_FromTimestamp(args: *mut PyObject) -> *mut PyObject;
|
pub fn PyDateTime_FromTimestamp(args: *mut PyObject) -> *mut PyObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(PyPy)]
|
#[cfg(PyPy)]
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#[link_name = "_PyPyDateTime_Import"]
|
#[link_name = "_PyPyDateTime_Import"]
|
||||||
|
@ -587,3 +607,70 @@ impl Deref for _PyDateTimeAPI_impl {
|
||||||
unsafe { PyDateTime_IMPORT() }
|
unsafe { PyDateTime_IMPORT() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[cfg(all(Py_3_7, not(PyPy)))]
|
||||||
|
pub struct _PyDateTime_TimeZone_UTC_impl {
|
||||||
|
inner: &'static _PyDateTimeAPI_impl,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(Py_3_7, not(PyPy)))]
|
||||||
|
impl Deref for _PyDateTime_TimeZone_UTC_impl {
|
||||||
|
type Target = crate::PyObject;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn deref(&self) -> &crate::PyObject {
|
||||||
|
unsafe {
|
||||||
|
&*((&self.inner.TimeZone_UTC) as *const *mut crate::ffi::PyObject
|
||||||
|
as *const crate::PyObject)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use crate::{py_run, AsPyPointer, IntoPy, Py, PyAny, Python};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_datetime_fromtimestamp() {
|
||||||
|
Python::with_gil(|py| {
|
||||||
|
let args: Py<PyAny> = (100,).into_py(py);
|
||||||
|
unsafe { PyDateTime_IMPORT() };
|
||||||
|
let dt: &PyAny = unsafe { py.from_owned_ptr(PyDateTime_FromTimestamp(args.as_ptr())) };
|
||||||
|
py_run!(
|
||||||
|
py,
|
||||||
|
dt,
|
||||||
|
"import datetime; assert dt == datetime.datetime.fromtimestamp(100)"
|
||||||
|
);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_date_fromtimestamp() {
|
||||||
|
Python::with_gil(|py| {
|
||||||
|
let args: Py<PyAny> = (100,).into_py(py);
|
||||||
|
dbg!(args.as_ref(py));
|
||||||
|
unsafe { PyDateTime_IMPORT() };
|
||||||
|
let dt: &PyAny = unsafe { py.from_owned_ptr(PyDate_FromTimestamp(args.as_ptr())) };
|
||||||
|
py_run!(
|
||||||
|
py,
|
||||||
|
dt,
|
||||||
|
"import datetime; assert dt == datetime.date.fromtimestamp(100)"
|
||||||
|
);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(all(Py_3_7, not(PyPy)))]
|
||||||
|
fn test_utc_timezone() {
|
||||||
|
Python::with_gil(|py| {
|
||||||
|
let utc_timezone = PyDateTime_TimeZone_UTC.as_ref(py);
|
||||||
|
py_run!(
|
||||||
|
py,
|
||||||
|
utc_timezone,
|
||||||
|
"import datetime; assert utc_timezone is datetime.timezone.utc"
|
||||||
|
);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue