diff --git a/.github/scripts/render-readme.py b/.github/scripts/render-readme.py index d109ca4..7ce42bc 100755 --- a/.github/scripts/render-readme.py +++ b/.github/scripts/render-readme.py @@ -1,5 +1,9 @@ -from jinja2 import Environment, FileSystemLoader import json +import logging +from jinja2 import Environment, FileSystemLoader # type: ignore + +# Setting up logging for better debugging and traceability +logging.basicConfig(level=logging.INFO) DATAFILE = "./data.json" TEMPLATEPATH = "./.github/" @@ -7,49 +11,100 @@ TEMPLATEFILE = "README-template.j2" TARGETFILE = "./README.md" def new_technology_dict(repo_technology): + """Creates a dictionary for new technology with an empty entries list.""" return {"link_id": repo_technology.lower(), "entries": []} -technologies = {} +def load_data(datafile): + """Loads data from the JSON file and handles errors in case of missing file or invalid JSON.""" + try: + with open(datafile, "r") as file: + return json.loads(file.read()) + except FileNotFoundError: + logging.error(f"Data file {datafile} not found.") + raise + except json.JSONDecodeError: + logging.error(f"Error decoding JSON from {datafile}. Please check the file format.") + raise -with open(DATAFILE, "r") as datafile: - data = json.loads(datafile.read()) +def process_technologies(data): + """Process technology data into a structured format.""" + technologies = {} + for technology in data["technologies"]: + technologies[technology] = { + "link_id": data["technologies"][technology], + "entries": [], + } + return technologies -for technology in data["technologies"]: - technologies[technology] = { - "link_id": data["technologies"][technology], - "entries": [], - } +def process_repositories(data, technologies): + """Process repository data and associate technologies.""" + for repository in data["repositories"]: + repo_technologies = repository["technologies"] + for repo_technology in repo_technologies: + if repo_technology not in technologies: + technologies[repo_technology] = new_technology_dict(repo_technology) + technologies[repo_technology]["entries"].append(repository) + return technologies -for repository in data["repositories"]: - repo_technologies = repository["technologies"] - for repo_technology in repo_technologies: - if not technologies.get(repo_technology, False): - technologies[repo_technology] = new_technology_dict(repo_technology) - technologies[repo_technology]["entries"].append(repository) +def organize_categories(technologies): + """Organize categories and entries for templating.""" + categories = [] + for key, value in zip(technologies.keys(), technologies.values()): + categories.append( + {"title": key, "link_id": value["link_id"], "entries": value["entries"]} + ) -env = Environment(loader=FileSystemLoader(TEMPLATEPATH)) -template = env.get_template(TEMPLATEFILE) + categories = sorted(categories, key=lambda x: x["title"].upper()) + category_groups = {"Misc": []} + + # Group categories by first character (A-Z), and handle miscellaneous ones separately + for category in categories: + category["entries"] = sorted(category["entries"], key=lambda x: x["name"].upper()) + first_char = category["title"][0].upper() + if first_char in "ABCDEFGHIJKLMNOPQRSTUVWXYZ": + if first_char not in category_groups: + category_groups[first_char] = [] + category_groups[first_char].append(category) + else: + category_groups["Misc"].append(category) + + return categories, category_groups -categories = [] -for key, value in zip(technologies.keys(), technologies.values()): - categories.append( - {"title": key, "link_id": value["link_id"], "entries": value["entries"]} - ) +def generate_readme(template, categories, category_groups, sponsors): + """Render the README file using the Jinja2 template.""" + output = template.render(category_groups=category_groups, categories=categories, sponsors=sponsors) + with open(TARGETFILE, "w") as targetfile: + targetfile.write(output) + logging.info(f"README generated at {TARGETFILE}") -categories = sorted(categories, key=lambda x: x["title"].upper()) -category_groups = {"Misc": []} -for category in categories: - category["entries"] = sorted(category["entries"], key=lambda x: x["name"].upper()) - first_char = category["title"][0].upper() - if first_char in "ABCDEFGHIJKLMNOPQRSTUVWXYZ": - if first_char not in category_groups: - category_groups[first_char] = [] - category_groups[first_char].append(category) - else: - category_groups["Misc"].append(category) +def main(): + """Main function to load data, process repositories and generate the README.""" + try: + # Load the data from the JSON file + data = load_data(DATAFILE) -sponsors = data["sponsors"] + # Process the technology data + technologies = process_technologies(data) -output = template.render(category_groups=category_groups, categories=categories, sponsors=sponsors) + # Process repositories and associate them with technologies + technologies = process_repositories(data, technologies) -open(TARGETFILE, "w").write(output) + # Set up the Jinja2 environment and load the template + env = Environment(loader=FileSystemLoader(TEMPLATEPATH)) + template = env.get_template(TEMPLATEFILE) + + # Organize categories based on technologies + categories, category_groups = organize_categories(technologies) + + # Extract sponsors data + sponsors = data["sponsors"] + + # Generate the README file using the template + generate_readme(template, categories, category_groups, sponsors) + + except Exception as e: + logging.error("An error occurred while generating the README.") + logging.exception(e) + +if __name__ == "__main__": + main()