Metadata-Version: 2.4
Name: nomox-semantics
Version: 0.1.2
Summary: Semantic data model for data catalog.
Author-email: nomox <admin@get-nomox.com>
License-Expression: MIT
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Requires-Python: >=3.11
Requires-Dist: pydantic<3,>=2.7
Provides-Extra: dev
Requires-Dist: mypy>=1; extra == 'dev'
Requires-Dist: pytest-cov>=4; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: ruff>=0.1; extra == 'dev'
Description-Content-Type: text/markdown

# Nomox Semantic Model

The shared knowledge contract between every Nomox service. Describes what data exists (physical layer) and what it means (ontology), and ties the two together so an agent can move from a natural-language concept all the way down to a specific column in a specific table.

## Installation

The repo is private, so all installs need a GitHub Personal Access Token (PAT) with `repo` scope. Export it as `GITHUB_TOKEN` before installing.

### Ad-hoc install

```bash
pip install git+https://${GITHUB_TOKEN}@github.com/Nomox-ai/semantics-model.git
```

Pin to a tag for reproducible installs:

```bash
pip install git+https://${GITHUB_TOKEN}@github.com/Nomox-ai/semantics-model.git@v0.1.1
```

### Adding to `requirements.txt`

Add the following line so the package is pulled automatically on `pip install -r requirements.txt`:

```text
nomox-semantics @ git+https://${GITHUB_TOKEN}@github.com/Nomox-ai/semantics-model.git@main
```

`@main` tracks the latest commit on `main`. Replace it with a tag (e.g. `@v0.1.1`) or a commit SHA if you ever need to pin to a specific version.

> **Heads up:** pip caches git installs by URL, so a plain `pip install -r requirements.txt` will say "Requirement already satisfied" and skip the fetch even when `main` has moved. To force the latest:
>
> ```bash
> pip install --upgrade --force-reinstall --no-deps nomox-semantics
> # or, to refresh everything in the file
> pip install -r requirements.txt --upgrade --force-reinstall
> ```

Then before installing:

```bash
# bash / zsh
export GITHUB_TOKEN=github_pat_...
pip install -r requirements.txt
```

> **Never commit the raw PAT** - keep it in an env var, a `.env` file that is gitignored, or your CI's secret store. If a token ever lands in source, revoke it immediately at github.com/settings/tokens.

### `pyproject.toml` equivalent

```toml
[project]
dependencies = [
    "nomox-semantics @ git+https://${GITHUB_TOKEN}@github.com/Nomox-ai/semantics-model.git@main",
]
```

## Importing

The distribution is named `nomox-semantics`, but the Python import name is `nomox_semantics` (underscore). Every public symbol is re-exported from the top-level package, so always import from `nomox_semantics` directly - not from submodules:

```python
from nomox_semantics import (
    # Physical layer
    DataSource, SourceType, SyncStatus,
    Table, Column, ColumnDataType, ForeignKeyRef,
    # Semantic layer
    BusinessDomain, Entity, EntityAttribute, EntityTableMapping,
    AttributeRole, SemanticType, Relationship, RelationshipCardinality,
    # Metrics
    Metric, MetricType, MetricFormat, MetricFilter, MetricColumnRef,
    # Glossary
    GlossaryTerm,
    # Queries
    SavedQuery, QueryStatus, QueryTrace, QueryResult, Dashboard,
    # Root
    SemanticCatalog,
)
```

## Quickstart

```python
from uuid import uuid4
from nomox_semantics import (
    SemanticCatalog, DataSource, SourceType, Table, Column, ColumnDataType,
    Entity, EntityAttribute, EntityTableMapping, AttributeRole, SemanticType,
)

# 1. Physical layer — what exists in the database
src   = DataSource(slug="prod", name="Prod", source_type=SourceType.POSTGRES)
users = Table(source_id=src.id, schema_name="public", table_name="users")
ltv   = Column(table_id=users.id, source_id=src.id, column_name="ltv_cents",
               ordinal_position=1, data_type=ColumnDataType.BIGINT, raw_data_type="bigint")

# 2. Semantic layer — what the data means in business terms
customer = Entity(
    slug="customer", name="Customer", plural_name="Customers",
    aliases=["user", "account holder"],                      # for natural-language matching
    table_mappings=[EntityTableMapping(table_id=users.id, source_id=src.id)],  # entity -> table
)

# An EntityAttribute binds a business field to a physical column
ltv_attr = EntityAttribute(
    entity_id=customer.id, column_id=ltv.id, source_id=src.id,
    name="lifetime_value", display_name="Lifetime Value",
    role=AttributeRole.MEASURE, default_aggregation="SUM",   # tells the query engine it's aggregatable
    semantic_type=SemanticType.CURRENCY, unit="EUR",         # values are EUR, not raw cents
)

# 3. Assemble the catalog — the root object every Nomox service consumes
catalog = SemanticCatalog(organisation_id=uuid4(), name="Acme")
catalog.sources[src.id] = src
catalog.tables[users.id] = users
catalog.columns[ltv.id] = ltv
catalog.entities[customer.id] = customer
catalog.attributes[ltv_attr.id] = ltv_attr
```

## Documentation

See [docs/](docs/) for the full design documentation.
