mirror of
https://github.com/esphome/esphome.git
synced 2024-12-22 05:24:53 +01:00
Make compatible with python 3 (#281)
* Make compatible with python 3 * Update travis * Env * Fix typo * Fix install correct platformio * Lint * Fix build flags * Lint * Upgrade pylint * Lint
This commit is contained in:
parent
5db70bea3c
commit
22fd4ec722
39 changed files with 249 additions and 181 deletions
32
.travis.yml
32
.travis.yml
|
@ -1,20 +1,30 @@
|
|||
sudo: false
|
||||
language: python
|
||||
python:
|
||||
- "2.7"
|
||||
jobs:
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
include:
|
||||
- name: "Lint"
|
||||
install:
|
||||
- pip install -r requirements.txt
|
||||
- pip install flake8==3.5.0 pylint==1.9.3 tzlocal pillow
|
||||
- python: "2.7"
|
||||
env: TARGET=Lint2.7
|
||||
install: pip install -e . && pip install flake8==3.6.0 pylint==1.9.4 tzlocal pillow
|
||||
script:
|
||||
- flake8 esphomeyaml
|
||||
- pylint esphomeyaml
|
||||
- name: "Test"
|
||||
install:
|
||||
- pip install -e .
|
||||
- pip install tzlocal pillow
|
||||
- python: "3.5.3"
|
||||
env: TARGET=Lint3.5
|
||||
install: pip install -U https://github.com/platformio/platformio-core/archive/develop.zip && pip install -e . && pip install flake8==3.6.0 pylint==2.2.2 tzlocal pillow
|
||||
script:
|
||||
- flake8 esphomeyaml
|
||||
- pylint esphomeyaml
|
||||
- python: "2.7"
|
||||
env: TARGET=Test2.7
|
||||
install: pip install -e . && pip install flake8==3.6.0 pylint==1.9.4 tzlocal pillow
|
||||
script:
|
||||
- esphomeyaml tests/test1.yaml compile
|
||||
- esphomeyaml tests/test2.yaml compile
|
||||
- python: "3.5.3"
|
||||
env: TARGET=Test3.5
|
||||
install: pip install -U https://github.com/platformio/platformio-core/archive/develop.zip && pip install -e . && pip install flake8==3.6.0 pylint==2.2.2 tzlocal pillow
|
||||
script:
|
||||
- esphomeyaml tests/test1.yaml compile
|
||||
- esphomeyaml tests/test2.yaml compile
|
||||
|
|
|
@ -3,4 +3,4 @@ FROM python:2.7
|
|||
COPY requirements.txt /requirements.txt
|
||||
|
||||
RUN pip install -r /requirements.txt && \
|
||||
pip install flake8==3.5.0 pylint==1.9.3 tzlocal pillow
|
||||
pip install flake8==3.6.0 pylint==1.9.4 tzlocal pillow
|
||||
|
|
|
@ -16,8 +16,9 @@ from esphomeyaml.const import CONF_BAUD_RATE, CONF_ESPHOMEYAML, CONF_LOGGER, CON
|
|||
from esphomeyaml.core import CORE, EsphomeyamlError
|
||||
from esphomeyaml.cpp_generator import Expression, RawStatement, add, statement
|
||||
from esphomeyaml.helpers import color, indent
|
||||
from esphomeyaml.storage_json import StorageJSON, storage_path, start_update_check_thread, \
|
||||
esphomeyaml_storage_path
|
||||
from esphomeyaml.py_compat import safe_input, text_type
|
||||
from esphomeyaml.storage_json import StorageJSON, esphomeyaml_storage_path, \
|
||||
start_update_check_thread, storage_path
|
||||
from esphomeyaml.util import run_external_command, safe_print
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
@ -50,7 +51,7 @@ def choose_prompt(options):
|
|||
safe_print(u" [{}] {}".format(i + 1, desc))
|
||||
|
||||
while True:
|
||||
opt = raw_input('(number): ')
|
||||
opt = safe_input('(number): ')
|
||||
if opt in options:
|
||||
opt = options.index(opt)
|
||||
break
|
||||
|
@ -140,7 +141,7 @@ def write_cpp(config):
|
|||
if not config[CONF_ESPHOMEYAML][CONF_USE_CUSTOM_CODE]:
|
||||
if isinstance(exp, Expression) and not exp.required:
|
||||
continue
|
||||
all_code.append(unicode(statement(exp)))
|
||||
all_code.append(text_type(statement(exp)))
|
||||
|
||||
writer.write_platformio_project()
|
||||
|
||||
|
@ -199,7 +200,7 @@ def upload_program(config, args, host):
|
|||
if storage is not None and not storage.use_legacy_ota:
|
||||
return res
|
||||
|
||||
_LOGGER.warn("OTA v2 method failed. Trying with legacy OTA...")
|
||||
_LOGGER.warning("OTA v2 method failed. Trying with legacy OTA...")
|
||||
return espota2.run_legacy_ota(verbose, host_port, host, remote_port, password,
|
||||
CORE.firmware_bin)
|
||||
|
||||
|
@ -208,9 +209,9 @@ def show_logs(config, args, port):
|
|||
if get_port_type(port) == 'SERIAL':
|
||||
run_miniterm(config, port)
|
||||
return 0
|
||||
elif get_port_type(port) == 'NETWORK':
|
||||
if get_port_type(port) == 'NETWORK':
|
||||
return run_logs(config, port)
|
||||
elif get_port_type(port) == 'MQTT':
|
||||
if get_port_type(port) == 'MQTT':
|
||||
return mqtt.show_logs(config, args.topic, args.username, args.password, args.client_id)
|
||||
|
||||
raise ValueError
|
||||
|
|
|
@ -14,6 +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
|
||||
from esphomeyaml.util import safe_print
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
@ -254,14 +255,14 @@ class APIClient(threading.Thread):
|
|||
|
||||
def _send_message(self, msg):
|
||||
# type: (message.Message) -> None
|
||||
for message_type, klass in MESSAGE_TYPE_TO_PROTO.iteritems():
|
||||
for message_type, klass in MESSAGE_TYPE_TO_PROTO.items():
|
||||
if isinstance(msg, klass):
|
||||
break
|
||||
else:
|
||||
raise ValueError
|
||||
|
||||
encoded = msg.SerializeToString()
|
||||
_LOGGER.debug("Sending %s:\n%s", type(msg), indent(unicode(msg)))
|
||||
_LOGGER.debug("Sending %s:\n%s", type(msg), indent(text_type(msg)))
|
||||
req = chr(0x00)
|
||||
req += _varuint_to_bytes(len(encoded))
|
||||
req += _varuint_to_bytes(message_type)
|
||||
|
@ -435,12 +436,14 @@ def run_logs(config, address):
|
|||
while retry_timer:
|
||||
retry_timer.pop(0).cancel()
|
||||
|
||||
error = None
|
||||
try:
|
||||
cli.connect()
|
||||
cli.login()
|
||||
except APIConnectionError as error:
|
||||
pass
|
||||
else:
|
||||
except APIConnectionError as err: # noqa
|
||||
error = err
|
||||
|
||||
if error is None:
|
||||
_LOGGER.info("Successfully connected to %s", address)
|
||||
return
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ def validate_recursive_condition(value):
|
|||
raise vol.Invalid(u"Unable to find condition with the name '{}', is the "
|
||||
u"component loaded?".format(key), path + [key])
|
||||
item.setdefault(CONF_CONDITION_ID, None)
|
||||
key2 = next((x for x in item if x != CONF_CONDITION_ID and x != key), None)
|
||||
key2 = next((x for x in item if x not in (CONF_CONDITION_ID, key)), None)
|
||||
if key2 is not None:
|
||||
raise vol.Invalid(u"Cannot have two conditions in one item. Key '{}' overrides '{}'! "
|
||||
u"Did you forget to indent the block inside the condition?"
|
||||
|
@ -76,7 +76,7 @@ def validate_recursive_action(value):
|
|||
raise vol.Invalid(u"Unable to find action with the name '{}', is the component loaded?"
|
||||
u"".format(key), path + [key])
|
||||
item.setdefault(CONF_ACTION_ID, None)
|
||||
key2 = next((x for x in item if x != CONF_ACTION_ID and x != key), None)
|
||||
key2 = next((x for x in item if x not in (CONF_ACTION_ID, key)), None)
|
||||
if key2 is not None:
|
||||
raise vol.Invalid(u"Cannot have two actions in one item. Key '{}' overrides '{}'! "
|
||||
u"Did you forget to indent the block inside the action?"
|
||||
|
|
|
@ -43,7 +43,7 @@ BUILD_FLAGS = '-DUSE_API'
|
|||
def lib_deps(config):
|
||||
if CORE.is_esp32:
|
||||
return 'AsyncTCP@1.0.1'
|
||||
elif CORE.is_esp8266:
|
||||
if CORE.is_esp8266:
|
||||
return 'ESPAsyncTCP@1.1.3'
|
||||
raise NotImplementedError
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ from esphomeyaml.core import CORE
|
|||
from esphomeyaml.cpp_generator import process_lambda, ArrayInitializer, add, Pvariable, \
|
||||
StructInitializer, get_variable
|
||||
from esphomeyaml.cpp_types import esphomelib_ns, Nameable, Trigger, NoArg, Component, App, bool_
|
||||
from esphomeyaml.py_compat import string_types
|
||||
|
||||
DEVICE_CLASSES = [
|
||||
'', 'battery', 'cold', 'connectivity', 'door', 'garage_door', 'gas',
|
||||
|
@ -70,7 +71,7 @@ MULTI_CLICK_TIMING_SCHEMA = vol.Schema({
|
|||
|
||||
|
||||
def parse_multi_click_timing_str(value):
|
||||
if not isinstance(value, basestring):
|
||||
if not isinstance(value, string_types):
|
||||
return value
|
||||
|
||||
parts = value.lower().split(' ')
|
||||
|
|
|
@ -73,40 +73,40 @@ def receiver_base(full_config):
|
|||
key, config = next((k, v) for k, v in full_config.items() if k in REMOTE_KEYS)
|
||||
if key == CONF_LG:
|
||||
return LGReceiver.new(name, config[CONF_DATA], config[CONF_NBITS])
|
||||
elif key == CONF_NEC:
|
||||
if key == CONF_NEC:
|
||||
return NECReceiver.new(name, config[CONF_ADDRESS], config[CONF_COMMAND])
|
||||
elif key == CONF_PANASONIC:
|
||||
if key == CONF_PANASONIC:
|
||||
return PanasonicReceiver.new(name, config[CONF_ADDRESS], config[CONF_COMMAND])
|
||||
elif key == CONF_SAMSUNG:
|
||||
if key == CONF_SAMSUNG:
|
||||
return SamsungReceiver.new(name, config[CONF_DATA])
|
||||
elif key == CONF_SONY:
|
||||
if key == CONF_SONY:
|
||||
return SonyReceiver.new(name, config[CONF_DATA], config[CONF_NBITS])
|
||||
elif key == CONF_RAW:
|
||||
if key == CONF_RAW:
|
||||
data = ArrayInitializer(*config, multiline=False)
|
||||
return RawReceiver.new(name, data)
|
||||
elif key == CONF_RC_SWITCH_RAW:
|
||||
if key == CONF_RC_SWITCH_RAW:
|
||||
return RCSwitchRawReceiver.new(name, build_rc_switch_protocol(config[CONF_PROTOCOL]),
|
||||
binary_code(config[CONF_CODE]), len(config[CONF_CODE]))
|
||||
elif key == CONF_RC_SWITCH_TYPE_A:
|
||||
if key == CONF_RC_SWITCH_TYPE_A:
|
||||
return RCSwitchTypeAReceiver.new(name, build_rc_switch_protocol(config[CONF_PROTOCOL]),
|
||||
binary_code(config[CONF_GROUP]),
|
||||
binary_code(config[CONF_DEVICE]),
|
||||
config[CONF_STATE])
|
||||
elif key == CONF_RC_SWITCH_TYPE_B:
|
||||
if key == CONF_RC_SWITCH_TYPE_B:
|
||||
return RCSwitchTypeBReceiver.new(name, build_rc_switch_protocol(config[CONF_PROTOCOL]),
|
||||
config[CONF_ADDRESS], config[CONF_CHANNEL],
|
||||
config[CONF_STATE])
|
||||
elif key == CONF_RC_SWITCH_TYPE_C:
|
||||
if key == CONF_RC_SWITCH_TYPE_C:
|
||||
return RCSwitchTypeCReceiver.new(name, build_rc_switch_protocol(config[CONF_PROTOCOL]),
|
||||
ord(config[CONF_FAMILY][0]) - ord('a'),
|
||||
config[CONF_GROUP], config[CONF_DEVICE],
|
||||
config[CONF_STATE])
|
||||
elif key == CONF_RC_SWITCH_TYPE_D:
|
||||
if key == CONF_RC_SWITCH_TYPE_D:
|
||||
return RCSwitchTypeDReceiver.new(name, build_rc_switch_protocol(config[CONF_PROTOCOL]),
|
||||
ord(config[CONF_GROUP][0]) - ord('a'),
|
||||
config[CONF_DEVICE], config[CONF_STATE])
|
||||
else:
|
||||
raise NotImplementedError("Unknown receiver type {}".format(config))
|
||||
|
||||
raise NotImplementedError("Unknown receiver type {}".format(config))
|
||||
|
||||
|
||||
def to_code(config):
|
||||
|
|
|
@ -33,10 +33,9 @@ def validate_glyphs(value):
|
|||
|
||||
if len(x_) < len(y_):
|
||||
return -1
|
||||
elif len(x_) > len(y_):
|
||||
if len(x_) > len(y_):
|
||||
return 1
|
||||
else:
|
||||
raise vol.Invalid(u"Found duplicate glyph {}".format(x))
|
||||
raise vol.Invalid(u"Found duplicate glyph {}".format(x))
|
||||
|
||||
value.sort(cmp=comparator)
|
||||
return value
|
||||
|
@ -47,11 +46,11 @@ def validate_pillow_installed(value):
|
|||
import PIL
|
||||
except ImportError:
|
||||
raise vol.Invalid("Please install the pillow python package to use this feature. "
|
||||
"(pip2 install pillow)")
|
||||
"(pip install pillow)")
|
||||
|
||||
if PIL.__version__[0] < '4':
|
||||
raise vol.Invalid("Please update your pillow installation to at least 4.0.x. "
|
||||
"(pip2 install -U pillow)")
|
||||
"(pip install -U pillow)")
|
||||
|
||||
return value
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@ from esphomeyaml.core import EsphomeyamlError, Lambda, CORE
|
|||
from esphomeyaml.cpp_generator import Pvariable, RawExpression, add, process_lambda, statement
|
||||
from esphomeyaml.cpp_types import App, Component, esphomelib_ns, global_ns
|
||||
|
||||
from esphomeyaml.py_compat import text_type
|
||||
|
||||
LOG_LEVELS = {
|
||||
'NONE': global_ns.ESPHOMELIB_LOG_LEVEL_NONE,
|
||||
'ERROR': global_ns.ESPHOMELIB_LOG_LEVEL_ERROR,
|
||||
|
@ -37,7 +39,7 @@ is_log_level = cv.one_of(*LOG_LEVELS, upper=True)
|
|||
|
||||
def validate_local_no_higher_than_global(value):
|
||||
global_level = value.get(CONF_LEVEL, 'DEBUG')
|
||||
for tag, level in value.get(CONF_LOGS, {}).iteritems():
|
||||
for tag, level in value.get(CONF_LOGS, {}).items():
|
||||
if LOG_LEVEL_SEVERITY.index(level) > LOG_LEVEL_SEVERITY.index(global_level):
|
||||
raise EsphomeyamlError(u"The local log level {} for {} must be less severe than the "
|
||||
u"global log level {}.".format(level, tag, global_level))
|
||||
|
@ -64,7 +66,7 @@ def to_code(config):
|
|||
add(log.set_tx_buffer_size(config[CONF_TX_BUFFER_SIZE]))
|
||||
if CONF_LEVEL in config:
|
||||
add(log.set_global_log_level(LOG_LEVELS[config[CONF_LEVEL]]))
|
||||
for tag, level in config.get(CONF_LOGS, {}).iteritems():
|
||||
for tag, level in config.get(CONF_LOGS, {}).items():
|
||||
add(log.set_log_level(tag, LOG_LEVELS[level]))
|
||||
|
||||
|
||||
|
@ -120,7 +122,7 @@ def validate_printf(value):
|
|||
[cCdiouxXeEfgGaAnpsSZ] # type
|
||||
) | # OR
|
||||
%%) # literal "%%"
|
||||
"""
|
||||
""" # noqa
|
||||
matches = re.findall(cfmt, value[CONF_FORMAT], flags=re.X)
|
||||
if len(matches) != len(value[CONF_ARGS]):
|
||||
raise vol.Invalid(u"Found {} printf-patterns ({}), but {} args were given!"
|
||||
|
@ -140,9 +142,9 @@ LOGGER_LOG_ACTION_SCHEMA = vol.All(maybe_simple_message({
|
|||
@ACTION_REGISTRY.register(CONF_LOGGER_LOG, LOGGER_LOG_ACTION_SCHEMA)
|
||||
def logger_log_action_to_code(config, action_id, arg_type, template_arg):
|
||||
esp_log = LOG_LEVEL_TO_ESP_LOG[config[CONF_LEVEL]]
|
||||
args = [RawExpression(unicode(x)) for x in config[CONF_ARGS]]
|
||||
args = [RawExpression(text_type(x)) for x in config[CONF_ARGS]]
|
||||
|
||||
text = unicode(statement(esp_log(config[CONF_TAG], config[CONF_FORMAT], *args)))
|
||||
text = text_type(statement(esp_log(config[CONF_TAG], config[CONF_FORMAT], *args)))
|
||||
|
||||
for lambda_ in process_lambda(Lambda(text), [(arg_type, 'x')]):
|
||||
yield None
|
||||
|
|
|
@ -36,7 +36,7 @@ def get_port(config):
|
|||
return config[CONF_OTA][CONF_PORT]
|
||||
if CORE.is_esp32:
|
||||
return 3232
|
||||
elif CORE.is_esp8266:
|
||||
if CORE.is_esp8266:
|
||||
return 8266
|
||||
raise NotImplementedError
|
||||
|
||||
|
@ -52,6 +52,6 @@ REQUIRED_BUILD_FLAGS = '-DUSE_NEW_OTA'
|
|||
def lib_deps(config):
|
||||
if CORE.is_esp32:
|
||||
return ['Update', 'ESPmDNS']
|
||||
elif CORE.is_esp8266:
|
||||
if CORE.is_esp8266:
|
||||
return ['Hash', 'ESP8266mDNS']
|
||||
raise NotImplementedError
|
||||
|
|
|
@ -37,7 +37,7 @@ def validate_custom_output(value):
|
|||
value[CONF_TYPE] = type
|
||||
if type == 'binary':
|
||||
return BINARY_SCHEMA(value)
|
||||
elif type == 'float':
|
||||
if type == 'float':
|
||||
return FLOAT_SCHEMA(value)
|
||||
raise vol.Invalid("type must either be binary or float, not {}!".format(type))
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ from esphomeyaml.const import CONF_BUFFER_SIZE, CONF_DUMP, CONF_FILTER, CONF_ID,
|
|||
from esphomeyaml.cpp_generator import Pvariable, add
|
||||
from esphomeyaml.cpp_helpers import gpio_input_pin_expression, setup_component
|
||||
from esphomeyaml.cpp_types import App, Component, esphomelib_ns
|
||||
from esphomeyaml.py_compat import string_types
|
||||
|
||||
remote_ns = esphomelib_ns.namespace('remote')
|
||||
MULTI_CONF = True
|
||||
|
@ -30,7 +31,7 @@ DUMPERS = {
|
|||
|
||||
|
||||
def validate_dumpers_all(value):
|
||||
if not isinstance(value, (str, unicode)):
|
||||
if not isinstance(value, string_types):
|
||||
raise vol.Invalid("Not valid dumpers")
|
||||
if value.upper() == "ALL":
|
||||
return list(sorted(list(DUMPERS)))
|
||||
|
|
|
@ -10,6 +10,7 @@ from esphomeyaml.core import HexInt
|
|||
from esphomeyaml.cpp_generator import Pvariable, add
|
||||
from esphomeyaml.cpp_helpers import gpio_output_pin_expression, setup_component
|
||||
from esphomeyaml.cpp_types import App, Component
|
||||
from esphomeyaml.py_compat import text_type
|
||||
|
||||
RemoteTransmitterComponent = remote_ns.class_('RemoteTransmitterComponent',
|
||||
RemoteControlComponentBase, Component)
|
||||
|
@ -20,7 +21,7 @@ MULTI_CONF = True
|
|||
|
||||
|
||||
def validate_rc_switch_code(value):
|
||||
if not isinstance(value, (str, unicode)):
|
||||
if not isinstance(value, (str, text_type)):
|
||||
raise vol.Invalid("All RCSwitch codes must be in quotes ('')")
|
||||
for c in value:
|
||||
if c not in ('0', '1'):
|
||||
|
|
|
@ -6,6 +6,7 @@ import esphomeyaml.config_validation as cv
|
|||
from esphomeyaml.const import CONF_ADS1115_ID, CONF_GAIN, CONF_MULTIPLEXER, CONF_NAME, \
|
||||
CONF_UPDATE_INTERVAL
|
||||
from esphomeyaml.cpp_generator import get_variable
|
||||
from esphomeyaml.py_compat import string_types
|
||||
|
||||
DEPENDENCIES = ['ads1115']
|
||||
|
||||
|
@ -35,7 +36,7 @@ GAIN = {
|
|||
def validate_gain(value):
|
||||
if isinstance(value, float):
|
||||
value = u'{:0.03f}'.format(value)
|
||||
elif not isinstance(value, (str, unicode)):
|
||||
elif not isinstance(value, string_types):
|
||||
raise vol.Invalid('invalid gain "{}"'.format(value))
|
||||
|
||||
return cv.one_of(*GAIN)(value)
|
||||
|
|
|
@ -36,7 +36,7 @@ SENSORS_TO_TYPE = {
|
|||
|
||||
|
||||
def validate_pmsx003_sensors(value):
|
||||
for key, types in SENSORS_TO_TYPE.iteritems():
|
||||
for key, types in SENSORS_TO_TYPE.items():
|
||||
if key in value and value[CONF_TYPE] not in types:
|
||||
raise vol.Invalid(u"{} does not have {} sensor!".format(value[CONF_TYPE], key))
|
||||
return value
|
||||
|
|
|
@ -35,8 +35,8 @@ def validate_internal_filter(value):
|
|||
if value.total_microseconds > 13:
|
||||
raise vol.Invalid("Maximum internal filter value for ESP32 is 13us")
|
||||
return value
|
||||
else:
|
||||
return cv.positive_time_period_microseconds(value)
|
||||
|
||||
return cv.positive_time_period_microseconds(value)
|
||||
|
||||
|
||||
PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({
|
||||
|
|
|
@ -61,8 +61,8 @@ def _expand_substitutions(substitutions, value, path):
|
|||
if name.startswith(u'{') and name.endswith(u'}'):
|
||||
name = name[1:-1]
|
||||
if name not in substitutions:
|
||||
_LOGGER.warn(u"Found '%s' (see %s) which looks like a substitution, but '%s' was not "
|
||||
u"declared", orig_value, u'->'.join(str(x) for x in path), name)
|
||||
_LOGGER.warning(u"Found '%s' (see %s) which looks like a substitution, but '%s' was "
|
||||
u"not declared", orig_value, u'->'.join(str(x) for x in path), name)
|
||||
i = j
|
||||
continue
|
||||
|
||||
|
@ -82,7 +82,7 @@ def _substitute_item(substitutions, item, path):
|
|||
item[i] = sub
|
||||
elif isinstance(item, dict):
|
||||
replace_keys = []
|
||||
for k, v in item.iteritems():
|
||||
for k, v in item.items():
|
||||
if path or k != CONF_SUBSTITUTIONS:
|
||||
sub = _substitute_item(substitutions, k, path + [k])
|
||||
if sub is not None:
|
||||
|
@ -116,7 +116,7 @@ def do_substitution_pass(config):
|
|||
key = ''
|
||||
try:
|
||||
replace_keys = []
|
||||
for key, value in substitutions.iteritems():
|
||||
for key, value in substitutions.items():
|
||||
sub = validate_substitution_key(key)
|
||||
if sub != key:
|
||||
replace_keys.append((key, sub))
|
||||
|
|
|
@ -85,15 +85,15 @@ def transmitter_base(full_config):
|
|||
|
||||
if key == CONF_LG:
|
||||
return LGTransmitter.new(name, config[CONF_DATA], config[CONF_NBITS])
|
||||
elif key == CONF_NEC:
|
||||
if key == CONF_NEC:
|
||||
return NECTransmitter.new(name, config[CONF_ADDRESS], config[CONF_COMMAND])
|
||||
elif key == CONF_PANASONIC:
|
||||
if key == CONF_PANASONIC:
|
||||
return PanasonicTransmitter.new(name, config[CONF_ADDRESS], config[CONF_COMMAND])
|
||||
elif key == CONF_SAMSUNG:
|
||||
if key == CONF_SAMSUNG:
|
||||
return SamsungTransmitter.new(name, config[CONF_DATA])
|
||||
elif key == CONF_SONY:
|
||||
if key == CONF_SONY:
|
||||
return SonyTransmitter.new(name, config[CONF_DATA], config[CONF_NBITS])
|
||||
elif key == CONF_RAW:
|
||||
if key == CONF_RAW:
|
||||
if isinstance(config, dict):
|
||||
data = config[CONF_DATA]
|
||||
carrier_frequency = config.get(CONF_CARRIER_FREQUENCY)
|
||||
|
@ -102,29 +102,29 @@ def transmitter_base(full_config):
|
|||
carrier_frequency = None
|
||||
return RawTransmitter.new(name, ArrayInitializer(*data, multiline=False),
|
||||
carrier_frequency)
|
||||
elif key == CONF_RC_SWITCH_RAW:
|
||||
if key == CONF_RC_SWITCH_RAW:
|
||||
return RCSwitchRawTransmitter.new(name, build_rc_switch_protocol(config[CONF_PROTOCOL]),
|
||||
binary_code(config[CONF_CODE]), len(config[CONF_CODE]))
|
||||
elif key == CONF_RC_SWITCH_TYPE_A:
|
||||
if key == CONF_RC_SWITCH_TYPE_A:
|
||||
return RCSwitchTypeATransmitter.new(name, build_rc_switch_protocol(config[CONF_PROTOCOL]),
|
||||
binary_code(config[CONF_GROUP]),
|
||||
binary_code(config[CONF_DEVICE]),
|
||||
config[CONF_STATE])
|
||||
elif key == CONF_RC_SWITCH_TYPE_B:
|
||||
if key == CONF_RC_SWITCH_TYPE_B:
|
||||
return RCSwitchTypeBTransmitter.new(name, build_rc_switch_protocol(config[CONF_PROTOCOL]),
|
||||
config[CONF_ADDRESS], config[CONF_CHANNEL],
|
||||
config[CONF_STATE])
|
||||
elif key == CONF_RC_SWITCH_TYPE_C:
|
||||
if key == CONF_RC_SWITCH_TYPE_C:
|
||||
return RCSwitchTypeCTransmitter.new(name, build_rc_switch_protocol(config[CONF_PROTOCOL]),
|
||||
ord(config[CONF_FAMILY][0]) - ord('a'),
|
||||
config[CONF_GROUP], config[CONF_DEVICE],
|
||||
config[CONF_STATE])
|
||||
elif key == CONF_RC_SWITCH_TYPE_D:
|
||||
if key == CONF_RC_SWITCH_TYPE_D:
|
||||
return RCSwitchTypeDTransmitter.new(name, build_rc_switch_protocol(config[CONF_PROTOCOL]),
|
||||
ord(config[CONF_GROUP][0]) - ord('a'),
|
||||
config[CONF_DEVICE], config[CONF_STATE])
|
||||
else:
|
||||
raise NotImplementedError("Unknown transmitter type {}".format(config))
|
||||
|
||||
raise NotImplementedError("Unknown transmitter type {}".format(config))
|
||||
|
||||
|
||||
def to_code(config):
|
||||
|
|
|
@ -7,6 +7,7 @@ from esphomeyaml.const import CONF_DATA, CONF_INVERTED, CONF_MAKE_ID, CONF_NAME,
|
|||
from esphomeyaml.core import HexInt
|
||||
from esphomeyaml.cpp_generator import ArrayInitializer, get_variable, variable
|
||||
from esphomeyaml.cpp_types import App, Application
|
||||
from esphomeyaml.py_compat import text_type
|
||||
|
||||
DEPENDENCIES = ['uart']
|
||||
|
||||
|
@ -15,11 +16,11 @@ UARTSwitch = switch.switch_ns.class_('UARTSwitch', switch.Switch, uart.UARTDevic
|
|||
|
||||
|
||||
def validate_data(value):
|
||||
if isinstance(value, unicode):
|
||||
if isinstance(value, text_type):
|
||||
return value.encode('utf-8')
|
||||
elif isinstance(value, str):
|
||||
if isinstance(value, str):
|
||||
return value
|
||||
elif isinstance(value, list):
|
||||
if isinstance(value, list):
|
||||
return vol.Schema([cv.hex_uint8_t])(value)
|
||||
raise vol.Invalid("data must either be a string wrapped in quotes or a list of bytes")
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ from esphomeyaml.const import CONF_CRON, CONF_DAYS_OF_MONTH, CONF_DAYS_OF_WEEK,
|
|||
from esphomeyaml.core import CORE
|
||||
from esphomeyaml.cpp_generator import add, Pvariable, ArrayInitializer
|
||||
from esphomeyaml.cpp_types import esphomelib_ns, Component, NoArg, Trigger, App
|
||||
from esphomeyaml.py_compat import string_types
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
@ -30,9 +31,9 @@ def _tz_timedelta(td):
|
|||
offset_second = int(abs(td.total_seconds())) % 60
|
||||
if offset_hour == 0 and offset_minute == 0 and offset_second == 0:
|
||||
return '0'
|
||||
elif offset_minute == 0 and offset_second == 0:
|
||||
if offset_minute == 0 and offset_second == 0:
|
||||
return '{}'.format(offset_hour)
|
||||
elif offset_second == 0:
|
||||
if offset_second == 0:
|
||||
return '{}:{}'.format(offset_hour, offset_minute)
|
||||
return '{}:{}:{}'.format(offset_hour, offset_minute, offset_second)
|
||||
|
||||
|
@ -119,7 +120,7 @@ def detect_tz():
|
|||
import pytz
|
||||
except ImportError:
|
||||
raise vol.Invalid("No timezone specified and 'tzlocal' not installed. To automatically "
|
||||
"detect the timezone please install tzlocal (pip2 install tzlocal)")
|
||||
"detect the timezone please install tzlocal (pip install tzlocal)")
|
||||
try:
|
||||
tz = tzlocal.get_localzone()
|
||||
except pytz.exceptions.UnknownTimeZoneError:
|
||||
|
@ -131,7 +132,7 @@ def detect_tz():
|
|||
|
||||
def _parse_cron_int(value, special_mapping, message):
|
||||
special_mapping = special_mapping or {}
|
||||
if isinstance(value, (str, unicode)) and value in special_mapping:
|
||||
if isinstance(value, string_types) and value in special_mapping:
|
||||
return special_mapping[value]
|
||||
try:
|
||||
return int(value)
|
||||
|
@ -140,7 +141,7 @@ def _parse_cron_int(value, special_mapping, message):
|
|||
|
||||
|
||||
def _parse_cron_part(part, min_value, max_value, special_mapping):
|
||||
if part == '*' or part == '?':
|
||||
if part in ('*', '?'):
|
||||
return set(x for x in range(min_value, max_value + 1))
|
||||
if '/' in part:
|
||||
data = part.split('/')
|
||||
|
|
|
@ -171,6 +171,6 @@ def to_code(config):
|
|||
def lib_deps(config):
|
||||
if CORE.is_esp8266:
|
||||
return 'ESP8266WiFi'
|
||||
elif CORE.is_esp32:
|
||||
if CORE.is_esp32:
|
||||
return None
|
||||
raise NotImplementedError
|
||||
|
|
|
@ -13,6 +13,7 @@ from esphomeyaml.components import substitutions
|
|||
from esphomeyaml.const import CONF_ESPHOMEYAML, CONF_PLATFORM, ESP_PLATFORMS
|
||||
from esphomeyaml.core import CORE, EsphomeyamlError
|
||||
from esphomeyaml.helpers import color, indent
|
||||
from esphomeyaml.py_compat import text_type
|
||||
from esphomeyaml.util import safe_print
|
||||
|
||||
# pylint: disable=unused-import, wrong-import-order
|
||||
|
@ -50,7 +51,7 @@ def is_platform_component(component):
|
|||
|
||||
|
||||
def iter_components(config):
|
||||
for domain, conf in config.iteritems():
|
||||
for domain, conf in config.items():
|
||||
if domain == CONF_ESPHOMEYAML:
|
||||
yield CONF_ESPHOMEYAML, core_config, conf
|
||||
continue
|
||||
|
@ -67,7 +68,7 @@ def iter_components(config):
|
|||
yield p_name, platform, p_config
|
||||
|
||||
|
||||
ConfigPath = List[Union[basestring, int]]
|
||||
ConfigPath = List[Union[str, int]]
|
||||
|
||||
|
||||
def _path_begins_with_(path, other): # type: (ConfigPath, ConfigPath) -> bool
|
||||
|
@ -90,8 +91,8 @@ class Config(OrderedDict):
|
|||
|
||||
def add_error(self, message, path):
|
||||
# type: (basestring, ConfigPath) -> None
|
||||
if not isinstance(message, unicode):
|
||||
message = unicode(message)
|
||||
if not isinstance(message, text_type):
|
||||
message = text_type(message)
|
||||
self.errors.append((message, path))
|
||||
|
||||
def add_domain(self, path, name):
|
||||
|
@ -158,7 +159,7 @@ def iter_ids(config, path=None):
|
|||
for result in iter_ids(item, path + [i]):
|
||||
yield result
|
||||
elif isinstance(config, dict):
|
||||
for key, value in config.iteritems():
|
||||
for key, value in config.items():
|
||||
for result in iter_ids(value, path + [key]):
|
||||
yield result
|
||||
|
||||
|
@ -229,7 +230,7 @@ def validate_config(config):
|
|||
result.add_domain([CONF_ESPHOMEYAML], CONF_ESPHOMEYAML)
|
||||
result[CONF_ESPHOMEYAML] = config[CONF_ESPHOMEYAML]
|
||||
|
||||
for domain, conf in config.iteritems():
|
||||
for domain, conf in config.items():
|
||||
domain = str(domain)
|
||||
if domain == CONF_ESPHOMEYAML or domain.startswith(u'.'):
|
||||
skip_paths.append([domain])
|
||||
|
@ -337,7 +338,7 @@ def validate_config(config):
|
|||
except vol.Invalid as ex:
|
||||
_comp_error(ex, [CONF_ESPHOMEYAML])
|
||||
|
||||
for domain, conf in result.iteritems():
|
||||
for domain, conf in result.items():
|
||||
domain = str(domain)
|
||||
if [domain] in skip_paths:
|
||||
continue
|
||||
|
@ -401,7 +402,7 @@ def humanize_error(config, validation_error):
|
|||
offending_item_summary = json.dumps(offending_item_summary)
|
||||
except (TypeError, ValueError):
|
||||
pass
|
||||
validation_error = unicode(validation_error)
|
||||
validation_error = text_type(validation_error)
|
||||
m = re.match(r'^(.*?)\s*(?:for dictionary value )?@ data\[.*$', validation_error)
|
||||
if m is not None:
|
||||
validation_error = m.group(1)
|
||||
|
@ -514,7 +515,7 @@ def dump_dict(config, path, at_root=True):
|
|||
ret += u'{}'
|
||||
multiline = False
|
||||
|
||||
for k in conf.iterkeys():
|
||||
for k in conf.keys():
|
||||
path_ = path + [k]
|
||||
error = config.get_error_for_path(path_)
|
||||
if error is not None:
|
||||
|
@ -543,9 +544,9 @@ def dump_dict(config, path, at_root=True):
|
|||
conf = u'|-\n' + indent(conf)
|
||||
error = config.get_error_for_path(path)
|
||||
col = 'bold_red' if error else 'white'
|
||||
ret += color(col, unicode(conf))
|
||||
ret += color(col, text_type(conf))
|
||||
elif isinstance(conf, core.Lambda):
|
||||
conf = u'!lambda |-\n' + indent(unicode(conf.value))
|
||||
conf = u'!lambda |-\n' + indent(text_type(conf.value))
|
||||
error = config.get_error_for_path(path)
|
||||
col = 'bold_red' if error else 'white'
|
||||
ret += color(col, conf)
|
||||
|
@ -554,7 +555,7 @@ def dump_dict(config, path, at_root=True):
|
|||
else:
|
||||
error = config.get_error_for_path(path)
|
||||
col = 'bold_red' if error else 'white'
|
||||
ret += color(col, unicode(conf))
|
||||
ret += color(col, text_type(conf))
|
||||
multiline = u'\n' in ret
|
||||
|
||||
return ret, multiline
|
||||
|
@ -571,7 +572,7 @@ def strip_default_ids(config):
|
|||
config.remove(x)
|
||||
elif isinstance(config, dict):
|
||||
to_remove = []
|
||||
for k, v in config.iteritems():
|
||||
for k, v in config.items():
|
||||
v = config[k] = strip_default_ids(v)
|
||||
if isinstance(v, core.ID) and not v.is_manual:
|
||||
to_remove.append(k)
|
||||
|
|
|
@ -16,6 +16,7 @@ from esphomeyaml.const import CONF_AVAILABILITY, CONF_COMMAND_TOPIC, CONF_DISCOV
|
|||
ESP_PLATFORM_ESP8266
|
||||
from esphomeyaml.core import CORE, HexInt, IPAddress, Lambda, TimePeriod, TimePeriodMicroseconds, \
|
||||
TimePeriodMilliseconds, TimePeriodSeconds
|
||||
from esphomeyaml.py_compat import text_type, string_types, integer_types
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
@ -51,7 +52,7 @@ RESERVED_IDS = [
|
|||
def alphanumeric(value):
|
||||
if value is None:
|
||||
raise vol.Invalid("string value is None")
|
||||
value = unicode(value)
|
||||
value = text_type(value)
|
||||
if not value.isalnum():
|
||||
raise vol.Invalid("string value is not alphanumeric")
|
||||
return value
|
||||
|
@ -70,13 +71,13 @@ def string(value):
|
|||
if isinstance(value, (dict, list)):
|
||||
raise vol.Invalid("string value cannot be dictionary or list.")
|
||||
if value is not None:
|
||||
return unicode(value)
|
||||
return text_type(value)
|
||||
raise vol.Invalid("string value is None")
|
||||
|
||||
|
||||
def string_strict(value):
|
||||
"""Strictly only allow strings."""
|
||||
if isinstance(value, (str, unicode)):
|
||||
if isinstance(value, string_types):
|
||||
return value
|
||||
raise vol.Invalid("Must be string, got {}. did you forget putting quotes "
|
||||
"around the value?".format(type(value)))
|
||||
|
@ -138,7 +139,7 @@ def ensure_dict(value):
|
|||
|
||||
|
||||
def hex_int_(value):
|
||||
if isinstance(value, (int, long)):
|
||||
if isinstance(value, integer_types):
|
||||
return HexInt(value)
|
||||
value = string_strict(value).lower()
|
||||
if value.startswith('0x'):
|
||||
|
@ -147,7 +148,7 @@ def hex_int_(value):
|
|||
|
||||
|
||||
def int_(value):
|
||||
if isinstance(value, (int, long)):
|
||||
if isinstance(value, integer_types):
|
||||
return value
|
||||
value = string_strict(value).lower()
|
||||
if value.startswith('0x'):
|
||||
|
@ -310,9 +311,9 @@ def time_period_str_colon(value):
|
|||
def time_period_str_unit(value):
|
||||
"""Validate and transform time period with time unit and integer value."""
|
||||
if isinstance(value, int):
|
||||
raise vol.Invalid("Don't know what '{}' means as it has no time *unit*! Did you mean "
|
||||
"'{}s'?".format(value, value))
|
||||
elif not isinstance(value, (str, unicode)):
|
||||
raise vol.Invalid("Don't know what '{0}' means as it has no time *unit*! Did you mean "
|
||||
"'{0}s'?".format(value))
|
||||
elif not isinstance(value, string_types):
|
||||
raise vol.Invalid("Expected string for time period with unit.")
|
||||
|
||||
unit_to_kwarg = {
|
||||
|
@ -489,7 +490,7 @@ def ssid(value):
|
|||
def ipv4(value):
|
||||
if isinstance(value, list):
|
||||
parts = value
|
||||
elif isinstance(value, basestring):
|
||||
elif isinstance(value, string_types):
|
||||
parts = value.split('.')
|
||||
elif isinstance(value, IPAddress):
|
||||
return value
|
||||
|
@ -579,7 +580,7 @@ i2c_address = hex_uint8_t
|
|||
|
||||
|
||||
def percentage(value):
|
||||
has_percent_sign = isinstance(value, (str, unicode)) and value.endswith('%')
|
||||
has_percent_sign = isinstance(value, string_types) and value.endswith('%')
|
||||
if has_percent_sign:
|
||||
value = float(value[:-1].rstrip()) / 100.0
|
||||
if value > 1:
|
||||
|
@ -591,7 +592,7 @@ def percentage(value):
|
|||
|
||||
|
||||
def percentage_int(value):
|
||||
if isinstance(value, (str, unicode)) and value.endswith('%'):
|
||||
if isinstance(value, string_types) and value.endswith('%'):
|
||||
value = int(value[:-1].rstrip())
|
||||
return value
|
||||
|
||||
|
|
|
@ -13,15 +13,22 @@ from esphomeyaml.helpers import ensure_unique_string
|
|||
# pylint: disable=unused-import, wrong-import-order
|
||||
from typing import Any, Dict, List # noqa
|
||||
|
||||
from esphomeyaml.py_compat import integer_types, IS_PY2
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class EsphomeyamlError(Exception):
|
||||
"""General esphomeyaml exception occurred."""
|
||||
pass
|
||||
|
||||
|
||||
class HexInt(long):
|
||||
if IS_PY2:
|
||||
base_int = long
|
||||
else:
|
||||
base_int = int
|
||||
|
||||
|
||||
class HexInt(base_int):
|
||||
def __str__(self):
|
||||
if 0 <= self <= 255:
|
||||
return "0x{:02X}".format(self)
|
||||
|
@ -55,7 +62,7 @@ class MACAddress(object):
|
|||
|
||||
|
||||
def is_approximately_integer(value):
|
||||
if isinstance(value, (int, long)):
|
||||
if isinstance(value, integer_types):
|
||||
return True
|
||||
return abs(value - round(value)) < 0.001
|
||||
|
||||
|
@ -379,7 +386,7 @@ class EsphomeyamlCore(object):
|
|||
task, domain = self.pending_tasks.popleft()
|
||||
_LOGGER.debug("Executing task for domain=%s", domain)
|
||||
try:
|
||||
task.next()
|
||||
next(task)
|
||||
self.pending_tasks.append((task, domain))
|
||||
except StopIteration:
|
||||
_LOGGER.debug(" -> %s finished", domain)
|
||||
|
@ -404,7 +411,7 @@ class EsphomeyamlCore(object):
|
|||
def get_variable_with_full_id(self, id):
|
||||
while True:
|
||||
if id in self.variables:
|
||||
for k, v in self.variables.iteritems():
|
||||
for k, v in self.variables.items():
|
||||
if k == id:
|
||||
yield (k, v)
|
||||
return
|
||||
|
|
|
@ -15,6 +15,7 @@ from esphomeyaml.const import ARDUINO_VERSION_ESP32_DEV, ARDUINO_VERSION_ESP8266
|
|||
from esphomeyaml.core import CORE, EsphomeyamlError
|
||||
from esphomeyaml.cpp_generator import Pvariable, RawExpression, add
|
||||
from esphomeyaml.cpp_types import App, NoArg, const_char_ptr, esphomelib_ns
|
||||
from esphomeyaml.py_compat import text_type
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
@ -52,12 +53,12 @@ def validate_simple_esphomelib_version(value):
|
|||
CONF_REPOSITORY: LIBRARY_URI_REPO,
|
||||
CONF_TAG: 'v' + ESPHOMELIB_VERSION,
|
||||
}
|
||||
elif value.upper() == 'DEV':
|
||||
if value.upper() == 'DEV':
|
||||
return {
|
||||
CONF_REPOSITORY: LIBRARY_URI_REPO,
|
||||
CONF_BRANCH: 'dev'
|
||||
}
|
||||
elif VERSION_REGEX.match(value) is not None:
|
||||
if VERSION_REGEX.match(value) is not None:
|
||||
return {
|
||||
CONF_REPOSITORY: LIBRARY_URI_REPO,
|
||||
CONF_TAG: 'v' + value,
|
||||
|
@ -139,7 +140,7 @@ def validate_arduino_version(value):
|
|||
if value_ in PLATFORMIO_ESP8266_LUT:
|
||||
return PLATFORMIO_ESP8266_LUT[value_]
|
||||
return value
|
||||
elif CORE.is_esp32:
|
||||
if CORE.is_esp32:
|
||||
if VERSION_REGEX.match(value) is not None and value_ not in PLATFORMIO_ESP32_LUT:
|
||||
raise vol.Invalid("Unfortunately the arduino framework version '{}' is unsupported "
|
||||
"at this time. You can override this by manually using "
|
||||
|
@ -206,7 +207,7 @@ def preload_core_config(config):
|
|||
CORE.build_path = CORE.relative_path(
|
||||
cv.string(core_conf.get(CONF_BUILD_PATH, default_build_path())))
|
||||
except vol.Invalid as e:
|
||||
raise EsphomeyamlError(unicode(e))
|
||||
raise EsphomeyamlError(text_type(e))
|
||||
|
||||
|
||||
def to_code(config):
|
||||
|
|
|
@ -7,6 +7,7 @@ from esphomeyaml.helpers import cpp_string_escape, indent_all_but_first_and_last
|
|||
# pylint: disable=unused-import, wrong-import-order
|
||||
from typing import Any, Generator, List, Optional, Tuple, Union # noqa
|
||||
from esphomeyaml.core import ID # noqa
|
||||
from esphomeyaml.py_compat import text_type, string_types, integer_types
|
||||
|
||||
|
||||
class Expression(object):
|
||||
|
@ -28,7 +29,7 @@ class Expression(object):
|
|||
return self.required
|
||||
|
||||
|
||||
SafeExpType = Union[Expression, bool, str, unicode, int, long, float, TimePeriod]
|
||||
SafeExpType = Union[Expression, bool, str, text_type, int, float, TimePeriod]
|
||||
|
||||
|
||||
class RawExpression(Expression):
|
||||
|
@ -73,7 +74,7 @@ class ExpressionList(Expression):
|
|||
self.args.append(exp)
|
||||
|
||||
def __str__(self):
|
||||
text = u", ".join(unicode(x) for x in self.args)
|
||||
text = u", ".join(text_type(x) for x in self.args)
|
||||
return indent_all_but_first_and_last(text)
|
||||
|
||||
|
||||
|
@ -115,7 +116,7 @@ class StructInitializer(Expression):
|
|||
if not isinstance(args, OrderedDict):
|
||||
args = OrderedDict(args)
|
||||
self.args = OrderedDict()
|
||||
for key, value in args.iteritems():
|
||||
for key, value in args.items():
|
||||
if value is None:
|
||||
continue
|
||||
exp = safe_exp(value)
|
||||
|
@ -124,7 +125,7 @@ class StructInitializer(Expression):
|
|||
|
||||
def __str__(self):
|
||||
cpp = u'{}{{\n'.format(self.base)
|
||||
for key, value in self.args.iteritems():
|
||||
for key, value in self.args.items():
|
||||
cpp += u' .{} = {},\n'.format(key, value)
|
||||
cpp += u'}'
|
||||
return cpp
|
||||
|
@ -176,7 +177,7 @@ class ParameterListExpression(Expression):
|
|||
self.requires.append(parameter)
|
||||
|
||||
def __str__(self):
|
||||
return u", ".join(unicode(x) for x in self.parameters)
|
||||
return u", ".join(text_type(x) for x in self.parameters)
|
||||
|
||||
|
||||
class LambdaExpression(Expression):
|
||||
|
@ -203,7 +204,7 @@ class LambdaExpression(Expression):
|
|||
|
||||
@property
|
||||
def content(self):
|
||||
return u''.join(unicode(part) for part in self.parts)
|
||||
return u''.join(text_type(part) for part in self.parts)
|
||||
|
||||
|
||||
class Literal(Expression):
|
||||
|
@ -232,7 +233,7 @@ class IntLiteral(Literal):
|
|||
return u'{}UL'.format(self.i)
|
||||
if self.i < -2147483648:
|
||||
return u'{}LL'.format(self.i)
|
||||
return unicode(self.i)
|
||||
return text_type(self.i)
|
||||
|
||||
|
||||
class BoolLiteral(Literal):
|
||||
|
@ -268,21 +269,21 @@ def safe_exp(obj # type: Union[Expression, bool, str, unicode, int, long, float
|
|||
# type: (...) -> Expression
|
||||
if isinstance(obj, Expression):
|
||||
return obj
|
||||
elif isinstance(obj, bool):
|
||||
if isinstance(obj, bool):
|
||||
return BoolLiteral(obj)
|
||||
elif isinstance(obj, (str, unicode)):
|
||||
if isinstance(obj, string_types):
|
||||
return StringLiteral(obj)
|
||||
elif isinstance(obj, HexInt):
|
||||
if isinstance(obj, HexInt):
|
||||
return HexIntLiteral(obj)
|
||||
elif isinstance(obj, (int, long)):
|
||||
if isinstance(obj, integer_types):
|
||||
return IntLiteral(obj)
|
||||
elif isinstance(obj, float):
|
||||
if isinstance(obj, float):
|
||||
return FloatLiteral(obj)
|
||||
elif isinstance(obj, TimePeriodMicroseconds):
|
||||
if isinstance(obj, TimePeriodMicroseconds):
|
||||
return IntLiteral(int(obj.total_microseconds))
|
||||
elif isinstance(obj, TimePeriodMilliseconds):
|
||||
if isinstance(obj, TimePeriodMilliseconds):
|
||||
return IntLiteral(int(obj.total_milliseconds))
|
||||
elif isinstance(obj, TimePeriodSeconds):
|
||||
if isinstance(obj, TimePeriodSeconds):
|
||||
return IntLiteral(int(obj.total_seconds))
|
||||
raise ValueError(u"Object is not an expression", obj)
|
||||
|
||||
|
@ -441,7 +442,7 @@ class MockObj(Expression):
|
|||
return obj
|
||||
|
||||
def __str__(self): # type: () -> unicode
|
||||
return unicode(self.base)
|
||||
return text_type(self.base)
|
||||
|
||||
def require(self): # type: () -> None
|
||||
self.required = True
|
||||
|
|
|
@ -20,11 +20,11 @@ def generic_gpio_pin_expression_(conf, mock_obj, default_mode):
|
|||
mode = pcf8574.PCF8675_GPIO_MODES[conf.get(CONF_MODE, u'INPUT')]
|
||||
yield hub.make_input_pin(number, mode, inverted)
|
||||
return
|
||||
elif default_mode == u'OUTPUT':
|
||||
if default_mode == u'OUTPUT':
|
||||
yield hub.make_output_pin(number, inverted)
|
||||
return
|
||||
else:
|
||||
raise EsphomeyamlError(u"Unknown default mode {}".format(default_mode))
|
||||
|
||||
raise EsphomeyamlError(u"Unknown default mode {}".format(default_mode))
|
||||
if len(conf) == 1:
|
||||
yield IntLiteral(number)
|
||||
return
|
||||
|
|
|
@ -176,7 +176,7 @@ class WizardRequestHandler(BaseHandler):
|
|||
if not self.is_authenticated():
|
||||
self.redirect('/login')
|
||||
return
|
||||
kwargs = {k: ''.join(v) for k, v in self.request.arguments.iteritems()}
|
||||
kwargs = {k: ''.join(v) for k, v in self.request.arguments.items()}
|
||||
destination = os.path.join(CONFIG_DIR, kwargs['name'] + '.yaml')
|
||||
wizard.wizard_write(path=destination, **kwargs)
|
||||
self.redirect('/?begin=True')
|
||||
|
@ -436,7 +436,7 @@ class LoginHandler(BaseHandler):
|
|||
self.redirect('/')
|
||||
return
|
||||
except Exception as err: # pylint: disable=broad-except
|
||||
_LOGGER.warn("Error during Hass.io auth request: %s", err)
|
||||
_LOGGER.warning("Error during Hass.io auth request: %s", err)
|
||||
self.set_status(500)
|
||||
self.render_hassio_login(error="Internal server error")
|
||||
return
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
|
||||
import hashlib
|
||||
import logging
|
||||
# pylint: disable=deprecated-module
|
||||
import optparse
|
||||
import os
|
||||
import random
|
||||
|
|
|
@ -6,6 +6,8 @@ import os
|
|||
import socket
|
||||
import subprocess
|
||||
|
||||
from esphomeyaml.py_compat import text_type, IS_PY2
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
@ -39,14 +41,16 @@ def indent(text, padding=u' '):
|
|||
|
||||
# From https://stackoverflow.com/a/14945195/8924614
|
||||
def cpp_string_escape(string, encoding='utf-8'):
|
||||
if isinstance(string, unicode):
|
||||
if isinstance(string, text_type):
|
||||
string = string.encode(encoding)
|
||||
result = ''
|
||||
for character in string:
|
||||
if not (32 <= ord(character) < 127) or character in ('\\', '"'):
|
||||
result += '\\%03o' % ord(character)
|
||||
if IS_PY2:
|
||||
character = ord(character)
|
||||
if not (32 <= character < 127) or character in ('\\', '"'):
|
||||
result += '\\%03o' % character
|
||||
else:
|
||||
result += character
|
||||
result += chr(character)
|
||||
return '"' + result + '"'
|
||||
|
||||
|
||||
|
|
|
@ -246,7 +246,7 @@ def validate_gpio_pin(value):
|
|||
_LOGGER.warning(u"ESP32: Pin %s (20, 24, 28-31) can usually not be used. "
|
||||
u"Be warned.", value)
|
||||
return value
|
||||
elif CORE.is_esp8266:
|
||||
if CORE.is_esp8266:
|
||||
if 6 <= value <= 11:
|
||||
_LOGGER.warning(u"ESP8266: Pin %s (6-11) might already be used by the "
|
||||
u"flash interface. Be warned.", value)
|
||||
|
@ -264,7 +264,7 @@ def input_pullup_pin(value):
|
|||
value = input_pin(value)
|
||||
if CORE.is_esp32:
|
||||
return output_pin(value)
|
||||
elif CORE.is_esp8266:
|
||||
if CORE.is_esp8266:
|
||||
if value == 0:
|
||||
raise vol.Invalid("GPIO Pin 0 does not support pullup pin mode. "
|
||||
"Please choose another pin.")
|
||||
|
@ -279,7 +279,7 @@ def output_pin(value):
|
|||
raise vol.Invalid(u"ESP32: GPIO{} (34-39) can only be used as an "
|
||||
u"input pin.".format(value))
|
||||
return value
|
||||
elif CORE.is_esp8266:
|
||||
if CORE.is_esp8266:
|
||||
return value
|
||||
raise NotImplementedError
|
||||
|
||||
|
@ -316,7 +316,7 @@ PIN_MODES_ESP32 = [
|
|||
def pin_mode(value):
|
||||
if CORE.is_esp32:
|
||||
return cv.one_of(*PIN_MODES_ESP32, upper=True)(value)
|
||||
elif CORE.is_esp8266:
|
||||
if CORE.is_esp8266:
|
||||
return cv.one_of(*PIN_MODES_ESP8266, upper=True)(value)
|
||||
raise NotImplementedError
|
||||
|
||||
|
|
25
esphomeyaml/py_compat.py
Normal file
25
esphomeyaml/py_compat.py
Normal file
|
@ -0,0 +1,25 @@
|
|||
import sys
|
||||
|
||||
PYTHON_MAJOR = sys.version_info[0]
|
||||
IS_PY2 = PYTHON_MAJOR == 2
|
||||
IS_PY3 = PYTHON_MAJOR == 3
|
||||
|
||||
|
||||
# pylint: disable=no-else-return
|
||||
def safe_input(line):
|
||||
if IS_PY2:
|
||||
return raw_input(line)
|
||||
else:
|
||||
return input(line)
|
||||
|
||||
|
||||
if IS_PY2:
|
||||
text_type = unicode
|
||||
string_types = (str, unicode)
|
||||
integer_types = (int, long)
|
||||
binary_type = str
|
||||
else:
|
||||
text_type = str
|
||||
string_types = (str,)
|
||||
integer_types = (int,)
|
||||
binary_type = bytes
|
|
@ -272,13 +272,13 @@ class CheckForUpdateThread(threading.Thread):
|
|||
remote_version = StrictVersion(storage.remote_version)
|
||||
self_version = StrictVersion(const.__version__)
|
||||
if remote_version > self_version:
|
||||
_LOGGER.warn("*" * 80)
|
||||
_LOGGER.warn("A new version of esphomeyaml is available: %s (this is %s)",
|
||||
self.format_version(remote_version), self.format_version(self_version))
|
||||
_LOGGER.warn("Changelog: %s/esphomeyaml/changelog/index.html", self.docs_base)
|
||||
_LOGGER.warn("Update Instructions: %s/esphomeyaml/guides/faq.html"
|
||||
"#how-do-i-update-to-the-latest-version", self.docs_base)
|
||||
_LOGGER.warn("*" * 80)
|
||||
_LOGGER.warning("*" * 80)
|
||||
_LOGGER.warning("A new version of esphomeyaml is available: %s (this is %s)",
|
||||
self.format_version(remote_version), self.format_version(self_version))
|
||||
_LOGGER.warning("Changelog: %s/esphomeyaml/changelog/index.html", self.docs_base)
|
||||
_LOGGER.warning("Update Instructions: %s/esphomeyaml/guides/faq.html"
|
||||
"#how-do-i-update-to-the-latest-version", self.docs_base)
|
||||
_LOGGER.warning("*" * 80)
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
|
|
|
@ -11,31 +11,32 @@ from esphomeyaml.const import ESP_PLATFORMS, ESP_PLATFORM_ESP32, ESP_PLATFORM_ES
|
|||
from esphomeyaml.helpers import color
|
||||
# pylint: disable=anomalous-backslash-in-string
|
||||
from esphomeyaml.pins import ESP32_BOARD_PINS, ESP8266_BOARD_PINS
|
||||
from esphomeyaml.py_compat import safe_input, text_type
|
||||
from esphomeyaml.storage_json import StorageJSON, ext_storage_path
|
||||
from esphomeyaml.util import safe_print
|
||||
|
||||
CORE_BIG = """ _____ ____ _____ ______
|
||||
CORE_BIG = r""" _____ ____ _____ ______
|
||||
/ ____/ __ \| __ \| ____|
|
||||
| | | | | | |__) | |__
|
||||
| | | | | | _ /| __|
|
||||
| |___| |__| | | \ \| |____
|
||||
\_____\____/|_| \_\______|
|
||||
"""
|
||||
ESP_BIG = """ ______ _____ _____
|
||||
ESP_BIG = r""" ______ _____ _____
|
||||
| ____|/ ____| __ \\
|
||||
| |__ | (___ | |__) |
|
||||
| __| \___ \| ___/
|
||||
| |____ ____) | |
|
||||
|______|_____/|_|
|
||||
"""
|
||||
WIFI_BIG = """ __ ___ ______ _
|
||||
WIFI_BIG = r""" __ ___ ______ _
|
||||
\ \ / (_) ____(_)
|
||||
\ \ /\ / / _| |__ _
|
||||
\ \/ \/ / | | __| | |
|
||||
\ /\ / | | | | |
|
||||
\/ \/ |_|_| |_|
|
||||
"""
|
||||
OTA_BIG = """ ____ _______
|
||||
OTA_BIG = r""" ____ _______
|
||||
/ __ \__ __|/\\
|
||||
| | | | | | / \\
|
||||
| | | | | | / /\ \\
|
||||
|
@ -85,7 +86,7 @@ def wizard_write(path, **kwargs):
|
|||
storage.save(storage_path)
|
||||
|
||||
|
||||
if os.getenv('ESPHOMEYAML_QUICKWIZARD', False):
|
||||
if os.getenv('ESPHOMEYAML_QUICKWIZARD', ''):
|
||||
def sleep(time):
|
||||
pass
|
||||
else:
|
||||
|
@ -104,12 +105,12 @@ def safe_print_step(step, big):
|
|||
def default_input(text, default):
|
||||
safe_print()
|
||||
safe_print(u"Press ENTER for default ({})".format(default))
|
||||
return raw_input(text.format(default)) or default
|
||||
return safe_input(text.format(default)) or default
|
||||
|
||||
|
||||
# From https://stackoverflow.com/a/518232/8924614
|
||||
def strip_accents(string):
|
||||
return u''.join(c for c in unicodedata.normalize('NFD', unicode(string))
|
||||
return u''.join(c for c in unicodedata.normalize('NFD', text_type(string))
|
||||
if unicodedata.category(c) != 'Mn')
|
||||
|
||||
|
||||
|
@ -140,7 +141,7 @@ def wizard(path):
|
|||
color('bold_white', "livingroom")))
|
||||
safe_print()
|
||||
sleep(1)
|
||||
name = raw_input(color("bold_white", "(name): "))
|
||||
name = safe_input(color("bold_white", "(name): "))
|
||||
while True:
|
||||
try:
|
||||
name = cv.valid_name(name)
|
||||
|
@ -165,7 +166,7 @@ def wizard(path):
|
|||
sleep(0.5)
|
||||
safe_print()
|
||||
safe_print("Please enter either ESP32 or ESP8266.")
|
||||
platform = raw_input(color("bold_white", "(ESP32/ESP8266): "))
|
||||
platform = safe_input(color("bold_white", "(ESP32/ESP8266): "))
|
||||
try:
|
||||
platform = vol.All(vol.Upper, vol.Any(*ESP_PLATFORMS))(platform)
|
||||
break
|
||||
|
@ -197,7 +198,7 @@ def wizard(path):
|
|||
safe_print("Options: {}".format(', '.join(boards)))
|
||||
|
||||
while True:
|
||||
board = raw_input(color("bold_white", "(board): "))
|
||||
board = safe_input(color("bold_white", "(board): "))
|
||||
try:
|
||||
board = vol.All(vol.Lower, vol.Any(*boards))(board)
|
||||
break
|
||||
|
@ -221,7 +222,7 @@ def wizard(path):
|
|||
sleep(1.5)
|
||||
safe_print("For example \"{}\".".format(color('bold_white', "Abraham Linksys")))
|
||||
while True:
|
||||
ssid = raw_input(color('bold_white', "(ssid): "))
|
||||
ssid = safe_input(color('bold_white', "(ssid): "))
|
||||
try:
|
||||
ssid = cv.ssid(ssid)
|
||||
break
|
||||
|
@ -241,7 +242,7 @@ def wizard(path):
|
|||
safe_print()
|
||||
safe_print("For example \"{}\"".format(color('bold_white', 'PASSWORD42')))
|
||||
sleep(0.5)
|
||||
psk = raw_input(color('bold_white', '(PSK): '))
|
||||
psk = safe_input(color('bold_white', '(PSK): '))
|
||||
safe_print("Perfect! WiFi is now set up (you can create static IPs and so on later).")
|
||||
sleep(1.5)
|
||||
|
||||
|
@ -253,7 +254,7 @@ def wizard(path):
|
|||
safe_print()
|
||||
sleep(0.25)
|
||||
safe_print("Press ENTER for no password")
|
||||
password = raw_input(color('bold_white', '(password): '))
|
||||
password = safe_input(color('bold_white', '(password): '))
|
||||
|
||||
wizard_write(path=path, name=name, platform=platform, board=board,
|
||||
ssid=ssid, psk=psk, password=password)
|
||||
|
|
|
@ -16,6 +16,7 @@ from esphomeyaml.core import CORE, EsphomeyamlError
|
|||
from esphomeyaml.core_config import VERSION_REGEX, LIBRARY_URI_REPO, GITHUB_ARCHIVE_ZIP
|
||||
from esphomeyaml.helpers import mkdir_p, run_system_command
|
||||
from esphomeyaml.pins import ESP8266_LD_SCRIPTS, ESP8266_FLASH_SIZES
|
||||
from esphomeyaml.py_compat import IS_PY3, string_types
|
||||
from esphomeyaml.storage_json import StorageJSON, storage_path
|
||||
from esphomeyaml.util import safe_print
|
||||
|
||||
|
@ -71,7 +72,7 @@ def get_build_flags(key):
|
|||
flags = flags(conf)
|
||||
if flags is None:
|
||||
continue
|
||||
if isinstance(flags, (str, unicode)):
|
||||
if isinstance(flags, string_types):
|
||||
flags = [flags]
|
||||
build_flags |= set(flags)
|
||||
return build_flags
|
||||
|
@ -114,14 +115,19 @@ def update_esphomelib_repo():
|
|||
'--')
|
||||
if rc != 0:
|
||||
# local changes, cannot update
|
||||
_LOGGER.warn("Local changes in esphomelib copy from git. Will not auto-update.")
|
||||
_LOGGER.warning("Local changes in esphomelib copy from git. Will not auto-update.")
|
||||
return
|
||||
_LOGGER.info("Updating esphomelib copy from git (%s)", esphomelib_path)
|
||||
rc, stdout, _ = run_system_command('git', '-c', 'color.ui=always', '-C', esphomelib_path,
|
||||
'pull', '--stat')
|
||||
if rc != 0:
|
||||
_LOGGER.warn("Couldn't auto-update local git copy of esphomelib.")
|
||||
_LOGGER.warning("Couldn't auto-update local git copy of esphomelib.")
|
||||
return
|
||||
if IS_PY3:
|
||||
try:
|
||||
stdout = stdout.encode('utf-8')
|
||||
except Exception: # pylint: disable=broad-except
|
||||
pass
|
||||
safe_print(stdout.strip())
|
||||
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ import yaml.constructor
|
|||
|
||||
from esphomeyaml import core
|
||||
from esphomeyaml.core import EsphomeyamlError, HexInt, IPAddress, Lambda, MACAddress, TimePeriod
|
||||
from esphomeyaml.py_compat import text_type, string_types
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
@ -24,14 +25,10 @@ SECRET_YAML = u'secrets.yaml'
|
|||
class NodeListClass(list):
|
||||
"""Wrapper class to be able to add attributes on a list."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class NodeStrClass(unicode):
|
||||
class NodeStrClass(text_type):
|
||||
"""Wrapper class to be able to add attributes on a string."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class SafeLineLoader(yaml.SafeLoader): # pylint: disable=too-many-ancestors
|
||||
"""Loader class that keeps track of line numbers."""
|
||||
|
@ -72,7 +69,7 @@ def custom_construct_pairs(loader, node):
|
|||
if not isinstance(obj, dict):
|
||||
raise EsphomeyamlError(
|
||||
"Expected mapping for anchored include tag, got {}".format(type(obj)))
|
||||
for key, value in obj.iteritems():
|
||||
for key, value in obj.items():
|
||||
pairs.append((key, value))
|
||||
else:
|
||||
key_node, value_node = kv
|
||||
|
@ -168,7 +165,7 @@ def _construct_seq(loader, node):
|
|||
|
||||
def _add_reference(obj, loader, node):
|
||||
"""Add file reference information to an object."""
|
||||
if isinstance(obj, (str, unicode)):
|
||||
if isinstance(obj, string_types):
|
||||
obj = NodeStrClass(obj)
|
||||
if isinstance(obj, list):
|
||||
obj = NodeListClass(obj)
|
||||
|
@ -184,7 +181,7 @@ def _env_var_yaml(_, node):
|
|||
# Check for a default value
|
||||
if len(args) > 1:
|
||||
return os.getenv(args[0], u' '.join(args[1:]))
|
||||
elif args[0] in os.environ:
|
||||
if args[0] in os.environ:
|
||||
return os.environ[args[0]]
|
||||
raise EsphomeyamlError(u"Environment variable {} not defined.".format(node.value))
|
||||
|
||||
|
@ -268,7 +265,7 @@ def _secret_yaml(loader, node):
|
|||
|
||||
|
||||
def _lambda(loader, node):
|
||||
return Lambda(unicode(node.value))
|
||||
return Lambda(text_type(node.value))
|
||||
|
||||
|
||||
yaml.SafeLoader.add_constructor(yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, _ordered_dict)
|
||||
|
@ -295,7 +292,7 @@ def represent_odict(dump, tag, mapping, flow_style=None):
|
|||
dump.represented_objects[dump.alias_key] = node
|
||||
best_style = True
|
||||
if hasattr(mapping, 'items'):
|
||||
mapping = mapping.items()
|
||||
mapping = list(mapping.items())
|
||||
for item_key, item_value in mapping:
|
||||
node_key = dump.represent_data(item_key)
|
||||
node_value = dump.represent_data(item_value)
|
||||
|
@ -372,7 +369,7 @@ yaml.SafeDumper.add_representer(
|
|||
dumper.represent_sequence('tag:yaml.org,2002:seq', value)
|
||||
)
|
||||
|
||||
yaml.SafeDumper.add_representer(unicode, unicode_representer)
|
||||
yaml.SafeDumper.add_representer(text_type, unicode_representer)
|
||||
yaml.SafeDumper.add_representer(HexInt, hex_int_representer)
|
||||
yaml.SafeDumper.add_representer(IPAddress, stringify_representer)
|
||||
yaml.SafeDumper.add_representer(MACAddress, stringify_representer)
|
||||
|
|
2
pylintrc
2
pylintrc
|
@ -19,6 +19,8 @@ disable=
|
|||
cyclic-import,
|
||||
redefined-builtin,
|
||||
undefined-loop-variable,
|
||||
useless-object-inheritance,
|
||||
stop-iteration-return,
|
||||
|
||||
|
||||
additional-builtins=
|
||||
|
|
2
setup.py
2
setup.py
|
@ -56,7 +56,7 @@ setup(
|
|||
zip_safe=False,
|
||||
platforms='any',
|
||||
test_suite='tests',
|
||||
python_requires='>=2.7,<3',
|
||||
python_requires='>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,<4.0',
|
||||
install_requires=REQUIRES,
|
||||
keywords=['home', 'automation'],
|
||||
entry_points={
|
||||
|
|
Loading…
Reference in a new issue