aiodpc 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. aiodpc-0.1.0/.gitignore +29 -0
  2. aiodpc-0.1.0/LICENSE +22 -0
  3. aiodpc-0.1.0/PKG-INFO +201 -0
  4. aiodpc-0.1.0/README.md +175 -0
  5. aiodpc-0.1.0/pyproject.toml +115 -0
  6. aiodpc-0.1.0/src/aiodpc/__init__.py +62 -0
  7. aiodpc-0.1.0/src/aiodpc/client.py +351 -0
  8. aiodpc-0.1.0/src/aiodpc/const.py +42 -0
  9. aiodpc-0.1.0/src/aiodpc/discovery.py +87 -0
  10. aiodpc-0.1.0/src/aiodpc/exceptions.py +23 -0
  11. aiodpc-0.1.0/src/aiodpc/geo.py +76 -0
  12. aiodpc-0.1.0/src/aiodpc/models.py +219 -0
  13. aiodpc-0.1.0/src/aiodpc/parsers.py +417 -0
  14. aiodpc-0.1.0/src/aiodpc/py.typed +0 -0
  15. aiodpc-0.1.0/src/aiodpc/urls.py +62 -0
  16. aiodpc-0.1.0/tests/__init__.py +89 -0
  17. aiodpc-0.1.0/tests/conftest.py +45 -0
  18. aiodpc-0.1.0/tests/fixtures/criticality_today.json +35 -0
  19. aiodpc-0.1.0/tests/fixtures/criticality_tomorrow.json +35 -0
  20. aiodpc-0.1.0/tests/fixtures/phenomena_domani.json +19 -0
  21. aiodpc-0.1.0/tests/fixtures/phenomena_dopodomani.json +6 -0
  22. aiodpc-0.1.0/tests/fixtures/phenomena_oggi.json +31 -0
  23. aiodpc-0.1.0/tests/fixtures/real/criticality_20261113_1434_today.json +1 -0
  24. aiodpc-0.1.0/tests/fixtures/real/criticality_page.html +7 -0
  25. aiodpc-0.1.0/tests/fixtures/real/phenomena_20261113_oggi.json +1 -0
  26. aiodpc-0.1.0/tests/fixtures/real/vigilance_20261113_oggi.json +1 -0
  27. aiodpc-0.1.0/tests/fixtures/real/vigilance_page.html +4 -0
  28. aiodpc-0.1.0/tests/fixtures/vigilance_domani.json +33 -0
  29. aiodpc-0.1.0/tests/fixtures/vigilance_dopodomani.json +33 -0
  30. aiodpc-0.1.0/tests/fixtures/vigilance_oggi.json +33 -0
  31. aiodpc-0.1.0/tests/server.py +138 -0
  32. aiodpc-0.1.0/tests/test_client.py +573 -0
  33. aiodpc-0.1.0/tests/test_discovery.py +82 -0
  34. aiodpc-0.1.0/tests/test_geo.py +63 -0
  35. aiodpc-0.1.0/tests/test_models.py +142 -0
  36. aiodpc-0.1.0/tests/test_parsers.py +520 -0
  37. aiodpc-0.1.0/tests/test_real_data.py +196 -0
