diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 1e20ee1b..1119bc7b 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -16,12 +16,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - [[package]] name = "cc" version = "1.0.79" @@ -34,11 +28,17 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "indoc" -version = "1.0.9" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa799dd5ed20a7e349f3b4639aa80d74549c81716d9ec4f994c9b5815598306" +checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" [[package]] name = "libc" @@ -56,16 +56,6 @@ dependencies = [ "libc", ] -[[package]] -name = "lock_api" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" -dependencies = [ - "autocfg", - "scopeguard", -] - [[package]] name = "memoffset" version = "0.9.0" @@ -91,48 +81,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] -name = "parking_lot" -version = "0.12.1" +name = "portable-atomic" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-sys", -] +checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" [[package]] name = "proc-macro2" -version = "1.0.51" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" dependencies = [ "unicode-ident", ] [[package]] name = "pyo3" -version = "0.19.1" +version = "0.22.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb88ae05f306b4bfcde40ac4a51dc0b05936a9207a4b75b798c7729c4258a59" +checksum = "f402062616ab18202ae8319da13fa4279883a2b8a9d9f83f20dbade813ce1884" dependencies = [ "cfg-if", "indoc", "libc", "memoffset", - "parking_lot", + "once_cell", + "portable-atomic", "pyo3-build-config", "pyo3-ffi", "pyo3-macros", @@ -141,9 +115,9 @@ dependencies = [ [[package]] name = "pyo3-build-config" -version = "0.19.1" +version = "0.22.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "554db24f0b3c180a9c0b1268f91287ab3f17c162e15b54caaae5a6b3773396b0" +checksum = "b14b5775b5ff446dd1056212d778012cbe8a0fbffd368029fd9e25b514479c38" dependencies = [ "once_cell", "python3-dll-a", @@ -152,9 +126,9 @@ dependencies = [ [[package]] name = "pyo3-ffi" -version = "0.19.1" +version = "0.22.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "922ede8759e8600ad4da3195ae41259654b9c55da4f7eec84a0ccc7d067a70a4" +checksum = "9ab5bcf04a2cdcbb50c7d6105de943f543f9ed92af55818fd17b660390fc8636" dependencies = [ "libc", "pyo3-build-config", @@ -162,9 +136,9 @@ dependencies = [ [[package]] name = "pyo3-macros" -version = "0.19.1" +version = "0.22.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a5caec6a1dd355964a841fcbeeb1b89fe4146c87295573f94228911af3cc5a2" +checksum = "0fd24d897903a9e6d80b968368a34e1525aeb719d568dba8b3d4bfa5dc67d453" dependencies = [ "proc-macro2", "pyo3-macros-backend", @@ -174,11 +148,13 @@ dependencies = [ [[package]] name = "pyo3-macros-backend" -version = "0.19.1" +version = "0.22.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0b78ccbb160db1556cdb6fd96c50334c5d4ec44dc5e0a968d0a1208fa0efa8b" +checksum = "36c011a03ba1e50152b4b394b479826cad97e7a21eb52df179cd91ac411cbfbe" dependencies = [ + "heck", "proc-macro2", + "pyo3-build-config", "quote", "syn", ] @@ -194,39 +170,18 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.23" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags", -] - -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - -[[package]] -name = "smallvec" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" - [[package]] name = "syn" -version = "1.0.109" +version = "2.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" dependencies = [ "proc-macro2", "quote", @@ -235,9 +190,9 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.12.6" +version = "0.12.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae9980cab1db3fceee2f6c6f643d5d8de2997c58ee8d25fb0cc8a9e9e7348e5" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "unicode-ident" @@ -247,72 +202,6 @@ checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" [[package]] name = "unindent" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1766d682d402817b5ac4490b3c3002d91dfa0d22812f341609f97b08757359c" - -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.42.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" - -[[package]] -name = "windows_i686_gnu" -version = "0.42.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" +checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce" diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 0d76a89f..31f55dc1 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -14,7 +14,7 @@ strip = true overflow-checks = false [dependencies] -pyo3 = { version = "0.19.0", features = ["extension-module", "generate-import-lib"] } +pyo3 = { version = "0.22", features = ["extension-module", "generate-import-lib"] } mimalloc = { version = "0.1.39", optional = true, default-features = false } [features] diff --git a/rust/src/python/helpers.rs b/rust/src/python/helpers.rs index 4a53e595..f4523426 100644 --- a/rust/src/python/helpers.rs +++ b/rust/src/python/helpers.rs @@ -1,7 +1,6 @@ use std::cmp::Ordering; use pyo3::{ - intern, prelude::*, types::{PyDate, PyDateAccess, PyDateTime, PyDelta, PyDeltaAccess, PyString, PyTimeAccess}, PyTypeInfo, @@ -74,57 +73,41 @@ impl PartialOrd for DateTimeInfo<'_> { } } -pub fn get_tz_name<'py>(py: Python, dt: &'py PyAny) -> PyResult<&'py str> { - let tz: &str = ""; +pub fn get_tz_name<'py>(dt: &Bound<'py, PyAny>) -> PyResult { + // let tz: &str = ""; - if !PyDateTime::is_type_of(dt) { - return Ok(tz); + if !PyDateTime::is_type_of_bound(dt) { + return Ok(String::new()); } - let tzinfo = dt.getattr("tzinfo"); + let tzinfo: Bound<'py, PyAny> = dt.getattr("tzinfo")?; - match tzinfo { - Err(_) => Ok(tz), - Ok(tzinfo) => { - if tzinfo.is_none() { - return Ok(tz); - } - if tzinfo.hasattr(intern!(py, "key")).unwrap_or(false) { - // zoneinfo timezone - let tzname: &PyString = tzinfo - .getattr(intern!(py, "key")) - .unwrap() - .downcast() - .unwrap(); - - return tzname.to_str(); - } else if tzinfo.hasattr(intern!(py, "name")).unwrap_or(false) { - // Pendulum timezone - let tzname: &PyString = tzinfo - .getattr(intern!(py, "name")) - .unwrap() - .downcast() - .unwrap(); - - return tzname.to_str(); - } else if tzinfo.hasattr(intern!(py, "zone")).unwrap_or(false) { - // pytz timezone - let tzname: &PyString = tzinfo - .getattr(intern!(py, "zone")) - .unwrap() - .downcast() - .unwrap(); - - return tzname.to_str(); - } + if tzinfo.is_none() { + return Ok(String::new()); + } - Ok(tz) - } + let tzname_attr: Option>; + + if tzinfo.hasattr("key")? { + tzname_attr = Some(tzinfo.getattr("key")?); + } else if tzinfo.hasattr("name")? { + tzname_attr = Some(tzinfo.getattr("name")?); + } else if tzinfo.hasattr("zone")? { + tzname_attr = Some(tzinfo.getattr("zone")?); + } else { + tzname_attr = None; + } + + if let Some(tzname_attr) = tzname_attr { + let tzname: &Bound = tzname_attr.downcast()?; + tzname.extract() + } else { + Ok(String::new()) } } -pub fn get_offset(dt: &PyAny) -> PyResult { - if !PyDateTime::is_type_of(dt) { +pub fn get_offset(dt: &Bound) -> PyResult { + if !PyDateTime::is_type_of_bound(dt) { return Ok(0); } @@ -133,8 +116,8 @@ pub fn get_offset(dt: &PyAny) -> PyResult { if tzinfo.is_none() { return Ok(0); } - - let offset: &PyDelta = tzinfo.call_method1("utcoffset", (dt,))?.downcast()?; + let binding = tzinfo.call_method1("utcoffset", (dt,))?; + let offset: &Bound = binding.downcast()?; Ok(offset.get_days() * SECS_PER_DAY as i32 + offset.get_seconds()) } @@ -169,8 +152,13 @@ pub fn local_time( } #[pyfunction] -pub fn precise_diff<'py>(py: Python, dt1: &'py PyAny, dt2: &'py PyAny) -> PyResult { +pub fn precise_diff<'py>( + dt1: &Bound<'py, PyAny>, + dt2: &Bound<'py, PyAny>, +) -> PyResult { let mut sign = 1; + let dt1_tz = get_tz_name(dt1)?; + let dt2_tz = get_tz_name(dt2)?; let mut dtinfo1 = DateTimeInfo { year: dt1.downcast::()?.get_year(), month: i32::from(dt1.downcast::()?.get_month()), @@ -180,9 +168,9 @@ pub fn precise_diff<'py>(py: Python, dt1: &'py PyAny, dt2: &'py PyAny) -> PyResu second: 0, microsecond: 0, total_seconds: 0, - tz: get_tz_name(py, dt1)?, + tz: dt1_tz.as_str(), offset: get_offset(dt1)?, - is_datetime: PyDateTime::is_type_of(dt1), + is_datetime: PyDateTime::is_type_of_bound(dt1), }; let mut dtinfo2 = DateTimeInfo { year: dt2.downcast::()?.get_year(), @@ -193,16 +181,16 @@ pub fn precise_diff<'py>(py: Python, dt1: &'py PyAny, dt2: &'py PyAny) -> PyResu second: 0, microsecond: 0, total_seconds: 0, - tz: get_tz_name(py, dt2)?, + tz: dt2_tz.as_str(), offset: get_offset(dt2)?, - is_datetime: PyDateTime::is_type_of(dt2), + is_datetime: PyDateTime::is_exact_type_of_bound(dt2), }; let in_same_tz: bool = dtinfo1.tz == dtinfo2.tz && !dtinfo1.tz.is_empty(); let mut total_days = helpers::day_number(dtinfo2.year, dtinfo2.month as u8, dtinfo2.day as u8) - helpers::day_number(dtinfo1.year, dtinfo1.month as u8, dtinfo1.day as u8); if dtinfo1.is_datetime { - let dt1dt: &PyDateTime = dt1.downcast()?; + let dt1dt: &Bound = dt1.downcast()?; dtinfo1.hour = i32::from(dt1dt.get_hour()); dtinfo1.minute = i32::from(dt1dt.get_minute()); @@ -247,7 +235,7 @@ pub fn precise_diff<'py>(py: Python, dt1: &'py PyAny, dt2: &'py PyAny) -> PyResu } if dtinfo2.is_datetime { - let dt2dt: &PyDateTime = dt2.downcast()?; + let dt2dt: &Bound = dt2.downcast()?; dtinfo2.hour = i32::from(dt2dt.get_hour()); dtinfo2.minute = i32::from(dt2dt.get_minute()); diff --git a/rust/src/python/mod.rs b/rust/src/python/mod.rs index 8d3cd41a..d62e45dc 100644 --- a/rust/src/python/mod.rs +++ b/rust/src/python/mod.rs @@ -9,7 +9,7 @@ use parsing::parse_iso8601; use types::{Duration, PreciseDiff}; #[pymodule] -pub fn _pendulum(_py: Python<'_>, m: &PyModule) -> PyResult<()> { +pub fn _pendulum(_py: Python<'_>, m: &Bound) -> PyResult<()> { m.add_function(wrap_pyfunction!(days_in_year, m)?)?; m.add_function(wrap_pyfunction!(is_leap, m)?)?; m.add_function(wrap_pyfunction!(is_long_year, m)?)?; diff --git a/rust/src/python/parsing.rs b/rust/src/python/parsing.rs index 48fa64c9..cff608e5 100644 --- a/rust/src/python/parsing.rs +++ b/rust/src/python/parsing.rs @@ -16,7 +16,7 @@ pub fn parse_iso8601(py: Python, input: &str) -> PyResult { (Some(datetime), None, None) => match (datetime.has_date, datetime.has_time) { (true, true) => match datetime.offset { Some(offset) => { - let dt = PyDateTime::new( + let dt = PyDateTime::new_bound( py, datetime.year as i32, datetime.month as u8, @@ -28,14 +28,14 @@ pub fn parse_iso8601(py: Python, input: &str) -> PyResult { Some( Py::new(py, FixedTimezone::new(offset, datetime.tzname))? .to_object(py) - .extract(py)?, + .downcast_bound(py)?, ), )?; Ok(dt.to_object(py)) } None => { - let dt = PyDateTime::new( + let dt = PyDateTime::new_bound( py, datetime.year as i32, datetime.month as u8, @@ -51,7 +51,7 @@ pub fn parse_iso8601(py: Python, input: &str) -> PyResult { } }, (true, false) => { - let dt = PyDate::new( + let dt = PyDate::new_bound( py, datetime.year as i32, datetime.month as u8, @@ -62,7 +62,7 @@ pub fn parse_iso8601(py: Python, input: &str) -> PyResult { } (false, true) => match datetime.offset { Some(offset) => { - let dt = PyTime::new( + let dt = PyTime::new_bound( py, datetime.hour as u8, datetime.minute as u8, @@ -71,14 +71,14 @@ pub fn parse_iso8601(py: Python, input: &str) -> PyResult { Some( Py::new(py, FixedTimezone::new(offset, datetime.tzname))? .to_object(py) - .extract(py)?, + .downcast_bound(py)?, ), )?; Ok(dt.to_object(py)) } None => { - let dt = PyTime::new( + let dt = PyTime::new_bound( py, datetime.hour as u8, datetime.minute as u8, diff --git a/rust/src/python/types/timezone.rs b/rust/src/python/types/timezone.rs index 1a8bbade..58012710 100644 --- a/rust/src/python/types/timezone.rs +++ b/rust/src/python/types/timezone.rs @@ -11,20 +11,29 @@ pub struct FixedTimezone { #[pymethods] impl FixedTimezone { #[new] + #[pyo3(signature = (offset, name=None))] pub fn new(offset: i32, name: Option) -> Self { Self { offset, name } } - fn utcoffset<'p>(&self, py: Python<'p>, _dt: &PyAny) -> PyResult<&'p PyDelta> { - PyDelta::new(py, 0, self.offset, 0, true) + fn utcoffset<'p>( + &self, + py: Python<'p>, + _dt: &Bound<'p, PyAny>, + ) -> Result, PyErr> { + PyDelta::new_bound(py, 0, self.offset, 0, true) } - fn tzname(&self, _dt: &PyAny) -> String { + fn tzname(&self, _dt: &Bound) -> String { self.__str__() } - fn dst<'p>(&self, py: Python<'p>, _dt: &PyAny) -> PyResult<&'p PyDelta> { - PyDelta::new(py, 0, 0, 0, true) + fn dst<'p>( + &self, + py: Python<'p>, + _dt: &Bound<'p, PyAny>, + ) -> Result, PyErr> { + PyDelta::new_bound(py, 0, 0, 0, true) } fn __repr__(&self) -> String { @@ -46,7 +55,7 @@ impl FixedTimezone { } } - fn __deepcopy__(&self, py: Python, _memo: &PyDict) -> PyResult> { + fn __deepcopy__(&self, py: Python, _memo: &Bound) -> PyResult> { Py::new(py, self.clone()) } }