\n")
f.write("use <%s/%s>\n" % (reltmp(dir, target), filename))
f.write("%s();\n" % module);
t = time.time()
target_def = ['-D$target="%s"' % target] if target else []
cwd_def = ['-D$cwd="%s"' % os.getcwd().replace('\\', '/')]
view_def = ['--viewall', '--autocenter'] if not (zoomed & (1 << explode)) else ['--camera=0,0,0,55,0,25,140']
openscad.run_list(["-o", tmp_name, png_maker_name] + options.list() + target_def + cwd_def + view_def + ["-D$pose=1", "-D$explode=%d" % explode, colour_scheme, "--projection=p", image_size, "-d", dname]);
times.add_time(png_name, t)
do_cmd(["magick", tmp_name, "-trim", "-resize", "1004x1004", "-bordercolor", background, "-border", "10", tmp_name])
update_image(tmp_name, png_name)
os.remove(png_maker_name)
tn_name = png_name.replace('.png', '_tn.png')
if mtime(png_name) > mtime(tn_name):
do_cmd(("magick "+ png_name + " -trim -resize 280x280 -background " + background + " -gravity Center -extent 280x280 -bordercolor " + background + " -border 10 " + tmp_name).split())
update_image(tmp_name, tn_name)
done_assemblies.append(real_name)
else:
if module == main_assembly:
main_blurb = blurb.scrape_module_blurb(lines[:line_no])
line_no += 1
#
# Build the document
#
doc_name = top_dir + "readme.md"
with open(doc_name, "wt") as doc_file:
#
# Title, description and picture
#
project = ' '.join(word[0].upper() + word[1:] for word in os.path.basename(os.getcwd()).split('_'))
print('', file = doc_file)
print('# %s' % project, file = doc_file)
text = blurb.scrape_blurb(source_dir + '/' + main_file)
blurbs = blurb.split_blurb(text)
if len(text):
print(blurbs[0], file = doc_file)
else:
print(Fore.MAGENTA + "Missing project description" + Fore.WHITE)
#
# Only add the image if the first blurb section doesn't contain one.
#
if not re.search(r'\!\[.*\]\(.*\)', blurbs[0], re.MULTILINE):
print('![Main Assembly](assemblies/%s.png)\n' % flat_bom[-1]["name"].replace('_assembly', '_assembled'), file = doc_file)
eop(doc_file, first = True)
#
# Build TOC
#
print('## Table of Contents', file = doc_file)
print('1. [Parts list](#Parts_list)', file = doc_file)
for ass in flat_bom:
name = ass["name"]
cap_name = titalise(name)
print('1. [%s](#%s)' % (cap_name, name), file = doc_file)
print(file = doc_file)
if len(blurbs) > 1:
print(blurbs[1], file = doc_file)
eop(doc_file)
#
# Global BOM
#
global_bom = [merged(ass) for ass in flat_bom if not ass['ngb']]
print('\n## Parts list', file = doc_file)
headings = {"vitamins" : "vitamins", "printed" : "3D printed parts", "routed" : "CNC routed parts"}
things = {}
for t in types:
things[t] = {}
for ass in flat_bom:
for t in types:
for thing in ass[t]:
if thing in things[t]:
things[t][thing] += ass[t][thing]["count"]
else:
things[t][thing] = ass[t][thing]["count"]
for ass in global_bom:
name = titalise(ass["name"][:-9]).replace(' ',' ')
if ass["count"] > 1:
name = "%d x %s" % (ass["count"], name)
print('| %s ' % name, file = doc_file, end = '')
print('| TOTALS | |', file = doc_file)
print(('|---:' * len(global_bom) + '|---:|:---|'), file = doc_file)
for t in types:
if things[t]:
totals = {}
grand_total2 = 0
heading = headings[t][0].upper() + headings[t][1:]
print(('| ' * len(global_bom) + '| | **%s** |') % heading, file = doc_file)
for thing in sorted(things[t], key = lambda s: s.split(":",1)[-1]):
for ass in global_bom:
count = ass[t][thing]["count"] if thing in ass[t] else 0
print('| %s ' % pad(count if count else '.', 2, 1), file = doc_file, end = '')
name = ass["name"]
if name in totals:
totals[name] += count
else:
totals[name] = count
grand_total2 += count
print('| %s | %s |' % (pad(things[t][thing], 2, 1), pad(thing.split(":",1)[-1], 2)), file = doc_file)
grand_total = 0
for ass in global_bom:
name = ass["name"]
total = totals[name] if name in totals else 0
print('| %s ' % pad(total if total else '.', 2, 1), file = doc_file, end = '')
grand_total += total
print("| %s | %s |" % (pad(grand_total, 2, 1), pad('Total %s count' % headings[t], 2)), file = doc_file)
assert grand_total == grand_total2
print(file = doc_file)
if len(blurbs) > 2:
print(blurbs[2], file = doc_file)
eop(doc_file)
#
# Assembly instructions
#
for ass in flat_bom:
name = ass["name"]
cap_name = titalise(name)
print('' % name, file = doc_file)
if ass["count"] > 1:
print('## %d x %s' % (ass["count"], cap_name), file = doc_file)
else:
print('## %s' % cap_name, file = doc_file)
vitamins = ass["vitamins"]
if vitamins:
print("### Vitamins", file = doc_file)
print("|Qty|Description|", file = doc_file)
print("|---:|:----------|", file = doc_file)
for v in sorted(vitamins, key = lambda s: s.split(":",1)[-1]):
print("|%d|%s|" % (vitamins[v]["count"], v.split(":",1)[1]), file = doc_file)
print("\n", file = doc_file)
printed = ass["printed"]
if printed:
print('### 3D Printed parts', file = doc_file)
keys = sorted(list(printed.keys()))
for i, p in enumerate(keys):
print('%s %d x %s |' % ('\n|' if not (i % 3) else '', printed[p]["count"], p), file = doc_file, end = '')
if (i % 3) == 2 or i == len(printed) - 1:
n = (i % 3) + 1
print('\n|%s' % ('---|' * n), file = doc_file)
for j in range(n):
part = keys[i - n + j + 1]
print('| ![%s](stls/%s) %s' % (part, part.replace('.stl','.png'), '|\n' if j == j - 1 else ''), end = '', file = doc_file)
print('\n', file = doc_file)
print('\n', file = doc_file)
routed = ass["routed"]
if routed:
print("### CNC Routed parts", file = doc_file)
keys = sorted(list(routed.keys()))
for i, r in enumerate(keys):
print('%s %d x %s |' % ('\n|' if not (i % 3) else '', routed[r]["count"], r), file = doc_file, end = '')
if (i % 3) == 2 or i == len(routed) - 1:
n = (i % 3) + 1
print('\n|%s' % ('---|' * n), file = doc_file)
for j in range(n):
part = keys[i - n + j + 1]
if (part[-4:] == ".dxf"):
print('| ![%s](dxfs/%s) %s' % (part, part.replace('.dxf','.png'), '|\n' if j == j - 1 else ''), end = '', file = doc_file)
elif (part[-4:] == ".svg"):
print('| ![%s](svgs/%s) %s' % (part, part.replace('.svg','.png'), '|\n' if j == j - 1 else ''), end = '', file = doc_file)
else:
print("Unkown file type ", part[-4:], " for file ", part)
print('\n', file = doc_file)
print('\n', file = doc_file)
sub_assemblies = ass["assemblies"]
if sub_assemblies:
print("### Sub-assemblies", file = doc_file)
keys = sorted(list(sub_assemblies.keys()))
for i, a in enumerate(keys):
print('%s %d x %s |' % ('\n|' if not (i % 3) else '', sub_assemblies[a], a), file = doc_file, end = '')
if (i % 3) == 2 or i == len(keys) - 1:
n = (i % 3) + 1
print('\n|%s' % ('---|' * n), file = doc_file)
for j in range(n):
a = keys[i - n + j + 1].replace('_assembly', '_assembled')
print('| ![%s](assemblies/%s) %s' % (a, a + '_tn.png', '|\n' if j == j - 1 else ''), end = '', file = doc_file)
print('\n', file = doc_file)
print('\n', file = doc_file)
small = not ass["big"]
suffix = '_tn.png' if small else '.png'
print('### Assembly instructions', file = doc_file)
print('![%s](assemblies/%s)\n' % (name, name + suffix), file = doc_file)
if "blurb" in ass and ass["blurb"]:
print(ass["blurb"], file = doc_file)
else:
print(Fore.MAGENTA + "Missing instructions for %s" % name, Fore.WHITE)
name = name.replace('_assembly', '_assembled')
print('![%s](assemblies/%s)\n' % (name, name + suffix), file = doc_file)
eop(doc_file, last = ass == flat_bom[-1] and not main_blurb)
#
# If main module is suppressed print any blurb here
#
if main_blurb:
print(main_blurb, file = doc_file)
eop(doc_file, last = True)
#
# Convert to HTML
#
html_name = top_dir + 'readme.html'
t = time.time()
with open(html_name, "wt") as html_file:
do_cmd(("python -m markdown -x tables -x sane_lists " + doc_name).split(), html_file)
times.add_time(html_name, t)
times.print_times(pngs + [html_name])
#
# Make the printme.html by replacing empty spans that invisibly mark the page breaks by page break divs.
#
with open(html_name, 'rt') as src:
lines = src.readlines()
i = 0
with open(top_dir + 'printme.html', 'wt') as dst:
while i < len(lines):
line = lines[i]
if line.startswith(''): # Empty span used to mark page breaks
i += 1
if lines[i].startswith('Top'): # The first page break won't have one
i += 1
if i < len(lines) and lines[i] == '
\n': # The last page break doesn't have one
dst.write('\n')
i += 1
else:
dst.write(line)
i += 1
#
# Remove tmp dir
#
rmtmpdir(tmp_dir)
#
# Spell check
#
do_cmd(('codespell -L od ' + top_dir + 'readme.md').split())
#
# List the ones we didn't find
#
missing = set()
for assembly in assemblies + (do_assemblies if do_assemblies else []):
if assembly not in done_assemblies:
missing.add(assembly)
if missing:
for assembly in missing:
print(Fore.MAGENTA + "Could not find a module called", assembly, Fore.WHITE)
sys.exit(1)
if __name__ == '__main__':
if len(sys.argv) > 1 and sys.argv[1][-9:] != "_assembly":
target, assemblies = sys.argv[1], sys.argv[2:]
else:
target, assemblies = None, sys.argv[1:]
for a in assemblies:
if a[-9:] != "_assembly": usage()
views(target, assemblies)