Skip to content

Commit 87d5a98

Browse files
Merge pull request #367 from tpvasconcelos/agents
🤖 AGENTS.md
2 parents 2eaff20 + aaf87aa commit 87d5a98

File tree

12 files changed

+353
-5
lines changed

12 files changed

+353
-5
lines changed

.claude/skills

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../skills
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# THIS IS AUTOGENERATED. DO NOT EDIT MANUALLY
2+
version = 1
3+
name = "ridgeplot"
4+
5+
[setup]
6+
script = '''
7+
if git remote | grep -q '^origin$'; then
8+
echo "info: git remote 'origin' already exists"
9+
else
10+
git remote add origin https://github.com/tpvasconcelos/ridgeplot.git
11+
fi
12+
13+
if git rev-parse --is-shallow-repository 2>/dev/null | grep -q true; then
14+
git fetch --unshallow
15+
else
16+
echo "info: git repository is already complete (not shallow)"
17+
fi
18+
19+
git fetch -v
20+
'''
21+
22+
[[actions]]
23+
name = "source venv"
24+
icon = "tool"
25+
command = "source .venv/bin/activate"
26+
27+
[[actions]]
28+
name = "tox -m tests"
29+
icon = "test"
30+
command = "uvx tox -m tests"
31+
32+
[[actions]]
33+
name = "tox -m static-quick"
34+
icon = "test"
35+
command = "uvx tox -m static-quick"

.codex/skills

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../skills

.cursor/skills

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../skills

.cursor/worktrees.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"setup-worktree": [
3-
"make init"
3+
"make init",
4+
"source .venv/bin/activate"
45
]
56
}

