mirror of
https://github.com/esphome/esphome.git
synced 2025-01-13 10:07:09 +01:00
Drop Python 2 Support (#793)
* Remove Python 2 support * Remove u-strings * Remove docker symlinks * Remove from travis * Update requirements * Upgrade flake8/pylint * Fixes * Manual * Run pyupgrade * Lint * Remove base_int * Fix * Update platformio_api.py * Update component.cpp
This commit is contained in:
parent
b5714cd70f
commit
056c72d50d
@ -21,12 +21,6 @@ matrix:
|
||||
- esphome tests/test1.yaml compile
|
||||
- esphome tests/test2.yaml compile
|
||||
- esphome tests/test3.yaml compile
|
||||
- python: "2.7"
|
||||
env: TARGET=Test2.7
|
||||
script:
|
||||
- esphome tests/test1.yaml compile
|
||||
- esphome tests/test2.yaml compile
|
||||
- esphome tests/test3.yaml compile
|
||||
- env: TARGET=Cpp-Lint
|
||||
dist: trusty
|
||||
sudo: required
|
||||
|
@ -14,7 +14,5 @@ RUN \
|
||||
COPY requirements_test.txt /requirements_test.txt
|
||||
RUN pip3 install --no-cache-dir wheel && pip3 install --no-cache-dir -r /requirements_test.txt
|
||||
|
||||
RUN ln -s /usr/bin/pip3 /usr/bin/pip && ln -f -s /usr/bin/python3 /usr/bin/python
|
||||
|
||||
VOLUME ["/esphome"]
|
||||
WORKDIR /esphome
|
||||
|
@ -1,5 +1,3 @@
|
||||
from __future__ import print_function
|
||||
|
||||
import argparse
|
||||
import functools
|
||||
import logging
|
||||
@ -14,7 +12,6 @@ from esphome.const import CONF_BAUD_RATE, CONF_BROKER, CONF_LOGGER, CONF_OTA, \
|
||||
CONF_PASSWORD, CONF_PORT, CONF_ESPHOME, CONF_PLATFORMIO_OPTIONS
|
||||
from esphome.core import CORE, EsphomeError, coroutine, coroutine_with_priority
|
||||
from esphome.helpers import color, indent
|
||||
from esphome.py_compat import IS_PY2, safe_input, IS_PY3
|
||||
from esphome.util import run_external_command, run_external_process, safe_print, list_yaml_files
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
@ -42,12 +39,12 @@ def choose_prompt(options):
|
||||
if len(options) == 1:
|
||||
return options[0][1]
|
||||
|
||||
safe_print(u"Found multiple options, please choose one:")
|
||||
safe_print("Found multiple options, please choose one:")
|
||||
for i, (desc, _) in enumerate(options):
|
||||
safe_print(u" [{}] {}".format(i + 1, desc))
|
||||
safe_print(f" [{i+1}] {desc}")
|
||||
|
||||
while True:
|
||||
opt = safe_input('(number): ')
|
||||
opt = input('(number): ')
|
||||
if opt in options:
|
||||
opt = options.index(opt)
|
||||
break
|
||||
@ -57,20 +54,20 @@ def choose_prompt(options):
|
||||
raise ValueError
|
||||
break
|
||||
except ValueError:
|
||||
safe_print(color('red', u"Invalid option: '{}'".format(opt)))
|
||||
safe_print(color('red', f"Invalid option: '{opt}'"))
|
||||
return options[opt - 1][1]
|
||||
|
||||
|
||||
def choose_upload_log_host(default, check_default, show_ota, show_mqtt, show_api):
|
||||
options = []
|
||||
for res, desc in get_serial_ports():
|
||||
options.append((u"{} ({})".format(res, desc), res))
|
||||
options.append((f"{res} ({desc})", res))
|
||||
if (show_ota and 'ota' in CORE.config) or (show_api and 'api' in CORE.config):
|
||||
options.append((u"Over The Air ({})".format(CORE.address), CORE.address))
|
||||
options.append((f"Over The Air ({CORE.address})", CORE.address))
|
||||
if default == 'OTA':
|
||||
return CORE.address
|
||||
if show_mqtt and 'mqtt' in CORE.config:
|
||||
options.append((u"MQTT ({})".format(CORE.config['mqtt'][CONF_BROKER]), 'MQTT'))
|
||||
options.append(("MQTT ({})".format(CORE.config['mqtt'][CONF_BROKER]), 'MQTT'))
|
||||
if default == 'OTA':
|
||||
return 'MQTT'
|
||||
if default is not None:
|
||||
@ -108,11 +105,7 @@ def run_miniterm(config, port):
|
||||
except serial.SerialException:
|
||||
_LOGGER.error("Serial port closed!")
|
||||
return
|
||||
if IS_PY2:
|
||||
line = raw.replace('\r', '').replace('\n', '')
|
||||
else:
|
||||
line = raw.replace(b'\r', b'').replace(b'\n', b'').decode('utf8',
|
||||
'backslashreplace')
|
||||
line = raw.replace(b'\r', b'').replace(b'\n', b'').decode('utf8', 'backslashreplace')
|
||||
time = datetime.now().time().strftime('[%H:%M:%S]')
|
||||
message = time + line
|
||||
safe_print(message)
|
||||
@ -127,11 +120,9 @@ def wrap_to_code(name, comp):
|
||||
@functools.wraps(comp.to_code)
|
||||
@coroutine_with_priority(coro.priority)
|
||||
def wrapped(conf):
|
||||
cg.add(cg.LineComment(u"{}:".format(name)))
|
||||
cg.add(cg.LineComment(f"{name}:"))
|
||||
if comp.config_schema is not None:
|
||||
conf_str = yaml_util.dump(conf)
|
||||
if IS_PY2:
|
||||
conf_str = conf_str.decode('utf-8')
|
||||
conf_str = conf_str.replace('//', '')
|
||||
cg.add(cg.LineComment(indent(conf_str)))
|
||||
yield coro(conf)
|
||||
@ -243,7 +234,7 @@ def setup_log(debug=False, quiet=False):
|
||||
log_level = logging.INFO
|
||||
logging.basicConfig(level=log_level)
|
||||
fmt = "%(levelname)s %(message)s"
|
||||
colorfmt = "%(log_color)s{}%(reset)s".format(fmt)
|
||||
colorfmt = f"%(log_color)s{fmt}%(reset)s"
|
||||
datefmt = '%H:%M:%S'
|
||||
|
||||
logging.getLogger('urllib3').setLevel(logging.WARNING)
|
||||
@ -292,12 +283,12 @@ def command_compile(args, config):
|
||||
if exit_code != 0:
|
||||
return exit_code
|
||||
if args.only_generate:
|
||||
_LOGGER.info(u"Successfully generated source code.")
|
||||
_LOGGER.info("Successfully generated source code.")
|
||||
return 0
|
||||
exit_code = compile_program(args, config)
|
||||
if exit_code != 0:
|
||||
return exit_code
|
||||
_LOGGER.info(u"Successfully compiled program.")
|
||||
_LOGGER.info("Successfully compiled program.")
|
||||
return 0
|
||||
|
||||
|
||||
@ -307,7 +298,7 @@ def command_upload(args, config):
|
||||
exit_code = upload_program(config, args, port)
|
||||
if exit_code != 0:
|
||||
return exit_code
|
||||
_LOGGER.info(u"Successfully uploaded program.")
|
||||
_LOGGER.info("Successfully uploaded program.")
|
||||
return 0
|
||||
|
||||
|
||||
@ -324,13 +315,13 @@ def command_run(args, config):
|
||||
exit_code = compile_program(args, config)
|
||||
if exit_code != 0:
|
||||
return exit_code
|
||||
_LOGGER.info(u"Successfully compiled program.")
|
||||
_LOGGER.info("Successfully compiled program.")
|
||||
port = choose_upload_log_host(default=args.upload_port, check_default=None,
|
||||
show_ota=True, show_mqtt=False, show_api=True)
|
||||
exit_code = upload_program(config, args, port)
|
||||
if exit_code != 0:
|
||||
return exit_code
|
||||
_LOGGER.info(u"Successfully uploaded program.")
|
||||
_LOGGER.info("Successfully uploaded program.")
|
||||
if args.no_logs:
|
||||
return 0
|
||||
port = choose_upload_log_host(default=args.upload_port, check_default=port,
|
||||
@ -349,7 +340,7 @@ def command_mqtt_fingerprint(args, config):
|
||||
|
||||
|
||||
def command_version(args):
|
||||
safe_print(u"Version: {}".format(const.__version__))
|
||||
safe_print(f"Version: {const.__version__}")
|
||||
return 0
|
||||
|
||||
|
||||
@ -377,10 +368,10 @@ def command_update_all(args):
|
||||
twidth = 60
|
||||
|
||||
def print_bar(middle_text):
|
||||
middle_text = " {} ".format(middle_text)
|
||||
middle_text = f" {middle_text} "
|
||||
width = len(click.unstyle(middle_text))
|
||||
half_line = "=" * ((twidth - width) // 2)
|
||||
click.echo("%s%s%s" % (half_line, middle_text, half_line))
|
||||
click.echo(f"{half_line}{middle_text}{half_line}")
|
||||
|
||||
for f in files:
|
||||
print("Updating {}".format(color('cyan', f)))
|
||||
@ -431,7 +422,7 @@ POST_CONFIG_ACTIONS = {
|
||||
|
||||
|
||||
def parse_args(argv):
|
||||
parser = argparse.ArgumentParser(description='ESPHome v{}'.format(const.__version__))
|
||||
parser = argparse.ArgumentParser(description=f'ESPHome v{const.__version__}')
|
||||
parser.add_argument('-v', '--verbose', help="Enable verbose esphome logs.",
|
||||
action='store_true')
|
||||
parser.add_argument('-q', '--quiet', help="Disable all esphome logs.",
|
||||
@ -525,14 +516,10 @@ def run_esphome(argv):
|
||||
_LOGGER.error("Missing configuration parameter, see esphome --help.")
|
||||
return 1
|
||||
|
||||
if IS_PY2:
|
||||
_LOGGER.warning("You're using ESPHome with python 2. Support for python 2 is deprecated "
|
||||
"and will be removed in 1.15.0. Please reinstall ESPHome with python 3.6 "
|
||||
"or higher.")
|
||||
elif IS_PY3 and sys.version_info < (3, 6, 0):
|
||||
_LOGGER.warning("You're using ESPHome with python 3.5. Support for python 3.5 is "
|
||||
"deprecated and will be removed in 1.15.0. Please reinstall ESPHome with "
|
||||
"python 3.6 or higher.")
|
||||
if sys.version_info < (3, 6, 0):
|
||||
_LOGGER.error("You're running ESPHome with Python <3.6. ESPHome is no longer compatible "
|
||||
"with this Python version. Please reinstall ESPHome with Python 3.6+")
|
||||
return 1
|
||||
|
||||
if args.command in PRE_CONFIG_ACTIONS:
|
||||
try:
|
||||
@ -551,7 +538,7 @@ def run_esphome(argv):
|
||||
CORE.config = config
|
||||
|
||||
if args.command not in POST_CONFIG_ACTIONS:
|
||||
safe_print(u"Unknown command {}".format(args.command))
|
||||
safe_print(f"Unknown command {args.command}")
|
||||
|
||||
try:
|
||||
rc = POST_CONFIG_ACTIONS[args.command](args, config)
|
||||
|
@ -14,7 +14,6 @@ import esphome.api.api_pb2 as pb
|
||||
from esphome.const import CONF_PASSWORD, CONF_PORT
|
||||
from esphome.core import EsphomeError
|
||||
from esphome.helpers import resolve_ip_address, indent, color
|
||||
from esphome.py_compat import text_type, IS_PY2, byte_to_bytes, char_to_byte
|
||||
from esphome.util import safe_print
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
@ -67,16 +66,16 @@ MESSAGE_TYPE_TO_PROTO = {
|
||||
|
||||
def _varuint_to_bytes(value):
|
||||
if value <= 0x7F:
|
||||
return byte_to_bytes(value)
|
||||
return bytes([value])
|
||||
|
||||
ret = bytes()
|
||||
while value:
|
||||
temp = value & 0x7F
|
||||
value >>= 7
|
||||
if value:
|
||||
ret += byte_to_bytes(temp | 0x80)
|
||||
ret += bytes([temp | 0x80])
|
||||
else:
|
||||
ret += byte_to_bytes(temp)
|
||||
ret += bytes([temp])
|
||||
|
||||
return ret
|
||||
|
||||
@ -84,8 +83,7 @@ def _varuint_to_bytes(value):
|
||||
def _bytes_to_varuint(value):
|
||||
result = 0
|
||||
bitpos = 0
|
||||
for c in value:
|
||||
val = char_to_byte(c)
|
||||
for val in value:
|
||||
result |= (val & 0x7F) << bitpos
|
||||
bitpos += 7
|
||||
if (val & 0x80) == 0:
|
||||
@ -191,8 +189,8 @@ class APIClient(threading.Thread):
|
||||
self._socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
|
||||
try:
|
||||
self._socket.connect((ip, self._port))
|
||||
except socket.error as err:
|
||||
err = APIConnectionError("Error connecting to {}: {}".format(ip, err))
|
||||
except OSError as err:
|
||||
err = APIConnectionError(f"Error connecting to {ip}: {err}")
|
||||
self._fatal_error(err)
|
||||
raise err
|
||||
self._socket.settimeout(0.1)
|
||||
@ -200,7 +198,7 @@ class APIClient(threading.Thread):
|
||||
self._socket_open_event.set()
|
||||
|
||||
hello = pb.HelloRequest()
|
||||
hello.client_info = 'ESPHome v{}'.format(const.__version__)
|
||||
hello.client_info = f'ESPHome v{const.__version__}'
|
||||
try:
|
||||
resp = self._send_message_await_response(hello, pb.HelloResponse)
|
||||
except APIConnectionError as err:
|
||||
@ -251,8 +249,8 @@ class APIClient(threading.Thread):
|
||||
with self._socket_write_lock:
|
||||
try:
|
||||
self._socket.sendall(data)
|
||||
except socket.error as err:
|
||||
err = APIConnectionError("Error while writing data: {}".format(err))
|
||||
except OSError as err:
|
||||
err = APIConnectionError(f"Error while writing data: {err}")
|
||||
self._fatal_error(err)
|
||||
raise err
|
||||
|
||||
@ -265,11 +263,8 @@ class APIClient(threading.Thread):
|
||||
raise ValueError
|
||||
|
||||
encoded = msg.SerializeToString()
|
||||
_LOGGER.debug("Sending %s:\n%s", type(msg), indent(text_type(msg)))
|
||||
if IS_PY2:
|
||||
req = chr(0x00)
|
||||
else:
|
||||
req = bytes([0])
|
||||
_LOGGER.debug("Sending %s:\n%s", type(msg), indent(str(msg)))
|
||||
req = bytes([0])
|
||||
req += _varuint_to_bytes(len(encoded))
|
||||
req += _varuint_to_bytes(message_type)
|
||||
req += encoded
|
||||
@ -355,14 +350,14 @@ class APIClient(threading.Thread):
|
||||
raise APIConnectionError("Socket was closed")
|
||||
except socket.timeout:
|
||||
continue
|
||||
except socket.error as err:
|
||||
raise APIConnectionError("Error while receiving data: {}".format(err))
|
||||
except OSError as err:
|
||||
raise APIConnectionError(f"Error while receiving data: {err}")
|
||||
ret += val
|
||||
return ret
|
||||
|
||||
def _recv_varint(self):
|
||||
raw = bytes()
|
||||
while not raw or char_to_byte(raw[-1]) & 0x80:
|
||||
while not raw or raw[-1] & 0x80:
|
||||
raw += self._recv(1)
|
||||
return _bytes_to_varuint(raw)
|
||||
|
||||
@ -371,7 +366,7 @@ class APIClient(threading.Thread):
|
||||
return
|
||||
|
||||
# Preamble
|
||||
if char_to_byte(self._recv(1)[0]) != 0x00:
|
||||
if self._recv(1)[0] != 0x00:
|
||||
raise APIConnectionError("Invalid preamble")
|
||||
|
||||
length = self._recv_varint()
|
||||
@ -436,7 +431,7 @@ def run_logs(config, address):
|
||||
return
|
||||
|
||||
if err:
|
||||
_LOGGER.warning(u"Disconnected from API: %s", err)
|
||||
_LOGGER.warning("Disconnected from API: %s", err)
|
||||
|
||||
while retry_timer:
|
||||
retry_timer.pop(0).cancel()
|
||||
@ -454,18 +449,18 @@ def run_logs(config, address):
|
||||
|
||||
wait_time = int(min(1.5**min(tries, 100), 30))
|
||||
if not has_connects:
|
||||
_LOGGER.warning(u"Initial connection failed. The ESP might not be connected "
|
||||
u"to WiFi yet (%s). Re-Trying in %s seconds",
|
||||
_LOGGER.warning("Initial connection failed. The ESP might not be connected "
|
||||
"to WiFi yet (%s). Re-Trying in %s seconds",
|
||||
error, wait_time)
|
||||
else:
|
||||
_LOGGER.warning(u"Couldn't connect to API (%s). Trying to reconnect in %s seconds",
|
||||
_LOGGER.warning("Couldn't connect to API (%s). Trying to reconnect in %s seconds",
|
||||
error, wait_time)
|
||||
timer = threading.Timer(wait_time, functools.partial(try_connect, None, tries + 1))
|
||||
timer.start()
|
||||
retry_timer.append(timer)
|
||||
|
||||
def on_log(msg):
|
||||
time_ = datetime.now().time().strftime(u'[%H:%M:%S]')
|
||||
time_ = datetime.now().time().strftime('[%H:%M:%S]')
|
||||
text = msg.message
|
||||
if msg.send_failed:
|
||||
text = color('white', '(Message skipped because it was too big to fit in '
|
||||
|
@ -83,9 +83,9 @@ def validate_automation(extra_schema=None, extra_validators=None, single=False):
|
||||
try:
|
||||
return cv.Schema([schema])(value)
|
||||
except cv.Invalid as err2:
|
||||
if u'extra keys not allowed' in str(err2) and len(err2.path) == 2:
|
||||
if 'extra keys not allowed' in str(err2) and len(err2.path) == 2:
|
||||
raise err
|
||||
if u'Unable to find action' in str(err):
|
||||
if 'Unable to find action' in str(err):
|
||||
raise err2
|
||||
raise cv.MultipleInvalid([err, err2])
|
||||
elif isinstance(value, dict):
|
||||
|
@ -36,4 +36,4 @@ def to_code(config):
|
||||
continue
|
||||
conf = config[key]
|
||||
sens = yield sensor.new_sensor(conf)
|
||||
cg.add(getattr(var, 'set_{}_sensor'.format(key))(sens))
|
||||
cg.add(getattr(var, f'set_{key}_sensor')(sens))
|
||||
|
@ -2,7 +2,6 @@ import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import sensor, voltage_sampler
|
||||
from esphome.const import CONF_GAIN, CONF_MULTIPLEXER, ICON_FLASH, UNIT_VOLT, CONF_ID
|
||||
from esphome.py_compat import string_types
|
||||
from . import ads1115_ns, ADS1115Component
|
||||
|
||||
DEPENDENCIES = ['ads1115']
|
||||
@ -32,9 +31,9 @@ GAIN = {
|
||||
|
||||
def validate_gain(value):
|
||||
if isinstance(value, float):
|
||||
value = u'{:0.03f}'.format(value)
|
||||
elif not isinstance(value, string_types):
|
||||
raise cv.Invalid('invalid gain "{}"'.format(value))
|
||||
value = f'{value:0.03f}'
|
||||
elif not isinstance(value, str):
|
||||
raise cv.Invalid(f'invalid gain "{value}"')
|
||||
|
||||
return cv.enum(GAIN)(value)
|
||||
|
||||
|
@ -102,7 +102,7 @@ def homeassistant_service_to_code(config, action_id, template_arg, args):
|
||||
|
||||
def validate_homeassistant_event(value):
|
||||
value = cv.string(value)
|
||||
if not value.startswith(u'esphome.'):
|
||||
if not value.startswith('esphome.'):
|
||||
raise cv.Invalid("ESPHome can only generate Home Assistant events that begin with "
|
||||
"esphome. For example 'esphome.xyz'")
|
||||
return value
|
||||
|
@ -9,7 +9,6 @@ from esphome.const import CONF_DEVICE_CLASS, CONF_FILTERS, \
|
||||
CONF_ON_DOUBLE_CLICK, CONF_ON_MULTI_CLICK, CONF_ON_PRESS, CONF_ON_RELEASE, CONF_ON_STATE, \
|
||||
CONF_STATE, CONF_TIMING, CONF_TRIGGER_ID, CONF_FOR, CONF_NAME, CONF_MQTT_ID
|
||||
from esphome.core import CORE, coroutine, coroutine_with_priority
|
||||
from esphome.py_compat import string_types
|
||||
from esphome.util import Registry
|
||||
|
||||
DEVICE_CLASSES = [
|
||||
@ -94,7 +93,7 @@ MULTI_CLICK_TIMING_SCHEMA = cv.Schema({
|
||||
|
||||
|
||||
def parse_multi_click_timing_str(value):
|
||||
if not isinstance(value, string_types):
|
||||
if not isinstance(value, str):
|
||||
return value
|
||||
|
||||
parts = value.lower().split(' ')
|
||||
@ -104,10 +103,10 @@ def parse_multi_click_timing_str(value):
|
||||
try:
|
||||
state = cv.boolean(parts[0])
|
||||
except cv.Invalid:
|
||||
raise cv.Invalid(u"First word must either be ON or OFF, not {}".format(parts[0]))
|
||||
raise cv.Invalid("First word must either be ON or OFF, not {}".format(parts[0]))
|
||||
|
||||
if parts[1] != 'for':
|
||||
raise cv.Invalid(u"Second word must be 'for', got {}".format(parts[1]))
|
||||
raise cv.Invalid("Second word must be 'for', got {}".format(parts[1]))
|
||||
|
||||
if parts[2] == 'at':
|
||||
if parts[3] == 'least':
|
||||
@ -115,12 +114,12 @@ def parse_multi_click_timing_str(value):
|
||||
elif parts[3] == 'most':
|
||||
key = CONF_MAX_LENGTH
|
||||
else:
|
||||
raise cv.Invalid(u"Third word after at must either be 'least' or 'most', got {}"
|
||||
u"".format(parts[3]))
|
||||
raise cv.Invalid("Third word after at must either be 'least' or 'most', got {}"
|
||||
"".format(parts[3]))
|
||||
try:
|
||||
length = cv.positive_time_period_milliseconds(parts[4])
|
||||
except cv.Invalid as err:
|
||||
raise cv.Invalid(u"Multi Click Grammar Parsing length failed: {}".format(err))
|
||||
raise cv.Invalid(f"Multi Click Grammar Parsing length failed: {err}")
|
||||
return {
|
||||
CONF_STATE: state,
|
||||
key: str(length)
|
||||
@ -132,12 +131,12 @@ def parse_multi_click_timing_str(value):
|
||||
try:
|
||||
min_length = cv.positive_time_period_milliseconds(parts[2])
|
||||
except cv.Invalid as err:
|
||||
raise cv.Invalid(u"Multi Click Grammar Parsing minimum length failed: {}".format(err))
|
||||
raise cv.Invalid(f"Multi Click Grammar Parsing minimum length failed: {err}")
|
||||
|
||||
try:
|
||||
max_length = cv.positive_time_period_milliseconds(parts[4])
|
||||
except cv.Invalid as err:
|
||||
raise cv.Invalid(u"Multi Click Grammar Parsing minimum length failed: {}".format(err))
|
||||
raise cv.Invalid(f"Multi Click Grammar Parsing minimum length failed: {err}")
|
||||
|
||||
return {
|
||||
CONF_STATE: state,
|
||||
|
@ -8,8 +8,8 @@ from esphome.const import CONF_ID, CONF_MODE, CONF_NUMBER, CONF_PINS, CONF_RUN_C
|
||||
def validate_pin_number(value):
|
||||
valid_pins = [0, 2, 4, 12, 13, 14, 15, 25, 26, 27, 32, 33, 34, 35, 36, 37, 38, 39]
|
||||
if value[CONF_NUMBER] not in valid_pins:
|
||||
raise cv.Invalid(u"Only pins {} support wakeup"
|
||||
u"".format(', '.join(str(x) for x in valid_pins)))
|
||||
raise cv.Invalid("Only pins {} support wakeup"
|
||||
"".format(', '.join(str(x) for x in valid_pins)))
|
||||
return value
|
||||
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
# coding=utf-8
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome import core, automation
|
||||
@ -27,7 +26,7 @@ DISPLAY_ROTATIONS = {
|
||||
|
||||
def validate_rotation(value):
|
||||
value = cv.string(value)
|
||||
if value.endswith(u"°"):
|
||||
if value.endswith("°"):
|
||||
value = value[:-1]
|
||||
return cv.enum(DISPLAY_ROTATIONS, int=True)(value)
|
||||
|
||||
|
@ -46,33 +46,33 @@ def bt_uuid(value):
|
||||
pattern = re.compile("^[A-F|0-9]{4,}$")
|
||||
if not pattern.match(value):
|
||||
raise cv.Invalid(
|
||||
u"Invalid hexadecimal value for 16 bit UUID format: '{}'".format(in_value))
|
||||
f"Invalid hexadecimal value for 16 bit UUID format: '{in_value}'")
|
||||
return value
|
||||
if len(value) == len(bt_uuid32_format):
|
||||
pattern = re.compile("^[A-F|0-9]{8,}$")
|
||||
if not pattern.match(value):
|
||||
raise cv.Invalid(
|
||||
u"Invalid hexadecimal value for 32 bit UUID format: '{}'".format(in_value))
|
||||
f"Invalid hexadecimal value for 32 bit UUID format: '{in_value}'")
|
||||
return value
|
||||
if len(value) == len(bt_uuid128_format):
|
||||
pattern = re.compile(
|
||||
"^[A-F|0-9]{8,}-[A-F|0-9]{4,}-[A-F|0-9]{4,}-[A-F|0-9]{4,}-[A-F|0-9]{12,}$")
|
||||
if not pattern.match(value):
|
||||
raise cv.Invalid(
|
||||
u"Invalid hexadecimal value for 128 UUID format: '{}'".format(in_value))
|
||||
f"Invalid hexadecimal value for 128 UUID format: '{in_value}'")
|
||||
return value
|
||||
raise cv.Invalid(
|
||||
u"Service UUID must be in 16 bit '{}', 32 bit '{}', or 128 bit '{}' format".format(
|
||||
"Service UUID must be in 16 bit '{}', 32 bit '{}', or 128 bit '{}' format".format(
|
||||
bt_uuid16_format, bt_uuid32_format, bt_uuid128_format))
|
||||
|
||||
|
||||
def as_hex(value):
|
||||
return cg.RawExpression('0x{}ULL'.format(value))
|
||||
return cg.RawExpression(f'0x{value}ULL')
|
||||
|
||||
|
||||
def as_hex_array(value):
|
||||
value = value.replace("-", "")
|
||||
cpp_array = ['0x{}'.format(part) for part in [value[i:i+2] for i in range(0, len(value), 2)]]
|
||||
cpp_array = [f'0x{part}' for part in [value[i:i+2] for i in range(0, len(value), 2)]]
|
||||
return cg.RawExpression(
|
||||
'(uint8_t*)(const uint8_t[16]){{{}}}'.format(','.join(reversed(cpp_array))))
|
||||
|
||||
|
@ -27,7 +27,7 @@ TOUCH_PADS = {
|
||||
def validate_touch_pad(value):
|
||||
value = validate_gpio_pin(value)
|
||||
if value not in TOUCH_PADS:
|
||||
raise cv.Invalid("Pin {} does not support touch pads.".format(value))
|
||||
raise cv.Invalid(f"Pin {value} does not support touch pads.")
|
||||
return value
|
||||
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
# coding=utf-8
|
||||
import functools
|
||||
|
||||
from esphome import core
|
||||
from esphome.components import display
|
||||
import esphome.config_validation as cv
|
||||
import esphome.codegen as cg
|
||||
from esphome.const import CONF_FILE, CONF_GLYPHS, CONF_ID, CONF_SIZE
|
||||
from esphome.core import CORE, HexInt
|
||||
from esphome.py_compat import sort_by_cmp
|
||||
|
||||
DEPENDENCIES = ['display']
|
||||
MULTI_CONF = True
|
||||
@ -33,9 +33,9 @@ def validate_glyphs(value):
|
||||
return -1
|
||||
if len(x_) > len(y_):
|
||||
return 1
|
||||
raise cv.Invalid(u"Found duplicate glyph {}".format(x))
|
||||
raise cv.Invalid(f"Found duplicate glyph {x}")
|
||||
|
||||
sort_by_cmp(value, comparator)
|
||||
value.sort(key=functools.cmp_to_key(comparator))
|
||||
return value
|
||||
|
||||
|
||||
@ -55,15 +55,15 @@ def validate_pillow_installed(value):
|
||||
|
||||
def validate_truetype_file(value):
|
||||
if value.endswith('.zip'): # for Google Fonts downloads
|
||||
raise cv.Invalid(u"Please unzip the font archive '{}' first and then use the .ttf files "
|
||||
u"inside.".format(value))
|
||||
raise cv.Invalid("Please unzip the font archive '{}' first and then use the .ttf files "
|
||||
"inside.".format(value))
|
||||
if not value.endswith('.ttf'):
|
||||
raise cv.Invalid(u"Only truetype (.ttf) files are supported. Please make sure you're "
|
||||
u"using the correct format or rename the extension to .ttf")
|
||||
raise cv.Invalid("Only truetype (.ttf) files are supported. Please make sure you're "
|
||||
"using the correct format or rename the extension to .ttf")
|
||||
return cv.file_(value)
|
||||
|
||||
|
||||
DEFAULT_GLYPHS = u' !"%()+,-.:0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz°'
|
||||
DEFAULT_GLYPHS = ' !"%()+,-.:0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz°'
|
||||
CONF_RAW_DATA_ID = 'raw_data_id'
|
||||
|
||||
FONT_SCHEMA = cv.Schema({
|
||||
@ -84,7 +84,7 @@ def to_code(config):
|
||||
try:
|
||||
font = ImageFont.truetype(path, config[CONF_SIZE])
|
||||
except Exception as e:
|
||||
raise core.EsphomeError(u"Could not load truetype file {}: {}".format(path, e))
|
||||
raise core.EsphomeError(f"Could not load truetype file {path}: {e}")
|
||||
|
||||
ascent, descent = font.getmetrics()
|
||||
|
||||
|
@ -4,7 +4,6 @@ from esphome import config_validation as cv, automation
|
||||
from esphome import codegen as cg
|
||||
from esphome.const import CONF_ID, CONF_INITIAL_VALUE, CONF_RESTORE_VALUE, CONF_TYPE, CONF_VALUE
|
||||
from esphome.core import coroutine_with_priority
|
||||
from esphome.py_compat import IS_PY3
|
||||
|
||||
globals_ns = cg.esphome_ns.namespace('globals')
|
||||
GlobalsComponent = globals_ns.class_('GlobalsComponent', cg.Component)
|
||||
@ -36,7 +35,7 @@ def to_code(config):
|
||||
|
||||
if config[CONF_RESTORE_VALUE]:
|
||||
value = config[CONF_ID].id
|
||||
if IS_PY3 and isinstance(value, str):
|
||||
if isinstance(value, str):
|
||||
value = value.encode()
|
||||
hash_ = int(hashlib.md5(value).hexdigest()[:8], 16)
|
||||
cg.add(glob.set_restore_value(hash_))
|
||||
|
@ -1,11 +1,9 @@
|
||||
# coding=utf-8
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import i2c, sensor
|
||||
from esphome.const import (CONF_ADDRESS, CONF_ID, CONF_OVERSAMPLING, CONF_RANGE, ICON_MAGNET,
|
||||
UNIT_MICROTESLA, UNIT_DEGREES, ICON_SCREEN_ROTATION,
|
||||
CONF_UPDATE_INTERVAL)
|
||||
from esphome.py_compat import text_type
|
||||
|
||||
DEPENDENCIES = ['i2c']
|
||||
|
||||
@ -54,7 +52,7 @@ def validate_enum(enum_values, units=None, int=True):
|
||||
_units = []
|
||||
if units is not None:
|
||||
_units = units if isinstance(units, list) else [units]
|
||||
_units = [text_type(x) for x in _units]
|
||||
_units = [str(x) for x in _units]
|
||||
enum_bound = cv.enum(enum_values, int=int)
|
||||
|
||||
def validate_enum_bound(value):
|
||||
@ -74,7 +72,7 @@ CONFIG_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(): cv.declare_id(HMC5883LComponent),
|
||||
cv.Optional(CONF_ADDRESS): cv.i2c_address,
|
||||
cv.Optional(CONF_OVERSAMPLING, default='1x'): validate_enum(HMC5883LOversamplings, units="x"),
|
||||
cv.Optional(CONF_RANGE, default=u'130µT'): validate_enum(HMC5883L_RANGES, units=["uT", u"µT"]),
|
||||
cv.Optional(CONF_RANGE, default='130µT'): validate_enum(HMC5883L_RANGES, units=["uT", "µT"]),
|
||||
cv.Optional(CONF_FIELD_STRENGTH_X): field_strength_schema,
|
||||
cv.Optional(CONF_FIELD_STRENGTH_Y): field_strength_schema,
|
||||
cv.Optional(CONF_FIELD_STRENGTH_Z): field_strength_schema,
|
||||
|
@ -1,3 +1,5 @@
|
||||
import urllib.parse as urlparse
|
||||
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome import automation
|
||||
@ -5,12 +7,6 @@ from esphome.const import CONF_ID, CONF_TIMEOUT, CONF_ESPHOME, CONF_METHOD, \
|
||||
CONF_ARDUINO_VERSION, ARDUINO_VERSION_ESP8266_2_5_0
|
||||
from esphome.core import CORE, Lambda
|
||||
from esphome.core_config import PLATFORMIO_ESP8266_LUT
|
||||
from esphome.py_compat import IS_PY3
|
||||
|
||||
if IS_PY3:
|
||||
import urllib.parse as urlparse # pylint: disable=no-name-in-module,import-error
|
||||
else:
|
||||
import urlparse # pylint: disable=import-error
|
||||
|
||||
DEPENDENCIES = ['network']
|
||||
AUTO_LOAD = ['json']
|
||||
|
@ -1,4 +1,3 @@
|
||||
# coding=utf-8
|
||||
import logging
|
||||
|
||||
from esphome import core
|
||||
@ -33,7 +32,7 @@ def to_code(config):
|
||||
try:
|
||||
image = Image.open(path)
|
||||
except Exception as e:
|
||||
raise core.EsphomeError(u"Could not load image file {}: {}".format(path, e))
|
||||
raise core.EsphomeError(f"Could not load image file {path}: {e}")
|
||||
|
||||
if CONF_RESIZE in config:
|
||||
image.thumbnail(config[CONF_RESIZE])
|
||||
|
@ -1,4 +1,3 @@
|
||||
# coding=utf-8
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import i2c, sensor
|
||||
|
@ -1,4 +1,3 @@
|
||||
# coding=utf-8
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import i2c, sensor
|
||||
|
@ -1,4 +1,3 @@
|
||||
# coding=utf-8
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import i2c, sensor
|
||||
|
@ -253,8 +253,8 @@ def validate_effects(allowed_effects):
|
||||
name = x[key][CONF_NAME]
|
||||
if name in names:
|
||||
errors.append(
|
||||
cv.Invalid(u"Found the effect name '{}' twice. All effects must have "
|
||||
u"unique names".format(name), [i])
|
||||
cv.Invalid("Found the effect name '{}' twice. All effects must have "
|
||||
"unique names".format(name), [i])
|
||||
)
|
||||
continue
|
||||
names.add(name)
|
||||
|
@ -7,7 +7,6 @@ from esphome.automation import LambdaAction
|
||||
from esphome.const import CONF_ARGS, CONF_BAUD_RATE, CONF_FORMAT, CONF_HARDWARE_UART, CONF_ID, \
|
||||
CONF_LEVEL, CONF_LOGS, CONF_ON_MESSAGE, CONF_TAG, CONF_TRIGGER_ID, CONF_TX_BUFFER_SIZE
|
||||
from esphome.core import CORE, EsphomeError, Lambda, coroutine_with_priority
|
||||
from esphome.py_compat import text_type
|
||||
|
||||
logger_ns = cg.esphome_ns.namespace('logger')
|
||||
LOG_LEVELS = {
|
||||
@ -64,8 +63,8 @@ def validate_local_no_higher_than_global(value):
|
||||
global_level = value.get(CONF_LEVEL, 'DEBUG')
|
||||
for tag, level in value.get(CONF_LOGS, {}).items():
|
||||
if LOG_LEVEL_SEVERITY.index(level) > LOG_LEVEL_SEVERITY.index(global_level):
|
||||
raise EsphomeError(u"The local log level {} for {} must be less severe than the "
|
||||
u"global log level {}.".format(level, tag, global_level))
|
||||
raise EsphomeError("The local log level {} for {} must be less severe than the "
|
||||
"global log level {}.".format(level, tag, global_level))
|
||||
return value
|
||||
|
||||
|
||||
@ -119,7 +118,7 @@ def to_code(config):
|
||||
|
||||
if CORE.is_esp8266 and has_serial_logging and is_at_least_verbose:
|
||||
debug_serial_port = HARDWARE_UART_TO_SERIAL[config.get(CONF_HARDWARE_UART)]
|
||||
cg.add_build_flag("-DDEBUG_ESP_PORT={}".format(debug_serial_port))
|
||||
cg.add_build_flag(f"-DDEBUG_ESP_PORT={debug_serial_port}")
|
||||
cg.add_build_flag("-DLWIP_DEBUG")
|
||||
DEBUG_COMPONENTS = {
|
||||
'HTTP_CLIENT',
|
||||
@ -134,7 +133,7 @@ def to_code(config):
|
||||
# 'MDNS_RESPONDER',
|
||||
}
|
||||
for comp in DEBUG_COMPONENTS:
|
||||
cg.add_build_flag("-DDEBUG_ESP_{}".format(comp))
|
||||
cg.add_build_flag(f"-DDEBUG_ESP_{comp}")
|
||||
if CORE.is_esp32 and is_at_least_verbose:
|
||||
cg.add_build_flag('-DCORE_DEBUG_LEVEL=5')
|
||||
if CORE.is_esp32 and is_at_least_very_verbose:
|
||||
@ -165,7 +164,7 @@ def maybe_simple_message(schema):
|
||||
def validate_printf(value):
|
||||
# https://stackoverflow.com/questions/30011379/how-can-i-parse-a-c-format-string-in-python
|
||||
# pylint: disable=anomalous-backslash-in-string
|
||||
cfmt = u"""\
|
||||
cfmt = """\
|
||||
( # start of capture group 1
|
||||
% # literal "%"
|
||||
(?: # first option
|
||||
@ -179,8 +178,8 @@ def validate_printf(value):
|
||||
""" # noqa
|
||||
matches = re.findall(cfmt, value[CONF_FORMAT], flags=re.X)
|
||||
if len(matches) != len(value[CONF_ARGS]):
|
||||
raise cv.Invalid(u"Found {} printf-patterns ({}), but {} args were given!"
|
||||
u"".format(len(matches), u', '.join(matches), len(value[CONF_ARGS])))
|
||||
raise cv.Invalid("Found {} printf-patterns ({}), but {} args were given!"
|
||||
"".format(len(matches), ', '.join(matches), len(value[CONF_ARGS])))
|
||||
return value
|
||||
|
||||
|
||||
@ -196,9 +195,9 @@ LOGGER_LOG_ACTION_SCHEMA = cv.All(maybe_simple_message({
|
||||
@automation.register_action(CONF_LOGGER_LOG, LambdaAction, LOGGER_LOG_ACTION_SCHEMA)
|
||||
def logger_log_action_to_code(config, action_id, template_arg, args):
|
||||
esp_log = LOG_LEVEL_TO_ESP_LOG[config[CONF_LEVEL]]
|
||||
args_ = [cg.RawExpression(text_type(x)) for x in config[CONF_ARGS]]
|
||||
args_ = [cg.RawExpression(str(x)) for x in config[CONF_ARGS]]
|
||||
|
||||
text = text_type(cg.statement(esp_log(config[CONF_TAG], config[CONF_FORMAT], *args_)))
|
||||
text = str(cg.statement(esp_log(config[CONF_TAG], config[CONF_FORMAT], *args_)))
|
||||
|
||||
lambda_ = yield cg.process_lambda(Lambda(text), args, return_type=cg.void)
|
||||
yield cg.new_Pvariable(action_id, template_arg, lambda_)
|
||||
|
@ -39,14 +39,14 @@ def to_code(config):
|
||||
yield i2c.register_i2c_device(var, config)
|
||||
|
||||
for d in ['x', 'y', 'z']:
|
||||
accel_key = 'accel_{}'.format(d)
|
||||
accel_key = f'accel_{d}'
|
||||
if accel_key in config:
|
||||
sens = yield sensor.new_sensor(config[accel_key])
|
||||
cg.add(getattr(var, 'set_accel_{}_sensor'.format(d))(sens))
|
||||
accel_key = 'gyro_{}'.format(d)
|
||||
cg.add(getattr(var, f'set_accel_{d}_sensor')(sens))
|
||||
accel_key = f'gyro_{d}'
|
||||
if accel_key in config:
|
||||
sens = yield sensor.new_sensor(config[accel_key])
|
||||
cg.add(getattr(var, 'set_gyro_{}_sensor'.format(d))(sens))
|
||||
cg.add(getattr(var, f'set_gyro_{d}_sensor')(sens))
|
||||
|
||||
if CONF_TEMPERATURE in config:
|
||||
sens = yield sensor.new_sensor(config[CONF_TEMPERATURE])
|
||||
|
@ -64,28 +64,28 @@ def validate_config(value):
|
||||
topic_prefix = value[CONF_TOPIC_PREFIX]
|
||||
if CONF_BIRTH_MESSAGE not in value:
|
||||
out[CONF_BIRTH_MESSAGE] = {
|
||||
CONF_TOPIC: '{}/status'.format(topic_prefix),
|
||||
CONF_TOPIC: f'{topic_prefix}/status',
|
||||
CONF_PAYLOAD: 'online',
|
||||
CONF_QOS: 0,
|
||||
CONF_RETAIN: True,
|
||||
}
|
||||
if CONF_WILL_MESSAGE not in value:
|
||||
out[CONF_WILL_MESSAGE] = {
|
||||
CONF_TOPIC: '{}/status'.format(topic_prefix),
|
||||
CONF_TOPIC: f'{topic_prefix}/status',
|
||||
CONF_PAYLOAD: 'offline',
|
||||
CONF_QOS: 0,
|
||||
CONF_RETAIN: True,
|
||||
}
|
||||
if CONF_SHUTDOWN_MESSAGE not in value:
|
||||
out[CONF_SHUTDOWN_MESSAGE] = {
|
||||
CONF_TOPIC: '{}/status'.format(topic_prefix),
|
||||
CONF_TOPIC: f'{topic_prefix}/status',
|
||||
CONF_PAYLOAD: 'offline',
|
||||
CONF_QOS: 0,
|
||||
CONF_RETAIN: True,
|
||||
}
|
||||
if CONF_LOG_TOPIC not in value:
|
||||
out[CONF_LOG_TOPIC] = {
|
||||
CONF_TOPIC: '{}/debug'.format(topic_prefix),
|
||||
CONF_TOPIC: f'{topic_prefix}/debug',
|
||||
CONF_QOS: 0,
|
||||
CONF_RETAIN: True,
|
||||
}
|
||||
@ -95,7 +95,7 @@ def validate_config(value):
|
||||
def validate_fingerprint(value):
|
||||
value = cv.string(value)
|
||||
if re.match(r'^[0-9a-f]{40}$', value) is None:
|
||||
raise cv.Invalid(u"fingerprint must be valid SHA1 hash")
|
||||
raise cv.Invalid("fingerprint must be valid SHA1 hash")
|
||||
return value
|
||||
|
||||
|
||||
|
@ -82,7 +82,7 @@ def validate_method_pin(value):
|
||||
for opt in (CONF_PIN, CONF_CLOCK_PIN, CONF_DATA_PIN):
|
||||
if opt in value and value[opt] not in pins_:
|
||||
raise cv.Invalid("Method {} only supports pin(s) {}".format(
|
||||
method, ', '.join('GPIO{}'.format(x) for x in pins_)
|
||||
method, ', '.join(f'GPIO{x}' for x in pins_)
|
||||
), path=[CONF_METHOD])
|
||||
return value
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
# coding=utf-8
|
||||
from math import log
|
||||
|
||||
import esphome.config_validation as cv
|
||||
@ -28,7 +27,7 @@ def validate_calibration_parameter(value):
|
||||
value = cv.string(value)
|
||||
parts = value.split('->')
|
||||
if len(parts) != 2:
|
||||
raise cv.Invalid(u"Calibration parameter must be of form 3000 -> 23°C")
|
||||
raise cv.Invalid("Calibration parameter must be of form 3000 -> 23°C")
|
||||
voltage = cv.resistance(parts[0].strip())
|
||||
temperature = cv.temperature(parts[1].strip())
|
||||
return validate_calibration_parameter({
|
||||
|
@ -10,8 +10,8 @@ PartitionLightOutput = partitions_ns.class_('PartitionLightOutput', light.Addres
|
||||
|
||||
def validate_from_to(value):
|
||||
if value[CONF_FROM] > value[CONF_TO]:
|
||||
raise cv.Invalid(u"From ({}) must not be larger than to ({})"
|
||||
u"".format(value[CONF_FROM], value[CONF_TO]))
|
||||
raise cv.Invalid("From ({}) must not be larger than to ({})"
|
||||
"".format(value[CONF_FROM], value[CONF_TO]))
|
||||
return value
|
||||
|
||||
|
||||
|
@ -36,7 +36,7 @@ SENSORS_TO_TYPE = {
|
||||
def validate_pmsx003_sensors(value):
|
||||
for key, types in SENSORS_TO_TYPE.items():
|
||||
if key in value and value[CONF_TYPE] not in types:
|
||||
raise cv.Invalid(u"{} does not have {} sensor!".format(value[CONF_TYPE], key))
|
||||
raise cv.Invalid("{} does not have {} sensor!".format(value[CONF_TYPE], key))
|
||||
return value
|
||||
|
||||
|
||||
|
@ -1,11 +1,9 @@
|
||||
# coding=utf-8
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import i2c, sensor
|
||||
from esphome.const import (CONF_ADDRESS, CONF_ID, CONF_OVERSAMPLING, CONF_RANGE, ICON_MAGNET,
|
||||
UNIT_MICROTESLA, UNIT_DEGREES, ICON_SCREEN_ROTATION,
|
||||
CONF_UPDATE_INTERVAL)
|
||||
from esphome.py_compat import text_type
|
||||
|
||||
DEPENDENCIES = ['i2c']
|
||||
|
||||
@ -46,7 +44,7 @@ def validate_enum(enum_values, units=None, int=True):
|
||||
_units = []
|
||||
if units is not None:
|
||||
_units = units if isinstance(units, list) else [units]
|
||||
_units = [text_type(x) for x in _units]
|
||||
_units = [str(x) for x in _units]
|
||||
enum_bound = cv.enum(enum_values, int=int)
|
||||
|
||||
def validate_enum_bound(value):
|
||||
@ -65,7 +63,7 @@ heading_schema = sensor.sensor_schema(UNIT_DEGREES, ICON_SCREEN_ROTATION, 1)
|
||||
CONFIG_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(): cv.declare_id(QMC5883LComponent),
|
||||
cv.Optional(CONF_ADDRESS): cv.i2c_address,
|
||||
cv.Optional(CONF_RANGE, default=u'200µT'): validate_enum(QMC5883L_RANGES, units=["uT", u"µT"]),
|
||||
cv.Optional(CONF_RANGE, default='200µT'): validate_enum(QMC5883L_RANGES, units=["uT", "µT"]),
|
||||
cv.Optional(CONF_OVERSAMPLING, default="512x"): validate_enum(QMC5883LOversamplings, units="x"),
|
||||
cv.Optional(CONF_FIELD_STRENGTH_X): field_strength_schema,
|
||||
cv.Optional(CONF_FIELD_STRENGTH_Y): field_strength_schema,
|
||||
|
@ -7,7 +7,6 @@ from esphome.const import CONF_DATA, CONF_TRIGGER_ID, CONF_NBITS, CONF_ADDRESS,
|
||||
CONF_PROTOCOL, CONF_GROUP, CONF_DEVICE, CONF_STATE, CONF_CHANNEL, CONF_FAMILY, CONF_REPEAT, \
|
||||
CONF_WAIT_TIME, CONF_TIMES, CONF_TYPE_ID, CONF_CARRIER_FREQUENCY
|
||||
from esphome.core import coroutine
|
||||
from esphome.py_compat import string_types, text_type
|
||||
from esphome.util import Registry, SimpleRegistry
|
||||
|
||||
AUTO_LOAD = ['binary_sensor']
|
||||
@ -52,7 +51,7 @@ def register_trigger(name, type, data_type):
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(type),
|
||||
cv.GenerateID(CONF_RECEIVER_ID): cv.use_id(RemoteReceiverBase),
|
||||
})
|
||||
registerer = TRIGGER_REGISTRY.register('on_{}'.format(name), validator)
|
||||
registerer = TRIGGER_REGISTRY.register(f'on_{name}', validator)
|
||||
|
||||
def decorator(func):
|
||||
@coroutine
|
||||
@ -98,7 +97,7 @@ def register_action(name, type_, schema):
|
||||
cv.GenerateID(CONF_TRANSMITTER_ID): cv.use_id(RemoteTransmitterBase),
|
||||
cv.Optional(CONF_REPEAT): validate_repeat,
|
||||
})
|
||||
registerer = automation.register_action('remote_transmitter.transmit_{}'.format(name),
|
||||
registerer = automation.register_action(f'remote_transmitter.transmit_{name}',
|
||||
type_, validator)
|
||||
|
||||
def decorator(func):
|
||||
@ -122,11 +121,11 @@ def register_action(name, type_, schema):
|
||||
|
||||
|
||||
def declare_protocol(name):
|
||||
data = ns.struct('{}Data'.format(name))
|
||||
binary_sensor_ = ns.class_('{}BinarySensor'.format(name), RemoteReceiverBinarySensorBase)
|
||||
trigger = ns.class_('{}Trigger'.format(name), RemoteReceiverTrigger)
|
||||
action = ns.class_('{}Action'.format(name), RemoteTransmitterActionBase)
|
||||
dumper = ns.class_('{}Dumper'.format(name), RemoteTransmitterDumper)
|
||||
data = ns.struct(f'{name}Data')
|
||||
binary_sensor_ = ns.class_(f'{name}BinarySensor', RemoteReceiverBinarySensorBase)
|
||||
trigger = ns.class_(f'{name}Trigger', RemoteReceiverTrigger)
|
||||
action = ns.class_(f'{name}Action', RemoteTransmitterActionBase)
|
||||
dumper = ns.class_(f'{name}Dumper', RemoteTransmitterDumper)
|
||||
return data, binary_sensor_, trigger, action, dumper
|
||||
|
||||
|
||||
@ -141,7 +140,7 @@ DUMPER_REGISTRY = Registry({
|
||||
|
||||
|
||||
def validate_dumpers(value):
|
||||
if isinstance(value, string_types) and value.lower() == 'all':
|
||||
if isinstance(value, str) and value.lower() == 'all':
|
||||
return validate_dumpers(list(DUMPER_REGISTRY.keys()))
|
||||
return cv.validate_registry('dumper', DUMPER_REGISTRY)(value)
|
||||
|
||||
@ -432,12 +431,12 @@ RC_SWITCH_PROTOCOL_SCHEMA = cv.Any(
|
||||
|
||||
|
||||
def validate_rc_switch_code(value):
|
||||
if not isinstance(value, (str, text_type)):
|
||||
if not isinstance(value, (str, str)):
|
||||
raise cv.Invalid("All RCSwitch codes must be in quotes ('')")
|
||||
for c in value:
|
||||
if c not in ('0', '1'):
|
||||
raise cv.Invalid(u"Invalid RCSwitch code character '{}'. Only '0' and '1' are allowed"
|
||||
u"".format(c))
|
||||
raise cv.Invalid("Invalid RCSwitch code character '{}'. Only '0' and '1' are allowed"
|
||||
"".format(c))
|
||||
if len(value) > 64:
|
||||
raise cv.Invalid("Maximum length for RCSwitch codes is 64, code '{}' has length {}"
|
||||
"".format(value, len(value)))
|
||||
@ -447,7 +446,7 @@ def validate_rc_switch_code(value):
|
||||
|
||||
|
||||
def validate_rc_switch_raw_code(value):
|
||||
if not isinstance(value, (str, text_type)):
|
||||
if not isinstance(value, (str, str)):
|
||||
raise cv.Invalid("All RCSwitch raw codes must be in quotes ('')")
|
||||
for c in value:
|
||||
if c not in ('0', '1', 'x'):
|
||||
|
@ -19,12 +19,12 @@ def show_new(value):
|
||||
if 'name' in value:
|
||||
args.append(('name', value['name']))
|
||||
args.append(('turn_on_action', {
|
||||
'remote_transmitter.transmit_{}'.format(key): val
|
||||
f'remote_transmitter.transmit_{key}': val
|
||||
}))
|
||||
|
||||
text = yaml_util.dump([OrderedDict(args)])
|
||||
raise cv.Invalid(u"This platform has been removed in 1.13, please change to:\n\n{}\n\n."
|
||||
u"".format(text))
|
||||
raise cv.Invalid("This platform has been removed in 1.13, please change to:\n\n{}\n\n."
|
||||
"".format(text))
|
||||
|
||||
|
||||
CONFIG_SCHEMA = show_new
|
||||
|
@ -28,7 +28,7 @@ def validate_acceleration(value):
|
||||