Contributing

Thank you for your interest in contributing to Nereus! This guide will help you get started.

Development Setup

  1. Clone the repository:

    git clone https://github.com/koldunovn/nereus.git
    cd nereus
    
  2. Create a development environment:

    Using conda/mamba (recommended):

    mamba create -n nereus-dev python=3.11
    mamba activate nereus-dev
    mamba install -c conda-forge numpy scipy xarray netcdf4 matplotlib cartopy dask
    

    Or using pip:

    python -m venv .venv
    source .venv/bin/activate  # On Windows: .venv\Scripts\activate
    
  3. Install in development mode:

    pip install -e ".[dev]"
    

    This installs Nereus in editable mode with development dependencies (pytest, ruff, mypy).

Running Tests

Run the full test suite:

pytest tests/

Run tests with coverage:

pytest tests/ --cov=nereus --cov-report=html

Run a specific test file:

pytest tests/test_core/test_coordinates.py

Run tests matching a pattern:

pytest -k "test_regrid"

Code Style

We use ruff for linting and formatting:

# Check for issues
ruff check src/

# Auto-fix issues
ruff check src/ --fix

# Format code
ruff format src/

Configuration is in pyproject.toml:

[tool.ruff]
line-length = 100
target-version = "py310"

[tool.ruff.lint]
select = ["E", "F", "I", "UP", "B", "SIM"]

Type Checking

We use mypy for static type checking:

mypy src/nereus/

All public functions should have type annotations.

Documentation

Build documentation locally:

cd docs
pip install -r requirements.txt
make html

View the built documentation:

open _build/html/index.html  # macOS
xdg-open _build/html/index.html  # Linux

Docstring Format

Use NumPy-style docstrings:

def my_function(param1, param2):
    """Short description of the function.

    Longer description if needed. Can span multiple lines.

    Parameters
    ----------
    param1 : type
        Description of param1.
    param2 : type, optional
        Description of param2. Defaults to X.

    Returns
    -------
    type
        Description of return value.

    Examples
    --------
    >>> my_function(1, 2)
    3

    Notes
    -----
    Additional notes about the implementation.
    """

Pull Request Process

  1. Fork the repository and create a new branch:

    git checkout -b feature/my-new-feature
    
  2. Make your changes and ensure:

    • All tests pass: pytest tests/

    • Code is formatted: ruff format src/

    • No linting errors: ruff check src/

    • Type hints are correct: mypy src/nereus/

  3. Write tests for new functionality.

  4. Update documentation if needed.

  5. Commit with clear messages:

    git commit -m "Add feature X for doing Y"
    
  6. Push and create a pull request:

    git push origin feature/my-new-feature
    
  7. Address review feedback and update as needed.

Adding New Features

Adding a New Diagnostic

  1. Create the function in the appropriate module (e.g., src/nereus/diag/ice.py).

  2. Add docstrings with examples.

  3. Export from src/nereus/diag/__init__.py.

  4. Export from src/nereus/__init__.py if it should be top-level.

  5. Add tests in tests/test_diag/.

  6. Update documentation in docs/api/diag.rst.

Adding Model Support

  1. Create a new directory under src/nereus/models/ (e.g., models/newmodel/).

  2. Create __init__.py with:

    • A Mesh class inheriting from MeshBase

    • A load_mesh() function

    • Any model-specific utilities

  3. Export from src/nereus/models/__init__.py.

  4. Add namespace export in src/nereus/__init__.py.

  5. Add tests and documentation.

Example:

# src/nereus/models/newmodel/__init__.py
from nereus.models._base import MeshBase

class NewModelMesh(MeshBase):
    def __init__(self, ...):
        ...

    @property
    def lon(self):
        return self._lon

    @property
    def lat(self):
        return self._lat

    @property
    def area(self):
        return self._area

def load_mesh(path):
    """Load NewModel mesh from file."""
    ...
    return NewModelMesh(...)

Reporting Issues

When reporting bugs, please include:

  1. Python version and Nereus version

  2. Operating system

  3. Minimal reproducible example

  4. Expected behavior vs actual behavior

  5. Full error traceback if applicable

Feature requests are also welcome! Please describe:

  1. Use case: What are you trying to accomplish?

  2. Current workaround: How do you handle it now?

  3. Proposed solution: What would the ideal API look like?

Code of Conduct

We are committed to providing a welcoming and inclusive environment. Please:

  • Be respectful and considerate

  • Welcome newcomers and help them get started

  • Focus on constructive feedback

  • Assume good intentions

Thank you for contributing!