From ab1b124253e36a8a5a16808c8294eda885cf546a Mon Sep 17 00:00:00 2001 From: Arie Bovenberg Date: Sun, 17 Nov 2024 19:31:20 +0100 Subject: [PATCH] fix final issues in PR --- CHANGELOG.rst | 6 +++--- README.md | 5 ++--- pysrc/whenever/_pywhenever.py | 3 +-- src/common.rs | 2 +- src/instant.rs | 5 +++-- src/local_datetime.rs | 4 ++-- src/offset_datetime.rs | 6 +++--- src/zoned_datetime.rs | 2 +- tests/test_date.py | 2 +- tests/test_instant.py | 1 - 10 files changed, 17 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 0c464b0..e64ee73 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,14 +1,14 @@ 🚀 Changelog ============ -0.6.13 (2024-11-16) +0.6.13 (2024-11-17) ------------------- **Added** - Make ``from_py_datetime()`` on ``Instant``/``OffsetDateTime`` less pedantic. - It now accepts any aware datetime -- ``Date.today_in_system_tz()`` convenience method + They now accept any aware datetime +- New ``Date.today_in_system_tz()`` convenience method **Fixed** diff --git a/README.md b/README.md index 441d08e..8f5e5b6 100644 --- a/README.md +++ b/README.md @@ -181,13 +181,12 @@ or [API reference](https://whenever.readthedocs.io/en/latest/api.html). - ✅ Deltas - ✅ Date and time of day (separate from datetime) - ✅ Implement Rust extension for performance + - 🚧 Tweaks to the delta API - 🔒 **1.0**: API stability and backwards compatibility - - 🚧 Improved parsing and formatting + - 🚧 Customizable parsing and formatting - 🚧 Intervals - 🚧 Ranges and recurring times - 🚧 Parsing leap seconds - - 🚧 More helpful error messages - ## Limitations diff --git a/pysrc/whenever/_pywhenever.py b/pysrc/whenever/_pywhenever.py index 15be951..04fcb51 100644 --- a/pysrc/whenever/_pywhenever.py +++ b/pysrc/whenever/_pywhenever.py @@ -193,7 +193,7 @@ def today_in_system_tz() -> Date: Date(2021-01-02) """ # Use now() so this function gets patched like the other now functions - return Instant.now().to_system_tz().date() + return SystemDateTime.now().date() @property def year(self) -> int: @@ -5307,7 +5307,6 @@ def _load_offset(offset: int | TimeDelta, /) -> _timezone: _fromisoformat = _datetime.fromisoformat _fromtimestamp = _datetime.fromtimestamp _DT_RE_GROUPED = r"(\d{4})-([0-2]\d)-([0-3]\d)T([0-2]\d):([0-5]\d):([0-5]\d)(?:\.(\d{1,9}))?" -# TODO: check correct of incorrect offset 13:90 _OFFSET_DATETIME_RE = ( _DT_RE_GROUPED + r"(?:([+-])([0-2]\d):([0-5]\d)(?::([0-5]\d))?|Z)" ) diff --git a/src/common.rs b/src/common.rs index b549115..de66f81 100644 --- a/src/common.rs +++ b/src/common.rs @@ -1073,7 +1073,7 @@ unsafe fn getattr_tzinfo_unchecked(dt: *mut PyObject) -> *mut PyObject { } #[inline] -pub(crate) unsafe fn get_dt_tzinfo(dt: *mut PyObject) -> *mut PyObject { +pub(crate) unsafe fn borrow_dt_tzinfo(dt: *mut PyObject) -> *mut PyObject { #[cfg(Py_3_10)] { PyDateTime_DATE_GET_TZINFO(dt) diff --git a/src/instant.rs b/src/instant.rs index d20ddff..2ec8560 100644 --- a/src/instant.rs +++ b/src/instant.rs @@ -231,7 +231,7 @@ impl Instant { } unsafe fn from_py(dt: *mut PyObject, state: &State) -> PyResult> { - let tzinfo = get_dt_tzinfo(dt); + let tzinfo = borrow_dt_tzinfo(dt); if is_none(tzinfo) { Err(value_err!("datetime cannot be naive"))?; }; @@ -253,6 +253,7 @@ impl Instant { Some(inst) } else { let delta = methcall1(tzinfo, "utcoffset", dt)?; + defer_decref!(delta); if is_none(delta) { Err(value_err!("datetime utcoffset() is None"))?; } @@ -790,7 +791,7 @@ unsafe fn parse_rfc2822(cls: *mut PyObject, s_obj: *mut PyObject) -> PyReturn { dt = call1(state.parse_rfc2822, s_obj)?; } defer_decref!(dt); - let tzinfo = get_dt_tzinfo(dt); + let tzinfo = borrow_dt_tzinfo(dt); if tzinfo == state.py_api.TimeZone_UTC || (is_none(tzinfo) && s_obj.to_str()?.unwrap().contains("-0000")) { diff --git a/src/local_datetime.rs b/src/local_datetime.rs index c4ad2f5..4416797 100644 --- a/src/local_datetime.rs +++ b/src/local_datetime.rs @@ -568,7 +568,7 @@ unsafe fn from_py_datetime(type_: *mut PyObject, dt: *mut PyObject) -> PyReturn if PyDateTime_Check(dt) == 0 { Err(type_err!("argument must be datetime.datetime"))? } - let tzinfo = get_dt_tzinfo(dt); + let tzinfo = borrow_dt_tzinfo(dt); if !is_none(tzinfo) { Err(value_err!( "datetime must be naive, but got tzinfo={}", @@ -669,7 +669,7 @@ unsafe fn strptime(cls: *mut PyObject, args: &[*mut PyObject]) -> PyReturn { ) .as_result()?; defer_decref!(parsed); - let tzinfo = get_dt_tzinfo(parsed); + let tzinfo = borrow_dt_tzinfo(parsed); if !is_none(tzinfo) { Err(value_err!( "datetime must be naive, but got tzinfo={}", diff --git a/src/offset_datetime.rs b/src/offset_datetime.rs index 5fd8a71..e5f10ef 100644 --- a/src/offset_datetime.rs +++ b/src/offset_datetime.rs @@ -129,7 +129,7 @@ impl OffsetDateTime { // Returns None if the tzinfo is incorrect, or the UTC time is out of bounds pub(crate) unsafe fn from_py(dt: *mut PyObject, state: &State) -> PyResult> { debug_assert!(PyObject_IsInstance(dt, state.py_api.DateTimeType.cast()).is_positive()); - if is_none(get_dt_tzinfo(dt)) { + if is_none(borrow_dt_tzinfo(dt)) { Err(value_err!("Datetime cannot be naive"))? } Ok(OffsetDateTime::new( @@ -1086,7 +1086,7 @@ unsafe fn parse_rfc2822(cls: *mut PyObject, s_obj: *mut PyObject) -> PyReturn { let state = State::for_type(cls.cast()); let py_dt = call1(state.parse_rfc2822, s_obj)?; defer_decref!(py_dt); - if is_none(get_dt_tzinfo(py_dt)) { + if is_none(borrow_dt_tzinfo(py_dt)) { Err(value_err!( "parsed datetime must have a timezone, got {}", s_obj.repr() @@ -1119,7 +1119,7 @@ unsafe fn parse_rfc2822(cls: *mut PyObject, s_obj: *mut PyObject) -> PyReturn { } })?; defer_decref!(py_dt); - if is_none(get_dt_tzinfo(py_dt)) { + if is_none(borrow_dt_tzinfo(py_dt)) { Err(value_err!( "parsed datetime must have a timezone, got {}", s_obj.repr() diff --git a/src/zoned_datetime.rs b/src/zoned_datetime.rs index 77237a6..1bbb399 100644 --- a/src/zoned_datetime.rs +++ b/src/zoned_datetime.rs @@ -797,7 +797,7 @@ unsafe fn from_py_datetime(cls: *mut PyObject, dt: *mut PyObject) -> PyReturn { if PyDateTime_Check(dt) == 0 { Err(type_err!("Argument must be a datetime.datetime instance"))?; } - let tzinfo = get_dt_tzinfo(dt); + let tzinfo = borrow_dt_tzinfo(dt); // NOTE: it has to be exactly a `ZoneInfo`, since subclasses // could theoretically introduce circular references. diff --git a/tests/test_date.py b/tests/test_date.py index 6e5c003..6a37fd1 100644 --- a/tests/test_date.py +++ b/tests/test_date.py @@ -148,7 +148,7 @@ def test_py_date(): def test_today_in_system_tz(): d = Date.today_in_system_tz() # NOTE: this may fail if the test is run *exactly* at midnight. - # Macking this out would make things more complicated than it's worth. + # Mocking this out would make things more complicated than it's worth. assert d == Date.from_py_date(py_date.today()) diff --git a/tests/test_instant.py b/tests/test_instant.py index 5420698..31902ee 100644 --- a/tests/test_instant.py +++ b/tests/test_instant.py @@ -895,7 +895,6 @@ def test_format_rfc3339(): ).format_rfc3339() == "2020-08-15 23:12:09.00000045Z" ) - Instant.now().format_rfc3339 class TestParseRFC3339: