Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
775 changes: 775 additions & 0 deletions .ai/ARCHITECTURE.md

Large diffs are not rendered by default.

81 changes: 81 additions & 0 deletions .ai/COMMANDS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Commands

## Initial Setup

```bash
# Create and activate virtual environment
python3 -m venv venv
source venv/bin/activate # Windows: source venv/scripts/activate

# Install Python dependencies
pip install -e .[ci,dev,testing,celery,diskcache]

# Install Node dependencies
npm ci
```

## Building

```bash
# Full build (Linux/Mac)
npm run build

# Full build (Windows - use Bash terminal, not PowerShell/CMD)
npm run first-build

# Build single component after changes
dash-update-components "dash-core-components" # or dash-html-components, dash-table

# Build renderer only
cd dash/dash-renderer && renderer build
```

## Testing

Tests use pytest with Selenium/ChromeDriver. ChromeDriver must match your Chrome version. See [TESTING.md](TESTING.md) for fixtures, patterns, and detailed documentation.

```bash
# Run all tests
npm run test

# Unit tests only
pytest tests/unit

# Integration tests (requires ChromeDriver)
pytest tests/integration

# Run specific test by name
pytest -k test_name

# Run tests matching pattern
pytest -k cbcx # runs all tests with "cbcx" in name

# Renderer unit tests (Jest)
cd dash/dash-renderer && npm run test

# Setup test components before running integration tests
npm run setup-tests.py
```
Comment on lines +37 to +58
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

similar to the "Quick Reference" I don't think we should have duplicate examples.


## Linting

Linting runs automatically on commit via husky pre-commit hook and lint-staged (`.lintstagedrc.js`). You typically don't need to run these manually.

**Pre-commit runs on staged files:**
- Python (`dash/`, `tests/`): pylint, flake8, black --check
- JavaScript/TypeScript: eslint, prettier --check (per component package)

**Manual commands** (if needed):

```bash
# Run all linters
npm run lint

# Individual linters
npm run private::lint.black # Check Black formatting
npm run private::lint.flake8 # Flake8
npm run private::lint.pylint-dash # Pylint on dash/

# Auto-format Python with Black
npm run private::format.black
```
182 changes: 182 additions & 0 deletions .ai/COMPONENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
# Component System

The component system bridges React components to Python with auto-generated wrappers.

## Generation Pipeline

```
React/TypeScript Source
extract-meta.js (Node.js)
├── react-docgen (for .js/.jsx - parses PropTypes)
└── TypeScript Compiler API (for .tsx - parses type definitions)
metadata.json
dash-generate-components (Python CLI)
Python component classes (+ R/Julia if requested)
```

### Key Files

- **`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.

- **`dash/development/component_generator.py`** - CLI entry point (`dash-generate-components`). Orchestrates metadata extraction and code generation.

- **`dash/development/_py_components_generation.py`** - Generates Python class files from metadata. Creates typed `__init__` methods, docstrings, and prop validation.

- **`dash/development/_py_prop_typing.py`** - Maps JavaScript/TypeScript types to Python types (e.g., `arrayOf` → `typing.Sequence`, `shape` → `TypedDict`).

- **`dash/development/_generate_prop_types.py`** - For TypeScript components, generates a `proptypes.js` file since TSX doesn't have runtime PropTypes.

## Component JSON Structure

Components serialize to `{type, namespace, props}` via `to_plotly_json()` in `base_component.py`:

```python
# Python component
html.Div(id='my-div', children='Hello')

# Serializes to JSON
{
"type": "Div",
"namespace": "dash_html_components",
"props": {
"id": "my-div",
"children": "Hello"
}
}
```

This JSON is sent to the frontend via `/_dash-layout` (initial load) and `/_dash-update-component` (callback responses).

## Frontend Component Resolution

Components must be available on the frontend at `window[namespace][type]`:

```javascript
// Component packages register themselves
window.dash_html_components = {
Div: DivComponent,
Span: SpanComponent,
// ...
};

window.dash_core_components = {
Dropdown: DropdownComponent,
Graph: GraphComponent,
// ...
};
```

The renderer resolves components via `registry.js`:

```javascript
resolve: (component) => {
const {type, namespace} = component;
return window[namespace][type]; // Returns React component class
}
```

## Package Structure

### `_imports_.py`

Auto-generated by `generate_imports()` in `_py_components_generation.py`:

```python
from .Dropdown import Dropdown
from .Graph import Graph
from .Input import Input
# ... one import per component

__all__ = [
"Dropdown",
"Graph",
"Input",
# ...
]
```

### `__init__.py`

Manually maintained, imports from `_imports_.py`:

```python
from ._imports_ import * # Re-exports all components
from ._imports_ import __all__ as _components

