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