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
13 changes: 12 additions & 1 deletion SETUP.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,17 @@ The validation tooling is expected to check things such as:
- SHACL validation, where applicable
- Cross-version consistency for published contexts and schemas

To generate a field reference for each schema version:
```bash
uv run python tools/render-docs.py
```

The generated `spec/<version>/generated-field-reference.md` contains a separate
table for each `*.schema.json` file, including `ProvenanceRecord` and
`TrainingProvenanceRecord`. Fields required by a schema's `then` or `else`
branch are marked conditional; see their descriptions for the condition.
These generated files are ignored by Git and should not be committed.

## Run Maven checks

The Maven build packages the specification resources for downstream use.
Expand Down Expand Up @@ -193,4 +204,4 @@ Development discussion happens on the Sourcelume developer mailing list:
dev@sourcelume.apache.org
```

The project also uses the ASF Slack `#sourcelume` channel.
The project also uses the ASF Slack `#sourcelume` channel.
54 changes: 35 additions & 19 deletions tools/render-docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
"""Render human-readable docs from the JSON Schema.
"""Render human-readable docs from the JSON Schemas.

This is a starting skeleton. It currently generates a single Markdown
field-reference table per published schema version, from
`schema/<version>/sourcelume.schema.json`. It does not yet render SHACL
shapes, cross-link to the prose spec, or produce HTML output — see
SETUP.md for the intended scope.
Generates a Markdown field reference per schema version, with a table
for each `schema/<version>/*.schema.json` record schema. This includes
both ProvenanceRecord and TrainingProvenanceRecord. It does not render
SHACL shapes, cross-link to the prose spec, or produce HTML output.

Usage:
uv run python tools/render-docs.py
Expand All @@ -29,7 +28,6 @@
each published schema version. Generated files are not intended to be
committed until the project decides how generated output should be
handled (see the "Notes for contributors" section of SETUP.md).
Note: gitIgnores spec/*/generated-field-reference.md entry exists.
"""

from __future__ import annotations
Expand Down Expand Up @@ -57,20 +55,27 @@ def find_version_dirs(base: Path) -> list[Path]:
def render_field_table(schema: dict) -> str:
properties = schema.get("properties", {})
required = set(schema.get("required", []))
conditional_required = set()
for keyword in ("then", "else"):
branch = schema.get(keyword)
if isinstance(branch, dict):
conditional_required.update(branch.get("required", []))

lines = [
f"# {schema.get('title', 'Schema Reference')}",
"",
"> Generated from the JSON Schema. Do not edit by hand — edit the",
"> schema and re-run `tools/render-docs.py` instead.",
f"## {schema.get('title', 'Schema Reference')}",
"",
"| Field | Type | Required | Description |",
"|-------|------|----------|-------------|",
]

for field_name, field_def in properties.items():
field_type = field_def.get("type", field_def.get("format", "—"))
is_required = "Yes" if field_name in required else "No"
if field_name in required:
is_required = "Yes"
elif field_name in conditional_required:
is_required = "Conditional (see description)"
else:
is_required = "No"
description = field_def.get("description", "").replace("\n", " ")
lines.append(f"| `{field_name}` | {field_type} | {is_required} | {description} |")

Expand All @@ -79,18 +84,29 @@ def render_field_table(schema: dict) -> str:

# Render generated documentation for one schema version and return the output path.
def render_version(version_dir: Path) -> Path | None:
# Only the ProvenanceRecord schema is rendered so far, not sourcelume-training.schema.json.
schema_file = version_dir / "sourcelume.schema.json"
if not schema_file.exists():
schema_files = sorted(
version_dir.glob("*.schema.json"),
key=lambda path: (path.name != "sourcelume.schema.json", path.name),
)
if not schema_files:
return None

schema = json.loads(schema_file.read_text())
doc = render_field_table(schema)
sections = [
f"# Apache Sourcelume Field Reference ({version_dir.name})",
"",
"> Generated from the JSON Schemas. Do not edit by hand — edit the",
"> schemas and re-run `tools/render-docs.py` instead.",
"",
]
for schema_file in schema_files:
schema = json.loads(schema_file.read_text(encoding="utf-8"))
sections.append(render_field_table(schema))
doc = "\n".join(sections)

output_dir = SPEC_DIR / version_dir.name
output_dir.mkdir(parents=True, exist_ok=True)
output_path = output_dir / "generated-field-reference.md"
output_path.write_text(doc)
output_path.write_text(doc, encoding="utf-8")
return output_path


Expand All @@ -107,7 +123,7 @@ def main() -> int:
if output_path:
print(f"Wrote {output_path}")
else:
print(f"Skipped {version_dir}: no sourcelume.schema.json file found.")
print(f"Skipped {version_dir}: no *.schema.json files found.")

return 0

Expand Down
Loading