Metadata-Version: 2.4
Name: llama-cloud-fake
Version: 0.1.1
Summary: A respx-backed fake of the LlamaCloud v2 API for use in tests
Keywords: llama-cloud,testing,respx,fake,mock
Author: LlamaIndex
License-Expression: MIT
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Testing
Requires-Dist: httpx>=0.27
Requires-Dist: respx>=0.21
Requires-Dist: jsonref>=1.1
Requires-Dist: llama-cloud>=2.4.1,<3
Requires-Dist: pydantic>=2.0
Requires-Python: >=3.12
Description-Content-Type: text/markdown

# llama-cloud-fake

A [respx](https://lundberg.github.io/respx/)-backed fake of the [LlamaCloud](https://cloud.llamaindex.ai/) v2 HTTP API for tests.

Enter `FakeLlamaCloudServer` as a context manager and it intercepts outbound calls to `api.cloud.llamaindex.ai`, serving deterministic canned responses for the namespaces your workflow actually exercises (`files`, `extract`, `parse`, `pipelines`, `classify`, `agent_data`, `configurations`, `sheets`, `split`). The real `llama_cloud` client drives the fake unchanged — point it at the fake by env var and run your workflow end-to-end without hitting the real API.

## Install

```bash
pip install llama-cloud-fake
```

Test-time dependency — add it to your dev group (e.g. `[dependency-groups].dev` in `pyproject.toml`).

## Quick start

```python
import pytest
from llama_cloud import AsyncLlamaCloud
from llama_cloud_fake import FakeLlamaCloudServer
from pydantic import BaseModel

class Receipt(BaseModel):
    merchant: str
    total: float

@pytest.fixture(autouse=True)
def _fake_env(monkeypatch):
    monkeypatch.setenv("LLAMA_CLOUD_API_KEY", "unit-test-key")
    monkeypatch.setenv("LLAMA_CLOUD_BASE_URL", FakeLlamaCloudServer.DEFAULT_BASE_URL)

@pytest.mark.asyncio
async def test_extract(tmp_path):
    sample = tmp_path / "receipt.txt"
    sample.write_text("Merchant: Lunar Bistro\nTotal: 123.45")

    with FakeLlamaCloudServer():
        client = AsyncLlamaCloud(api_key="unit-test-key")
        file = await client.files.create(file=sample, purpose="extract")
        job = await client.extract.run(
            file_input=file.id,
            configuration={
                "data_schema": Receipt.model_json_schema(),
                "tier": "cost_effective",
            },
        )
        assert job.status == "COMPLETED"
        assert "merchant" in job.extract_result
```

Responses are derived deterministically from the request (file hash, schema hash), so repeated calls return the same payloads. Unmatched requests fail respx assertions.

## Overriding responses

Each namespace exposes `stub_*` methods to inject a canned result for specific requests. Later stubs win; they fall through to the deterministic default if no matcher fits.

```python
from llama_cloud_fake import (
    FakeLlamaCloudServer,
    FileMatcher,
    RequestMatcher,
    SchemaMatcher,
)

with FakeLlamaCloudServer() as fake:
    fake.extract.stub_run(
        RequestMatcher(
            file=FileMatcher(filename="receipt.txt"),
            schema=SchemaMatcher(model=Receipt),
        ),
        data={"merchant": "Lunar Bistro", "total": 123.45},
        status="COMPLETED",
    )
    # ...run your workflow; the extract.run call above now returns the stub.
```

`RequestMatcher` also accepts `agent_id`, `project_id`, `organization_id`, and a custom `predicate: Callable[[httpx.Request], bool]`.

## Preloading files

Skip the `client.files.create` round-trip in tests that just need a file id:

```python
with FakeLlamaCloudServer() as fake:
    file_id = fake.files.preload(path="tests/fixtures/invoice.pdf")
    # pass file_id straight into extract / parse / classify calls
```

## Source

The source for this package isn't hosted in a public repository. It's MIT-licensed and the wheel on PyPI ships the full source — unpack it and copy whatever you find useful.
