Skip to content

Commit

Permalink
Add pyo3 integration
Browse files Browse the repository at this point in the history
  • Loading branch information
pickfire committed Mar 7, 2021
1 parent 3467172 commit 543a827
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 2 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ num-traits = { version = "0.2", default-features = false }
rustc-serialize = { version = "0.3.20", optional = true }
serde = { version = "1.0.99", default-features = false, optional = true }
pure-rust-locales = { version = "0.5.2", optional = true }
pyo3 = { version = "0.13.2", optional = true }

[target.'cfg(all(target_arch = "wasm32", not(any(target_os = "emscripten", target_os = "wasi"))))'.dependencies]
wasm-bindgen = { version = "0.2", optional = true }
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ test:

.PHONY: doc
doc: authors readme
cargo doc --features 'serde rustc-serialize bincode'
cargo doc --features 'serde rustc-serialize bincode pyo3'
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,13 @@ Optional features:

- `wasmbind`: Enable integration with [wasm-bindgen][] and its `js-sys` project
- [`serde`][]: Enable serialization/deserialization via serde.
- [`pyo3`][]: Enable integration with pyo3.
- `unstable-locales`: Enable localization. This adds various methods with a
`_localized` suffix. The implementation and API may change or even be
removed in a patch release. Feedback welcome.

[`serde`]: https://github.com/serde-rs/serde
[`pyo3`]: https://github.com/PyO3/pyo3
[wasm-bindgen]: https://github.com/rustwasm/wasm-bindgen

See the [cargo docs][] for examples of specifying features.
Expand Down
2 changes: 1 addition & 1 deletion ci/github.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ set -euo pipefail
source "${BASH_SOURCE[0]%/*}/_shlib.sh"

TEST_TZS=(ACST-9:30 EST4 UTC0 Asia/Katmandu)
FEATURES=(std serde clock "alloc serde" unstable-locales)
FEATURES=(std serde clock "alloc serde" unstable-locales pyo3)
CHECK_FEATURES=(alloc "std unstable-locales" "serde clock" "clock unstable-locales")
RUST_113_FEATURES=(rustc-serialize serde)

Expand Down
4 changes: 4 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,13 @@
//!
//! - `wasmbind`: Enable integration with [wasm-bindgen][] and its `js-sys` project
//! - [`serde`][]: Enable serialization/deserialization via serde.
//! - [`pyo3`][]: Enable integration with pyo3.
//! - `unstable-locales`: Enable localization. This adds various methods with a
//! `_localized` suffix. The implementation and API may change or even be
//! removed in a patch release. Feedback welcome.
//!
//! [`serde`]: https://github.com/serde-rs/serde
//! [`pyo3`]: https://github.com/PyO3/pyo3
//! [wasm-bindgen]: https://github.com/rustwasm/wasm-bindgen
//!
//! See the [cargo docs][] for examples of specifying features.
Expand Down Expand Up @@ -486,6 +488,8 @@ extern crate doc_comment;
extern crate js_sys;
#[cfg(feature = "unstable-locales")]
extern crate pure_rust_locales;
#[cfg(feature = "pyo3")]
extern crate pyo3;
#[cfg(feature = "bench")]
extern crate test;
#[cfg(all(target_arch = "wasm32", not(target_os = "wasi"), feature = "wasmbind"))]
Expand Down
59 changes: 59 additions & 0 deletions src/naive/date.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1901,6 +1901,65 @@ mod serde {
}
}

#[cfg(feature = "pyo3")]
mod pyo3 {
use super::{Datelike, NaiveDate};
use pyo3::conversion::{FromPyObject, ToPyObject};
use pyo3::types::{PyDate, PyDateAccess};

impl ToPyObject for NaiveDate {
fn to_object(&self, py: pyo3::Python) -> pyo3::PyObject {
let mdf = self.mdf();
let date = PyDate::new(py, self.year(), mdf.month() as u8, mdf.day() as u8)
.expect("Failed to construct date");
date.into()
}
}

impl FromPyObject<'_> for NaiveDate {
fn extract(ob: &pyo3::PyAny) -> pyo3::PyResult<Self> {
let date: &PyDate = ob.downcast()?;
Ok(NaiveDate::from_ymd(date.get_year(), date.get_month() as u32, date.get_day() as u32))
}
}

#[test]
fn test_pyo3_topyobject() {
use std::cmp::Ordering;

let gil = pyo3::Python::acquire_gil();
let py = gil.python();
let eq_ymd = |y, m, d| {
let date = NaiveDate::from_ymd(y, m, d).to_object(py);
let date: &PyDate = date.extract(py).unwrap();
let py_date = PyDate::new(py, y, m as u8, d as u8).unwrap();
assert_eq!(date.compare(py_date).unwrap(), Ordering::Equal);
};

eq_ymd(2012, 2, 29);
eq_ymd(1, 1, 1); // min
eq_ymd(3000, 6, 5); // future
eq_ymd(9999, 12, 31); // max
}

#[test]
fn test_pyo3_frompyobject() {
let gil = pyo3::Python::acquire_gil();
let py = gil.python();
let eq_ymd = |y, m, d| {
let py_date = PyDate::new(py, y, m as u8, d as u8).unwrap();
let py_date: NaiveDate = py_date.extract().unwrap();
let date = NaiveDate::from_ymd(y, m, d);
assert_eq!(py_date, date);
};

eq_ymd(2012, 2, 29);
eq_ymd(1, 1, 1); // min
eq_ymd(3000, 6, 5); // future
eq_ymd(9999, 12, 31); // max
}
}

#[cfg(test)]
mod tests {
use super::NaiveDate;
Expand Down

0 comments on commit 543a827

Please sign in to comment.