#!/usr/bin/python3 import sys import argparse import cgi import tempfile import os import threading import time # Python 2 vs Python 3 compat try: from urllib.parse import unquote_plus except ImportError: from urllib import unquote_plus from wsgiref.util import setup_testing_defaults from wsgiref.simple_server import make_server import wsgiref.util try: import boxes.generators except ImportError: sys.path.append(os.path.dirname(__file__) + "/..") import boxes.generators from boxes.generators import box, box2, box3, drillbox from boxes.generators import flexbox, flexbox2, flexbox3, flexbox4 from boxes.generators import flextest, folder from boxes.generators import magazinefile, trayinsert, traylayout, typetray, silverwarebox class FileChecker(threading.Thread): def __init__(self, files=[], checkmodules=True): super(FileChecker, self).__init__() self.checkmodules = checkmodules self.timestamps = {} for path in files: self.timestamps[path] = os.stat(path).st_mtime if checkmodules: self._addModules() def _addModules(self): for name, module in sys.modules.items(): path = getattr(module, "__file__", None) if not path: continue if path not in self.timestamps: self.timestamps[path] = os.stat(path).st_mtime def filesOK(self): if self.checkmodules: self._addModules() for path, timestamp in self.timestamps.items(): try: if os.stat(path).st_mtime != timestamp: return False except FileNotFoundError: return False return True def run(self): while True: if not self.filesOK(): os.execv(__file__, sys.argv) time.sleep(1) class ArgumentParserError(Exception): pass class ThrowingArgumentParser(argparse.ArgumentParser): def error(self, message): raise ArgumentParserError(message) boxes.ArgumentParser = ThrowingArgumentParser # Evil hack class BServer: def __init__(self): self.boxes = { "Box" : box.Box(), "Box2" : box2.Box(), "Box3" : box3.Box(), "DrillBox" : drillbox.Box(), "FlexBox" : flexbox.FlexBox(), "FlexBox2" : flexbox2.FlexBox(), "FlexBox3" : flexbox3.FlexBox(), "FlexBox4" : flexbox4.FlexBox(), "FlexTest": flextest.FlexTest(), "Folder": folder.Folder(), "MagazinFile" : magazinefile.Box(), "TrayInsert" : trayinsert.TrayInsert(), "TypeTray" : typetray.TypeTray(), "SilverwareBox" : silverwarebox.Silverware(), "TrayLayout" : traylayout.LayoutGenerator(), "TrayLayout2" : traylayout.Layout(webargs=True), } def arg2html(self, a): name = a.option_strings[0].replace("-", "") if isinstance(a, argparse._HelpAction): return "" row = """%s%%s%s\n""" % \ (name, a.help or "") if (isinstance(a, argparse._StoreAction) and isinstance(a.type, boxes.ArgparseEdgeType)): input = a.type.html(name, a.default) elif a.dest == "layout": val = a.default.split("\n") input = """""" % \ (name, max((len(l) for l in val))+10, len(val)+1, a.default) elif a.type is bool: input = """""" % \ (name, ) elif a.choices: options = "\n".join( ("""""" % (e, ' selected="selected"' if e == a.default else "", e) for e in a.choices)) input = """\n""" % (name, options) else: input = """""" % \ (name, a.default) return row % input def args2html(self, name, box, action=""): result = ["""Boxes - """, name, """

""", name, """

""", box.__doc__, """

""" % (action)] for a in box.argparser._actions: if a.dest in ("input", "output"): continue result.append(self.arg2html(a)) if a.dest == "burn": result.append("
\n
\n\n") result.append("""

""") return (s.encode("utf-8") for s in result) def menu(self): result = [""" Boxes.py

Boxes.py

A Python based generator for laser cut boxes and other things.

It features both finished parametrized generators as well as a Python API for writing your own scripts. It features finger and (flat) dovetail joints, flex cuts, holes and slots for screws and more high level functions.

These are the available generators: