diff --git a/esphomeyaml/api/client.py b/esphomeyaml/api/client.py index 53608a3082..446de042b5 100644 --- a/esphomeyaml/api/client.py +++ b/esphomeyaml/api/client.py @@ -14,7 +14,7 @@ import esphomeyaml.api.api_pb2 as pb from esphomeyaml.const import CONF_PASSWORD, CONF_PORT from esphomeyaml.core import EsphomeyamlError from esphomeyaml.helpers import resolve_ip_address, indent, color -from esphomeyaml.py_compat import text_type, IS_PY2, byte, char, format_bytes +from esphomeyaml.py_compat import text_type, IS_PY2, byte_to_bytes, char_to_byte, format_bytes from esphomeyaml.util import safe_print _LOGGER = logging.getLogger(__name__) @@ -67,16 +67,16 @@ MESSAGE_TYPE_TO_PROTO = { def _varuint_to_bytes(value): if value <= 0x7F: - return byte(value) + return byte_to_bytes(value) ret = bytes() while value: temp = value & 0x7F value >>= 7 if value: - ret += byte(temp | 0x80) + ret += byte_to_bytes(temp | 0x80) else: - ret += byte(temp) + ret += byte_to_bytes(temp) return ret @@ -85,7 +85,7 @@ def _bytes_to_varuint(value): result = 0 bitpos = 0 for c in value: - val = char(c) + val = char_to_byte(c) result |= (val & 0x7F) << bitpos bitpos += 7 if (val & 0x80) == 0: @@ -361,7 +361,7 @@ class APIClient(threading.Thread): def _recv_varint(self): raw = bytes() - while not raw or char(raw[-1]) & 0x80: + while not raw or char_to_byte(raw[-1]) & 0x80: raw += self._recv(1) return _bytes_to_varuint(raw) @@ -370,7 +370,7 @@ class APIClient(threading.Thread): return # Preamble - if char(self._recv(1)[0]) != 0x00: + if char_to_byte(self._recv(1)[0]) != 0x00: raise APIConnectionError("Invalid preamble") length = self._recv_varint() diff --git a/esphomeyaml/components/font.py b/esphomeyaml/components/font.py index ab1611231e..c69ffbd46e 100644 --- a/esphomeyaml/components/font.py +++ b/esphomeyaml/components/font.py @@ -8,6 +8,7 @@ from esphomeyaml.const import CONF_FILE, CONF_GLYPHS, CONF_ID, CONF_SIZE from esphomeyaml.core import CORE, HexInt from esphomeyaml.cpp_generator import ArrayInitializer, MockObj, Pvariable, RawExpression, add from esphomeyaml.cpp_types import App +from esphomeyaml.py_compat import sort_by_cmp DEPENDENCIES = ['display'] MULTI_CONF = True @@ -37,7 +38,7 @@ def validate_glyphs(value): return 1 raise vol.Invalid(u"Found duplicate glyph {}".format(x)) - value.sort(cmp=comparator) + sort_by_cmp(value, comparator) return value diff --git a/esphomeyaml/espota2.py b/esphomeyaml/espota2.py index 423fc6a5bd..b541f4d63b 100755 --- a/esphomeyaml/espota2.py +++ b/esphomeyaml/espota2.py @@ -7,7 +7,7 @@ import time from esphomeyaml.core import EsphomeyamlError from esphomeyaml.helpers import resolve_ip_address, is_ip_address -from esphomeyaml.py_compat import IS_PY2, char +from esphomeyaml.py_compat import IS_PY2, char_to_byte RESPONSE_OK = 0 RESPONSE_REQUEST_AUTH = 1 @@ -68,7 +68,7 @@ def recv_decode(sock, amount, decode=True): data = sock.recv(amount) if not decode: return data - return [char(x) for x in data] + return [char_to_byte(x) for x in data] def receive_exactly(sock, amount, msg, expect, decode=True): diff --git a/esphomeyaml/helpers.py b/esphomeyaml/helpers.py index b7afe6cfca..b13b9768e1 100644 --- a/esphomeyaml/helpers.py +++ b/esphomeyaml/helpers.py @@ -6,7 +6,7 @@ import os import socket import subprocess -from esphomeyaml.py_compat import text_type, IS_PY2 +from esphomeyaml.py_compat import text_type, char_to_byte _LOGGER = logging.getLogger(__name__) @@ -41,13 +41,19 @@ def indent(text, padding=u' '): # From https://stackoverflow.com/a/14945195/8924614 def cpp_string_escape(string, encoding='utf-8'): + def _should_escape(byte): # type: (int) -> bool + if not 32 <= byte < 127: + return True + if byte in (char_to_byte('\\'), char_to_byte('"')): + return True + return False + if isinstance(string, text_type): string = string.encode(encoding) result = '' for character in string: - if IS_PY2: - character = ord(character) - if not (32 <= character < 127) or character in ('\\', '"'): + character = char_to_byte(character) + if _should_escape(character): result += '\\%03o' % character else: result += chr(character) diff --git a/esphomeyaml/py_compat.py b/esphomeyaml/py_compat.py index 5e70766c46..5147749efa 100644 --- a/esphomeyaml/py_compat.py +++ b/esphomeyaml/py_compat.py @@ -1,3 +1,4 @@ +import functools import sys PYTHON_MAJOR = sys.version_info[0] @@ -25,18 +26,28 @@ else: binary_type = bytes -def byte(val): +def byte_to_bytes(val): # type: (int) -> bytes if IS_PY2: return chr(val) else: return bytes([val]) -def char(val): +def char_to_byte(val): # type: (str) -> int if IS_PY2: - return ord(val) + if isinstance(val, string_types): + return ord(val) + elif isinstance(val, int): + return val + else: + raise ValueError else: - return val + if isinstance(val, str): + return ord(val) + elif isinstance(val, int): + return val + else: + raise ValueError def format_bytes(val): @@ -44,3 +55,10 @@ def format_bytes(val): return ' '.join('{:02X}'.format(ord(x)) for x in val) else: return ' '.join('{:02X}'.format(x) for x in val) + + +def sort_by_cmp(list_, cmp): + if IS_PY2: + list_.sort(cmp=cmp) + else: + list_.sort(key=functools.cmp_to_key(cmp))