Skip to content

Commit c861781

Browse files
author
Peter Sprygada
committed
release: 0.1.0
Initial public release. Async Python client for the IAG 4.x REST API. - Services layer: 23 thin async wrappers, one per API endpoint - Resources layer: 22 declarative abstractions (ensure/absent/run/load/dump) - Serialization: JSON, YAML (optional), TOML (optional) - Typed exception hierarchy with HTTP and transport error classification - Silent logging by default; enable with logger.set_level(logging.DEBUG)
1 parent a2ee5b7 commit c861781

5 files changed

Lines changed: 442 additions & 253 deletions

File tree

CHANGELOG.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7+
8+
## [Unreleased]
9+
10+
## [0.1.0] - 2026-03-09
11+
12+
### Added
13+
14+
- TOML support in `serdes` module alongside existing JSON and YAML support (#16)
15+
- `heuristics` module for connection parameter validation and normalization (#9)
16+
- Structured logging module replacing the previous `logger` stub, with configurable log levels (#9)
17+
- 23 async service wrappers covering all IAG 4.x API tag groups (#6)
18+
- 22 declarative resource classes with `ensure`/`absent`/`run`/`dry_run`/`load`/`dump` patterns (#6)
19+
- Comprehensive unit test suite with 686 tests across services and resources (#6)
20+
- Filesystem-based bulk loader via `client.load(path, op)` dispatching to `service.load()` (#6)
21+
- `Operation` string class (`MERGE`, `REPLACE`, `OVERWRITE`) for bulk operations (#6)
22+
- Typed exception hierarchy rooted at `AsyncGatewayError` with HTTP status and transport error mapping (#6)
23+
- Pagination helper `ServiceBase._get_all()` shared across service layer (#6)
24+
- Version derived from git tags via `uv-dynamic-versioning` (#6)
25+
- SPDX license headers across all source files for GPL v3 compliance (#11)
26+
- GitHub Actions CI pipeline with lint, typecheck, security, and tox matrix (py310–py313) (#5, #7, #8)
27+
- GitHub issue and PR templates, CODEOWNERS, CODE_OF_CONDUCT, CONTRIBUTING, SECURITY policy (#11, initial)
28+
- Contributor License Agreement (#initial)
29+
30+
### Fixed
31+
32+
- Pagination infinite loop in services using `_get_all` helper (#13)
33+
- `delete_all` filter bug in `devices` service that incorrectly scoped deletions (#13)
34+
- Minor low-priority issues across services and resources (#14)
35+
36+
### Changed
37+
38+
- Simplified exceptions module from multiple classes to two core exception types (#10)
39+
- Module docstrings added across all source files; stale `Operation` example corrected (#12)
40+
41+
[Unreleased]: https://github.com/itential/asyncgateway/compare/v0.1.0...HEAD
42+
[0.1.0]: https://github.com/itential/asyncgateway/releases/tag/v0.1.0

CLAUDE.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
- `client.py``Client` class with two `_Namespace` containers (`services`, `resources`). On init, scans `services/` and `resources/` directories via `importlib`, instantiates each `Service`/`Resource` class, and attaches it to the appropriate namespace by its `.name` attribute. All `**kwargs` pass through to `ipsdk.gateway_factory(want_async=True, **kwargs)`. `client.load(path, op)` is a filesystem bulk loader that dispatches to `service.load(data, op)` for any service that exposes one.
1010
- `services/` — 23 files covering all IAG API tag groups. Each file has one `Service(ServiceBase)` class. Methods call `self.client.{verb}(path)` and return `res.json()` — no logic. Pagination handled by the shared `ServiceBase._get_all(path, **params)` helper.
1111
- `resources/` — 22 files. Each has one `Resource(ResourceBase)` class that receives the `services` namespace as `self.services`. Implements declarative patterns: `ensure`/`absent` for CRUD, `run`/`dry_run` for execution, `load`/`dump` for bulk operations.
12-
- `serdes.py` — JSON/YAML serialization. JSON is tried first; YAML requires optional `PyYAML`. The `YAML_AVAILABLE` bool controls runtime behavior.
12+
- `serdes.py` — JSON/YAML/TOML serialization. JSON is tried first; YAML requires optional `PyYAML`; TOML uses stdlib `tomllib` (Python 3.11+) or `tomli` on 3.10. The `YAML_AVAILABLE` and `TOML_AVAILABLE` bools control runtime behavior.
1313
- `exceptions.py` — Exception hierarchy rooted at `AsyncGatewayError`. `classify_httpx_error` and `classify_http_status` map transport errors to typed exceptions. Aliases (`HTTPError`, `TimeoutError`, etc.) exist for backward compatibility.
1414
- `logger.py` — stdlib `logging` wrapper. **Default level is 100 (silent).** Enable with `asyncgateway.logger.set_level(logging.DEBUG)`.
1515
- `metadata.py` — Reads version from installed package metadata via `importlib.metadata`.
@@ -43,7 +43,7 @@
4343

4444
```bash
4545
uv sync --group dev # install all deps including tox
46-
uv run pytest # run tests (all 200, ~0.4s)
46+
uv run pytest # run tests (all 686, ~0.4s)
4747
uv run pytest -v --cov # with coverage
4848
tox # test across py310–py313
4949
tox -e py312 # single version
@@ -75,7 +75,7 @@ CI runs on GitHub Actions (`.github/workflows/ci.yaml`) on push/PR to `main`/`de
7575
3. **`devices.delete_all()` in `services/devices.py` only deletes devices starting with `"router"`** — leftover test code that is still in the public API.
7676
4. **`__main__.py` is a stub** — prints a message and exits. No CLI.
7777
5. **`pyproject.toml` still lists `requires-python = ">=3.10"`** but `docs/development.md` says 3.8+. The latter is stale.
78-
6. **No resource-level tests** for the 22 new resource files. Current tests cover services and infrastructure only. All resource logic (ensure, absent, run, load) is untested.
78+
6. ~~**No resource-level tests**~~ — resolved in #6. Resource tests covering ensure, absent, run, load, and passthrough patterns are now included in the 686-test suite.
7979
7. **YAML errors raise `JSONError`** — intentional for consistency but confusing.
8080
8. **`Operation` docstring still refers to `client.devices.import_devices()`** — a method that no longer exists.
8181

NOTICE

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,13 @@ PyYAML (optional dependency)
3030
Copyright (c) 2017-2021 Ingy döt Net
3131
Copyright (c) 2006-2016 Kirill Simonov
3232
https://github.com/yaml/pyyaml
33+
34+
tomli (optional dependency, Python < 3.11 only)
35+
License: MIT
36+
Copyright (c) 2021 Taneli Hukkinen
37+
https://github.com/hukkin/tomli
38+
39+
tomli-w (optional dependency)
40+
License: MIT
41+
Copyright (c) 2021 Taneli Hukkinen
42+
https://github.com/hukkin/tomli-w

SECURITY.md

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,21 @@ receive backported security patches.
77

88
| Version | Supported |
99
|---------|-----------|
10-
| latest | Yes |
11-
| older | No |
10+
| 0.1.0 | Yes |
11+
12+
## Release Security Notes
13+
14+
### 0.1.0 (2026-03-09)
15+
16+
No security vulnerabilities were identified or patched in this initial release.
17+
`bandit` static analysis reports zero issues across all 3,305 lines of source
18+
code. The following security-relevant hardening was applied:
19+
20+
- SPDX license headers added to all source files for supply chain transparency (#11)
21+
- Typed exception hierarchy prevents accidental leakage of raw HTTP details (#6)
22+
- Credentials and secrets are never logged — default log level is silent (100) (#6)
23+
- `certifi` updated to 2026-02-25 for current CA bundle
24+
- `ipsdk` updated from 0.3.0 to 0.8.0 (upstream dependency upgrade)
1225

1326
## Reporting a Vulnerability
1427

0 commit comments

Comments
 (0)