Add test to fix #220

This commit is contained in:
konstin 2018-11-11 12:24:24 +01:00
parent 4c0ddbe61e
commit a9b05711b0
5 changed files with 268 additions and 231 deletions

View file

@ -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,

View 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(())
}

View file

@ -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(())
}

View 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(())
}

View file

@ -0,0 +1,9 @@
from rustapi_module.subclassing import Subclassable
class SomeSubClass(Subclassable):
pass
a = SomeSubClass()
_b = str(a) + repr(a)