Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 24 additions & 3 deletions docs-gen/content/docs/tools/units-cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ chapter: false

The S2DM Units CLI provides integration with the [QUDT (Quantities, Units, Dimensions and Types)](https://qudt.org/) reference model to generate standardized GraphQL unit enums. This replaces static unit definitions with a dynamic system that synchronizes directly from the authoritative QUDT repository.

## How QUDT Maps to GraphQL

The `sync` command reads a specific released version of QUDT and maps it onto GraphQL SDL enum structures:

- Each QUDT **quantity kind** (e.g. `quantitykind:Velocity`) becomes one GraphQL **enum type** (e.g. `VelocityUnit`).
- Each QUDT **unit** belonging to that quantity kind (e.g. `unit:M-PER-SEC`) becomes one **enum value** of that type (e.g. `M_PER_SEC`).

Elements that are marked **deprecated in the QUDT release** — whether the unit itself or its quantity kind — are intentionally **not mapped and are ignored**. They do not appear in generated enums in any form (not even as `@deprecated` values); only QUDT's current, non-deprecated vocabulary is represented.

## Features

- **Dynamic Unit Synchronization**: Fetch unit definitions from QUDT's GitHub repository
Expand Down Expand Up @@ -45,12 +54,13 @@ s2dm units sync --dry-run
```

**Options:**
- `--version` (optional): QUDT version string. Defaults to latest release if not specified
- `--version` (optional): QUDT release tag, including the leading `v` (e.g. `v3.1.6`). This must match a git tag in the [qudt-public-repo](https://github.com/qudt/qudt-public-repo/tags) exactly. Defaults to the latest release tag if not specified
- `--dry-run` (optional): Show how many enum files would be generated without creating them

**Output:**
- Creates `<QuantityKind>Unit.graphql` files in `~/.s2dm/units/qudt` (e.g., `LengthUnit.graphql`)
- Generates `README.md` with version and attribution information
- Generates `CHANGELOG.md` listing quantity kinds and units that QUDT marks as deprecated in that release (and are therefore intentionally excluded from the generated enums)
- Reports number of enum files generated

### `s2dm units check-version`
Expand All @@ -71,7 +81,7 @@ s2dm units check-version
Each generated enum follows this structure:

```graphql
# Generated from QUDT units catalog version 3.1.5
# Generated by S2DM from the QUDT unit vocabulary. See README.md in this directory for the QUDT version used.
# Source data: QUDT Public Repository (https://github.com/qudt/qudt-public-repo)
# © QUDT.org — Licensed under Creative Commons Attribution 4.0 International (CC BY 4.0)
# License: https://creativecommons.org/licenses/by/4.0/
Expand All @@ -89,6 +99,11 @@ enum LengthUnit @reference(uri: "http://qudt.org/vocab/quantitykind/Length") {
}
```

{{< callout context="note" >}}
The QUDT catalog version is not embedded in each enum file. It is recorded once in the directory's `README.md` so that re-syncing an unchanged catalog doesn't touch every file, keeping Git diffs focused on actual content changes.
{{< /callout >}}


**Key Elements:**
- **Enum name**: `<QuantityKind>Unit` in PascalCase
- **@reference on enum**: Links to QUDT quantity kind IRI
Expand All @@ -103,6 +118,7 @@ QUDT units are stored in the `S2DM_HOME` directory:
```
~/.s2dm/units/qudt/ # QUDT units (generated, read-only)
├── README.md # Version and attribution
├── CHANGELOG.md # Deprecated quantity kinds/units excluded from this release
├── LengthUnit.graphql # Length units
├── VelocityUnit.graphql # Velocity units
└── ... (500+ more unit enums)
Expand Down Expand Up @@ -159,9 +175,14 @@ S2DM uses QUDT URI segments instead of labels for enum values because:

### Deduplication
- Uses `DISTINCT` in SPARQL queries to eliminate exact duplicates
- Filters out deprecated units to prevent symbol conflicts
- Filters out units marked `qudt:deprecated true` to prevent symbol conflicts (e.g. `unit:Standard`, replaced by `unit:STANDARD`)
- Filters out units whose quantity kind is itself marked `qudt:deprecated true` (e.g. `quantitykind:Conductivity`, replaced by `quantitykind:ElectricConductivity`), so units aren't grouped under a stale quantity kind label
- Prefers entries with UCUM codes when duplicates remain

{{< callout context="note" >}}
QUDT's own git tags are prefixed with `v` (e.g. `v3.5.2`), not bare version numbers. Always pass `--version` with the `v` prefix, matching the tag names at [qudt-public-repo/tags](https://github.com/qudt/qudt-public-repo/tags).
{{< /callout >}}

### Error Handling
- **Network Issues**: Graceful failure with informative error messages
- **Invalid Units**: Units that cannot generate valid symbols are skipped
Expand Down
11 changes: 9 additions & 2 deletions src/s2dm/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -650,7 +650,8 @@ def units() -> None:
type=str,
required=False,
help=(
"QUDT version tag (e.g., 3.1.6). Defaults to the latest tag, falls back to 'main' when tags are unavailable."
"QUDT version tag, including the leading 'v' (e.g., v3.1.6), matching a tag in the "
"qudt-public-repo. Defaults to the latest tag, falls back to 'main' when tags are unavailable."
),
)
@units_directory_option
Expand All @@ -660,7 +661,13 @@ def units() -> None:
help="Show what would be generated without actually writing files",
)
def units_sync(version: str | None, directory: Path, dry_run: bool) -> None:
"""Fetch QUDT quantity kinds and generate GraphQL enums under the specified directory.
"""Fetch a specific QUDT release and generate GraphQL enums under the specified directory.

Reads the given QUDT release and maps it onto GraphQL SDL enum structures: each
enum type corresponds to a specific quantity kind (e.g. `VelocityUnit`), and each
enum value is a possible unit for that quantity kind (e.g. `M_PER_SEC`). Elements
that are deprecated in the QUDT release (units or their quantity kind) are
intentionally not mapped and are ignored.

Args:
version: QUDT version tag. Defaults to the latest tag.
Expand Down
Loading
Loading