guidelinely 1.0.19.dev0__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 (32) hide show
  1. guidelinely-1.0.19.dev0/.github/workflows/ci.yml +127 -0
  2. guidelinely-1.0.19.dev0/.gitignore +53 -0
  3. guidelinely-1.0.19.dev0/.pre-commit-config.yaml +34 -0
  4. guidelinely-1.0.19.dev0/LICENSE +21 -0
  5. guidelinely-1.0.19.dev0/PKG-INFO +389 -0
  6. guidelinely-1.0.19.dev0/README.md +352 -0
  7. guidelinely-1.0.19.dev0/examples/01_basic_metadata.py +72 -0
  8. guidelinely-1.0.19.dev0/examples/02_calculate_single_parameter.py +73 -0
  9. guidelinely-1.0.19.dev0/examples/03_batch_calculations.py +87 -0
  10. guidelinely-1.0.19.dev0/examples/04_groundwater_calculations.py +83 -0
  11. guidelinely-1.0.19.dev0/examples/05_advanced_workflow.py +155 -0
  12. guidelinely-1.0.19.dev0/examples/README.md +27 -0
  13. guidelinely-1.0.19.dev0/guidelinely/__init__.py +62 -0
  14. guidelinely-1.0.19.dev0/guidelinely/_version.py +34 -0
  15. guidelinely-1.0.19.dev0/guidelinely/auth.py +29 -0
  16. guidelinely-1.0.19.dev0/guidelinely/cache.py +53 -0
  17. guidelinely-1.0.19.dev0/guidelinely/client.py +621 -0
  18. guidelinely-1.0.19.dev0/guidelinely/exceptions.py +103 -0
  19. guidelinely-1.0.19.dev0/guidelinely/models.py +153 -0
  20. guidelinely-1.0.19.dev0/guidelinely.egg-info/PKG-INFO +389 -0
  21. guidelinely-1.0.19.dev0/guidelinely.egg-info/SOURCES.txt +30 -0
  22. guidelinely-1.0.19.dev0/guidelinely.egg-info/dependency_links.txt +1 -0
  23. guidelinely-1.0.19.dev0/guidelinely.egg-info/requires.txt +14 -0
  24. guidelinely-1.0.19.dev0/guidelinely.egg-info/top_level.txt +1 -0
  25. guidelinely-1.0.19.dev0/pyproject.toml +85 -0
  26. guidelinely-1.0.19.dev0/setup.cfg +4 -0
  27. guidelinely-1.0.19.dev0/tests/__init__.py +1 -0
  28. guidelinely-1.0.19.dev0/tests/test_auth.py +37 -0
  29. guidelinely-1.0.19.dev0/tests/test_cache.py +338 -0
  30. guidelinely-1.0.19.dev0/tests/test_client.py +428 -0
  31. guidelinely-1.0.19.dev0/tests/test_edge_cases.py +519 -0
  32. guidelinely-1.0.19.dev0/tests/test_models.py +213 -0
