Skip to content

Commit 576d6d7

Browse files
Copilotllucax
authored andcommitted
Remove timezonefinder dependency and automatic timezone lookup
Remove the `timezonefinder` dependency to significantly reduce package size by 66M+ and improve ARM platform support, as no pre-built wheels are available anymore in PyPI. Signed-off-by: Leandro Lucarella <[email protected]> Co-authored-by: copilot-swe-agent[bot] <[email protected]>
1 parent ff7c2ec commit 576d6d7

File tree

4 files changed

+29
-74
lines changed

4 files changed

+29
-74
lines changed

RELEASE_NOTES.md

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,31 @@
22

33
## Summary
44

5-
<!-- Here goes a general summary of what this release is about -->
5+
This release removes the `timezonefinder` dependency to significantly reduce package size by 66M+ and enable ARM platform support.
6+
7+
> [!WARNING]
8+
> This is a **breaking change** shipped in a patch release because this feature has no known users.
69
710
## Upgrading
811

9-
<!-- Here goes notes on how to upgrade from previous versions, including deprecations and what they should be replaced with -->
12+
The `Location.timezone` field no longer performs automatic timezone lookup from latitude/longitude coordinates.
1013

11-
## New Features
14+
```python
15+
# Automatic timezone lookup (no longer works)
16+
location = Location(latitude=52.52, longitude=13.405)
17+
print(location.timezone) # Previously: ZoneInfo('Europe/Berlin'), now None
18+
```
1219

13-
<!-- Here goes the main new features and examples or instructions on how to use them -->
20+
If you need timezone lookup from coordinates, install [`timezonefinder`](https://pypi.org/project/timezonefinder/) separately and implement manual lookup:
1421

15-
## Bug Fixes
22+
```python
23+
# Install: pip install timezonefinder
24+
from timezonefinder import TimezoneFinder
25+
from zoneinfo import ZoneInfo
26+
from frequenz.client.microgrid import Location
1627

17-
<!-- Here goes notable bug fixes that are worth a special mention or explanation -->
28+
tf = TimezoneFinder()
29+
tz_name = tf.timezone_at(lat=52.52, lng=13.405)
30+
timezone = ZoneInfo(tz_name) if tz_name else None
31+
location = Location(latitude=52.52, longitude=13.405, timezone=timezone)
32+
```

pyproject.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ dependencies = [
4242
"frequenz-client-common >= 0.3.2, < 0.4.0",
4343
"grpcio >= 1.63.0, < 2",
4444
"protobuf >= 5.26.1, < 7",
45-
"timezonefinder >= 6.2.0, < 7",
4645
"typing-extensions >= 4.13.0, < 5",
4746
]
4847
dynamic = ["version"]

src/frequenz/client/microgrid/_metadata.py

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@
77
from zoneinfo import ZoneInfo
88

99
from frequenz.client.common.microgrid import MicrogridId
10-
from timezonefinder import TimezoneFinder
11-
12-
_timezone_finder = TimezoneFinder()
1310

1411

1512
@dataclass(frozen=True, kw_only=True)
@@ -23,23 +20,7 @@ class Location:
2320
"""The longitude of the microgrid in degree."""
2421

2522
timezone: ZoneInfo | None = None
26-
"""The timezone of the microgrid.
27-
28-
If not passed during construction (or `None` is passed), and there is a `longitude`
29-
and `latitude`, then the timezone wil be looked up in a database based on the
30-
coordinates. This lookup could fail, in which case the timezone will still be
31-
`None`.
32-
"""
33-
34-
def __post_init__(self) -> None:
35-
"""Initialize the timezone of the microgrid."""
36-
if self.latitude is None or self.longitude is None or self.timezone is not None:
37-
return
38-
39-
timezone = _timezone_finder.timezone_at(lat=self.latitude, lng=self.longitude)
40-
if timezone:
41-
# The dataclass is frozen, so it needs to use __setattr__ to set the timezone.
42-
object.__setattr__(self, "timezone", ZoneInfo(key=timezone))
23+
"""The timezone of the microgrid."""
4324

4425

4526
@dataclass(frozen=True, kw_only=True)

tests/test_metadata.py

Lines changed: 7 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33

44
"""Tests for the microgrid metadata types."""
55

6-
from collections.abc import Iterator
7-
from unittest.mock import MagicMock, patch
86
from zoneinfo import ZoneInfo
97

108
import pytest
@@ -13,59 +11,20 @@
1311
from frequenz.client.microgrid import Location, Metadata
1412

1513

16-
@pytest.fixture
17-
def timezone_finder() -> Iterator[MagicMock]:
18-
"""Return a mock timezone finder."""
19-
with patch(
20-
"frequenz.client.microgrid._metadata._timezone_finder", autospec=True
21-
) as mock_timezone_finder:
22-
yield mock_timezone_finder
23-
24-
25-
@pytest.mark.parametrize(
26-
"latitude, longitude, timezone",
27-
[
28-
(None, None, None),
29-
(52.52, None, None),
30-
(None, 13.405, None),
31-
(None, None, ZoneInfo(key="UTC")),
32-
(52.52, None, ZoneInfo(key="UTC")),
33-
(None, 13.405, ZoneInfo(key="UTC")),
34-
(52.52, 13.405, ZoneInfo(key="UTC")),
35-
],
36-
ids=str,
37-
)
38-
def test_location_timezone_not_looked_up_if_not_possible_or_necessary(
39-
timezone_finder: MagicMock,
14+
@pytest.mark.parametrize("latitude", [None, 52.52], ids=str)
15+
@pytest.mark.parametrize("longitude", [None, 13.405], ids=str)
16+
@pytest.mark.parametrize("timezone", [None, ZoneInfo(key="UTC")], ids=str)
17+
def test_location_initialization(
4018
latitude: float | None,
4119
longitude: float | None,
4220
timezone: ZoneInfo | None,
4321
) -> None:
44-
"""Test the location timezone is not looked up if is not necessary or possible."""
45-
timezone_finder.timezone_at.return_value = "Europe/Berlin"
46-
22+
"""Test location initialization with different combinations of parameters."""
4723
location = Location(latitude=latitude, longitude=longitude, timezone=timezone)
4824

4925
assert location.latitude == latitude
5026
assert location.longitude == longitude
5127
assert location.timezone == timezone
52-
timezone_finder.timezone_at.assert_not_called()
53-
54-
55-
@pytest.mark.parametrize("timezone", [None, "Europe/Berlin"], ids=str)
56-
def test_location_timezone_lookup(
57-
timezone_finder: MagicMock, timezone: str | None
58-
) -> None:
59-
"""Test the location timezone is looked up if not provided and there is enough info."""
60-
timezone_finder.timezone_at.return_value = timezone
61-
62-
location = Location(latitude=52.52, longitude=13.405)
63-
64-
if timezone is None:
65-
assert location.timezone is None
66-
else:
67-
assert location.timezone == ZoneInfo(key=timezone)
68-
timezone_finder.timezone_at.assert_called_once_with(lat=52.52, lng=13.405)
6928

7029

7130
def test_metadata_initialization() -> None:
@@ -81,11 +40,12 @@ def test_metadata_initialization() -> None:
8140
assert metadata.microgrid_id == microgrid_id
8241
assert metadata.location is None
8342

84-
# Test with only location
43+
# Test with only location - timezone should be None even with lat/lng
8544
location = Location(latitude=52.52, longitude=13.405)
8645
metadata = Metadata(location=location)
8746
assert metadata.microgrid_id is None
8847
assert metadata.location == location
48+
assert metadata.location.timezone is None
8949

9050
# Test with both parameters
9151
metadata = Metadata(microgrid_id=microgrid_id, location=location)

0 commit comments

Comments
 (0)