diff --git a/src/octoprint/__main__.py b/src/octoprint/__main__.py new file mode 100644 index 00000000..3dd81998 --- /dev/null +++ b/src/octoprint/__main__.py @@ -0,0 +1,7 @@ +#!/usr/bin/env python2 +# coding=utf-8 +from __future__ import absolute_import, division, print_function + +if __name__ == "__main__": + import octoprint + octoprint.main() diff --git a/src/octoprint/cli/__init__.py b/src/octoprint/cli/__init__.py index 7a4133ce..1cc3d82e 100644 --- a/src/octoprint/cli/__init__.py +++ b/src/octoprint/cli/__init__.py @@ -135,9 +135,10 @@ from .plugins import plugin_commands from .dev import dev_commands from .client import client_commands from .config import config_commands +from .analysis import analysis_commands @click.group(name="octoprint", invoke_without_command=True, cls=click.CommandCollection, - sources=[server_commands, plugin_commands, dev_commands, client_commands, config_commands]) + sources=[server_commands, plugin_commands, dev_commands, client_commands, config_commands, analysis_commands]) @standard_options() @legacy_options @click.version_option(version=octoprint.__version__, allow_from_autoenv=False) diff --git a/src/octoprint/cli/analysis.py b/src/octoprint/cli/analysis.py new file mode 100644 index 00000000..34c90d78 --- /dev/null +++ b/src/octoprint/cli/analysis.py @@ -0,0 +1,73 @@ +# coding=utf-8 +from __future__ import absolute_import, division, print_function + +__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' +__copyright__ = "Copyright (C) 2017 The OctoPrint Project - Released under terms of the AGPLv3 License" + +import click + +#~~ "octoprint util" commands + +@click.group() +def analysis_commands(): + pass + +@analysis_commands.group(name="analysis") +def util(): + """Analysis tools.""" + pass + + +@util.command(name="gcode") +@click.option("--throttle", "throttle", type=float, default=None) +@click.option("--throttle-lines", "throttle_lines", type=int, default=None) +@click.option("--speed-x", "speedx", type=float, default=6000) +@click.option("--speed-y", "speedy", type=float, default=6000) +@click.option("--speed-z", "speedz", type=float, default=300) +@click.option("--offset", "offset", type=(float, float), multiple=True) +@click.option("--max-t", "maxt", type=int, default=10) +@click.option("--g90-extruder", "g90_extruder", is_flag=True) +@click.option("--progress", "progress", is_flag=True) +@click.argument("path", type=click.Path()) +def gcode_command(path, speedx, speedy, speedz, offset, maxt, throttle, throttle_lines, g90_extruder, progress): + """Runs a GCODE file analysis.""" + + import time + import yaml + from octoprint.util.gcodeInterpreter import gcode + + throttle_callback = None + if throttle: + def throttle_callback(filePos, readBytes): + if filePos % throttle_lines == 0: + # only apply throttle every $throttle_lines lines + time.sleep(throttle) + + offsets = offset + if offsets is None: + offsets = [] + elif isinstance(offset, tuple): + offsets = list(offsets) + offsets = [(0, 0)] + offsets + if len(offsets) < maxt: + offsets += [(0, 0)] * (maxt - len(offsets)) + + start_time = time.time() + + progress_callback = None + if progress: + def progress_callback(percentage): + click.echo("PROGRESS:{}".format(percentage)) + interpreter = gcode(progress_callback=progress_callback) + + interpreter.load(path, + speedx=speedx, + speedy=speedy, + offsets=offsets, + throttle=throttle_callback, + max_extruders=maxt, + g90_extruder=g90_extruder) + + click.echo("DONE:{}s".format(time.time() - start_time)) + click.echo("RESULTS:") + click.echo(yaml.safe_dump(interpreter.get_result(), default_flow_style=False, indent=" ", allow_unicode=True)) diff --git a/src/octoprint/filemanager/analysis.py b/src/octoprint/filemanager/analysis.py index 33a7a2e8..9c913d81 100644 --- a/src/octoprint/filemanager/analysis.py +++ b/src/octoprint/filemanager/analysis.py @@ -324,8 +324,8 @@ class GcodeAnalysisQueue(AbstractAnalysisQueue): speedy = self._current.printer_profile["axes"]["y"]["speed"] offsets = self._current.printer_profile["extruder"]["offsets"] - interpreter = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", "util", "gcodeInterpreter.py")) - command = [sys.executable, interpreter, "--speed-x={}".format(speedx), "--speed-y={}".format(speedy), + command = [sys.executable, "-m", "octoprint", "analysis", "gcode", + "--speed-x={}".format(speedx), "--speed-y={}".format(speedy), "--max-t={}".format(max_extruders), "--throttle={}".format(throttle), "--throttle-lines={}".format(throttle_lines)] for offset in offsets[1:]: diff --git a/src/octoprint/util/gcodeInterpreter.py b/src/octoprint/util/gcodeInterpreter.py index 2e8f62df..061564ce 100644 --- a/src/octoprint/util/gcodeInterpreter.py +++ b/src/octoprint/util/gcodeInterpreter.py @@ -512,85 +512,3 @@ def getCodeFloat(line, code): except: return None -if __name__ == "__main__": - import click - import time - import yaml - import sys - - @click.command() - @click.option("--throttle", "throttle", type=float, default=None) - @click.option("--throttle-lines", "throttle_lines", type=int, default=None) - @click.option("--speed-x", "speedx", type=float, default=6000) - @click.option("--speed-y", "speedy", type=float, default=6000) - @click.option("--speed-z", "speedz", type=float, default=300) - @click.option("--offset", "offset", type=(float, float), multiple=True) - @click.option("--max-t", "maxt", type=int, default=10) - @click.option("--g90-extruder", "g90_extruder", is_flag=True) - @click.option("--progress", "progress", is_flag=True) - @click.argument("path", type=click.Path()) - def main(path, speedx, speedy, speedz, offset, maxt, throttle, throttle_lines, g90_extruder, progress): - throttle_callback = None - if throttle: - def throttle_callback(filePos, readBytes): - if filePos % throttle_lines == 0: - # only apply throttle every $throttle_lines lines - time.sleep(throttle) - - offsets = offset - if offsets is None: - offsets = [] - elif isinstance(offset, tuple): - offsets = list(offsets) - offsets = [(0, 0)] + offsets - if len(offsets) < maxt: - offsets += [(0, 0)] * (maxt - len(offsets)) - - start_time = time.time() - - progress_callback = None - if progress: - def progress_callback(percentage): - print("PROGRESS:{}".format(percentage)) - interpreter = gcode(progress_callback=progress_callback) - - interpreter.load(path, - speedx=speedx, - speedy=speedy, - offsets=offsets, - throttle=throttle_callback, - max_extruders=maxt, - g90_extruder=g90_extruder) - - print("DONE:{}s".format(time.time() - start_time)) - print("RESULTS:") - print(yaml.safe_dump(interpreter.get_result(), default_flow_style=False, indent=" ", allow_unicode=True)) - - # os args are gained differently on win32 - try: - from click.utils import get_os_args - args = get_os_args() - except ImportError: - # for whatever reason we are running an older Click version? - args = sys.argv[1:] - - if len(args) >= len(sys.argv): - # Now some ugly preprocessing of our arguments starts. We have a somewhat difficult situation on our hands - # here if we are running under Windows and want to be able to handle utf-8 command line parameters (think - # plugin parameters such as names or something, e.g. for the "dev plugin:new" command) while at the same - # time also supporting sys.argv rewriting for debuggers etc (e.g. PyCharm). - # - # So what we try to do here is solve this... Generally speaking, sys.argv and whatever Windows returns - # for its CommandLineToArgvW win32 function should have the same length. If it doesn't however and - # sys.argv is shorter than the win32 specific command line arguments, obviously stuff was cut off from - # sys.argv which also needs to be cut off of the win32 command line arguments. - # - # So this is what we do here. - - # -1 because first entry is the script that was called - sys_args_length = len(sys.argv) - 1 - - # cut off stuff from the beginning - args = args[-1 * sys_args_length:] if sys_args_length else [] - - main(args=args, prog_name="octoprint-gcode-analysis")