Metadata-Version: 2.5
Name: AnalystStack
Version: 0.3.0
Summary: This package contains functions that help me tackle my day to day data analytics requirements
Project-URL: Homepage, https://github.com/AbisheakJacob/AnalystStack
Project-URL: Repository, https://github.com/AbisheakJacob/AnalystStack
Project-URL: Documentation, https://abisheakjacob.github.io/AnalystStack/
Project-URL: Changelog, https://github.com/AbisheakJacob/AnalystStack/releases
Author-email: Abisheak Jacob J <abisheakjacob0032@gmail.com>
License-Expression: MIT
License-File: LICENSE
Keywords: analytics,data,data-quality,etl,pandas,sql
Requires-Python: <3.14,>=3.13
Requires-Dist: jinja2>=3.1
Requires-Dist: openpyxl>=3.1
Requires-Dist: pandas>=2.0
Requires-Dist: ruff>=0.12
Requires-Dist: sqlfluff>=3.0
Requires-Dist: sqlglot>=26.0
Requires-Dist: tabulate>=0.9
Provides-Extra: bigquery
Requires-Dist: db-dtypes>=1.0; extra == 'bigquery'
Requires-Dist: google-cloud-bigquery>=3.0; extra == 'bigquery'
Requires-Dist: sqlalchemy-bigquery>=1.10; extra == 'bigquery'
Requires-Dist: sqlalchemy>=2.0; extra == 'bigquery'
Provides-Extra: databricks
Requires-Dist: databricks-sql-connector>=3.0; extra == 'databricks'
Requires-Dist: databricks-sqlalchemy>=2.0; extra == 'databricks'
Requires-Dist: sqlalchemy>=2.0; extra == 'databricks'
Provides-Extra: docs
Requires-Dist: mkdocstrings-python; extra == 'docs'
Requires-Dist: zensical; extra == 'docs'
Provides-Extra: duckdb
Requires-Dist: duckdb-engine>=0.13; extra == 'duckdb'
Requires-Dist: duckdb>=1.0; extra == 'duckdb'
Requires-Dist: sqlalchemy>=2.0; extra == 'duckdb'
Provides-Extra: pandera
Requires-Dist: pandera>=0.20; extra == 'pandera'
Provides-Extra: postgres
Requires-Dist: psycopg2-binary>=2.9; extra == 'postgres'
Requires-Dist: sqlalchemy>=2.0; extra == 'postgres'
Provides-Extra: snowflake
Requires-Dist: snowflake-sqlalchemy>=1.6; extra == 'snowflake'
Requires-Dist: sqlalchemy>=2.0; extra == 'snowflake'
Provides-Extra: stats
Requires-Dist: scipy>=1.11; extra == 'stats'
Description-Content-Type: text/markdown

# AnalystStack

