Skip to content

Commit d89eb35

Browse files
committed
Adapt to producing images for the bundle
Assumptions are a bit different: * We will list paths on the commandline * We will run from the bundle directory, not from the screenshot maker directory * The path elements 'examples', 'libraries', 'drivers', and 'helpers' can be omitted * A screenshot is generated for each file, and no other .py files are used (though, subdirectories are shown even if they contain no files that would be included) This also still behaves compatibly with the learn repo script
1 parent 2a2b59c commit d89eb35

File tree

3 files changed

+117
-59
lines changed

3 files changed

+117
-59
lines changed

create_requirement_images.py

Lines changed: 81 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,14 @@
1313
import os
1414
import traceback
1515

16+
import click
1617
from PIL import Image, ImageDraw, ImageFont
1718

1819
from get_imports import (
1920
get_libs_for_project,
2021
get_files_for_project,
22+
get_libs_for_example,
23+
get_files_for_example,
2124
get_learn_guide_cp_projects,
2225
)
2326

@@ -40,20 +43,22 @@
4043
bundle_data = json.load(f)
4144
f.close()
4245

43-
font = ImageFont.truetype("Roboto-Regular.ttf", 24)
44-
right_triangle = Image.open("img/right_triangle.png")
45-
down_triangle = Image.open("img/down_triangle.png")
46+
def ASSET(x):
47+
return os.path.join(os.path.dirname(__file__), x)
48+
font = ImageFont.truetype(ASSET("Roboto-Regular.ttf"), 24)
49+
right_triangle = Image.open(ASSET("img/right_triangle.png"))
50+
down_triangle = Image.open(ASSET("img/down_triangle.png"))
4651

47-
folder_icon = Image.open("img/folder.png")
48-
folder_hidden_icon = Image.open("img/folder_hidden.png")
49-
file_icon = Image.open("img/file.png")
50-
file_hidden_icon = Image.open("img/file_hidden.png")
51-
file_empty_icon = Image.open("img/file_empty.png")
52-
file_empty_hidden_icon = Image.open("img/file_empty_hidden.png")
52+
folder_icon = Image.open(ASSET("img/folder.png"))
53+
folder_hidden_icon = Image.open(ASSET("img/folder_hidden.png"))
54+
file_icon = Image.open(ASSET("img/file.png"))
55+
file_hidden_icon = Image.open(ASSET("img/file_hidden.png"))
56+
file_empty_icon = Image.open(ASSET("img/file_empty.png"))
57+
file_empty_hidden_icon = Image.open(ASSET("img/file_empty_hidden.png"))
5358

54-
file_image_icon = Image.open("img/file_image.png")
55-
file_music_icon = Image.open("img/file_music.png")
56-
file_font_icon = Image.open("img/file_font.png")
59+
file_image_icon = Image.open(ASSET("img/file_image.png"))
60+
file_music_icon = Image.open(ASSET("img/file_music.png"))
61+
file_font_icon = Image.open(ASSET("img/file_font.png"))
5762

5863
FILE_TYPE_ICON_MAP = {
5964
"py": file_icon,
@@ -73,7 +78,7 @@
7378

7479

7580
def generate_requirement_image(
76-
learn_guide_project,
81+
project_files, libs, image_name
7782
): # pylint: disable=too-many-statements
7883
"""Generate a single requirement image"""
7984

@@ -149,7 +154,7 @@ def make_line(
149154
font=font,
150155
)
151156

152-
def make_header(position, learn_guide_project):
157+
def make_header(position, project_files):
153158
# Static files
154159
make_line("CIRCUITPY", position)
155160
make_line(
@@ -181,24 +186,17 @@ def make_header(position, learn_guide_project):
181186
)
182187

183188
# dynamic files from project dir in learn guide repo
184-
project_files = get_files_for_project(learn_guide_project)
185189
rows_added = 0
186190
project_files_to_draw = []
187191
project_folders_to_draw = []
188192
for cur_file in project_files:
189193
if "." in cur_file[-5:]:
190194
cur_extension = cur_file.split(".")[-1]
191195
if cur_extension in SHOWN_FILETYPES:
192-
if cur_file != "main.py":
193-
project_files_to_draw.append(cur_file)
196+
project_files_to_draw.append(cur_file)
194197
else:
195198
project_folders_to_draw.append(cur_file)
196199

197-
try:
198-
project_files_to_draw.remove("code.py")
199-
except ValueError:
200-
pass
201-
202200
for i, file in enumerate(sorted(project_files_to_draw)):
203201
cur_file_extension = file.split(".")[-1]
204202

@@ -291,50 +289,76 @@ def make_libraries(libraries, position):
291289
triangle_icon=triangle_icon,
292290
)
293291

294-
try:
295-
libs = get_libs_for_project(learn_guide_project)
296-
final_list_to_render = sort_libraries(libs)
292+
final_list_to_render = sort_libraries(libs)
297293

298-
project_file_list = get_files_for_project(learn_guide_project)
299294

300-
project_files_count = len(project_file_list)
295+
if "code.py" in project_files:
296+
project_files.remove("code.py")
301297

302-
if "code.py" in project_file_list:
303-
project_files_count -= 1
298+
if "main.py" in project_files:
299+
project_files.remove("main.py")
304300

305-
if "main.py" in project_file_list:
306-
project_files_count -= 1
301+
project_files_count = len(project_files)
307302

