| name | python-api-surface |
| description | Maintain the public Python API for eo-processor, including exports, __all__, docstrings, and type stubs. Use when adding/renaming functions, changing signatures/behavior, or ensuring Python typing and user-facing docs stay consistent with the Rust/PyO3 core. |
| license | Proprietary. See repository LICENSE |
| compatibility | Intended for this repository’s Python package (python/eo_processor) paired with a Rust PyO3 extension; assumes numpy/xarray usage patterns and standard Python tooling (pytest, ruff, mypy, tox/uv). |
| metadata | [object Object] |
Python API surface & typing skill (eo-processor)
Use this skill when you need to change anything users import from eo_processor, or when you change behavior/signatures in the Rust core and must keep Python exports + typing stubs + docs + tests aligned.
This skill is intentionally opinionated: public API stability and consistency beat cleverness.
What “Python API surface” means in this repo
The user-visible API typically includes:
python/eo_processor/__init__.py- imports from the compiled extension module
__all__- module docstring / high-level documentation
- occasionally
__version__or metadata (if present in this repo)
python/eo_processor/__init__.pyi- the canonical typing surface for users and CI type checks
- Any Python helpers/wrappers that sit on top of the Rust core (if present)
- Documentation that enumerates functions and guides usage:
README.md(always)QUICKSTART.md(only when it materially improves onboarding)docs/(if the repo generates longer-form docs)
Key invariant: if it’s public, it must be importable, typed, tested, and documented (at least minimally).
Activation checklist (before you edit)
- Identify whether the change is:
- new public function
- renamed function
- signature change
- behavior change
- docs-only change
- Identify the single source of truth for the behavior (usually Rust core), and confirm:
- input shapes (1D/2D), dtype(s), and expected ranges
- NaN/Inf behavior
- divide-by-zero / epsilon strategy (if applicable)
- Decide if the function should be public:
- If it’s stable, broadly useful, and not experimental → public.
- If it’s internal glue or unstable → keep internal, don’t export.
If any of those are unclear and you cannot infer them from existing functions, stop and ask the user for clarification (max 3 targeted questions).
Step-by-step workflow
Step 1: Wire exports correctly
When a function is intended to be public:
- Import it into
python/eo_processor/__init__.pyfrom the extension module (or its wrapper module). - Add it to
__all__. - Ensure naming matches docs and tests exactly.
Rules:
- Re-export under a single canonical name. Avoid multiple aliases unless there’s a compatibility story.
- Keep ordering/grouping consistent (e.g., indices together, masking together, temporal stats together).
Step 2: Define the typing contract in __init__.pyi
The .pyi signature should be:
- accurate to runtime behavior (including accepted dtypes/shapes)
- helpful to users (clear parameter names, optional defaults)
- consistent across the library (similar functions should have similar typing style)
Typing guidance:
- Prefer
numpy.typing.NDArrayfor NumPy arrays. - If the project supports
xarray.DataArraydirectly at runtime, either:- provide overloads, or
- document that
xarrayusage is viaxr.apply_ufuncand keep types NumPy-focused.
- Don’t promise more than the function actually supports (e.g., don’t type as accepting
ArrayLikeif it fails on lists).
Return type:
- If the function returns a new array:
NDArray[np.floating[Any]]or a specificnp.float64/np.float32depending on behavior. - If dtype is guaranteed (common in Rust kernels), reflect that explicitly.
Step 3: Update docstrings and high-level docs
For user-facing completeness:
- Ensure
README.mdmentions the function in the right section (API summary / feature list). - Provide a minimal example snippet in docs if this is a new capability.
- If it’s an EO index, include:
- formula
- band meanings
- expected input scaling (0–1 reflectance vs scaled integers)
- output range and interpretation notes
Keep docs concise; move deep explanations to docs/ if the repo uses it.
Step 4: Add/adjust tests
Any public API change requires tests. At minimum:
- a correctness test on a small array
- shape mismatch behavior (if relevant)
- stability (near-zero denominator) tests for ratio/normalized difference functions
When behavior changes:
- update or add a regression test that captures the intended new behavior
- avoid “brittle” tests that encode implementation quirks rather than contract
Compatibility and deprecation rules
Renames
If renaming a public function:
- Prefer a deprecation window:
- keep old name available and forward it to the new name
- add a deprecation note in docs
- (optionally) emit a
DeprecationWarningfrom the old alias
- Update:
- docs, tests,
__all__, stubs - any examples referencing the old name
- docs, tests,
Signature changes
Avoid breaking signature changes. If necessary:
- make new args optional with safe defaults
- document default behavior carefully
- update stubs and tests
If a breaking change is unavoidable, it must be explicit and coordinated with versioning policy.
Quality bar (must pass before “done”)
- Public function is importable from
eo_processor -
__all__includes it (if this repo uses__all__as canonical) -
.pyityping matches runtime behavior - Tests cover correctness + key edge cases
- Docs mention the function and provide guidance
- No redundant exports or conflicting names
- No undocumented behavior change
Common pitfalls (avoid)
- Adding a Rust function but forgetting:
python/eo_processor/__init__.pyexportpython/eo_processor/__init__.pyistub- docs update
- tests
- Typing promises that runtime can’t fulfill (e.g.,
ArrayLikewhen onlyndarrayworks) - Silent behavioral changes without a corresponding doc/test update
- Inconsistent naming (e.g.,
normalizedDifferencevsnormalized_difference) - Returning different dtype than typed/documented
- “Convenience” broadcasting rules in one function that don’t exist elsewhere
Suggested “API change summary” format (use in your response/PR)
When you use this skill, summarize the API outcome:
- What changed
- How to use it (minimal snippet)
- Typing contract (inputs/outputs)
- Edge cases (NaN, divide-by-zero, shape mismatch)
- Tests added/updated
Local references (repo)
- Engineering and checklists:
AGENTS.md - User docs:
README.md,QUICKSTART.md - Workflows/examples:
WORKFLOWS.md,examples/ - Python surface:
python/eo_processor/__init__.py,python/eo_processor/__init__.pyi - Tests:
tests/