forked from platformio/platformio-core
Fixed an issue when Python 2 does not keep encoding when converting .INO file // Resolve #3393
This commit is contained in:
@ -12,6 +12,7 @@ PlatformIO Core 4
|
|||||||
* Added support for Arm Mbed "module.json" ``dependencies`` field (`issue #3400 <https://github.com/platformio/platformio-core/issues/3400>`_)
|
* Added support for Arm Mbed "module.json" ``dependencies`` field (`issue #3400 <https://github.com/platformio/platformio-core/issues/3400>`_)
|
||||||
* Fixed an issue when quitting from PlatformIO IDE does not shutdown PIO Home server
|
* Fixed an issue when quitting from PlatformIO IDE does not shutdown PIO Home server
|
||||||
* Fixed an issue "the JSON object must be str, not 'bytes'" when PIO Home is used with Python 3.5 (`issue #3396 <https://github.com/platformio/platformio-core/issues/3396>`_)
|
* Fixed an issue "the JSON object must be str, not 'bytes'" when PIO Home is used with Python 3.5 (`issue #3396 <https://github.com/platformio/platformio-core/issues/3396>`_)
|
||||||
|
* Fixed an issue when Python 2 does not keep encoding when converting .INO file (`issue #3393 <https://github.com/platformio/platformio-core/issues/3393>`_)
|
||||||
|
|
||||||
4.2.1 (2020-02-17)
|
4.2.1 (2020-02-17)
|
||||||
~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
@ -15,17 +15,19 @@
|
|||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
import atexit
|
import atexit
|
||||||
|
import io
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
from os import environ, remove, walk
|
from os import environ, remove, walk
|
||||||
from os.path import basename, isdir, isfile, join, realpath, relpath, sep
|
from os.path import basename, isdir, isfile, join, realpath, relpath, sep
|
||||||
from tempfile import mkstemp
|
from tempfile import mkstemp
|
||||||
|
|
||||||
|
import click
|
||||||
from SCons.Action import Action # pylint: disable=import-error
|
from SCons.Action import Action # pylint: disable=import-error
|
||||||
from SCons.Script import ARGUMENTS # pylint: disable=import-error
|
from SCons.Script import ARGUMENTS # pylint: disable=import-error
|
||||||
|
|
||||||
from platformio import fs, util
|
from platformio import fs, util
|
||||||
from platformio.compat import glob_escape
|
from platformio.compat import get_filesystem_encoding, get_locale_encoding, glob_escape
|
||||||
from platformio.managers.core import get_core_package_dir
|
from platformio.managers.core import get_core_package_dir
|
||||||
from platformio.proc import exec_command
|
from platformio.proc import exec_command
|
||||||
|
|
||||||
@ -48,6 +50,40 @@ class InoToCPPConverter(object):
|
|||||||
def __init__(self, env):
|
def __init__(self, env):
|
||||||
self.env = env
|
self.env = env
|
||||||
self._main_ino = None
|
self._main_ino = None
|
||||||
|
self._safe_encoding = None
|
||||||
|
|
||||||
|
def read_safe_contents(self, path):
|
||||||
|
last_exc = None
|
||||||
|
for encoding in (
|
||||||
|
"utf-8",
|
||||||
|
None,
|
||||||
|
get_filesystem_encoding(),
|
||||||
|
get_locale_encoding(),
|
||||||
|
"latin-1",
|
||||||
|
):
|
||||||
|
try:
|
||||||
|
with io.open(path, encoding=encoding) as fp:
|
||||||
|
contents = fp.read()
|
||||||
|
self._safe_encoding = encoding
|
||||||
|
return contents
|
||||||
|
except UnicodeDecodeError as e:
|
||||||
|
last_exc = e
|
||||||
|
click.secho(
|
||||||
|
"Unicode decode error has occurred, please remove invalid "
|
||||||
|
"(non-ASCII or non-UTF8) characters from %s file or convert it to UTF-8"
|
||||||
|
% path,
|
||||||
|
fg="yellow",
|
||||||
|
err=True,
|
||||||
|
)
|
||||||
|
if last_exc:
|
||||||
|
raise last_exc
|
||||||
|
return None
|
||||||
|
|
||||||
|
def write_safe_contents(self, path, contents):
|
||||||
|
with io.open(
|
||||||
|
path, "w", encoding=self._safe_encoding, errors="backslashreplace"
|
||||||
|
) as fp:
|
||||||
|
return fp.write(contents)
|
||||||
|
|
||||||
def is_main_node(self, contents):
|
def is_main_node(self, contents):
|
||||||
return self.DETECTMAIN_RE.search(contents)
|
return self.DETECTMAIN_RE.search(contents)
|
||||||
@ -62,7 +98,7 @@ class InoToCPPConverter(object):
|
|||||||
assert nodes
|
assert nodes
|
||||||
lines = []
|
lines = []
|
||||||
for node in nodes:
|
for node in nodes:
|
||||||
contents = fs.get_file_contents(node.get_path())
|
contents = self.read_safe_contents(node.get_path())
|
||||||
_lines = ['# 1 "%s"' % node.get_path().replace("\\", "/"), contents]
|
_lines = ['# 1 "%s"' % node.get_path().replace("\\", "/"), contents]
|
||||||
if self.is_main_node(contents):
|
if self.is_main_node(contents):
|
||||||
lines = _lines + lines
|
lines = _lines + lines
|
||||||
@ -78,16 +114,14 @@ class InoToCPPConverter(object):
|
|||||||
def process(self, contents):
|
def process(self, contents):
|
||||||
out_file = self._main_ino + ".cpp"
|
out_file = self._main_ino + ".cpp"
|
||||||
assert self._gcc_preprocess(contents, out_file)
|
assert self._gcc_preprocess(contents, out_file)
|
||||||
contents = fs.get_file_contents(out_file)
|
contents = self.read_safe_contents(out_file)
|
||||||
contents = self._join_multiline_strings(contents)
|
contents = self._join_multiline_strings(contents)
|
||||||
fs.write_file_contents(
|
self.write_safe_contents(out_file, self.append_prototypes(contents))
|
||||||
out_file, self.append_prototypes(contents), errors="backslashreplace"
|
|
||||||
)
|
|
||||||
return out_file
|
return out_file
|
||||||
|
|
||||||
def _gcc_preprocess(self, contents, out_file):
|
def _gcc_preprocess(self, contents, out_file):
|
||||||
tmp_path = mkstemp()[1]
|
tmp_path = mkstemp()[1]
|
||||||
fs.write_file_contents(tmp_path, contents, errors="backslashreplace")
|
self.write_safe_contents(tmp_path, contents)
|
||||||
self.env.Execute(
|
self.env.Execute(
|
||||||
self.env.VerboseAction(
|
self.env.VerboseAction(
|
||||||
'$CXX -o "{0}" -x c++ -fpreprocessed -dD -E "{1}"'.format(
|
'$CXX -o "{0}" -x c++ -fpreprocessed -dD -E "{1}"'.format(
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
import io
|
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
@ -49,30 +48,6 @@ def get_source_dir():
|
|||||||
return os.path.dirname(curpath)
|
return os.path.dirname(curpath)
|
||||||
|
|
||||||
|
|
||||||
def get_file_contents(path, encoding=None):
|
|
||||||
try:
|
|
||||||
with io.open(path, encoding=encoding) as fp:
|
|
||||||
return fp.read()
|
|
||||||
except UnicodeDecodeError:
|
|
||||||
click.secho(
|
|
||||||
"Unicode decode error has occurred, please remove invalid "
|
|
||||||
"(non-ASCII or non-UTF8) characters from %s file" % path,
|
|
||||||
fg="yellow",
|
|
||||||
err=True,
|
|
||||||
)
|
|
||||||
with io.open(path, encoding="latin-1") as fp:
|
|
||||||
return fp.read()
|
|
||||||
|
|
||||||
|
|
||||||
def write_file_contents(path, contents, errors=None):
|
|
||||||
try:
|
|
||||||
with open(path, "w") as fp:
|
|
||||||
return fp.write(contents)
|
|
||||||
except UnicodeEncodeError:
|
|
||||||
with io.open(path, "w", encoding="latin-1", errors=errors) as fp:
|
|
||||||
return fp.write(contents)
|
|
||||||
|
|
||||||
|
|
||||||
def load_json(file_path):
|
def load_json(file_path):
|
||||||
try:
|
try:
|
||||||
with open(file_path, "r") as f:
|
with open(file_path, "r") as f:
|
||||||
@ -102,11 +77,14 @@ def ensure_udev_rules():
|
|||||||
from platformio.util import get_systype # pylint: disable=import-outside-toplevel
|
from platformio.util import get_systype # pylint: disable=import-outside-toplevel
|
||||||
|
|
||||||
def _rules_to_set(rules_path):
|
def _rules_to_set(rules_path):
|
||||||
return set(
|
result = set()
|
||||||
l.strip()
|
with open(rules_path) as fp:
|
||||||
for l in get_file_contents(rules_path).split("\n")
|
for line in fp.readlines():
|
||||||
if l.strip() and not l.startswith("#")
|
line = line.strip()
|
||||||
)
|
if not line or line.startswith("#"):
|
||||||
|
continue
|
||||||
|
result.add(line)
|
||||||
|
return result
|
||||||
|
|
||||||
if "linux" not in get_systype():
|
if "linux" not in get_systype():
|
||||||
return None
|
return None
|
||||||
|
Reference in New Issue
Block a user