[![CI](https://github.com/AbisheakJacob/AnalystStack/actions/workflows/workflow.yml/badge.svg)](https://github.com/AbisheakJacob/AnalystStack/actions/workflows/workflow.yml)
[![PyPI](https://img.shields.io/pypi/v/AnalystStack.svg)](https://pypi.org/project/AnalystStack/)
[![Python](https://img.shields.io/pypi/pyversions/AnalystStack.svg)](https://pypi.org/project/AnalystStack/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Docs](https://img.shields.io/badge/docs-zensical-blue.svg)](https://abisheakjacob.github.io/AnalystStack/)

**AnalystStack** is a Python toolkit of reusable helpers for the work data analysts do every
day: connecting to data warehouses, validating and reporting on data quality, reading and
writing files, rendering SQL from templates, and formatting code. It replaces the pile of
copy-pasted snippets every analyst accumulates with a small, tested, `pip install`-able
package.

📖 **Full documentation:** <https://abisheakjacob.github.io/AnalystStack/>

## Installation

```bash
# From PyPI
pip install AnalystStack

# With a warehouse connector -- also available: postgres, databricks, duckdb, snowflake
pip install "AnalystStack[bigquery]"

# With optional validation extras -- scipy-backed drift tests, or a pandera bridge
pip install "AnalystStack[stats,pandera]"

# From GitHub
pip install "git+https://github.com/AbisheakJacob/AnalystStack"
```

## Quickstart

```python
from AnalystStack import io

# Render SQL from an inline Jinja template...
query = io.read.jinja("SELECT * FROM {{ table }} WHERE region = '{{ region }}'",
                      table="sales", region="APAC")

# ...or from a template file on disk.
query = io.read.jinja("queries/monthly_sales.sql.j2", month="2026-05")

# Read an Excel range, write it back out as Markdown.
df = io.read.excel("report.xlsx", sheet_name="Data", start_cell="B2", end_cell="F100")
io.write.markdown(df, "summary.md")
```

```python
from AnalystStack.connectors import GoogleBigQueryConnector

bq = GoogleBigQueryConnector(gcp_project_id="my-project")
df = bq.read_data("SELECT * FROM dataset.table LIMIT 100")
profile = bq.profile_columns("dataset", "table")   # DataFrame: dtype, nullability, fill rate %, ...
```

```python
from AnalystStack import ReportBuilder, Validator, not_null, unique

validation = Validator([not_null("price"), unique("id")]).validate(df)
report = ReportBuilder("Table Data Quality Report").add_validation(validation).build()
report.write("data_quality_report.md")
```

## Modules

### Connectors

Read, write and profile tables in cloud data warehouses — BigQuery, Postgres, Databricks,
Snowflake, and embedded/local DuckDB ([docs](https://abisheakjacob.github.io/AnalystStack/connectors/)).
Every metadata method returns a DataFrame with the same columns across every backend, even
when a given warehouse can't cheaply populate one of them.

| Method | Description |
| ------ | ----------- |
| `read_data(query)` | Run a query and return a DataFrame. |
| `write_data(df, schema, table_id, if_exists="append")` | Write a DataFrame to a table. |
| `list_tables(schema)` | DataFrame of tables, with row count / size / created / last-altered. |
| `list_columns(schema, table_id)` | DataFrame of a table's columns: name, position, dtype, nullability. |
| `profile_columns(schema, table_id)` | `list_columns` plus fill rate / null counts per column. |

### Validation

Attach declarative sanity checks to a DataFrame, without a heavyweight schema library
([docs](https://abisheakjacob.github.io/AnalystStack/validate/)).

| Function / class | Description |
| ----------------- | ----------- |
| `not_null` / `unique` / `in_range` / `is_in` / `matches_regex` / `has_dtype` | Per-column rule factories. |
| `row_count_between` / `no_duplicate_rows` / `is_fresh` / `no_outliers` | Whole-frame / statistical rule factories. |
| `Validator([...]).validate(df)` / `.enforce(df)` | Run every rule; get a report, or raise on failure. |
| `validate.schema.check_schema` / `enforce_schema` | Column existence / order / dtype checks. |
| `validate.drift.compare_dataframe_drift` | Statistical drift between two snapshots of a DataFrame. |
| `validate.referential.check_referential_integrity` | Foreign-key-style checks between two DataFrames. |

### Reporting

Compose validation results, comparisons, and connector metadata into one deliverable — no
scheduling, just a call ([docs](https://abisheakjacob.github.io/AnalystStack/report/)).

```python
from AnalystStack import ReportBuilder

report = ReportBuilder("Orders Data Quality Report").add_validation(validation).build()
report.write("orders_report.xlsx", format="excel")
```

### Tidy data & Compare

`to_tidy` / `from_tidy` reshape DataFrames between wide and long
([docs](https://abisheakjacob.github.io/AnalystStack/tidy/)); `compare_dataframes` /
`summarize` diff two DataFrames and profile one in a single call
([docs](https://abisheakjacob.github.io/AnalystStack/compare/)).

### IO

Read and write data, and render Jinja templates ([docs](https://abisheakjacob.github.io/AnalystStack/io/)).

| Method | Description |
| ------ | ----------- |
| `read.excel` / `read.csv` / `read.parquet` | Read files into DataFrames. |
| `read.jinja(source, **context)` | Render a Jinja template from a **file path or string**. |
| `write.excel` / `write.csv` | Write DataFrames to files. |
| `write.markdown` / `write.txt` | Write a DataFrame or string to Markdown / text. |
| `write.clipboard` | Copy a DataFrame or string to the OS clipboard. |

### Formatting

Format and lint code from Python or the CLI ([docs](https://abisheakjacob.github.io/AnalystStack/formatting/)).

| Class | Description |
| ----- | ----------- |
| `PythonFormatter` | Format and syntax-check Python with Ruff + `ast`. |
| `SQLFormatter` | Format and lint SQL with SQLFluff (any dialect), at a configurable `FormattingLevel` from whitespace-only up to a `sqlglot`-powered structural rewrite. |

```bash
# CLI
analyststack format python path/to/file.py                                    # format in place
analyststack format sql    path/to/query.sql --lint                           # lint only
analyststack format sql    path/to/query.sql --dialect postgres --level low   # light touch-up only
```

## Development

This project is managed with [uv](https://docs.astral.sh/uv/) and targets **Python 3.13**.

```bash
git clone https://github.com/AbisheakJacob/AnalystStack
cd AnalystStack
uv sync --all-extras     # create .venv and install dev deps + every connector extra
```

`uv` reads the pinned interpreter from `.python-version` and installs it if needed
(`uv python install 3.13`).

Common tasks (see the `Makefile`, or run the commands directly with `uv run ...`):

| Command | Description |
| ------- | ----------- |
| `make sync` | Create/update `.venv` with all extras (`uv sync --all-extras`). |
| `make check` | Run format, lint, type-check and tests. |
| `make test` | Run the test suite with coverage (`uv run pytest`). |
| `make format` / `make lint` / `make typecheck` | Individual quality gates. |
| `make build` | Build the sdist and wheel (`uv build`). |
| `make docs` | Build the documentation site. |

The same gates run in CI with uv (`.github/workflows/workflow.yml`).

## Roadmap

Planned work — and recently closed gaps — live on the
[roadmap](https://abisheakjacob.github.io/AnalystStack/next-steps/).

## License

Released under the [MIT License](LICENSE).
