Use smallest types for Py{Date}{Time} constructors

Because it's unlikely that anything other than the `year` parameter will
change in the C Python API, the rest can be restricted to their logical
ranges, which improves the compile-time error checking.
This commit is contained in:
Paul Ganssle 2018-08-21 14:14:01 -04:00
parent 5d5689f95b
commit a05a78f7e0
No known key found for this signature in database
GPG key ID: CD54FCE3D964BEFB
3 changed files with 96 additions and 106 deletions

View file

@ -14,13 +14,16 @@ use pyo3::{ObjectProtocol, ToPyObject};
use pyo3::{Py, PyResult, Python};
#[pyfunction]
fn make_date(py: Python, year: i32, month: i32, day: i32) -> PyResult<Py<PyDate>> {
fn make_date(py: Python, year: i32, month: u8, day: u8) -> PyResult<Py<PyDate>> {
PyDate::new(py, year, month, day)
}
#[pyfunction]
fn get_date_tuple(py: Python, d: &PyDate) -> Py<PyTuple> {
PyTuple::new(py, &[d.get_year(), d.get_month(), d.get_day()])
PyTuple::new(
py,
&[d.get_year(), d.get_month() as i32, d.get_day() as i32],
)
}
#[pyfunction]
@ -33,10 +36,10 @@ fn date_from_timestamp(py: Python, ts: i64) -> PyResult<Py<PyDate>> {
#[pyfunction]
fn make_time(
py: Python,
hour: i32,
minute: i32,
second: i32,
microsecond: i32,
hour: u8,
minute: u8,
second: u8,
microsecond: u32,
tzinfo: Option<&PyTzInfo>,
) -> PyResult<Py<PyTime>> {
PyTime::new(
@ -53,10 +56,10 @@ fn make_time(
#[pyfunction]
fn time_with_fold(
py: Python,
hour: i32,
minute: i32,
second: i32,
microsecond: i32,
hour: u8,
minute: u8,
second: u8,
microsecond: u32,
tzinfo: Option<&PyTzInfo>,
fold: bool,
) -> PyResult<Py<PyTime>> {
@ -76,9 +79,9 @@ fn get_time_tuple(py: Python, dt: &PyTime) -> Py<PyTuple> {
PyTuple::new(
py,
&[
dt.get_hour(),
dt.get_minute(),
dt.get_second(),
dt.get_hour() as u32,
dt.get_minute() as u32,
dt.get_second() as u32,
dt.get_microsecond(),
],
)
@ -90,11 +93,11 @@ fn get_time_tuple_fold(py: Python, dt: &PyTime) -> Py<PyTuple> {
PyTuple::new(
py,
&[
dt.get_hour(),
dt.get_minute(),
dt.get_second(),
dt.get_hour() as u32,
dt.get_minute() as u32,
dt.get_second() as u32,
dt.get_microsecond(),
dt.get_fold() as i32,
dt.get_fold() as u32,
],
)
}
@ -120,12 +123,12 @@ fn get_delta_tuple(py: Python, delta: &PyDelta) -> Py<PyTuple> {
fn make_datetime(
py: Python,
year: i32,
month: i32,
day: i32,
hour: i32,
minute: i32,
second: i32,
microsecond: i32,
month: u8,
day: u8,
hour: u8,
minute: u8,
second: u8,
microsecond: u32,
tzinfo: Option<&PyTzInfo>,
) -> PyResult<Py<PyDateTime>> {
PyDateTime::new(
@ -147,12 +150,12 @@ fn get_datetime_tuple(py: Python, dt: &PyDateTime) -> Py<PyTuple> {
py,
&[
dt.get_year(),
dt.get_month(),
dt.get_day(),
dt.get_hour(),
dt.get_minute(),
dt.get_second(),
dt.get_microsecond(),
dt.get_month() as i32,
dt.get_day() as i32,
dt.get_hour() as i32,
dt.get_minute() as i32,
dt.get_second() as i32,
dt.get_microsecond() as i32,
],
)
}
@ -164,12 +167,12 @@ fn get_datetime_tuple_fold(py: Python, dt: &PyDateTime) -> Py<PyTuple> {
py,
&[
dt.get_year(),
dt.get_month(),
dt.get_day(),
dt.get_hour(),
dt.get_minute(),
dt.get_second(),
dt.get_microsecond(),
dt.get_month() as i32,
dt.get_day() as i32,
dt.get_hour() as i32,
dt.get_minute() as i32,
dt.get_second() as i32,
dt.get_microsecond() as i32,
dt.get_fold() as i32,
],
)

View file

@ -29,8 +29,8 @@ use python::{Python, ToPyPointer};
// Traits
pub trait PyDateAccess {
fn get_year(&self) -> i32;
fn get_month(&self) -> i32;
fn get_day(&self) -> i32;
fn get_month(&self) -> u8;
fn get_day(&self) -> u8;
}
pub trait PyDeltaAccess {
@ -40,10 +40,10 @@ pub trait PyDeltaAccess {
}
pub trait PyTimeAccess {
fn get_hour(&self) -> i32;
fn get_minute(&self) -> i32;
fn get_second(&self) -> i32;
fn get_microsecond(&self) -> i32;
fn get_hour(&self) -> u8;
fn get_minute(&self) -> u8;
fn get_second(&self) -> u8;
fn get_microsecond(&self) -> u32;
#[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: i32, month: i32, day: i32) -> PyResult<Py<PyDate>> {
pub fn new(py: Python, year: i32, month: u8, day: u8) -> PyResult<Py<PyDate>> {
unsafe {
let ptr = (PyDateTimeAPI.Date_FromDate)(
year as c_int,
@ -78,12 +78,12 @@ impl PyDateAccess for PyDate {
unsafe { PyDateTime_GET_YEAR(self.as_ptr()) as i32 }
}
fn get_month(&self) -> i32 {
unsafe { PyDateTime_GET_MONTH(self.as_ptr()) as i32 }
fn get_month(&self) -> u8 {
unsafe { PyDateTime_GET_MONTH(self.as_ptr()) as u8 }
}
fn get_day(&self) -> i32 {
unsafe { PyDateTime_GET_DAY(self.as_ptr()) as i32 }
fn get_day(&self) -> u8 {
unsafe { PyDateTime_GET_DAY(self.as_ptr()) as u8 }
}
}
@ -95,12 +95,12 @@ impl PyDateTime {
pub fn new(
py: Python,
year: i32,
month: i32,
day: i32,
hour: i32,
minute: i32,
second: i32,
microsecond: i32,
month: u8,
day: u8,
hour: u8,
minute: u8,
second: u8,
microsecond: u32,
tzinfo: Option<&PyObject>,
) -> PyResult<Py<PyDateTime>> {
unsafe {
@ -143,30 +143,30 @@ impl PyDateAccess for PyDateTime {
unsafe { PyDateTime_GET_YEAR(self.as_ptr()) as i32 }
}
fn get_month(&self) -> i32 {
unsafe { PyDateTime_GET_MONTH(self.as_ptr()) as i32 }
fn get_month(&self) -> u8 {
unsafe { PyDateTime_GET_MONTH(self.as_ptr()) as u8 }
}
fn get_day(&self) -> i32 {
unsafe { PyDateTime_GET_DAY(self.as_ptr()) as i32 }
fn get_day(&self) -> u8 {
unsafe { PyDateTime_GET_DAY(self.as_ptr()) as u8 }
}
}
impl PyTimeAccess for PyDateTime {
fn get_hour(&self) -> i32 {
unsafe { PyDateTime_DATE_GET_HOUR(self.as_ptr()) as i32 }
fn get_hour(&self) -> u8 {
unsafe { PyDateTime_DATE_GET_HOUR(self.as_ptr()) as u8 }
}
fn get_minute(&self) -> i32 {
unsafe { PyDateTime_DATE_GET_MINUTE(self.as_ptr()) as i32 }
fn get_minute(&self) -> u8 {
unsafe { PyDateTime_DATE_GET_MINUTE(self.as_ptr()) as u8 }
}
fn get_second(&self) -> i32 {
unsafe { PyDateTime_DATE_GET_SECOND(self.as_ptr()) as i32 }
fn get_second(&self) -> u8 {
unsafe { PyDateTime_DATE_GET_SECOND(self.as_ptr()) as u8 }
}
fn get_microsecond(&self) -> i32 {
unsafe { PyDateTime_DATE_GET_MICROSECOND(self.as_ptr()) as i32 }
fn get_microsecond(&self) -> u32 {
unsafe { PyDateTime_DATE_GET_MICROSECOND(self.as_ptr()) as u32 }
}
#[cfg(Py_3_6)]
@ -182,10 +182,10 @@ pyobject_native_type!(PyTime, PyDateTime_TimeType, PyTime_Check);
impl PyTime {
pub fn new(
py: Python,
hour: i32,
minute: i32,
second: i32,
microsecond: i32,
hour: u8,
minute: u8,
second: u8,
microsecond: u32,
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: i32,
minute: i32,
second: i32,
microsecond: i32,
hour: u8,
minute: u8,
second: u8,
microsecond: u32,
tzinfo: Option<&PyObject>,
fold: bool,
) -> PyResult<Py<PyTime>> {
@ -233,20 +233,20 @@ impl PyTime {
}
impl PyTimeAccess for PyTime {
fn get_hour(&self) -> i32 {
unsafe { PyDateTime_TIME_GET_HOUR(self.as_ptr()) as i32 }
fn get_hour(&self) -> u8 {
unsafe { PyDateTime_TIME_GET_HOUR(self.as_ptr()) as u8 }
}
fn get_minute(&self) -> i32 {
unsafe { PyDateTime_TIME_GET_MINUTE(self.as_ptr()) as i32 }
fn get_minute(&self) -> u8 {
unsafe { PyDateTime_TIME_GET_MINUTE(self.as_ptr()) as u8 }
}
fn get_second(&self) -> i32 {
unsafe { PyDateTime_TIME_GET_SECOND(self.as_ptr()) as i32 }
fn get_second(&self) -> u8 {
unsafe { PyDateTime_TIME_GET_SECOND(self.as_ptr()) as u8 }
}
fn get_microsecond(&self) -> i32 {
unsafe { PyDateTime_TIME_GET_MICROSECOND(self.as_ptr()) as i32 }
fn get_microsecond(&self) -> u32 {
unsafe { PyDateTime_TIME_GET_MICROSECOND(self.as_ptr()) as u32 }
}
#[cfg(Py_3_6)]

View file

@ -4,8 +4,8 @@ extern crate pyo3;
use std::iter;
use pyo3::prelude::*;
use pyo3::ffi::*;
use pyo3::prelude::*;
fn _get_subclasses<'p>(
py: &'p Python,
@ -124,33 +124,20 @@ 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),
static INVALID_DATES: &'static [(i32, u8, u8)] = &[
(-1, 1, 1),
(0, 1, 1),
(10000, 1, 1),
(2 << 30, 1, 1),
(2018, 0, 1),
(2018, 13, 1),
(2018, 1, 0),
(2017, 2, 29),
(2018, 1, 32),
];
static INVALID_TIMES: &'static [(u8, u8, u8, u32)] =
&[(25, 0, 0, 0), (255, 0, 0, 0), (0, 60, 0, 0), (0, 0, 61, 0)];
#[cfg(Py_3_6)]
#[test]