Use UTF-8 for _all_ output from sarge
Lines taking from the asynchronous processing of stdout/stderr where left as str, leading to encoding problems when utf8 characters showed up in the stream and were being interpreted as ascii encoding. (cherry picked from commit 9373be3)
This commit is contained in:
parent
7b3e0563cc
commit
d7a86a4d28
5 changed files with 54 additions and 35 deletions
|
|
@ -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 <step_factor> 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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue