Add datetime.datetime and switch to PyResult<Py<T>>
This commit is contained in:
parent
52a64a9240
commit
d7b90c1b3a
|
@ -5,12 +5,12 @@ use ffi3::object::*;
|
|||
use ffi3::pycapsule::PyCapsule_Import;
|
||||
|
||||
#[cfg_attr(windows, link(name="pythonXY"))] extern "C" {
|
||||
pub static mut PyDateTime_Date: PyTypeObject;
|
||||
pub static mut PyDateTime_Time: PyTypeObject;
|
||||
pub static mut PyDateTime_DateTime: PyTypeObject;
|
||||
pub static mut PyDateTime_DateType: PyTypeObject;
|
||||
pub static mut PyDateTime_TimeType: PyTypeObject;
|
||||
pub static mut PyDateTime_DateTimeType: PyTypeObject;
|
||||
|
||||
pub static mut PyDateTime_Delta: PyTypeObject;
|
||||
pub static mut PyDateTime_TZInfo: PyTypeObject;
|
||||
pub static mut PyDateTime_DeltaType: PyTypeObject;
|
||||
pub static mut PyDateTime_TZInfoType: PyTypeObject;
|
||||
}
|
||||
|
||||
|
||||
|
@ -101,6 +101,11 @@ pub struct PyDateTime_CAPI {
|
|||
|
||||
unsafe impl Sync for PyDateTime_CAPI {}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref PyDateTimeAPI: PyDateTime_CAPI = unsafe { PyDateTime_IMPORT() };
|
||||
}
|
||||
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn PyDateTime_IMPORT() -> PyDateTime_CAPI {
|
||||
// PyDateTime_CAPSULE_NAME is a macro in C
|
||||
|
@ -113,5 +118,15 @@ pub unsafe fn PyDateTime_IMPORT() -> PyDateTime_CAPI {
|
|||
|
||||
#[inline(always)]
|
||||
pub unsafe fn PyDate_Check(op: *mut PyObject) -> c_int {
|
||||
PyObject_TypeCheck(op, &mut PyDateTime_Date) as c_int
|
||||
PyObject_TypeCheck(op, PyDateTimeAPI.DateType) as c_int
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn PyDateTime_Check(op: *mut PyObject) -> c_int {
|
||||
PyObject_TypeCheck(op, PyDateTimeAPI.DateTimeType) as c_int
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn PyTZInfo_Check(op: *mut PyObject) -> c_int {
|
||||
PyObject_TypeCheck(op, PyDateTimeAPI.TZInfoType) as c_int
|
||||
}
|
||||
|
|
|
@ -1,27 +1,61 @@
|
|||
use err::PyResult;
|
||||
use object::PyObject;
|
||||
use std::os::raw::c_int;
|
||||
use ffi::{PyDateTime_CAPI, PyDateTime_IMPORT};
|
||||
use ffi::{PyDateTimeAPI};
|
||||
use python::{Python, ToPyPointer};
|
||||
use instance::Py;
|
||||
|
||||
|
||||
|
||||
// datetime.date bindings
|
||||
pub struct PyDate(PyObject);
|
||||
pyobject_convert!(PyDate);
|
||||
pyobject_nativetype!(PyDate, PyDateTime_Date, PyDate_Check);
|
||||
|
||||
lazy_static! {
|
||||
static ref PyDateTimeAPI: PyDateTime_CAPI = unsafe { PyDateTime_IMPORT() };
|
||||
}
|
||||
pyobject_nativetype!(PyDate, PyDateTime_DateType, PyDate_Check);
|
||||
|
||||
impl PyDate {
|
||||
pub fn new(py: Python, year: u32, month: u32, day: u32) -> Py<PyDate> {
|
||||
pub fn new(py: Python, year: u32, month: u32, day: u32) -> PyResult<Py<PyDate>> {
|
||||
let y = year as c_int;
|
||||
let m = month as c_int;
|
||||
let d = day as c_int;
|
||||
|
||||
unsafe {
|
||||
let ptr = PyDateTimeAPI.Date_FromDate.unwrap()(y, m, d, PyDateTimeAPI.DateType);
|
||||
Py::from_owned_ptr_or_panic(ptr)
|
||||
Py::from_owned_ptr_or_err(py, ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// datetime.datetime bindings
|
||||
pub struct PyDateTime(PyObject);
|
||||
pyobject_convert!(PyDateTime);
|
||||
pyobject_nativetype!(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,
|
||||
tzinfo: &PyObject) -> PyResult<Py<PyDateTime>> {
|
||||
let y = year as c_int;
|
||||
let mo = month as c_int;
|
||||
let d = day as c_int;
|
||||
let h = hour as c_int;
|
||||
let mi = minute as c_int;
|
||||
let s = second as c_int;
|
||||
let u = microsecond as c_int;
|
||||
|
||||
unsafe {
|
||||
let ptr = PyDateTimeAPI.DateTime_FromDateAndTime.unwrap()(
|
||||
y, mo, d, h, mi, s, u, tzinfo.as_ptr(),
|
||||
PyDateTimeAPI.DateTimeType
|
||||
);
|
||||
Py::from_owned_ptr_or_err(py, ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// datetime.tzinfo bindings
|
||||
pub struct PyTzInfo(PyObject);
|
||||
pyobject_convert!(PyTzInfo);
|
||||
pyobject_nativetype!(PyTzInfo, PyDateTime_TZInfoType, PyTZInfo_Check);
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ mod exc_impl;
|
|||
|
||||
pub use self::boolobject::PyBool;
|
||||
pub use self::bytearray::PyByteArray;
|
||||
pub use self::datetime::{PyDate};
|
||||
pub use self::datetime::{PyDate,PyDateTime,PyTzInfo};
|
||||
pub use self::dict::PyDict;
|
||||
pub use self::floatob::PyFloat;
|
||||
pub use self::iterator::PyIterator;
|
||||
|
|
|
@ -1,15 +1,27 @@
|
|||
#![feature(proc_macro, specialization)]
|
||||
|
||||
extern crate pyo3;
|
||||
|
||||
use pyo3::{py, Py, Python, PyModule, PyResult};
|
||||
use pyo3::prelude::PyDate;
|
||||
use pyo3::{ToPyObject};
|
||||
use pyo3::prelude::{PyObject};
|
||||
use pyo3::prelude::{PyDate, PyDateTime, PyTzInfo};
|
||||
|
||||
#[py::modinit(datetime)]
|
||||
fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
#[pyfn(m, "make_date")]
|
||||
fn make_date(py: Python, year: u32, month: u32, day: u32) -> PyResult<Py<PyDate>> {
|
||||
Ok(PyDate::new(py, year, month, day))
|
||||
PyDate::new(py, year, month, day)
|
||||
}
|
||||
|
||||
#[pyfn(m, "make_datetime")]
|
||||
fn make_datetime(py: Python, year: u32, month: u32, day: u32,
|
||||
hour: u32, minute: u32, second: u32, microsecond: u32,
|
||||
tzinfo: Option<&PyTzInfo>) -> PyResult<Py<PyDateTime>> {
|
||||
let tzi : PyObject = match tzinfo {
|
||||
Some(t) => t.to_object(py),
|
||||
None => py.None(),
|
||||
};
|
||||
PyDateTime::new(py, year, month, day, hour, minute, second, microsecond, &tzi)
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -9,6 +9,27 @@ def test_date():
|
|||
assert rdt.make_date(2017, 9, 1) == pdt.date(2017, 9, 1)
|
||||
|
||||
|
||||
def test_date_fails():
|
||||
def test_invalid_date_fails():
|
||||
with pytest.raises(ValueError):
|
||||
rdt.make_date(2017, 2, 30)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('args, kwargs', [
|
||||
((2017, 9, 1, 12, 45, 30, 0), {}),
|
||||
((2017, 9, 1, 12, 45, 30, 0), {'tzinfo': pdt.timezone.utc}),
|
||||
])
|
||||
def test_datetime(args, kwargs):
|
||||
act = rdt.make_datetime(*args, **kwargs)
|
||||
exp = pdt.datetime(*args, **kwargs)
|
||||
|
||||
assert act == exp
|
||||
|
||||
|
||||
def test_invalid_datetime_fails():
|
||||
with pytest.raises(ValueError):
|
||||
rdt.make_datetime(2011, 1, 42, 0, 0, 0, 0)
|
||||
|
||||
|
||||
def test_datetime_typeerror():
|
||||
with pytest.raises(TypeError):
|
||||
rdt.make_datetime('2011', 1, 1, 0, 0, 0, 0)
|
||||
|
|
Loading…
Reference in a new issue