예제 #1
0
def tests(tests):
    scad_dir = "tests"
    deps_dir = scad_dir + "/deps"
    png_dir = scad_dir + "/png"
    bom_dir = scad_dir + "/bom"
    for dir in [deps_dir, png_dir, bom_dir]:
        if not os.path.isdir(dir):
            os.makedirs(dir)
    doc_name = "readme.md"
    index = {}
    bodies = {}
    times.read_times()
    options.check_options(deps_dir)
    #
    # Make cover pic if does not exist as very slow. Delete it to force an update.
    #
    png_name = "libtest.png"
    scad_name = "libtest.scad"
    if not os.path.isfile(png_name):
        openscad.run(colour_scheme, "--projection=p",
                     "--imgsize=%d,%d" % (w, h), "--camera=0,0,0,50,0,340,500",
                     "--autocenter", "--viewall", "-o", png_name, scad_name)
        do_cmd([
            "magick", png_name, "-trim", "-resize", "1280", "-bordercolor",
            background, "-border", "10", png_name
        ])
    #
    # List of individual part files
    #
    scads = [i for i in sorted(os.listdir(scad_dir)) if i[-5:] == ".scad"]

    for scad in scads:
        base_name = scad[:-5]
        if not tests or base_name in tests:
            print(base_name)
            cap_name = base_name[0].capitalize() + base_name[1:]
            scad_name = scad_dir + '/' + scad
            png_name = png_dir + '/' + base_name + '.png'
            bom_name = bom_dir + '/' + base_name + '.json'

            objects_name = None
            vits_name = 'vitamins/' + base_name + '.scad'
            if is_plural(base_name) and os.path.isfile(vits_name):
                objects_name = vits_name

            locations = [
                ('vitamins/' + depluralise(base_name) + '.scad', 'Vitamins'),
                ('printed/' + base_name + '.scad', 'Printed'),
                ('utils/' + base_name + '.scad', 'Utilities'),
                ('utils/core/' + base_name + '.scad', 'Core Utilities'),
            ]

            for name, type in locations:
                if os.path.isfile(name):
                    impl_name = name
                    break
            else:
                print("Can't find implementation!")
                continue

            vsplit = "M"
            vtype = locations[0][1]
            types = [
                vtype + ' A-' + vsplit[0],
                vtype + ' ' + chr(ord(vsplit) + 1) + '-Z'
            ] + [loc[1] for loc in locations[1:]]
            if type == vtype:
                type = types[0] if cap_name[0] <= vsplit else types[1]

            for t in types:
                if not t in bodies:
                    bodies[t] = []
                    index[t] = []

            body = bodies[type]

            index[type] += [cap_name]
            body += ['<a name="%s"></a>' % cap_name]
            body += ["## " + cap_name]

            doc = None
            if impl_name:
                doc = scrape_code(impl_name)
                blurb = doc["blurb"]
            else:
                blurb = scrape_blurb(scad_name)

            if not len(blurb):
                print("Blurb not found!")
            else:
                body += [blurb]

            if objects_name:
                body += [
                    "[%s](%s) Object definitions.\n" %
                    (objects_name, objects_name)
                ]

            if impl_name:
                body += ["[%s](%s) Implementation.\n" % (impl_name, impl_name)]

            body += [
                "[%s](%s) Code for this example.\n" %
                (scad_name.replace('\\', '/'), scad_name)
            ]

            if doc:
                for thing, heading in [("properties", "Function"),
                                       ("functions", "Function"),
                                       ("modules", "Module")]:
                    things = doc[thing]
                    if things:
                        body += [
                            '### %s\n| %s | Description |\n|:--- |:--- |' %
                            (thing.title(), heading)
                        ]
                        for item in sorted(things):
                            body += [
                                '| ```%s``` | %s |' % (item, things[item])
                            ]
                        body += ['']

            body += ["![%s](%s)\n" % (base_name, png_name)]

            dname = deps_name(deps_dir, scad)
            oldest = png_name if mtime(png_name) < mtime(
                bom_name) else bom_name
            changed = check_deps(oldest, dname)
            changed = times.check_have_time(changed, scad_name)
            changed = options.have_changed(changed, oldest)
            if changed:
                print(changed)
                t = time.time()
                tmp_name = 'tmp.png'
                openscad.run_list(options.list() + [
                    "-D$bom=2", colour_scheme, "--projection=p",
                    "--imgsize=%d,%d" %
                    (w, h), "--camera=0,0,0,70,0,315,500", "--autocenter",
                    "--viewall", "-d", dname, "-o", tmp_name, scad_name
                ])
                times.add_time(scad_name, t)
                do_cmd([
                    "magick", tmp_name, "-trim", "-resize", "1000x600",
                    "-bordercolor", background, "-border", "10", tmp_name
                ])
                update_image(tmp_name, png_name)
                BOM = bom.parse_bom()
                with open(bom_name, 'wt') as outfile:
                    json.dump(BOM.flat_data(), outfile, indent=4)

            with open(bom_name, "rt") as bom_file:
                BOM = json.load(bom_file)
                for thing, heading in [("vitamins", "Module call | BOM entry"),
                                       ("printed", "Filename"),
                                       ("routed", "Filename"),
                                       ("assemblies", "Name")]:
                    things = BOM[thing]
                    if things:
                        body += [
                            '### %s\n| Qty | %s |\n| ---:|:--- |%s' %
                            (thing.title(), heading,
                             ':---|' if '|' in heading else '')
                        ]
                        for item in sorted(things,
                                           key=lambda s: s.split(":")[-1]):
                            name = item
                            desc = ''
                            if thing == "vitamins":
                                vit = item.split(':')
                                name = '```' + vit[0] + '```' if vit[0] else ''
                                while '[[' in name and ']]' in name:
                                    i = name.find('[[')
                                    j = name.find(']]') + 2
                                    name = name.replace(name[i:j], '[ ... ]')
                                desc = vit[1]
                                body += [
                                    '| %3d | %s | %s |' %
                                    (things[item], name, desc)
                                ]
                            else:
                                body += ['| %3d | %s |' % (things[item], name)]
                        body += ['']

            body += ['\n<a href="#top">Top</a>']
            body += ["\n---"]

    with open(doc_name, "wt") as doc_file:
        print('# NopSCADlib', file=doc_file)
        print('''\
An ever expanding library of parts modelled in OpenSCAD useful for 3D printers and enclosures for electronics, etc.

It contains lots of vitamins (the RepRap term for non-printed parts), some general purpose printed parts and
some utilities. There are also Python scripts to generate Bills of Materials (BOMs),
 STL files for all the printed parts, DXF files for CNC routed parts in a project and a manual containing assembly
instructions and exploded views by scraping markdown embedded in OpenSCAD comments, [see scripts](scripts/readme.md). A simple example project can be found [here](examples/MainsBreakOutBox/readme.md).

For more examples of what it can make see the [gallery](gallery/readme.md).

The license is GNU General Public License v3.0, see [COPYING](COPYING).

See [usage](docs/usage.md) for requirements, installation instructions and a usage guide.

<img src="libtest.png" width="100%"/>\n
''',
              file=doc_file)

        print('## Table of Contents<a name="top"/>', file=doc_file)
        print('<table><tr>', file=doc_file)
        n = 0
        for type in types:
            print('<th align="left"> %s </th>' % type, end='', file=doc_file)
            n = max(n, len(index[type]))
        print('</tr>', file=doc_file)
        for i in range(n):
            print('<tr>', file=doc_file, end='')
            for type in types:
                if i < len(index[type]):
                    name = sorted(index[type])[i]
                    print('<td> <a href = "#' + name + '">' + name +
                          '</a> </td>',
                          file=doc_file,
                          end='')
                else:
                    print('<td></td>', file=doc_file, end='')
            print('</tr>', file=doc_file)
        print('</table>\n\n---', file=doc_file)
        for type in types:
            for line in bodies[type]:
                print(line, file=doc_file)
    with open("readme.html", "wt") as html_file:
        do_cmd("python -m markdown -x tables readme.md".split(), html_file)
    times.print_times()
    do_cmd('codespell -L od readme.md'.split())
