diff --git a/octoprint/cura/__init__.py b/octoprint/cura/__init__.py index 7b60968d..d44d1f20 100644 --- a/octoprint/cura/__init__.py +++ b/octoprint/cura/__init__.py @@ -37,7 +37,6 @@ class CuraEngine(object): self, config, gcode, file_path, call_back=None, call_back_args=None): - from octoprint.cura import parser """Wraps around the main.cpp processFile method. :param config: :class: `string` :path to a cura config file: @@ -48,27 +47,21 @@ class CuraEngine(object): """ import threading - def start_thread(call_back, call_back_args, call_args): + def start_thread(call_back, call_back_args, call_args, cwd): import subprocess - logging.info("Starting SubProcess in Thread") + logging.info("Starting SubProcess in Thread %s", str(cwd)) logging.info("Subprocess args: %s" % str(call_args)) - process = subprocess.call(call_args) + process = subprocess.call(call_args, cwd=cwd) call_back(*call_back_args) logging.info("Slicing call back complete:%s" % str(call_back)) - args = [self.cura_path, '-o', gcode] + args = ['python', '-m', 'Cura.cura', '-i', config, '-s', file_path, '-o', gcode] - settings = parser.process_profile_ini(config) - - args.extend(settings) - - args.extend([file_path]) - - logging.info('CuraEngine args:%s' % str(args)) + logging.info('Cura args:%s' % str(args)) thread = threading.Thread(target=start_thread, args=(call_back, - call_back_args, args)) + call_back_args, args, self.cura_path)) thread.start() - logging.info('CuraEngine Slicing File:%s' % file_path) + logging.info('Cura Slicing File:%s' % file_path) diff --git a/octoprint/cura/parser.py b/octoprint/cura/parser.py deleted file mode 100644 index 86e509fa..00000000 --- a/octoprint/cura/parser.py +++ /dev/null @@ -1,147 +0,0 @@ -import logging -from StringIO import StringIO - - -def process_profile_ini(filename): - """Builds the array that needs to be sent to the subprocess call. - - :param filename: :class: `str` - - :note: The filename should be the full path to the profile.ini - """ - - if not filename: - raise ValueError("No file name to process") - - # This made it easier to mock and test - profile = read_filename(filename) - data = {} - - logging.info("Processing %s" % filename) - for line in profile: - if _is_multi_start(line): - read_multi_line(line, profile, data) - - if _is_single(line): - data = process_setting_line(data, line) - - return format_data_for_command(data) - -def read_multi_line(line, profile, data): - - multi_line = line - - line = profile.readline() - if _is_multi_continue(line): - multi_line += line - - if _is_single(line): - data = process_setting_line(data, multi_line) - data = process_setting_line(data, line) - return - - while(_is_multi_continue(line)): - - line = profile.readline() - if not line: - break - - if _is_single(line): - data = process_setting_line(data, line) - break - - if _is_multi_start(line): - read_multi_line(line, profile, data) - break - - multi_line += line - - data = process_multi_setting_line(data, multi_line) - - - - -def process_multi_setting_line(data, multi_line): - - data = process_setting_line(data, multi_line) - return data - - -def process_setting_line(data, setting_line): - """Adds to the data dictionary a converted to camel case version of the - variable name as the key and the value as the parameter's value. - - :param data: :class: `dict` - :param setting_line: :class: `str` - """ - - if not data: - data = {} - - if not setting_line: - return data - - # TODO: Make this more fault tolerant - - # Changes var_with_underscore to varWithUnderscore - split = setting_line.split("=") - variable_parts = split[0].split("_") - end_variable_parts = ''.join(word.title() for word in variable_parts[1:]) - - new_name = (str(variable_parts[0]) + end_variable_parts).strip() - new_value = split[1].strip() - - if '.gcode' in new_name: - new_name = new_name.replace('.gcode', 'Code') - - # might need to surround the value in quotes? - #new_value = "'" + new_value + "'" - - data[new_name] = new_value - - return data - - -def format_data_for_command(data): - """Takes the data parsed from the file and formats it for the command line - - :param data: :class: `dict` - - :returns: :class: `list` of :class: `str` - """ - - if not data: - raise ValueError("Data not found") - - result = [] - - for key, value in data.iteritems(): - result.extend(['-s', '%s=%s' % (key, str(value))]) - - return result - - -def read_filename(filename): - - lines = open(filename, 'r').read() - return StringIO(lines) - -def _is_multi_start(line): - - if '.gcode' in line or "=" in line and "(lp" in line: - return True - -def _is_multi_continue(line): - - if '=' not in line: - return True - - if '.gcode' not in line and '=' not in line: - return True - -def _is_single(line): - - if '=' in line and '.gcode' not in line: - return True - - diff --git a/octoprint/cura/tests/test_parser.py b/octoprint/cura/tests/test_parser.py deleted file mode 100644 index 4eb29702..00000000 --- a/octoprint/cura/tests/test_parser.py +++ /dev/null @@ -1,122 +0,0 @@ -import logging -import unittest -from StringIO import StringIO -import io - - -from mock import patch -from mock import MagicMock -from mock import Mock - -class ParserTestCase(unittest.TestCase): - - def setUp(self): - - self.setting_string = """ -[profile] -layer_height = 0.1 -retraction_enable = False -solid_layer_thickness = 0.6 -end4.gcode = ;end gcode -nozzle_size = 0.5 -print_speed = 50 -end.gcode = ;End gcode - M102 T0 ; whatever -print_temperature = 220 -print_temperature2 = 0 -start2.gcode = ;Sliced at: {day} {date} {time} - ;Basic settings: Layer height: {layer_height} Walls: {wall_thickness} Fill: {fill_density} - ;Print time: {print_time} - ;Filament used: {filament_amount}m {filament_weight}g - ;Filament cost: {filament_cost} - G21 ;metric values - G90 ;absolute positioning - M107 ;start with the fan off - G28 X0 Y0 ;move X/Y to min endstops - M117 Printing... -end2.gcode = ;End GCode - M104 T0 S0 ;extruder heater off - M104 T1 S0 ;extruder heater off - M140 S0 ;heated bed heater off (if you have it) - G91 ;relative positioning - G1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure - G1 Z+0.5 E-5 X-20 Y-20 F{travel_speed} ;move Z up a bit and retract filament even more - G28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way - M84 ;steppers off - G90 ;absolute positioning -print_temperature3 = 0 -""" - - @patch('octoprint.cura.parser.read_filename') - def test_process_profile_ini(self, open_f): - - from octoprint.cura.parser import process_profile_ini - - open_f.return_value = StringIO(self.setting_string) - - result = process_profile_ini('fake_filename') - - logging.info(str(result)) - - expected = len([line for line in self.setting_string if '=' in line])*2 - self.assertEqual(len(result), expected) - - def test_is_mult_line(self): - - from octoprint.cura.parser import _is_multi_start - test = "cool_end_start = 1.0" - - self.assertFalse(_is_multi_start(test)) - - test = "G92 E0" - - self.assertFalse(_is_multi_start(test)) - - test = "start2.gcode = ;Sliced at:" - - self.assertTrue(_is_multi_start(test)) - - test = "plugin_config = (lp1" - - self.assertTrue(_is_multi_start(test)) - - - def test_is_single_line(self): - - from octoprint.cura.parser import _is_single - test = "cool_end_start = 1.0" - - self.assertTrue(_is_single(test)) - - test = "G92 E0" - - self.assertFalse(_is_single(test)) - - - def test_process_setting_line(self): - - from octoprint.cura.parser import process_setting_line - - setting_line = "print_speed_size2 = 3.22" - - data = {} - - data = process_setting_line(data, setting_line) - - logging.info(data) - self.assertEqual(len(data.values()), 1) - - def test_format_command(self): - - from octoprint.cura.parser import format_data_for_command - - data = {'layerHeight': '0.1', - 'printTemperature': '220'} - - result = [] - - result = format_data_for_command(data) - - self.assertIsNotNone(result) - self.assertEqual(len(result), len(data.values()) * 2) -