@@ -0,0 +1,127 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ tags: [ 'v*' ] # Run on version tags
7
+ pull_request:
8
+ branches: [ main ]
9
+
10
+ jobs:
11
+ test:
12
+ runs-on: ubuntu-latest
13
+ strategy:
14
+ matrix:
15
+ python-version: ["3.9", "3.10", "3.11", "3.12"]
16
+
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+
20
+ - name: Set up Python ${{ matrix.python-version }}
21
+ uses: actions/setup-python@v5
22
+ with:
23
+ python-version: ${{ matrix.python-version }}
24
+
25
+ - name: Cache pip dependencies
26
+ uses: actions/cache@v4
27
+ with:
28
+ path: ~/.cache/pip
29
+ key: ${{ runner.os }}-pip-${{ matrix.python-version }}-${{ hashFiles('**/pyproject.toml') }}
30
+ restore-keys: |
31
+ ${{ runner.os }}-pip-${{ matrix.python-version }}-
32
+ ${{ runner.os }}-pip-
33
+
34
+ - name: Install dependencies
35
+ run: |
36
+ python -m pip install --upgrade pip
37
+ pip install -e ".[dev]"
38
+
39
+ - name: Run tests with coverage
40
+ run: |
41
+ pytest --cov=guidelinely --cov-report=xml --cov-report=term-missing
42
+
43
+ - name: Upload coverage to Codecov
44
+ uses: codecov/codecov-action@v4
45
+ with:
46
+ file: ./coverage.xml
47
+ flags: unittests
48
+ name: codecov-umbrella
49
+ fail_ci_if_error: false
50
+
51
+ lint:
52
+ runs-on: ubuntu-latest
53
+ steps:
54
+ - uses: actions/checkout@v4
55
+
56
+ - name: Set up Python
57
+ uses: actions/setup-python@v5
58
+ with:
59
+ python-version: "3.11"
60
+
61
+ - name: Cache pip dependencies
62
+ uses: actions/cache@v4
63
+ with:
64
+ path: ~/.cache/pip
65
+ key: ${{ runner.os }}-pip-lint-${{ hashFiles('**/pyproject.toml') }}
66
+ restore-keys: |
67
+ ${{ runner.os }}-pip-lint-
68
+ ${{ runner.os }}-pip-
69
+
70
+ - name: Install dependencies
71
+ run: |
72
+ python -m pip install --upgrade pip
73
+ pip install -e ".[dev]"
74
+
75
+ - name: Check formatting with Black
76
+ run: black --check --exclude='_version\.py' guidelinely/ tests/
77
+
78
+ - name: Lint with Ruff
79
+ run: ruff check guidelinely/ tests/
80
+
81
+ - name: Type check with MyPy
82
+ run: mypy guidelinely/
83
+
84
+ build:
85
+ runs-on: ubuntu-latest
86
+ steps:
87
+ - uses: actions/checkout@v4
88
+ with:
89
+ fetch-depth: 0 # Fetch all history and tags for setuptools_scm versioning
90
+
91
+ - name: Set up Python
92
+ uses: actions/setup-python@v5
93
+ with:
94
+ python-version: "3.11"
95
+
96
+ - name: Install build dependencies
97
+ run: |
98
+ python -m pip install --upgrade pip
99
+ pip install build
100
+
101
+ - name: Build package
102
+ run: python -m build
103
+
104
+ - name: Check build artifacts
105
+ run: ls -la dist/
106
+
107
+ - name: Upload build artifacts
108
+ uses: actions/upload-artifact@v4
109
+ with:
110
+ name: dist
111
+ path: dist/
112
+
113
+ publish:
114
+ runs-on: ubuntu-latest
115
+ needs: [test, lint, build]
116
+ if: startsWith(github.ref, 'refs/tags/v') # Only publish on version tags
117
+ permissions:
118
+ id-token: write # Required for trusted publishing
119
+ steps:
120
+ - name: Download build artifacts
121
+ uses: actions/download-artifact@v4
122
+ with:
123
+ name: dist
124
+ path: dist/
125
+
126
+ - name: Publish to PyPI
127
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,53 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ build/
8
+ develop-eggs/
9
+ dist/
10
+ downloads/
11
+ eggs/
12
+ .eggs/
13
+ lib/
14
+ lib64/
15
+ parts/
16
+ sdist/
17
+ var/
18
+ wheels/
19
+ *.egg-info/
20
+ .installed.cfg
21
+ *.egg
22
+
23
+ # Virtual environments
24
+ venv/
25
+ env/
26
+ ENV/
27
+ .venv
28
+
29
+ # Testing
30
+ .pytest_cache/
31
+ .coverage
32
+ htmlcov/
33
+ .tox/
34
+
35
+ # IDE
36
+ .vscode/
37
+ .idea/
38
+ *.swp
39
+ *.swo
40
+ *~
41
+
42
+ # Type checking
43
+ .mypy_cache/
44
+ .dmypy.json
45
+ dmypy.json
46
+
47
+ # R reference (temporary)
48
+ r_reference/
49
+
50
+ # OS
51
+ .DS_Store
52
+ Thumbs.db
53
+ *ipynb
@@ -0,0 +1,34 @@
1
+ repos:
2
+ - repo: https://github.com/psf/black
3
+ rev: 24.10.0
4
+ hooks:
5
+ - id: black
6
+ args: [--check, --line-length=100]
7
+ files: ^(guidelinely|tests)/
8
+ exclude: ^guidelinely/_version\.py$
9
+
10
+ - repo: https://github.com/astral-sh/ruff-pre-commit
11
+ rev: v0.8.1
12
+ hooks:
13
+ - id: ruff
14
+ files: ^(guidelinely|tests)/
15
+
16
+ - repo: https://github.com/pre-commit/mirrors-mypy
17
+ rev: v1.13.0
18
+ hooks:
19
+ - id: mypy
20
+ files: ^guidelinely/
21
+ additional_dependencies:
22
+ - httpx>=0.25.0
23
+ - pydantic>=2.0.0
24
+ - diskcache>=5.6.0
25
+
26
+ - repo: local
27
+ hooks:
28
+ - id: pytest
29
+ name: pytest
30
+ entry: pytest --cov=guidelinely --cov-report=term-missing
31
+ language: system
32
+ types: [python]
33
+ pass_filenames: false
34
+ always_run: true
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Guidelinely Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,389 @@
1
+ Metadata-Version: 2.4
2
+ Name: guidelinely
3
+ Version: 1.0.19.dev0
4
+ Summary: Python client for the Guidelinely Environmental Guidelines API
5
+ Author-email: Michael Davison <michael.davison@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/mpdavison/envguidelines-py
8
+ Project-URL: Documentation, https://guidelines.1681248.com/docs
9
+ Project-URL: Repository, https://github.com/mpdavison/envguidelines-py
10
+ Project-URL: Bug Tracker, https://github.com/mpdavison/envguidelines-py/issues
11
+ Keywords: environmental,guidelines,api,water quality,soil,sediment
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Scientific/Engineering
20
+ Requires-Python: >=3.9
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Requires-Dist: httpx>=0.25.0
24
+ Requires-Dist: pydantic>=2.0.0
25
+ Requires-Dist: diskcache>=5.6.0
26
+ Provides-Extra: dev
27
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
28
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
29
+ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
30
+ Requires-Dist: pytest-httpx>=0.30.0; extra == "dev"
31
+ Requires-Dist: responses>=0.23.0; extra == "dev"
32
+ Requires-Dist: black>=23.0.0; extra == "dev"
33
+ Requires-Dist: mypy>=1.0.0; extra == "dev"
34
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
35
+ Requires-Dist: pre-commit>=3.0.0; extra == "dev"
36
+ Dynamic: license-file
37
+
38
+ # Guidelinely Python Client
39
+
40
+ [![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/downloads/)
41
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
42
+
43
+ Python client library for the [Guidelinely API](https://guidelines.1681248.com/docs) - an environmental guideline calculation and search API.
44
+
45
+ Calculate context-dependent environmental guideline values for chemical parameters (Aluminum, Copper, Lead, etc.) in various media (water, soil, sediment) based on environmental conditions (pH, hardness, temperature, etc.).
46
+
47
+ This Python client mirrors the functionality of the [R client](https://github.com/mpdavison/envguidelines).
48
+
49
+ ## Features
50
+
51
+ - **Metadata Queries**: List parameters, search, explore media types and sources
52
+ - **Single Calculations**: Calculate guidelines for individual parameters
53
+ - **Batch Calculations**: Efficiently calculate multiple parameters (up to 50)
54
+ - **Context-Aware**: Support for pH, hardness, temperature, and other environmental factors
55
+ - **Unit Conversion**: Optional target unit specification
56
+ - **Type Safety**: Full Pydantic model support for request/response validation
57
+ - **Comprehensive Tests**: Mock-based test suite with pytest-httpx
58
+
59
+ ## Installation
60
+
61
+ Requires **Python 3.9+**.
62
+
63
+ ```bash
64
+ # Install from PyPI (when available)
65
+ pip install guidelinely
66
+
67
+ # Or install from source
68
+ git clone https://github.com/mpdavison/envguidelines-py.git
69
+ cd envguidelines-py
70
+ pip install -e . # Development mode
71
+ pip install -e ".[dev]" # With dev dependencies
72
+ ```
73
+
74
+ ## Quick Start
75
+
76
+ ```python
77
+ from guidelinely import calculate_guidelines
78
+
79
+ # Calculate dissolved aluminum guidelines in surface water
80
+ result = calculate_guidelines(
81
+ parameter="Aluminum, Dissolved",
82
+ media="surface_water",
83
+ context={
84
+ "hardness": "100 mg/L" # Water hardness as CaCO3
85
+ }
86
+ )
87
+
88
+ print(f"Found {result.total_count} guidelines")
89
+ for guideline in result.results:
90
+ print(f"{guideline.parameter}: {guideline.value} ({guideline.source})")
91
+ ```
92
+
93
+ ## API Key
94
+
95
+ Calculation endpoints optionally accept an API key. Set it as an environment variable:
96
+
97
+ ```bash
98
+ export GUIDELINELY_API_KEY="your_api_key_here"
99
+ ```
100
+
101
+ Metadata endpoints (list parameters, search, etc.) work without authentication.
102
+
103
+ ## Environment Variables
104
+
105
+ The library supports the following environment variables for configuration:
106
+
107
+ | Variable | Description | Default |
108
+ |----------|-------------|---------|
109
+ | `GUIDELINELY_API_KEY` | API key for calculation endpoints | None (optional) |
110
+ | `GUIDELINELY_CACHE_DIR` | Directory for persistent caching | `~/.guidelinely_cache` |
111
+ | `GUIDELINELY_CACHE_TTL` | Cache time-to-live in seconds | `604800` (7 days) |
112
+ | `GUIDELINELY_TIMEOUT` | HTTP request timeout in seconds | `30` |
113
+
114
+ ### Cache Configuration
115
+
116
+ By default, calculation results are cached to `~/.guidelinely_cache` for 7 days. You can customize the location and TTL:
117
+
118
+ ```bash
119
+ export GUIDELINELY_CACHE_DIR="/path/to/custom/cache"
120
+ export GUIDELINELY_CACHE_TTL="86400" # 1 day in seconds
121
+ ```
122
+
123
+ To manually clear the cache:
124
+
125
+ ```python
126
+ from guidelinely.cache import cache
127
+ cache.clear()
128
+ ```
129
+
130
+ ## Usage Examples
131
+
132
+ ### Basic Metadata Queries
133
+
134
+ ```python
135
+ from guidelinely import (
136
+ health_check,
137
+ list_parameters,
138
+ search_parameters,
139
+ list_media,
140
+ list_sources,
141
+ get_stats,
142
+ )
143
+
144
+ # Check API health
145
+ status = health_check()
146
+
147
+ # List all chemical parameters
148
+ params = list_parameters()
149
+ print(f"Available parameters: {len(params)}")
150
+
151
+ # Search for ammonia-related parameters
152
+ ammonia = search_parameters("ammon")
153
+ print(ammonia) # ['Ammonia', 'Ammonium', ...]
154
+
155
+ # Get available media types
156
+ media = list_media()
157
+ # {'surface_water': 'Surface Water', 'soil': 'Soil', ...}
158
+
159
+ # View guideline sources
160
+ sources = list_sources()
161
+
162
+ # Database statistics
163
+ stats = get_stats()
164
+ ```
165
+
166
+ ### Single Parameter Calculation
167
+
168
+ ```python
169
+ from guidelinely import calculate_guidelines
170
+ import os
171
+
172
+ os.environ["GUIDELINELY_API_KEY"] = "your_key"
173
+
174
+ result = calculate_guidelines(
175
+ parameter="Ammonia, un-ionized as N",
176
+ media="surface_water",
177
+ context={
178
+ "pH": "7.5 1",
179
+ "temperature": "15 °C"
180
+ },
181
+ target_unit="mg/L" # Optional unit conversion
182
+ )
183
+
184
+ # Filter results
185
+ chronic_aquatic = [
186
+ g for g in result.results
187
+ if g.basis == "aquatic biota" and g.exposure_duration == "Chronic"
188
+ ]
189
+ ```
190
+
191
+ ### Batch Calculations
192
+
193
+ ```python
194
+ from guidelinely import calculate_batch
195
+
196
+ # Calculate multiple parameters at once (more efficient)
197
+ result = calculate_batch(
198
+ parameters=["Aluminum, Dissolved", "Ammonia, un-ionized as N", "Lead, Dissolved", "Sulfate as SO4", "Nitrite as N"],
199
+ media="surface_water",
200
+ context={
201
+ "pH": "7.5 1",
202
+ "hardness": "150 mg/L",
203
+ "temperature": "15 °C",
204
+ "chloride": "18 mg/L"
205
+ }
206
+ )
207
+
208
+ print(f"Total: {result.total_count} guidelines")
209
+
210
+ # With per-parameter unit conversion
211
+ result = calculate_batch(
212
+ parameters=[
213
+ "Aluminum, Dissolved",
214
+ {"name": "Lead, Dissolved", "target_unit": "mg/L"}
215
+ ],
216
+ media="surface_water",
217
+ context={
218
+ "hardness": "100 mg/L",
219
+ }
220
+ )
221
+ ```
222
+
223
+ ## Environmental Context Parameters
224
+
225
+ > **Note**: Currently, only **surface_water** and **groundwater** guidelines are present in the API database. Soil, sediment, and other media types are planned for future releases.
226
+
227
+ All context parameters **must be strings with units** (Pint format):
228
+
229
+ ### Water (surface_water, groundwater)
230
+ ```python
231
+ context = {
232
+ "pH": "7.0 1", # Dimensionless - use "1" as unit
233
+ "hardness": "100 mg/L", # mg/L as CaCO3
234
+ "temperature": "20 °C",
235
+ "chloride": "50 mg/L"
236
+ }
237
+ ```
238
+
239
+ ### Soil (coming soon)
240
+ ```python
241
+ context = {
242
+ "pH": "6.5 1",
243
+ "organic_matter": "3.5 %",
244
+ "cation_exchange_capacity": "15 meq/100g"
245
+ }
246
+ ```
247
+
248
+ ### Sediment (coming soon)
249
+ ```python
250
+ context = {
251
+ "pH": "7.0 1",
252
+ "organic_matter": "2.5 %",
253
+ "grain_size": "0.5 mm"
254
+ }
255
+ ```
256
+
257
+ ## Error Handling
258
+
259
+ The library provides custom exceptions for structured error handling:
260
+
261
+ ```python
262
+ from guidelinely import (
263
+ calculate_guidelines,
264
+ GuidelinelyError,
265
+ GuidelinelyAPIError,
266
+ GuidelinelyTimeoutError,
267
+ )
268
+
269
+ try:
270
+ result = calculate_guidelines(
271
+ parameter="Copper",
272
+ media="surface_water",
273
+ context={"pH": "7.0 1", "hardness": "100 mg/L"}
274
+ )
275
+ except GuidelinelyTimeoutError:
276
+ print("Request timed out, please try again")
277
+ except GuidelinelyAPIError as e:
278
+ if e.status_code == 404:
279
+ print("Parameter not found")
280
+ elif e.status_code == 401:
281
+ print("Invalid API key")
282
+ else:
283
+ print(f"API error {e.status_code}: {e.message}")
284
+ except GuidelinelyError as e:
285
+ print(f"Guidelinely error: {e}")
286
+ ```
287
+
288
+ ### Exception Types
289
+
290
+ - `GuidelinelyError` - Base exception for all library errors
291
+ - `GuidelinelyAPIError` - API returned an error response (has `status_code` and `message` attributes)
292
+ - `GuidelinelyTimeoutError` - Request timed out
293
+
294
+ ## Data Models
295
+
296
+ The library uses Pydantic for type-safe data handling:
297
+
298
+ ```python
299
+ from guidelinely.models import GuidelineResponse, CalculationResponse
300
+
301
+ # All API responses are strongly typed
302
+ result: CalculationResponse = calculate_guidelines(...)
303
+
304
+ # Access typed fields
305
+ for guideline in result.results:
306
+ guideline.parameter # str
307
+ guideline.value # str (PostgreSQL unitrange format)
308
+ guideline.lower # Optional[float]
309
+ guideline.upper # Optional[float]
310
+ guideline.unit # str
311
+ guideline.is_calculated # bool
312
+ ```
313
+
314
+ ## Guideline Value Format
315
+
316
+ Guidelines use [postgresql-unit](https://github.com/df7cb/postgresql-unit) `unitrange` format:
317
+ - `[10 μg/L,100 μg/L]` - Range from 10 to 100 μg/L
318
+ - `(,87.0 μg/L]` - Upper limit only (≤87.0 μg/L)
319
+ - `[5.0 mg/L,)` - Lower limit only (≥5.0 mg/L)
320
+
321
+ Parsed into `lower`, `upper`, and `unit` fields.
322
+
323
+ ## Development
324
+
325
+ ```bash
326
+ # Install development dependencies
327
+ pip install -e ".[dev]"
328
+
329
+ # Run tests
330
+ pytest
331
+
332
+ # Run tests with coverage
333
+ pytest --cov=guidelinely --cov-report=html
334
+
335
+ # Format code
336
+ black guidelinely/ tests/ examples/
337
+
338
+ # Type checking
339
+ mypy guidelinely/
340
+
341
+ # Linting
342
+ ruff check guidelinely/ tests/
343
+ ```
344
+
345
+ ## API Reference
346
+
347
+ ### Client Functions
348
+
349
+ - `health_check()` - Service health check
350
+ - `readiness_check()` - Database readiness check
351
+ - `list_parameters()` - List all chemical parameters
352
+ - `search_parameters(q, media)` - Search parameters
353
+ - `list_media()` - List media types
354
+ - `list_sources()` - List guideline sources
355
+ - `get_stats()` - Database statistics
356
+ - `calculate_guidelines(parameter, media, context, target_unit, api_key)` - Calculate single parameter
357
+ - `calculate_batch(parameters, media, context, api_key)` - Batch calculate (max 50 parameters)
358
+
359
+ ### Models
360
+
361
+ - `GuidelineResponse` - Single guideline result
362
+ - `CalculationResponse` - Calculation endpoint response
363
+ - `CalculateRequest` - Single calculation request body
364
+ - `BatchCalculateRequest` - Batch calculation request body
365
+
366
+ ## Examples
367
+
368
+ See the `examples/` directory for complete working examples:
369
+
370
+ 1. `01_basic_metadata.py` - Basic metadata queries
371
+ 2. `02_calculate_single_parameter.py` - Single parameter calculations
372
+ 3. `03_batch_calculations.py` - Batch calculations
373
+ 4. `04_groundwater_calculations.py` - Groundwater calculations (soil guidelines coming soon)
374
+ 5. `05_advanced_workflow.py` - Advanced filtering and analysis
375
+
376
+ ## Resources
377
+
378
+ - **API Documentation**: https://guidelines.1681248.com/docs
379
+ - **OpenAPI Spec**: https://guidelines.1681248.com/openapi.json
380
+ - **R Client**: https://github.com/mpdavison/envguidelines
381
+ - **Issue Tracker**: https://github.com/mpdavison/envguidelines-py/issues
382
+
383
+ ## License
384
+
385
+ MIT License - see [LICENSE](LICENSE) file for details.
386
+
387
+ ## Contributing
388
+
389
+ Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for development setup, code style guidelines, and the pull request process.