From 228b7e2655640c24a4b23fbdb7906a504a5fd054 Mon Sep 17 00:00:00 2001 From: Benjamin Gutzmann Date: Mon, 6 Jan 2025 22:53:02 +0100 Subject: [PATCH] Move more details into `MetadataModel` --- docs/data/parameters.md | 6 +- docs/library/core.md | 4 - pyproject.toml | 2 + .../provider/dwd/observation/test_api_data.py | 7 +- .../observation/test_available_datasets.py | 2 +- tests/provider/dwd/radar/test_util.py | 2 +- tests/provider/dwd/road/test_api.py | 2 +- tests/provider/dwd/test_index.py | 2 +- tests/util/test_network.py | 2 +- uv.lock | 19 ++++- wetterdienst/__init__.py | 4 - wetterdienst/core/core.py | 34 -------- wetterdienst/core/timeseries/metadata.py | 22 ++++-- wetterdienst/core/timeseries/request.py | 28 +------ wetterdienst/core/timeseries/result.py | 10 +-- wetterdienst/core/timeseries/values.py | 19 ++--- wetterdienst/{util => metadata}/cache.py | 0 wetterdienst/metadata/datarange.py | 12 --- wetterdienst/metadata/kind.py | 9 --- wetterdienst/metadata/provider.py | 77 ------------------- wetterdienst/metadata/timezone.py | 14 ---- wetterdienst/provider/dwd/dmo/api.py | 14 +--- wetterdienst/provider/dwd/dmo/metadata.py | 7 +- wetterdienst/provider/dwd/metadata.py | 23 ++++++ .../provider/dwd/metadata/__init__.py | 2 - .../provider/dwd/metadata/datetime.py | 15 ---- wetterdienst/provider/dwd/mosmix/access.py | 2 +- wetterdienst/provider/dwd/mosmix/api.py | 15 +--- wetterdienst/provider/dwd/mosmix/metadata.py | 7 +- wetterdienst/provider/dwd/observation/api.py | 25 +++--- .../provider/dwd/observation/download.py | 2 +- .../provider/dwd/observation/fileindex.py | 4 +- .../provider/dwd/observation/metadata.py | 6 +- .../provider/dwd/observation/metaindex.py | 2 +- .../provider/dwd/observation/parser.py | 2 +- wetterdienst/provider/dwd/radar/api.py | 4 +- wetterdienst/provider/dwd/radar/index.py | 4 +- wetterdienst/provider/dwd/road/api.py | 18 ++--- wetterdienst/provider/ea/hydrology/api.py | 22 +++--- wetterdienst/provider/eaufrance/hubeau/api.py | 22 +++--- wetterdienst/provider/eccc/observation/api.py | 13 +--- .../provider/eccc/observation/metadata.py | 11 ++- .../provider/geosphere/observation/api.py | 11 +-- .../geosphere/observation/metadata.py | 11 ++- wetterdienst/provider/imgw/hydrology/api.py | 18 ++--- wetterdienst/provider/imgw/metadata.py | 8 ++ wetterdienst/provider/imgw/meteorology/api.py | 20 +++-- wetterdienst/provider/noaa/ghcn/api.py | 14 +--- wetterdienst/provider/noaa/ghcn/metadata.py | 11 ++- wetterdienst/provider/nws/observation/api.py | 24 +++--- wetterdienst/provider/wsv/pegel/api.py | 25 +++--- wetterdienst/ui/cli.py | 8 +- wetterdienst/ui/restapi.py | 15 +++- wetterdienst/util/network.py | 2 +- wetterdienst/util/pdf.py | 2 +- wetterdienst/util/python.py | 16 ---- 56 files changed, 249 insertions(+), 433 deletions(-) delete mode 100644 wetterdienst/core/core.py rename wetterdienst/{util => metadata}/cache.py (100%) delete mode 100644 wetterdienst/metadata/datarange.py delete mode 100644 wetterdienst/metadata/kind.py delete mode 100644 wetterdienst/metadata/provider.py delete mode 100644 wetterdienst/metadata/timezone.py create mode 100644 wetterdienst/provider/dwd/metadata.py delete mode 100644 wetterdienst/provider/dwd/metadata/__init__.py delete mode 100644 wetterdienst/provider/dwd/metadata/datetime.py create mode 100644 wetterdienst/provider/imgw/metadata.py diff --git a/docs/data/parameters.md b/docs/data/parameters.md index 2380fe7bc..ef5db6f02 100644 --- a/docs/data/parameters.md +++ b/docs/data/parameters.md @@ -13,11 +13,11 @@ from wetterdienst.provider.dwd.observation import DwdObservationMetadata # print resolutions, datasets and parameters for resolution in DwdObservationMetadata: - print(f"{2*"\t"}{resolution.name}", "\n") + print(f"{2 * "\t"}{resolution.name}", "\n") for dataset in resolution: - print(f"{3*"\t"}{dataset.name}", "\n") + print(f"{3 * "\t"}{dataset.name}", "\n") for parameter in dataset: - print(f"{4*"\t"}{parameter.name}", "\n") + print(f"{4 * "\t"}{parameter.name}", "\n") ``` The amount of distinct parameters and a list of the parameter names: diff --git a/docs/library/core.md b/docs/library/core.md index 464d2eddd..c8362731c 100644 --- a/docs/library/core.md +++ b/docs/library/core.md @@ -2,10 +2,6 @@ ## Core -::: wetterdienst.core.core - options: - heading_level: 3 - ::: wetterdienst.core.timeseries options: heading_level: 3 diff --git a/pyproject.toml b/pyproject.toml index 153b09d77..4ac636f5e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -97,6 +97,7 @@ dependencies = [ "portion>=2.4.2,<3", "pyarrow>=13,<19", "pydantic>=2.7.3,<3", + "pydantic-extra-types>=2.10.1,<3", "pydantic-settings>=2.7.0,<3", "pypdf>=3.12.1,<6", "python-dateutil>=2,<3", @@ -105,6 +106,7 @@ dependencies = [ "stamina>=23,<25", "tabulate>=0.8,<1", "tqdm>=4,<5", + "tzdata>=2024.2,<2025", "tzfpy>=0.15.2,<1", ] diff --git a/tests/provider/dwd/observation/test_api_data.py b/tests/provider/dwd/observation/test_api_data.py index e96b4abf5..8a9af4338 100644 --- a/tests/provider/dwd/observation/test_api_data.py +++ b/tests/provider/dwd/observation/test_api_data.py @@ -11,7 +11,6 @@ from wetterdienst import Settings from wetterdienst.metadata.columns import Columns from wetterdienst.metadata.period import Period -from wetterdienst.metadata.timezone import Timezone from wetterdienst.provider.dwd.observation.api import DwdObservationRequest from wetterdienst.provider.dwd.observation.metadata import ( DwdObservationMetadata, @@ -117,7 +116,7 @@ def test_request_period_historical_recent_now(default_settings): ] -@freeze_time(dt.datetime(2022, 1, 29, 1, 30, tzinfo=ZoneInfo(Timezone.GERMANY.value))) +@freeze_time(dt.datetime(2022, 1, 29, 1, 30, tzinfo=ZoneInfo("Europe/Berlin"))) def test_request_period_recent_now(default_settings): request = DwdObservationRequest( parameters=[("daily", "climate_summary")], @@ -127,7 +126,7 @@ def test_request_period_recent_now(default_settings): assert request.periods == [Period.RECENT, Period.NOW] -@freeze_time(dt.datetime(2022, 1, 29, 2, 30, tzinfo=ZoneInfo(Timezone.GERMANY.value))) +@freeze_time(dt.datetime(2022, 1, 29, 2, 30, tzinfo=ZoneInfo("Europe/Berlin"))) def test_request_period_now(default_settings): # Now period request = DwdObservationRequest( @@ -138,7 +137,7 @@ def test_request_period_now(default_settings): assert request.periods == [Period.NOW] -@freeze_time(dt.datetime(2021, 3, 28, 18, 38, tzinfo=ZoneInfo(Timezone.GERMANY.value))) +@freeze_time(dt.datetime(2021, 3, 28, 18, 38, tzinfo=ZoneInfo("Europe/Berlin"))) def test_request_period_now_fixed_date(default_settings): # Now period request = DwdObservationRequest( diff --git a/tests/provider/dwd/observation/test_available_datasets.py b/tests/provider/dwd/observation/test_available_datasets.py index d60b9af78..4b78c420a 100644 --- a/tests/provider/dwd/observation/test_available_datasets.py +++ b/tests/provider/dwd/observation/test_available_datasets.py @@ -3,10 +3,10 @@ import polars as pl import pytest +from wetterdienst.metadata.cache import CacheExpiry from wetterdienst.provider.dwd.observation.metadata import ( DwdObservationMetadata, ) -from wetterdienst.util.cache import CacheExpiry from wetterdienst.util.network import HTTPFileSystem SKIP_DATASETS = ( diff --git a/tests/provider/dwd/radar/test_util.py b/tests/provider/dwd/radar/test_util.py index 4319010eb..3142ae38f 100644 --- a/tests/provider/dwd/radar/test_util.py +++ b/tests/provider/dwd/radar/test_util.py @@ -6,7 +6,7 @@ import pytest from fsspec.implementations.http import HTTPFileSystem -from wetterdienst.provider.dwd.metadata.datetime import DatetimeFormat +from wetterdienst.provider.dwd.metadata import DatetimeFormat from wetterdienst.provider.dwd.radar.util import RADAR_DT_PATTERN, get_date_from_filename, verify_hdf5 HDF5_EXAMPLE = ( diff --git a/tests/provider/dwd/road/test_api.py b/tests/provider/dwd/road/test_api.py index 17ce56f97..5f890f556 100644 --- a/tests/provider/dwd/road/test_api.py +++ b/tests/provider/dwd/road/test_api.py @@ -1,8 +1,8 @@ import pytest from wetterdienst import Settings +from wetterdienst.metadata.cache import CacheExpiry from wetterdienst.provider.dwd.road.api import DwdRoadRequest, DwdRoadStationGroup -from wetterdienst.util.cache import CacheExpiry from wetterdienst.util.eccodes import ensure_eccodes, ensure_pdbufr from wetterdienst.util.network import list_remote_files_fsspec diff --git a/tests/provider/dwd/test_index.py b/tests/provider/dwd/test_index.py index 17ec6b0d4..fc9e72eb5 100644 --- a/tests/provider/dwd/test_index.py +++ b/tests/provider/dwd/test_index.py @@ -3,12 +3,12 @@ import pytest from wetterdienst import Period +from wetterdienst.metadata.cache import CacheExpiry from wetterdienst.provider.dwd.observation.fileindex import _create_file_index_for_dwd_server, build_path_to_parameter from wetterdienst.provider.dwd.observation.metadata import ( DwdObservationMetadata, ) from wetterdienst.settings import Settings -from wetterdienst.util.cache import CacheExpiry from wetterdienst.util.network import list_remote_files_fsspec diff --git a/tests/util/test_network.py b/tests/util/test_network.py index fd40c6a4b..b3a1e2f53 100644 --- a/tests/util/test_network.py +++ b/tests/util/test_network.py @@ -1,7 +1,7 @@ # Copyright (C) 2018-2021, earthobservations developers. # Distributed under the MIT License. See LICENSE for more info. +from wetterdienst.metadata.cache import CacheExpiry from wetterdienst.settings import Settings -from wetterdienst.util.cache import CacheExpiry from wetterdienst.util.network import NetworkFilesystemManager diff --git a/uv.lock b/uv.lock index 62679c146..88481772c 100644 --- a/uv.lock +++ b/uv.lock @@ -2861,6 +2861,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a9/f9/b6bcaf874f410564a78908739c80861a171788ef4d4f76f5009656672dfe/pydantic_core-2.23.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:9a5bce9d23aac8f0cf0836ecfc033896aa8443b501c58d0602dbfd5bd5b37753", size = 1920344 }, ] +[[package]] +name = "pydantic-extra-types" +version = "2.10.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pydantic" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c3/12/844a4796dbbc814ef0a706f403cb0f3029bf324c2bca2bf0681f4f7d8618/pydantic_extra_types-2.10.1.tar.gz", hash = "sha256:e4f937af34a754b8f1fa228a2fac867091a51f56ed0e8a61d5b3a6719b13c923", size = 85694 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a8/f1/92f7b4711d3d0d08981c2677ec9cdde6cb114205a69814bf803e0be5ae9b/pydantic_extra_types-2.10.1-py3-none-any.whl", hash = "sha256:db2c86c04a837bbac0d2d79bbd6f5d46c4c9253db11ca3fdd36a2b282575f1e2", size = 35155 }, +] + [[package]] name = "pydantic-settings" version = "2.7.0" @@ -4025,7 +4038,7 @@ wheels = [ [[package]] name = "wetterdienst" -version = "0.99.0" +version = "0.100.0" source = { editable = "." } dependencies = [ { name = "backports-datetime-fromisoformat", marker = "python_full_version < '3.11'" }, @@ -4045,6 +4058,7 @@ dependencies = [ { name = "portion" }, { name = "pyarrow" }, { name = "pydantic" }, + { name = "pydantic-extra-types" }, { name = "pydantic-settings" }, { name = "pypdf" }, { name = "python-dateutil" }, @@ -4053,6 +4067,7 @@ dependencies = [ { name = "stamina" }, { name = "tabulate" }, { name = "tqdm" }, + { name = "tzdata" }, { name = "tzfpy" }, ] @@ -4207,6 +4222,7 @@ requires-dist = [ { name = "pybufrkit", marker = "extra == 'bufr'", specifier = ">=0.2,<1" }, { name = "pybufrkit", marker = "extra == 'radarplus'", specifier = ">=0.2,<1" }, { name = "pydantic", specifier = ">=2.7.3,<3" }, + { name = "pydantic-extra-types", specifier = ">=2.10.1,<3" }, { name = "pydantic-settings", specifier = ">=2.7.0,<3" }, { name = "pypdf", specifier = ">=3.12.1,<6" }, { name = "python-dateutil", specifier = ">=2,<3" }, @@ -4222,6 +4238,7 @@ requires-dist = [ { name = "streamlit", marker = "extra == 'explorer'", specifier = ">=1.27,<2" }, { name = "tabulate", specifier = ">=0.8,<1" }, { name = "tqdm", specifier = ">=4,<5" }, + { name = "tzdata", specifier = ">=2024.2,<2025" }, { name = "tzfpy", specifier = ">=0.15.2,<1" }, { name = "utm", marker = "extra == 'interpolation'", specifier = ">=0.7,<1" }, { name = "uvicorn", marker = "extra == 'restapi'", specifier = ">=0.14,<1" }, diff --git a/wetterdienst/__init__.py b/wetterdienst/__init__.py index 3c3e00299..0c050fd61 100644 --- a/wetterdienst/__init__.py +++ b/wetterdienst/__init__.py @@ -6,10 +6,8 @@ from wetterdienst import boot from wetterdienst.api import Wetterdienst -from wetterdienst.metadata.kind import Kind from wetterdienst.metadata.parameter import Parameter from wetterdienst.metadata.period import Period -from wetterdienst.metadata.provider import Provider from wetterdienst.metadata.resolution import Resolution from wetterdienst.settings import Settings @@ -65,10 +63,8 @@ def to_dict(self): "__version__", "Author", "Info", - "Kind", "Parameter", "Period", - "Provider", "Resolution", "Settings", "Wetterdienst", diff --git a/wetterdienst/core/core.py b/wetterdienst/core/core.py deleted file mode 100644 index 87fe576b5..000000000 --- a/wetterdienst/core/core.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright (C) 2018-2021, earthobservations developers. -# Distributed under the MIT License. See LICENSE for more info. -import datetime as dt -from abc import ABCMeta, abstractmethod -from zoneinfo import ZoneInfo - -from wetterdienst.metadata.timezone import Timezone - - -class Core(metaclass=ABCMeta): - """Core class for any related requests of wetterdienst""" - - def __init__(self): - # Time of request. - self.now = dt.datetime.now(ZoneInfo("UTC")) - - @property - def tz(self) -> ZoneInfo: - """timezone of country that may be used for internal date parsing or reflection - of release schedules""" - return ZoneInfo(self._tz.value) - - @property - @abstractmethod - def _tz(self) -> Timezone: - """Abstract representation of timezone that has to be implemented by source - class, uses the Timezone enumeration""" - pass - - @property - def _now_local(self) -> dt.datetime: - """Local now time based on the given timezone that represents the request time - in local time""" - return self.now.astimezone(self.tz) diff --git a/wetterdienst/core/timeseries/metadata.py b/wetterdienst/core/timeseries/metadata.py index 07b973e01..2e9a48faf 100644 --- a/wetterdienst/core/timeseries/metadata.py +++ b/wetterdienst/core/timeseries/metadata.py @@ -3,9 +3,12 @@ import logging from collections.abc import Iterable from dataclasses import dataclass -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Literal from pydantic import BaseModel, Field, SkipValidation, field_validator +from pydantic_extra_types.timezone_name import ( + TimeZoneName, # noqa: TCH002, needs to stay here for pydantic model to work +) from wetterdienst.metadata.period import Period # noqa: TCH001, needs to stay here for pydantic model to work from wetterdienst.metadata.resolution import Resolution # noqa: TCH001, needs to stay here for pydantic model to work @@ -167,6 +170,15 @@ def __iter__(self) -> Iterator[DatasetModel]: class MetadataModel(BaseModel): + name_short: str + name_english: str + name_local: str + country: str + copyright: str + url: str + kind: Literal["observation", "forecast"] + timezone: TimeZoneName + timezone_data: TimeZoneName | Literal["dynamic"] resolutions: list[ResolutionModel] def __getitem__(self, item: str | int): @@ -199,13 +211,7 @@ def __getattr__(self, item): ): return resolution else: - available_resolutions = [ - f"{resolution.name}/{resolution.name_original}" - if resolution.name != resolution.name_original - else resolution.name - for resolution in self.resolutions - ] - raise AttributeError(f"'{item}'. Available resolutions: {', '.join(available_resolutions)}") + return super().__getattr__(item) def __iter__(self) -> Iterator[ResolutionModel]: return iter(self.resolutions) diff --git a/wetterdienst/core/timeseries/request.py b/wetterdienst/core/timeseries/request.py index d2ff7295d..d74ebefa4 100644 --- a/wetterdienst/core/timeseries/request.py +++ b/wetterdienst/core/timeseries/request.py @@ -7,7 +7,6 @@ from abc import abstractmethod from collections.abc import Sequence from hashlib import sha256 -from typing import TYPE_CHECKING from zoneinfo import ZoneInfo import numpy as np @@ -17,7 +16,6 @@ from polars.exceptions import NoDataError from rapidfuzz import fuzz, process -from wetterdienst.core.core import Core from wetterdienst.core.timeseries.metadata import ( DatasetModel, MetadataModel, @@ -42,11 +40,6 @@ from wetterdienst.settings import Settings from wetterdienst.util.python import to_list -if TYPE_CHECKING: - from wetterdienst.metadata.datarange import DataRange - from wetterdienst.metadata.kind import Kind - from wetterdienst.metadata.provider import Provider - try: from backports.datetime_fromisoformat import MonkeyPatch except ImportError: @@ -69,34 +62,15 @@ _SETTINGS_TYPE = dict | Settings | None -class TimeseriesRequest(Core): +class TimeseriesRequest: """Core for stations_result information of a source""" - @property - @abstractmethod - def _provider(self) -> Provider: - """Optional enumeration for multiple resolutions""" - pass - - @property - @abstractmethod - def _kind(self) -> Kind: - """Optional enumeration for multiple resolutions""" - pass - @property @abstractmethod def metadata(self) -> MetadataModel: """metadata model""" pass - @property - @abstractmethod - def _data_range(self) -> DataRange: - """State whether data from this provider is given in fixed data chunks - or has to be defined over start and end date""" - pass - @property @abstractmethod def _values(self): diff --git a/wetterdienst/core/timeseries/result.py b/wetterdienst/core/timeseries/result.py index 680e44c41..3748711b5 100644 --- a/wetterdienst/core/timeseries/result.py +++ b/wetterdienst/core/timeseries/result.py @@ -125,10 +125,6 @@ def __eq__(self, other): def settings(self): return self.stations.settings - @property - def provider(self): - return self.stations._provider - @property def station_id(self) -> pl.Series: return self.df.get_column(Columns.STATION_ID.value) @@ -185,7 +181,11 @@ def get_metadata(self) -> _Metadata: from wetterdienst import Info info = Info() - name_local, name_english, country, copyright_, url = self.stations._provider.value + name_local = self.stations.metadata.name_local + name_english = self.stations.metadata.name_english + country = self.stations.metadata.country + copyright_ = self.stations.metadata.copyright + url = self.stations.metadata.url return { "provider": { "name_local": name_local, diff --git a/wetterdienst/core/timeseries/values.py b/wetterdienst/core/timeseries/values.py index cb1d88780..013266aca 100644 --- a/wetterdienst/core/timeseries/values.py +++ b/wetterdienst/core/timeseries/values.py @@ -18,7 +18,6 @@ from wetterdienst.core.timeseries.unit import UnitConverter from wetterdienst.metadata.columns import Columns from wetterdienst.metadata.resolution import DAILY_AT_MOST, Frequency, Resolution -from wetterdienst.metadata.timezone import Timezone from wetterdienst.util.logging import TqdmToLogger if TYPE_CHECKING: @@ -105,15 +104,9 @@ def _meta_fields(self) -> dict[str, str]: # TODO: add data type (mosmix, observation, ...) @property - def data_tz(self) -> str: + def timezone_data(self) -> str: """Timezone of the published data""" - return self._data_tz.value - - @property - @abstractmethod - def _data_tz(self) -> Timezone: - """Timezone enumeration of published data.""" - pass + return self.sr.stations.metadata.timezone_data def _adjust_start_end_date( self, @@ -263,10 +256,10 @@ def _create_empty_station_df(self, station_id: str, dataset: DatasetModel) -> pl if not self.sr.start_date: return pl.DataFrame(schema=self._meta_fields) - if self._data_tz == Timezone.DYNAMIC: + if self.timezone_data == "dynamic": tzinfo = ZoneInfo(self._get_timezone_from_station(station_id)) else: - tzinfo = ZoneInfo(self.data_tz) + tzinfo = ZoneInfo(self.timezone_data) start_date, end_date = self._adjust_start_end_date( self.sr.start_date, self.sr.end_date, tzinfo, dataset.resolution.value ) @@ -301,10 +294,10 @@ def _build_complete_df(self, df: pl.DataFrame, station_id: str, resolution: Reso """ if df.is_empty(): return df - if self._data_tz == Timezone.DYNAMIC: + if self.timezone_data == "dynamic": tzinfo = ZoneInfo(self._get_timezone_from_station(station_id)) else: - tzinfo = ZoneInfo(self.data_tz) + tzinfo = ZoneInfo(self.timezone_data) start_date, end_date = self._adjust_start_end_date(self.sr.start_date, self.sr.end_date, tzinfo, resolution) base_df = self._get_base_df(start_date, end_date, resolution) data = [] diff --git a/wetterdienst/util/cache.py b/wetterdienst/metadata/cache.py similarity index 100% rename from wetterdienst/util/cache.py rename to wetterdienst/metadata/cache.py diff --git a/wetterdienst/metadata/datarange.py b/wetterdienst/metadata/datarange.py deleted file mode 100644 index 8c0544cb8..000000000 --- a/wetterdienst/metadata/datarange.py +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (C) 2018-2021, earthobservations developers. -# Distributed under the MIT License. See LICENSE for more info. -from enum import Enum - - -class DataRange(Enum): - """Enumeration for data range. This is required for querying data - which can not be queried in a fixed file format and must be defined - over start and end date""" - - FIXED = "fixed" - LOOSELY = "loosely" diff --git a/wetterdienst/metadata/kind.py b/wetterdienst/metadata/kind.py deleted file mode 100644 index 82ec52d4a..000000000 --- a/wetterdienst/metadata/kind.py +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (C) 2018-2021, earthobservations developers. -# Distributed under the MIT License. See LICENSE for more info. -from enum import Enum - - -class Kind(Enum): - OBSERVATION = "observation" - FORECAST = "mosmix" - RADAR = "radar" diff --git a/wetterdienst/metadata/provider.py b/wetterdienst/metadata/provider.py deleted file mode 100644 index dcb884e3c..000000000 --- a/wetterdienst/metadata/provider.py +++ /dev/null @@ -1,77 +0,0 @@ -# Copyright (C) 2018-2021, earthobservations developers. -# Distributed under the MIT License. See LICENSE for more info. -from enum import Enum - - -class Provider(Enum): - """Source of weather information given as tuple of - - local name - - english name - - country - - copyright string - - url to data - """ - - DWD = ( - "Deutscher Wetterdienst", - "German Weather Service", - "Germany", - "© Deutscher Wetterdienst (DWD), Climate Data Center (CDC)", - "https://opendata.dwd.de/climate_environment/CDC/", - ) - EA = ( - "Environment Agency", - "Environment Agency", - "United Kingdom", - "© Environment Agency of UK", - "https://environment.data.gov.uk/", - ) - EAUFRANCE = ( - "Eaufrance", - "Eaufrance", - "France", - "© Eaufrance", - "https://www.eaufrance.fr/", - ) - ECCC = ( - "Environnement Et Changement Climatique Canada", - "Environment And Climate Change Canada", - "Canada", - "© Environment And Climate Change Canada (ECCC)", - "https://climate.weather.gc.ca/climate_data/bulk_data_e.html", - ) - GEOSPHERE = ( - "Geosphere Österreich", - "Geosphere Austria", - "Austria", - "© ZAMG, Observations", - "https://www.zamg.ac.at/", - ) - IMGW = ( - "Instytut Meteorologii i Gospodarki Wodnej", - "Institute of Meteorology and Water Management", - "Poland", - "© IMGW, Observations", - "https://imgw.pl/", - ) - NOAA = ( - "National Oceanic And Atmospheric Administration", - "National Oceanic And Atmospheric Administration", - "United States Of America", - "© National Oceanic And Atmospheric Administration (NOAA), Global Historical Climatology Network", - "http://noaa-ghcn-pds.s3.amazonaws.com/csv.gz/by_station/", - ) - NWS = ( - "NOAA National Weather Service", - "NOAA National Weather Service", - "United States Of America", - "© NOAA NWS (National Weather Service), Observations", - "https://api.weather.gov/", - ) - WSV = ( - "Wasserstraßen- und Schifffahrtsverwaltung des Bundes", - "Federal Waterways and Shipping Administration", - "Germany", - "© Wasserstraßen- und Schifffahrtsverwaltung des Bundes (WSV), Pegelonline", - "https://pegelonline.wsv.de/webservice/ueberblick", - ) diff --git a/wetterdienst/metadata/timezone.py b/wetterdienst/metadata/timezone.py deleted file mode 100644 index fdb96c5e4..000000000 --- a/wetterdienst/metadata/timezone.py +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (C) 2018-2021, earthobservations developers. -# Distributed under the MIT License. See LICENSE for more info. -from enum import Enum - - -class Timezone(Enum): - GERMANY = "Europe/Berlin" - AUSTRIA = "Europe/Vienna" - FRANCE = "Europe/Paris" - UTC = "UTC" - USA = "US/Washington" - UK = "Europe/London" - POLAND = "Europe/Warsaw" - DYNAMIC = "dynamic" # station based timezone (get tz from lon/lat) diff --git a/wetterdienst/provider/dwd/dmo/api.py b/wetterdienst/provider/dwd/dmo/api.py index 2c00830b2..77c5dded8 100644 --- a/wetterdienst/provider/dwd/dmo/api.py +++ b/wetterdienst/provider/dwd/dmo/api.py @@ -12,16 +12,13 @@ import polars as pl -from wetterdienst import Kind, Provider from wetterdienst.core.timeseries.request import _DATETIME_TYPE, _PARAMETER_TYPE, _SETTINGS_TYPE, TimeseriesRequest from wetterdienst.core.timeseries.values import TimeseriesValues from wetterdienst.exceptions import InvalidEnumerationError +from wetterdienst.metadata.cache import CacheExpiry from wetterdienst.metadata.columns import Columns -from wetterdienst.metadata.datarange import DataRange -from wetterdienst.metadata.timezone import Timezone from wetterdienst.provider.dwd.dmo.metadata import DwdDmoMetadata from wetterdienst.provider.dwd.mosmix.access import KMLReader -from wetterdienst.util.cache import CacheExpiry from wetterdienst.util.enumeration import parse_enumeration_from_template from wetterdienst.util.network import download_file, list_remote_files_fsspec from wetterdienst.util.polars_util import read_fwf_from_df @@ -125,9 +122,6 @@ class DwdDmoValues(TimeseriesValues): https://www.dwd.de/DE/leistungen/opendata/help/schluessel_datenformate/kml/mosmix_elemente_pdf.pdf?__blob=publicationFile&v=2 """ # noqa:B950,E501 - _tz = Timezone.GERMANY - _data_tz = Timezone.UTC - def __init__(self, stations_result: StationsResult) -> None: """ @@ -231,12 +225,8 @@ def get_url_for_date(self, url: str, date: dt.datetime | DwdForecastDate) -> str class DwdDmoRequest(TimeseriesRequest): """Implementation of sites for dmo sites""" - _provider = Provider.DWD - _kind = Kind.FORECAST - _tz = Timezone.GERMANY - _data_range = DataRange.FIXED - _values = DwdDmoValues metadata = DwdDmoMetadata + _values = DwdDmoValues _url = ( "https://www.dwd.de/DE/leistungen/opendata/help/schluessel_datenformate/kml/" diff --git a/wetterdienst/provider/dwd/dmo/metadata.py b/wetterdienst/provider/dwd/dmo/metadata.py index d254dadb9..e0a63c883 100644 --- a/wetterdienst/provider/dwd/dmo/metadata.py +++ b/wetterdienst/provider/dwd/dmo/metadata.py @@ -1,8 +1,13 @@ from __future__ import annotations from wetterdienst.core.timeseries.metadata import build_metadata_model +from wetterdienst.provider.dwd.metadata import _METADATA DwdDmoMetadata = { + **_METADATA, + "kind": "forecast", + "timezone": "Europe/Berlin", + "timezone_data": "UTC", "resolutions": [ { "name": "hourly", @@ -998,6 +1003,6 @@ }, ], } - ] + ], } DwdDmoMetadata = build_metadata_model(DwdDmoMetadata, "DwdDmoMetadata") diff --git a/wetterdienst/provider/dwd/metadata.py b/wetterdienst/provider/dwd/metadata.py new file mode 100644 index 000000000..f99f91811 --- /dev/null +++ b/wetterdienst/provider/dwd/metadata.py @@ -0,0 +1,23 @@ +from enum import Enum + + +class DatetimeFormat(Enum): + YMD = "%Y%m%d" + YMDHM = "%Y%m%d%H%M" + YMDHMS = "%Y%m%d%H%M%S" + YMDH_COLUMN_M = "%Y%m%d%H:%M" + YMD_TIME_H = "%Y-%m-%dT%H" + + # For RADOLAN file datetime parsing + YM = "%Y%m" + ymdhm = "%y%m%d%H%M" + + +_METADATA = { + "name_short": "DWD", + "name_english": "German Weather Service", + "name_local": "Deutscher Wetterdienst", + "country": "Germany", + "copyright": "© Deutscher Wetterdienst (DWD), Climate Data Center (CDC)", + "url": "https://opendata.dwd.de/climate_environment/CDC/", +} diff --git a/wetterdienst/provider/dwd/metadata/__init__.py b/wetterdienst/provider/dwd/metadata/__init__.py deleted file mode 100644 index 57a368863..000000000 --- a/wetterdienst/provider/dwd/metadata/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# Copyright (C) 2018-2021, earthobservations developers. -# Distributed under the MIT License. See LICENSE for more info. diff --git a/wetterdienst/provider/dwd/metadata/datetime.py b/wetterdienst/provider/dwd/metadata/datetime.py deleted file mode 100644 index dbfa74e2d..000000000 --- a/wetterdienst/provider/dwd/metadata/datetime.py +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright (C) 2018-2021, earthobservations developers. -# Distributed under the MIT License. See LICENSE for more info. -from enum import Enum - - -class DatetimeFormat(Enum): - YMD = "%Y%m%d" - YMDHM = "%Y%m%d%H%M" - YMDHMS = "%Y%m%d%H%M%S" - YMDH_COLUMN_M = "%Y%m%d%H:%M" - YMD_TIME_H = "%Y-%m-%dT%H" - - # For RADOLAN file datetime parsing - YM = "%Y%m" - ymdhm = "%y%m%d%H%M" diff --git a/wetterdienst/provider/dwd/mosmix/access.py b/wetterdienst/provider/dwd/mosmix/access.py index 703d33d18..ef772c8de 100644 --- a/wetterdienst/provider/dwd/mosmix/access.py +++ b/wetterdienst/provider/dwd/mosmix/access.py @@ -15,8 +15,8 @@ from lxml.etree import iterparse # noqa: S410 from tqdm import tqdm +from wetterdienst.metadata.cache import CacheExpiry from wetterdienst.metadata.columns import Columns -from wetterdienst.util.cache import CacheExpiry from wetterdienst.util.io import read_in_chunks from wetterdienst.util.logging import TqdmToLogger from wetterdienst.util.network import NetworkFilesystemManager diff --git a/wetterdienst/provider/dwd/mosmix/api.py b/wetterdienst/provider/dwd/mosmix/api.py index 9788662d2..e6d9c8edf 100644 --- a/wetterdienst/provider/dwd/mosmix/api.py +++ b/wetterdienst/provider/dwd/mosmix/api.py @@ -14,15 +14,11 @@ from wetterdienst.core.timeseries.request import _DATETIME_TYPE, _PARAMETER_TYPE, _SETTINGS_TYPE, TimeseriesRequest from wetterdienst.core.timeseries.values import TimeseriesValues from wetterdienst.exceptions import InvalidEnumerationError +from wetterdienst.metadata.cache import CacheExpiry from wetterdienst.metadata.columns import Columns -from wetterdienst.metadata.datarange import DataRange -from wetterdienst.metadata.kind import Kind -from wetterdienst.metadata.provider import Provider -from wetterdienst.metadata.timezone import Timezone -from wetterdienst.provider.dwd.metadata.datetime import DatetimeFormat +from wetterdienst.provider.dwd.metadata import DatetimeFormat from wetterdienst.provider.dwd.mosmix.access import KMLReader from wetterdienst.provider.dwd.mosmix.metadata import DwdMosmixMetadata -from wetterdienst.util.cache import CacheExpiry from wetterdienst.util.enumeration import parse_enumeration_from_template from wetterdienst.util.geo import convert_dm_to_dd from wetterdienst.util.network import download_file, list_remote_files_fsspec @@ -75,9 +71,6 @@ class DwdMosmixValues(TimeseriesValues): https://www.dwd.de/DE/leistungen/opendata/help/schluessel_datenformate/kml/mosmix_elemente_pdf.pdf?__blob=publicationFile&v=2 """ # noqa:B950,E501 - _tz = Timezone.GERMANY - _data_tz = Timezone.UTC - def __init__(self, stations_result: StationsResult) -> None: """ @@ -225,10 +218,6 @@ class DwdMosmixRequest(TimeseriesRequest): """Implementation of sites for MOSMIX mosmix sites""" metadata = DwdMosmixMetadata - _provider = Provider.DWD - _kind = Kind.FORECAST - _tz = Timezone.GERMANY - _data_range = DataRange.FIXED _values = DwdMosmixValues _url = "https://www.dwd.de/DE/leistungen/met_verfahren_mosmix/mosmix_stationskatalog.cfg?view=nasPublication" diff --git a/wetterdienst/provider/dwd/mosmix/metadata.py b/wetterdienst/provider/dwd/mosmix/metadata.py index 3d77636cc..7d078b51d 100644 --- a/wetterdienst/provider/dwd/mosmix/metadata.py +++ b/wetterdienst/provider/dwd/mosmix/metadata.py @@ -1,8 +1,13 @@ from __future__ import annotations from wetterdienst.core.timeseries.metadata import build_metadata_model +from wetterdienst.provider.dwd.metadata import _METADATA DwdMosmixMetadata = { + **_METADATA, + "kind": "forecast", + "timezone": "Europe/Berlin", + "timezone_data": "UTC", "resolutions": [ { "name": "hourly", @@ -998,6 +1003,6 @@ }, ], } - ] + ], } DwdMosmixMetadata = build_metadata_model(DwdMosmixMetadata, "DwdMosmixMetadata") diff --git a/wetterdienst/provider/dwd/observation/api.py b/wetterdienst/provider/dwd/observation/api.py index 32ade6d30..349450bc5 100644 --- a/wetterdienst/provider/dwd/observation/api.py +++ b/wetterdienst/provider/dwd/observation/api.py @@ -7,6 +7,7 @@ from collections.abc import Iterable from itertools import repeat from typing import TYPE_CHECKING, Literal +from zoneinfo import ZoneInfo import polars as pl import portion as P @@ -17,12 +18,8 @@ from wetterdienst.core.timeseries.request import _DATETIME_TYPE, _PARAMETER_TYPE, _SETTINGS_TYPE, TimeseriesRequest from wetterdienst.core.timeseries.values import TimeseriesValues from wetterdienst.metadata.columns import Columns -from wetterdienst.metadata.datarange import DataRange -from wetterdienst.metadata.kind import Kind from wetterdienst.metadata.period import Period -from wetterdienst.metadata.provider import Provider from wetterdienst.metadata.resolution import Resolution -from wetterdienst.metadata.timezone import Timezone from wetterdienst.provider.dwd.observation.download import ( download_climate_observations_data_parallel, ) @@ -55,9 +52,6 @@ class DwdObservationValues(TimeseriesValues): observation data as provided by the DWD service. """ - _tz = Timezone.GERMANY - _data_tz = Timezone.UTC - def _collect_station_parameter_or_dataset( self, station_id: str, @@ -299,10 +293,6 @@ class DwdObservationRequest(TimeseriesRequest): """ metadata = DwdObservationMetadata - _provider = Provider.DWD - _kind = Kind.OBSERVATION - _tz = Timezone.GERMANY - _data_range = DataRange.FIXED _values = DwdObservationValues _available_periods = {Period.HISTORICAL, Period.RECENT, Period.NOW} @@ -315,7 +305,10 @@ def _interval(self) -> Interval | None: """ if self.start_date: # cut of hours, seconds,... - return P.closed(self.start_date.astimezone(self.tz), self.end_date.astimezone(self.tz)) + return P.closed( + self.start_date.astimezone(ZoneInfo(self.metadata.timezone)), + self.end_date.astimezone(ZoneInfo(self.metadata.timezone)), + ) return None @@ -327,7 +320,8 @@ def _historical_interval(self) -> Interval: :return: """ - historical_end = self._now_local.replace(month=1, day=1) + now_local = dt.datetime.now(ZoneInfo(self.metadata.timezone)) + historical_end = now_local.replace(month=1, day=1) # a year that is way before any data is collected historical_begin = dt.datetime(year=1678, month=1, day=1, tzinfo=historical_end.tzinfo) return P.closed(historical_begin, historical_end) @@ -340,7 +334,8 @@ def _recent_interval(self) -> Interval: :return: """ - recent_end = self._now_local.replace(hour=0, minute=0, second=0) + now_local = dt.datetime.now(ZoneInfo(self.metadata.timezone)) + recent_end = now_local.replace(hour=0, minute=0, second=0) recent_begin = recent_end - dt.timedelta(days=500) return P.closed(recent_begin, recent_end) @@ -352,7 +347,7 @@ def _now_interval(self) -> Interval: :return: """ - now_end = self._now_local + now_end = dt.datetime.now(ZoneInfo(self.metadata.timezone)) now_begin = now_end.replace(hour=0, minute=0, second=0) - dt.timedelta(days=1) return P.closed(now_begin, now_end) diff --git a/wetterdienst/provider/dwd/observation/download.py b/wetterdienst/provider/dwd/observation/download.py index 65d4d4e48..8b9756861 100644 --- a/wetterdienst/provider/dwd/observation/download.py +++ b/wetterdienst/provider/dwd/observation/download.py @@ -11,7 +11,7 @@ from fsspec.implementations.zip import ZipFileSystem from wetterdienst.exceptions import ProductFileNotFoundError -from wetterdienst.util.cache import CacheExpiry +from wetterdienst.metadata.cache import CacheExpiry from wetterdienst.util.network import download_file if TYPE_CHECKING: diff --git a/wetterdienst/provider/dwd/observation/fileindex.py b/wetterdienst/provider/dwd/observation/fileindex.py index 17ec0685a..bae5916e0 100644 --- a/wetterdienst/provider/dwd/observation/fileindex.py +++ b/wetterdienst/provider/dwd/observation/fileindex.py @@ -7,12 +7,12 @@ import polars as pl +from wetterdienst.metadata.cache import CacheExpiry from wetterdienst.metadata.columns import Columns from wetterdienst.metadata.extension import Extension from wetterdienst.metadata.period import Period -from wetterdienst.provider.dwd.metadata.datetime import DatetimeFormat +from wetterdienst.provider.dwd.metadata import DatetimeFormat from wetterdienst.provider.dwd.observation.metadata import DWD_URBAN_DATASETS, HIGH_RESOLUTIONS, DwdObservationMetadata -from wetterdienst.util.cache import CacheExpiry from wetterdienst.util.network import list_remote_files_fsspec if TYPE_CHECKING: diff --git a/wetterdienst/provider/dwd/observation/metadata.py b/wetterdienst/provider/dwd/observation/metadata.py index 647f2a7a9..43d4057eb 100644 --- a/wetterdienst/provider/dwd/observation/metadata.py +++ b/wetterdienst/provider/dwd/observation/metadata.py @@ -1,8 +1,12 @@ from wetterdienst.core.timeseries.metadata import build_metadata_model from wetterdienst.metadata.resolution import Resolution -from wetterdienst.provider.dwd.metadata.datetime import DatetimeFormat +from wetterdienst.provider.dwd.metadata import _METADATA, DatetimeFormat DwdObservationMetadata = { + **_METADATA, + "kind": "observation", + "timezone": "Europe/Berlin", + "timezone_data": "UTC", "resolutions": [ { "name": "1_minute", diff --git a/wetterdienst/provider/dwd/observation/metaindex.py b/wetterdienst/provider/dwd/observation/metaindex.py index efbb29215..403f7650d 100644 --- a/wetterdienst/provider/dwd/observation/metaindex.py +++ b/wetterdienst/provider/dwd/observation/metaindex.py @@ -13,11 +13,11 @@ from fsspec.implementations.zip import ZipFileSystem from wetterdienst.exceptions import MetaFileNotFoundError +from wetterdienst.metadata.cache import CacheExpiry from wetterdienst.metadata.columns import Columns from wetterdienst.metadata.period import Period from wetterdienst.provider.dwd.observation.fileindex import build_path_to_parameter from wetterdienst.provider.dwd.observation.metadata import DWD_URBAN_DATASETS, DwdObservationMetadata -from wetterdienst.util.cache import CacheExpiry from wetterdienst.util.network import download_file, list_remote_files_fsspec if TYPE_CHECKING: diff --git a/wetterdienst/provider/dwd/observation/parser.py b/wetterdienst/provider/dwd/observation/parser.py index 73eee5d5c..e649d2c2a 100644 --- a/wetterdienst/provider/dwd/observation/parser.py +++ b/wetterdienst/provider/dwd/observation/parser.py @@ -11,7 +11,7 @@ from wetterdienst.metadata.columns import Columns from wetterdienst.metadata.period import Period from wetterdienst.metadata.resolution import Resolution -from wetterdienst.provider.dwd.metadata.datetime import DatetimeFormat +from wetterdienst.provider.dwd.metadata import DatetimeFormat from wetterdienst.provider.dwd.observation.metadata import ( DwdObservationMetadata, ) diff --git a/wetterdienst/provider/dwd/radar/api.py b/wetterdienst/provider/dwd/radar/api.py index e422bd1b4..71754b382 100644 --- a/wetterdienst/provider/dwd/radar/api.py +++ b/wetterdienst/provider/dwd/radar/api.py @@ -16,10 +16,11 @@ import polars as pl from fsspec.implementations.tar import TarFileSystem +from wetterdienst.metadata.cache import CacheExpiry from wetterdienst.metadata.extension import Extension from wetterdienst.metadata.period import Period from wetterdienst.metadata.resolution import Resolution -from wetterdienst.provider.dwd.metadata.datetime import DatetimeFormat +from wetterdienst.provider.dwd.metadata import DatetimeFormat from wetterdienst.provider.dwd.radar.index import ( create_fileindex_radar, create_fileindex_radolan_cdc, @@ -38,7 +39,6 @@ from wetterdienst.provider.dwd.radar.util import RADAR_DT_PATTERN, get_date_from_filename, verify_hdf5 from wetterdienst.provider.eumetnet.opera.sites import OperaRadarSites from wetterdienst.settings import Settings -from wetterdienst.util.cache import CacheExpiry from wetterdienst.util.datetime import raster_minutes, round_minutes from wetterdienst.util.enumeration import parse_enumeration_from_template from wetterdienst.util.network import download_file diff --git a/wetterdienst/provider/dwd/radar/index.py b/wetterdienst/provider/dwd/radar/index.py index 6976d25d5..0f8d3c256 100644 --- a/wetterdienst/provider/dwd/radar/index.py +++ b/wetterdienst/provider/dwd/radar/index.py @@ -7,10 +7,11 @@ import polars as pl +from wetterdienst.metadata.cache import CacheExpiry from wetterdienst.metadata.extension import Extension from wetterdienst.metadata.period import Period from wetterdienst.metadata.resolution import Resolution -from wetterdienst.provider.dwd.metadata.datetime import DatetimeFormat +from wetterdienst.provider.dwd.metadata import DatetimeFormat from wetterdienst.provider.dwd.radar.metadata import ( RADAR_PARAMETERS_COMPOSITES, RADAR_PARAMETERS_RADOLAN, @@ -26,7 +27,6 @@ RADOLAN_DT_PATTERN, get_date_from_filename, ) -from wetterdienst.util.cache import CacheExpiry from wetterdienst.util.network import list_remote_files_fsspec if TYPE_CHECKING: diff --git a/wetterdienst/provider/dwd/road/api.py b/wetterdienst/provider/dwd/road/api.py index 4d9bc640e..7e23b8ef0 100644 --- a/wetterdienst/provider/dwd/road/api.py +++ b/wetterdienst/provider/dwd/road/api.py @@ -12,7 +12,6 @@ import polars as pl -from wetterdienst import Kind, Provider from wetterdienst.core.timeseries.metadata import ( DATASET_NAME_DEFAULT, DatasetModel, @@ -21,10 +20,9 @@ ) from wetterdienst.core.timeseries.request import _DATETIME_TYPE, _PARAMETER_TYPE, _SETTINGS_TYPE, TimeseriesRequest from wetterdienst.core.timeseries.values import TimeseriesValues +from wetterdienst.metadata.cache import CacheExpiry from wetterdienst.metadata.columns import Columns -from wetterdienst.metadata.datarange import DataRange -from wetterdienst.metadata.timezone import Timezone -from wetterdienst.util.cache import CacheExpiry +from wetterdienst.provider.dwd.metadata import _METADATA from wetterdienst.util.eccodes import check_pdbufr from wetterdienst.util.network import download_file, list_remote_files_fsspec @@ -40,6 +38,10 @@ DwdRoadMetadata = { + **_METADATA, + "kind": "observation", + "timezone": "Europe/Berlin", + "timezone_data": "UTC", "resolutions": [ { "name": "15_minutes", @@ -140,7 +142,7 @@ } ], } - ] + ], } DwdRoadMetadata = build_metadata_model(DwdRoadMetadata, "DwdRoadMetadata") @@ -193,8 +195,6 @@ class DwdRoadValues(TimeseriesValues): observation data from road weather stations as provided by the DWD service. """ - _data_tz = Timezone.UTC - def __init__(self, stations_result: StationsResult) -> None: check_pdbufr() super().__init__(stations_result) @@ -383,11 +383,7 @@ def __parse_dwd_road_weather_data( class DwdRoadRequest(TimeseriesRequest): metadata = DwdRoadMetadata - _provider = Provider.DWD - _kind = Kind.OBSERVATION - _tz = Timezone.GERMANY _values = DwdRoadValues - _data_range = DataRange.FIXED _base_columns = list(TimeseriesRequest._base_columns) _base_columns.extend( diff --git a/wetterdienst/provider/ea/hydrology/api.py b/wetterdienst/provider/ea/hydrology/api.py index ba9d67a49..58d047353 100644 --- a/wetterdienst/provider/ea/hydrology/api.py +++ b/wetterdienst/provider/ea/hydrology/api.py @@ -14,18 +14,23 @@ ) from wetterdienst.core.timeseries.request import _DATETIME_TYPE, _PARAMETER_TYPE, _SETTINGS_TYPE, TimeseriesRequest from wetterdienst.core.timeseries.values import TimeseriesValues +from wetterdienst.metadata.cache import CacheExpiry from wetterdienst.metadata.columns import Columns -from wetterdienst.metadata.datarange import DataRange -from wetterdienst.metadata.kind import Kind -from wetterdienst.metadata.provider import Provider -from wetterdienst.metadata.timezone import Timezone -from wetterdienst.util.cache import CacheExpiry from wetterdienst.util.network import download_file log = logging.getLogger(__file__) EAHydrologyMetadata = { + "name_short": "EA", + "name_english": "Environment Agency", + "name_local": "Environment Agency", + "country": "United Kingdom", + "copyright": "© Environment Agency of UK", + "url": "https://environment.data.gov.uk/", + "kind": "observation", + "timezone": "Europe/London", + "timezone_data": "Europe/London", "resolutions": [ { "name": "15_minutes", @@ -109,14 +114,13 @@ } ], }, - ] + ], } EAHydrologyMetadata = build_metadata_model(EAHydrologyMetadata, "EAHydrologyMetadata") class EAHydrologyValues(TimeseriesValues): _url = "https://environment.data.gov.uk/hydrology/id/stations/{station_id}.json" - _data_tz = Timezone.UK def _collect_station_parameter_or_dataset( self, @@ -153,10 +157,6 @@ def _collect_station_parameter_or_dataset( class EAHydrologyRequest(TimeseriesRequest): metadata = EAHydrologyMetadata - _provider = Provider.EA - _kind = Kind.OBSERVATION - _tz = Timezone.UK - _data_range = DataRange.FIXED _values = EAHydrologyValues _url = "https://environment.data.gov.uk/hydrology/id/stations.json" diff --git a/wetterdienst/provider/eaufrance/hubeau/api.py b/wetterdienst/provider/eaufrance/hubeau/api.py index 4bc0ee317..35b18eef4 100644 --- a/wetterdienst/provider/eaufrance/hubeau/api.py +++ b/wetterdienst/provider/eaufrance/hubeau/api.py @@ -18,12 +18,8 @@ ) from wetterdienst.core.timeseries.request import _DATETIME_TYPE, _PARAMETER_TYPE, _SETTINGS_TYPE, TimeseriesRequest from wetterdienst.core.timeseries.values import TimeseriesValues +from wetterdienst.metadata.cache import CacheExpiry from wetterdienst.metadata.columns import Columns -from wetterdienst.metadata.datarange import DataRange -from wetterdienst.metadata.kind import Kind -from wetterdienst.metadata.provider import Provider -from wetterdienst.metadata.timezone import Timezone -from wetterdienst.util.cache import CacheExpiry from wetterdienst.util.network import download_file if TYPE_CHECKING: @@ -45,6 +41,15 @@ HubeauMetadata = { + "name_short": "Eaufrance", + "name_english": "Eaufrance", + "name_local": "Eaufrance", + "country": "France", + "copyright": "© Eaufrance", + "url": "https://www.eaufrance.fr/", + "kind": "observation", + "timezone": "Europe/Paris", + "timezone_data": "dynamic", "resolutions": [ { "name": "dynamic", @@ -73,13 +78,12 @@ } ], } - ] + ], } HubeauMetadata = build_metadata_model(HubeauMetadata, "HubeauMetadata") class HubeauValues(TimeseriesValues): - _data_tz = Timezone.DYNAMIC _endpoint = ( "https://hubeau.eaufrance.fr/api/v1/hydrometrie/observations_tr?code_entite={station_id}" "&grandeur_hydro={grandeur_hydro}&sort=asc&date_debut_obs={start_date}&date_fin_obs={end_date}" @@ -191,10 +195,6 @@ def _collect_station_parameter_or_dataset( class HubeauRequest(TimeseriesRequest): metadata = HubeauMetadata - _provider = Provider.EAUFRANCE - _kind = Kind.OBSERVATION - _tz = Timezone.FRANCE - _data_range = DataRange.FIXED _values = HubeauValues _endpoint = "https://hubeau.eaufrance.fr/api/v1/hydrometrie/referentiel/stations?format=json&en_service=true" diff --git a/wetterdienst/provider/eccc/observation/api.py b/wetterdienst/provider/eccc/observation/api.py index 17434beab..d23e6390a 100644 --- a/wetterdienst/provider/eccc/observation/api.py +++ b/wetterdienst/provider/eccc/observation/api.py @@ -12,14 +12,10 @@ from wetterdienst.core.timeseries.request import _DATETIME_TYPE, _PARAMETER_TYPE, _SETTINGS_TYPE, TimeseriesRequest from wetterdienst.core.timeseries.values import TimeseriesValues +from wetterdienst.metadata.cache import CacheExpiry from wetterdienst.metadata.columns import Columns -from wetterdienst.metadata.datarange import DataRange -from wetterdienst.metadata.kind import Kind -from wetterdienst.metadata.provider import Provider from wetterdienst.metadata.resolution import Resolution -from wetterdienst.metadata.timezone import Timezone from wetterdienst.provider.eccc.observation.metadata import EcccObservationMetadata -from wetterdienst.util.cache import CacheExpiry from wetterdienst.util.network import download_file if TYPE_CHECKING: @@ -31,8 +27,6 @@ class EcccObservationValues(TimeseriesValues): - _data_tz = Timezone.UTC - _base_url = ( "https://climate.weather.gc.ca/climate_data/bulk_data_e.html?" "format=csv&stationID={0}&timeframe={1}" @@ -191,10 +185,6 @@ class EcccObservationRequest(TimeseriesRequest): """ metadata = EcccObservationMetadata - _provider = Provider.ECCC - _kind = Kind.OBSERVATION - _tz = Timezone.UTC - _data_range = DataRange.FIXED _values = EcccObservationValues _columns_mapping: dict = { @@ -218,7 +208,6 @@ def __init__( """ :param parameters: parameter or list of parameters that are being queried - :param resolution: resolution of data :param start_date: start date for values filtering :param end_date: end date for values filtering """ diff --git a/wetterdienst/provider/eccc/observation/metadata.py b/wetterdienst/provider/eccc/observation/metadata.py index ff9993e78..7fa3fd207 100644 --- a/wetterdienst/provider/eccc/observation/metadata.py +++ b/wetterdienst/provider/eccc/observation/metadata.py @@ -3,6 +3,15 @@ from wetterdienst.core.timeseries.metadata import DATASET_NAME_DEFAULT, build_metadata_model EcccObservationMetadata = { + "name_short": "ECCC", + "name_english": "Environment And Climate Change Canada", + "name_local": "Environnement Et Changement Climatique Canada", + "country": "Canada", + "copyright": "© Environment And Climate Change Canada (ECCC)", + "url": "https://climate.weather.gc.ca/climate_data/bulk_data_e.html", + "kind": "observation", + "timezone": "UTC", + "timezone_data": "UTC", "resolutions": [ { "name": "hourly", @@ -496,6 +505,6 @@ } ], }, - ] + ], } EcccObservationMetadata = build_metadata_model(EcccObservationMetadata, "EcccObservationMetadata") diff --git a/wetterdienst/provider/geosphere/observation/api.py b/wetterdienst/provider/geosphere/observation/api.py index 4850736ab..cd8167efa 100644 --- a/wetterdienst/provider/geosphere/observation/api.py +++ b/wetterdienst/provider/geosphere/observation/api.py @@ -13,14 +13,10 @@ from wetterdienst.core.timeseries.request import _DATETIME_TYPE, _PARAMETER_TYPE, _SETTINGS_TYPE, TimeseriesRequest from wetterdienst.core.timeseries.values import TimeseriesValues +from wetterdienst.metadata.cache import CacheExpiry from wetterdienst.metadata.columns import Columns -from wetterdienst.metadata.datarange import DataRange -from wetterdienst.metadata.kind import Kind -from wetterdienst.metadata.provider import Provider from wetterdienst.metadata.resolution import Resolution -from wetterdienst.metadata.timezone import Timezone from wetterdienst.provider.geosphere.observation.metadata import GeosphereObservationMetadata -from wetterdienst.util.cache import CacheExpiry from wetterdienst.util.network import download_file if TYPE_CHECKING: @@ -30,7 +26,6 @@ class GeosphereObservationValues(TimeseriesValues): - _data_tz = Timezone.UTC _endpoint = ( "https://dataset.api.hub.geosphere.at/v1/station/historical/{dataset}?" "parameters={parameters}&" @@ -101,10 +96,6 @@ def _collect_station_parameter_or_dataset( class GeosphereObservationRequest(TimeseriesRequest): metadata = GeosphereObservationMetadata - _provider = Provider.GEOSPHERE - _kind = Kind.OBSERVATION - _tz = Timezone.AUSTRIA - _data_range = DataRange.FIXED _values = GeosphereObservationValues _endpoint = "https://dataset.api.hub.zamg.ac.at/v1/station/historical/{dataset}/metadata/stations" diff --git a/wetterdienst/provider/geosphere/observation/metadata.py b/wetterdienst/provider/geosphere/observation/metadata.py index 9bbef034f..4b3b93b50 100644 --- a/wetterdienst/provider/geosphere/observation/metadata.py +++ b/wetterdienst/provider/geosphere/observation/metadata.py @@ -3,6 +3,15 @@ from wetterdienst.core.timeseries.metadata import DATASET_NAME_DEFAULT, build_metadata_model GeosphereObservationMetadata = { + "name_short": "Geosphere", + "name_english": "Geosphere Austria", + "name_local": "Geosphere Österreich", + "country": "Austria", + "copyright": "© ZAMG, Observations", + "url": "https://www.zamg.ac.at/", + "kind": "observation", + "timezone": "Europe/Vienna", + "timezone_data": "UTC", "resolutions": [ { "name": "10_minutes", @@ -628,6 +637,6 @@ } ], }, - ] + ], } GeosphereObservationMetadata = build_metadata_model(GeosphereObservationMetadata, "GeosphereObservationMetadata") diff --git a/wetterdienst/provider/imgw/hydrology/api.py b/wetterdienst/provider/imgw/hydrology/api.py index 46de1fafb..745d90b7f 100644 --- a/wetterdienst/provider/imgw/hydrology/api.py +++ b/wetterdienst/provider/imgw/hydrology/api.py @@ -13,14 +13,13 @@ from dateutil.relativedelta import relativedelta from fsspec.implementations.zip import ZipFileSystem -from wetterdienst import Kind, Provider, Resolution from wetterdienst.core.timeseries.metadata import DatasetModel, build_metadata_model from wetterdienst.core.timeseries.request import _DATETIME_TYPE, _PARAMETER_TYPE, _SETTINGS_TYPE, TimeseriesRequest from wetterdienst.core.timeseries.values import TimeseriesValues +from wetterdienst.metadata.cache import CacheExpiry from wetterdienst.metadata.columns import Columns -from wetterdienst.metadata.datarange import DataRange -from wetterdienst.metadata.timezone import Timezone -from wetterdienst.util.cache import CacheExpiry +from wetterdienst.metadata.resolution import Resolution +from wetterdienst.provider.imgw.metadata import _METADATA from wetterdienst.util.geo import convert_dms_string_to_dd from wetterdienst.util.network import download_file, list_remote_files_fsspec @@ -28,6 +27,10 @@ ImgwHydrologyMetadata = { + **_METADATA, + "kind": "observation", + "timezone": "Europe/Warsaw", + "timezone_data": "UTC", "resolutions": [ { "name": "daily", @@ -131,13 +134,12 @@ } ], }, - ] + ], } ImgwHydrologyMetadata = build_metadata_model(ImgwHydrologyMetadata, "ImgwHydrologyMetadata") class ImgwHydrologyValues(TimeseriesValues): - _data_tz = Timezone.UTC _endpoint = "https://danepubliczne.imgw.pl/data/dane_pomiarowo_obserwacyjne/dane_hydrologiczne/{resolution}/" _file_schema = { Resolution.DAILY: { @@ -362,10 +364,6 @@ def _get_urls(self, dataset: DatasetModel) -> pl.Series: class ImgwHydrologyRequest(TimeseriesRequest): metadata = ImgwHydrologyMetadata - _provider = Provider.IMGW - _kind = Kind.OBSERVATION - _tz = Timezone.POLAND - _data_range = DataRange.FIXED _values = ImgwHydrologyValues _endpoint = "https://dane.imgw.pl/datastore/getfiledown/Arch/Telemetria/Hydro/kody_stacji.csv" diff --git a/wetterdienst/provider/imgw/metadata.py b/wetterdienst/provider/imgw/metadata.py new file mode 100644 index 000000000..1662e815f --- /dev/null +++ b/wetterdienst/provider/imgw/metadata.py @@ -0,0 +1,8 @@ +_METADATA = { + "name_short": "IMGW", + "name_english": "Institute of Meteorology and Water Management", + "name_local": "Instytut Meteorologii i Gospodarki Wodnej", + "country": "Poland", + "copyright": "© IMGW, Observations", + "url": "https://imgw.pl/", +} diff --git a/wetterdienst/provider/imgw/meteorology/api.py b/wetterdienst/provider/imgw/meteorology/api.py index c4a92c17f..37db244e7 100644 --- a/wetterdienst/provider/imgw/meteorology/api.py +++ b/wetterdienst/provider/imgw/meteorology/api.py @@ -12,18 +12,21 @@ from dateutil.relativedelta import relativedelta from fsspec.implementations.zip import ZipFileSystem -from wetterdienst import Kind, Provider, Resolution from wetterdienst.core.timeseries.metadata import DatasetModel, build_metadata_model from wetterdienst.core.timeseries.request import _DATETIME_TYPE, _PARAMETER_TYPE, _SETTINGS_TYPE, TimeseriesRequest from wetterdienst.core.timeseries.values import TimeseriesValues +from wetterdienst.metadata.cache import CacheExpiry from wetterdienst.metadata.columns import Columns -from wetterdienst.metadata.datarange import DataRange -from wetterdienst.metadata.timezone import Timezone -from wetterdienst.util.cache import CacheExpiry +from wetterdienst.metadata.resolution import Resolution +from wetterdienst.provider.imgw.metadata import _METADATA from wetterdienst.util.geo import convert_dms_string_to_dd from wetterdienst.util.network import download_file, list_remote_files_fsspec ImgwMeteorologyMetadata = { + **_METADATA, + "kind": "observation", + "timezone": "Europe/Warsaw", + "timezone_data": "UTC", "resolutions": [ { "name": "daily", @@ -395,13 +398,12 @@ }, ], }, - ] + ], } ImgwMeteorologyMetadata = build_metadata_model(ImgwMeteorologyMetadata, "ImgwMeteorologyMetadata") class ImgwMeteorologyValues(TimeseriesValues): - _data_tz = Timezone.UTC _endpoint = ( "https://danepubliczne.imgw.pl/data/dane_pomiarowo_obserwacyjne/dane_meteorologiczne/{resolution}/{dataset}/" ) @@ -707,12 +709,8 @@ def _get_urls(self, dataset: DatasetModel) -> pl.Series: class ImgwMeteorologyRequest(TimeseriesRequest): - _provider = Provider.IMGW - _kind = Kind.OBSERVATION - _tz = Timezone.POLAND - _data_range = DataRange.FIXED - _values = ImgwMeteorologyValues metadata = ImgwMeteorologyMetadata + _values = ImgwMeteorologyValues _endpoint = "https://dane.imgw.pl/datastore/getfiledown/Arch/Telemetria/Meteo/kody_stacji.csv" def __init__( diff --git a/wetterdienst/provider/noaa/ghcn/api.py b/wetterdienst/provider/noaa/ghcn/api.py index fbc1161ed..7c7ff8d52 100644 --- a/wetterdienst/provider/noaa/ghcn/api.py +++ b/wetterdienst/provider/noaa/ghcn/api.py @@ -11,17 +11,13 @@ from wetterdienst.core.timeseries.request import _DATETIME_TYPE, _PARAMETER_TYPE, _SETTINGS_TYPE, TimeseriesRequest from wetterdienst.core.timeseries.values import TimeseriesValues +from wetterdienst.metadata.cache import CacheExpiry from wetterdienst.metadata.columns import Columns -from wetterdienst.metadata.datarange import DataRange -from wetterdienst.metadata.kind import Kind -from wetterdienst.metadata.provider import Provider from wetterdienst.metadata.resolution import Resolution -from wetterdienst.metadata.timezone import Timezone from wetterdienst.provider.noaa.ghcn.metadata import ( DAILY_PARAMETER_MULTIPLICATION_FACTORS, NoaaGhcnMetadata, ) -from wetterdienst.util.cache import CacheExpiry from wetterdienst.util.network import download_file from wetterdienst.util.polars_util import read_fwf_from_df @@ -32,8 +28,6 @@ class NoaaGhcnValues(TimeseriesValues): - _data_tz = Timezone.DYNAMIC - def _collect_station_parameter_or_dataset( self, station_id: str, parameter_or_dataset: DatasetModel ) -> pl.DataFrame: @@ -391,12 +385,8 @@ def _apply_daily_factors(df: pl.DataFrame) -> pl.DataFrame: class NoaaGhcnRequest(TimeseriesRequest): - _provider = Provider.NOAA - _kind = Kind.OBSERVATION - _tz = Timezone.USA - _data_range = DataRange.FIXED - _values = NoaaGhcnValues metadata = NoaaGhcnMetadata + _values = NoaaGhcnValues def __init__( self, diff --git a/wetterdienst/provider/noaa/ghcn/metadata.py b/wetterdienst/provider/noaa/ghcn/metadata.py index e0a4bda98..42fee8626 100644 --- a/wetterdienst/provider/noaa/ghcn/metadata.py +++ b/wetterdienst/provider/noaa/ghcn/metadata.py @@ -4,6 +4,15 @@ # translate the above enums to dictionary based model NoaaGhcnMetadata = { + "name_short": "NOAA", + "name_english": "National Oceanic And Atmospheric Administration", + "name_local": "National Oceanic And Atmospheric Administration", + "country": "United States Of America", + "copyright": "© National Oceanic And Atmospheric Administration (NOAA), Global Historical Climatology Network", + "url": "http://noaa-ghcn-pds.s3.amazonaws.com/csv.gz/by_station/", + "kind": "observation", + "timezone": "America/New_York", + "timezone_data": "dynamic", "resolutions": [ { "name": "hourly", @@ -1542,7 +1551,7 @@ } ], }, - ] + ], } NoaaGhcnMetadata = build_metadata_model(NoaaGhcnMetadata, "NoaaGhcnMetadata") diff --git a/wetterdienst/provider/nws/observation/api.py b/wetterdienst/provider/nws/observation/api.py index ef62652a1..fcfafd8bc 100644 --- a/wetterdienst/provider/nws/observation/api.py +++ b/wetterdienst/provider/nws/observation/api.py @@ -11,17 +11,22 @@ from wetterdienst.core.timeseries.metadata import DATASET_NAME_DEFAULT, DatasetModel, build_metadata_model from wetterdienst.core.timeseries.request import _DATETIME_TYPE, _PARAMETER_TYPE, _SETTINGS_TYPE, TimeseriesRequest from wetterdienst.core.timeseries.values import TimeseriesValues +from wetterdienst.metadata.cache import CacheExpiry from wetterdienst.metadata.columns import Columns -from wetterdienst.metadata.datarange import DataRange -from wetterdienst.metadata.kind import Kind -from wetterdienst.metadata.provider import Provider -from wetterdienst.metadata.timezone import Timezone -from wetterdienst.util.cache import CacheExpiry from wetterdienst.util.network import download_file log = logging.getLogger(__name__) NwsObservationMetadata = { + "name_short": "NWS", + "name_english": "NOAA National Weather Service", + "name_local": "NOAA National Weather Service", + "country": "United States Of America", + "copyright": "© NOAA NWS (National Weather Service), Observations", + "url": "https://api.weather.gov/", + "kind": "observation", + "timezone": "America/New_York", + "timezone_data": "UTC", "resolutions": [ { "name": "hourly", @@ -128,13 +133,12 @@ } ], } - ] + ], } NwsObservationMetadata = build_metadata_model(NwsObservationMetadata, "NwsObservationMetadata") class NwsObservationValues(TimeseriesValues): - _data_tz = Timezone.UTC _endpoint = "https://api.weather.gov/stations/{station_id}/observations" def _collect_station_parameter_or_dataset( @@ -242,12 +246,8 @@ def _collect_station_parameter_or_dataset( class NwsObservationRequest(TimeseriesRequest): - _provider = Provider.NWS - _kind = Kind.OBSERVATION - _tz = Timezone.USA - _data_range = DataRange.FIXED - _values = NwsObservationValues metadata = NwsObservationMetadata + _values = NwsObservationValues _endpoint = "https://madis-data.ncep.noaa.gov/madisPublic1/data/stations/METARTable.txt" diff --git a/wetterdienst/provider/wsv/pegel/api.py b/wetterdienst/provider/wsv/pegel/api.py index 91af2e0f3..82ed4a11b 100644 --- a/wetterdienst/provider/wsv/pegel/api.py +++ b/wetterdienst/provider/wsv/pegel/api.py @@ -9,12 +9,8 @@ from wetterdienst.core.timeseries.metadata import DATASET_NAME_DEFAULT, ParameterModel, build_metadata_model from wetterdienst.core.timeseries.request import _DATETIME_TYPE, _PARAMETER_TYPE, _SETTINGS_TYPE, TimeseriesRequest from wetterdienst.core.timeseries.values import TimeseriesValues +from wetterdienst.metadata.cache import CacheExpiry from wetterdienst.metadata.columns import Columns -from wetterdienst.metadata.datarange import DataRange -from wetterdienst.metadata.kind import Kind -from wetterdienst.metadata.provider import Provider -from wetterdienst.metadata.timezone import Timezone -from wetterdienst.util.cache import CacheExpiry from wetterdienst.util.network import download_file FLOAT_9_TIMES = tuple[ @@ -31,6 +27,15 @@ WsvPegelMetadata = { + "name_short": "WSV", + "name_english": "Federal Waterways and Shipping Administration", + "name_local": "Wasserstraßen- und Schifffahrtsverwaltung des Bundes", + "country": "Germany", + "copyright": "© Wasserstraßen- und Schifffahrtsverwaltung des Bundes (WSV), Pegelonline", + "url": "https://pegelonline.wsv.de/webservice/ueberblick", + "kind": "observation", + "timezone": "Europe/Berlin", + "timezone_data": "Europe/Berlin", "resolutions": [ { "name": "dynamic", @@ -173,7 +178,7 @@ } ], } - ] + ], } WsvPegelMetadata = build_metadata_model(WsvPegelMetadata, "WsvPegelMetadata") @@ -185,10 +190,6 @@ class WsvPegelValues(TimeseriesValues): # Used for getting frequency of timeseries _station_endpoint = "https://pegelonline.wsv.de/webservices/rest-api/v2/stations/{station_id}/{parameter}/" - @property - def _data_tz(self) -> Timezone: - return Timezone.GERMANY - def _collect_station_parameter_or_dataset( self, station_id: str, parameter_or_dataset: ParameterModel ) -> pl.DataFrame: @@ -224,10 +225,6 @@ class WsvPegelRequest(TimeseriesRequest): provider of river-based measurements for last 30 days""" metadata = WsvPegelMetadata - _provider = Provider.WSV - _kind = Kind.OBSERVATION - _tz = Timezone.GERMANY - _data_range = DataRange.FIXED _values = WsvPegelValues _endpoint = ( diff --git a/wetterdienst/ui/cli.py b/wetterdienst/ui/cli.py index 7e6e9603c..e20549cff 100644 --- a/wetterdienst/ui/cli.py +++ b/wetterdienst/ui/cli.py @@ -18,7 +18,7 @@ from cloup.constraints import If, RequireExactly, accept_none from PIL import Image -from wetterdienst import Provider, Settings, Wetterdienst, __appname__, __version__ +from wetterdienst import Settings, Wetterdienst, __appname__, __version__ from wetterdienst.ui.core import ( InterpolationRequest, StationsRequest, @@ -44,7 +44,7 @@ "Provider", click.option( "--provider", - type=click.Choice([provider.name for provider in Provider], case_sensitive=False), + type=click.STRING, required=True, ), ) @@ -661,7 +661,7 @@ def about(): "Provider", click.option( "--provider", - type=click.Choice([provider.name for provider in Provider], case_sensitive=False), + type=click.STRING, ), ) @cloup.option_group( @@ -718,7 +718,7 @@ def coverage(provider, network, resolutions, datasets, debug): def fields(provider, network, dataset, resolution, period, language, **kwargs): api = get_api(provider, network) - if not (api.provider == Provider.DWD and network.lower() == "observation") and kwargs.get("fields"): + if not (api.metadata.name_short == "DWD" and api.metadata.kind == "observation") and kwargs.get("fields"): raise click.BadParameter("'fields' command only available for provider 'DWD'") metadata = api.describe_fields( diff --git a/wetterdienst/ui/restapi.py b/wetterdienst/ui/restapi.py index 35d312b6c..18787eb42 100644 --- a/wetterdienst/ui/restapi.py +++ b/wetterdienst/ui/restapi.py @@ -11,7 +11,7 @@ from pydantic import ValidationError from starlette.responses import RedirectResponse -from wetterdienst import Author, Info, Provider, Settings, Wetterdienst +from wetterdienst import Author, Info, Settings, Wetterdienst from wetterdienst.core.timeseries.result import ( _InterpolatedValuesDict, _InterpolatedValuesOgcFeatureCollection, @@ -67,9 +67,16 @@ def _create_author_entry(author: Author): title = f"{info.slogan} | {info.name}" sources = [] - for provider in Provider: - shortname = provider.name - _, name, country, copyright_, url = provider.value + + for provider in Wetterdienst.registry.keys(): + # take the first network api + first_network = list(Wetterdienst.registry[provider].keys())[0] + api = Wetterdienst(provider, first_network) + shortname = api.metadata.name_short + name = api.metadata.name_english + country = api.metadata.country + copyright_ = api.metadata.copyright + url = api.metadata.url sources.append( f"
  • {shortname} ({name}, {country}) - {copyright_}
  • ", ) diff --git a/wetterdienst/util/network.py b/wetterdienst/util/network.py index f9e7d2e1b..799367951 100644 --- a/wetterdienst/util/network.py +++ b/wetterdienst/util/network.py @@ -12,7 +12,7 @@ from fsspec.implementations.cached import WholeFileCacheFileSystem from fsspec.implementations.http import HTTPFileSystem as _HTTPFileSystem -from wetterdienst.util.cache import CacheExpiry +from wetterdienst.metadata.cache import CacheExpiry if TYPE_CHECKING: from fsspec import AbstractFileSystem diff --git a/wetterdienst/util/pdf.py b/wetterdienst/util/pdf.py index 4c981498b..89bd70d57 100644 --- a/wetterdienst/util/pdf.py +++ b/wetterdienst/util/pdf.py @@ -4,8 +4,8 @@ import pypdf +from wetterdienst.metadata.cache import CacheExpiry from wetterdienst.settings import Settings -from wetterdienst.util.cache import CacheExpiry from wetterdienst.util.network import download_file diff --git a/wetterdienst/util/python.py b/wetterdienst/util/python.py index 060474a9f..b80d41aaf 100644 --- a/wetterdienst/util/python.py +++ b/wetterdienst/util/python.py @@ -6,22 +6,6 @@ binary_types = (bytes,) -class classproperty(property): - """ - A decorator that behaves like @property except that operates - on classes rather than instances. - - From SQLAlchemy's `sqlalchemy.util.langhelpers`. - """ - - def __init__(self, fget, *arg, **kw): - super().__init__(fget, *arg, **kw) - self.__doc__ = fget.__doc__ - - def __get__(desc, self, cls): - return desc.fget(cls) - - def to_list(x, default=None): """ Conveniently wrap single items into list, while keeping lists as is.