Metadata-Version: 2.4
Name: kumo-connectors
Version: 1.0.1
Summary: Shared data-source connectors (connect, read, SQL quoting) for the kumo-relational-client and its engines
Author: NVIDIA
License-Expression: Apache-2.0
Project-URL: Homepage, https://github.com/kumo-ai/kumo-relational-client
Project-URL: Source, https://github.com/kumo-ai/kumo-relational-client
Project-URL: Issues, https://github.com/kumo-ai/kumo-relational-client/issues
Keywords: structured-data,connectors,sql
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3 :: Only
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: Topic :: Database
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
Requires-Dist: pandas>=2.0
Requires-Dist: pyarrow
Provides-Extra: sqlite
Requires-Dist: adbc-driver-sqlite; extra == "sqlite"
Provides-Extra: duckdb
Requires-Dist: duckdb>=1.5.0; extra == "duckdb"
Provides-Extra: snowflake
Requires-Dist: snowflake-connector-python; extra == "snowflake"
Provides-Extra: databricks
Requires-Dist: databricks-sql-connector<5,>=4.0.3; extra == "databricks"
Provides-Extra: postgres
Requires-Dist: psycopg[binary]>=3.1; extra == "postgres"
Provides-Extra: s3
Requires-Dist: s3fs>=2023.12.0; extra == "s3"
Provides-Extra: all
Requires-Dist: kumo-connectors[databricks,duckdb,postgres,s3,snowflake,sqlite]; extra == "all"
Provides-Extra: test
Requires-Dist: pytest; extra == "test"
Requires-Dist: moto[server]>=5; extra == "test"
Dynamic: license-file

# kumo-connectors

Shared data-source connectors for the [`kumo-relational-client`](../kumo-relational-client/README.md) client and its
model engines. One place that knows how to reach each warehouse, so the client
(flat table reads) and the Kumo Relational driver (warehouse connections for
its graph samplers) don't each carry their own copy.

It provides:

- `connect(backend, **kwargs)`: open a connection to `sqlite` / `duckdb` /
  `snowflake` / `databricks` / `postgres` (one driver per backend).
- `read(source, **kwargs) -> DataFrame`: read a table or query as a flat pandas
  DataFrame (also handles `local` DataFrames / CSV / Parquet, and `s3` object
  URIs: `read('s3', path='s3://bucket/table.parquet', storage_options=...)`).
- `read_table(connection, table=…, query=…) -> DataFrame`: driver-agnostic
  fetch over an open connection, in that connection's own session.
- `quote_ident(ident, char='"')` and `resolve_sql(table=…, query=…)`: SQL
  identifier quoting and a safe table/query guard.

File reads (`local` and `s3`) accept `.csv` / `.txt` (optionally compressed) and
`.parquet` / `.pq` / `.parq`, plus a directory as a Parquet dataset. Any other
suffix is rejected with `INVALID_CONNECTOR_ARGS` rather than parsed as CSV; pass
`format='csv'` or `format='parquet'` to read a file whose name carries no
recognised suffix.

The two file-backed backends, `sqlite` and `duckdb`, accept `database=` and
`uri=` as aliases for the same argument (supplying both is an error). The
remote backends, `snowflake`, `databricks`, and `postgres`, are addressed by
connection keywords instead, and reject any their driver does not declare;
`driver_options={...}` passes anything else straight through. The
`snowflake` backend reuses an active Snowpark session when no authentication
arguments are given; a borrowed session cannot be reconfigured, so passing
session-scoped arguments such as `schema=` alongside it is an error.

The `postgres` backend uses psycopg and accepts a PostgreSQL URI, a libpq
conninfo string, explicit connection keywords, or standard `PG*` environment
variables. Provider-specific requirements such as TLS must be passed explicitly
(for example, `sslmode='require'` for a direct Lakebase connection).

`table=` accepts only plain, unquoted, dot-separated ASCII identifiers, and
interpolates them as written, so they are subject to each backend's default
case folding (Snowflake upper-cases; Databricks and PostgreSQL lower-case). A
name that needs quoting (spaces, non-ASCII characters, a leading digit) is
rejected with `INVALID_CONNECTOR_ARGS`. A reserved word such as `select` is a plain
identifier by that rule, so it is accepted here and instead fails at execution
as `QUERY_FAILED`. Either way, reach the table through `query=` with
`quote_ident`, choosing the quote character your backend uses (`"` for
SQLite/DuckDB/Snowflake/PostgreSQL, `` ` `` for Databricks):

```python
read('duckdb', database='w.db', query=f'SELECT * FROM {quote_ident("café")}')
```

Failures raised by `connect` / `read` / `read_table` surface as
`ConnectorError` with a stable `code`: `UNKNOWN_CONNECTOR`,
`INVALID_CONNECTOR_ARGS`, `CONNECT_FAILED`, `QUERY_FAILED`, `READ_FAILED`, or
`NOT_FOUND`, with the original driver exception chained as `__cause__`. Two
cases stay unwrapped by design: a missing optional driver raises
`MissingBackendError`, and a broken or incompatible driver installation raises
`ImportError` (consumers map it to their own broken-install category, e.g.
kumo-relational-client's `DRIVER_LOAD_FAILED`).

Pure-python. Database drivers are optional extras:

```bash
pip install "kumo-connectors[sqlite]"      # or [duckdb] / [snowflake] / [databricks] / [postgres] / [s3] / [all]
```

Consumers depend on it and surface these extras under their own name, e.g.
`kumo-relational-client[snowflake]` and `kumo_relational_engine[databricks]` both resolve the corresponding
`kumo-connectors` extra.

## Local development

```bash
pip install -e ".[sqlite,duckdb,test]"
pytest tests
```
