Add PyDelta component accessors

Adds the PyDateTime_DELTA_GET_{comp} accessors and bindings to them in
the PyDelta object.
This commit is contained in:
Paul Ganssle 2018-08-08 14:41:39 -04:00
parent 149a13cbfa
commit 08e7e0f55a
No known key found for this signature in database
GPG Key ID: CD54FCE3D964BEFB
5 changed files with 85 additions and 0 deletions

View File

@ -1,6 +1,7 @@
use std::os::raw::c_int;
use std::ffi::CString;
use std::option::Option;
use ffi3::pyport::Py_hash_t;
use ffi3::object::*;
use ffi3::pycapsule::PyCapsule_Import;
@ -104,6 +105,16 @@ pub struct PyDateTime_CAPI {
>,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct PyDateTime_Delta {
pub ob_base: PyObject,
pub hashcode: Py_hash_t,
pub days: c_int,
pub seconds: c_int,
pub microseconds: c_int,
}
unsafe impl Sync for PyDateTime_CAPI {}
lazy_static! {
@ -145,3 +156,34 @@ pub unsafe fn PyTime_Check(op: *mut PyObject) -> c_int {
pub unsafe fn PyDelta_Check(op: *mut PyObject) -> c_int {
PyObject_TypeCheck(op, PyDateTimeAPI.DeltaType) as c_int
}
//
// Accessor functions
//
macro_rules! _access_field {
($obj:expr, $type: ident, $field:tt) => {
(*($obj as *mut $type)).$field
}
}
// Accessor functions for PyDateTime_Delta
macro_rules! _access_delta_field {
($obj:expr, $field:tt) => {
_access_field!($obj, PyDateTime_Delta, $field)
}
}
#[inline(always)]
pub unsafe fn PyDateTime_DELTA_GET_DAYS(o: *mut PyObject) -> c_int {
_access_delta_field!(o, days)
}
#[inline(always)]
pub unsafe fn PyDateTime_DELTA_GET_SECONDS(o: *mut PyObject) -> c_int {
_access_delta_field!(o, seconds)
}
#[inline(always)]
pub unsafe fn PyDateTime_DELTA_GET_MICROSECONDS(o: *mut PyObject) -> c_int {
_access_delta_field!(o, microseconds)
}

View File

@ -5,12 +5,19 @@ use ffi::{PyDateTimeAPI};
use ffi::{PyDateTime_DateType, PyDate_Check};
use ffi::{PyDateTime_DateTimeType, PyDateTime_Check};
use ffi::{PyDateTime_DeltaType, PyDelta_Check};
use ffi::{PyDateTime_DELTA_GET_DAYS, PyDateTime_DELTA_GET_SECONDS, PyDateTime_DELTA_GET_MICROSECONDS};
use ffi::{PyDateTime_TimeType, PyTime_Check};
use ffi::{PyDateTime_TZInfoType, PyTZInfo_Check};
use python::{Python, ToPyPointer};
use instance::Py;
pub trait PyDeltaComponentAccess {
fn get_days(&self) -> i32;
fn get_seconds(&self) -> i32;
fn get_microseconds(&self) -> i32;
}
// datetime.date bindings
pub struct PyDate(PyObject);
@ -142,3 +149,22 @@ impl PyDelta {
}
}
impl PyDeltaComponentAccess for PyDelta {
fn get_days(&self) -> i32 {
unsafe {
PyDateTime_DELTA_GET_DAYS(self.as_ptr()) as i32
}
}
fn get_seconds(&self) -> i32 {
unsafe {
PyDateTime_DELTA_GET_SECONDS(self.as_ptr()) as i32
}
}
fn get_microseconds(&self) -> i32 {
unsafe {
PyDateTime_DELTA_GET_MICROSECONDS(self.as_ptr()) as i32
}
}
}

View File

@ -6,6 +6,7 @@ mod exc_impl;
pub use self::boolobject::PyBool;
pub use self::bytearray::PyByteArray;
pub use self::datetime::{PyDate,PyTime,PyDateTime,PyDelta,PyTzInfo};
pub use self::datetime::{PyDeltaComponentAccess};
pub use self::dict::PyDict;
pub use self::floatob::PyFloat;
pub use self::iterator::PyIterator;

View File

@ -9,6 +9,7 @@ use pyo3::prelude::{pyfunction, pymodinit};
use pyo3::prelude::{PyObject};
use pyo3::prelude::{PyModule};
use pyo3::prelude::{PyDate, PyTime, PyDateTime, PyDelta, PyTzInfo};
use pyo3::prelude::{PyDeltaComponentAccess};
use pyo3::prelude::{PyTuple, PyDict};
@ -44,6 +45,11 @@ fn make_delta(py: Python, days: i32, seconds: i32, microseconds: i32) -> PyResul
PyDelta::new(py, days, seconds, microseconds, true)
}
#[pyfunction]
fn get_delta_tuple(py: Python, delta: &PyDelta) -> Py<PyTuple> {
PyTuple::new(py, &[delta.get_days(), delta.get_seconds(), delta.get_microseconds()])
}
#[pyfunction]
fn make_datetime(py: Python, year: u32, month: u32, day: u32,
hour: u32, minute: u32, second: u32, microsecond: u32,
@ -87,6 +93,7 @@ fn datetime(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_function!(date_from_timestamp))?;
m.add_function(wrap_function!(make_time))?;
m.add_function(wrap_function!(make_delta))?;
m.add_function(wrap_function!(get_delta_tuple))?;
m.add_function(wrap_function!(make_datetime))?;
m.add_function(wrap_function!(datetime_from_timestamp))?;

View File

@ -5,6 +5,7 @@ import datetime as pdt
import pytest
from hypothesis import given
from hypothesis import strategies as st
from hypothesis.strategies import dates, datetimes
# Constants
@ -152,6 +153,14 @@ def test_delta(args):
assert act == exp
@given(td=st.timedeltas())
def test_delta_accessors(td):
act = rdt.get_delta_tuple(td)
exp = (td.days, td.seconds, td.microseconds)
assert act == exp
@pytest.mark.parametrize('args,err_type', [
((MAX_DAYS + 1, 0, 0), OverflowError),
((MIN_DAYS - 1, 0, 0), OverflowError),