Developing
This guide covers setting up a development environment, running tests, building documentation, and enforcing code quality.
Prerequisites
Python 3.12+
uv — package manager and virtual environment manager (https://github.com/astral-sh/uv). Install with:
curl -LsSf https://astral.sh/uv/install.sh | sh
Project structure
proyecto_aemet_api/
|-- pyproject.toml # Project metadata and dependencies
|-- src/aemetxfb/ # Package source code
| |-- clim/ # Climate data module
| |-- obs/ # Observations module
| |-- pred/ # Predictions (hourly forecasts) module
| |-- utils.py # Shared utilities and configuration
| `-- cache.py # Optional disk cache
|-- tests/ # Unit tests (mirrors src/ structure)
|-- docs/source/ # Sphinx documentation source
`-- scripts/ # Utility scripts
Setting up the environment
The project uses uv to manage dependencies and the virtual environment.
All commands below assume you are in the project root directory.
Install dependencies
# Core dependencies (numpy, pandas)
uv sync
# With test dependencies (pytest, ruff)
uv sync --extra tests
# With documentation dependencies (sphinx, sphinx-rtd-theme)
uv sync --extra docs
# With all extras (tests, docs, dev tools)
uv sync --all-extras
Running tests
The test suite uses pytest and covers all public functions. Tests
include unit tests, mocked HTTP calls, and doctests embedded in docstrings.
# Run all tests
uv run pytest
# Run a specific test file
uv run pytest tests/pred/test_pred.py
# Run a specific test class
uv run pytest tests/pred/test_pred.py::TestGetForecast
# Run a specific test method
uv run pytest tests/pred/test_pred.py::TestGetForecast::test_by_name_returns_forecast_instance
# Run with verbose output
uv run pytest -v
# Stop on first failure
uv run pytest -x
# Show captured stdout/stderr
uv run pytest -s
Test structure
Tests mirror the package structure under tests/:
tests/
|-- test_utils.py # Tests for shared utilities
|-- clim/ # Tests for climate module
| |-- conftest.py
| |-- test_clim_ephem.py
| |-- test_clim_extremes.py
| |-- test_clim_normals.py
| |-- test_clim_thresholds.py
| `-- test_masts.py
|-- obs/ # Tests for observations module
| |-- test_chem.py
| |-- test_lightning.py
| |-- test_obs.py
| |-- test_radar.py
| |-- test_radiation.py
| `-- test_satellite.py
`-- pred/ # Tests for predictions module
|-- test_pred.py
`-- test_stations.py
Some tests use unittest.mock.patch to avoid real network calls.
Tests that require live AEMet endpoints are marked with @pytest.mark.skip
by default.
Linting and formatting
The project uses ruff for linting and formatting. All code must pass
both checks before committing.
# Check for linting issues
uv run ruff check
# Auto-fix fixable issues
uv run ruff check --fix
# Check formatting
uv run ruff format --check
# Format all files
uv run ruff format
# Check a specific directory
uv run ruff check src/aemetxfb/pred/
uv run ruff format --check src/aemetxfb/pred/
Style rules
Line length: 79 characters (enforced by
ruff format)Import order: standard library, third-party, local (enforced by
ruff)Type annotations: required for all public functions and classes
Docstrings: NumPy/SciPy style with
Parameters,Returns,Raises, andExamplessectionsNaming:
snake_casefor functions and variables,PascalCasefor classes
Building documentation
Documentation is written in reStructuredText and built with Sphinx.
Source files live in docs/source/.
# Install documentation dependencies
uv sync --extra docs
# Build HTML documentation
uv run sphinx-build docs/source docs/source/build/html
# Or use the provided script
./scripts/build_docs.sh
# Build with warnings as errors (CI mode)
uv run sphinx-build -W docs/source docs/source/build/html
The generated HTML is written to docs/source/build/html/. Open
index.html in a browser to view it.
Documentation structure
docs/source/
|-- conf.py # Sphinx configuration
|-- index.rst # Documentation home page
|-- quickstart.rst # Quick start guide
|-- configuration.rst # Runtime configuration guide
|-- caching.rst # Disk cache guide
|-- developing.rst # This page
|-- modules/
| |-- climate.rst # Climate module guide
| |-- observations.rst # Observations module guide
| `-- predictions.rst # Predictions module guide
`-- api/
|-- aemetxfb.rst # Top-level package reference
|-- aemetxfb.clim.rst # Climate API reference
|-- aemetxfb.obs.rst # Observations API reference
|-- aemetxfb.pred.rst # Predictions API reference
|-- aemetxfb.utils.rst # Utilities API reference
`-- aemetxfb.cache.rst # Cache API reference
Writing documentation
Use
:py:func:\`~module.func\,:py:class:\`~module.Class\, and:py:mod:\`~module\cross-references to link to API elements.Use
.. code-block:: pythonfor Python code examples.Use
.. list-table::for structured data (columns, types, descriptions).Use
.. note::,.. warning::, and.. seealso::directives for callouts.Docstrings in source code use NumPy/SciPy style and are automatically included in the API reference via
sphinx.ext.autodoc.
Continuous integration
The project uses the following checks in CI:
Tests:
uv run pytest— all tests must passLinting:
uv run ruff check— no lint errorsFormatting:
uv run ruff format --check— code must be formattedDocumentation:
uv run sphinx-build -W docs/source docs/source/build/html— no Sphinx warnings
Pre-commit checklist
Before committing changes, run:
uv run pytest
uv run ruff check
uv run ruff format --check
If all three pass, the changes are ready to commit.