AGENTS.md

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
# ridgeplot Development Guide for AI Agents
2+
3+
`ridgeplot` is a Python package for beautiful, interactive ridgeline plots built on Plotly.
4+
5+
## Start Here
6+
7+
- Read this file first, then the most relevant source file(s).
8+
- Prefer local docs and tests over memory; do not guess behavior.
9+
- If requirements are unclear or risky, ask a concrete question before changing code.
10+
11+
## Stack and Style Constraints
12+
13+
- Python >=3.10
14+
- Plotly graph objects (dependency is `plotly>=5.20`)
15+
- Line length 100, formatting with ruff
16+
- Docstrings are NumPy style
17+
- Type annotations are modern and throughout with strict checking via pyright
18+
19+
## Quick Commands
20+
21+
### Environment Setup
22+
23+
```shell
24+
# Initialize full development environment (recommended for first-time setup)
25+
# This creates .venv, installs dependencies, and sets up pre-commit hooks
26+
make init
27+
28+
# Activate the virtual environment
29+
source .venv/bin/activate
30+
```
31+
32+
### Running Tests
33+
34+
```shell
35+
# Run all test suites (unit + e2e + cicd_utils)
36+
uvx tox -m tests
37+
38+
# Run a specific test suite
39+
uvx tox -e tests-unit # Unit tests with coverage
40+
uvx tox -e tests-e2e # End-to-end tests
41+
uvx tox -e tests-cicd_utils # CI/CD utilities tests
42+
43+
# Run pytest directly with custom options
44+
uvx tox -e pytest -- tests/unit/test_init.py --no-cov
45+
uvx tox -e pytest -- -k "test_specific_function" --no-cov
46+
```
47+
48+
### Linting and Formatting
49+
50+
```shell
51+
# Run the main static checks
52+
uvx tox -m static-quick
53+
54+
# Run the entire suite of static checks (incl. all pre-commit hooks)
55+
# If running from the main branch, you'll need
56+
# to skip the 'no-commit-to-branch' check with:
57+
SKIP='no-commit-to-branch' uvx tox -m static
58+
59+
# Run all pre-commit hooks on all files
60+
uvx pre-commit run --all-files
61+
62+
# Run specific pre-commit hooks
63+
uvx pre-commit run ruff-format --all-files
64+
65+
# Run type checking with pyright only
66+
uvx tox -e typing
67+
```
68+
69+
### Documentation
70+
71+
```shell
72+
# Build static documentation
73+
uvx tox -e docs-static
74+
```
75+
76+
## Project Map
77+
78+
```text
79+
src/ridgeplot/
80+
├── __init__.py # Public API exports
81+
├── _ridgeplot.py # Main ridgeplot() function
82+
├── _figure_factory.py # Plotly Figure construction
83+
├── _kde.py # Kernel Density Estimation
84+
├── _hist.py # Histogram binning
85+
├── _types.py # Type aliases and type guards
86+
├── _utils.py # Utility functions
87+
├── _missing.py # Sentinel for missing values
88+
├── _version.py # Version string (setuptools-scm)
89+
├── _color/ # Color handling
90+
│ ├── colorscale.py # Colorscale resolution
91+
│ ├── css_colors.py # CSS color parsing
92+
│ ├── interpolation.py # Color interpolation
93+
│ └── utils.py # Color utilities
94+
├── _obj/traces/ # Trace objects
95+
│ ├── area.py # Area trace (filled curves)
96+
│ ├── bar.py # Bar trace (histograms)
97+
│ └── base.py # Base trace class
98+
├── _vendor/ # Vendored dependencies
99+
└── datasets/ # Built-in datasets
100+
└── data/ # CSV data files
101+
102+
tests/
103+
├── conftest.py # Shared pytest fixtures
104+
├── unit/ # Unit tests for individual modules
105+
├── e2e/ # End-to-end tests with expected outputs
106+
│ └── artifacts/ # JSON artifacts for e2e comparisons
107+
└── cicd_utils/ # Tests for CI/CD utilities
108+
109+
cicd_utils/ # CI/CD helper modules
110+
├── cicd/ # Scripts and test helpers
111+
└── ridgeplot_examples/ # Example implementations for docs/testing
112+
```
113+
114+
## Public API
115+
116+
The public API exposes one main function: `ridgeplot.ridgeplot(...) -> go.Figure`
117+
118+
The `ridgeplot()` docstring in `src/ridgeplot/_ridgeplot.py` contains the API contract.
119+
120+
`ridgeplot.datasets.load_probly()` and
121+
`ridgeplot.datasets.load_lincoln_weather()` are legacy loaders kept for
122+
backwards compatibility only.
123+
124+
## Key Data Flow
125+
126+
1. Users call `ridgeplot(samples=...)` or `ridgeplot(densities=...)`.
127+
2. If samples are provided, KDE in `_kde.py` or histogram binning in `_hist.py`
128+
produces densities.
129+
3. Densities are normalised if the `norm` parameter is set.
130+
4. `create_ridgeplot()` in `_figure_factory.py` builds the Plotly Figure by
131+
resolving colors, creating traces, and applying layout settings.
132+
5. The function returns a `plotly.graph_objects.Figure`.
133+
134+
## Key Files to Know
135+
136+
| File | Purpose |
137+
|------------------------------------|-----------------------------|
138+
| `src/ridgeplot/_ridgeplot.py` | Main `ridgeplot()` function |
139+
| `src/ridgeplot/_figure_factory.py` | Figure construction logic |
140+
| `src/ridgeplot/_types.py` | All type aliases and guards |
141+
| `tests/unit/test_ridgeplot.py` | Core function tests |
142+
| `cicd_utils/ridgeplot_examples/` | Example scripts for docs |
143+
| `docs/` | User and developer docs |
144+
| `tox.ini` | CI environment definitions |
145+
| `ruff.toml` | Linting configuration |
146+
147+
Documentation: https://ridgeplot.readthedocs.io/en/stable/
148+
149+
## Workflow Expectations
150+
151+
### When Adding New Features
152+
153+
1. Start with `src/ridgeplot/_ridgeplot.py` to understand the entry point.
154+
2. Add parameters following existing patterns and deprecation handling.
155+
3. Update types in `src/ridgeplot/_types.py` when introducing new structures.
156+
4. Add tests in `tests/unit/` with good coverage.
157+
5. Update docstrings to match the new behavior.
158+
159+
### When Fixing Bugs
160+
161+
1. Write a failing test first.
162+
2. Fix the issue with minimal changes.
163+
3. Ensure tests and type checks pass.
164+
4. Verify docstrings remain accurate.
165+
166+
### Type Annotations
167+
168+
- Uses **pyright** in strict mode (see `pyrightconfig.json`)
169+
- All functions must be fully typed, following modern Python typing practices and existing project conventions.
170+
- Use `TYPE_CHECKING` blocks for import-only types
171+
- Use type guards for runtime type narrowing (see `_types.py`)
172+
- Follow this general principle for user-facing code: be contravariant in the input type and covariant in the output type
173+
- Add type aliases close to their usage. If widely used, place in `_types.py`.
174+
175+
## Common Patterns
176+
177+
**Handling deprecated parameters:**
178+
179+
```python
180+
if deprecated_param is not MISSING:
181+
if new_param is not None:
182+
raise ValueError("Cannot use both...")
183+
warnings.warn("...", DeprecationWarning, stacklevel=2)
184+
new_param = deprecated_param
185+
```
186+
187+
**Type narrowing with guards:**
188+
189+
```python
190+
if is_shallow_samples(samples):
191+
samples = nest_shallow_collection(samples)
192+
samples = cast("Samples", samples)
193+
```
194+
195+
**Lazy imports for performance:**
196+
197+
```python
198+
# Heavy imports inside functions to reduce import time
199+
def _coerce_to_densities(...):
200+
from ridgeplot._kde import estimate_densities # statsmodels is slow to import
201+
```
202+
203+
## Testing Notes
204+
205+
- Use `--no-cov` flag during development for faster test runs
206+
- Run targeted tests via: `uvx tox -e pytest -- tests/unit/test_foo.py -k "test_bar" --no-cov`
207+
- The `tests/e2e/artifacts/` directory contains expected Plotly Figure JSON for e2e tests
208+
209+
## CI/CD Pipeline
210+
211+
GitHub Actions runs tests on Python 3.10–3.14 across Ubuntu, macOS, and Windows.
212+
Codecov minimums are 98% overall and 100% diff coverage for new code.
213+
214+
## Notes for AI Assistants
215+
216+
1. Run tests after changes when feasible, starting with the smallest relevant subset.
217+
2. Run `uvx tox -e typing` if types are touched or errors are likely.
218+
3. Run `uvx pre-commit run ruff-format --all-files` to format code.
219+
4. Preserve deprecation behavior and public API stability.
220+
5. Keep changes minimal and aligned with existing patterns.
221+
6. Respect existing patterns - this is a mature codebase with consistent style.

CLAUDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
AGENTS.md

MANIFEST.in

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,14 @@ prune docs/api/autogen
3333
prune docs/api/public
3434

3535
# Misc
36-
recursive-include .cursor *.json
36+
recursive-include .claude *.md
37+
recursive-include .codex *.toml *.md
38+
recursive-include .cursor *.json *.md
3739
recursive-include .github *.yml *.yaml
3840
recursive-include cicd_utils README.md *.py *.sh
3941
recursive-include misc *.py *.ipynb *.txt *.png
4042
recursive-include requirements *.txt
43+
recursive-include skills *.md
4144
recursive-include tests *.py
4245
recursive-include tests/e2e/artifacts *.json
4346

Makefile

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ VENV_BIN := $(VENV_PATH)/bin
1010
OFFLINE ?= 0
1111
ifeq ($(OFFLINE), 1)
1212
_UV_OFFLINE_ARG = --offline
13-
1413
else
1514
_UV_OFFLINE_ARG =
1615
endif
@@ -58,7 +57,7 @@ _check-sys: ## Check system requirements
5857
fi
5958

6059

61-
$(VENV_PATH): _check-sys ## create a virtual environment
60+
$(VENV_PATH): | _check-sys ## create a virtual environment
6261
@echo "==> Creating local virtual environment under: $(VENV_PATH)/ ($(BASE_PYTHON))"
6362
@uv venv $(_UV_OFFLINE_ARG) --python="$(BASE_PYTHON)" --seed "$(VENV_PATH)"
6463

@@ -78,7 +77,7 @@ install: $(VENV_PATH) ## install all local development dependencies
7877
.PHONY: jupyter-init
7978
jupyter-init: install ## initialise a jupyter environment
8079
@echo "==> Setting up jupyterlab environment..."
81-
@$(VENV_BIN)/uv pip install --upgrade ipykernel jupyter
80+
@uv pip install --upgrade ipykernel jupyter
8281
@$(VENV_BIN)/python -m ipykernel install --user --name='ridgeplot' --display-name='ridgeplot'
8382

8483

docs/reference/changelog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ Unreleased changes
1818

1919
### Developer Experience
2020

21+
- Add AGENTS.md, CLAUDE.md, .codex/, and .cursor/ helper files for AI-assisted development ({gh-pr}`367`)
22+
- Small improvements to the project's Makefile ({gh-pr}`367`)
2123
- Add a basic version of Cursor's `worktrees.json` config ({gh-pr}`364`)
2224

2325
### CI/CD

0 commit comments

Comments
 (0)