Skip to content

Commit 144f240

Browse files
authored
Merge pull request #12 from bio-oracle/release/v1.0.0
Release v1.0.0: modernize deps + biooracler parity
2 parents 65a42db + 1b8828c commit 144f240

22 files changed

Lines changed: 1281 additions & 101 deletions

.github/workflows/docs.yml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
name: Deploy docs
2+
3+
on:
4+
push:
5+
branches: ["main"]
6+
workflow_dispatch:
7+
8+
permissions:
9+
contents: read
10+
pages: write
11+
id-token: write
12+
13+
concurrency:
14+
group: "pages"
15+
cancel-in-progress: false
16+
17+
jobs:
18+
build:
19+
runs-on: ubuntu-latest
20+
steps:
21+
- uses: actions/checkout@v4
22+
- uses: actions/setup-python@v5
23+
with:
24+
python-version: "3.12"
25+
- name: Install
26+
run: |
27+
python -m pip install --upgrade pip
28+
python -m pip install -e ".[docs]"
29+
- name: Build site
30+
run: mkdocs build --strict
31+
- uses: actions/upload-pages-artifact@v3
32+
with:
33+
path: site
34+
35+
deploy:
36+
needs: build
37+
runs-on: ubuntu-latest
38+
environment:
39+
name: github-pages
40+
url: ${{ steps.deployment.outputs.page_url }}
41+
steps:
42+
- id: deployment
43+
uses: actions/deploy-pages@v4

.github/workflows/pypi-publish.yml

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,35 +22,31 @@ jobs:
2222
runs-on: ubuntu-latest
2323

2424
steps:
25-
- uses: actions/checkout@v3
26-
- name: Set up Python 3.10
27-
uses: actions/setup-python@v3
25+
- uses: actions/checkout@v4
26+
- name: Set up Python 3.12
27+
uses: actions/setup-python@v5
2828
with:
29-
python-version: "3.10"
29+
python-version: "3.12"
3030
- name: Install dependencies
3131
run: |
3232
python -m pip install --upgrade pip
33-
pip install flake8 pytest
34-
pip install .
35-
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
33+
python -m pip install -e ".[dev,xarray]"
3634
- name: Lint with flake8
3735
run: |
3836
# stop the build if there are Python syntax errors or undefined names
3937
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
40-
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
41-
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
42-
- name: Test with pytest
38+
- name: Test with pytest (unit tests only)
4339
run: |
44-
pytest
40+
pytest -m "not integration"
4541
deploy:
4642
runs-on: ubuntu-latest
4743
needs:
4844
- test
4945

5046
steps:
51-
- uses: actions/checkout@v3
47+
- uses: actions/checkout@v4
5248
- name: Set up Python
53-
uses: actions/setup-python@v3
49+
uses: actions/setup-python@v5
5450
with:
5551
python-version: '3.x'
5652
- name: Install dependencies

.github/workflows/python-app.yml

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,62 @@
1-
# This workflow will install Python dependencies, run tests and lint with a single version of Python
2-
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
1+
# Install Python dependencies, lint, and run tests across supported versions.
2+
# https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
33

44
name: Python application
55

66
on:
77
push:
8-
branches: [ "main" ]
8+
branches: ["main"]
99
pull_request:
10-
branches: [ "main" ]
10+
branches: ["main"]
1111

1212
permissions:
1313
contents: read
1414

1515
jobs:
1616
build:
17-
1817
runs-on: ubuntu-latest
18+
strategy:
19+
fail-fast: false
20+
matrix:
21+
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
1922

2023
steps:
21-
- uses: actions/checkout@v3
22-
- name: Set up Python 3.10
23-
uses: actions/setup-python@v3
24+
- uses: actions/checkout@v4
25+
- name: Set up Python ${{ matrix.python-version }}
26+
uses: actions/setup-python@v5
2427
with:
25-
python-version: "3.10"
28+
python-version: ${{ matrix.python-version }}
2629
- name: Install dependencies
2730
run: |
2831
python -m pip install --upgrade pip
29-
python -m pip install flake8 pytest pytest-cov
30-
python -m pip install -e .
31-
if [ -f requirements.txt ]; then python -m pip install -r requirements.txt; fi
32-
- name: Lint with flake8
33-
run: |
34-
# stop the build if there are Python syntax errors or undefined names
35-
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
36-
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
37-
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
38-
- name: Test with coverage
32+
python -m pip install -e ".[dev,xarray]"
33+
- name: Lint with ruff
34+
run: ruff check pyo_oracle tests
35+
- name: Lint with flake8 (syntax errors only)
36+
run: flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
37+
- name: Test with coverage (unit tests only)
3938
run: |
40-
python -m pytest --cov=pyo_oracle --cov-report=html --cov-report=term-missing tests/
39+
python -m pytest -m "not integration" \
40+
--cov=pyo_oracle --cov-report=html --cov-report=term-missing tests/
4141
- name: Upload coverage report
42+
if: matrix.python-version == '3.12'
4243
uses: actions/upload-artifact@v4
4344
with:
4445
name: coverage-report
4546
path: htmlcov/
47+
48+
integration:
49+
# Tests that hit the live Bio-ORACLE ERDDAP server. Blocking: a failure here
50+
# gates the PR.
51+
runs-on: ubuntu-latest
52+
steps:
53+
- uses: actions/checkout@v4
54+
- uses: actions/setup-python@v5
55+
with:
56+
python-version: "3.12"
57+
- name: Install dependencies
58+
run: |
59+
python -m pip install --upgrade pip
60+
python -m pip install -e ".[dev,xarray]"
61+
- name: Run integration tests
62+
run: python -m pytest -m integration tests/

.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`.

0 commit comments

Comments
 (0)