diff --git a/src/octoprint/plugins/cura/__init__.py b/src/octoprint/plugins/cura/__init__.py index e1ce090c..6b1b7291 100644 --- a/src/octoprint/plugins/cura/__init__.py +++ b/src/octoprint/plugins/cura/__init__.py @@ -218,7 +218,7 @@ class CuraPlugin(octoprint.plugin.SlicerPlugin, if not on_progress_kwargs: on_progress_kwargs = dict() - self._cura_logger.info("### Slicing %s to %s using profile stored at %s" % (model_path, machinecode_path, profile_path)) + self._cura_logger.info(u"### Slicing %s to %s using profile stored at %s" % (model_path, machinecode_path, profile_path)) engine_settings = self._convert_to_engine(profile_path, printer_profile, posX, posY) @@ -227,16 +227,15 @@ class CuraPlugin(octoprint.plugin.SlicerPlugin, return False, "Path to CuraEngine is not configured " working_dir, _ = os.path.split(executable) - args = ['"%s"' % executable, '-v', '-p'] + args = [executable, '-v', '-p'] for k, v in engine_settings.items(): - args += ["-s", '"%s=%s"' % (k, str(v))] - args += ['-o', '"%s"' % machinecode_path, '"%s"' % model_path] + args += ["-s", "%s=%s" % (k, str(v))] + args += ["-o", machinecode_path, model_path] + + self._logger.info(u"Running %r in %s" % (" ".join(args), working_dir)) import sarge - command = " ".join(args) - self._logger.info("Running %r in %s" % (command, working_dir)) - - p = sarge.run(command, cwd=working_dir, async=True, stdout=sarge.Capture(), stderr=sarge.Capture()) + p = sarge.run(args, cwd=working_dir, async=True, stdout=sarge.Capture(), stderr=sarge.Capture()) p.wait_events() self._slicing_commands[machinecode_path] = p.commands[0] @@ -254,6 +253,7 @@ class CuraPlugin(octoprint.plugin.SlicerPlugin, p.commands[0].poll() continue + line = octoprint.util.to_unicode(line, errors="replace") self._cura_logger.debug(line.strip()) if on_progress is not None: @@ -282,14 +282,14 @@ class CuraPlugin(octoprint.plugin.SlicerPlugin, # # with being 0 for "inset", 1 for "skin" and 2 for "export". - if line.startswith("Layer count:") and layer_count is None: + if line.startswith(u"Layer count:") and layer_count is None: try: - layer_count = float(line[len("Layer count:"):].strip()) + layer_count = float(line[len(u"Layer count:"):].strip()) except: pass - elif line.startswith("Progress:"): - split_line = line[len("Progress:"):].strip().split(":") + elif line.startswith(u"Progress:"): + split_line = line[len(u"Progress:"):].strip().split(":") if len(split_line) == 3: step, current_layer, _ = split_line try: @@ -302,21 +302,21 @@ class CuraPlugin(octoprint.plugin.SlicerPlugin, on_progress_kwargs["_progress"] = (step_factor[step] * layer_count + current_layer) / (layer_count * 3) on_progress(*on_progress_args, **on_progress_kwargs) - elif line.startswith("Print time:"): + elif line.startswith(u"Print time:"): try: - print_time = int(line[len("Print time:"):].strip()) + print_time = int(line[len(u"Print time:"):].strip()) if analysis is None: analysis = dict() analysis["estimatedPrintTime"] = print_time except: pass - elif line.startswith("Filament:") or line.startswith("Filament2:"): - if line.startswith("Filament:"): - filament_str = line[len("Filament:"):].strip() + elif line.startswith(u"Filament:") or line.startswith(u"Filament2:"): + if line.startswith(u"Filament:"): + filament_str = line[len(u"Filament:"):].strip() tool_key = "tool0" else: - filament_str = line[len("Filament2:"):].strip() + filament_str = line[len(u"Filament2:"):].strip() tool_key = "tool1" try: @@ -339,20 +339,20 @@ class CuraPlugin(octoprint.plugin.SlicerPlugin, with self._job_mutex: if machinecode_path in self._cancelled_jobs: - self._cura_logger.info("### Cancelled") + self._cura_logger.info(u"### Cancelled") raise octoprint.slicing.SlicingCancelled() - self._cura_logger.info("### Finished, returncode %d" % p.returncode) + self._cura_logger.info(u"### Finished, returncode %d" % p.returncode) if p.returncode == 0: return True, dict(analysis=analysis) else: - self._logger.warn("Could not slice via Cura, got return code %r" % p.returncode) + self._logger.warn(u"Could not slice via Cura, got return code %r" % p.returncode) return False, "Got returncode %r" % p.returncode except octoprint.slicing.SlicingCancelled as e: raise e except: - self._logger.exception("Could not slice via Cura, got an unknown error") + self._logger.exception(u"Could not slice via Cura, got an unknown error") return False, "Unknown error, please consult the log file" finally: @@ -371,7 +371,7 @@ class CuraPlugin(octoprint.plugin.SlicerPlugin, command = self._slicing_commands[machinecode_path] if command is not None: command.terminate() - self._logger.info("Cancelled slicing of %s" % machinecode_path) + self._logger.info(u"Cancelled slicing of %s" % machinecode_path) def _load_profile(self, path): import yaml diff --git a/src/octoprint/plugins/pluginmanager/__init__.py b/src/octoprint/plugins/pluginmanager/__init__.py index 58b662bb..a458acd1 100644 --- a/src/octoprint/plugins/pluginmanager/__init__.py +++ b/src/octoprint/plugins/pluginmanager/__init__.py @@ -418,13 +418,13 @@ class PluginManagerPlugin(octoprint.plugin.SimpleApiPlugin, return self._pip_caller.execute(*args) def _log_call(self, *lines): - self._log(lines, prefix=" ", stream="call") + self._log(lines, prefix=u" ", stream="call") def _log_stdout(self, *lines): - self._log(lines, prefix=">", stream="stdout") + self._log(lines, prefix=u">", stream="stdout") def _log_stderr(self, *lines): - self._log(lines, prefix="!", stream="stderr") + self._log(lines, prefix=u"!", stream="stderr") def _log(self, lines, prefix=None, stream=None, strip=True): if strip: diff --git a/src/octoprint/plugins/softwareupdate/updaters/pip.py b/src/octoprint/plugins/softwareupdate/updaters/pip.py index 36f52812..446313b0 100644 --- a/src/octoprint/plugins/softwareupdate/updaters/pip.py +++ b/src/octoprint/plugins/softwareupdate/updaters/pip.py @@ -46,12 +46,12 @@ def perform_update(target, check, target_version): install_arg = check["pip"].format(target_version=target_version) - logger.debug("Target: %s, executing pip install %s" % (target, install_arg)) + logger.debug(u"Target: %s, executing pip install %s" % (target, install_arg)) pip_args = ["install", check["pip"].format(target_version=target_version, target=target_version)] pip_caller.execute(*pip_args) - logger.debug("Target: %s, executing pip install %s --ignore-reinstalled --force-reinstall --no-deps" % (target, install_arg)) + logger.debug(u"Target: %s, executing pip install %s --ignore-reinstalled --force-reinstall --no-deps" % (target, install_arg)) pip_args += ["--ignore-installed", "--force-reinstall", "--no-deps"] pip_caller.execute(*pip_args) @@ -59,13 +59,13 @@ def perform_update(target, check, target_version): return "ok" def _log_call(*lines): - _log(lines, prefix=" ") + _log(lines, prefix=u" ") def _log_stdout(*lines): - _log(lines, prefix=">") + _log(lines, prefix=u">") def _log_stderr(*lines): - _log(lines, prefix="!") + _log(lines, prefix=u"!") def _log(lines, prefix=None): lines = map(lambda x: x.strip(), lines) diff --git a/src/octoprint/util/__init__.py b/src/octoprint/util/__init__.py index 9b63618e..3b3d03a4 100644 --- a/src/octoprint/util/__init__.py +++ b/src/octoprint/util/__init__.py @@ -352,9 +352,7 @@ def silent_remove(file): def sanitize_ascii(line): if not isinstance(line, basestring): raise ValueError("Expected either str or unicode but got {} instead".format(line.__class__.__name__ if line is not None else None)) - if isinstance(line, str): - line = unicode(line, 'ascii', 'replace') - return line.encode('ascii', 'replace').rstrip() + return to_unicode(line, encoding="ascii", errors="replace").rstrip() def filter_non_ascii(line): @@ -369,12 +367,28 @@ def filter_non_ascii(line): """ try: - unicode(line, 'ascii').encode('ascii') + to_str(to_unicode(line, encoding="ascii"), encoding="ascii") return False except ValueError: return True +def to_str(s_or_u, encoding="utf-8", errors="strict"): + """Make sure ``s_or_u`` is a str.""" + if isinstance(s_or_u, unicode): + return s_or_u.encode(encoding, errors=errors) + else: + return s_or_u + + +def to_unicode(s_or_u, encoding="utf-8", errors="strict"): + """Make sure ``s_or_u`` is a unicode string.""" + if isinstance(s_or_u, str): + return s_or_u.decode(encoding, errors=errors) + else: + return s_or_u + + def dict_merge(a, b): """ Recursively deep-merges two dictionaries. diff --git a/src/octoprint/util/pip.py b/src/octoprint/util/pip.py index 7d3d1da1..980e5735 100644 --- a/src/octoprint/util/pip.py +++ b/src/octoprint/util/pip.py @@ -11,6 +11,9 @@ import sys import logging +from octoprint.util import to_unicode + + class UnknownPip(Exception): pass @@ -77,11 +80,13 @@ class PipCaller(object): while p.returncode is None: line = p.stderr.readline(timeout=0.5) if line: + line = to_unicode(line, errors="replace") self._log_stderr(line) all_stderr.append(line) line = p.stdout.readline(timeout=0.5) if line: + line = to_unicode(line, errors="replace") self._log_stdout(line) all_stdout.append(line)