Skip to content
Closed
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
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -161,4 +161,6 @@ cython_debug/
#.idea/

src/spdx_python_model/bindings/
gen/*.py
gen/**/*
!gen/.keep

Empty file added gen/.keep
Empty file.
25 changes: 0 additions & 25 deletions gen/generate-bindings

This file was deleted.

4 changes: 3 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ license = "Apache-2.0"
[project.optional-dependencies]
dev = [
"pytest >= 7.4",
"requests == 2.32.5",
]

[project.urls]
Expand All @@ -35,6 +36,7 @@ requires = [
"hatchling",
"hatch-build-scripts",
"shacl2code == 0.0.25",
"requests == 2.32.5",
]
build-backend = "hatchling.build"

Expand All @@ -51,7 +53,7 @@ out_dir = "src/spdx_python_model/bindings"
work_dir = "gen"
clean_out_dir = true
commands = [
"./generate-bindings"
"../scripts/generate-bindings"
]
artifacts = [
"*.py"
Expand Down
108 changes: 108 additions & 0 deletions scripts/generate-bindings
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
#! /usr/bin/env python3
#
# SPDX-License-Identifier: Apache-2.0


import argparse
import sys
import requests
import subprocess
import re
import os
from pathlib import Path

SPDX_VERSIONS = ("3.0.1",)

THIS_DIR = Path(__file__).parent
OUT_DIR = THIS_DIR.parent / "gen"

INIT_FILE_PATH = OUT_DIR / "__init__.py"


def download_url(when, session, url, output):
if output.exists():
if when in ("if-missing", "never"):
print(f"File {output} already exists, skipping download.")
return
elif when == "never":
raise FileNotFoundError(
f"File {output} does not exist and download is disabled."
)

print(f"Downloading {url} to {output}...")
response = session.get(url)
response.raise_for_status()
with output.open("wb") as f:
f.write(response.content)


def main():
parser = argparse.ArgumentParser(
description="Generate SPDX Python bindings from RDF SHACL model"
)
parser.add_argument(
"--download",
choices=("always", "never", "if-missing"),
default=os.environ.get("SPDX_PYTHON_MODEL_DOWNLOAD", "if-missing"),
help="Controls how model files are downloaded. 'always' will force downloading files, 'never' will never download files, 'if-missing' will download the files if they do not already exits. Default is '%(default)s'",
)
args = parser.parse_args()

OUT_DIR.mkdir(parents=True, exist_ok=True)

with INIT_FILE_PATH.open("w") as init_file, requests.Session() as session:
init_file.write("# Import all versions\n")

for version in SPDX_VERSIONS:
modname = "v" + re.sub(r"[^a-zA-Z0-9_]", "_", version)
dl_dir = OUT_DIR / "download" / version
dl_dir.mkdir(parents=True, exist_ok=True)

context_url = f"https://spdx.org/rdf/{version}/spdx-context.jsonld"

download_url(
args.download,
session,
context_url,
dl_dir / "context.jsonld",
)
download_url(
args.download,
session,
f"https://spdx.org/rdf/{version}/spdx-model.ttl",
dl_dir / "model.ttl",
)
download_url(
args.download,
session,
f"https://spdx.org/rdf/{version}/spdx-json-serialize-annotations.ttl",
dl_dir / "annotations.ttl",
)
p = subprocess.run(
[
"shacl2code",
"generate",
"--input",
dl_dir / "model.ttl",
"--input",
dl_dir / "annotations.ttl",
"--context-url",
dl_dir / "context.jsonld",
context_url,
"--license",
"Apache-2.0",
"python",
"-o",
OUT_DIR / f"{modname}.py",
]
)
if p.returncode != 0:
return p.returncode

init_file.write(f"from . import {modname}\n")

return 0


if __name__ == "__main__":
sys.exit(main())