2021-11-01 07:21:50 +01:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
#
|
2021-11-17 16:16:22 +01:00
|
|
|
# generate-hugo-content.py v0.0.1
|
2021-11-01 07:21:50 +01:00
|
|
|
#
|
|
|
|
# SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
|
|
|
|
import argparse
|
|
|
|
import os
|
|
|
|
import re
|
|
|
|
import sys
|
|
|
|
from shutil import rmtree
|
2021-12-13 14:03:20 +01:00
|
|
|
from shutil import copyfile
|
2021-11-01 07:21:50 +01:00
|
|
|
|
|
|
|
import pandas as pd
|
|
|
|
|
|
|
|
|
|
|
|
def parseSchema(schema_df):
|
|
|
|
# Iterate over all rows (the "index, row" syntax allows us to access column
|
|
|
|
# headings in each row, which isn't possible if we just do row).
|
|
|
|
for index, row in schema_df.iterrows():
|
2021-12-13 12:16:39 +01:00
|
|
|
element_name = row["element name"]
|
2021-11-01 07:21:50 +01:00
|
|
|
|
|
|
|
# Make sure element name is URL friendly because we need to use it in
|
|
|
|
# the file system and in the URL.
|
|
|
|
#
|
|
|
|
# Replace two or more whitespaces with one
|
|
|
|
element_name = re.sub(r"\s{2,}", " ", element_name)
|
|
|
|
# Replace unnecessary stuff in some element names (I should tell Peter
|
|
|
|
# that these belong in the description)
|
|
|
|
element_name = re.sub(r"\s?\(\w+\)", "", element_name)
|
|
|
|
# Remove commas and question marks
|
|
|
|
element_name = re.sub(r"[,?]", "", element_name)
|
|
|
|
# Replace ": " with a dash (as in "Evaluation: ")
|
|
|
|
element_name = element_name.replace(": ", "-")
|
|
|
|
# Replace " / " with a dash (as in "biome / zone")
|
|
|
|
element_name = element_name.replace(" / ", "-")
|
|
|
|
# Replace whitespace, colons, and slashes with dashes
|
|
|
|
element_name = re.sub(r"[\s/]", "-", element_name)
|
|
|
|
# Lower case it
|
|
|
|
element_name = element_name.lower()
|
|
|
|
# Strip just in case
|
|
|
|
element_name = element_name.strip()
|
|
|
|
|
|
|
|
# For example Certifying Body, FSC audit, Certificate, etc
|
2021-11-26 10:58:06 +01:00
|
|
|
cluster = row["idss element cluster"].capitalize()
|
2021-11-01 07:21:50 +01:00
|
|
|
|
2021-12-13 12:20:09 +01:00
|
|
|
# For example Assurance, Certification, Core, Impact, etc
|
|
|
|
module = row["idss schema module"].capitalize()
|
|
|
|
|
2021-12-13 12:31:29 +01:00
|
|
|
# Generate a "safe" version of the element name for use in URLs and
|
|
|
|
# files by combining the cluster and the element name. This could
|
|
|
|
# change in the future.
|
2021-11-26 10:58:06 +01:00
|
|
|
element_name_safe = cluster.replace(" ", "-").lower() + "-" + element_name
|
|
|
|
|
|
|
|
print(f"element name: {element_name_safe}")
|
2021-11-01 07:21:50 +01:00
|
|
|
|
|
|
|
# Create output directory for term using the URL-safe version
|
|
|
|
outputDirectory = f"site/content/terms/{element_name_safe}"
|
|
|
|
os.makedirs(outputDirectory, mode=0o755, exist_ok=True)
|
|
|
|
|
|
|
|
if args.debug:
|
|
|
|
print(f"Created terms directory: site/content/terms/{element_name_safe}")
|
|
|
|
|
|
|
|
# Take the element description as is, but remove quotes
|
|
|
|
element_description = row["element description"].replace("'", "")
|
|
|
|
|
|
|
|
# Take the element guidance as is
|
|
|
|
if row["element guidance"]:
|
|
|
|
comment = row["element guidance"]
|
|
|
|
else:
|
|
|
|
comment = False
|
|
|
|
|
|
|
|
example = row["element link for more information"]
|
|
|
|
|
|
|
|
# How to use these in the HTML, slightly overlapping?
|
|
|
|
cardinality = row["element options"].capitalize()
|
|
|
|
prop_type = row["element type"].capitalize()
|
|
|
|
|
|
|
|
if row["element controlled values or terms"]:
|
|
|
|
controlled_vocab = True
|
|
|
|
|
2021-12-13 14:03:20 +01:00
|
|
|
controlled_vocabulary_src=f"data/controlled-vocabularies/{element_name_safe}.txt"
|
|
|
|
controlled_vocabulary_dst=f"site/content/terms/{element_name_safe}/vocabulary.txt"
|
|
|
|
|
|
|
|
copyfile(controlled_vocabulary_src, controlled_vocabulary_dst)
|
|
|
|
|
|
|
|
if args.debug:
|
|
|
|
print(f"Copied controlled vocabulary: {element_name_safe}")
|
2021-11-01 07:21:50 +01:00
|
|
|
else:
|
|
|
|
controlled_vocab = False
|
|
|
|
|
|
|
|
if row["mandatory?"] == "MANDATORY":
|
|
|
|
required = True
|
|
|
|
else:
|
|
|
|
required = False
|
|
|
|
|
|
|
|
if row["dspace field name"] is not None and row["dspace field name"] != "":
|
|
|
|
dspace_field_name = row["dspace field name"]
|
|
|
|
else:
|
|
|
|
dspace_field_name = False
|
|
|
|
|
|
|
|
# Combine element type and options into a "policy" of sorts and convert
|
|
|
|
# them to sentence case because they are ALL CAPS in the Excel. We don't
|
|
|
|
# need to do any checks because these fields should always exist.
|
|
|
|
policy = f'{row["element type"].capitalize()}. {row["element options"].capitalize()}.'
|
|
|
|
|
|
|
|
if args.debug:
|
|
|
|
print(f"Processed: {row['element name']}")
|
|
|
|
|
|
|
|
# Create an empty list with lines we'll write to the term's index.md in
|
|
|
|
# TOML frontmatter format for Hugo.
|
|
|
|
indexLines = []
|
|
|
|
indexLines.append("---\n")
|
2021-11-26 10:58:06 +01:00
|
|
|
# Use the full title for now (even though it's ugly). Better to fix the
|
|
|
|
# schema spreadsheet than try to process the title here.
|
2021-11-01 07:21:50 +01:00
|
|
|
indexLines.append("title: '" + row["element name"] + "'\n")
|
|
|
|
if dspace_field_name:
|
|
|
|
indexLines.append(f"field: '{dspace_field_name}'\n")
|
|
|
|
indexLines.append(f"slug: '{element_name_safe}'\n")
|
|
|
|
if element_description:
|
|
|
|
indexLines.append(f"description: '{element_description}'\n")
|
|
|
|
if comment:
|
|
|
|
indexLines.append(f"comment: '{comment}'\n")
|
|
|
|
indexLines.append(f"required: {required}\n")
|
|
|
|
if controlled_vocab:
|
2021-12-13 14:03:20 +01:00
|
|
|
indexLines.append(f"vocabulary: 'vocabulary.txt'\n")
|
2021-11-11 14:05:18 +01:00
|
|
|
if module:
|
|
|
|
indexLines.append(f"module: '{module}'\n")
|
2021-11-26 10:58:06 +01:00
|
|
|
if cluster:
|
|
|
|
indexLines.append(f"cluster: '{cluster}'\n")
|
2021-11-01 07:21:50 +01:00
|
|
|
indexLines.append(f"policy: '{policy}'\n")
|
|
|
|
## TODO: use some real date...?
|
|
|
|
# indexLines.append(f"date: '2019-05-04T00:00:00+00:00'\n")
|
|
|
|
indexLines.append("---")
|
|
|
|
|
|
|
|
with open(f"site/content/terms/{element_name_safe}/index.md", "w") as f:
|
|
|
|
f.writelines(indexLines)
|
|
|
|
|
|
|
|
|
|
|
|
parser = argparse.ArgumentParser(
|
2021-12-20 11:04:11 +01:00
|
|
|
description="Parse an ISEAL schema CSV file to produce documentation about metadata requirements."
|
2021-11-01 07:21:50 +01:00
|
|
|
)
|
|
|
|
parser.add_argument(
|
|
|
|
"--clean",
|
|
|
|
help="Clean output directory before building.",
|
|
|
|
action="store_true",
|
|
|
|
)
|
|
|
|
parser.add_argument(
|
|
|
|
"-d",
|
|
|
|
"--debug",
|
|
|
|
help="Print debug messages.",
|
|
|
|
action="store_true",
|
|
|
|
)
|
|
|
|
parser.add_argument(
|
|
|
|
"-i",
|
|
|
|
"--input-file",
|
2021-12-20 11:04:11 +01:00
|
|
|
help="Path to schema fields file (ie, iseal-core.csv).",
|
2021-11-01 07:21:50 +01:00
|
|
|
required=True,
|
|
|
|
type=argparse.FileType("r"),
|
|
|
|
)
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
|
|
if args.clean:
|
|
|
|
if args.debug:
|
|
|
|
print(f"Cleaning terms output directory")
|
|
|
|
|
|
|
|
rmtree("site/content/terms", ignore_errors=True)
|
|
|
|
|
|
|
|
if args.debug:
|
|
|
|
print(f"Creating terms output directory")
|
|
|
|
# Make sure content directory exists. This is where we will deposit all the term
|
|
|
|
# metadata and controlled vocabularies for Hugo to process.
|
|
|
|
os.makedirs("site/content/terms", mode=0o755, exist_ok=True)
|
|
|
|
|
|
|
|
if args.debug:
|
|
|
|
print(f"Opening {args.input_file.name}")
|
|
|
|
|
2021-12-07 21:57:09 +01:00
|
|
|
df = pd.read_csv(args.input_file.name)
|
2021-11-01 07:21:50 +01:00
|
|
|
# Added inplace=True
|
|
|
|
df.dropna(how="all", axis=1, inplace=True)
|
|
|
|
df.fillna("", inplace=True)
|
|
|
|
|
|
|
|
parseSchema(df)
|