Compare commits
No commits in common. "main" and "add-actions" have entirely different histories.
main
...
add-action
4 changed files with 82 additions and 155 deletions
|
|
@ -6,13 +6,15 @@ SPDX-License-Identifier: MIT
|
|||
|
||||
This folder contains scripts that can be run to create requirement screenshots for all of the learn guide projects
|
||||
|
||||
To use the scripts you must set the environment `LEARN_GUIDE_REPO` to point to the location of learn guide repo. It must end with a trailing slash.
|
||||
To use the scripts you must set `LEARN_GUIDE_REPO` inside of `get_imports.py` to point to the location of learn guide repo.
|
||||
|
||||
The default value is `"../Adafruit_Learning_System_Guides/"`, one directory above the root of this repo.
|
||||
default value is `"../../Adafruit_Learning_System_Guides/"`
|
||||
|
||||
One directory above the root of this repo.
|
||||
|
||||
With that pointed at a learn guide repo you can run:
|
||||
|
||||
```
|
||||
python3 create_requirement_images.py
|
||||
python create_requirement_images.py
|
||||
```
|
||||
It will create images in the `generated_images` directory.
|
||||
|
|
|
|||
|
|
@ -11,15 +11,13 @@ Create requirement screenshots for learn guide projects
|
|||
from multiprocessing import Pool
|
||||
import json
|
||||
import os
|
||||
import traceback
|
||||
|
||||
import click
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
|
||||
from get_imports import (
|
||||
get_libs_for_project,
|
||||
get_files_for_project,
|
||||
get_libs_for_example,
|
||||
get_files_for_example,
|
||||
get_learn_guide_cp_projects,
|
||||
)
|
||||
|
||||
|
|
@ -42,26 +40,20 @@ f = open("latest_bundle_data.json", "r")
|
|||
bundle_data = json.load(f)
|
||||
f.close()
|
||||
|
||||
font = ImageFont.truetype("Roboto-Regular.ttf", 24)
|
||||
right_triangle = Image.open("img/right_triangle.png")
|
||||
down_triangle = Image.open("img/down_triangle.png")
|
||||
|
||||
def asset_path(x):
|
||||
"""Return the location of a file shipped with the screenshot maker"""
|
||||
return os.path.join(os.path.dirname(__file__), x)
|
||||
folder_icon = Image.open("img/folder.png")
|
||||
folder_hidden_icon = Image.open("img/folder_hidden.png")
|
||||
file_icon = Image.open("img/file.png")
|
||||
file_hidden_icon = Image.open("img/file_hidden.png")
|
||||
file_empty_icon = Image.open("img/file_empty.png")
|
||||
file_empty_hidden_icon = Image.open("img/file_empty_hidden.png")
|
||||
|
||||
|
||||
font = ImageFont.truetype(asset_path("Roboto-Regular.ttf"), 24)
|
||||
right_triangle = Image.open(asset_path("img/right_triangle.png"))
|
||||
down_triangle = Image.open(asset_path("img/down_triangle.png"))
|
||||
|
||||
folder_icon = Image.open(asset_path("img/folder.png"))
|
||||
folder_hidden_icon = Image.open(asset_path("img/folder_hidden.png"))
|
||||
file_icon = Image.open(asset_path("img/file.png"))
|
||||
file_hidden_icon = Image.open(asset_path("img/file_hidden.png"))
|
||||
file_empty_icon = Image.open(asset_path("img/file_empty.png"))
|
||||
file_empty_hidden_icon = Image.open(asset_path("img/file_empty_hidden.png"))
|
||||
|
||||
file_image_icon = Image.open(asset_path("img/file_image.png"))
|
||||
file_music_icon = Image.open(asset_path("img/file_music.png"))
|
||||
file_font_icon = Image.open(asset_path("img/file_font.png"))
|
||||
file_image_icon = Image.open("img/file_image.png")
|
||||
file_music_icon = Image.open("img/file_music.png")
|
||||
file_font_icon = Image.open("img/file_font.png")
|
||||
|
||||
FILE_TYPE_ICON_MAP = {
|
||||
"py": file_icon,
|
||||
|
|
@ -81,7 +73,7 @@ for file_icon in FILE_TYPE_ICON_MAP.values():
|
|||
|
||||
|
||||
def generate_requirement_image(
|
||||
project_files, libs, image_name
|
||||
learn_guide_project,
|
||||
): # pylint: disable=too-many-statements
|
||||
"""Generate a single requirement image"""
|
||||
|
||||
|
|
@ -157,7 +149,7 @@ def generate_requirement_image(
|
|||
font=font,
|
||||
)
|
||||
|
||||
def make_header(position, project_files):
|
||||
def make_header(position, learn_guide_project):
|
||||
# Static files
|
||||
make_line("CIRCUITPY", position)
|
||||
make_line(
|
||||
|
|
@ -189,6 +181,7 @@ def generate_requirement_image(
|
|||
)
|
||||
|
||||
# dynamic files from project dir in learn guide repo
|
||||
project_files = get_files_for_project(learn_guide_project)
|
||||
rows_added = 0
|
||||
project_files_to_draw = []
|
||||
project_folders_to_draw = []
|
||||
|
|
@ -196,10 +189,16 @@ def generate_requirement_image(
|
|||
if "." in cur_file[-5:]:
|
||||
cur_extension = cur_file.split(".")[-1]
|
||||
if cur_extension in SHOWN_FILETYPES:
|
||||
project_files_to_draw.append(cur_file)
|
||||
if cur_file != "main.py":
|
||||
project_files_to_draw.append(cur_file)
|
||||
else:
|
||||
project_folders_to_draw.append(cur_file)
|
||||
|
||||
try:
|
||||
project_files_to_draw.remove("code.py")
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
for i, file in enumerate(sorted(project_files_to_draw)):
|
||||
cur_file_extension = file.split(".")[-1]
|
||||
|
||||
|
|
@ -292,87 +291,48 @@ def generate_requirement_image(
|
|||
triangle_icon=triangle_icon,
|
||||
)
|
||||
|
||||
final_list_to_render = sort_libraries(libs)
|
||||
try:
|
||||
libs = get_libs_for_project(learn_guide_project)
|
||||
final_list_to_render = sort_libraries(libs)
|
||||
|
||||
if "code.py" in project_files:
|
||||
project_files.remove("code.py")
|
||||
project_file_list = get_files_for_project(learn_guide_project)
|
||||
|
||||
if "main.py" in project_files:
|
||||
project_files.remove("main.py")
|
||||
project_files_count = len(project_file_list)
|
||||
|
||||
project_files_count = len(project_files)
|
||||
if "code.py" in project_file_list:
|
||||
project_files_count -= 1
|
||||
|
||||
image_height = (
|
||||
PADDING * 2
|
||||
+ 7 * LINE_SPACING
|
||||
+ len(final_list_to_render) * LINE_SPACING
|
||||
+ (project_files_count) * LINE_SPACING
|
||||
)
|
||||
img = Image.new("RGB", (OUT_WIDTH, image_height), "#303030")
|
||||
draw = ImageDraw.Draw(img)
|
||||
if "main.py" in project_file_list:
|
||||
project_files_count -= 1
|
||||
|
||||
make_background_highlights(
|
||||
7 + len(final_list_to_render) + project_files_count,
|
||||
offset=(PADDING, PADDING),
|
||||
)
|
||||
image_height = (
|
||||
PADDING * 2
|
||||
+ 7 * LINE_SPACING
|
||||
+ len(final_list_to_render) * LINE_SPACING
|
||||
+ (project_files_count) * LINE_SPACING
|
||||
)
|
||||
img = Image.new("RGB", (OUT_WIDTH, image_height), "#303030")
|
||||
draw = ImageDraw.Draw(img)
|
||||
|
||||
make_header((PADDING, PADDING), project_files)
|
||||
make_libraries(
|
||||
final_list_to_render,
|
||||
(PADDING, PADDING + (LINE_SPACING * (7 + project_files_count))),
|
||||
)
|
||||
make_background_highlights(
|
||||
7 + len(final_list_to_render) + project_files_count,
|
||||
offset=(PADDING, PADDING),
|
||||
)
|
||||
|
||||
img.save("generated_images/{}.png".format(image_name))
|
||||
make_header((PADDING, PADDING), learn_guide_project)
|
||||
make_libraries(
|
||||
final_list_to_render,
|
||||
(PADDING, PADDING + (LINE_SPACING * (7 + project_files_count))),
|
||||
)
|
||||
|
||||
|
||||
def generate_learn_requirement_image( # pylint: disable=invalid-name
|
||||
learn_guide_project,
|
||||
):
|
||||
"""Generate an image for a single learn project"""
|
||||
image_name = learn_guide_project.replace("/", "_")
|
||||
libs = get_libs_for_project(learn_guide_project)
|
||||
project_files = get_files_for_project(learn_guide_project)
|
||||
generate_requirement_image(project_files, libs, image_name)
|
||||
|
||||
|
||||
def generate_example_requirement_image(example_path): # pylint: disable=invalid-name
|
||||
"""Generate an image for a library example"""
|
||||
image_name = "_".join(
|
||||
element
|
||||
for element in example_path.split("/")
|
||||
if element not in ("libraries", "drivers", "helpers", "examples")
|
||||
)
|
||||
libs = get_libs_for_example(example_path)
|
||||
project_files = get_files_for_example(example_path)
|
||||
generate_requirement_image(project_files, libs, image_name)
|
||||
|
||||
|
||||
@click.group(invoke_without_command=True)
|
||||
@click.pass_context
|
||||
def cli(ctx):
|
||||
"""Main entry point; invokes the learn subcommand if nothing is specified"""
|
||||
if ctx.invoked_subcommand is None:
|
||||
learn()
|
||||
|
||||
|
||||
@cli.command()
|
||||
def learn():
|
||||
"""Generate images for a learn-style repo"""
|
||||
with Pool() as pool:
|
||||
for _ in pool.imap(
|
||||
generate_learn_requirement_image, get_learn_guide_cp_projects()
|
||||
):
|
||||
pass
|
||||
|
||||
|
||||
@cli.command()
|
||||
@click.argument("paths", nargs=-1)
|
||||
def bundle(paths):
|
||||
"""Generate images for a bundle-style repo"""
|
||||
with Pool() as pool:
|
||||
for _ in pool.imap(generate_example_requirement_image, paths):
|
||||
pass
|
||||
img.save("generated_images/{}.png".format(learn_guide_project))
|
||||
except SyntaxError as exc:
|
||||
print(exc)
|
||||
traceback.print_exc()
|
||||
print("SyntaxError finding imports for {}".format(learn_guide_project))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
cli() # pylint: disable=no-value-for-parameter
|
||||
with Pool() as p:
|
||||
for _ in p.imap(generate_requirement_image, get_learn_guide_cp_projects()):
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -16,11 +16,10 @@ BUNDLE_DATA = "latest_bundle_data.json"
|
|||
BUNDLE_TAG = "latest_bundle_tag.json"
|
||||
|
||||
LEARN_GUIDE_REPO = os.environ.get(
|
||||
"LEARN_GUIDE_REPO", "../Adafruit_Learning_System_Guides/"
|
||||
"LEARN_GUIDE_REPO", "../../Adafruit_Learning_System_Guides/"
|
||||
)
|
||||
|
||||
SHOWN_FILETYPES = ["py", "mpy", "bmp", "pcf", "bdf", "wav", "mp3", "json", "txt"]
|
||||
SHOWN_FILETYPES_EXAMPLE = [s for s in SHOWN_FILETYPES if s != "py"]
|
||||
|
||||
|
||||
def get_bundle(tag):
|
||||
|
|
@ -141,61 +140,28 @@ def get_libs_for_project(project_name):
|
|||
return found_libs
|
||||
|
||||
|
||||
def get_files_for_example(example_path):
|
||||
"""Get the set of files for a library example"""
|
||||
found_files = set(("code.py",))
|
||||
example_dir = os.path.dirname(example_path)
|
||||
for file in os.listdir(example_dir):
|
||||
if "." in file:
|
||||
cur_extension = file.split(".")[-1]
|
||||
if cur_extension in SHOWN_FILETYPES_EXAMPLE:
|
||||
# print(file)
|
||||
found_files.add(file)
|
||||
else:
|
||||
# add dir
|
||||
found_files.add(file)
|
||||
return found_files
|
||||
|
||||
|
||||
def get_libs_for_example(example_path):
|
||||
"""Get the set of libraries for a library example"""
|
||||
found_libs = set()
|
||||
found_imports = []
|
||||
found_imports = findimports.find_imports(example_path)
|
||||
|
||||
for cur_import in found_imports:
|
||||
cur_lib = cur_import.name.split(".")[0]
|
||||
if cur_lib in bundle_data:
|
||||
found_libs.add(cur_lib)
|
||||
|
||||
return found_libs
|
||||
def get_learn_guide_projects():
|
||||
"""Get the list of all folders in the learn guide"""
|
||||
return os.listdir(LEARN_GUIDE_REPO)
|
||||
|
||||
|
||||
def get_learn_guide_cp_projects():
|
||||
"""Get the list of all circuitpython projects, according to some heuristics"""
|
||||
for dirpath, dirnames, filenames in os.walk(LEARN_GUIDE_REPO):
|
||||
# Don't consider hidden directories
|
||||
dirnames[:] = [d for d in dirnames if not d.startswith(".")]
|
||||
cp_projects = []
|
||||
|
||||
# The top-level needs special treatment
|
||||
if dirpath == LEARN_GUIDE_REPO:
|
||||
continue
|
||||
def has_py_file(location):
|
||||
dir_files = os.listdir(location)
|
||||
for file in dir_files:
|
||||
if file.endswith(".py"):
|
||||
return ".circuitpython.skip" not in dir_files
|
||||
return False
|
||||
|
||||
# Skip this folder and all subfolders
|
||||
if ".circuitpython.skip" in filenames:
|
||||
del dirnames[:]
|
||||
continue
|
||||
# Skip files in this folder, but handle sub-folders
|
||||
if ".circuitpython.skip-here" in filenames:
|
||||
continue
|
||||
# Do not reurse, but handle files in this folder
|
||||
if ".circuitpython.skip-sub" in filenames:
|
||||
del dirnames[:]
|
||||
|
||||
if any(f for f in filenames if f.endswith(".py")):
|
||||
yield os.path.relpath(dirpath, LEARN_GUIDE_REPO)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
for p in get_learn_guide_cp_projects():
|
||||
print("PROJECT", p)
|
||||
all_projects = get_learn_guide_projects()
|
||||
for project in all_projects:
|
||||
project_dir = "{}/{}/".format(LEARN_GUIDE_REPO, project)
|
||||
try:
|
||||
if has_py_file(project_dir):
|
||||
cp_projects.append(project)
|
||||
except NotADirectoryError:
|
||||
pass
|
||||
return cp_projects
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
findimports
|
||||
pillow
|
||||
requests
|
||||
click
|
||||
|
|
|
|||
Loading…
Reference in a new issue