From 02064e81c50a5f6de00bfc2fc75675197e889650 Mon Sep 17 00:00:00 2001 From: Sarah Hoffmann Date: Tue, 26 Aug 2025 15:55:12 +0200 Subject: [PATCH 1/2] make Timestamp casting thread-safe Avoid gmtime and use Python's own methos instead. --- lib/cast.h | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/lib/cast.h b/lib/cast.h index 4ff547ff..ac719449 100644 --- a/lib/cast.h +++ b/lib/cast.h @@ -2,14 +2,13 @@ * * This file is part of pyosmium. (https://osmcode.org/pyosmium/) * - * Copyright (C) 2024 Sarah Hoffmann and others. + * Copyright (C) 2025 Sarah Hoffmann and others. * For a full list of authors see the git log. */ #ifndef PYOSMIUM_CAST_H #define PYOSMIUM_CAST_H #include -#include #include #include @@ -44,25 +43,14 @@ namespace pybind11 { namespace detail { static handle cast(type const &src, return_value_policy, handle) { - using namespace std::chrono; // Lazy initialise the PyDateTime import if (!PyDateTimeAPI) { PyDateTime_IMPORT; } std::time_t tt = src.seconds_since_epoch(); - std::tm localtime = *std::gmtime(&tt); - handle pydate = PyDateTime_FromDateAndTime(localtime.tm_year + 1900, - localtime.tm_mon + 1, - localtime.tm_mday, - localtime.tm_hour, - localtime.tm_min, - localtime.tm_sec, - 0); static auto utc = module::import("datetime").attr("timezone").attr("utc"); - using namespace literals; - handle with_utc = pydate.attr("replace")("tzinfo"_a=utc).inc_ref(); - pydate.dec_ref(); - return with_utc; + + return PyDateTime_FromTimestamp(pybind11::make_tuple(tt, utc).ptr()); } PYBIND11_TYPE_CASTER(type, _("datetime.datetime")); From 11ab6069f562a679c98784d162569b60053766da Mon Sep 17 00:00:00 2001 From: Sarah Hoffmann Date: Mon, 25 Aug 2025 18:49:59 +0200 Subject: [PATCH 2/2] fix test for changeset times --- test/test_osm.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test_osm.py b/test/test_osm.py index 6603c30b..967c3805 100644 --- a/test/test_osm.py +++ b/test/test_osm.py @@ -304,14 +304,14 @@ def area(o): area=area) -def test_changest_attributes(area_importer): +def test_changeset_attributes(area_importer): def changeset(c): assert 34 == c.id assert 1 == c.uid assert not c.user_is_anonymous() assert "Steve" == c.user - assert mkdate(2005, 4, 9, 19, 54, 13), c.created_at - assert mkdate(2005, 4, 9, 20, 54, 39), c.closed_at + assert mkdate(2005, 4, 9, 19, 54, 13) == c.created_at + assert mkdate(2005, 4, 9, 20, 54, 39) == c.closed_at assert not c.open assert 2 == c.num_changes assert 0 == len(c.tags)