# Read version from package-info.json
with open(os.path.join(_basepath, "package-info.json")) as f:
package = json.load(f)
__version__ = package["version"]

# Define JavaScript assets to serve
_js_dist = [
{
"relative_package_path": "dash_core_components.js",
"namespace": "dash",
},
# async chunks, source maps, proptypes.js for dev, etc.
]

# Attach _js_dist to each component class
for _component in _components:
setattr(locals()[_component], "_js_dist", _js_dist)
```

## Resource System (`_js_dist` / `_css_dist`)

**`dash/resources.py`** manages JavaScript and CSS asset loading for components.

### Resource Entry Structure

```python
{
"relative_package_path": "dcc/dash_core_components.js", # Path within package
"external_url": "https://unpkg.com/...", # CDN fallback
"namespace": "dash", # JS namespace
"async": True | "eager" | "lazy", # Async loading mode
"dynamic": True, # Loaded on demand (source maps)
"dev_package_path": "dcc/proptypes.js", # Dev-only path
"dev_only": True, # Only in dev mode
}
```

### Resource Loading Flow

1. Each component class has `_js_dist` (and optionally `_css_dist`) attribute set in `__init__.py`
2. When component is imported, `ComponentMeta` registers module in `ComponentRegistry.registry`
3. `ComponentRegistry.get_resources("_js_dist")` iterates registered modules, collects all `_js_dist` lists
4. `Scripts` / `Css` classes in `resources.py` filter resources based on config:
- `serve_locally=True`: Use `relative_package_path`, serve via `/_dash-component-suites/`
- `serve_locally=False`: Use `external_url` (CDN)
- `eager_loading=True`: Load async resources immediately
- `dev_bundles=True`: Include `dev_package_path` resources

### Async Loading Modes

- `async: True` - Dynamic unless `eager_loading` is enabled
- `async: "lazy"` - Always loaded dynamically (on-demand)
- `async: "eager"` - Loaded dynamically only if server isn't in eager mode

## Creating New Components

1. Write React component with PropTypes (JS) or TypeScript props interface (TSX)
2. Run `dash-generate-components src/lib/components -p package_name`
3. Generated Python wrapper goes to `package_name/ComponentName.py`
4. `_imports_.py` is auto-generated with imports for all components
5. For TSX, `proptypes.js` is also generated for runtime prop validation
6. Bundle with webpack, register on `window[namespace]`
7. Update `__init__.py` to set `_js_dist` on components

## Built-in Component Packages

Managed as a Lerna monorepo in `components/`:

- **`components/dash-core-components/`** - Interactive components (Dropdown, Slider, Graph, Input, etc.)
- **`components/dash-html-components/`** - HTML element wrappers (Div, Span, H1, etc.)
- **`components/dash-table/`** - DataTable component (deprecated in favor of dash-ag-grid)

Use `dash-update-components "component-name"` to rebuild after changes.
48 changes: 48 additions & 0 deletions .ai/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Dash AI Agent Guide

This directory contains documentation for AI coding assistants working with the Dash codebase.

## Quick Links

- [Commands](./COMMANDS.md) - Build, test, and lint commands
- [Architecture](./ARCHITECTURE.md) - Backend, callbacks, pages, assets, errors, background callbacks, Jupyter, config, stores, async, security
- [Renderer](./RENDERER.md) - Frontend, crawlLayout, Redux store, clientside API, component API
- [Components](./COMPONENTS.md) - Component generation, package structure, resource system
- [Testing](./TESTING.md) - Testing framework, fixtures, patterns, type compliance
- [Troubleshooting](./TROUBLESHOOTING.md) - Common errors and solutions

## Project Overview

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.

## Key Directories

```
dash/
├── dash/ # Main Python package
│ ├── dash.py # Core Dash app class
│ ├── _callback.py # Callback registration/execution
│ ├── dependencies.py # Input/Output/State classes
│ ├── _pages.py # Multi-page app support
│ ├── development/ # Component generation tools
│ ├── dash-renderer/ # TypeScript/React frontend
│ └── dcc/, html/, dash_table/ # Built-in components
├── components/ # Component source packages (Lerna monorepo)
│ ├── dash-core-components/
│ ├── dash-html-components/
│ └── dash-table/
├── tests/
│ ├── unit/ # pytest unit tests
│ ├── integration/ # Selenium browser tests
│ ├── compliance/ # Type checking (pyright/mypy)
│ └── background_callback/ # Background callback tests
└── requirements/ # Modular dependency files
```

## Code Review Conventions

Emoji used in reviews:
- `:dancer:` - Can merge
- `:tiger2:` - Needs more tests
- `:snake:` - Security concern
- `:pill:` - Performance issue
Loading
Loading