@@ -0,0 +1,29 @@
1
+ # Virtual environments
2
+ .venv/
3
+ venv/
4
+ env/
5
+
6
+ # Python
7
+ __pycache__/
8
+ *.py[cod]
9
+ *.egg-info/
10
+
11
+ # Tool caches
12
+ .mypy_cache/
13
+ .pytest_cache/
14
+ .ruff_cache/
15
+
16
+ # Coverage
17
+ .coverage
18
+ .coverage.*
19
+ coverage.xml
20
+ htmlcov/
21
+
22
+ # Build artifacts
23
+ build/
24
+ dist/
25
+
26
+ # Editors and OS
27
+ .idea/
28
+ .vscode/
29
+ .DS_Store
aiodpc-0.1.0/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2019 caiosweet
4
+ Copyright (c) 2026 Webysther Sperandio
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
aiodpc-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,201 @@
1
+ Metadata-Version: 2.5
2
+ Name: aiodpc
3
+ Version: 0.1.0
4
+ Summary: Async client for the Italian Civil Protection Department (DPC) alert and weather vigilance bulletins
5
+ Author: Webysther Sperandio
6
+ License-Expression: MIT
7
+ License-File: LICENSE
8
+ Keywords: alert,allerta,asyncio,civil protection,dpc,italy,protezione civile,weather
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Framework :: AsyncIO
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Natural Language :: English
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3 :: Only
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Programming Language :: Python :: 3.14
18
+ Classifier: Topic :: Scientific/Engineering :: Atmospheric Science
19
+ Classifier: Topic :: Software Development :: Libraries
20
+ Classifier: Typing :: Typed
21
+ Requires-Python: >=3.13
22
+ Requires-Dist: aiohttp>=3.10
23
+ Requires-Dist: geojson-utils<0.1,>=0.0.3
24
+ Requires-Dist: tzdata; sys_platform == 'win32'
25
+ Description-Content-Type: text/markdown
26
+
27
+ # aiodpc
28
+
29
+ Async Python client for the open data of the Italian Civil Protection
30
+ Department (Dipartimento della Protezione Civile, DPC): the national alert
31
+ bulletins.
32
+
33
+ - **Bollettino di criticità idrogeologica e idraulica**: the alert level
34
+ (green, yellow, orange, red) of each alert zone for today and tomorrow, for
35
+ the hydraulic, thunderstorm and hydrogeological risks.
36
+ - **Bollettino di vigilanza meteorologica**: the expected precipitation of each
37
+ vigilance zone for today, tomorrow and the day after, and the significant
38
+ weather phenomena (heavy rain, wind, sea storms, frost, fog, temperatures).
39
+
40
+ Given a location (coordinates, optionally a municipality), aiodpc finds its
41
+ zone and returns typed results. It is built on `asyncio` and `aiohttp`, has no
42
+ Home Assistant dependency and is fully typed.
43
+
44
+ ## Installation
45
+
46
+ ```bash
47
+ pip install aiodpc
48
+ ```
49
+
50
+ Python 3.13 or later is required.
51
+
52
+ ## Usage
53
+
54
+ ```python
55
+ import asyncio
56
+
57
+ from aiodpc import AlertLevel, DpcClient, DpcError, Risk
58
+
59
+
60
+ async def main() -> None:
61
+ async with DpcClient() as client:
62
+ try:
63
+ criticality = await client.get_criticality(41.9, 12.5)
64
+ vigilance = await client.get_vigilance(
65
+ 41.9, 12.5, phenomena_radius_km=50
66
+ )
67
+ except DpcError as err:
68
+ print(f"DPC data unavailable: {err}")
69
+ return
70
+
71
+ print(f"Criticality bulletin {criticality.id}")
72
+ for day in criticality.days:
73
+ print(f"{day.date} {day.zone_name}: {day.summary.alert}")
74
+ for risk, assessment in day.risks.items():
75
+ print(f" {risk.name.lower()}: {assessment.level.name}")
76
+
77
+ if (today := criticality.today()) and today.max_level >= AlertLevel.YELLOW:
78
+ print("Alert today:", today.risks[Risk.HYDROGEOLOGICAL].info)
79
+
80
+ for day in vigilance.days:
81
+ print(f"{day.date} {day.zone_name}: {day.precipitation}")
82
+ for phenomenon in day.phenomena:
83
+ print(
84
+ f" {phenomenon.category} {phenomenon.description}"
85
+ f" {phenomenon.distance_km} km {phenomenon.direction}"
86
+ )
87
+
88
+
89
+ asyncio.run(main())
90
+ ```
91
+
92
+ Pass your own session with `DpcClient(session)`; the client never closes a
93
+ session it did not create.
94
+
95
+ ### Days and expiry
96
+
97
+ Each day of a bulletin carries its calendar `date` and its `expires` time (the
98
+ midnight, Europe/Rome, that ends the day). Look days up by date instead of by
99
+ position: `bulletin.day_for(date)`, `bulletin.today()` and
100
+ `bulletin.tomorrow()`. After midnight the bulletin published the day before
101
+ still answers `today()` with its second day until DPC publishes a new one.
102
+
103
+ By default, days that are already over are not downloaded
104
+ (`skip_expired=False` to get them all, e.g. for a past `bulletin_id`).
105
+
106
+ ### Polling
107
+
108
+ The bulletin files are large (several MB per day). To poll, check the latest
109
+ ID and fetch the bulletin only when it changed:
110
+
111
+ ```python
112
+ from aiodpc import BulletinKind
113
+
114
+ latest = await client.latest_bulletin_id(BulletinKind.CRITICALITY)
115
+ if latest != criticality.id:
116
+ criticality = await client.get_criticality(41.9, 12.5, bulletin_id=latest)
117
+ ```
118
+
119
+ The criticality bulletin is published every day by 16:00 (Europe/Rome) and may
120
+ be re-issued later the same day ("Aggiornamento"); the vigilance bulletin by
121
+ 15:00.
122
+
123
+ ### Municipality
124
+
125
+ With `municipality="Roma"`, the zones that list the municipality are
126
+ considered and the one with the highest level is used; `zone_name` is the zone
127
+ containing the coordinates. Large municipalities span several zones.
128
+
129
+ ### Coverage check
130
+
131
+ `await client.is_location_covered(lat, lon)` returns whether the coordinates
132
+ are inside a DPC alert zone, for example to validate a configuration.
133
+
134
+ ### Errors
135
+
136
+ All errors derive from `DpcError`:
137
+
138
+ - `DpcConnectionError`: network error, HTTP error status or timeout.
139
+ - `DpcParseError`: invalid JSON or unexpected data format.
140
+ - `DpcLocationError`: the location is not inside any zone of the bulletin.
141
+
142
+ Invalid arguments (coordinates, bulletin IDs) raise `ValueError`.
143
+
144
+ ### Translations and codes
145
+
146
+ The texts written by DPC are kept in Italian (`Assessment.info`,
147
+ `Assessment.alert`, `VigilanceDay.precipitation`,
148
+ `Phenomenon.description`). Codes are exposed for translation and icons:
149
+ `AlertLevel`, `Risk` (value: the DPC code, e.g. `idraulico`),
150
+ `PhenomenonCategory` (e.g. `PRECIPITAZIONI`) and `Phenomenon.code` (the DPC
151
+ `id_fenomeno`).
152
+
153
+ ### Low-level API
154
+
155
+ - `aiodpc.parsers`: pure parsing functions taking the decoded GeoJSON, to parse
156
+ one download for several locations or to test without network.
157
+ - `aiodpc.urls`: URLs of the bulletin files.
158
+ - `aiodpc.discovery`: the latest bulletin ID is read from the DPC map pages by
159
+ default (`MapPageIdSource`); implement `BulletinIdSource` to use another
160
+ source.
161
+
162
+ ## Data source and attribution
163
+
164
+ The data is published by the Dipartimento della Protezione Civile on
165
+ [mappe.protezionecivile.gov.it](https://mappe.protezionecivile.gov.it/) and
166
+ GitHub
167
+ ([pcm-dpc/DPC-Bollettini-Criticita-Idrogeologica-Idraulica](https://github.com/pcm-dpc/DPC-Bollettini-Criticita-Idrogeologica-Idraulica),
168
+ [pcm-dpc/DPC-Bollettini-Vigilanza-Meteorologica](https://github.com/pcm-dpc/DPC-Bollettini-Vigilanza-Meteorologica))
169
+ under the [Creative Commons Attribution 4.0 International (CC BY 4.0)](https://creativecommons.org/licenses/by/4.0/)
170
+ license. Applications showing the data must credit:
171
+
172
+ > Dipartimento della Protezione Civile – Presidenza del Consiglio dei Ministri
173
+
174
+ The text is available as `aiodpc.ATTRIBUTION`.
175
+
176
+ This project is not affiliated with or endorsed by DPC. The bulletins are
177
+ official, but this library is not: for safety decisions, always refer to
178
+ the official DPC and regional channels.
179
+
180
+ ## Development
181
+
182
+ ```bash
183
+ python -m venv .venv && . .venv/bin/activate
184
+ pip install --editable . --group dev # pip >= 25.1
185
+ ruff format --check . && ruff check .
186
+ mypy
187
+ pytest --cov
188
+ ```
189
+
190
+ The tests never reach DPC: a local HTTPS server answers for the DPC hosts.
191
+ `tests/fixtures/real` holds unmodified excerpts of real bulletins to guard the
192
+ data format.
193
+
194
+ ## Credits
195
+
196
+ aiodpc derives from the [DPC Alert](https://github.com/caiosweet/Home-Assistant-custom-components-DPC-Alert)
197
+ Home Assistant integration by caiosweet (MIT license).
198
+
199
+ ## License
200
+
201
+ MIT, see [LICENSE](LICENSE).
aiodpc-0.1.0/README.md ADDED
@@ -0,0 +1,175 @@
1
+ # aiodpc
2
+
3
+ Async Python client for the open data of the Italian Civil Protection
4
+ Department (Dipartimento della Protezione Civile, DPC): the national alert
5
+ bulletins.
6
+
7
+ - **Bollettino di criticità idrogeologica e idraulica**: the alert level
8
+ (green, yellow, orange, red) of each alert zone for today and tomorrow, for
9
+ the hydraulic, thunderstorm and hydrogeological risks.
10
+ - **Bollettino di vigilanza meteorologica**: the expected precipitation of each
11
+ vigilance zone for today, tomorrow and the day after, and the significant
12
+ weather phenomena (heavy rain, wind, sea storms, frost, fog, temperatures).
13
+
14
+ Given a location (coordinates, optionally a municipality), aiodpc finds its
15
+ zone and returns typed results. It is built on `asyncio` and `aiohttp`, has no
16
+ Home Assistant dependency and is fully typed.
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ pip install aiodpc
22
+ ```
23
+
24
+ Python 3.13 or later is required.
25
+
26
+ ## Usage
27
+
28
+ ```python
29
+ import asyncio
30
+
31
+ from aiodpc import AlertLevel, DpcClient, DpcError, Risk
32
+
33
+
34
+ async def main() -> None:
35
+ async with DpcClient() as client:
36
+ try:
37
+ criticality = await client.get_criticality(41.9, 12.5)
38
+ vigilance = await client.get_vigilance(
39
+ 41.9, 12.5, phenomena_radius_km=50
40
+ )
41
+ except DpcError as err:
42
+ print(f"DPC data unavailable: {err}")
43
+ return
44
+
45
+ print(f"Criticality bulletin {criticality.id}")
46
+ for day in criticality.days:
47
+ print(f"{day.date} {day.zone_name}: {day.summary.alert}")
48
+ for risk, assessment in day.risks.items():
49
+ print(f" {risk.name.lower()}: {assessment.level.name}")
50
+
51
+ if (today := criticality.today()) and today.max_level >= AlertLevel.YELLOW:
52
+ print("Alert today:", today.risks[Risk.HYDROGEOLOGICAL].info)
53
+
54
+ for day in vigilance.days:
55
+ print(f"{day.date} {day.zone_name}: {day.precipitation}")
56
+ for phenomenon in day.phenomena:
57
+ print(
58
+ f" {phenomenon.category} {phenomenon.description}"
59
+ f" {phenomenon.distance_km} km {phenomenon.direction}"
60
+ )
61
+
62
+
63
+ asyncio.run(main())
64
+ ```
65
+
66
+ Pass your own session with `DpcClient(session)`; the client never closes a
67
+ session it did not create.
68
+
69
+ ### Days and expiry
70
+
71
+ Each day of a bulletin carries its calendar `date` and its `expires` time (the
72
+ midnight, Europe/Rome, that ends the day). Look days up by date instead of by
73
+ position: `bulletin.day_for(date)`, `bulletin.today()` and
74
+ `bulletin.tomorrow()`. After midnight the bulletin published the day before
75
+ still answers `today()` with its second day until DPC publishes a new one.
76
+
77
+ By default, days that are already over are not downloaded
78
+ (`skip_expired=False` to get them all, e.g. for a past `bulletin_id`).
79
+
80
+ ### Polling
81
+
82
+ The bulletin files are large (several MB per day). To poll, check the latest
83
+ ID and fetch the bulletin only when it changed:
84
+
85
+ ```python
86
+ from aiodpc import BulletinKind
87
+
88
+ latest = await client.latest_bulletin_id(BulletinKind.CRITICALITY)
89
+ if latest != criticality.id:
90
+ criticality = await client.get_criticality(41.9, 12.5, bulletin_id=latest)
91
+ ```
92
+
93
+ The criticality bulletin is published every day by 16:00 (Europe/Rome) and may
94
+ be re-issued later the same day ("Aggiornamento"); the vigilance bulletin by
95
+ 15:00.
96
+
97
+ ### Municipality
98
+
99
+ With `municipality="Roma"`, the zones that list the municipality are
100
+ considered and the one with the highest level is used; `zone_name` is the zone
101
+ containing the coordinates. Large municipalities span several zones.
102
+
103
+ ### Coverage check
104
+
105
+ `await client.is_location_covered(lat, lon)` returns whether the coordinates
106
+ are inside a DPC alert zone, for example to validate a configuration.
107
+
108
+ ### Errors
109
+
110
+ All errors derive from `DpcError`:
111
+
112
+ - `DpcConnectionError`: network error, HTTP error status or timeout.
113
+ - `DpcParseError`: invalid JSON or unexpected data format.
114
+ - `DpcLocationError`: the location is not inside any zone of the bulletin.
115
+
116
+ Invalid arguments (coordinates, bulletin IDs) raise `ValueError`.
117
+
118
+ ### Translations and codes
119
+
120
+ The texts written by DPC are kept in Italian (`Assessment.info`,
121
+ `Assessment.alert`, `VigilanceDay.precipitation`,
122
+ `Phenomenon.description`). Codes are exposed for translation and icons:
123
+ `AlertLevel`, `Risk` (value: the DPC code, e.g. `idraulico`),
124
+ `PhenomenonCategory` (e.g. `PRECIPITAZIONI`) and `Phenomenon.code` (the DPC
125
+ `id_fenomeno`).
126
+
127
+ ### Low-level API
128
+
129
+ - `aiodpc.parsers`: pure parsing functions taking the decoded GeoJSON, to parse
130
+ one download for several locations or to test without network.
131
+ - `aiodpc.urls`: URLs of the bulletin files.
132
+ - `aiodpc.discovery`: the latest bulletin ID is read from the DPC map pages by
133
+ default (`MapPageIdSource`); implement `BulletinIdSource` to use another
134
+ source.
135
+
136
+ ## Data source and attribution
137
+
138
+ The data is published by the Dipartimento della Protezione Civile on
139
+ [mappe.protezionecivile.gov.it](https://mappe.protezionecivile.gov.it/) and
140
+ GitHub
141
+ ([pcm-dpc/DPC-Bollettini-Criticita-Idrogeologica-Idraulica](https://github.com/pcm-dpc/DPC-Bollettini-Criticita-Idrogeologica-Idraulica),
142
+ [pcm-dpc/DPC-Bollettini-Vigilanza-Meteorologica](https://github.com/pcm-dpc/DPC-Bollettini-Vigilanza-Meteorologica))
143
+ under the [Creative Commons Attribution 4.0 International (CC BY 4.0)](https://creativecommons.org/licenses/by/4.0/)
144
+ license. Applications showing the data must credit:
145
+
146
+ > Dipartimento della Protezione Civile – Presidenza del Consiglio dei Ministri
147
+
148
+ The text is available as `aiodpc.ATTRIBUTION`.
149
+
150
+ This project is not affiliated with or endorsed by DPC. The bulletins are
151
+ official, but this library is not: for safety decisions, always refer to
152
+ the official DPC and regional channels.
153
+
154
+ ## Development
155
+
156
+ ```bash
157
+ python -m venv .venv && . .venv/bin/activate
158
+ pip install --editable . --group dev # pip >= 25.1
159
+ ruff format --check . && ruff check .
160
+ mypy
161
+ pytest --cov
162
+ ```
163
+
164
+ The tests never reach DPC: a local HTTPS server answers for the DPC hosts.
165
+ `tests/fixtures/real` holds unmodified excerpts of real bulletins to guard the
166
+ data format.
167
+
168
+ ## Credits
169
+
170
+ aiodpc derives from the [DPC Alert](https://github.com/caiosweet/Home-Assistant-custom-components-DPC-Alert)
171
+ Home Assistant integration by caiosweet (MIT license).
172
+
173
+ ## License
174
+
175
+ MIT, see [LICENSE](LICENSE).
@@ -0,0 +1,115 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.27"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "aiodpc"
7
+ dynamic = ["version"]
8
+ description = "Async client for the Italian Civil Protection Department (DPC) alert and weather vigilance bulletins"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ license-files = ["LICENSE"]
12
+ authors = [{ name = "Webysther Sperandio" }]
13
+ requires-python = ">=3.13"
14
+ keywords = [
15
+ "allerta",
16
+ "alert",
17
+ "asyncio",
18
+ "civil protection",
19
+ "dpc",
20
+ "italy",
21
+ "protezione civile",
22
+ "weather",
23
+ ]
24
+ classifiers = [
25
+ "Development Status :: 3 - Alpha",
26
+ "Framework :: AsyncIO",
27
+ "Intended Audience :: Developers",
28
+ "Natural Language :: English",
29
+ "Operating System :: OS Independent",
30
+ "Programming Language :: Python :: 3",
31
+ "Programming Language :: Python :: 3 :: Only",
32
+ "Programming Language :: Python :: 3.13",
33
+ "Programming Language :: Python :: 3.14",
34
+ "Topic :: Scientific/Engineering :: Atmospheric Science",
35
+ "Topic :: Software Development :: Libraries",
36
+ "Typing :: Typed",
37
+ ]
38
+ dependencies = [
39
+ "aiohttp>=3.10",
40
+ "geojson-utils>=0.0.3,<0.1",
41
+ # zoneinfo needs a time zone database; Windows has none built in.
42
+ "tzdata; sys_platform == 'win32'",
43
+ ]
44
+
45
+ [dependency-groups]
46
+ dev = [
47
+ "mypy>=1.15",
48
+ "pytest>=8.3",
49
+ "pytest-asyncio>=1.0",
50
+ "pytest-cov>=6.0",
51
+ "ruff==0.14.4",
52
+ # Certificates of the local HTTPS server standing in for DPC in the tests
53
+ "trustme>=1.2",
54
+ ]
55
+
56
+ [tool.hatch.version]
57
+ path = "src/aiodpc/__init__.py"
58
+
59
+ [tool.hatch.build.targets.wheel]
60
+ packages = ["src/aiodpc"]
61
+
62
+ [tool.hatch.build.targets.sdist]
63
+ include = ["src", "tests", "README.md", "LICENSE"]
64
+
65
+ [tool.ruff]
66
+ target-version = "py313"
67
+ src = ["src", "tests"]
68
+
69
+ [tool.ruff.lint]
70
+ select = ["ALL"]
71
+ ignore = [
72
+ "COM812", # conflicts with the formatter
73
+ "D203", # incompatible with D211
74
+ "D213", # incompatible with D212
75
+ "PLR0913", # keyword-only options on public methods
76
+ ]
77
+
78
+ [tool.ruff.lint.flake8-type-checking]
79
+ # Keep the imports of dataclass annotations at runtime (typing.get_type_hints).
80
+ runtime-evaluated-decorators = ["dataclasses.dataclass"]
81
+
82
+ [tool.ruff.lint.per-file-ignores]
83
+ "tests/**" = [
84
+ "PLR2004", # magic values in assertions
85
+ "S101", # assert
86
+ "SLF001", # private access to test internals
87
+ ]
88
+
89
+ [tool.mypy]
90
+ python_version = "3.13"
91
+ strict = true
92
+ files = ["src", "tests"]
93
+ mypy_path = "src"
94
+
95
+ [[tool.mypy.overrides]]
96
+ # geojson-utils ships type hints but no py.typed marker.
97
+ module = ["geojson_utils", "geojson_utils.*"]
98
+ ignore_missing_imports = true
99
+
100
+ [tool.pytest.ini_options]
101
+ asyncio_mode = "auto"
102
+ asyncio_default_fixture_loop_scope = "function"
103
+ testpaths = ["tests"]
104
+ addopts = "--strict-markers --strict-config"
105
+ filterwarnings = ["error"]
106
+
107
+ [tool.coverage.run]
108
+ source = ["aiodpc"]
109
+ branch = true
110
+
111
+ [tool.coverage.report]
112
+ show_missing = true
113
+ skip_covered = false
114
+ fail_under = 95
115
+ exclude_also = ["if TYPE_CHECKING:", "\\.\\.\\."]
@@ -0,0 +1,62 @@
1
+ """Async client for the Italian Civil Protection Department (DPC) bulletins.
2
+
3
+ It reads the national "Bollettino di criticità idrogeologica e idraulica"
4
+ (alert levels per risk) and "Bollettino di vigilanza meteorologica" (weather
5
+ vigilance and phenomena) published by DPC as open data.
6
+ """
7
+
8
+ from .client import DpcClient
9
+ from .const import (
10
+ ATTRIBUTION,
11
+ CRITICALITY_PAGE_URL,
12
+ DEFAULT_PHENOMENA_RADIUS_KM,
13
+ DEFAULT_REQUEST_TIMEOUT,
14
+ ROME_TZ,
15
+ VIGILANCE_PAGE_URL,
16
+ )
17
+ from .discovery import BulletinIdSource, MapPageIdSource, TextFetcher
18
+ from .exceptions import DpcConnectionError, DpcError, DpcLocationError, DpcParseError
19
+ from .models import (
20
+ AlertLevel,
21
+ Assessment,
22
+ BulletinKind,
23
+ CriticalityBulletin,
24
+ CriticalityDay,
25
+ Phenomenon,
26
+ PhenomenonCategory,
27
+ Risk,
28
+ VigilanceBulletin,
29
+ VigilanceDay,
30
+ rome_date,
31
+ )
32
+
33
+ __version__ = "0.1.0"
34
+
35
+ __all__ = [
36
+ "ATTRIBUTION",
37
+ "CRITICALITY_PAGE_URL",
38
+ "DEFAULT_PHENOMENA_RADIUS_KM",
39
+ "DEFAULT_REQUEST_TIMEOUT",
40
+ "ROME_TZ",
41
+ "VIGILANCE_PAGE_URL",
42
+ "AlertLevel",
43
+ "Assessment",
44
+ "BulletinIdSource",
45
+ "BulletinKind",
46
+ "CriticalityBulletin",
47
+ "CriticalityDay",
48
+ "DpcClient",
49
+ "DpcConnectionError",
50
+ "DpcError",
51
+ "DpcLocationError",
52
+ "DpcParseError",
53
+ "MapPageIdSource",
54
+ "Phenomenon",
55
+ "PhenomenonCategory",
56
+ "Risk",
57
+ "TextFetcher",
58
+ "VigilanceBulletin",
59
+ "VigilanceDay",
60
+ "__version__",
61
+ "rome_date",
62
+ ]