<filename>helpers/make_programming_idioms_folder.py
import json
import shutil
from datetime import datetime
from pathlib import Path

from black import FileMode, format_str

import regex  # type: ignore

import context
from paroxython.goodies import title_to_slug_factory

title_to_slug = title_to_slug_factory()

algos = json.loads(Path("helpers/programming-idioms.org.2019-09-28_23-33.json").read_text())

base_path = Path("examples/idioms/programs")
if base_path.is_dir():
    shutil.rmtree(base_path)
elif base_path.exists():
    base_path.unlink()
base_path.mkdir(parents=True)

count = 0
for algo in algos:
    slug = title_to_slug(algo["Title"])
    for program in algo["Implementations"]:
        if program["LanguageName"] != "Python":
            continue
        if program["Id"] == 669:  # contents: "print >>sys.stderr, "%s is negative" % x"
            continue
        comment = "\n# ".join(program["AuthorComment"].split("\n"))

        # Manually “fix” some source codes
        source = regex.sub(r"print +([^\(].*)\n", r"print(\1)\n", program["CodeBlock"] + "\n")
        if program["Id"] == 2687:
            source = source.replace("<your data dict>", "'<your data dict>'")
        elif program["Id"] == 1829:
            source = source.replace("input().split())", "input().split()))")
        elif program["Id"] in (2427, 2428, 2429):
            source = f'print("{source[:-1]}")\n'
        source = "\n".join(
            [
                f'"""{algo["Title"]}.',
                f"\n{algo['LeadParagraph']}",
                f"\nSource: {algo['Author']}",
                f'"""',
                "",
                f"# Implementation author: {program['Author']}",
                f"# Created on {program['CreationDate']}",
                f"# Last modified on {program['VersionDate']}",
                f"# Version {program['Version']}",
                "" if not comment else f"\n# {comment}\n",
                "" if not program["ImportsBlock"] else f"\n{program['ImportsBlock']}\n",
                source,
            ]
        ).replace("\n\n\n", "\n\n")

        path = base_path / f"{algo['Id']:03}.{program['Id']:04}-{slug}.py"
        try:
            source = format_str(source, mode=FileMode())
        except Exception:
            print(f"Problem during the formatting of {path}.")
        if program["Id"] == 2283:  # rejected after Black formatting
            source = source.replace(
                "vertex = stack.pop()",
                "vertex = stack.pop()  # paroxython: -member_call_method:pop +member_call_method:list:pop",
            )
        path.write_text(source)
        count += 1
print(f"Dumped {count} programs in '{base_path.resolve()}' directory.")

(base_path / ".." / "read_me.md").write_text(
    f"""\
This collection of Python snippets originates from a snapshot of the CC BY-SA 3.0 Unported
Licensed database of https://www.programming-idioms.org, provided by the author of the engine,
<NAME>, in response to: https://github.com/Deleplace/programming-idioms/issues/98.

The snapshot itself is not placed under version control on the present repository, but you can
retrieve it yourself at https://gist.github.com/Deleplace/76e101f1b9a9e05f00b736a338929355.

The contents of the present folder was generated by helpers/make_programming_idioms_folder.py on
{datetime.now()}. All changes will be lost the next time this program is executed.
"""
)
