Switch Py{Date}{Time} constructor parameters to i32
While the valid ranges for the constructor parameters is the same when expressed as either u32 or i32, since the Python API uses i32 in their public interface, we won't have to make any changes to the signatures if the Python behavior changes (e.g. supporting negative years) without their API changing.
This commit is contained in:
parent
113de1bcd3
commit
5d5689f95b
|
@ -14,7 +14,7 @@ use pyo3::{ObjectProtocol, ToPyObject};
|
|||
use pyo3::{Py, PyResult, Python};
|
||||
|
||||
#[pyfunction]
|
||||
fn make_date(py: Python, year: u32, month: u32, day: u32) -> PyResult<Py<PyDate>> {
|
||||
fn make_date(py: Python, year: i32, month: i32, day: i32) -> PyResult<Py<PyDate>> {
|
||||
PyDate::new(py, year, month, day)
|
||||
}
|
||||
|
||||
|
@ -33,10 +33,10 @@ fn date_from_timestamp(py: Python, ts: i64) -> PyResult<Py<PyDate>> {
|
|||
#[pyfunction]
|
||||
fn make_time(
|
||||
py: Python,
|
||||
hour: u32,
|
||||
minute: u32,
|
||||
second: u32,
|
||||
microsecond: u32,
|
||||
hour: i32,
|
||||
minute: i32,
|
||||
second: i32,
|
||||
microsecond: i32,
|
||||
tzinfo: Option<&PyTzInfo>,
|
||||
) -> PyResult<Py<PyTime>> {
|
||||
PyTime::new(
|
||||
|
@ -53,10 +53,10 @@ fn make_time(
|
|||
#[pyfunction]
|
||||
fn time_with_fold(
|
||||
py: Python,
|
||||
hour: u32,
|
||||
minute: u32,
|
||||
second: u32,
|
||||
microsecond: u32,
|
||||
hour: i32,
|
||||
minute: i32,
|
||||
second: i32,
|
||||
microsecond: i32,
|
||||
tzinfo: Option<&PyTzInfo>,
|
||||
fold: bool,
|
||||
) -> PyResult<Py<PyTime>> {
|
||||
|
@ -94,7 +94,7 @@ fn get_time_tuple_fold(py: Python, dt: &PyTime) -> Py<PyTuple> {
|
|||
dt.get_minute(),
|
||||
dt.get_second(),
|
||||
dt.get_microsecond(),
|
||||
dt.get_fold() as u32,
|
||||
dt.get_fold() as i32,
|
||||
],
|
||||
)
|
||||
}
|
||||
|
@ -119,13 +119,13 @@ fn get_delta_tuple(py: Python, delta: &PyDelta) -> Py<PyTuple> {
|
|||
#[pyfunction]
|
||||
fn make_datetime(
|
||||
py: Python,
|
||||
year: u32,
|
||||
month: u32,
|
||||
day: u32,
|
||||
hour: u32,
|
||||
minute: u32,
|
||||
second: u32,
|
||||
microsecond: u32,
|
||||
year: i32,
|
||||
month: i32,
|
||||
day: i32,
|
||||
hour: i32,
|
||||
minute: i32,
|
||||
second: i32,
|
||||
microsecond: i32,
|
||||
tzinfo: Option<&PyTzInfo>,
|
||||
) -> PyResult<Py<PyDateTime>> {
|
||||
PyDateTime::new(
|
||||
|
@ -170,7 +170,7 @@ fn get_datetime_tuple_fold(py: Python, dt: &PyDateTime) -> Py<PyTuple> {
|
|||
dt.get_minute(),
|
||||
dt.get_second(),
|
||||
dt.get_microsecond(),
|
||||
dt.get_fold() as u32,
|
||||
dt.get_fold() as i32,
|
||||
],
|
||||
)
|
||||
}
|
||||
|
|
|
@ -28,9 +28,9 @@ use python::{Python, ToPyPointer};
|
|||
|
||||
// Traits
|
||||
pub trait PyDateAccess {
|
||||
fn get_year(&self) -> u32;
|
||||
fn get_month(&self) -> u32;
|
||||
fn get_day(&self) -> u32;
|
||||
fn get_year(&self) -> i32;
|
||||
fn get_month(&self) -> i32;
|
||||
fn get_day(&self) -> i32;
|
||||
}
|
||||
|
||||
pub trait PyDeltaAccess {
|
||||
|
@ -40,10 +40,10 @@ pub trait PyDeltaAccess {
|
|||
}
|
||||
|
||||
pub trait PyTimeAccess {
|
||||
fn get_hour(&self) -> u32;
|
||||
fn get_minute(&self) -> u32;
|
||||
fn get_second(&self) -> u32;
|
||||
fn get_microsecond(&self) -> u32;
|
||||
fn get_hour(&self) -> i32;
|
||||
fn get_minute(&self) -> i32;
|
||||
fn get_second(&self) -> i32;
|
||||
fn get_microsecond(&self) -> i32;
|
||||
#[cfg(Py_3_6)]
|
||||
fn get_fold(&self) -> u8;
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ pub struct PyDate(PyObject);
|
|||
pyobject_native_type!(PyDate, PyDateTime_DateType, PyDate_Check);
|
||||
|
||||
impl PyDate {
|
||||
pub fn new(py: Python, year: u32, month: u32, day: u32) -> PyResult<Py<PyDate>> {
|
||||
pub fn new(py: Python, year: i32, month: i32, day: i32) -> PyResult<Py<PyDate>> {
|
||||
unsafe {
|
||||
let ptr = (PyDateTimeAPI.Date_FromDate)(
|
||||
year as c_int,
|
||||
|
@ -74,16 +74,16 @@ impl PyDate {
|
|||
}
|
||||
|
||||
impl PyDateAccess for PyDate {
|
||||
fn get_year(&self) -> u32 {
|
||||
unsafe { PyDateTime_GET_YEAR(self.as_ptr()) as u32 }
|
||||
fn get_year(&self) -> i32 {
|
||||
unsafe { PyDateTime_GET_YEAR(self.as_ptr()) as i32 }
|
||||
}
|
||||
|
||||
fn get_month(&self) -> u32 {
|
||||
unsafe { PyDateTime_GET_MONTH(self.as_ptr()) as u32 }
|
||||
fn get_month(&self) -> i32 {
|
||||
unsafe { PyDateTime_GET_MONTH(self.as_ptr()) as i32 }
|
||||
}
|
||||
|
||||
fn get_day(&self) -> u32 {
|
||||
unsafe { PyDateTime_GET_DAY(self.as_ptr()) as u32 }
|
||||
fn get_day(&self) -> i32 {
|
||||
unsafe { PyDateTime_GET_DAY(self.as_ptr()) as i32 }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,13 +94,13 @@ pyobject_native_type!(PyDateTime, PyDateTime_DateTimeType, PyDateTime_Check);
|
|||
impl PyDateTime {
|
||||
pub fn new(
|
||||
py: Python,
|
||||
year: u32,
|
||||
month: u32,
|
||||
day: u32,
|
||||
hour: u32,
|
||||
minute: u32,
|
||||
second: u32,
|
||||
microsecond: u32,
|
||||
year: i32,
|
||||
month: i32,
|
||||
day: i32,
|
||||
hour: i32,
|
||||
minute: i32,
|
||||
second: i32,
|
||||
microsecond: i32,
|
||||
tzinfo: Option<&PyObject>,
|
||||
) -> PyResult<Py<PyDateTime>> {
|
||||
unsafe {
|
||||
|
@ -139,34 +139,34 @@ impl PyDateTime {
|
|||
}
|
||||
|
||||
impl PyDateAccess for PyDateTime {
|
||||
fn get_year(&self) -> u32 {
|
||||
unsafe { PyDateTime_GET_YEAR(self.as_ptr()) as u32 }
|
||||
fn get_year(&self) -> i32 {
|
||||
unsafe { PyDateTime_GET_YEAR(self.as_ptr()) as i32 }
|
||||
}
|
||||
|
||||
fn get_month(&self) -> u32 {
|
||||
unsafe { PyDateTime_GET_MONTH(self.as_ptr()) as u32 }
|
||||
fn get_month(&self) -> i32 {
|
||||
unsafe { PyDateTime_GET_MONTH(self.as_ptr()) as i32 }
|
||||
}
|
||||
|
||||
fn get_day(&self) -> u32 {
|
||||
unsafe { PyDateTime_GET_DAY(self.as_ptr()) as u32 }
|
||||
fn get_day(&self) -> i32 {
|
||||
unsafe { PyDateTime_GET_DAY(self.as_ptr()) as i32 }
|
||||
}
|
||||
}
|
||||
|
||||
impl PyTimeAccess for PyDateTime {
|
||||
fn get_hour(&self) -> u32 {
|
||||
unsafe { PyDateTime_DATE_GET_HOUR(self.as_ptr()) as u32 }
|
||||
fn get_hour(&self) -> i32 {
|
||||
unsafe { PyDateTime_DATE_GET_HOUR(self.as_ptr()) as i32 }
|
||||
}
|
||||
|
||||
fn get_minute(&self) -> u32 {
|
||||
unsafe { PyDateTime_DATE_GET_MINUTE(self.as_ptr()) as u32 }
|
||||
fn get_minute(&self) -> i32 {
|
||||
unsafe { PyDateTime_DATE_GET_MINUTE(self.as_ptr()) as i32 }
|
||||
}
|
||||
|
||||
fn get_second(&self) -> u32 {
|
||||
unsafe { PyDateTime_DATE_GET_SECOND(self.as_ptr()) as u32 }
|
||||
fn get_second(&self) -> i32 {
|
||||
unsafe { PyDateTime_DATE_GET_SECOND(self.as_ptr()) as i32 }
|
||||
}
|
||||
|
||||
fn get_microsecond(&self) -> u32 {
|
||||
unsafe { PyDateTime_DATE_GET_MICROSECOND(self.as_ptr()) as u32 }
|
||||
fn get_microsecond(&self) -> i32 {
|
||||
unsafe { PyDateTime_DATE_GET_MICROSECOND(self.as_ptr()) as i32 }
|
||||
}
|
||||
|
||||
#[cfg(Py_3_6)]
|
||||
|
@ -182,10 +182,10 @@ pyobject_native_type!(PyTime, PyDateTime_TimeType, PyTime_Check);
|
|||
impl PyTime {
|
||||
pub fn new(
|
||||
py: Python,
|
||||
hour: u32,
|
||||
minute: u32,
|
||||
second: u32,
|
||||
microsecond: u32,
|
||||
hour: i32,
|
||||
minute: i32,
|
||||
second: i32,
|
||||
microsecond: i32,
|
||||
tzinfo: Option<&PyObject>,
|
||||
) -> PyResult<Py<PyTime>> {
|
||||
unsafe {
|
||||
|
@ -207,10 +207,10 @@ impl PyTime {
|
|||
#[cfg(Py_3_6)]
|
||||
pub fn new_with_fold(
|
||||
py: Python,
|
||||
hour: u32,
|
||||
minute: u32,
|
||||
second: u32,
|
||||
microsecond: u32,
|
||||
hour: i32,
|
||||
minute: i32,
|
||||
second: i32,
|
||||
microsecond: i32,
|
||||
tzinfo: Option<&PyObject>,
|
||||
fold: bool,
|
||||
) -> PyResult<Py<PyTime>> {
|
||||
|
@ -233,20 +233,20 @@ impl PyTime {
|
|||
}
|
||||
|
||||
impl PyTimeAccess for PyTime {
|
||||
fn get_hour(&self) -> u32 {
|
||||
unsafe { PyDateTime_TIME_GET_HOUR(self.as_ptr()) as u32 }
|
||||
fn get_hour(&self) -> i32 {
|
||||
unsafe { PyDateTime_TIME_GET_HOUR(self.as_ptr()) as i32 }
|
||||
}
|
||||
|
||||
fn get_minute(&self) -> u32 {
|
||||
unsafe { PyDateTime_TIME_GET_MINUTE(self.as_ptr()) as u32 }
|
||||
fn get_minute(&self) -> i32 {
|
||||
unsafe { PyDateTime_TIME_GET_MINUTE(self.as_ptr()) as i32 }
|
||||
}
|
||||
|
||||
fn get_second(&self) -> u32 {
|
||||
unsafe { PyDateTime_TIME_GET_SECOND(self.as_ptr()) as u32 }
|
||||
fn get_second(&self) -> i32 {
|
||||
unsafe { PyDateTime_TIME_GET_SECOND(self.as_ptr()) as i32 }
|
||||
}
|
||||
|
||||
fn get_microsecond(&self) -> u32 {
|
||||
unsafe { PyDateTime_TIME_GET_MICROSECOND(self.as_ptr()) as u32 }
|
||||
fn get_microsecond(&self) -> i32 {
|
||||
unsafe { PyDateTime_TIME_GET_MICROSECOND(self.as_ptr()) as i32 }
|
||||
}
|
||||
|
||||
#[cfg(Py_3_6)]
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
|
||||
extern crate pyo3;
|
||||
|
||||
use pyo3::prelude::*;
|
||||
use std::iter;
|
||||
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::ffi::*;
|
||||
|
||||
fn _get_subclasses<'p>(
|
||||
|
@ -123,19 +124,41 @@ fn test_datetime_utc() {
|
|||
assert_eq!(offset, 0f32);
|
||||
}
|
||||
|
||||
static INVALID_DATES : &'static [(i32, i32, i32)] = &[
|
||||
(-1, 1, 1),
|
||||
(0, 1, 1),
|
||||
(10000, 1, 1),
|
||||
(2<<30, 1, 1),
|
||||
(2018, 2<<30, 1),
|
||||
(2018, 0, 1),
|
||||
(2018, -1, 1),
|
||||
(2018, 13, 1),
|
||||
(2018, 1, 0),
|
||||
(2017, 2, 29),
|
||||
(2018, 1, -1),
|
||||
(2018, 1, 32),
|
||||
];
|
||||
|
||||
static INVALID_TIMES: &'static [(i32, i32, i32, i32)] = &[
|
||||
(-1, 0, 0, 0),
|
||||
(25, 0, 0, 0),
|
||||
(2<<30, 0, 0, 0),
|
||||
(0, -1, 0, 0),
|
||||
(0, 60, 0, 0),
|
||||
(0, 2<<30, 0, 0),
|
||||
(0, 0, -1, 0),
|
||||
(0, 0, 61, 0),
|
||||
(0, 0, 2<<30, 0),
|
||||
];
|
||||
|
||||
|
||||
#[cfg(Py_3_6)]
|
||||
#[test]
|
||||
fn test_pydate_out_of_bounds() {
|
||||
// This test is an XFAIL on Python < 3.6 until bounds checking is implemented
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let vals = [
|
||||
(2147484672u32, 1, 1),
|
||||
(2018, 2147484672u32, 1),
|
||||
(2018, 1, 2147484672u32),
|
||||
];
|
||||
|
||||
for val in vals.into_iter() {
|
||||
for val in INVALID_DATES.into_iter() {
|
||||
let (year, month, day) = val;
|
||||
let dt = PyDate::new(py, *year, *month, *day);
|
||||
let msg = format!("Should have raised an error: {:#?}", val);
|
||||
|
@ -152,14 +175,7 @@ fn test_pytime_out_of_bounds() {
|
|||
// This test is an XFAIL on Python < 3.6 until bounds checking is implemented
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let vals = [
|
||||
(2147484672u32, 0, 0, 0),
|
||||
(0, 2147484672u32, 0, 0),
|
||||
(0, 0, 2147484672u32, 0),
|
||||
(0, 0, 0, 2147484672u32),
|
||||
];
|
||||
|
||||
for val in vals.into_iter() {
|
||||
for val in INVALID_TIMES.into_iter() {
|
||||
let (hour, minute, second, microsecond) = val;
|
||||
let dt = PyTime::new(py, *hour, *minute, *second, *microsecond, None);
|
||||
let msg = format!("Should have raised an error: {:#?}", val);
|
||||
|
@ -176,18 +192,18 @@ fn test_pydatetime_out_of_bounds() {
|
|||
// This test is an XFAIL on Python < 3.6 until bounds checking is implemented
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let vals = [
|
||||
(2147484672u32, 1, 1, 0, 0, 0, 0),
|
||||
(2018, 2147484672u32, 1, 0, 0, 0, 0),
|
||||
(2018, 1, 2147484672u32, 0, 0, 0, 0),
|
||||
(2018, 1, 1, 2147484672u32, 0, 0, 0),
|
||||
(2018, 1, 1, 0, 2147484672u32, 0, 0),
|
||||
(2018, 1, 1, 0, 0, 2147484672u32, 0),
|
||||
(2018, 1, 1, 0, 0, 0, 2147484672u32),
|
||||
];
|
||||
let valid_time = (0, 0, 0, 0);
|
||||
let valid_date = (2018, 1, 1);
|
||||
|
||||
for val in vals.into_iter() {
|
||||
let (year, month, day, hour, minute, second, microsecond) = val;
|
||||
let invalid_dates = INVALID_DATES.into_iter().zip(iter::repeat(&valid_time));
|
||||
let invalid_times = iter::repeat(&valid_date).zip(INVALID_TIMES.into_iter());
|
||||
|
||||
let vals = invalid_dates.chain(invalid_times);
|
||||
|
||||
for val in vals {
|
||||
let (date, time) = val;
|
||||
let (year, month, day) = date;
|
||||
let (hour, minute, second, microsecond) = time;
|
||||
let dt = PyDateTime::new(
|
||||
py,
|
||||
*year,
|
||||
|
|
Loading…
Reference in New Issue