Skip to content

Commit 60ce27c

Browse files
vinisalazarclaude
andcommitted
docs: refresh README, add CHANGELOG and CLAUDE.md
Rewrite the README around the new API, add a Keep a Changelog CHANGELOG for v1.0.0 and a CLAUDE.md contributor guide (env, tests, release flow, erddapy caveats). Ignore dist/, site/ and .pytest_cache/. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 45aa916 commit 60ce27c

4 files changed

Lines changed: 201 additions & 29 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@
66
**/.DS_Store
77
**/*.ini
88
build/
9+
dist/
910
pyo_oracle/data
1011
.coverage
1112
coverage.*
1213
htmlcov/
1314
.venv/
15+
.pytest_cache/
16+
site/

CHANGELOG.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Changelog
2+
3+
All notable changes to this project are documented here. The format is based on
4+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this project adheres
5+
to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6+
7+
## [1.0.0] - 2026-06-02
8+
9+
First stable release. Modernizes dependencies, reaches feature parity with the
10+
R package [`biooracler`](https://github.com/bio-oracle/biooracler), and adds new
11+
functionality.
12+
13+
### Added
14+
15+
- **`info_layer(dataset_id)`** — inspect a layer's dimension ranges (time,
16+
latitude, longitude, depth) and its variables with units and long names
17+
(parity with `biooracler::info_layer`).
18+
- **`load_layer(dataset_id, ...)`** — load a layer directly into memory as a
19+
`pandas.DataFrame` (default) or `xarray.Dataset` (`fmt="xarray"`).
20+
- **`build_constraints(...)`** — build griddap constraints from friendly
21+
`(min, max)` bounds and strides, with optional validation against the
22+
dataset's real ranges.
23+
- **`variables=`** argument on `download_layers` to download a subset of
24+
variables.
25+
- Optional dependency extras: `xarray`, `docs`, `dev`.
26+
- MkDocs Material documentation site (quickstart, tutorials, API reference) with
27+
a GitHub Pages deploy workflow.
28+
- `respx` and `ruff` to the dev toolchain; `integration` pytest marker to
29+
separate live-server tests from offline unit tests.
30+
- `CLAUDE.md` contributor guide and this changelog.
31+
32+
### Changed
33+
34+
- Declared explicit dependencies (`erddapy>=2.2`, `pandas>=2.0`, `httpx>=0.27`)
35+
and raised the Python floor to `>=3.9`.
36+
- Refactored griddap server construction into a single shared
37+
`_build_griddap_server` helper used by downloads, in-memory loading, and
38+
metadata lookups.
39+
- CI now tests a Python 3.9–3.13 matrix, lints with ruff, and runs offline unit
40+
tests by default with a separate (non-blocking) integration job.
41+
42+
### Fixed
43+
44+
- Replaced unsafe `eval()` parsing of the `skip_confirmation` config value with a
45+
safe boolean coercion (`_as_bool`), which also handles strings like `"false"`.
46+
- Hardened handling of erddapy's private `_constraints_original` attribute.
47+
48+
## [0.2.0]
49+
50+
- Previous release.

CLAUDE.md

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# CLAUDE.md
2+
3+
Guidance for working in this repository.
4+
5+
## What this is
6+
7+
`pyo_oracle` is the Python client for the **Bio-ORACLE** ERDDAP server
8+
(<https://erddap.bio-oracle.org/erddap/>). It is the Python counterpart of the R
9+
package [`biooracler`](https://github.com/bio-oracle/biooracler) and is built on
10+
top of [`erddapy`](https://github.com/ioos/erddapy).
11+
12+
## Layout
13+
14+
- `pyo_oracle/__init__.py` — public namespace; re-exports the API.
15+
- `pyo_oracle/main.py` — public functions: `list_layers`, `info_layer`,
16+
`load_layer`, `download_layers`, `list_local_data`.
17+
- `pyo_oracle/utils.py` — internals: `_build_griddap_server` (the single shared
18+
griddap setup path), `_layer_info`, `_layer_dataframe`, `build_constraints`,
19+
`_as_bool`, download helpers.
20+
- `pyo_oracle/_config.py` — configparser-based config (data dir, server URL,
21+
`skip_confirmation`). `config.ini` is generated and git-ignored.
22+
- `tests/``test_utils.py` (offline), `test_main.py` (mostly live), `test_config.py`.
23+
- `docs/` + `mkdocs.yml` — MkDocs Material site (mkdocstrings API ref).
24+
25+
## Public API parity with `biooracler`
26+
27+
`list_layers`, `info_layer`, `download_layers` mirror the R package. Python adds
28+
`load_layer` (in-memory pandas/xarray) and `build_constraints` (friendly
29+
subsetting helper).
30+
31+
## Dev environment
32+
33+
All development happens in the conda env named **`pyo_oracle`**:
34+
35+
```bash
36+
conda env create -n pyo_oracle -f environment-dev.yaml # or `mamba`
37+
conda activate pyo_oracle
38+
pip install -e ".[dev,xarray,docs]"
39+
```
40+
41+
## Tests
42+
43+
Two kinds, separated by the `integration` marker:
44+
45+
```bash
46+
pytest -m "not integration" # offline unit tests (fast, used in CI by default)
47+
pytest # full suite incl. tests that hit the live server
48+
pytest -m integration # only the live-server tests
49+
```
50+
51+
The exit goal for changes is a **fully green `pytest`** in the `pyo_oracle` env.
52+
53+
## Lint & docs
54+
55+
```bash
56+
ruff check pyo_oracle tests
57+
mkdocs serve # live preview
58+
mkdocs build --strict # must pass (CI deploys to GitHub Pages)
59+
```
60+
61+
## Release flow
62+
63+
1. Bump `version` in `pyproject.toml` and update `CHANGELOG.md`.
64+
2. Ensure `pytest`, `ruff`, and `mkdocs build --strict` pass.
65+
3. `python -m build` and inspect the artifacts.
66+
4. Push a tag — `.github/workflows/pypi-publish.yml` builds and publishes to PyPI
67+
(package name `pyo-oracle`).
68+
69+
## Gotchas
70+
71+
- **erddapy private API**: `_build_griddap_server` relies on
72+
`ERDDAP._constraints_original`. It is guarded with `getattr`/`hasattr` but
73+
watch this if bumping erddapy (verified against erddapy 3.2.x).
74+
- Requires `erddapy>=2.2`, `pandas>=2.0`, Python `>=3.9`. xarray loading needs
75+
the optional `xarray` extra (`xarray` + `netCDF4`).
76+
- `download_layers` with no constraints downloads the entire global layer and
77+
prompts for confirmation unless `skip_confirmation=True`.

README.md

Lines changed: 71 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,82 @@
11
# pyo_oracle
2-
## Python interface for the Bio-ORACLE ERDDAP server
32

4-
### Quick start
3+
**Python client for the [Bio-ORACLE](https://bio-oracle.org/) ERDDAP server.**
54

6-
```python
7-
import pyo_oracle
8-
9-
# List available layers in the Bio-ORACLE server
10-
pyo_oracle.list_layers()
11-
12-
# Define constraints and download a layer (the full layer is a large file)
13-
constraints = {
14-
"time>=": "2000-01-01T00:00:00Z",
15-
"time<=": "2010-01-01T12:00:00Z",
16-
"time_step": 100,
17-
"latitude>=": 0,
18-
"latitude<=": 10,
19-
"latitude_step": 100,
20-
"longitude>=": 0,
21-
"longitude<=": 10,
22-
"longitude_step": 1
23-
}
24-
pyo_oracle.download_layers("thetao_baseline_2000_2019_depthsurf", constraints=constraints)
25-
26-
# See local data
27-
pyo_oracle.list_local_data()
28-
```
5+
Discover, inspect, subset, download, and load Bio-ORACLE marine environmental
6+
layers (temperature, salinity, nutrients, sea ice, and more) from Python.
7+
`pyo_oracle` is the Python counterpart of the R package
8+
[`biooracler`](https://github.com/bio-oracle/biooracler) and is built on
9+
[`erddapy`](https://github.com/ioos/erddapy).
10+
11+
📖 **Documentation:** <https://bio-oracle.github.io/pyo_oracle/>
2912

30-
### Installation
13+
## Installation
3114

3215
```bash
16+
# With pip
17+
pip install pyo-oracle
18+
19+
# Load layers as xarray (optional extra)
20+
pip install "pyo-oracle[xarray]"
21+
3322
# With conda
3423
conda create -n pyo_oracle conda-forge::pyo-oracle
24+
```
3525

36-
# or with pip
37-
pip install pyo-oracle
26+
## Quick start
27+
28+
```python
29+
import pyo_oracle as pyo
30+
31+
# 1. List available layers (filter by search term, variable, scenario, depth, ...)
32+
pyo.list_layers(search="Temperature")
33+
34+
# 2. Inspect a layer: dimension ranges + variables and units
35+
pyo.info_layer("thetao_baseline_2000_2019_depthsurf")
36+
37+
# 3. Build constraints from friendly bounds (no hand-written dicts)
38+
constraints = pyo.build_constraints(
39+
"thetao_baseline_2000_2019_depthsurf",
40+
time=("2000-01-01T00:00:00Z", "2010-01-01T00:00:00Z"),
41+
latitude=(0, 10),
42+
longitude=(0, 10),
43+
)
44+
45+
# 4a. Load directly into memory (pandas or xarray)
46+
df = pyo.load_layer(
47+
"thetao_baseline_2000_2019_depthsurf",
48+
constraints=constraints,
49+
variables=["thetao_mean"],
50+
)
51+
ds = pyo.load_layer(
52+
"thetao_baseline_2000_2019_depthsurf",
53+
constraints=constraints,
54+
fmt="xarray",
55+
)
56+
57+
# 4b. Or download to a file (NetCDF by default)
58+
pyo.download_layers(
59+
"thetao_baseline_2000_2019_depthsurf",
60+
constraints=constraints,
61+
variables=["thetao_mean"],
62+
)
63+
64+
# 5. See local data
65+
pyo.list_local_data()
3866
```
3967

40-
Please open an issue if you experience any problems. More documentation coming soon!
68+
## Key functions
69+
70+
| Function | Purpose |
71+
|----------|---------|
72+
| `list_layers` | List/filter available layers |
73+
| `info_layer` | Inspect a layer's dimensions and variables |
74+
| `build_constraints` | Build griddap constraints from `(min, max)` bounds + strides |
75+
| `load_layer` | Load a layer into memory (`pandas` or `xarray`) |
76+
| `download_layers` | Download a layer (NetCDF/CSV), optionally a variable subset |
77+
| `list_local_data` | List downloaded files |
78+
79+
## Contributing
80+
81+
See [`CLAUDE.md`](CLAUDE.md) for the dev setup, testing, and release flow.
82+
Please open an issue if you experience any problems.

0 commit comments

Comments
 (0)