def gcodeFileCommand(filename, target): if not target in [FileDestinations.LOCAL, FileDestinations.SDCARD]: return make_response("Unknown target: %s" % target, 404) # valid file commands, dict mapping command name to mandatory parameters valid_commands = { "select": [], "slice": [], "copy": ["destination"], "move": ["destination"] } command, data, response = get_json_command_from_request(request, valid_commands) if response is not None: return response if command == "select": if not _verifyFileExists(target, filename): return make_response("File not found on '%s': %s" % (target, filename), 404) # selects/loads a file if not octoprint.filemanager.valid_file_type(filename, type="machinecode"): return make_response("Cannot select {filename} for printing, not a machinecode file".format(**locals()), 415) printAfterLoading = False if "print" in data.keys() and data["print"] in valid_boolean_trues: if not printer.is_operational(): return make_response("Printer is not operational, cannot directly start printing", 409) printAfterLoading = True sd = False if target == FileDestinations.SDCARD: filenameToSelect = filename sd = True else: filenameToSelect = fileManager.path_on_disk(target, filename) printer.select_file(filenameToSelect, sd, printAfterLoading) elif command == "slice": if not _verifyFileExists(target, filename): return make_response("File not found on '%s': %s" % (target, filename), 404) try: if "slicer" in data: slicer = data["slicer"] del data["slicer"] slicer_instance = slicingManager.get_slicer(slicer) elif "cura" in slicingManager.registered_slicers: slicer = "cura" slicer_instance = slicingManager.get_slicer("cura") else: return make_response("Cannot slice {filename}, no slicer available".format(**locals()), 415) except octoprint.slicing.UnknownSlicer as e: return make_response("Slicer {slicer} is not available".format(slicer=e.slicer), 400) if not any([octoprint.filemanager.valid_file_type(filename, type=source_file_type) for source_file_type in slicer_instance.get_slicer_properties().get("source_file_types", ["model"])]): return make_response("Cannot slice {filename}, not a model file".format(**locals()), 415) if slicer_instance.get_slicer_properties().get("same_device", True) and (printer.is_printing() or printer.is_paused()): # slicer runs on same device as OctoPrint, slicing while printing is hence disabled return make_response("Cannot slice on {slicer} while printing due to performance reasons".format(**locals()), 409) if "destination" in data and data["destination"]: destination = data["destination"] del data["destination"] elif "gcode" in data and data["gcode"]: destination = data["gcode"] del data["gcode"] else: import os name, _ = os.path.splitext(filename) destination = name + "." + slicer_instance.get_slicer_properties().get("destination_extensions", ["gco", "gcode", "g"])[0] full_path = destination if "path" in data and data["path"]: full_path = fileManager.join_path(target, data["path"], destination) else: path, _ = fileManager.split_path(target, filename) if path: full_path = fileManager.join_path(target, path, destination) # prohibit overwriting the file that is currently being printed currentOrigin, currentFilename = _getCurrentFile() if currentFilename == full_path and currentOrigin == target and (printer.is_printing() or printer.is_paused()): make_response("Trying to slice into file that is currently being printed: %s" % full_path, 409) if "profile" in data.keys() and data["profile"]: profile = data["profile"] del data["profile"] else: profile = None if "printerProfile" in data.keys() and data["printerProfile"]: printerProfile = data["printerProfile"] del data["printerProfile"] else: printerProfile = None if "position" in data.keys() and data["position"] and isinstance(data["position"], dict) and "x" in data["position"] and "y" in data["position"]: position = data["position"] del data["position"] else: position = None select_after_slicing = False if "select" in data.keys() and data["select"] in valid_boolean_trues: if not printer.is_operational(): return make_response("Printer is not operational, cannot directly select for printing", 409) select_after_slicing = True print_after_slicing = False if "print" in data.keys() and data["print"] in valid_boolean_trues: if not printer.is_operational(): return make_response("Printer is not operational, cannot directly start printing", 409) select_after_slicing = print_after_slicing = True override_keys = [k for k in data if k.startswith("profile.") and data[k] is not None] overrides = dict() for key in override_keys: overrides[key[len("profile."):]] = data[key] def slicing_done(target, path, select_after_slicing, print_after_slicing): if select_after_slicing or print_after_slicing: sd = False if target == FileDestinations.SDCARD: filenameToSelect = path sd = True else: filenameToSelect = fileManager.path_on_disk(target, path) printer.select_file(filenameToSelect, sd, print_after_slicing) try: fileManager.slice(slicer, target, filename, target, full_path, profile=profile, printer_profile_id=printerProfile, position=position, overrides=overrides, callback=slicing_done, callback_args=(target, full_path, select_after_slicing, print_after_slicing)) except octoprint.slicing.UnknownProfile: return make_response("Profile {profile} doesn't exist".format(**locals()), 400) files = {} location = url_for(".readGcodeFile", target=target, filename=full_path, _external=True) result = { "name": destination, "path": full_path, "origin": FileDestinations.LOCAL, "refs": { "resource": location, "download": url_for("index", _external=True) + "downloads/files/" + target + "/" + full_path } } r = make_response(jsonify(result), 202) r.headers["Location"] = location return r elif command == "copy" or command == "move": # Copy and move are only possible on local storage if not target in [FileDestinations.LOCAL]: return make_response("Unsupported target for {}: {}".format(command, target), 400) if not _verifyFileExists(target, filename) and not _verifyFolderExists(target, filename): return make_response("File or folder not found on {}: {}".format(target, filename), 404) path, name = fileManager.split_path(target, filename) destination = data["destination"] if _verifyFolderExists(target, destination): # destination is an existing folder, we'll assume we are supposed to move filename to this # folder under the same name destination = fileManager.join_path(target, destination, name) if _verifyFileExists(target, destination) or _verifyFolderExists(target, destination): return make_response("File or folder does already exist on {}: {}".format(target, destination), 409) is_file = fileManager.file_exists(target, filename) is_folder = fileManager.folder_exists(target, filename) if not (is_file or is_folder): return make_response("{} on {} is neither file or folder, can't {}".format(filename, target, command), 400) if command == "copy": if is_file: fileManager.copy_file(target, filename, destination) else: fileManager.copy_folder(target, filename, destination) elif command == "move": if _isBusy(target, filename): return make_response("Trying to move a file or folder that is currently in use: {}".format(filename), 409) # deselect the file if it's currently selected currentOrigin, currentFilename = _getCurrentFile() if currentFilename is not None and filename == currentFilename: printer.unselect_file() if is_file: fileManager.move_file(target, filename, destination) else: fileManager.move_folder(target, filename, destination) location = url_for(".readGcodeFile", target=target, filename=destination, _external=True) result = { "name": name, "path": destination, "origin": FileDestinations.LOCAL, "refs": { "resource": location } } if is_file: result["refs"]["download"] = url_for("index", _external=True) + "downloads/files/" + target + "/" + destination r = make_response(jsonify(result), 201) r.headers["Location"] = location return r return NO_CONTENT
def gcodeFileCommand(filename, target): if not target in [FileDestinations.LOCAL, FileDestinations.SDCARD]: return make_response("Unknown target: %s" % target, 404) # valid file commands, dict mapping command name to mandatory parameters valid_commands = { "select": [], "slice": [], "analyse": [], "copy": ["destination"], "move": ["destination"] } command, data, response = get_json_command_from_request(request, valid_commands) if response is not None: return response user = current_user.get_name() if command == "select": if not _verifyFileExists(target, filename): return make_response("File not found on '%s': %s" % (target, filename), 404) # selects/loads a file if not octoprint.filemanager.valid_file_type(filename, type="machinecode"): return make_response("Cannot select {filename} for printing, not a machinecode file".format(**locals()), 415) printAfterLoading = False if "print" in data.keys() and data["print"] in valid_boolean_trues: if not printer.is_operational(): return make_response("Printer is not operational, cannot directly start printing", 409) printAfterLoading = True sd = False if target == FileDestinations.SDCARD: filenameToSelect = filename sd = True else: filenameToSelect = fileManager.path_on_disk(target, filename) printer.select_file(filenameToSelect, sd, printAfterLoading, user) elif command == "slice": if not _verifyFileExists(target, filename): return make_response("File not found on '%s': %s" % (target, filename), 404) try: if "slicer" in data: slicer = data["slicer"] del data["slicer"] slicer_instance = slicingManager.get_slicer(slicer) elif "cura" in slicingManager.registered_slicers: slicer = "cura" slicer_instance = slicingManager.get_slicer("cura") else: return make_response("Cannot slice {filename}, no slicer available".format(**locals()), 415) except octoprint.slicing.UnknownSlicer as e: return make_response("Slicer {slicer} is not available".format(slicer=e.slicer), 400) if not any([octoprint.filemanager.valid_file_type(filename, type=source_file_type) for source_file_type in slicer_instance.get_slicer_properties().get("source_file_types", ["model"])]): return make_response("Cannot slice {filename}, not a model file".format(**locals()), 415) if slicer_instance.get_slicer_properties().get("same_device", True) and (printer.is_printing() or printer.is_paused()): # slicer runs on same device as OctoPrint, slicing while printing is hence disabled return make_response("Cannot slice on {slicer} while printing due to performance reasons".format(**locals()), 409) if "destination" in data and data["destination"]: destination = data["destination"] del data["destination"] elif "gcode" in data and data["gcode"]: destination = data["gcode"] del data["gcode"] else: import os name, _ = os.path.splitext(filename) destination = name + "." + slicer_instance.get_slicer_properties().get("destination_extensions", ["gco", "gcode", "g"])[0] full_path = destination if "path" in data and data["path"]: full_path = fileManager.join_path(target, data["path"], destination) else: path, _ = fileManager.split_path(target, filename) if path: full_path = fileManager.join_path(target, path, destination) canon_path, canon_name = fileManager.canonicalize(target, full_path) sanitized_name = fileManager.sanitize_name(target, canon_name) if canon_path: full_path = fileManager.join_path(target, canon_path, sanitized_name) else: full_path = sanitized_name # prohibit overwriting the file that is currently being printed currentOrigin, currentFilename = _getCurrentFile() if currentFilename == full_path and currentOrigin == target and (printer.is_printing() or printer.is_paused()): make_response("Trying to slice into file that is currently being printed: %s" % full_path, 409) if "profile" in data.keys() and data["profile"]: profile = data["profile"] del data["profile"] else: profile = None if "printerProfile" in data.keys() and data["printerProfile"]: printerProfile = data["printerProfile"] del data["printerProfile"] else: printerProfile = None if "position" in data.keys() and data["position"] and isinstance(data["position"], dict) and "x" in data["position"] and "y" in data["position"]: position = data["position"] del data["position"] else: position = None select_after_slicing = False if "select" in data.keys() and data["select"] in valid_boolean_trues: if not printer.is_operational(): return make_response("Printer is not operational, cannot directly select for printing", 409) select_after_slicing = True print_after_slicing = False if "print" in data.keys() and data["print"] in valid_boolean_trues: if not printer.is_operational(): return make_response("Printer is not operational, cannot directly start printing", 409) select_after_slicing = print_after_slicing = True override_keys = [k for k in data if k.startswith("profile.") and data[k] is not None] overrides = dict() for key in override_keys: overrides[key[len("profile."):]] = data[key] def slicing_done(target, path, select_after_slicing, print_after_slicing): if select_after_slicing or print_after_slicing: sd = False if target == FileDestinations.SDCARD: filenameToSelect = path sd = True else: filenameToSelect = fileManager.path_on_disk(target, path) printer.select_file(filenameToSelect, sd, print_after_slicing, user) try: fileManager.slice(slicer, target, filename, target, full_path, profile=profile, printer_profile_id=printerProfile, position=position, overrides=overrides, display=canon_name, callback=slicing_done, callback_args=(target, full_path, select_after_slicing, print_after_slicing)) except octoprint.slicing.UnknownProfile: return make_response("Profile {profile} doesn't exist".format(**locals()), 400) files = {} location = url_for(".readGcodeFile", target=target, filename=full_path, _external=True) result = { "name": sanitized_name, "path": full_path, "display": canon_name, "origin": FileDestinations.LOCAL, "refs": { "resource": location, "download": url_for("index", _external=True) + "downloads/files/" + target + "/" + full_path } } r = make_response(jsonify(result), 202) r.headers["Location"] = location return r elif command == "analyse": if not _verifyFileExists(target, filename): return make_response("File not found on '%s': %s" % (target, filename), 404) printer_profile = None if "printerProfile" in data and data["printerProfile"]: printer_profile = data["printerProfile"] if not fileManager.analyse(target, filename, printer_profile_id=printer_profile): return make_response("No analysis possible for {} on {}".format(filename, target), 400) elif command == "copy" or command == "move": # Copy and move are only possible on local storage if not target in [FileDestinations.LOCAL]: return make_response("Unsupported target for {}: {}".format(command, target), 400) if not _verifyFileExists(target, filename) and not _verifyFolderExists(target, filename): return make_response("File or folder not found on {}: {}".format(target, filename), 404) path, name = fileManager.split_path(target, filename) destination = data["destination"] dst_path, dst_name = fileManager.split_path(target, destination) sanitized_destination = fileManager.join_path(target, dst_path, fileManager.sanitize_name(target, dst_name)) if _verifyFolderExists(target, destination) and sanitized_destination != filename: # destination is an existing folder and not ourselves (= display rename), we'll assume we are supposed # to move filename to this folder under the same name destination = fileManager.join_path(target, destination, name) is_file = fileManager.file_exists(target, filename) is_folder = fileManager.folder_exists(target, filename) if not (is_file or is_folder): return make_response("{} on {} is neither file or folder, can't {}".format(filename, target, command), 400) if command == "copy": # destination already there? error... if _verifyFileExists(target, destination) or _verifyFolderExists(target, destination): return make_response("File or folder does already exist on {}: {}".format(target, destination), 409) if is_file: fileManager.copy_file(target, filename, destination) else: fileManager.copy_folder(target, filename, destination) elif command == "move": if _isBusy(target, filename): return make_response("Trying to move a file or folder that is currently in use: {}".format(filename), 409) # destination already there AND not ourselves (= display rename)? error... if (_verifyFileExists(target, destination) or _verifyFolderExists(target, destination)) \ and sanitized_destination != filename: return make_response("File or folder does already exist on {}: {}".format(target, destination), 409) # deselect the file if it's currently selected currentOrigin, currentFilename = _getCurrentFile() if currentFilename is not None and filename == currentFilename: printer.unselect_file() if is_file: fileManager.move_file(target, filename, destination) else: fileManager.move_folder(target, filename, destination) location = url_for(".readGcodeFile", target=target, filename=destination, _external=True) result = { "name": name, "path": destination, "origin": FileDestinations.LOCAL, "refs": { "resource": location } } if is_file: result["refs"]["download"] = url_for("index", _external=True) + "downloads/files/" + target + "/" + destination r = make_response(jsonify(result), 201) r.headers["Location"] = location return r return NO_CONTENT
def gcodeFileCommand(filename, target): if not target in [FileDestinations.LOCAL, FileDestinations.SDCARD]: return make_response("Unknown target: %s" % target, 404) if not _verifyFileExists(target, filename): return make_response("File not found on '%s': %s" % (target, filename), 404) # valid file commands, dict mapping command name to mandatory parameters valid_commands = { "select": [], "slice": [] } command, data, response = get_json_command_from_request(request, valid_commands) if response is not None: return response if command == "select": # selects/loads a file printAfterLoading = False if "print" in data.keys() and data["print"] in valid_boolean_trues: if not printer.is_operational(): return make_response("Printer is not operational, cannot directly start printing", 409) printAfterLoading = True sd = False if target == FileDestinations.SDCARD: filenameToSelect = filename sd = True else: filenameToSelect = fileManager.path_on_disk(target, filename) printer.select_file(filenameToSelect, sd, printAfterLoading) elif command == "slice": try: if "slicer" in data: slicer = data["slicer"] del data["slicer"] slicer_instance = slicingManager.get_slicer(slicer) elif "cura" in slicingManager.registered_slicers: slicer = "cura" slicer_instance = slicingManager.get_slicer("cura") else: return make_response("Cannot slice {filename}, no slicer available".format(**locals()), 415) except octoprint.slicing.UnknownSlicer as e: return make_response("Slicer {slicer} is not available".format(slicer=e.slicer), 400) if not any([octoprint.filemanager.valid_file_type(filename, type=source_file_type) for source_file_type in slicer_instance.get_slicer_properties().get("source_file_types", ["model"])]): return make_response("Cannot slice {filename}, not a model file".format(**locals()), 415) if slicer_instance.get_slicer_properties().get("same_device", True) and (printer.is_printing() or printer.is_paused()): # slicer runs on same device as OctoPrint, slicing while printing is hence disabled return make_response("Cannot slice on {slicer} while printing due to performance reasons".format(**locals()), 409) if "destination" in data and data["destination"]: destination = data["destination"] del data["destination"] elif "gcode" in data and data["gcode"]: destination = data["gcode"] del data["gcode"] else: import os name, _ = os.path.splitext(filename) destination = name + "." + slicer_instance.get_slicer_properties().get("destination_extensions", ["gco", "gcode", "g"])[0] # prohibit overwriting the file that is currently being printed currentOrigin, currentFilename = _getCurrentFile() if currentFilename == destination and currentOrigin == target and (printer.is_printing() or printer.is_paused()): make_response("Trying to slice into file that is currently being printed: %s" % destination, 409) if "profile" in data.keys() and data["profile"]: profile = data["profile"] del data["profile"] else: profile = None if "printerProfile" in data.keys() and data["printerProfile"]: printerProfile = data["printerProfile"] del data["printerProfile"] else: printerProfile = None if "position" in data.keys() and data["position"] and isinstance(data["position"], dict) and "x" in data["position"] and "y" in data["position"]: position = data["position"] del data["position"] else: position = None select_after_slicing = False if "select" in data.keys() and data["select"] in valid_boolean_trues: if not printer.is_operational(): return make_response("Printer is not operational, cannot directly select for printing", 409) select_after_slicing = True print_after_slicing = False if "print" in data.keys() and data["print"] in valid_boolean_trues: if not printer.is_operational(): return make_response("Printer is not operational, cannot directly start printing", 409) select_after_slicing = print_after_slicing = True override_keys = [k for k in data if k.startswith("profile.") and data[k] is not None] overrides = dict() for key in override_keys: overrides[key[len("profile."):]] = data[key] def slicing_done(target, gcode_name, select_after_slicing, print_after_slicing): if select_after_slicing or print_after_slicing: sd = False if target == FileDestinations.SDCARD: filenameToSelect = gcode_name sd = True else: filenameToSelect = fileManager.path_on_disk(target, gcode_name) printer.select_file(filenameToSelect, sd, print_after_slicing) try: fileManager.slice(slicer, target, filename, target, destination, profile=profile, printer_profile_id=printerProfile, position=position, overrides=overrides, callback=slicing_done, callback_args=(target, destination, select_after_slicing, print_after_slicing)) except octoprint.slicing.UnknownProfile: return make_response("Profile {profile} doesn't exist".format(**locals()), 400) files = {} location = url_for(".readGcodeFile", target=target, filename=destination, _external=True) result = { "name": destination, "origin": FileDestinations.LOCAL, "refs": { "resource": location, "download": url_for("index", _external=True) + "downloads/files/" + target + "/" + destination } } r = make_response(jsonify(result), 202) r.headers["Location"] = location return r return NO_CONTENT
def gcodeFileCommand(filename, target): if target not in [FileDestinations.LOCAL, FileDestinations.SDCARD]: abort(404) if not _validate(target, filename): abort(404) # valid file commands, dict mapping command name to mandatory parameters valid_commands = { "select": [], "unselect": [], "slice": [], "analyse": [], "copy": ["destination"], "move": ["destination"], } command, data, response = get_json_command_from_request( request, valid_commands) if response is not None: return response user = current_user.get_name() if command == "select": with Permissions.FILES_SELECT.require(403): if not _verifyFileExists(target, filename): abort(404) # selects/loads a file if not octoprint.filemanager.valid_file_type(filename, type="machinecode"): abort( 415, description= "Cannot select file for printing, not a machinecode file", ) if not printer.is_ready(): abort( 409, description= "Printer is already printing, cannot select a new file", ) printAfterLoading = False if "print" in data and data["print"] in valid_boolean_trues: with Permissions.PRINT.require(403): if not printer.is_operational(): abort( 409, description= "Printer is not operational, cannot directly start printing", ) printAfterLoading = True sd = False if target == FileDestinations.SDCARD: filenameToSelect = filename sd = True else: filenameToSelect = fileManager.path_on_disk(target, filename) printer.select_file(filenameToSelect, sd, printAfterLoading, user) elif command == "unselect": with Permissions.FILES_SELECT.require(403): if not printer.is_ready(): return make_response( "Printer is already printing, cannot unselect current file", 409) _, currentFilename = _getCurrentFile() if currentFilename is None: return make_response( "Cannot unselect current file when there is no file selected", 409) if filename != currentFilename and filename != "current": return make_response( "Only the currently selected file can be unselected", 400) printer.unselect_file() elif command == "slice": with Permissions.SLICE.require(403): if not _verifyFileExists(target, filename): abort(404) try: if "slicer" in data: slicer = data["slicer"] del data["slicer"] slicer_instance = slicingManager.get_slicer(slicer) elif "cura" in slicingManager.registered_slicers: slicer = "cura" slicer_instance = slicingManager.get_slicer("cura") else: abort(415, description="Cannot slice file, no slicer available") except octoprint.slicing.UnknownSlicer: abort(404) if not any([ octoprint.filemanager.valid_file_type( filename, type=source_file_type) for source_file_type in slicer_instance. get_slicer_properties().get("source_file_types", ["model"]) ]): abort(415, description="Cannot slice file, not a model file") cores = psutil.cpu_count() if (slicer_instance.get_slicer_properties().get( "same_device", True) and (printer.is_printing() or printer.is_paused()) and (cores is None or cores < 2)): # slicer runs on same device as OctoPrint, slicing while printing is hence disabled abort( 409, description= "Cannot slice on this slicer while printing on single core systems or systems of unknown core count due to performance reasons", ) if "destination" in data and data["destination"]: destination = data["destination"] del data["destination"] elif "gcode" in data and data["gcode"]: destination = data["gcode"] del data["gcode"] else: import os name, _ = os.path.splitext(filename) destination = ( name + "." + slicer_instance.get_slicer_properties().get( "destination_extensions", ["gco", "gcode", "g"])[0]) full_path = destination if "path" in data and data["path"]: full_path = fileManager.join_path(target, data["path"], destination) else: path, _ = fileManager.split_path(target, filename) if path: full_path = fileManager.join_path(target, path, destination) canon_path, canon_name = fileManager.canonicalize( target, full_path) sanitized_name = fileManager.sanitize_name(target, canon_name) if canon_path: full_path = fileManager.join_path(target, canon_path, sanitized_name) else: full_path = sanitized_name # prohibit overwriting the file that is currently being printed currentOrigin, currentFilename = _getCurrentFile() if (currentFilename == full_path and currentOrigin == target and (printer.is_printing() or printer.is_paused())): abort( 409, description= "Trying to slice into file that is currently being printed", ) if "profile" in data and data["profile"]: profile = data["profile"] del data["profile"] else: profile = None if "printerProfile" in data and data["printerProfile"]: printerProfile = data["printerProfile"] del data["printerProfile"] else: printerProfile = None if ("position" in data and data["position"] and isinstance(data["position"], dict) and "x" in data["position"] and "y" in data["position"]): position = data["position"] del data["position"] else: position = None select_after_slicing = False if "select" in data and data["select"] in valid_boolean_trues: if not printer.is_operational(): abort( 409, description= "Printer is not operational, cannot directly select for printing", ) select_after_slicing = True print_after_slicing = False if "print" in data and data["print"] in valid_boolean_trues: if not printer.is_operational(): abort( 409, description= "Printer is not operational, cannot directly start printing", ) select_after_slicing = print_after_slicing = True override_keys = [ k for k in data if k.startswith("profile.") and data[k] is not None ] overrides = {} for key in override_keys: overrides[key[len("profile."):]] = data[key] def slicing_done(target, path, select_after_slicing, print_after_slicing): if select_after_slicing or print_after_slicing: sd = False if target == FileDestinations.SDCARD: filenameToSelect = path sd = True else: filenameToSelect = fileManager.path_on_disk( target, path) printer.select_file(filenameToSelect, sd, print_after_slicing, user) try: fileManager.slice( slicer, target, filename, target, full_path, profile=profile, printer_profile_id=printerProfile, position=position, overrides=overrides, display=canon_name, callback=slicing_done, callback_args=( target, full_path, select_after_slicing, print_after_slicing, ), ) except octoprint.slicing.UnknownProfile: abort(404, description="Unknown profile") location = url_for(".readGcodeFile", target=target, filename=full_path, _external=True) result = { "name": destination, "path": full_path, "display": canon_name, "origin": FileDestinations.LOCAL, "refs": { "resource": location, "download": url_for("index", _external=True) + "downloads/files/" + target + "/" + full_path, }, } r = make_response(jsonify(result), 202) r.headers["Location"] = location return r elif command == "analyse": with Permissions.FILES_UPLOAD.require(403): if not _verifyFileExists(target, filename): abort(404) printer_profile = None if "printerProfile" in data and data["printerProfile"]: printer_profile = data["printerProfile"] if not fileManager.analyse( target, filename, printer_profile_id=printer_profile): abort(400, description="No analysis possible") elif command == "copy" or command == "move": with Permissions.FILES_UPLOAD.require(403): # Copy and move are only possible on local storage if target not in [FileDestinations.LOCAL]: abort(400, description="Unsupported target for {}".format(command)) if not _verifyFileExists(target, filename) and not _verifyFolderExists( target, filename): abort(404) path, name = fileManager.split_path(target, filename) destination = data["destination"] dst_path, dst_name = fileManager.split_path(target, destination) sanitized_destination = fileManager.join_path( target, dst_path, fileManager.sanitize_name(target, dst_name)) # Check for exception thrown by _verifyFolderExists, if outside the root directory try: if (_verifyFolderExists(target, destination) and sanitized_destination != filename): # destination is an existing folder and not ourselves (= display rename), we'll assume we are supposed # to move filename to this folder under the same name destination = fileManager.join_path( target, destination, name) if _verifyFileExists(target, destination) or _verifyFolderExists( target, destination): abort(409, description="File or folder does already exist") except Exception: abort(409, description= "Exception thrown by storage, bad folder/file name?") is_file = fileManager.file_exists(target, filename) is_folder = fileManager.folder_exists(target, filename) if not (is_file or is_folder): abort(400, description="Neither file nor folder, can't {}".format( command)) if command == "copy": # destination already there? error... if _verifyFileExists(target, destination) or _verifyFolderExists( target, destination): abort(409, description="File or folder does already exist") if is_file: fileManager.copy_file(target, filename, destination) else: fileManager.copy_folder(target, filename, destination) elif command == "move": with Permissions.FILES_DELETE.require(403): if _isBusy(target, filename): abort( 409, description= "Trying to move a file or folder that is currently in use", ) # destination already there AND not ourselves (= display rename)? error... if (_verifyFileExists(target, destination) or _verifyFolderExists(target, destination) ) and sanitized_destination != filename: abort(409, description="File or folder does already exist") # deselect the file if it's currently selected currentOrigin, currentFilename = _getCurrentFile() if currentFilename is not None and filename == currentFilename: printer.unselect_file() if is_file: fileManager.move_file(target, filename, destination) else: fileManager.move_folder(target, filename, destination) location = url_for(".readGcodeFile", target=target, filename=destination, _external=True) result = { "name": name, "path": destination, "origin": FileDestinations.LOCAL, "refs": { "resource": location }, } if is_file: result["refs"]["download"] = ( url_for("index", _external=True) + "downloads/files/" + target + "/" + destination) r = make_response(jsonify(result), 201) r.headers["Location"] = location return r return NO_CONTENT
def gcodeConvertCommand(): target = FileDestinations.LOCAL # valid file commands, dict mapping command name to mandatory parameters valid_commands = {"convert": []} command, data, response = get_json_command_from_request( request, valid_commands) if response is not None: return response appendGcodeFiles = data['gcodeFilesToAppend'] del data['gcodeFilesToAppend'] # def appendCallback(location, path, sources, **kwargs): # if '_error' in kwargs: # result = kwargs['_error'] # return make_response("Could not slice: {result}".format(result=result), 500) # else: # output_path = fileManager.path_on_disk(location, path) # # append additioal gcodes # with open(output_path,'ab') as wfd: # for f in sources: # path = fileManager.path_on_disk(f['origin'], f['name']) # wfd.write( "\n; "+ f['name'] + "\n") # # with open(path,'rb') as fd: # shutil.copyfileobj(fd, wfd, 1024*1024*10) # # wfd.write( "\nM05\n") # ensure that the laser is off. # #files = {} # #location = url_for(".readGcodeFile", target=target, filename=gcode_name, _external=True) # #result = { ## "name": gcode_name, ## "origin": FileDestinations.LOCAL, ## "refs": { ## "resource": location, ## "download": url_for("index", _external=True) + "downloads/files/" + target + "/" + gcode_name ## } ## } # # #r = make_response(jsonify(result), 202) # #r.headers["Location"] = location # #return r if command == "convert": # TODO stripping non-ascii is a hack - svg contains lots of non-ascii in <text> tags. Fix this! import re svg = ''.join(i for i in data['svg'] if ord(i) < 128) # strip non-ascii chars like € del data['svg'] import os name, _ = os.path.splitext(data['gcode']) filename = target + "/temp.svg" class Wrapper(object): def __init__(self, filename, content): self.filename = filename self.content = content def save(self, absolute_dest_path): with open(absolute_dest_path, "w") as d: d.write(self.content) d.close() fileObj = Wrapper(filename, svg) fileManager.add_file(target, filename, fileObj, links=None, allow_overwrite=True) slicer = "svgtogcode" slicer_instance = slicingManager.get_slicer(slicer) if slicer_instance.get_slicer_properties()["same_device"] and ( printer.is_printing() or printer.is_paused()): # slicer runs on same device as OctoPrint, slicing while printing is hence disabled return make_response( "Cannot convert while lasering due to performance reasons". format(**locals()), 409) if "gcode" in data.keys() and data["gcode"]: gcode_name = data["gcode"] del data["gcode"] else: import os name, _ = os.path.splitext(filename) gcode_name = name + ".gco" # append number if file exists name, ext = os.path.splitext(gcode_name) i = 1 while (fileManager.file_exists(target, gcode_name)): gcode_name = name + '.' + str(i) + ext i += 1 # prohibit overwriting the file that is currently being printed currentOrigin, currentFilename = _getCurrentFile() if currentFilename == gcode_name and currentOrigin == target and ( printer.is_printing() or printer.is_paused()): make_response( "Trying to slice into file that is currently being printed: %s" % gcode_name, 409) if "profile" in data.keys() and data["profile"]: profile = data["profile"] del data["profile"] else: profile = None ## if "printerProfile" in data.keys() and data["printerProfile"]: printerProfile = data["printerProfile"] del data["printerProfile"] else: printerProfile = None if "position" in data.keys() and data["position"] and isinstance( data["position"], dict) and "x" in data["position"] and "y" in data["position"]: position = data["position"] del data["position"] else: position = None select_after_slicing = False if "select" in data.keys() and data["select"] in valid_boolean_trues: if not printer.is_operational(): return make_response( "Printer is not operational, cannot directly select for printing", 409) select_after_slicing = True print_after_slicing = False if "print" in data.keys() and data["print"] in valid_boolean_trues: if not printer.is_operational(): return make_response( "Printer is not operational, cannot directly start printing", 409) select_after_slicing = print_after_slicing = True override_keys = [ k for k in data if k.startswith("profile.") and data[k] is not None ] overrides = dict() for key in override_keys: overrides[key[len("profile."):]] = data[key] def slicing_done(target, gcode_name, select_after_slicing, print_after_slicing, append_these_files): # append additioal gcodes output_path = fileManager.path_on_disk(target, gcode_name) with open(output_path, 'ab') as wfd: for f in append_these_files: path = fileManager.path_on_disk(f['origin'], f['name']) wfd.write("\n; " + f['name'] + "\n") with open(path, 'rb') as fd: shutil.copyfileobj(fd, wfd, 1024 * 1024 * 10) wfd.write("\nM05\n") # ensure that the laser is off. if select_after_slicing or print_after_slicing: sd = False filenameToSelect = fileManager.path_on_disk(target, gcode_name) printer.select_file(filenameToSelect, sd, True) try: fileManager.slice(slicer, target, filename, target, gcode_name, profile=profile, printer_profile_id=printerProfile, position=position, overrides=overrides, callback=slicing_done, callback_args=[ target, gcode_name, select_after_slicing, print_after_slicing, appendGcodeFiles ]) except octoprint.slicing.UnknownProfile: return make_response( "Profile {profile} doesn't exist".format(**locals()), 400) files = {} location = url_for(".readGcodeFile", target=target, filename=gcode_name, _external=True) result = { "name": gcode_name, "origin": FileDestinations.LOCAL, "refs": { "resource": location, "download": url_for("index", _external=True) + "downloads/files/" + target + "/" + gcode_name } } r = make_response(jsonify(result), 202) r.headers["Location"] = location return r return NO_CONTENT
def gcodeFileCommand(filename, target): if not target in [FileDestinations.LOCAL, FileDestinations.SDCARD]: return make_response("Unknown target: %s" % target, 404) if not _verifyFileExists(target, filename): return make_response("File not found on '%s': %s" % (target, filename), 404) # valid file commands, dict mapping command name to mandatory parameters valid_commands = {"select": [], "slice": []} command, data, response = get_json_command_from_request( request, valid_commands) if response is not None: return response if command == "select": # selects/loads a file printAfterLoading = False if "print" in data.keys() and data["print"] in valid_boolean_trues: if not printer.is_operational(): return make_response( "Printer is not operational, cannot directly start printing", 409) printAfterLoading = True sd = False if target == FileDestinations.SDCARD: filenameToSelect = filename sd = True else: filenameToSelect = fileManager.path_on_disk(target, filename) printer.select_file(filenameToSelect, sd, printAfterLoading) elif command == "slice": try: if "slicer" in data: slicer = data["slicer"] del data["slicer"] slicer_instance = slicingManager.get_slicer(slicer) elif "cura" in slicingManager.registered_slicers: slicer = "cura" slicer_instance = slicingManager.get_slicer("cura") else: return make_response( "Cannot slice {filename}, no slicer available".format( **locals()), 415) except octoprint.slicing.UnknownSlicer as e: return make_response( "Slicer {slicer} is not available".format(slicer=e.slicer), 400) if not octoprint.filemanager.valid_file_type(filename, type="stl"): return make_response( "Cannot slice {filename}, not an STL file".format(**locals()), 415) if slicer_instance.get_slicer_properties()["same_device"] and ( printer.is_printing() or printer.is_paused()): # slicer runs on same device as OctoPrint, slicing while printing is hence disabled return make_response( "Cannot slice on {slicer} while printing due to performance reasons" .format(**locals()), 409) if "gcode" in data and data["gcode"]: gcode_name = data["gcode"] del data["gcode"] else: import os name, _ = os.path.splitext(filename) gcode_name = name + ".gco" # prohibit overwriting the file that is currently being printed currentOrigin, currentFilename = _getCurrentFile() if currentFilename == gcode_name and currentOrigin == target and ( printer.is_printing() or printer.is_paused()): make_response( "Trying to slice into file that is currently being printed: %s" % gcode_name, 409) if "profile" in data.keys() and data["profile"]: profile = data["profile"] del data["profile"] else: profile = None ## if "printerProfile" in data.keys() and data["printerProfile"]: printerProfile = data["printerProfile"] del data["printerProfile"] else: printerProfile = None if "position" in data.keys() and data["position"] and isinstance( data["position"], dict) and "x" in data["position"] and "y" in data["position"]: position = data["position"] del data["position"] else: position = None select_after_slicing = False if "select" in data.keys() and data["select"] in valid_boolean_trues: if not printer.is_operational(): return make_response( "Printer is not operational, cannot directly select for printing", 409) select_after_slicing = True print_after_slicing = False if "print" in data.keys() and data["print"] in valid_boolean_trues: if not printer.is_operational(): return make_response( "Printer is not operational, cannot directly start printing", 409) select_after_slicing = print_after_slicing = True override_keys = [ k for k in data if k.startswith("profile.") and data[k] is not None ] overrides = dict() for key in override_keys: overrides[key[len("profile."):]] = data[key] def slicing_done(target, gcode_name, select_after_slicing, print_after_slicing): if select_after_slicing or print_after_slicing: sd = False if target == FileDestinations.SDCARD: filenameToSelect = gcode_name sd = True else: filenameToSelect = fileManager.path_on_disk( target, gcode_name) printer.select_file(filenameToSelect, sd, print_after_slicing) try: fileManager.slice(slicer, target, filename, target, gcode_name, profile=profile, printer_profile_id=printerProfile, position=position, overrides=overrides, callback=slicing_done, callback_args=(target, gcode_name, select_after_slicing, print_after_slicing)) except octoprint.slicing.UnknownProfile: return make_response( "Profile {profile} doesn't exist".format(**locals()), 400) files = {} location = url_for(".readGcodeFile", target=target, filename=gcode_name, _external=True) result = { "name": gcode_name, "origin": FileDestinations.LOCAL, "refs": { "resource": location, "download": url_for("index", _external=True) + "downloads/files/" + target + "/" + gcode_name } } r = make_response(jsonify(result), 202) r.headers["Location"] = location return r return NO_CONTENT