308-
image_height = (
309-
PADDING * 2
310-
+ 7 * LINE_SPACING
311-
+ len(final_list_to_render) * LINE_SPACING
312-
+ (project_files_count) * LINE_SPACING
313-
)
314-
img = Image.new("RGB", (OUT_WIDTH, image_height), "#303030")
315-
draw = ImageDraw.Draw(img)
303+
image_height = (
304+
PADDING * 2
305+
+ 7 * LINE_SPACING
306+
+ len(final_list_to_render) * LINE_SPACING
307+
+ (project_files_count) * LINE_SPACING
308+
)
309+
img = Image.new("RGB", (OUT_WIDTH, image_height), "#303030")
310+
draw = ImageDraw.Draw(img)
316311

317-
make_background_highlights(
318-
7 + len(final_list_to_render) + project_files_count,
319-
offset=(PADDING, PADDING),
320-
)
312+
make_background_highlights(
313+
7 + len(final_list_to_render) + project_files_count,
314+
offset=(PADDING, PADDING),
315+
)
321316

322-
make_header((PADDING, PADDING), learn_guide_project)
323-
make_libraries(
324-
final_list_to_render,
325-
(PADDING, PADDING + (LINE_SPACING * (7 + project_files_count))),
326-
)
317+
make_header((PADDING, PADDING), project_files)
318+
make_libraries(
319+
final_list_to_render,
320+
(PADDING, PADDING + (LINE_SPACING * (7 + project_files_count))),
321+
)
327322

328-
img.save(
329-
"generated_images/{}.png".format(learn_guide_project.replace("/", "_"))
330-
)
331-
except SyntaxError as exc:
332-
print(exc)
333-
traceback.print_exc()
334-
print("SyntaxError finding imports for {}".format(learn_guide_project))
323+
img.save(
324+
"generated_images/{}.png".format(image_name)
325+
)
335326

327+
def generate_learn_requirement_image(
328+
learn_guide_project,
329+
):
330+
image_name = learn_guide_project.replace("/", "_")
331+
libs = get_libs_for_project(learn_guide_project)
332+
project_files = get_files_for_project(learn_guide_project)
333+
generate_requirement_image(project_files, libs, image_name)
334+
335+
def generate_example_requirement_image(
336+
example_path
337+
):
338+
image_name = "_".join(element for element in example_path.split('/')
339+
if element not in ('libraries', 'drivers', 'helpers', 'examples'))
340+
libs = get_libs_for_example(example_path)
341+
project_files = get_files_for_example(example_path)
342+
generate_requirement_image(project_files, libs, image_name)
343+
344+
@click.group(invoke_without_command=True)
345+
@click.pass_context
346+
def cli(ctx):
347+
if ctx.invoked_subcommand is None:
348+
learn()
349+
350+
@cli.command()
351+
def learn():
352+
with Pool() as p:
353+
for _ in p.imap(generate_learn_requirement_image, get_learn_guide_cp_projects()):
354+
pass
336355

337-
if __name__ == "__main__":
356+
@cli.command()
357+
@click.argument('paths', nargs=-1)
358+
def bundle(paths):
338359
with Pool() as p:
339-
for _ in p.imap(generate_requirement_image, get_learn_guide_cp_projects()):
360+
for _ in p.imap(generate_example_requirement_image, paths):
340361
pass
362+
363+
if __name__ == "__main__":
364+
cli()

get_imports.py

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
)
2121

2222
SHOWN_FILETYPES = ["py", "mpy", "bmp", "pcf", "bdf", "wav", "mp3", "json", "txt"]
23-
23+
SHOWN_FILETYPES_EXAMPLE = [s for s in SHOWN_FILETYPES if s != "py"]
2424

2525
def get_bundle(tag):
2626
"""Download the given bundle's data to BUNDLE_DATA"""
@@ -139,14 +139,47 @@ def get_libs_for_project(project_name):
139139

140140
return found_libs
141141

142+
def get_files_for_example(example_path):
143+
"""Get the set of files for a library example"""
144+
found_files = set(('code.py',))
145+
example_dir = os.path.dirname(example_path)
146+
for file in os.listdir(example_dir):
147+
if "." in file:
148+
cur_extension = file.split(".")[-1]
149+
if cur_extension in SHOWN_FILETYPES_EXAMPLE:
150+
# print(file)
151+
found_files.add(file)
152+
else:
153+
# add dir
154+
found_files.add(file)
155+
return found_files
156+
157+
158+
def get_libs_for_example(example_path):
159+
"""Get the set of libraries for a library example"""
160+
found_libs = set()
161+
found_imports = []
162+
found_imports = findimports.find_imports(example_path)
163+
164+
for cur_import in found_imports:
165+
cur_lib = cur_import.name.split(".")[0]
166+
if cur_lib in bundle_data:
167+
found_libs.add(cur_lib)
168+
169+
return found_libs
170+
171+
142172

143173
def get_learn_guide_cp_projects():
144174
"""Get the list of all circuitpython projects, according to some heuristics"""
145175
for dirpath, dirnames, filenames in os.walk(LEARN_GUIDE_REPO):
176+
# Don't consider hidden directories
177+
dirnames[:] = [d for d in dirnames if not d.startswith('.')]
178+
146179
# The top-level needs special treatment
147180
if dirpath == LEARN_GUIDE_REPO:
148-
dirnames.remove(".git")
149181
continue
182+
150183
# Skip this folder and all subfolders
151184
if ".circuitpython.skip" in filenames:
152185
del dirnames[:]

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
findimports
22
pillow
33
requests
4+
click

0 commit comments

Comments
 (0)