Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
9c99ae0
Bump the minor group with 2 updates
dependabot[bot] Jul 1, 2025
69b1315
Bump the minor group with 2 updates (#163)
llucax Jul 1, 2025
478dc5d
Bump the patch group with 5 updates
dependabot[bot] Jul 1, 2025
b2d54fa
Bump the patch group with 5 updates (#162)
llucax Jul 1, 2025
b517c51
Bump pytest-asyncio from 0.26.0 to 1.0.0
dependabot[bot] Jul 1, 2025
ff7c2ec
Bump pytest-asyncio from 0.26.0 to 1.0.0 (#164)
llucax Jul 1, 2025
576d6d7
Remove timezonefinder dependency and automatic timezone lookup
Copilot Jul 31, 2025
7f5649d
Remove timezonefinder dependency (#168)
llucax Jul 31, 2025
c6aa8ef
Bump mkdocs-material from 9.6.14 to 9.6.16 in the patch group
dependabot[bot] Aug 1, 2025
e32bf05
Bump mypy from 1.16.1 to 1.17.1 in the minor group
dependabot[bot] Aug 1, 2025
3eebf41
Bump types-markdown from 3.8.0.20250415 to 3.8.0.20250708
dependabot[bot] Aug 1, 2025
ebe2d10
Bump pytest-asyncio from 1.0.0 to 1.1.0
dependabot[bot] Aug 1, 2025
8b3e117
Bump the compatible group with 2 updates
dependabot[bot] Aug 1, 2025
31d9782
Bump mkdocs-material from 9.6.14 to 9.6.16 in the patch group (#169)
tiyash-basu-frequenz Aug 1, 2025
0ba2f9d
Bump mypy from 1.16.1 to 1.17.1 in the minor group (#170)
tiyash-basu-frequenz Aug 1, 2025
c2d921f
Bump types-markdown from 3.8.0.20250415 to 3.8.0.20250708 (#172)
tiyash-basu-frequenz Aug 1, 2025
3f7f1d1
Bump pytest-asyncio from 1.0.0 to 1.1.0 (#174)
tiyash-basu-frequenz Aug 1, 2025
b91e45d
Bump types-protobuf from 6.30.2.20250516 to 6.30.2.20250703
dependabot[bot] Aug 1, 2025
34172dd
Bump async-solipsism from 0.7 to 0.8
dependabot[bot] Aug 1, 2025
8ca57d5
Bump mkdocstrings[python] in the mkdocstrings group
dependabot[bot] Aug 1, 2025
9edab20
Bump mkdocstrings[python] from 0.29.1 to 0.30.0 in the mkdocstrings g…
Marenz Aug 12, 2025
5e29a6e
Bump async-solipsism from 0.7 to 0.8 (#175)
Marenz Aug 14, 2025
632a859
Bump types-protobuf from 6.30.2.20250516 to 6.30.2.20250703 (#173)
llucax Aug 21, 2025
c025df1
Bump the compatible group with 2 updates (#176)
llucax Aug 21, 2025
342aae4
Clear release notes
llucax Aug 21, 2025
edce1c3
Clear release notes (#177)
llucax Aug 27, 2025
b6f5032
Bump actions/download-artifact from 4 to 5 in the artifacts group
dependabot[bot] Sep 1, 2025
cf002d4
Bump actions/checkout from 4 to 5
dependabot[bot] Sep 1, 2025
ff259d1
Bump mkdocstrings-python in the mkdocstrings group
dependabot[bot] Sep 1, 2025
6c0dc5a
Bump pydoclint from 0.6.6 to 0.6.11
dependabot[bot] Sep 1, 2025
f65c970
Bump setuptools-scm[toml] from 8.3.1 to 9.2.0
dependabot[bot] Sep 1, 2025
33453c3
Bump the patch group with 3 updates
dependabot[bot] Sep 1, 2025
8f49566
Bump types-markdown from 3.8.0.20250708 to 3.8.0.20250809
dependabot[bot] Sep 1, 2025
8fb25c7
Bump types-markdown from 3.8.0.20250708 to 3.8.0.20250809 (#187)
llucax Sep 1, 2025
6827452
Bump the patch group with 3 updates (#185)
llucax Sep 1, 2025
e90fda1
Bump setuptools-scm[toml] from 8.3.1 to 9.2.0 (#184)
llucax Sep 1, 2025
af5d9d8
Bump pydoclint from 0.6.6 to 0.6.11 (#183)
llucax Sep 1, 2025
33c94e5
Bump mkdocstrings-python from 1.16.12 to 1.18.2 in the mkdocstrings g…
llucax Sep 1, 2025
20bdb5f
Bump actions/checkout from 4 to 5 (#181)
llucax Sep 1, 2025
7b4b888
Bump actions/download-artifact from 4 to 5 in the artifacts group (#180)
llucax Sep 1, 2025
1fc09b4
Bump types-protobuf from 6.30.2.20250703 to 6.30.2.20250822
dependabot[bot] Sep 1, 2025
723ea50
Bump types-protobuf from 6.30.2.20250703 to 6.30.2.20250822 (#186)
llucax Sep 1, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/ci-pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:

steps:
- name: Run nox
uses: frequenz-floss/[email protected].0
uses: frequenz-floss/[email protected].1
with:
python-version: "3.11"
nox-session: ci_checks_max
Expand All @@ -30,12 +30,12 @@ jobs:
uses: frequenz-floss/[email protected]

- name: Fetch sources
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
submodules: true

- name: Setup Python
uses: frequenz-floss/[email protected].0
uses: frequenz-floss/[email protected].1
with:
python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
dependencies: .[dev-mkdocs]
Expand Down
22 changes: 11 additions & 11 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:

steps:
- name: Run nox
uses: frequenz-floss/[email protected].0
uses: frequenz-floss/[email protected].1
with:
python-version: ${{ matrix.python }}
nox-session: ${{ matrix.nox-session }}
Expand Down Expand Up @@ -79,12 +79,12 @@ jobs:
uses: frequenz-floss/[email protected]

- name: Fetch sources
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
submodules: true

- name: Setup Python
uses: frequenz-floss/[email protected].0
uses: frequenz-floss/[email protected].1
with:
python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
dependencies: build
Expand Down Expand Up @@ -123,7 +123,7 @@ jobs:
run: env

- name: Download package
uses: actions/download-artifact@v4
uses: actions/download-artifact@v5
with:
name: dist-packages
path: dist
Expand All @@ -143,7 +143,7 @@ jobs:
> pyproject.toml

- name: Setup Python
uses: frequenz-floss/[email protected].0
uses: frequenz-floss/[email protected].1
with:
python-version: ${{ matrix.python }}
dependencies: dist/*.whl
Expand Down Expand Up @@ -177,12 +177,12 @@ jobs:
uses: frequenz-floss/[email protected]

- name: Fetch sources
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
submodules: true

- name: Setup Python
uses: frequenz-floss/[email protected].0
uses: frequenz-floss/[email protected].1
with:
python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
dependencies: .[dev-mkdocs]
Expand Down Expand Up @@ -213,12 +213,12 @@ jobs:
uses: frequenz-floss/[email protected]

- name: Fetch sources
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
submodules: true

- name: Setup Python
uses: frequenz-floss/[email protected].0
uses: frequenz-floss/[email protected].1
with:
python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
dependencies: .[dev-mkdocs]
Expand Down Expand Up @@ -279,7 +279,7 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Download distribution files
uses: actions/download-artifact@v4
uses: actions/download-artifact@v5
with:
name: dist-packages
path: dist
Expand Down Expand Up @@ -325,7 +325,7 @@ jobs:
id-token: write
steps:
- name: Download distribution files
uses: actions/download-artifact@v4
uses: actions/download-artifact@v5
with:
name: dist-packages
path: dist
Expand Down
39 changes: 19 additions & 20 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
[build-system]
requires = [
"setuptools == 80.9.0",
"setuptools_scm[toml] == 8.3.1",
"frequenz-repo-config[lib] == 0.13.4",
"setuptools_scm[toml] == 9.2.0",
"frequenz-repo-config[lib] == 0.13.5",
]
build-backend = "setuptools.build_meta"

Expand Down Expand Up @@ -42,7 +42,6 @@ dependencies = [
"frequenz-client-common >= 0.3.2, < 0.4.0",
"grpcio >= 1.63.0, < 2",
"protobuf >= 5.26.1, < 7",
"timezonefinder >= 6.2.0, < 7",
"typing-extensions >= 4.13.0, < 5",
]
dynamic = ["version"]
Expand All @@ -53,45 +52,45 @@ email = "[email protected]"

[project.optional-dependencies]
dev-flake8 = [
"flake8 == 7.2.0",
"flake8 == 7.3.0",
"flake8-docstrings == 1.7.0",
"flake8-pyproject == 1.2.3", # For reading the flake8 config from pyproject.toml
"pydoclint == 0.6.6",
"pydoclint == 0.6.11",
"pydocstyle == 6.3.0",
]
dev-formatting = ["black == 25.1.0", "isort == 6.0.1"]
dev-mkdocs = [
"black == 25.1.0",
"Markdown==3.8",
"Markdown==3.8.2",
"mike == 2.1.3",
"mkdocs-gen-files == 0.5.0",
"mkdocs-literate-nav == 0.6.2",
"mkdocs-macros-plugin == 1.3.7",
"mkdocs-material == 9.6.14",
"mkdocstrings[python] == 0.29.1",
"mkdocstrings-python == 1.16.11",
"frequenz-repo-config[lib] == 0.13.4",
"mkdocs-macros-plugin == 1.3.9",
"mkdocs-material == 9.6.18",
"mkdocstrings[python] == 0.30.0",
"mkdocstrings-python == 1.18.2",
"frequenz-repo-config[lib] == 0.13.5",
]
dev-mypy = [
"mypy == 1.16.0",
"mypy == 1.17.1",
"grpc-stubs == 1.53.0.6",
"types-Markdown == 3.8.0.20250415",
"types-protobuf == 6.30.2.20250516",
"types-Markdown == 3.8.0.20250809",
"types-protobuf == 6.30.2.20250822",
# For checking the noxfile, docs/ script, and tests
"frequenz-client-microgrid[dev-mkdocs,dev-noxfile,dev-pytest]",
]
dev-noxfile = ["nox == 2025.5.1", "frequenz-repo-config[lib] == 0.13.4"]
dev-noxfile = ["nox == 2025.5.1", "frequenz-repo-config[lib] == 0.13.5"]
dev-pylint = [
"pylint == 3.3.7",
"pylint == 3.3.8",
# For checking the noxfile, docs/ script, and tests
"frequenz-client-microgrid[dev-mkdocs,dev-noxfile,dev-pytest]",
]
dev-pytest = [
"pytest == 8.3.5",
"frequenz-repo-config[extra-lint-examples] == 0.13.4",
"pytest == 8.4.1",
"frequenz-repo-config[extra-lint-examples] == 0.13.5",
"pytest-mock == 3.14.1",
"pytest-asyncio == 0.26.0",
"async-solipsism == 0.7",
"pytest-asyncio == 1.1.0",
"async-solipsism == 0.8",
]
dev = [
"frequenz-client-microgrid[dev-mkdocs,dev-flake8,dev-formatting,dev-mkdocs,dev-mypy,dev-noxfile,dev-pylint,dev-pytest]",
Expand Down
21 changes: 1 addition & 20 deletions src/frequenz/client/microgrid/_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@
from zoneinfo import ZoneInfo

from frequenz.client.common.microgrid import MicrogridId
from timezonefinder import TimezoneFinder

_timezone_finder = TimezoneFinder()


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

timezone: ZoneInfo | None = None
"""The timezone of the microgrid.

If not passed during construction (or `None` is passed), and there is a `longitude`
and `latitude`, then the timezone wil be looked up in a database based on the
coordinates. This lookup could fail, in which case the timezone will still be
`None`.
"""

def __post_init__(self) -> None:
"""Initialize the timezone of the microgrid."""
if self.latitude is None or self.longitude is None or self.timezone is not None:
return

timezone = _timezone_finder.timezone_at(lat=self.latitude, lng=self.longitude)
if timezone:
# The dataclass is frozen, so it needs to use __setattr__ to set the timezone.
object.__setattr__(self, "timezone", ZoneInfo(key=timezone))
"""The timezone of the microgrid."""


@dataclass(frozen=True, kw_only=True)
Expand Down
54 changes: 7 additions & 47 deletions tests/test_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@

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

from collections.abc import Iterator
from unittest.mock import MagicMock, patch
from zoneinfo import ZoneInfo

import pytest
Expand All @@ -13,59 +11,20 @@
from frequenz.client.microgrid import Location, Metadata


@pytest.fixture
def timezone_finder() -> Iterator[MagicMock]:
"""Return a mock timezone finder."""
with patch(
"frequenz.client.microgrid._metadata._timezone_finder", autospec=True
) as mock_timezone_finder:
yield mock_timezone_finder


@pytest.mark.parametrize(
"latitude, longitude, timezone",
[
(None, None, None),
(52.52, None, None),
(None, 13.405, None),
(None, None, ZoneInfo(key="UTC")),
(52.52, None, ZoneInfo(key="UTC")),
(None, 13.405, ZoneInfo(key="UTC")),
(52.52, 13.405, ZoneInfo(key="UTC")),
],
ids=str,
)
def test_location_timezone_not_looked_up_if_not_possible_or_necessary(
timezone_finder: MagicMock,
@pytest.mark.parametrize("latitude", [None, 52.52], ids=str)
@pytest.mark.parametrize("longitude", [None, 13.405], ids=str)
@pytest.mark.parametrize("timezone", [None, ZoneInfo(key="UTC")], ids=str)
def test_location_initialization(
latitude: float | None,
longitude: float | None,
timezone: ZoneInfo | None,
) -> None:
"""Test the location timezone is not looked up if is not necessary or possible."""
timezone_finder.timezone_at.return_value = "Europe/Berlin"

"""Test location initialization with different combinations of parameters."""
location = Location(latitude=latitude, longitude=longitude, timezone=timezone)

assert location.latitude == latitude
assert location.longitude == longitude
assert location.timezone == timezone
timezone_finder.timezone_at.assert_not_called()


@pytest.mark.parametrize("timezone", [None, "Europe/Berlin"], ids=str)
def test_location_timezone_lookup(
timezone_finder: MagicMock, timezone: str | None
) -> None:
"""Test the location timezone is looked up if not provided and there is enough info."""
timezone_finder.timezone_at.return_value = timezone

location = Location(latitude=52.52, longitude=13.405)

if timezone is None:
assert location.timezone is None
else:
assert location.timezone == ZoneInfo(key=timezone)
timezone_finder.timezone_at.assert_called_once_with(lat=52.52, lng=13.405)


def test_metadata_initialization() -> None:
Expand All @@ -81,11 +40,12 @@ def test_metadata_initialization() -> None:
assert metadata.microgrid_id == microgrid_id
assert metadata.location is None

# Test with only location
# Test with only location - timezone should be None even with lat/lng
Copy link

Copilot AI Sep 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The comment uses 'lat/lng' abbreviations. For consistency with the code that uses 'latitude' and 'longitude', consider using the full names: 'latitude/longitude'.

Suggested change
# Test with only location - timezone should be None even with lat/lng
# Test with only location - timezone should be None even with latitude/longitude

Copilot uses AI. Check for mistakes.
location = Location(latitude=52.52, longitude=13.405)
metadata = Metadata(location=location)
assert metadata.microgrid_id is None
assert metadata.location == location
assert metadata.location.timezone is None

# Test with both parameters
metadata = Metadata(microgrid_id=microgrid_id, location=location)
Expand Down