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

View File

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

View File

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