Skip to content

Commit bf5a329

Browse files
authored
Merge pull request #3732 from plotly/claude-init
Initialize ai agents documentation
2 parents 21ae4d5 + a20bf1b commit bf5a329

File tree

10 files changed

+2307
-0
lines changed

10 files changed

+2307
-0
lines changed

.ai/ARCHITECTURE.md

Lines changed: 775 additions & 0 deletions
Large diffs are not rendered by default.

.ai/COMMANDS.md

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# Commands
2+
3+
## Initial Setup
4+
5+
```bash
6+
# Create and activate virtual environment
7+
python3 -m venv venv
8+
source venv/bin/activate # Windows: source venv/scripts/activate
9+
10+
# Install Python dependencies
11+
pip install -e .[ci,dev,testing,celery,diskcache]
12+
13+
# Install Node dependencies
14+
npm ci
15+
```
16+
17+
## Building
18+
19+
```bash
20+
# Full build (Linux/Mac)
21+
npm run build
22+
23+
# Full build (Windows - use Bash terminal, not PowerShell/CMD)
24+
npm run first-build
25+
26+
# Build single component after changes
27+
dash-update-components "dash-core-components" # or dash-html-components, dash-table
28+
29+
# Build renderer only
30+
cd dash/dash-renderer && renderer build
31+
```
32+
33+
## Testing
34+
35+
Tests use pytest with Selenium/ChromeDriver. ChromeDriver must match your Chrome version. See [TESTING.md](TESTING.md) for fixtures, patterns, and detailed documentation.
36+
37+
```bash
38+
# Run all tests
39+
npm run test
40+
41+
# Unit tests only
42+
pytest tests/unit
43+
44+
# Integration tests (requires ChromeDriver)
45+
pytest tests/integration
46+
47+
# Run specific test by name
48+
pytest -k test_name
49+
50+
# Run tests matching pattern
51+
pytest -k cbcx # runs all tests with "cbcx" in name
52+
53+
# Renderer unit tests (Jest)
54+
cd dash/dash-renderer && npm run test
55+
56+
# Setup test components before running integration tests
57+
npm run setup-tests.py
58+
```
59+
60+
## Linting
61+
62+
Linting runs automatically on commit via husky pre-commit hook and lint-staged (`.lintstagedrc.js`). You typically don't need to run these manually.
63+
64+
**Pre-commit runs on staged files:**
65+
- Python (`dash/`, `tests/`): pylint, flake8, black --check
66+
- JavaScript/TypeScript: eslint, prettier --check (per component package)
67+
68+
**Manual commands** (if needed):
69+
70+
```bash
71+
# Run all linters
72+
npm run lint
73+
74+
# Individual linters
75+
npm run private::lint.black # Check Black formatting
76+
npm run private::lint.flake8 # Flake8
77+
npm run private::lint.pylint-dash # Pylint on dash/
78+
79+
# Auto-format Python with Black
80+
npm run private::format.black
81+
```

