Metadata-Version: 2.5
Name: environment-client
Version: 0.5.16
Summary: Python client for DEFRA's environment.data.gov.uk APIs (typed, async-friendly)
Project-URL: Bug Tracker, https://github.com/cogna-public/environment-client/issues
Project-URL: Homepage, https://github.com/cogna-public/environment-client
Author-email: "Cogna.co" <engineering@cogna.co>
License: MIT License
        
        Copyright (c) 2025 cogna-public
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Keywords: api,defra,environment,environment.data.gov.uk,flood,hydrology,uk
Classifier: Development Status :: 3 - Alpha
Classifier: Framework :: AsyncIO
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Typing :: Typed
Requires-Python: >=3.12
Requires-Dist: httpx>=0.28.1
Requires-Dist: pydantic>=2.11.7
Requires-Dist: pyyaml>=6.0.2
Description-Content-Type: text/markdown

# DEFRA Environment Client 🌿

[![PyPI version](https://img.shields.io/pypi/v/environment-client.svg)](https://pypi.org/project/environment-client/)
[![GitHub Release](https://img.shields.io/github/v/release/cogna-public/environment-client?display_name=release)](https://github.com/cogna-public/environment-client/releases)
[![Publish Status](https://github.com/cogna-public/environment-client/actions/workflows/publish.yml/badge.svg)](https://github.com/cogna-public/environment-client/actions/workflows/publish.yml)
[![Python Versions](https://img.shields.io/pypi/pyversions/environment-client.svg)](https://pypi.org/project/environment-client/)
[![License: MIT](https://img.shields.io/pypi/l/environment-client.svg)](LICENSE)

Python client for DEFRA’s environment.data.gov.uk APIs — fast, typed, and async‑friendly. 🌟

## Installation 🧰

```bash
uv pip install environment-client
```

## Usage 🐍

```python
import asyncio
from environment.flood_monitoring import FloodClient
from environment.public_register import PublicRegisterClient


async def main():
    """
    An example of how to use the clients to get data from the APIs.
    """
    async with (
        FloodClient() as flood_client,
        PublicRegisterClient() as public_register_client,
    ):
        # Get flood warnings
        flood_warnings = await flood_client.get_flood_warnings()
        print(f"Found {len(flood_warnings)} flood warnings.")

        # Search for waste operations registrations
        waste_operations = await public_register_client.get_waste_operations(limit=5)
        print(f"Found {len(waste_operations.items)} waste operations.")

        # Search across all registers
        all_registrations = await public_register_client.search_all_registers(name_search="Limited", limit=5)
        print(f"Found {len(all_registrations.items)} registrations with 'Limited' in the name.")


if __name__ == "__main__":
    asyncio.run(main())
```

## Supported APIs 🌐

- Real-time Flood Monitoring (flood warnings, areas, stations, measures, readings)
- Bathing Waters
- Asset Management
- Hydrology
- Rainfall
- Water Quality Data Archive (WQA)
- Public Register (waste operations, end-of-life vehicles, industrial installations, water discharges, radioactive substances, waste carriers/brokers, waste exemptions, water discharge exemptions, scrap metal dealers, enforcement actions, flood risk exemptions)

## Package Name vs Import Path 🔤

- Distribution (PyPI): `environment-client`
- Import path (Python): `environment`

Example:

```python
from environment.flood_monitoring import FloodClient
```

Note: The distribution is named `environment-client` while the import path is `environment`. This keeps imports concise but clarifies the project scope on PyPI.

### ⚠️ Important: WQA API Replacement

Note: The Water Quality Archive (WQA) APIs will be replaced later this year, meaning that the existing APIs will no longer work after Spring/Summer 2025. As of now, many `water-quality/view` endpoints return HTTP 404. We’ve:

- Added a `DeprecationWarning` when instantiating `WaterQualityDataArchiveClient`.
- Marked WQA tests as `skipped` until the replacement API is available.

For updates, see DEFRA’s support pages:
https://environment.data.gov.uk/apiportal/support

## Implementation Status 📊

- Flood Monitoring
  - Base: `https://environment.data.gov.uk/flood-monitoring`
  - Implemented: `get_flood_warnings` (`/id/floods`), `get_flood_areas` (`/id/floodAreas`), `get_stations` (`/id/stations`), `get_station_by_id`, `get_measures` (`/id/measures`), `get_measure_by_id`, `get_readings` (`/data/readings`), `get_reading_by_id`.
  - Notes: Uses canonical `/id` for entities and `/data` for readings. Integration tests use VCR.

- Rainfall
  - Base: Flood Monitoring (parameterised)
  - Implemented: Stations and measures filtered with `parameter=rainfall`; readings via `/data/readings?parameter=rainfall`; reading-by-id via `/data/readings/{measure_id}/{timestamp}`.
  - Notes: Rainfall is part of Flood Monitoring; not a separate base path.

- Tide Gauge
  - Base: Flood Monitoring (typed)
  - Implemented: Stations via `/id/stations?type=TideGauge`, station-by-id, readings via `/data/readings?stationType=TideGauge`, reading-by-id via `/data/readings/{measure_id}/{timestamp}`.

- Hydrology
  - Base: `https://environment.data.gov.uk/hydrology`
  - Implemented: Stations, station-by-id, measures, measure-by-id, readings per-measure via `/id/measures/{id}/readings` (lists do not expose a global `/id/readings`).
  - Notes: Some fields (e.g., `status`, `riverName`, `station`, `unit`) are normalised for model compatibility.

- Bathing Waters
  - Base: `https://environment.data.gov.uk`
  - Implemented: `get_bathing_waters` (`/doc/bathing-water.json`), plus related entity lookups under `/id/*`.

- Asset Management
  - Base: `https://environment.data.gov.uk/asset-management`
  - Implemented: Assets, maintenance activities/tasks/plans, capital schemes (JSON endpoints under `/id/*.json`).

- Catchment Planning (Catchment Data)
  - Base: `https://environment.data.gov.uk/catchment-planning`
  - Status: Placeholder only (`get_catchment_data` returns `[]` until the correct endpoint is confirmed).

- Water Quality Data Archive (WQA)
  - Base: `https://environment.data.gov.uk/water-quality/view`
  - Status: Being replaced by DEFRA; many endpoints currently return HTTP 404. Client issues a `DeprecationWarning`. Tests are skipped until the replacement API is available.

## Testing & VCR 🧪

- Tests are recorded/replayed with `pytest-vcr` (record mode: once).
- Cassettes are stored under `tests/cassettes/` with per-module subfolders (e.g., `rainfall/`, `hydrology/`, `tide_gauge/`, `integration/`).
- To re-record a cassette, delete the corresponding YAML file and re-run the specific test.
- Integration tests also use VCR to avoid live network dependency.

## Development 🛠️

Contributing? See AGENTS.md for full repository guidelines (structure, style, testing, and PR conventions).

This project uses `uv` for dependency management.

- Install dependencies: `uv sync` or `just install`
- Run tests: `just test`
- Run integration tests: `just test-integration`
- Lint (fix): `just lint`
- Format: `just format`
- Example script: `just run-main`

## Contributing 🤝

- Start with AGENTS.md for repository structure, coding style, testing, and PR conventions.
- Open an issue for larger changes; link issues in PRs.
- Follow commit prefixes (e.g., `feat:`, `fix:`, `docs:`) and keep messages concise.
- Run `just lint`, `just format`, and `just test` before pushing. Update or re-record VCR cassettes when tests change network interactions.

## Releasing 🚀

### Automatic Releases (Default)

Every merge to `main` is released once its tests pass. Merge your PR and GitHub Actions:

1. Runs the tests on the merge, and waits for them to pass
2. Bumps the version: the patch (0.5.11 → 0.5.12), unless the PR title ends with `[minor]` or `[major]`
3. Creates the git tag and GitHub release
4. Publishes to PyPI via Trusted Publishing

There are no manual steps. A merge that changes only `.github/`, such as a Dependabot action update, releases nothing; the next release includes it.

### Minor and Major Releases

For a **minor** or **major** release, end the PR title with `[minor]` or `[major]`, for example `Add hydrology readings endpoint [minor]`. The squash-merge commit takes the PR title, and the workflow bumps that part instead of the patch (0.5.x → 0.6.0, or 0.5.x → 1.0.0).

Nobody can push a bump commit or a `v*` tag by hand: the repository rules reserve both for the release app.

### How It Works

- **Automatic workflow:** `.github/workflows/auto-version.yml` bumps the version on every merge to main, then tags and releases as the `cogna-package-releaser` GitHub App
- **Publishing workflow:** `.github/workflows/publish.yml` publishes to PyPI when a release is created
- **Trusted Publishing:** PyPI accepts uploads only from `publish.yml` running in the `pypi` environment, which only `v*` tags can deploy to

### Setup

The repository settings (rules and the `release` and `pypi` environments) are managed in Terraform in `cogna-co/terraform`. The `release` environment needs:

- variable `RELEASE_APP_CLIENT_ID`: the app's client ID
- secret `RELEASE_APP_PRIVATE_KEY`: a private key for the app

The app's token, unlike `GITHUB_TOKEN`, lets the release trigger `publish.yml`.

**Links:**
- PyPI project: https://pypi.org/project/environment-client/
- Workflow setup guide: `.github/workflows/README.md`
