Metadata-Version: 2.5
Name: insightfactory-sdk
Version: 8.0.6
Summary: Insight Factory REST API client
Author-email: "insightfactory.ai Support" <support@insightfactory.ai>
Keywords: insightfactory,openapi,sdk
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: httpx>=0.28.1
Requires-Dist: pydantic>=2.11
Requires-Dist: python-dateutil>=2.8.2
Requires-Dist: typing-extensions>=4.7.1
Description-Content-Type: text/markdown

# insightfactory-sdk

Async Python client for the Insight Factory REST API.

```python
from insightfactory_sdk import ApiClient, Configuration
from insightfactory_sdk.api.tasks_api import TasksApi

config = Configuration(
    host="https://your-factory.insightfactory.ai", access_token=token
)

async with ApiClient(config) as client:
    tasks = await TasksApi(client).tasks_get()
```

Every operation is `async` and non-blocking, over a pooled `httpx.AsyncClient`.
Each also has a `_sync` twin for scripts and notebooks — note this builds its own
client, outside any `async with` block:

```python
sync_client = ApiClient(config)
tasks = TasksApi(sync_client).tasks_get_sync()
```

`_sync` runs the coroutine on a dedicated background event loop, so it must **not**
be called from inside `async` code — `await` the async method there instead.

Don't mix the two on one `ApiClient`. The connection pool is created on the first
request and bound to whichever loop issued it, so a client used both ways binds its
pool to one loop and fails on the other — usually as an `Event loop is closed` far
from the call that caused it. Use a separate client for each style.

## Layout

| path | |
|---|---|
| `src/insightfactory_sdk/` | generated — do not hand-edit, `make generate` overwrites it |
| `openapi/swagger.json` | the spec the client is generated from |
| `tools/patch_spec.py` | assigns operationIds so methods get readable names |
| `tools/operation_id_overrides.json` | hand-chosen names where the path doesn't state intent |
| `tests/` | hand-written |

Only the package tree is copied out of the generator's output, so `pyproject.toml`,
this README and CI are never at risk of being clobbered — there is no
`.openapi-generator-ignore` to keep in sync.

## Regenerating

```bash
make regen     # fetch the latest spec, then regenerate
make generate  # regenerate from the committed spec
make lint test # what CI runs

make test-integration          # live read-only tests (token via if-cli)
make test-integration-writes   # plus the write paths
```

`make check-drift` regenerates and fails if the committed client is stale — wire it
into CI so a new endpoint can't ship without the SDK catching up.

Method names come from operationIds. The API does not currently emit any, so
`patch_spec.py` derives them from tag, path and verb before generation. It skips any
operation that already has one, so when the API starts supplying its own
(`CustomOperationIds` in `if_fc_interfaces_api`) this step becomes a no-op and both
it and the overrides file can be deleted.

## Versioning

`pyproject.toml` is the single source of truth. The Makefile passes it to the
generator as `packageVersion`, so the wheel and `insightfactory_sdk.__version__`
cannot drift; a test asserts it.