예제 #2
0
def tests(tests):
    scad_dir = "tests"
    deps_dir = scad_dir + "/deps"
    png_dir = scad_dir + "/png"
    bom_dir = scad_dir + "/bom"
    for dir in [deps_dir, png_dir, bom_dir]:
        if not os.path.isdir(dir):
            os.makedirs(dir)
    index = {}
    bodies = {}
    done = []
    times.read_times()
    options.check_options(deps_dir)
    #
    # Make cover pic if does not exist as very slow. Delete it to force an update.
    #
    png_name = "libtest.png"
    scad_name = "libtest.scad"
    if os.path.isfile(scad_name):
        libtest = True
        lib_blurb = scrape_blurb(scad_name)
        if not os.path.isfile(png_name):
            openscad.run(colour_scheme, "--projection=p",
                         "--imgsize=%d,%d" % (w, h),
                         "--camera=0,0,0,50,0,340,500", "--autocenter",
                         "--viewall", "-o", png_name, scad_name)
            do_cmd([
                "magick", png_name, "-trim", "-resize", "1280", "-bordercolor",
                background, "-border", "10", png_name
            ])
    else:
        #
        # Project tests so just a title
        #
        libtest = False
        project = ' '.join(
            word[0].upper() + word[1:]
            for word in os.path.basename(os.getcwd()).split('_'))
        lib_blurb = '#' + project + ' Tests\n'

    doc_base_name = "readme" if libtest else "tests"
    doc_name = doc_base_name + ".md"
    #
    # List of individual part files
    #

    scads = [
        i for i in sorted(os.listdir(scad_dir), key=lambda s: s.lower())
        if i[-5:] == ".scad"
    ]
    types = []
    for scad in scads:
        base_name = scad[:-5]
        if not tests or base_name in tests:
            done.append(base_name)
            print('\n' + base_name)
            cap_name = base_name[0].capitalize() + base_name[1:]
            base_name = base_name.lower()
            scad_name = scad_dir + '/' + scad
            png_name = png_dir + '/' + base_name + '.png'
            bom_name = bom_dir + '/' + base_name + '.json'

            objects_name = None
            vits_name = 'vitamins/' + base_name + '.scad'
            if is_plural(base_name) and os.path.isfile(vits_name):
                objects_name = vits_name

            locations = []
            if os.path.isdir('vitamins'):
                locations.append(
                    ('vitamins/' + depluralise(base_name) + '.scad',
                     'Vitamins'))
            if os.path.isdir('printed'):
                locations.append(('printed/' + base_name + '.scad', 'Printed'))
            if os.path.isdir('utils'):
                locations.append(('utils/' + base_name + '.scad', 'Utilities'))
            if libtest and os.path.isdir('utils/core'):
                locations.append(
                    ('utils/core/' + base_name + '.scad', 'Core Utilities'))

            for name, type in locations:
                if os.path.isfile(name):
                    impl_name = name
                    break
            else:
                if libtest:
                    print("Can't find implementation!")
                    continue
                else:
                    type = 'Tests'  # OK when testing part of a project
                    impl_name = None

            if libtest:
                vsplit = "AJR" + chr(ord('Z') + 1)
                vtype = locations[0][1]
                types = [
                    vtype + ' ' + vsplit[i] + '-' +
                    chr(ord(vsplit[i + 1]) - 1)
                    for i in range(len(vsplit) - 1)
                ] + [loc[1] for loc in locations[1:]]
                if type == vtype:
                    for i in range(1, len(vsplit)):
                        if cap_name[0] < vsplit[i]:
                            type = types[i - 1]
                            break
            else:
                if not types:
                    types = [loc[1] for loc in locations
                             ]  # No need to split up the vitamin list
                    if not type in types:  # Will happen when implementation is not found and type is set to Tests
                        types.append(type)

            for t in types:
                if not t in bodies:
                    bodies[t] = []
                    index[t] = []

            body = bodies[type]

            index[type] += [cap_name]
            body += ['<a name="%s"></a>' % cap_name]
            body += ["## " + cap_name]

            doc = None
            if impl_name:
                doc = scrape_code(impl_name)
                blurb = doc["blurb"]
            else:
                blurb = scrape_blurb(scad_name)

            if not len(blurb):
                print("Blurb not found!")
            else:
                body += [blurb]

            if objects_name:
                body += [
                    "[%s](%s) Object definitions.\n" %
                    (objects_name, objects_name)
                ]

            if impl_name:
                body += ["[%s](%s) Implementation.\n" % (impl_name, impl_name)]

            body += [
                "[%s](%s) Code for this example.\n" %
                (scad_name.replace('\\', '/'), scad_name)
            ]

            if doc:
                for thing, heading in [("properties", "Function"),
                                       ("functions", "Function"),
                                       ("modules", "Module")]:
                    things = doc[thing]
                    if things:
                        body += [
                            '### %s\n| %s | Description |\n|:--- |:--- |' %
                            (thing.title(), heading)
                        ]
                        for item in sorted(things):
                            body += ['| `%s` | %s |' % (item, things[item])]
                        body += ['']

            body += ["![%s](%s)\n" % (base_name, png_name)]

            dname = deps_name(deps_dir, scad.lower())
            oldest = png_name if mtime(png_name) < mtime(
                bom_name) else bom_name
            changed = check_deps(oldest, dname)
            changed = times.check_have_time(changed, scad_name)
            changed = options.have_changed(changed, oldest)
            if changed:
                print(changed)
                t = time.time()
                tmp_name = 'tmp.png'
                openscad.run_list(options.list() + [
                    "-D$bom=2", colour_scheme, "--projection=p",
                    "--imgsize=%d,%d" %
                    (w, h), "--camera=0,0,0,70,0,315,500", "--autocenter",
                    "--viewall", "-d", dname, "-o", tmp_name, scad_name
                ])
                times.add_time(scad_name, t)
                do_cmd([
                    "magick", tmp_name, "-trim", "-resize", "1000x600",
                    "-bordercolor", background, "-border", "10", tmp_name
                ])
                update_image(tmp_name, png_name)
                BOM = bom.parse_bom()
                with open(bom_name, 'wt') as outfile:
                    json.dump(BOM.flat_data(), outfile, indent=4)

            with open(bom_name, "rt") as bom_file:
                BOM = json.load(bom_file)
                for thing, heading in [("vitamins", "Module call | BOM entry"),
                                       ("printed", "Filename"),
                                       ("routed", "Filename"),
                                       ("assemblies", "Name")]:
                    things = BOM[thing]
                    if things:
                        body += [
                            '### %s\n| Qty | %s |\n| ---:|:--- |%s' %
                            (thing.title(), heading,
                             ':---|' if '|' in heading else '')
                        ]
                        for item in sorted(things,
                                           key=lambda s: s.split(":")[-1]):
                            name = item
                            desc = ''
                            if thing == "vitamins":
                                vit = item.split(':')
                                name = '`' + vit[0] + '`' if vit[0] else ''
                                while '[[' in name and ']]' in name:
                                    i = name.find('[[')
                                    j = name.find(']]') + 2
                                    name = name.replace(name[i:j], '[ ... ]')
                                desc = vit[1]
                                body += [
                                    '| %3d | %s | %s |' %
                                    (things[item]["count"], name, desc)
                                ]
                            else:
                                count = things[
                                    item] if thing == 'assemblies' else things[
                                        item]["count"]
                                body += ['| %3d | %s |' % (count, name)]
                        body += ['']

            body += ['\n<a href="#top">Top</a>']
            body += ["\n---"]

    for test in done:
        if test in tests:
            tests.remove(test)
    if tests:
        for test in tests:
            print(Fore.MAGENTA + "Could not find a test called", test,
                  Fore.WHITE)
        usage()

    with open(doc_name, "wt") as doc_file:
        print(lib_blurb, file=doc_file)
        print('## Table of Contents<a name="top"/>', file=doc_file)
        print('<table><tr>', file=doc_file)
        n = 0
        for type in types:
            print('<th align="left"> %s </th>' % type, end='', file=doc_file)
            n = max(n, len(index[type]))
        print('</tr>', file=doc_file)
        for i in range(n):
            print('<tr>', file=doc_file, end='')
            for type in types:
                if i < len(index[type]):
                    name = sorted(index[type])[i]
                    print('<td> <a href = "#' + name + '">' + name +
                          '</a> </td>',
                          file=doc_file,
                          end='')
                else:
                    print('<td></td>', file=doc_file, end='')
            print('</tr>', file=doc_file)
        print('</table>\n\n---', file=doc_file)
        for type in types:
            for line in bodies[type]:
                print(line, file=doc_file)
    with open(doc_base_name + ".html", "wt") as html_file:
        do_cmd(("python -m markdown -x tables " + doc_name).split(), html_file)
    times.print_times()
    do_cmd(('codespell -L od ' + doc_name).split())