Metadata-Version: 2.4
Name: alloy_notebooks
Version: 0.4.4
Summary: Multi-language notebook extension for JupyterLab with SQL, charting, and cross-language data sharing
Project-URL: Homepage, https://github.com/alloy-notebooks/alloy-notebooks
Project-URL: Bug Tracker, https://github.com/alloy-notebooks/alloy-notebooks/issues
Project-URL: Repository, https://github.com/alloy-notebooks/alloy-notebooks.git
Author-email: Alloy Team <alloy@example.com>
License: BSD 3-Clause License
        
        Copyright (c) 2026, Alloy Team
        All rights reserved.
        
        Redistribution and use in source and binary forms, with or without
        modification, are permitted provided that the following conditions are met:
        
        1. Redistributions of source code must retain the above copyright notice, this
           list of conditions and the following disclaimer.
        
        2. Redistributions in binary form must reproduce the above copyright notice,
           this list of conditions and the following disclaimer in the documentation
           and/or other materials provided with the distribution.
        
        3. Neither the name of the copyright holder nor the names of its
           contributors may be used to endorse or promote products derived from
           this software without specific prior written permission.
        
        THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
        AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
        DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
        FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
        SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
        CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
        OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
        OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
License-File: LICENSE
Keywords: jupyter,jupyterlab,jupyterlab-extension
Classifier: Framework :: Jupyter
Classifier: Framework :: Jupyter :: JupyterLab
Classifier: Framework :: Jupyter :: JupyterLab :: 4
Classifier: Framework :: Jupyter :: JupyterLab :: Extensions
Classifier: Framework :: Jupyter :: JupyterLab :: Extensions :: Prebuilt
Classifier: License :: OSI Approved :: BSD License
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Requires-Python: >=3.10
Requires-Dist: jupysql>=0.10.0
Requires-Dist: jupyter-server<3,>=2.4.0
Requires-Dist: matplotlib>=3.7
Requires-Dist: pandas>=2.0
Requires-Dist: plotly>=5.0
Requires-Dist: sqlalchemy>=2.0
Provides-Extra: dev
Requires-Dist: jupyterlab>=4; extra == 'dev'
Provides-Extra: test
Requires-Dist: coverage; extra == 'test'
Requires-Dist: pytest; extra == 'test'
Requires-Dist: pytest-asyncio; extra == 'test'
Requires-Dist: pytest-cov; extra == 'test'
Requires-Dist: pytest-jupyter[server]>=0.6.0; extra == 'test'
Description-Content-Type: text/markdown

# Alloy Notebooks

**Multi-language notebooks for JupyterLab** -- write SQL, Python, and R in the same notebook with seamless data sharing between languages.

Built as a replacement for Azure Data Studio's notebook experience, which was [retired in February 2026](https://learn.microsoft.com/en-us/sql/tools/whats-happening-azure-data-studio).

![JupyterLab 4](https://img.shields.io/badge/JupyterLab-4.x-orange)
![Python 3.10+](https://img.shields.io/badge/Python-3.10%2B-blue)
![License](https://img.shields.io/badge/License-BSD--3-green)

## Features

### SQL Cells with Inline Results
- Set any cell to **SQL** using the unified dropdown (Python | SQL | R | Markdown | Raw)
- SQL syntax highlighting
- Results rendered as interactive tables with row counts
- Click **Chart** to see value-count bar charts for each column -- no code needed
- Click **Configure Chart** for custom visualizations (bar, line, scatter, pie, area, histogram)

### Connection Manager
- Sidebar panel to save and manage database connections
- Supports **SQL Server**, PostgreSQL, MySQL, SQLite, DuckDB
- Auto-detects installed ODBC drivers
- Windows Authentication and SQL Authentication
- Connections persist across sessions (`~/.alloy/connections.json`)

### DuckDB Cells — Query DataFrames with SQL
- Set any cell to **DuckDB** in the dropdown
- Write SQL that queries your pandas DataFrames as if they were tables
- JOIN across DataFrames, use window functions, CTEs — full SQL power
- Results saved as `_alloy_last_result` or via `-- save as: varname`
- No database connection needed — DuckDB runs in-process
- Can also read Parquet/CSV files: `SELECT * FROM 'data.parquet'`

### Multiple Database Connections
- Connect to multiple databases simultaneously (SQL Server, PostgreSQL, MariaDB, etc.)
- Each connection gets a named alias
- Target specific connections with `-- connection: alias` in SQL cells
- Sidebar shows all active connections with green indicators
- Auto-reconnects all connections when the kernel restarts

### Cross-Language Data Sharing
- SQL results automatically available as pandas DataFrames in Python
- Name your results with `-- save as: my_data` in SQL cells
- R cells automatically receive only the Python variables they reference (smart transfer)
- New R variables (data.frames) automatically come back to Python after execution
- Uses **Apache Arrow** for near-zero-copy transfers when `pyarrow` + `rpy2-arrow` are installed (~425x faster than pandas2ri)
- `%alloy_vars` magic to list all available DataFrames

### Language Icons
- Small language icons (Python, SQL, R, Markdown) on the left margin of each cell
- Toggleable via Settings > Alloy Notebooks > "Show language icons"

### Unified Cell Type Dropdown
- Single dropdown replacing JupyterLab's Code/Markdown/Raw and a separate language selector
- Options: **Python | SQL | R | Markdown | Raw**
- Switching languages updates syntax highlighting instantly

## Install

### From PyPI (recommended)
```bash
pip install alloy-notebooks
```

### From GitHub (latest development version)
```bash
pip install git+https://github.com/Columbia-Data-Labs/alloy-notebooks.git
```

### Optional dependencies

For **SQL Server** connections:
```bash
pip install pyodbc
```

For **R** support:
```bash
pip install rpy2
```

For **fast data transfer** between Python and R (near-zero-copy via Apache Arrow):
```bash
pip install pyarrow rpy2-arrow
```

## Quick Start

1. **Install**: `pip install alloy-notebooks`
2. **Start JupyterLab**: `jupyter lab`
3. **Connect**: Click "Alloy" in the left sidebar, add a database connection
4. **Write SQL**: Create a cell, select "SQL" from the dropdown, write a query, run it
5. **See results**: Table with Chart button appears below the cell
6. **Use in Python**: Results are in `_alloy_last_result`, or use `-- save as: my_df` to name them
7. **Use in R**: Switch a cell to "R", reference your DataFrame by name -- it transfers automatically

## Example Workflow

**SQL cell (default connection):**
```sql
-- save as: orders
SELECT customer_name, product, quantity, price
FROM sales.orders
WHERE order_date > '2026-01-01'
```

**SQL cell (specific connection):**
```sql
-- connection: nas
-- save as: backups
SELECT * FROM backup_logs ORDER BY created_at DESC
```

**DuckDB cell (query DataFrames with SQL — no database needed):**
```sql
-- save as: top_customers
SELECT customer_name, SUM(quantity * price) as revenue
FROM orders
GROUP BY customer_name
ORDER BY revenue DESC
LIMIT 10
```

**Python cell:**
```python
# 'orders' and 'top_customers' are both pandas DataFrames
orders['total'] = orders['quantity'] * orders['price']
print(orders.describe())
```

**R cell:**
```r
# 'orders' transfers automatically -- only this variable, not everything
summary(orders)
model <- lm(total ~ quantity, data = orders)
summary(model)
```

**Python cell:**
```python
# 'model' created in R is available if it's a data.frame
# Use %alloy_vars to see all available DataFrames
%alloy_vars
```

## Platform Support

Works on **Windows**, **Linux**, and **macOS**. R and ODBC driver paths are auto-detected per platform.

## Requirements

- JupyterLab >= 4.0.0
- Python >= 3.10

### Database drivers

| Database | Package | Notes |
|---|---|---|
| SQL Server | `pyodbc` | Windows: ODBC Driver 17/18. Linux/Mac: `unixodbc` + Microsoft ODBC driver or FreeTDS |
| PostgreSQL | `psycopg2` | `pip install psycopg2-binary` |
| MySQL/MariaDB | `pymysql` | `pip install pymysql` |
| SQLite | (built-in) | No extra install needed |
| DuckDB | `duckdb` | `pip install duckdb` |

### SQL Server on Linux/Mac
```bash
# Ubuntu/Debian
curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -
sudo apt-get install -y msodbcsql18 unixodbc-dev
pip install pyodbc

# macOS (Homebrew)
brew install unixodbc microsoft/mssql-release/msodbcsql18
pip install pyodbc
```

### R integration
- Install R (4.4+) for your platform
- `pip install rpy2`
- For fast transfers: `pip install pyarrow rpy2-arrow`
- R_HOME is auto-detected on all platforms

## Development

```bash
# Clone and install in development mode
git clone https://github.com/Columbia-Data-Labs/alloy-notebooks.git
cd alloy-notebooks
pip install -e ".[dev]"
jlpm install
jlpm build

# Watch for changes
jlpm watch  # in one terminal
jupyter lab  # in another terminal
```

## License

BSD-3-Clause

## Acknowledgments

Inspired by [Azure Data Studio](https://learn.microsoft.com/en-us/sql/azure-data-studio/) notebooks and built on top of [JupySQL](https://github.com/ploomber/jupysql) for SQL execution.
