Metadata-Version: 2.4
Name: bideux
Version: 0.3.0
Summary: Bideux dashboards in one install: spec, core, engine, store, server, report and authoring.
Project-URL: Homepage, https://github.com/datalakehouse/bideux-working
Project-URL: Repository, https://github.com/datalakehouse/bideux-working
Project-URL: Documentation, https://github.com/datalakehouse/bideux-working/tree/develop/docs
Project-URL: Issues, https://github.com/datalakehouse/bideux-working/issues
Author: Bideux contributors
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: bideux,dashboard,fastapi,reports,semantic-model
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries
Classifier: Typing :: Typed
Requires-Python: <3.13,>=3.12
Requires-Dist: croniter==6.0.0
Requires-Dist: openpyxl==3.1.5
Requires-Dist: pillow==11.3.0
Requires-Dist: pydantic==2.13.4
Requires-Dist: python-dateutil==2.9.0.post0
Requires-Dist: python-pptx==1.0.2
Requires-Dist: pyyaml==6.0.2
Requires-Dist: ruamel-yaml==0.18.10
Requires-Dist: sqlalchemy>=2.0
Requires-Dist: sqlglot<31,>=27.14.0
Provides-Extra: ai
Requires-Dist: httpx<1,>=0.27; extra == 'ai'
Provides-Extra: demo
Requires-Dist: aiosqlite==0.21.0; extra == 'demo'
Requires-Dist: fastapi<1,>=0.115; extra == 'demo'
Requires-Dist: uvicorn<1,>=0.30; extra == 'demo'
Provides-Extra: fastapi
Requires-Dist: fastapi<1,>=0.115; extra == 'fastapi'
Provides-Extra: postgres
Requires-Dist: asyncpg==0.30.0; extra == 'postgres'
Provides-Extra: scope
Provides-Extra: sqlite
Requires-Dist: aiosqlite==0.21.0; extra == 'sqlite'
Provides-Extra: warehouse
Description-Content-Type: text/markdown

# `bideux`

Bideux dashboards in one install. This wheel carries the seven active Python
packages, `dashboard_spec`, `dashboard_core`, `dashboard_engine`,
`dashboard_store`, `dashboard_server`, `dashboard_report` and
`dashboard_authoring`, under their own import names, plus a `bideux` namespace
that re-exports the objects a host touches.

```bash
uv add bideux                    # the packages, no web framework
uv add "bideux[fastapi,sqlite]"  # plus the reader router and aiosqlite
uv add "bideux[fastapi,postgres]"
```

The granular `bideux-dashboard-*` wheels are unchanged and keep publishing. Pick
one family per environment: both provide the same `dashboard_*` modules, so
`import bideux` warns (`BideuxInstallConflict`) when it finds a granular
distribution next to it.

## What you import

```python
from bideux import Caller, DashboardService, DashboardReportService, Principal, ScopeContext
from bideux import Repositories, ServiceOptions          # ports and options
from bideux import DashboardAccessError, DashboardNotFoundError
from bideux.store import DashboardModelRepository        # one namespace per layer
from bideux.engine import ReferenceWarehouse, FixedClock
```

`bideux.spec`, `bideux.core`, `bideux.engine`, `bideux.store`, `bideux.server`,
`bideux.report` and `bideux.authoring` re-export every public name of the
matching layer, so a host never has to type a granular module name. The granular
names still work: every `from dashboard_server import ...` that runs against the
granular packages runs here unchanged. `bideux` is the short path, not a new
API.

## One call: `mount_bideux` (extra `fastapi`)

Tier 0 is one method and one call. `caller()` says who is asking; `database_url`
is where Bideux keeps its own tables; `warehouse=` is the SQLAlchemy engine your
rows live in.

```python
from fastapi import FastAPI, Request
from sqlalchemy.ext.asyncio import create_async_engine

from bideux.fastapi import mount_bideux
from bideux.hosting import HostAdapter
from bideux.server import Caller


class MyHost(HostAdapter):
    async def caller(self, request: Request) -> Caller:
        user = await my_auth(request)                      # your session, JWT or header
        return Caller(subject=user.id, is_admin=user.is_admin)


app = FastAPI()
bideux = mount_bideux(
    app,
    host=MyHost(),
    database_url="sqlite+aiosqlite:///dashboards.sqlite3",
    warehouse=create_async_engine("postgresql+asyncpg://..."),
)
```

That installs the reader, dashboard management and sharing, authoring, semantic
model and report routes under `/api/dashboards`, creates the store tables on
startup, runs widget SQL on your engine through the shipped
`SQLAlchemyWarehouse`, and is the API `<bideux-dashboard-list>`,
`<bideux-dashboard>` and the React components expect. `bideux init` writes this
file for you.

Everything else is a default you replace when you already own the thing (Tier
1): `engine=` and `session_for` to run inside your connection and transaction,
`migration_mode=MigrationMode.REUSE_ONLY` so your migrations own the tables,
`store_modules=("core", "durable")` for a persistent audit trail and cache,
`environment="production"` to be warned about memory defaults,
`require_host_session=True` to fail closed, and `HostAdapter` methods for
people, branding, embed secrets and the model editor. A host whose callers may
only read some rows adds a `RowScopePort` (Tier 2; the location plug in ships as
`bideux[scope]`). `bideux.report_service(caller)` is the port a host scheduler
calls. Every knob with its default is in the
[configuration reference](https://datalakehouse.github.io/bideux-working/docs/guides/configuration);
the tiers are explained in
[Choosing your tier](https://datalakehouse.github.io/bideux-working/docs/guides/host-integration#choosing-your-tier).

## The `bideux` command

```bash
bideux demo             # seeded API and page on http://127.0.0.1:5477 (needs bideux[demo] and the repo's conformance/fixtures)
bideux init my-app      # writes bideux_host.py and dashboard.html to start from
bideux doctor .         # checks the Python and Node install: versions, extras, mixed packages, stale node_modules
```

## `bideux.fastapi` piece by piece

The four reader routes the React reader and `@dlh.io/bideux`'s
`createHttpDashboardTransport` call, driven by one host-supplied factory:

```python
from contextlib import asynccontextmanager
from bideux.fastapi import build_reader_router, install_error_handlers

@asynccontextmanager
async def service_for(request: Request):
    caller = await authenticate(request)            # the host's identity
    async with sessions.begin() as session:         # the host's database
        yield DashboardService(caller=caller, repositories=repos(session), engines=engine_for, ...)

app.include_router(build_reader_router(service_for, prefix="/api/custom-dashboards"))
install_error_handlers(app)
```

`build_dashboard_router`, `build_authoring_router` and `build_report_router` are
the other groups `mount_bideux` installs, usable one by one the same way.

## `bideux.quickstart`

```python
from bideux.quickstart import DashboardDocuments, local_caller, memory_service

service = memory_service(
    caller=local_caller("olive"),
    dashboards=[DashboardDocuments(dashboard_yaml, [kpi_yaml, chart_yaml])],
    tables={"MART.RPT_DAILY_SALES_SUMMARY": rows},
)
render = await service.get_dashboard_render("sales-overview")
```

No database, no warehouse: in-memory repositories and the reference SQL
evaluator. Each keyword is a port a host later replaces.

## Not included

Scheduling. `bideux-dashboard-schedule` is deprecated and left out; a host owns
its schedules and calls `DashboardReportService.render` for the bytes.

## Version

`bideux` tracks the version of the packages it bundles; the release script
refuses to publish when they differ.
