Metadata-Version: 2.4
Name: commonmeta-schema
Version: 1.0rc4
Summary: Commonmeta JSON Schemas and conformance fixtures
Project-URL: Homepage, https://github.com/front-matter/commonmeta-schema
Project-URL: Repository, https://github.com/front-matter/commonmeta-schema
Project-URL: Issues, https://github.com/front-matter/commonmeta-schema/issues
Author: Front Matter
License-Expression: MIT
License-File: LICENSE
Keywords: commonmeta,fixtures,json-schema,metadata,schema
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
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: Programming Language :: Python :: 3.14
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: Text Processing
Requires-Python: >=3.9
Description-Content-Type: text/markdown

# commonmeta-schema

Language-neutral JSON Schema definitions and conformance fixtures for
[Commonmeta](https://commonmeta.org), the scholarly metadata interchange format.

This repository is the shared source of truth consumed by the following Commonmeta
implementations:

- [commonmeta-rs](https://github.com/front-matter/commonmeta-rs) (Rust)
- [commonmeta-py](https://github.com/front-matter/commonmeta-py) (Python)

Keeping the schema and the golden fixtures in one place lets every
implementation validate against the same contract and run the same
cross-format conformance tests.

## Layout

```
schemas/
  commonmeta_v1.0rc3.json      # the Commonmeta JSON Schema (current: v1.0rc3)
fixtures/
  commonmeta/                  # canonical Commonmeta records (round-trip + expected output)
  <format>/                    # input fixtures in a given source format
  <format>_out/                # expected writer output (Commonmeta -> format)
  <format>_commonmeta/         # expected reader output for non-JSON inputs
```

## Schema versions

Schemas are versioned by filename. The current version is
`commonmeta_v1.0rc3.json`; new versions are added alongside it rather than
replacing existing files, so implementations can pin a version. The
`schema_version` field of a Commonmeta record is the URL
`https://commonmeta.org/commonmeta_v1.0rc3.json`.

## Fixture conventions

The conformance harness in each implementation follows these naming rules
(a missing pair is skipped, so partial coverage is fine):

| Test kind            | Input                                  | Expected                                    |
|----------------------|----------------------------------------|---------------------------------------------|
| Round-trip           | `fixtures/commonmeta/<name>.json`      | itself (re-serialized, semantically equal)  |
| Reader (JSON input)  | `fixtures/<format>/<name>.json`        | `fixtures/commonmeta/<name>.json`           |
| Reader (text input)  | `fixtures/<format>/<name>.<ext>`       | `fixtures/<format>_commonmeta/<name>.json`  |
| Writer               | `fixtures/commonmeta/<name>.json`      | `fixtures/<format>_out/<name>.<ext>`        |

Formats currently covered: `crossref`, `crossref_xml`, `datacite`,
`datacite_xml`, `schemaorg`, `csl`, `bibtex`, `cff`, `ris`, `jsonfeed`,
`inveniordm`, `codemeta`.

### Semantic comparison

Fixtures are compared as parsed JSON trees, not as strings, using an
omitempty-aware and numeric-aware diff: key order and whitespace are
irrelevant, an absent field equals an empty/zero/null value, and `52`
equals `52.0`. This keeps hand-authored fixtures robust across
implementations.

## Using this repository

Each implementation vendors (copies) the schema and fixtures it needs from
here. Update the canonical files in this repository first, then sync them
into `commonmeta-rs` and `commonmeta-py`.

## Packaging and publishing

This repository can be published as both:

- a Python package on PyPI (`commonmeta-schema`)
- a Rust crate on crates.io (`commonmeta-schema`)

Publishing is done explicitly via CLI (no automated release pipeline in this repo).

Package versions follow the schema version:

- PyPI uses PEP 440 form: `1.0rc3`
- crates.io uses SemVer form: `1.0.0-rc.2`

To keep both versions in sync, run:

```bash
python scripts/sync_versions.py
```

To verify sync in CI/local checks without changing files:

```bash
python scripts/sync_versions.py --check
```

Before publishing the crate, sync canonical assets from the repo root into the
Rust crate directory:

```bash
mkdir -p rust/fixtures rust/schemas
rsync -a --delete --exclude '.DS_Store' fixtures/ rust/fixtures/
rsync -a --delete schemas/ rust/schemas/
```

Recommended pre-release checks:

```bash
python scripts/sync_versions.py --check
uv build
cargo test --manifest-path rust/Cargo.toml
cargo package --manifest-path rust/Cargo.toml
```

### Python (PyPI) via `uv publish`

1. Ensure you are authenticated for PyPI (recommended: trusted publisher or API token).
2. Build distribution artifacts:

  ```bash
  uv build
  ```

3. Optionally validate the build metadata:

  ```bash
  uvx twine check dist/*
  ```

4. Publish to PyPI:

  ```bash
  uv publish
  ```

### Rust (crates.io) via `cargo publish`

1. Log in once with a crates.io token:

  ```bash
  cargo login
  ```

2. Validate package contents:

  ```bash
  cargo package --manifest-path rust/Cargo.toml --allow-dirty
  ```

3. Publish:

  ```bash
  cargo publish --manifest-path rust/Cargo.toml
  ```

### Recommended release order

1. Publish `1.0rc3` to PyPI with `uv publish`.
2. Publish `1.0.0-rc3` to crates.io with `cargo publish`.
3. Create a git tag `v1.0rc3` after both uploads succeed.

### Copy-paste release run

Run this from the repository root:

```bash
set -euo pipefail

# 1) Ensure Rust crate version matches Python version
python scripts/sync_versions.py --check

# 2) Sync canonical assets into the Rust crate
mkdir -p rust/fixtures rust/schemas
rsync -a --delete --exclude '.DS_Store' fixtures/ rust/fixtures/
rsync -a --delete schemas/ rust/schemas/

# 3) Validate both package builds
uv build
cargo test --manifest-path rust/Cargo.toml
cargo package --manifest-path rust/Cargo.toml

# 4) Publish Python package
uv publish

# 5) Publish Rust crate
cargo publish --manifest-path rust/Cargo.toml

# 6) Tag release (replace with the release version)
git tag v1.0rc3
git push origin v1.0rc3
```

## License

[MIT](LICENSE) © 2026 Front Matter
