mirror of
https://codeberg.org/ziglings/exercises.git
synced 2024-12-26 09:30:31 +00:00
98 lines
2.2 KiB
Python
98 lines
2.2 KiB
Python
|
#!/usr/bin/env python
|
||
|
|
||
|
import difflib
|
||
|
import io
|
||
|
import os
|
||
|
import os.path
|
||
|
import subprocess
|
||
|
import sys
|
||
|
|
||
|
|
||
|
IGNORE = subprocess.DEVNULL
|
||
|
PIPE = subprocess.PIPE
|
||
|
|
||
|
EXERCISES_PATH = "exercises"
|
||
|
HEALED_PATH = "patches/healed"
|
||
|
PATCHES_PATH = "patches/patches"
|
||
|
|
||
|
|
||
|
# Heals all the exercises.
|
||
|
def heal():
|
||
|
maketree(HEALED_PATH)
|
||
|
|
||
|
with os.scandir(EXERCISES_PATH) as it:
|
||
|
for entry in it:
|
||
|
name = entry.name
|
||
|
|
||
|
original_path = entry.path
|
||
|
patch_path = os.path.join(PATCHES_PATH, patch_name(name))
|
||
|
output_path = os.path.join(HEALED_PATH, name)
|
||
|
|
||
|
patch(original_path, patch_path, output_path)
|
||
|
|
||
|
|
||
|
# Yields all the healed exercises that are not correctly formatted.
|
||
|
def check_healed():
|
||
|
term = subprocess.run(
|
||
|
["zig", "fmt", "--check", HEALED_PATH], stdout=PIPE, text=True
|
||
|
)
|
||
|
if term.stdout == "" and term.returncode != 0:
|
||
|
term.check_returncode()
|
||
|
|
||
|
stream = io.StringIO(term.stdout)
|
||
|
for line in stream:
|
||
|
yield line.strip()
|
||
|
|
||
|
|
||
|
def main():
|
||
|
heal()
|
||
|
|
||
|
# Show the unified diff between the original example and the correctly
|
||
|
# formatted one.
|
||
|
for i, original in enumerate(check_healed()):
|
||
|
if i > 0:
|
||
|
print()
|
||
|
|
||
|
name = os.path.basename(original)
|
||
|
print(f"checking exercise {name}...\n")
|
||
|
|
||
|
from_file = open(original)
|
||
|
to_file = zig_fmt_file(original)
|
||
|
|
||
|
diff = difflib.unified_diff(
|
||
|
from_file.readlines(), to_file.readlines(), name, name + "-fmt"
|
||
|
)
|
||
|
sys.stderr.writelines(diff)
|
||
|
|
||
|
|
||
|
def maketree(path):
|
||
|
return os.makedirs(path, exist_ok=True)
|
||
|
|
||
|
|
||
|
# Returns path with the patch extension.
|
||
|
def patch_name(path):
|
||
|
name, _ = os.path.splitext(path)
|
||
|
|
||
|
return name + ".patch"
|
||
|
|
||
|
|
||
|
# Applies patch to original, and write the file to output.
|
||
|
def patch(original, patch, output):
|
||
|
subprocess.run(
|
||
|
["patch", "-i", patch, "-o", output, original], stdout=IGNORE, check=True
|
||
|
)
|
||
|
|
||
|
|
||
|
# Formats the Zig file at path, and returns the possibly reformatted file as a
|
||
|
# file object.
|
||
|
def zig_fmt_file(path):
|
||
|
with open(path) as stdin:
|
||
|
term = subprocess.run(
|
||
|
["zig", "fmt", "--stdin"], stdin=stdin, stdout=PIPE, check=True, text=True
|
||
|
)
|
||
|
|
||
|
return io.StringIO(term.stdout)
|
||
|
|
||
|
|
||
|
main()
|