sgu-client 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.
- sgu_client-0.1.0/PKG-INFO +277 -0
- sgu_client-0.1.0/README.md +263 -0
- sgu_client-0.1.0/pyproject.toml +66 -0
- sgu_client-0.1.0/src/sgu_client/__init__.py +22 -0
- sgu_client-0.1.0/src/sgu_client/client/__init__.py +5 -0
- sgu_client-0.1.0/src/sgu_client/client/base.py +200 -0
- sgu_client-0.1.0/src/sgu_client/client/levels/__init__.py +30 -0
- sgu_client-0.1.0/src/sgu_client/client/levels/modeled.py +275 -0
- sgu_client-0.1.0/src/sgu_client/client/levels/observed.py +431 -0
- sgu_client-0.1.0/src/sgu_client/config.py +32 -0
- sgu_client-0.1.0/src/sgu_client/exceptions.py +39 -0
- sgu_client-0.1.0/src/sgu_client/models/__init__.py +36 -0
- sgu_client-0.1.0/src/sgu_client/models/base.py +41 -0
- sgu_client-0.1.0/src/sgu_client/models/modeled.py +216 -0
- sgu_client-0.1.0/src/sgu_client/models/observed.py +281 -0
- sgu_client-0.1.0/src/sgu_client/models/shared.py +46 -0
- sgu_client-0.1.0/src/sgu_client/py.typed +0 -0
- sgu_client-0.1.0/src/sgu_client/sgu_client.py +51 -0
- sgu_client-0.1.0/src/sgu_client/utils/__init__.py +5 -0
- sgu_client-0.1.0/src/sgu_client/utils/pandas_helpers.py +68 -0
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sgu-client
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A modern Python client library for accessing Geological Survey of Sweden groundwater data APIs with type safety and pandas integration
|
|
5
|
+
Author: Anders Retzner
|
|
6
|
+
Author-email: Anders Retzner <anders.retzner@gmail.com>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Requires-Dist: requests>=2.28.0
|
|
9
|
+
Requires-Dist: pydantic>=2.0.0
|
|
10
|
+
Requires-Dist: pandas>=1.5.0 ; extra == 'recommended'
|
|
11
|
+
Requires-Python: >=3.11
|
|
12
|
+
Provides-Extra: recommended
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
|
|
15
|
+
# SGU Client
|
|
16
|
+
|
|
17
|
+
A modern Python client library for accessing Geological Survey of Sweden (SGU) groundwater data APIs with type safety and pandas integration.
|
|
18
|
+
|
|
19
|
+
[](https://python.org)
|
|
20
|
+
[](https://badge.fury.io/py/sgu-client)
|
|
21
|
+
[](https://opensource.org/licenses/MIT)
|
|
22
|
+
[](https://github.com/astral-sh/ruff)
|
|
23
|
+
|
|
24
|
+
> This package is not affiliated with or endorsed by SGU.
|
|
25
|
+
|
|
26
|
+
## Features
|
|
27
|
+
|
|
28
|
+
- **Type-safe**: Full type hints with Pydantic validation
|
|
29
|
+
- **Pandas integration**: Convert data to DataFrames with optional pandas dependency
|
|
30
|
+
- **Friendly shortcuts**: Convenience functions to access stations by names, modeled levels by coordinates, and much more.
|
|
31
|
+
|
|
32
|
+
Get going with your analysis in just a few lines of code:
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
from sgu_client import SGUClient
|
|
36
|
+
|
|
37
|
+
with SGUClient() as client:
|
|
38
|
+
measurements = client.levels.observed.get_measurements_by_name(platsbeteckning="95_2")
|
|
39
|
+
df = measurements.to_dataframe()
|
|
40
|
+
|
|
41
|
+
# ... rest of your awesome workflow
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Installation
|
|
45
|
+
|
|
46
|
+
Using `uv`
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# basic installation
|
|
50
|
+
uv add sgu-client
|
|
51
|
+
|
|
52
|
+
# with pandas support for dataframe conversion
|
|
53
|
+
uv add "sgu-client[recommended]"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
... or using `pip`
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
# basic installation
|
|
60
|
+
pip install sgu-client
|
|
61
|
+
|
|
62
|
+
# with pandas support for dataframe conversion
|
|
63
|
+
pip install "sgu-client[recommended]"
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Usage
|
|
67
|
+
|
|
68
|
+
### Initializing a client
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
from sgu_client import SGUClient
|
|
72
|
+
|
|
73
|
+
client = SGUClient()
|
|
74
|
+
|
|
75
|
+
# with custom configuration
|
|
76
|
+
from sgu_client import SGUConfig
|
|
77
|
+
config = SGUConfig(timeout=60, debug=True, max_retries=5)
|
|
78
|
+
client = SGUClient(config=config)
|
|
79
|
+
|
|
80
|
+
# as a context manager
|
|
81
|
+
with SGUClient() as client:
|
|
82
|
+
stations = client.levels.observed.get_stations(limit=10)
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Observed groundwater levels
|
|
86
|
+
|
|
87
|
+
Access real-time and historical groundwater monitoring data from SGU's network of observation stations.
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
from sgu_client import SGUClient
|
|
91
|
+
from datetime import UTC, datetime
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
with SGUClient() as client:
|
|
95
|
+
# basic API endpoint usage
|
|
96
|
+
stations = client.levels.observed.get_stations(limit=50)
|
|
97
|
+
|
|
98
|
+
# with OGC API filters, like bbox of southern Sweden
|
|
99
|
+
stations = client.levels.observed.get_stations(
|
|
100
|
+
bbox=[12.0, 55.0, 16.0, 58.0],
|
|
101
|
+
limit=100
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
# convenience function to get station by name
|
|
105
|
+
station = client.levels.observed.get_station_by_name(
|
|
106
|
+
platsbeteckning="95_2" # or obsplatsnamn="95_2"
|
|
107
|
+
)
|
|
108
|
+
# or multiple stations by names
|
|
109
|
+
stations = client.levels.observed.get_stations_by_names(
|
|
110
|
+
platsbeteckning=["95_2", "101_1"] # or obsplatsnamn=["Lagga_2", ...]
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
# convenience function to get measurements by station name
|
|
114
|
+
measurements = client.levels.observed.get_measurements_by_name(
|
|
115
|
+
platsbeteckning="95_2", # or obsplatsnamn="95_2"
|
|
116
|
+
limit=100
|
|
117
|
+
)
|
|
118
|
+
# or multiple stations by names
|
|
119
|
+
measurements = client.levels.observed.get_measurements_by_names(
|
|
120
|
+
platsbeteckning=["95_2", "101_1"], # or obsplatsnamn=["Lagga_2", ...]
|
|
121
|
+
limit=100
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
# filter by datetime for faster responses
|
|
125
|
+
tmin = datetime(2020, 1, 1, tzinfo=UTC)
|
|
126
|
+
tmax = datetime(2021, 1, 1, tzinfo=UTC)
|
|
127
|
+
measurements = client.levels.observed.get_measurements_by_names(
|
|
128
|
+
platsbeteckning=["95_2"], tmin=tmin, tmax=tmax, limit=10
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
# responses that create lists of features can be converted to pandas DataFrames
|
|
132
|
+
measurements = client.levels.observed.get_measurements_by_names(
|
|
133
|
+
platsbeteckning=["95_2", "101_1"], # or obsplatsnamn=["Lagga_2", ...]
|
|
134
|
+
limit=100
|
|
135
|
+
)
|
|
136
|
+
df = measurements.to_dataframe() # requires pandas
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Modeled groundwater levels
|
|
140
|
+
|
|
141
|
+
Access modeled groundwater levels from SGU-HYPE.
|
|
142
|
+
|
|
143
|
+
```python
|
|
144
|
+
from sgu_client import SGUClient
|
|
145
|
+
|
|
146
|
+
with SGUClient() as client:
|
|
147
|
+
# basic API endpoint usage
|
|
148
|
+
areas = client.levels.modeled.get_areas(limit=10)
|
|
149
|
+
|
|
150
|
+
# with OGC API filters, like bbox of southern Sweden
|
|
151
|
+
areas = client.levels.modeled.get_areas(
|
|
152
|
+
bbox=[12.0, 55.0, 16.0, 58.0],
|
|
153
|
+
limit=20
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
# get a specific area by ID
|
|
157
|
+
area = client.levels.modeled.get_area("omraden.30125")
|
|
158
|
+
print(f"Area ID: {area.properties.omrade_id}")
|
|
159
|
+
print(f"Geometry: {area.geometry.type}")
|
|
160
|
+
|
|
161
|
+
# convenience function to get levels for a specific area
|
|
162
|
+
levels = client.levels.modeled.get_levels_by_area(30125, limit=10)
|
|
163
|
+
# or multiple areas by IDs
|
|
164
|
+
levels = client.levels.modeled.get_levels_by_areas(
|
|
165
|
+
area_ids=[30125, 30126],
|
|
166
|
+
limit=50
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
# convenience function to get levels by coordinates
|
|
170
|
+
levels = client.levels.modeled.get_levels_by_coords(
|
|
171
|
+
lat=57.7089,
|
|
172
|
+
lon=11.9746,
|
|
173
|
+
limit=10
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
# responses that create lists of features can be converted to pandas DataFrames
|
|
177
|
+
levels = client.levels.modeled.get_levels_by_areas(
|
|
178
|
+
area_ids=[30125, 30126],
|
|
179
|
+
limit=50
|
|
180
|
+
)
|
|
181
|
+
df = levels.to_dataframe() # requires pandas
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Working with Typed Data
|
|
185
|
+
|
|
186
|
+
All responses are fully typed with Pydantic models:
|
|
187
|
+
|
|
188
|
+
```python
|
|
189
|
+
from sgu_client import SGUClient
|
|
190
|
+
|
|
191
|
+
client = SGUClient()
|
|
192
|
+
|
|
193
|
+
# Get stations with full type safety
|
|
194
|
+
stations = client.levels.observed.get_stations(limit=5)
|
|
195
|
+
|
|
196
|
+
for station in stations.features:
|
|
197
|
+
# All properties are typed and documented
|
|
198
|
+
print(f"Station: {station.properties.obsplatsnamn}")
|
|
199
|
+
print(f"Municipality: {station.properties.kommun}")
|
|
200
|
+
print(f"Coordinates: {station.geometry.coordinates}")
|
|
201
|
+
|
|
202
|
+
# Get measurements with automatic datetime parsing
|
|
203
|
+
measurements = client.levels.observed.get_measurements(limit=5)
|
|
204
|
+
for measurement in measurements.features:
|
|
205
|
+
props = measurement.properties
|
|
206
|
+
print(f"Date: {props.observation_date}") # Parsed datetime object
|
|
207
|
+
print(f"Level: {props.grundvattenniva_m_o_h} m above sea level")
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## API Reference
|
|
211
|
+
|
|
212
|
+
### SGUClient
|
|
213
|
+
|
|
214
|
+
The main client class providing access to all SGU APIs.
|
|
215
|
+
|
|
216
|
+
- `levels.observed` - Observed groundwater level measurements
|
|
217
|
+
- `levels.modeled` - Modeled groundwater levels from SGU-HYPE
|
|
218
|
+
|
|
219
|
+
### Configuration
|
|
220
|
+
|
|
221
|
+
```python
|
|
222
|
+
from sgu_client import SGUConfig
|
|
223
|
+
|
|
224
|
+
config = SGUConfig(
|
|
225
|
+
timeout=30, # Request timeout in seconds
|
|
226
|
+
max_retries=3, # Maximum retry attempts
|
|
227
|
+
debug=False # Enable debug logging
|
|
228
|
+
)
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## Development
|
|
232
|
+
|
|
233
|
+
We recommend using [uv](https://github.com/astral-sh/uv) for development:
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
# Clone the repository
|
|
237
|
+
git clone https://github.com/officialankan/sgu-client.git
|
|
238
|
+
cd sgu-client
|
|
239
|
+
|
|
240
|
+
# Install dependencies and sync environment
|
|
241
|
+
uv sync --all-extras
|
|
242
|
+
|
|
243
|
+
# Run tests
|
|
244
|
+
uv run pytest
|
|
245
|
+
|
|
246
|
+
# Format and lint code
|
|
247
|
+
uv run ruff format
|
|
248
|
+
uv run ruff check --fix
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### Release Process
|
|
252
|
+
|
|
253
|
+
To release a new version:
|
|
254
|
+
|
|
255
|
+
1. Create PR with your changes + version bump in `pyproject.toml`
|
|
256
|
+
2. PR will be tested and published to TestPyPI for verification
|
|
257
|
+
3. Once merged, the new version is automatically published to PyPI
|
|
258
|
+
|
|
259
|
+
## Contributing
|
|
260
|
+
|
|
261
|
+
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
|
|
262
|
+
|
|
263
|
+
## Roadmap
|
|
264
|
+
|
|
265
|
+
- [x] Initial release with observed and modeled groundwater levels
|
|
266
|
+
- [ ] Add example notebooks and tutorials
|
|
267
|
+
- [ ] Add support for groundwater quality API
|
|
268
|
+
- [ ] Add support for geological data API
|
|
269
|
+
|
|
270
|
+
## License
|
|
271
|
+
|
|
272
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
273
|
+
|
|
274
|
+
## Acknowledgments
|
|
275
|
+
|
|
276
|
+
- [Sveriges geologiska undersökning (SGU)](https://www.sgu.se/) for providing open access to groundwater data
|
|
277
|
+
- Built with [uv](https://github.com/astral-sh/uv), [Pydantic](https://pydantic.dev/), and [requests](https://requests.readthedocs.io/)
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
# SGU Client
|
|
2
|
+
|
|
3
|
+
A modern Python client library for accessing Geological Survey of Sweden (SGU) groundwater data APIs with type safety and pandas integration.
|
|
4
|
+
|
|
5
|
+
[](https://python.org)
|
|
6
|
+
[](https://badge.fury.io/py/sgu-client)
|
|
7
|
+
[](https://opensource.org/licenses/MIT)
|
|
8
|
+
[](https://github.com/astral-sh/ruff)
|
|
9
|
+
|
|
10
|
+
> This package is not affiliated with or endorsed by SGU.
|
|
11
|
+
|
|
12
|
+
## Features
|
|
13
|
+
|
|
14
|
+
- **Type-safe**: Full type hints with Pydantic validation
|
|
15
|
+
- **Pandas integration**: Convert data to DataFrames with optional pandas dependency
|
|
16
|
+
- **Friendly shortcuts**: Convenience functions to access stations by names, modeled levels by coordinates, and much more.
|
|
17
|
+
|
|
18
|
+
Get going with your analysis in just a few lines of code:
|
|
19
|
+
|
|
20
|
+
```python
|
|
21
|
+
from sgu_client import SGUClient
|
|
22
|
+
|
|
23
|
+
with SGUClient() as client:
|
|
24
|
+
measurements = client.levels.observed.get_measurements_by_name(platsbeteckning="95_2")
|
|
25
|
+
df = measurements.to_dataframe()
|
|
26
|
+
|
|
27
|
+
# ... rest of your awesome workflow
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
Using `uv`
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# basic installation
|
|
36
|
+
uv add sgu-client
|
|
37
|
+
|
|
38
|
+
# with pandas support for dataframe conversion
|
|
39
|
+
uv add "sgu-client[recommended]"
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
... or using `pip`
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
# basic installation
|
|
46
|
+
pip install sgu-client
|
|
47
|
+
|
|
48
|
+
# with pandas support for dataframe conversion
|
|
49
|
+
pip install "sgu-client[recommended]"
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Usage
|
|
53
|
+
|
|
54
|
+
### Initializing a client
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
from sgu_client import SGUClient
|
|
58
|
+
|
|
59
|
+
client = SGUClient()
|
|
60
|
+
|
|
61
|
+
# with custom configuration
|
|
62
|
+
from sgu_client import SGUConfig
|
|
63
|
+
config = SGUConfig(timeout=60, debug=True, max_retries=5)
|
|
64
|
+
client = SGUClient(config=config)
|
|
65
|
+
|
|
66
|
+
# as a context manager
|
|
67
|
+
with SGUClient() as client:
|
|
68
|
+
stations = client.levels.observed.get_stations(limit=10)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Observed groundwater levels
|
|
72
|
+
|
|
73
|
+
Access real-time and historical groundwater monitoring data from SGU's network of observation stations.
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
from sgu_client import SGUClient
|
|
77
|
+
from datetime import UTC, datetime
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
with SGUClient() as client:
|
|
81
|
+
# basic API endpoint usage
|
|
82
|
+
stations = client.levels.observed.get_stations(limit=50)
|
|
83
|
+
|
|
84
|
+
# with OGC API filters, like bbox of southern Sweden
|
|
85
|
+
stations = client.levels.observed.get_stations(
|
|
86
|
+
bbox=[12.0, 55.0, 16.0, 58.0],
|
|
87
|
+
limit=100
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
# convenience function to get station by name
|
|
91
|
+
station = client.levels.observed.get_station_by_name(
|
|
92
|
+
platsbeteckning="95_2" # or obsplatsnamn="95_2"
|
|
93
|
+
)
|
|
94
|
+
# or multiple stations by names
|
|
95
|
+
stations = client.levels.observed.get_stations_by_names(
|
|
96
|
+
platsbeteckning=["95_2", "101_1"] # or obsplatsnamn=["Lagga_2", ...]
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
# convenience function to get measurements by station name
|
|
100
|
+
measurements = client.levels.observed.get_measurements_by_name(
|
|
101
|
+
platsbeteckning="95_2", # or obsplatsnamn="95_2"
|
|
102
|
+
limit=100
|
|
103
|
+
)
|
|
104
|
+
# or multiple stations by names
|
|
105
|
+
measurements = client.levels.observed.get_measurements_by_names(
|
|
106
|
+
platsbeteckning=["95_2", "101_1"], # or obsplatsnamn=["Lagga_2", ...]
|
|
107
|
+
limit=100
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
# filter by datetime for faster responses
|
|
111
|
+
tmin = datetime(2020, 1, 1, tzinfo=UTC)
|
|
112
|
+
tmax = datetime(2021, 1, 1, tzinfo=UTC)
|
|
113
|
+
measurements = client.levels.observed.get_measurements_by_names(
|
|
114
|
+
platsbeteckning=["95_2"], tmin=tmin, tmax=tmax, limit=10
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
# responses that create lists of features can be converted to pandas DataFrames
|
|
118
|
+
measurements = client.levels.observed.get_measurements_by_names(
|
|
119
|
+
platsbeteckning=["95_2", "101_1"], # or obsplatsnamn=["Lagga_2", ...]
|
|
120
|
+
limit=100
|
|
121
|
+
)
|
|
122
|
+
df = measurements.to_dataframe() # requires pandas
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Modeled groundwater levels
|
|
126
|
+
|
|
127
|
+
Access modeled groundwater levels from SGU-HYPE.
|
|
128
|
+
|
|
129
|
+
```python
|
|
130
|
+
from sgu_client import SGUClient
|
|
131
|
+
|
|
132
|
+
with SGUClient() as client:
|
|
133
|
+
# basic API endpoint usage
|
|
134
|
+
areas = client.levels.modeled.get_areas(limit=10)
|
|
135
|
+
|
|
136
|
+
# with OGC API filters, like bbox of southern Sweden
|
|
137
|
+
areas = client.levels.modeled.get_areas(
|
|
138
|
+
bbox=[12.0, 55.0, 16.0, 58.0],
|
|
139
|
+
limit=20
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
# get a specific area by ID
|
|
143
|
+
area = client.levels.modeled.get_area("omraden.30125")
|
|
144
|
+
print(f"Area ID: {area.properties.omrade_id}")
|
|
145
|
+
print(f"Geometry: {area.geometry.type}")
|
|
146
|
+
|
|
147
|
+
# convenience function to get levels for a specific area
|
|
148
|
+
levels = client.levels.modeled.get_levels_by_area(30125, limit=10)
|
|
149
|
+
# or multiple areas by IDs
|
|
150
|
+
levels = client.levels.modeled.get_levels_by_areas(
|
|
151
|
+
area_ids=[30125, 30126],
|
|
152
|
+
limit=50
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
# convenience function to get levels by coordinates
|
|
156
|
+
levels = client.levels.modeled.get_levels_by_coords(
|
|
157
|
+
lat=57.7089,
|
|
158
|
+
lon=11.9746,
|
|
159
|
+
limit=10
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
# responses that create lists of features can be converted to pandas DataFrames
|
|
163
|
+
levels = client.levels.modeled.get_levels_by_areas(
|
|
164
|
+
area_ids=[30125, 30126],
|
|
165
|
+
limit=50
|
|
166
|
+
)
|
|
167
|
+
df = levels.to_dataframe() # requires pandas
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Working with Typed Data
|
|
171
|
+
|
|
172
|
+
All responses are fully typed with Pydantic models:
|
|
173
|
+
|
|
174
|
+
```python
|
|
175
|
+
from sgu_client import SGUClient
|
|
176
|
+
|
|
177
|
+
client = SGUClient()
|
|
178
|
+
|
|
179
|
+
# Get stations with full type safety
|
|
180
|
+
stations = client.levels.observed.get_stations(limit=5)
|
|
181
|
+
|
|
182
|
+
for station in stations.features:
|
|
183
|
+
# All properties are typed and documented
|
|
184
|
+
print(f"Station: {station.properties.obsplatsnamn}")
|
|
185
|
+
print(f"Municipality: {station.properties.kommun}")
|
|
186
|
+
print(f"Coordinates: {station.geometry.coordinates}")
|
|
187
|
+
|
|
188
|
+
# Get measurements with automatic datetime parsing
|
|
189
|
+
measurements = client.levels.observed.get_measurements(limit=5)
|
|
190
|
+
for measurement in measurements.features:
|
|
191
|
+
props = measurement.properties
|
|
192
|
+
print(f"Date: {props.observation_date}") # Parsed datetime object
|
|
193
|
+
print(f"Level: {props.grundvattenniva_m_o_h} m above sea level")
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## API Reference
|
|
197
|
+
|
|
198
|
+
### SGUClient
|
|
199
|
+
|
|
200
|
+
The main client class providing access to all SGU APIs.
|
|
201
|
+
|
|
202
|
+
- `levels.observed` - Observed groundwater level measurements
|
|
203
|
+
- `levels.modeled` - Modeled groundwater levels from SGU-HYPE
|
|
204
|
+
|
|
205
|
+
### Configuration
|
|
206
|
+
|
|
207
|
+
```python
|
|
208
|
+
from sgu_client import SGUConfig
|
|
209
|
+
|
|
210
|
+
config = SGUConfig(
|
|
211
|
+
timeout=30, # Request timeout in seconds
|
|
212
|
+
max_retries=3, # Maximum retry attempts
|
|
213
|
+
debug=False # Enable debug logging
|
|
214
|
+
)
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## Development
|
|
218
|
+
|
|
219
|
+
We recommend using [uv](https://github.com/astral-sh/uv) for development:
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
# Clone the repository
|
|
223
|
+
git clone https://github.com/officialankan/sgu-client.git
|
|
224
|
+
cd sgu-client
|
|
225
|
+
|
|
226
|
+
# Install dependencies and sync environment
|
|
227
|
+
uv sync --all-extras
|
|
228
|
+
|
|
229
|
+
# Run tests
|
|
230
|
+
uv run pytest
|
|
231
|
+
|
|
232
|
+
# Format and lint code
|
|
233
|
+
uv run ruff format
|
|
234
|
+
uv run ruff check --fix
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Release Process
|
|
238
|
+
|
|
239
|
+
To release a new version:
|
|
240
|
+
|
|
241
|
+
1. Create PR with your changes + version bump in `pyproject.toml`
|
|
242
|
+
2. PR will be tested and published to TestPyPI for verification
|
|
243
|
+
3. Once merged, the new version is automatically published to PyPI
|
|
244
|
+
|
|
245
|
+
## Contributing
|
|
246
|
+
|
|
247
|
+
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
|
|
248
|
+
|
|
249
|
+
## Roadmap
|
|
250
|
+
|
|
251
|
+
- [x] Initial release with observed and modeled groundwater levels
|
|
252
|
+
- [ ] Add example notebooks and tutorials
|
|
253
|
+
- [ ] Add support for groundwater quality API
|
|
254
|
+
- [ ] Add support for geological data API
|
|
255
|
+
|
|
256
|
+
## License
|
|
257
|
+
|
|
258
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
259
|
+
|
|
260
|
+
## Acknowledgments
|
|
261
|
+
|
|
262
|
+
- [Sveriges geologiska undersökning (SGU)](https://www.sgu.se/) for providing open access to groundwater data
|
|
263
|
+
- Built with [uv](https://github.com/astral-sh/uv), [Pydantic](https://pydantic.dev/), and [requests](https://requests.readthedocs.io/)
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "sgu-client"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "A modern Python client library for accessing Geological Survey of Sweden groundwater data APIs with type safety and pandas integration"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
authors = [{ name = "Anders Retzner", email = "anders.retzner@gmail.com" }]
|
|
7
|
+
license = "MIT"
|
|
8
|
+
requires-python = ">=3.11"
|
|
9
|
+
dependencies = ["requests>=2.28.0", "pydantic>=2.0.0"]
|
|
10
|
+
|
|
11
|
+
[build-system]
|
|
12
|
+
requires = ["uv_build>=0.8.14,<0.9.0"]
|
|
13
|
+
build-backend = "uv_build"
|
|
14
|
+
|
|
15
|
+
[project.optional-dependencies]
|
|
16
|
+
recommended = ["pandas>=1.5.0"]
|
|
17
|
+
|
|
18
|
+
[dependency-groups]
|
|
19
|
+
dev = [
|
|
20
|
+
"pytest-cov>=6.0.0",
|
|
21
|
+
"pytest>=8.4.1",
|
|
22
|
+
"ruff>=0.12.11",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
[tool.ruff]
|
|
26
|
+
line-length = 88
|
|
27
|
+
target-version = "py311"
|
|
28
|
+
|
|
29
|
+
[tool.ruff.lint]
|
|
30
|
+
select = [
|
|
31
|
+
"E", # pycodestyle errors
|
|
32
|
+
"W", # pycodestyle warnings
|
|
33
|
+
"F", # pyflakes
|
|
34
|
+
"I", # isort
|
|
35
|
+
"B", # flake8-bugbear
|
|
36
|
+
"C4", # flake8-comprehensions
|
|
37
|
+
"UP", # pyupgrade
|
|
38
|
+
"ARG", # flake8-unused-arguments
|
|
39
|
+
"SIM", # flake8-simplify
|
|
40
|
+
"TCH", # flake8-type-checking
|
|
41
|
+
"TID", # flake8-tidy-imports
|
|
42
|
+
"RUF", # Ruff-specific rules
|
|
43
|
+
]
|
|
44
|
+
ignore = [
|
|
45
|
+
"E501", # line too long, handled by formatter
|
|
46
|
+
"B008", # do not perform function calls in argument defaults
|
|
47
|
+
"C901", # too complex
|
|
48
|
+
"W191", # indentation contains tabs
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
[tool.ruff.format]
|
|
52
|
+
quote-style = "double"
|
|
53
|
+
indent-style = "space"
|
|
54
|
+
skip-magic-trailing-comma = false
|
|
55
|
+
line-ending = "auto"
|
|
56
|
+
|
|
57
|
+
[tool.ruff.lint.per-file-ignores]
|
|
58
|
+
"__init__.py" = ["F401"] # Allow unused imports in __init__.py files
|
|
59
|
+
|
|
60
|
+
[tool.ruff.lint.isort]
|
|
61
|
+
known-first-party = ["sgu_client"]
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
[tool.pytest.ini_options]
|
|
65
|
+
addopts = "--cov=src --cov-report=term-missing --cov-report=html --cov-branch"
|
|
66
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""SGU Client - Python library for accessing SGU groundwater data."""
|
|
2
|
+
|
|
3
|
+
from .config import SGUConfig
|
|
4
|
+
from .exceptions import (
|
|
5
|
+
SGUAPIError,
|
|
6
|
+
SGUClientError,
|
|
7
|
+
SGUConnectionError,
|
|
8
|
+
SGUTimeoutError,
|
|
9
|
+
SGUValidationError,
|
|
10
|
+
)
|
|
11
|
+
from .sgu_client import SGUClient
|
|
12
|
+
|
|
13
|
+
__version__ = "0.1.0"
|
|
14
|
+
__all__ = [
|
|
15
|
+
"SGUAPIError",
|
|
16
|
+
"SGUClient",
|
|
17
|
+
"SGUClientError",
|
|
18
|
+
"SGUConfig",
|
|
19
|
+
"SGUConnectionError",
|
|
20
|
+
"SGUTimeoutError",
|
|
21
|
+
"SGUValidationError",
|
|
22
|
+
]
|