Metadata-Version: 2.4
Name: mini-oss-osdk
Version: 0.1.0a10
Summary: Async Python client and object facade for the ITEM Mini-OSS runtime
License-Expression: LicenseRef-Proprietary
Keywords: item,ontology,osdk,object-query
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.9
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: Typing :: Typed
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: httpx<1,>=0.27
Dynamic: license-file

# Mini-OSS Python OSDK

Async Python builder/runtime for canonical Object Query AST, Engine-backed SQL
explain, Tenant-scoped Operation polling and bounded Result Gateway access.
**`0.1.0a10`** adds native expression builders and explicit `type.Long` /
`type.String` constants, preserving existing string APIs and Alpha.8/9 queries.
Python 3.9+ remains supported. Install this exact pre-release version:

```bash
python -m pip install --upgrade "mini-oss-osdk==0.1.0a10"
```

**Engine compatibility:** new expressions require **Query `1.0.0-native.1`** in
Object Engine. The matching image is staging-verified; production has not been
promoted as part of this SDK release. Configure a compatible Engine/Result pair
explicitly. Older Engine/Tool Gateway/MCP validators reject new queries; there is
no silent downgrade. Ordinary queries retain Alpha.8, existing derived queries
retain Alpha.9, and Operation/Explain/Result/Catalog remain Alpha.8. Package a10
does not rename or freeze the entire runtime protocol.

Future capabilities will use separate package versions. This release contains no
`left_link`, row expansion, materialization or full205 replacement.
See [native expressions, types and limits](docs/native-completion.md).

This remains a pre-GA alpha package (not a `.dev` build). Explicit version pinning
is recommended; an unqualified pip upgrade may skip prereleases.

The proprietary public PyPI distribution is available as `mini-oss-osdk`; the
canonical import remains `mini_oss_osdk`.

## Build a qualified cross-Namespace query

Namespace API names are exact, case-sensitive PascalCase programming identifiers.
The first `pivot_to` argument is the Namespace that owns the Link, not the target
ObjectType Namespace. Both arguments are required; the old one-argument builder is
not supported.

```python
from mini_oss_osdk import Field, ObjectSet

query = (
    ObjectSet.base("FlightStage", "Flight")
    .where(Field("flightNumber").eq("SYN-001"))
    .pivot_to("Commerce", "orders")
    .fetch_page(select=("id", "status"), page_size=25)
)
```

Ordinary queries use the alpha.8 recursive AST and its schema URL:
`namespace` and `linkNamespace` contain API names, never Namespace short IDs or
display names. A Link owner may be a third Namespace, for example
`.pivot_to("Scheduling", "assignedFlights")` from `Fleet.Aircraft`.

## Build opt-in derived properties

**New in `0.1.0a9`:** public `0.1.0a8` does not provide this API. Derived queries
require an Engine supporting Query Alpha.9; an older Engine rejects them and the
SDK does not retry with a downgraded query. See [derived-property usage and
compatibility](docs/derived-properties.md). Installing this package does not
deploy services or upgrade Tool Gateway/MCP validators.

`with_properties()` is a lazy query-local projection. The callback receives an
expression-only root; it never receives a result row or a service client. CASE is
an ITEM query extension (not a claim about a matching Palantir Python API), and
its branch order and explicit `otherwise` are part of the query semantics:

```python
from mini_oss_osdk import Field, ObjectSet, case_when, literal

query = (
    ObjectSet.base("Sales", "Order")
    .with_properties(
        statusLabel=lambda root: case_when(
            (root.select_property("status").eq(1), literal("ready")),
            otherwise=literal("other"),
        ),
        lineCount=lambda root: root.pivot_to("Sales", "lines").count(),
    )
    .where(Field("statusLabel").eq("ready"))
    .fetch_page(select=("orderNo", "statusLabel", "lineCount"))
)
```

Existing a9-compatible `with_properties` constructions retain their Alpha.9 wire.
New native expressions explicitly choose native.1. No expression is evaluated in
Python, and scalar cardinality is never inferred from a local Catalog guess.

## Native expressions and type constants (a10)

```python
from mini_oss_osdk import ObjectSet, cast, coalesce, concat, literal, type

objects = ObjectSet.base("Sales", "Order").with_properties(
    customerName=lambda r: coalesce(
        r.pivot_to("Sales", "customer").select_property(
            "name", assert_zero_or_one=True,
        ),
        literal("Unknown"),
    ),
    exportVersion=lambda r: cast(literal("42"), type.Long),
)
query = objects.with_properties(
    label=lambda r: concat(
        r.derived_property("customerName"),
        r.derived_property("exportVersion").cast(type.String),
    ),
).fetch_page(select=("label",), page_size=25)
```

Names above are synthetic; use published Namespace/traversal/Property API names.
`assert_zero_or_one=True` is an **Athena runtime assertion**: no target gives NULL,
one target gives its value, and multiple distinct targets fail, even for equal
values. It does not pick a first/MIN/MAX value. `pivot_to` remains a deduplicated
ObjectSet traversal, not row expansion.

