Metadata-Version: 2.4
Name: fms-odata-spec
Version: 2.0.1
Summary: Python types and spec definitions for the FileMaker Server OData API, mirroring @fms-odata/spec-ts.
Project-URL: Homepage, https://github.com/fsans/fms-odata-spec
Project-URL: Repository, https://github.com/fsans/fms-odata-spec
Project-URL: Issues, https://github.com/fsans/fms-odata-spec/issues
Author-email: Francesc Sans <tecnic@ntwk.es>
License-Expression: MIT
License-File: LICENSE
Keywords: api,claris,filemaker,fms,odata,spec,types
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
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: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Provides-Extra: dev
Requires-Dist: build>=1.0; extra == 'dev'
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: twine>=4.0; extra == 'dev'
Description-Content-Type: text/markdown

# fms-odata-spec (Python)

Python types and spec definitions for the **Claris FileMaker Server OData API**.

This is the Python companion to [`@fms-odata/spec-ts`](https://www.npmjs.com/package/@fms-odata/spec-ts).
Both packages mirror the same specification (defined in the
[fms-odata-spec](https://github.com/fsans/fms-odata-spec) repository) and are
published independently — pick the one matching your runtime. The Python
package has **no runtime dependency** on the TypeScript package (or vice versa).

## What's in the box

- Version identifiers and a feature-flag matrix for Claris FileMaker 2023,
  2024, 2025, and 2026 (`versions`).
- Authentication helpers and config types for Basic and OAuth Bearer auth
  (`auth`).
- Endpoint descriptors and version-scoped lookup helpers (`endpoints`).
- OData query-option types and literal-formatting helpers (`query_options`).
- `$metadata` parsing helpers and EDM model types (`metadata`).
- Script execution types and response parsing (`scripts`).
- Container field upload/download helpers and MIME sniffing (`containers`).
- `$batch` request and result types (`batch`).
- Webhook management types (`webhooks`).
- Schema modification (DDL) types and field-type parsing (`schema`).
- Error class hierarchy for OData responses (`errors`).

All models are stdlib `dataclasses` (no pydantic / no validation framework).
Discriminated unions from the TS spec are modeled with `typing.Literal`
discriminator fields. The package ships a `py.typed` marker (PEP 561) so
static type checkers pick up the annotations.

## Install

```bash
pip install fms-odata-spec
```

For local development from this repository:

```bash
cd packages/fms-odata-spec-py
python -m venv .venv
source .venv/bin/activate        # Windows: .venv\Scripts\activate
pip install -e ".[dev]"
pytest
```

## Usage

```python
from fms_odata_spec import (
    FM_VERSION_MATRIX,
    has_feature,
    basic_auth,
    parse_server_version,
    format_literal,
    FMODataError,
)

# Check feature availability per FileMaker Server version.
# Feature names are snake_case (matching the FMFeatureFlags dataclass fields).
assert has_feature("26", "scripts_by_fmsid") is True
assert has_feature("20", "webhooks") is False

# Build a Basic auth header value.
hdr = basic_auth("admin", "secret")  # -> "Basic YWRtaW46c2VjcmV0"

# Detect the server version from a $metadata XML payload.
ver = parse_server_version(
    '<Annotation Term="Org.OData.Core.V1.ProductVersion" String="26.0.1.500"/>'
)
assert ver.major == 26

# Format an OData $filter literal.
assert format_literal("O'Brien") == "'O''Brien'"
assert format_literal(42) == "42"
```

## Versioning

This package is versioned independently of `@fms-odata/spec-ts`. It is published
to [PyPI](https://pypi.org/project/fms-odata-spec/) as `fms-odata-spec`.

## Roadmap

> **IMPORTANT — these items must be addressed before publishing to PyPI.**
> See `AGENTS.md` at the repository root for the same list with more detail.

- [ ] **PyPI publishing workflow** — `.github/workflows/py-publish.yml` exists
      and triggers on `py-v*` tag pushes. Remaining: create a PyPI API token,
      add it as the `PYPI_API_TOKEN` repo secret, optionally create a `pypi`
      environment for protection rules, then re-push the tag to trigger. See
      `AGENTS.md` for full steps.
- [x] **LICENSE bundling** — DONE. `LICENSE` is copied into this directory
      and declared as a wheel artifact + sdist include in `pyproject.toml`;
      verified it ships in both the wheel and sdist.
- [ ] **CHANGELOG** — add `CHANGELOG.md` with the 2.0.0 entry.
- [ ] **`ODataEntity[T]` ergonomics** — confirm the wrapping-dataclass shape
      (`envelope.entity.field`) is acceptable before the first release; it is a
      breaking change to alter afterwards.
- [ ] **CI matrix** — add Python 3.14 to `py-ci.yml` once
      `actions/setup-python` supports it.
- [ ] **Async token-refresh** — document that `FMOAuthAuthConfig.on_unauthorized`
      is typed but not invoked by this package (downstream must wire it).
- [ ] **Shared schema source** — revisit whether both language packages should
      be generated from a single JSON Schema / CSDL source before they drift.

## License

MIT — see the repository [LICENSE](../../LICENSE).
