From 2fa3b942f2d631fa20ef026d70481c321367283d Mon Sep 17 00:00:00 2001 From: Paul Ganssle Date: Thu, 27 Sep 2018 18:02:29 -0400 Subject: [PATCH 1/2] Add failing test to create tzinfo subclass Currently this fails at import time with undefined symbol: PyDateTime_TZInfoType --- examples/rustapi_module/src/lib.rs | 24 +++++++++++++++++++ .../rustapi_module/tests/test_datetime.py | 12 ++++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/examples/rustapi_module/src/lib.rs b/examples/rustapi_module/src/lib.rs index 84f14e8c..d160a3a9 100644 --- a/examples/rustapi_module/src/lib.rs +++ b/examples/rustapi_module/src/lib.rs @@ -186,6 +186,29 @@ fn issue_219() -> PyResult<()> { 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> { + PyDelta::new(py, 0, 3600, 0, true) + } + + fn tzname(&self, py: Python, dt: &PyDateTime) -> PyResult { + Ok(String::from("+01:00")) + } + + fn dst(&self, py: Python, dt: &PyDateTime) -> PyResult> { + Ok(None) + } +} + #[pymodinit] fn datetime(_py: Python, m: &PyModule) -> PyResult<()> { m.add_function(wrap_function!(make_date))?; @@ -209,5 +232,6 @@ fn datetime(_py: Python, m: &PyModule) -> PyResult<()> { m.add_function(wrap_function!(issue_219))?; + m.add_class::()?; Ok(()) } diff --git a/examples/rustapi_module/tests/test_datetime.py b/examples/rustapi_module/tests/test_datetime.py index f41d5213..6d2eaebc 100644 --- a/examples/rustapi_module/tests/test_datetime.py +++ b/examples/rustapi_module/tests/test_datetime.py @@ -3,8 +3,7 @@ import rustapi_module.datetime as rdt import sys import datetime as pdt -import pytest - +import pytest from hypothesis import given from hypothesis import strategies as st from hypothesis.strategies import dates, datetimes @@ -263,3 +262,12 @@ def test_delta_err(args, err_type): def test_issue_219(): rdt.issue_219() + +def test_tz_class(): + tzi = rdt.TzClass() + + dt = pdt.datetime(2018, 1, 1, tzinfo=tzi) + + assert dt.tzname() == "+01:00" + assert dt.utcoffset() == pdt.timedelta(hours=1) + assert dt.dst() is None From f12e299f1cb5d2ec814e8080fde7fe4117344367 Mon Sep 17 00:00:00 2001 From: kngwyu Date: Fri, 28 Sep 2018 11:49:36 +0900 Subject: [PATCH 2/2] Remove PyDateTime_*Types --- src/ffi/datetime.rs | 12 +----------- src/types/datetime.rs | 16 ++++++---------- 2 files changed, 7 insertions(+), 21 deletions(-) diff --git a/src/ffi/datetime.rs b/src/ffi/datetime.rs index 6cc01762..7232302c 100644 --- a/src/ffi/datetime.rs +++ b/src/ffi/datetime.rs @@ -1,4 +1,4 @@ -#![cfg_attr(feature="cargo-clippy", allow(type_complexity))] +#![cfg_attr(feature = "cargo-clippy", allow(type_complexity))] use ffi::PyCapsule_Import; use ffi::Py_hash_t; @@ -10,16 +10,6 @@ use std::os::raw::{c_char, c_int, c_uchar}; use std::ptr; use std::sync::Once; -#[cfg_attr(windows, link(name = "pythonXY"))] -extern "C" { - pub static mut PyDateTime_DateType: PyTypeObject; - pub static mut PyDateTime_TimeType: PyTypeObject; - pub static mut PyDateTime_DateTimeType: PyTypeObject; - - pub static mut PyDateTime_DeltaType: PyTypeObject; - pub static mut PyDateTime_TZInfoType: PyTypeObject; -} - #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct PyDateTime_CAPI { diff --git a/src/types/datetime.rs b/src/types/datetime.rs index a4cc39cb..41f51565 100644 --- a/src/types/datetime.rs +++ b/src/types/datetime.rs @@ -2,7 +2,7 @@ use conversion::ToPyObject; use err::PyResult; use ffi; use ffi::PyDateTimeAPI; -use ffi::{PyDateTime_Check, PyDateTime_DateTimeType}; +use ffi::{PyDateTime_Check, PyDate_Check, PyDelta_Check, PyTZInfo_Check, PyTime_Check}; #[cfg(Py_3_6)] use ffi::{PyDateTime_DATE_GET_FOLD, PyDateTime_TIME_GET_FOLD}; use ffi::{ @@ -12,15 +12,11 @@ use ffi::{ use ffi::{ PyDateTime_DELTA_GET_DAYS, PyDateTime_DELTA_GET_MICROSECONDS, PyDateTime_DELTA_GET_SECONDS, }; -use ffi::{PyDateTime_DateType, PyDate_Check}; -use ffi::{PyDateTime_DeltaType, PyDelta_Check}; use ffi::{PyDateTime_GET_DAY, PyDateTime_GET_MONTH, PyDateTime_GET_YEAR}; use ffi::{ PyDateTime_TIME_GET_HOUR, PyDateTime_TIME_GET_MICROSECOND, PyDateTime_TIME_GET_MINUTE, PyDateTime_TIME_GET_SECOND, }; -use ffi::{PyDateTime_TZInfoType, PyTZInfo_Check}; -use ffi::{PyDateTime_TimeType, PyTime_Check}; use instance::Py; use object::PyObject; use python::{Python, ToPyPointer}; @@ -52,7 +48,7 @@ pub trait PyTimeAccess { // datetime.date bindings pub struct PyDate(PyObject); -pyobject_native_type!(PyDate, PyDateTime_DateType, PyDate_Check); +pyobject_native_type!(PyDate, *PyDateTimeAPI.DateType, PyDate_Check); impl PyDate { pub fn new(py: Python, year: i32, month: u8, day: u8) -> PyResult> { @@ -93,7 +89,7 @@ impl PyDateAccess for PyDate { // datetime.datetime bindings pub struct PyDateTime(PyObject); -pyobject_native_type!(PyDateTime, PyDateTime_DateTimeType, PyDateTime_Check); +pyobject_native_type!(PyDateTime, *PyDateTimeAPI.DateTimeType, PyDateTime_Check); impl PyDateTime { pub fn new( @@ -187,7 +183,7 @@ impl PyTimeAccess for PyDateTime { // datetime.time pub struct PyTime(PyObject); -pyobject_native_type!(PyTime, PyDateTime_TimeType, PyTime_Check); +pyobject_native_type!(PyTime, *PyDateTimeAPI.TimeType, PyTime_Check); impl PyTime { pub fn new( @@ -261,11 +257,11 @@ impl PyTimeAccess for PyTime { // datetime.tzinfo bindings pub struct PyTzInfo(PyObject); -pyobject_native_type!(PyTzInfo, PyDateTime_TZInfoType, PyTZInfo_Check); +pyobject_native_type!(PyTzInfo, *PyDateTimeAPI.TZInfoType, PyTZInfo_Check); // datetime.timedelta bindings pub struct PyDelta(PyObject); -pyobject_native_type!(PyDelta, PyDateTime_DeltaType, PyDelta_Check); +pyobject_native_type!(PyDelta, *PyDateTimeAPI.DeltaType, PyDelta_Check); impl PyDelta { pub fn new(