Native.1 also supports nested ordered CASE, Boolean/comparison/null expressions,
previous-batch aliases, controlled strict CAST and `query_timestamp()`. It does
not add arbitrary SQL/UDFs or broaden CAST implicitly. Related derived
backing-object paths remain unsupported. Long/Decimal preserve exact wire strings.

`from mini_oss_osdk import type` exposes nine canonical plain-string constants:
Boolean, Integer, Long, Float, Double, Decimal, String, Date and Timestamp.
For example `cast(expr, type.Long)` and `cast(expr, "long")` have identical wire.
Use `type as T` if Python's built-in `type()` is needed; wildcard imports do not
export the `type` namespace. Type constants do not widen the Engine allowlist.

## Explain a query without executing it

```python
from mini_oss_osdk import OSDKClient

async with OSDKClient(
    tenant_id="01jabcdefgh1",
    object_engine_url="https://object-engine.example.com",
    result_gateway_url="https://object-results.example.com",
    api_key=tenant_api_key,
) as client:
    explanation = await client.explain(query=query)
    print(explanation.athena_sql)
    print(explanation.manifest_id, explanation.manifest_content_hash)
```

`explain()` delegates binding, planning and SQL rendering to Object Engine. It
returns `ExplainResult` with alpha.8 manifest lineage, warnings, the logical plan
and generated `athena_sql`; it does not submit Athena, create an Operation or
access Result Gateway. The low-level equivalent is
`ObjectEngineClient.explain(...)`.

Generated SQL can contain source details or business literals. Do not record it in
logs, traces or telemetry.

## High-level object lookup

```python
from mini_oss_osdk import OSDKClient, case_when, literal

async with OSDKClient(
    tenant_id="01jabcdefgh1",
    object_engine_url="https://object-engine.example.com",
    result_gateway_url="https://object-results.example.com",
    api_key=tenant_api_key,
) as client:
    flight = await client.ontology.objects.object(
        "FlightStage", "Flight"
    ).get(
        "F001",
        select=("flightNumber",),
    )

    if flight is not None:
        print(flight.rid, flight.namespace_id, flight.namespace_api_name)
        print(flight.primary_key, flight["flightNumber"])
```

`get()` orchestrates qualified canonical lookup → Tenant-scoped Engine execute →
Operation wait → ResultRef lineage validation → bounded Result page. It never
reads Dataset/Redash/Athena metadata, creates SQL, guesses a Namespace from a RID,
or fills missing `$namespaceId`/`$namespace` fields from the lookup entry. Generic
runtime has no Catalog property list, so an omitted/empty `select` retains the
deployed server behavior of returning all published base properties (and all
currently visible query-local derived properties). Callers can list Property API
names explicitly when they need a bounded projection. A future generated ontology
package may provide that static list.

For query-local fields on one object, pass a `with_properties` mapping to `get()`:

```python
flight = await client.ontology.objects.object("FlightStage", "Flight").get(
    1,  # Example integer primary key; use the type declared by your model.
    select=("flightId", "origin", "originLabel"),
    with_properties={
        "originLabel": lambda root: case_when(
            (root.select_property("origin").eq("EWR"), literal("Newark")),
            otherwise=literal("Other or unknown"),
        ),
    },
)
```

The example assumes those ObjectType/Property API names exist in your active
model. `get()` handles execution, polling and Result validation; the derived
value is available as `flight["originLabel"]` when the object exists.

Both service endpoints are required. HTTPS is mandatory except loopback HTTP used
by tests. Configure exactly one public credential: `api_key` for the Tenant API
Key lane or `bearer_token` for the delegated Cognito ID Token lane. A local wait
timeout does not cancel the server Operation. Long and Decimal result values stay
as wire strings, and Result Gateway cursors remain opaque.

## Alpha.8 migration

Alpha.8 is a deliberately breaking runtime switch. Replace Namespace short-ID
arguments with Namespace API names and qualify every base and Link traversal;
move Engine/Operation/Result calls to Tenant routes; and do not reuse alpha.7
Operation, ResultRef, cursor or query wire. See
[`docs/migration-alpha8.md`](docs/migration-alpha8.md) for the mapping and
rejection behavior.

Generated ontology-specific classes are not implemented.

## Distribution verification

```bash
python -m unittest discover -s tests
python -m ruff check src tests
python -m build
python -m twine check dist/*
python scripts/verify_distribution.py dist
```

Branch and `main` pipelines only test and build. A `v<version>` tag is the sole
public PyPI upload authority, and the tag must exactly match wheel metadata before
upload. Installing this client does not deploy services or migrate saved queries.

## License

Proprietary. Copyright (c) 2026 ITEM. All rights reserved. See [`LICENSE`](LICENSE);
public package availability does not grant permission to use, modify, or
redistribute the software.

Timestamp derived literals follow existing Result Wire v1: offset-bearing RFC3339, at most six fractional digits, UTC output. Higher precision is rejected, never silently truncated.
