Add test to fix #220
This commit is contained in:
parent
4c0ddbe61e
commit
a9b05711b0
|
@ -30,6 +30,7 @@ def get_py_version_cfgs():
|
||||||
|
|
||||||
return out_cfg
|
return out_cfg
|
||||||
|
|
||||||
|
|
||||||
install_requires = []
|
install_requires = []
|
||||||
tests_require = install_requires + ['pytest', 'pytest-benchmark']
|
tests_require = install_requires + ['pytest', 'pytest-benchmark']
|
||||||
|
|
||||||
|
@ -49,6 +50,8 @@ setup(
|
||||||
rust_extensions=[RustExtension('rustapi_module.othermod', 'Cargo.toml',
|
rust_extensions=[RustExtension('rustapi_module.othermod', 'Cargo.toml',
|
||||||
rustc_flags=get_py_version_cfgs()),
|
rustc_flags=get_py_version_cfgs()),
|
||||||
RustExtension('rustapi_module.datetime', 'Cargo.toml',
|
RustExtension('rustapi_module.datetime', 'Cargo.toml',
|
||||||
|
rustc_flags=get_py_version_cfgs()),
|
||||||
|
RustExtension('rustapi_module.subclassing', 'Cargo.toml',
|
||||||
rustc_flags=get_py_version_cfgs())],
|
rustc_flags=get_py_version_cfgs())],
|
||||||
install_requires=install_requires,
|
install_requires=install_requires,
|
||||||
tests_require=tests_require,
|
tests_require=tests_require,
|
||||||
|
|
230
examples/rustapi_module/src/datetime.rs
Normal file
230
examples/rustapi_module/src/datetime.rs
Normal file
|
@ -0,0 +1,230 @@
|
||||||
|
use pyo3::prelude::*;
|
||||||
|
use pyo3::types::{
|
||||||
|
PyDate, PyDateAccess, PyDateTime, PyDelta, PyDeltaAccess, PyTime, PyTimeAccess,
|
||||||
|
PyTuple, PyTzInfo,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[pyfunction]
|
||||||
|
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() as i32, d.get_day() as i32],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pyfunction]
|
||||||
|
fn date_from_timestamp(py: Python, timestamp: i64) -> PyResult<Py<PyDate>> {
|
||||||
|
PyDate::from_timestamp(py, timestamp)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pyfunction]
|
||||||
|
fn make_time(
|
||||||
|
py: Python,
|
||||||
|
hour: u8,
|
||||||
|
minute: u8,
|
||||||
|
second: u8,
|
||||||
|
microsecond: u32,
|
||||||
|
tzinfo: Option<&PyTzInfo>,
|
||||||
|
) -> PyResult<Py<PyTime>> {
|
||||||
|
PyTime::new(
|
||||||
|
py,
|
||||||
|
hour,
|
||||||
|
minute,
|
||||||
|
second,
|
||||||
|
microsecond,
|
||||||
|
tzinfo.map(|o| o.to_object(py)).as_ref(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(Py_3_6)]
|
||||||
|
#[pyfunction]
|
||||||
|
fn time_with_fold(
|
||||||
|
py: Python,
|
||||||
|
hour: u8,
|
||||||
|
minute: u8,
|
||||||
|
second: u8,
|
||||||
|
microsecond: u32,
|
||||||
|
tzinfo: Option<&PyTzInfo>,
|
||||||
|
fold: bool,
|
||||||
|
) -> PyResult<Py<PyTime>> {
|
||||||
|
PyTime::new_with_fold(
|
||||||
|
py,
|
||||||
|
hour,
|
||||||
|
minute,
|
||||||
|
second,
|
||||||
|
microsecond,
|
||||||
|
tzinfo.map(|o| o.to_object(py)).as_ref(),
|
||||||
|
fold,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pyfunction]
|
||||||
|
fn get_time_tuple(py: Python, dt: &PyTime) -> Py<PyTuple> {
|
||||||
|
PyTuple::new(
|
||||||
|
py,
|
||||||
|
&[
|
||||||
|
dt.get_hour() as u32,
|
||||||
|
dt.get_minute() as u32,
|
||||||
|
dt.get_second() as u32,
|
||||||
|
dt.get_microsecond(),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(Py_3_6)]
|
||||||
|
#[pyfunction]
|
||||||
|
fn get_time_tuple_fold(py: Python, dt: &PyTime) -> Py<PyTuple> {
|
||||||
|
PyTuple::new(
|
||||||
|
py,
|
||||||
|
&[
|
||||||
|
dt.get_hour() as u32,
|
||||||
|
dt.get_minute() as u32,
|
||||||
|
dt.get_second() as u32,
|
||||||
|
dt.get_microsecond(),
|
||||||
|
dt.get_fold() as u32,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pyfunction]
|
||||||
|
fn make_delta(py: Python, days: i32, seconds: i32, microseconds: i32) -> PyResult<Py<PyDelta>> {
|
||||||
|
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: i32,
|
||||||
|
month: u8,
|
||||||
|
day: u8,
|
||||||
|
hour: u8,
|
||||||
|
minute: u8,
|
||||||
|
second: u8,
|
||||||
|
microsecond: u32,
|
||||||
|
tzinfo: Option<&PyTzInfo>,
|
||||||
|
) -> PyResult<Py<PyDateTime>> {
|
||||||
|
PyDateTime::new(
|
||||||
|
py,
|
||||||
|
year,
|
||||||
|
month,
|
||||||
|
day,
|
||||||
|
hour,
|
||||||
|
minute,
|
||||||
|
second,
|
||||||
|
microsecond,
|
||||||
|
tzinfo.map(|o| (o.to_object(py))).as_ref(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pyfunction]
|
||||||
|
fn get_datetime_tuple(py: Python, dt: &PyDateTime) -> Py<PyTuple> {
|
||||||
|
PyTuple::new(
|
||||||
|
py,
|
||||||
|
&[
|
||||||
|
dt.get_year(),
|
||||||
|
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,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(Py_3_6)]
|
||||||
|
#[pyfunction]
|
||||||
|
fn get_datetime_tuple_fold(py: Python, dt: &PyDateTime) -> Py<PyTuple> {
|
||||||
|
PyTuple::new(
|
||||||
|
py,
|
||||||
|
&[
|
||||||
|
dt.get_year(),
|
||||||
|
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,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pyfunction]
|
||||||
|
fn datetime_from_timestamp(py: Python, ts: f64, tz: Option<&PyTzInfo>) -> PyResult<Py<PyDateTime>> {
|
||||||
|
PyDateTime::from_timestamp(py, ts, tz)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pyfunction]
|
||||||
|
fn issue_219() -> PyResult<()> {
|
||||||
|
let gil = Python::acquire_gil();
|
||||||
|
let _py = gil.python();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pyclass(extends=PyTzInfo)]
|
||||||
|
pub struct TzClass {}
|
||||||
|
|
||||||
|
#[pymethods]
|
||||||
|
impl TzClass {
|
||||||
|
#[new]
|
||||||
|
fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
||||||
|
obj.init(|_| TzClass {})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn utcoffset(&self, py: Python, _dt: &PyDateTime) -> PyResult<Py<PyDelta>> {
|
||||||
|
PyDelta::new(py, 0, 3600, 0, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tzname(&self, _py: Python, _dt: &PyDateTime) -> PyResult<String> {
|
||||||
|
Ok(String::from("+01:00"))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dst(&self, _py: Python, _dt: &PyDateTime) -> PyResult<Option<&PyDelta>> {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pymodinit]
|
||||||
|
fn datetime(_py: Python, m: &PyModule) -> PyResult<()> {
|
||||||
|
m.add_function(wrap_function!(make_date))?;
|
||||||
|
m.add_function(wrap_function!(get_date_tuple))?;
|
||||||
|
m.add_function(wrap_function!(date_from_timestamp))?;
|
||||||
|
m.add_function(wrap_function!(make_time))?;
|
||||||
|
m.add_function(wrap_function!(get_time_tuple))?;
|
||||||
|
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!(get_datetime_tuple))?;
|
||||||
|
m.add_function(wrap_function!(datetime_from_timestamp))?;
|
||||||
|
|
||||||
|
// Python 3.6+ functions
|
||||||
|
#[cfg(Py_3_6)]
|
||||||
|
{
|
||||||
|
m.add_function(wrap_function!(time_with_fold))?;
|
||||||
|
m.add_function(wrap_function!(get_time_tuple_fold))?;
|
||||||
|
m.add_function(wrap_function!(get_datetime_tuple_fold))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
m.add_function(wrap_function!(issue_219))?;
|
||||||
|
|
||||||
|
m.add_class::<TzClass>()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -3,235 +3,9 @@
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate pyo3;
|
extern crate pyo3;
|
||||||
|
|
||||||
pub mod othermod;
|
|
||||||
|
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
use pyo3::types::{
|
use subclassing::Subclassable;
|
||||||
PyDate, PyDateAccess, PyDateTime, PyDelta, PyDeltaAccess, PyDict, PyTime, PyTimeAccess,
|
|
||||||
PyTuple, PyTzInfo,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[pyfunction]
|
pub mod othermod;
|
||||||
fn make_date(py: Python, year: i32, month: u8, day: u8) -> PyResult<Py<PyDate>> {
|
pub mod subclassing;
|
||||||
PyDate::new(py, year, month, day)
|
pub mod datetime;
|
||||||
}
|
|
||||||
|
|
||||||
#[pyfunction]
|
|
||||||
fn get_date_tuple(py: Python, d: &PyDate) -> Py<PyTuple> {
|
|
||||||
PyTuple::new(
|
|
||||||
py,
|
|
||||||
&[d.get_year(), d.get_month() as i32, d.get_day() as i32],
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pyfunction]
|
|
||||||
fn date_from_timestamp(py: Python, timestamp: i64) -> PyResult<Py<PyDate>> {
|
|
||||||
PyDate::from_timestamp(py, timestamp)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pyfunction]
|
|
||||||
fn make_time(
|
|
||||||
py: Python,
|
|
||||||
hour: u8,
|
|
||||||
minute: u8,
|
|
||||||
second: u8,
|
|
||||||
microsecond: u32,
|
|
||||||
tzinfo: Option<&PyTzInfo>,
|
|
||||||
) -> PyResult<Py<PyTime>> {
|
|
||||||
PyTime::new(
|
|
||||||
py,
|
|
||||||
hour,
|
|
||||||
minute,
|
|
||||||
second,
|
|
||||||
microsecond,
|
|
||||||
tzinfo.map(|o| o.to_object(py)).as_ref(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(Py_3_6)]
|
|
||||||
#[pyfunction]
|
|
||||||
fn time_with_fold(
|
|
||||||
py: Python,
|
|
||||||
hour: u8,
|
|
||||||
minute: u8,
|
|
||||||
second: u8,
|
|
||||||
microsecond: u32,
|
|
||||||
tzinfo: Option<&PyTzInfo>,
|
|
||||||
fold: bool,
|
|
||||||
) -> PyResult<Py<PyTime>> {
|
|
||||||
PyTime::new_with_fold(
|
|
||||||
py,
|
|
||||||
hour,
|
|
||||||
minute,
|
|
||||||
second,
|
|
||||||
microsecond,
|
|
||||||
tzinfo.map(|o| o.to_object(py)).as_ref(),
|
|
||||||
fold,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pyfunction]
|
|
||||||
fn get_time_tuple(py: Python, dt: &PyTime) -> Py<PyTuple> {
|
|
||||||
PyTuple::new(
|
|
||||||
py,
|
|
||||||
&[
|
|
||||||
dt.get_hour() as u32,
|
|
||||||
dt.get_minute() as u32,
|
|
||||||
dt.get_second() as u32,
|
|
||||||
dt.get_microsecond(),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(Py_3_6)]
|
|
||||||
#[pyfunction]
|
|
||||||
fn get_time_tuple_fold(py: Python, dt: &PyTime) -> Py<PyTuple> {
|
|
||||||
PyTuple::new(
|
|
||||||
py,
|
|
||||||
&[
|
|
||||||
dt.get_hour() as u32,
|
|
||||||
dt.get_minute() as u32,
|
|
||||||
dt.get_second() as u32,
|
|
||||||
dt.get_microsecond(),
|
|
||||||
dt.get_fold() as u32,
|
|
||||||
],
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pyfunction]
|
|
||||||
fn make_delta(py: Python, days: i32, seconds: i32, microseconds: i32) -> PyResult<Py<PyDelta>> {
|
|
||||||
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: i32,
|
|
||||||
month: u8,
|
|
||||||
day: u8,
|
|
||||||
hour: u8,
|
|
||||||
minute: u8,
|
|
||||||
second: u8,
|
|
||||||
microsecond: u32,
|
|
||||||
tzinfo: Option<&PyTzInfo>,
|
|
||||||
) -> PyResult<Py<PyDateTime>> {
|
|
||||||
PyDateTime::new(
|
|
||||||
py,
|
|
||||||
year,
|
|
||||||
month,
|
|
||||||
day,
|
|
||||||
hour,
|
|
||||||
minute,
|
|
||||||
second,
|
|
||||||
microsecond,
|
|
||||||
tzinfo.map(|o| (o.to_object(py))).as_ref(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pyfunction]
|
|
||||||
fn get_datetime_tuple(py: Python, dt: &PyDateTime) -> Py<PyTuple> {
|
|
||||||
PyTuple::new(
|
|
||||||
py,
|
|
||||||
&[
|
|
||||||
dt.get_year(),
|
|
||||||
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,
|
|
||||||
],
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(Py_3_6)]
|
|
||||||
#[pyfunction]
|
|
||||||
fn get_datetime_tuple_fold(py: Python, dt: &PyDateTime) -> Py<PyTuple> {
|
|
||||||
PyTuple::new(
|
|
||||||
py,
|
|
||||||
&[
|
|
||||||
dt.get_year(),
|
|
||||||
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,
|
|
||||||
],
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pyfunction]
|
|
||||||
fn datetime_from_timestamp(py: Python, ts: f64, tz: Option<&PyTzInfo>) -> PyResult<Py<PyDateTime>> {
|
|
||||||
PyDateTime::from_timestamp(py, ts, tz)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pyfunction]
|
|
||||||
fn issue_219() -> PyResult<()> {
|
|
||||||
let gil = Python::acquire_gil();
|
|
||||||
let _py = gil.python();
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pyclass(extends=PyTzInfo)]
|
|
||||||
pub struct TzClass {}
|
|
||||||
|
|
||||||
#[pymethods]
|
|
||||||
impl TzClass {
|
|
||||||
#[new]
|
|
||||||
fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
|
||||||
obj.init(|_| TzClass {})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn utcoffset(&self, py: Python, dt: &PyDateTime) -> PyResult<Py<PyDelta>> {
|
|
||||||
PyDelta::new(py, 0, 3600, 0, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn tzname(&self, py: Python, dt: &PyDateTime) -> PyResult<String> {
|
|
||||||
Ok(String::from("+01:00"))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn dst(&self, py: Python, dt: &PyDateTime) -> PyResult<Option<&PyDelta>> {
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pymodinit]
|
|
||||||
fn datetime(_py: Python, m: &PyModule) -> PyResult<()> {
|
|
||||||
m.add_function(wrap_function!(make_date))?;
|
|
||||||
m.add_function(wrap_function!(get_date_tuple))?;
|
|
||||||
m.add_function(wrap_function!(date_from_timestamp))?;
|
|
||||||
m.add_function(wrap_function!(make_time))?;
|
|
||||||
m.add_function(wrap_function!(get_time_tuple))?;
|
|
||||||
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!(get_datetime_tuple))?;
|
|
||||||
m.add_function(wrap_function!(datetime_from_timestamp))?;
|
|
||||||
|
|
||||||
// Python 3.6+ functions
|
|
||||||
#[cfg(Py_3_6)]
|
|
||||||
{
|
|
||||||
m.add_function(wrap_function!(time_with_fold))?;
|
|
||||||
m.add_function(wrap_function!(get_time_tuple_fold))?;
|
|
||||||
m.add_function(wrap_function!(get_datetime_tuple_fold))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
m.add_function(wrap_function!(issue_219))?;
|
|
||||||
|
|
||||||
m.add_class::<TzClass>()?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
21
examples/rustapi_module/src/subclassing.rs
Normal file
21
examples/rustapi_module/src/subclassing.rs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
//! Test for [#220](https://github.com/PyO3/pyo3/issues/220)
|
||||||
|
|
||||||
|
use pyo3::prelude::*;
|
||||||
|
|
||||||
|
#[pyclass(subclass)]
|
||||||
|
pub struct Subclassable {}
|
||||||
|
|
||||||
|
#[pymethods]
|
||||||
|
impl Subclassable {
|
||||||
|
#[new]
|
||||||
|
fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
||||||
|
obj.init(|_| Subclassable {})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pymodinit]
|
||||||
|
fn subclassing(_py: Python, m: &PyModule) -> PyResult<()> {
|
||||||
|
m.add_class::<Subclassable>()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
9
examples/rustapi_module/tests/test_subclassing.py
Normal file
9
examples/rustapi_module/tests/test_subclassing.py
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
from rustapi_module.subclassing import Subclassable
|
||||||
|
|
||||||
|
|
||||||
|
class SomeSubClass(Subclassable):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
a = SomeSubClass()
|
||||||
|
_b = str(a) + repr(a)
|
Loading…
Reference in a new issue