Skip to content

Commit

Permalink
Fix: Open GCODE files als utf-8, replacing encoding errors
Browse files Browse the repository at this point in the history
Also detect files that contain a BOM and strip it.
Internal handling of GCODE file contents switched to unicode.

 Should take care of #1077
  • Loading branch information
foosel committed Oct 5, 2015
1 parent abf0733 commit 45c92cb
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 7 deletions.
23 changes: 23 additions & 0 deletions src/octoprint/util/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,29 @@ def atomic_write(filename, mode="w+b", prefix="tmp", suffix=""):
shutil.move(temp_config.name, filename)


def bom_aware_open(filename, encoding="ascii", mode="r", **kwargs):
import codecs

codec = codecs.lookup(encoding)
encoding = codec.name

if kwargs is None:
kwargs = dict()

potential_bom_attribute = "BOM_" + codec.name.replace("utf-", "utf").upper()
if "r" in mode and hasattr(codecs, potential_bom_attribute):
# these encodings might have a BOM, so let's see if there is one
bom = getattr(codecs, potential_bom_attribute)

with open(filename, "rb") as f:
header = f.read(4)

if header.startswith(bom):
encoding += "-sig"

return codecs.open(filename, encoding=encoding, **kwargs)


class RepeatedTimer(threading.Thread):
"""
This class represents an action that should be run repeatedly in an interval. It is similar to python's
Expand Down
13 changes: 7 additions & 6 deletions src/octoprint/util/comm.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from octoprint.events import eventManager, Events
from octoprint.filemanager import valid_file_type
from octoprint.filemanager.destinations import FileDestinations
from octoprint.util import get_exception_string, sanitize_ascii, filter_non_ascii, CountedEvent, RepeatedTimer
from octoprint.util import get_exception_string, sanitize_ascii, filter_non_ascii, CountedEvent, RepeatedTimer, to_unicode, bom_aware_open

try:
import _winreg
Expand Down Expand Up @@ -491,7 +491,7 @@ def fakeOk(self):
self._clear_to_send.set()

def sendCommand(self, cmd, cmd_type=None, processed=False):
cmd = cmd.encode('ascii', 'replace')
cmd = to_unicode(cmd, errors="replace")
if not processed:
cmd = process_gcode_line(cmd)
if not cmd:
Expand Down Expand Up @@ -1549,10 +1549,11 @@ def _send_loop(self):
continue

# now comes the part where we increase line numbers and send stuff - no turning back now
command_to_send = command.encode("ascii", errors="replace")
if (gcode is not None or self._sendChecksumWithUnknownCommands) and (self.isPrinting() or self._alwaysSendChecksum):
self._doIncrementAndSendWithChecksum(command)
self._doIncrementAndSendWithChecksum(command_to_send)
else:
self._doSendWithoutChecksum(command)
self._doSendWithoutChecksum(command_to_send)

# trigger "sent" phase and use up one "ok"
self._process_command_phase("sent", command, command_type, gcode=gcode)
Expand Down Expand Up @@ -1952,7 +1953,7 @@ def start(self):
Opens the file for reading and determines the file size.
"""
PrintingFileInformation.start(self)
self._handle = open(self._filename, "r")
self._handle = bom_aware_open(self._filename, encoding="utf-8", errors="replace")

def close(self):
"""
Expand Down Expand Up @@ -1982,7 +1983,7 @@ def getNext(self):
if self._handle is None:
# file got closed just now
return None
line = self._handle.readline()
line = to_unicode(self._handle.readline())
if not line:
self.close()
processed = process_gcode_line(line, offsets=offsets, current_tool=current_tool)
Expand Down
4 changes: 3 additions & 1 deletion src/octoprint/util/gcodeInterpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ def load(self, filename, printer_profile, throttle=None):
if os.path.isfile(filename):
self.filename = filename
self._fileSize = os.stat(filename).st_size
with open(filename, "r") as f:

import codecs
with codecs.open(filename, encoding="utf-8", errors="replace") as f:
self._load(f, printer_profile, throttle=throttle)

def abort(self):
Expand Down

0 comments on commit 45c92cb

Please sign in to comment.