.ai/COMPONENTS.md

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
# Component System
2+
3+
The component system bridges React components to Python with auto-generated wrappers.
4+
5+
## Generation Pipeline
6+
7+
```
8+
React/TypeScript Source
9+
10+
extract-meta.js (Node.js)
11+
├── react-docgen (for .js/.jsx - parses PropTypes)
12+
└── TypeScript Compiler API (for .tsx - parses type definitions)
13+
14+
metadata.json
15+
16+
dash-generate-components (Python CLI)
17+
18+
Python component classes (+ R/Julia if requested)
19+
```
20+
21+
### Key Files
22+
23+
- **`dash/extract-meta.js`** - Node.js script that extracts component metadata. For JavaScript components, uses `react-docgen` to parse PropTypes. For TypeScript components, uses the TypeScript Compiler API to parse type definitions and convert them to metadata format.
24+
25+
- **`dash/development/component_generator.py`** - CLI entry point (`dash-generate-components`). Orchestrates metadata extraction and code generation.
26+
27+
- **`dash/development/_py_components_generation.py`** - Generates Python class files from metadata. Creates typed `__init__` methods, docstrings, and prop validation.
28+
29+
- **`dash/development/_py_prop_typing.py`** - Maps JavaScript/TypeScript types to Python types (e.g., `arrayOf``typing.Sequence`, `shape``TypedDict`).
30+
31+
- **`dash/development/_generate_prop_types.py`** - For TypeScript components, generates a `proptypes.js` file since TSX doesn't have runtime PropTypes.
32+
33+
## Component JSON Structure
34+
35+
Components serialize to `{type, namespace, props}` via `to_plotly_json()` in `base_component.py`:
36+
37+
```python
38+
# Python component
39+
html.Div(id='my-div', children='Hello')
40+
41+
# Serializes to JSON
42+
{
43+
"type": "Div",
44+
"namespace": "dash_html_components",
45+
"props": {
46+
"id": "my-div",
47+
"children": "Hello"
48+
}
49+
}
50+
```
51+
52+
This JSON is sent to the frontend via `/_dash-layout` (initial load) and `/_dash-update-component` (callback responses).
53+
54+
## Frontend Component Resolution
55+
56+
Components must be available on the frontend at `window[namespace][type]`:
57+
58+
```javascript
59+
// Component packages register themselves
60+
window.dash_html_components = {
61+
Div: DivComponent,
62+
Span: SpanComponent,
63+
// ...
64+
};
65+
66+
window.dash_core_components = {
67+
Dropdown: DropdownComponent,
68+
Graph: GraphComponent,
69+
// ...
70+
};
71+
```
72+
73+
The renderer resolves components via `registry.js`:
74+
75+
```javascript
76+
resolve: (component) => {
77+
const {type, namespace} = component;
78+
return window[namespace][type]; // Returns React component class
79+
}
80+
```
81+
82+
## Package Structure
83+
84+
### `_imports_.py`
85+
86+
Auto-generated by `generate_imports()` in `_py_components_generation.py`:
87+
88+
```python
89+
from .Dropdown import Dropdown
90+
from .Graph import Graph
91+
from .Input import Input
92+
# ... one import per component
93+
94+
__all__ = [
95+
"Dropdown",
96+
"Graph",
97+
"Input",
98+
# ...
99+
]
100+
```
101+
102+
### `__init__.py`
103+
104+
Manually maintained, imports from `_imports_.py`:
105+
106+
```python
107+
from ._imports_ import * # Re-exports all components
108+
from ._imports_ import __all__ as _components
109+
110+
# Read version from package-info.json
111+
with open(os.path.join(_basepath, "package-info.json")) as f:
112+
package = json.load(f)
113+
__version__ = package["version"]
114+
115+
# Define JavaScript assets to serve
116+
_js_dist = [
117+
{
118+
"relative_package_path": "dash_core_components.js",
119+
"namespace": "dash",
120+
},
121+
# async chunks, source maps, proptypes.js for dev, etc.
122+
]
123+
124+
# Attach _js_dist to each component class
125+
for _component in _components:
126+
setattr(locals()[_component], "_js_dist", _js_dist)
127+
```
128+
129+
## Resource System (`_js_dist` / `_css_dist`)
130+
131+
**`dash/resources.py`** manages JavaScript and CSS asset loading for components.
132+
133+
### Resource Entry Structure
134+
135+
```python
136+
{
137+
"relative_package_path": "dcc/dash_core_components.js", # Path within package
138+
"external_url": "https://unpkg.com/...", # CDN fallback
139+
"namespace": "dash", # JS namespace
140+
"async": True | "eager" | "lazy", # Async loading mode
141+
"dynamic": True, # Loaded on demand (source maps)
142+
"dev_package_path": "dcc/proptypes.js", # Dev-only path
143+
"dev_only": True, # Only in dev mode
144+
}
145+
```
146+
147+
### Resource Loading Flow
148+
149+
1. Each component class has `_js_dist` (and optionally `_css_dist`) attribute set in `__init__.py`
150+
2. When component is imported, `ComponentMeta` registers module in `ComponentRegistry.registry`
151+
3. `ComponentRegistry.get_resources("_js_dist")` iterates registered modules, collects all `_js_dist` lists
152+
4. `Scripts` / `Css` classes in `resources.py` filter resources based on config:
153+
- `serve_locally=True`: Use `relative_package_path`, serve via `/_dash-component-suites/`
154+
- `serve_locally=False`: Use `external_url` (CDN)
155+
- `eager_loading=True`: Load async resources immediately
156+
- `dev_bundles=True`: Include `dev_package_path` resources
157+
158+
### Async Loading Modes
159+
160+
- `async: True` - Dynamic unless `eager_loading` is enabled
161+
- `async: "lazy"` - Always loaded dynamically (on-demand)
162+
- `async: "eager"` - Loaded dynamically only if server isn't in eager mode
163+
164+
## Creating New Components
165+
166+
1. Write React component with PropTypes (JS) or TypeScript props interface (TSX)
167+
2. Run `dash-generate-components src/lib/components -p package_name`
168+
3. Generated Python wrapper goes to `package_name/ComponentName.py`
169+
4. `_imports_.py` is auto-generated with imports for all components
170+
5. For TSX, `proptypes.js` is also generated for runtime prop validation
171+
6. Bundle with webpack, register on `window[namespace]`
172+
7. Update `__init__.py` to set `_js_dist` on components
173+
174+
## Built-in Component Packages
175+
176+
Managed as a Lerna monorepo in `components/`:
177+
178+
- **`components/dash-core-components/`** - Interactive components (Dropdown, Slider, Graph, Input, etc.)
179+
- **`components/dash-html-components/`** - HTML element wrappers (Div, Span, H1, etc.)
180+
- **`components/dash-table/`** - DataTable component (deprecated in favor of dash-ag-grid)
181+
182+
Use `dash-update-components "component-name"` to rebuild after changes.

.ai/README.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Dash AI Agent Guide
2+
3+
This directory contains documentation for AI coding assistants working with the Dash codebase.
4+
5+
## Quick Links
6+
7+
- [Commands](./COMMANDS.md) - Build, test, and lint commands
8+
- [Architecture](./ARCHITECTURE.md) - Backend, callbacks, pages, assets, errors, background callbacks, Jupyter, config, stores, async, security
9+
- [Renderer](./RENDERER.md) - Frontend, crawlLayout, Redux store, clientside API, component API
10+
- [Components](./COMPONENTS.md) - Component generation, package structure, resource system
11+
- [Testing](./TESTING.md) - Testing framework, fixtures, patterns, type compliance
12+
- [Troubleshooting](./TROUBLESHOOTING.md) - Common errors and solutions
13+
14+
## Project Overview
15+
16+
Dash is a Python framework for building reactive web-based data visualization applications. Built on Plotly.js, React, and Flask, it ties UI elements (dropdowns, sliders, graphs) directly to analytical Python code.
17+
18+
## Key Directories
19+
20+
```
21+
dash/
22+
├── dash/ # Main Python package
23+
│ ├── dash.py # Core Dash app class
24+
│ ├── _callback.py # Callback registration/execution
25+
│ ├── dependencies.py # Input/Output/State classes
26+
│ ├── _pages.py # Multi-page app support
27+
│ ├── development/ # Component generation tools
28+
│ ├── dash-renderer/ # TypeScript/React frontend
29+
│ └── dcc/, html/, dash_table/ # Built-in components
30+
├── components/ # Component source packages (Lerna monorepo)
31+
│ ├── dash-core-components/
32+
│ ├── dash-html-components/
33+
│ └── dash-table/
34+
├── tests/
35+
│ ├── unit/ # pytest unit tests
36+
│ ├── integration/ # Selenium browser tests
37+
│ ├── compliance/ # Type checking (pyright/mypy)
38+
│ └── background_callback/ # Background callback tests
39+
└── requirements/ # Modular dependency files
40+
```
41+
42+
## Code Review Conventions
43+
44+
Emoji used in reviews:
45+
- `:dancer:` - Can merge
46+
- `:tiger2:` - Needs more tests
47+
- `:snake:` - Security concern
48+
- `:pill:` - Performance issue

0 commit comments

Comments
 (0)