1
0
mirror of https://github.com/esphome/esphome.git synced 2025-11-13 21:35:48 +00:00

Compare commits

..

5 Commits

Author SHA1 Message Date
Otto Winter
c31c5c4041 Bump version to 1.2.2 2018-04-10 20:43:19 +02:00
Otto Winter
34605f19ee Secret and Include directives in confg (#4) 2018-04-10 20:18:02 +02:00
Otto Winter
58e1b8454d Handle multiple serial ports better 2018-04-10 20:17:20 +02:00
Otto Winter
0ab63dc4d4 Enable Travis Linting (#3)
* Flake8 Travis Job

* Fix flake8 warnings

* Fix pylint errors

* Fix travis file
2018-04-10 17:17:46 +02:00
Jimmy Hedman
51c856e65e It now complies with flake8 --ignore=E501,W291 (#1)
- Not changning long lines or lines ending with space.
2018-04-10 16:21:32 +02:00
20 changed files with 395 additions and 215 deletions

10
.travis.yml Normal file
View File

@@ -0,0 +1,10 @@
sudo: false
language: python
python:
- "2.7"
install:
- pip install -r requirements.txt
- pip install flake8==3.5.0 pylint==1.8.4
script:
- flake8 esphomeyaml
- pylint esphomeyaml

View File

@@ -11,7 +11,7 @@ RUN pip install --no-cache-dir -r requirements.txt
COPY docker/platformio.ini /usr/src/app/ COPY docker/platformio.ini /usr/src/app/
RUN platformio settings set enable_telemetry No && \ RUN platformio settings set enable_telemetry No && \
platformio lib --global install esphomelib=https://github.com/OttoWinter/esphomelib.git#v1.2.1 && \ platformio lib --global install esphomelib@1.2.1 && \
platformio run -e espressif32 -e espressif8266; exit 0 platformio run -e espressif32 -e espressif8266; exit 0
# Fix issue with static IP on ESP32: https://github.com/espressif/arduino-esp32/issues/1081 # Fix issue with static IP on ESP32: https://github.com/espressif/arduino-esp32/issues/1081

View File

@@ -12,7 +12,7 @@ from esphomeyaml.const import CONF_ESPHOMEYAML, CONF_HOSTNAME, CONF_MANUAL_IP, C
CONF_STATIC_IP, \ CONF_STATIC_IP, \
CONF_WIFI, CONF_LOGGER, CONF_BAUD_RATE CONF_WIFI, CONF_LOGGER, CONF_BAUD_RATE
from esphomeyaml.helpers import AssignmentExpression, RawStatement, _EXPRESSIONS, add, \ from esphomeyaml.helpers import AssignmentExpression, RawStatement, _EXPRESSIONS, add, \
get_variable, indent, quote, statement get_variable, indent, quote, statement, color
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@@ -36,21 +36,44 @@ def discover_serial_ports():
except ImportError: except ImportError:
return None return None
result = None result = []
for p, d, h in comports(): descs = []
if not p: for port, desc, info in comports():
if not port:
continue continue
if "VID:PID" in h: if "VID:PID" in info:
if result is not None: result.append(port)
return None descs.append(desc)
result = p
return result if not result:
return None
if len(result) == 1:
return result[0]
print(u"Found multiple serial port options, please choose one:")
for i, (res, desc) in enumerate(zip(result, descs)):
print(u" [{}] {} ({})".format(i, res, desc))
print(u" [{}] Over The Air".format(len(result)))
print()
while True:
opt = raw_input('(number): ')
if opt in result:
opt = result.index(opt)
break
try:
opt = int(opt)
if opt < 0 or opt > len(result):
raise ValueError
break
except ValueError:
print(color('red', u"Invalid option: '{}'".format(opt)))
if opt == len(result):
return None
return result[opt]
def run_platformio(*cmd): def run_platformio(*cmd):
def mock_exit(rc): def mock_exit(return_code):
raise SystemExit(rc) raise SystemExit(return_code)
orig_argv = sys.argv orig_argv = sys.argv
orig_exit = sys.exit # mock sys.exit orig_exit = sys.exit # mock sys.exit
@@ -63,10 +86,10 @@ def run_platformio(*cmd):
return platformio.__main__.main() return platformio.__main__.main()
except KeyboardInterrupt: except KeyboardInterrupt:
return 1 return 1
except SystemExit as e: except SystemExit as err:
return e.args[0] return err.args[0]
except Exception as e: except Exception as err: # pylint: disable=broad-except
_LOGGER.error(u"Running platformio failed: %s", e) _LOGGER.error(u"Running platformio failed: %s", err)
_LOGGER.error(u"Please try running %s locally.", full_cmd) _LOGGER.error(u"Please try running %s locally.", full_cmd)
finally: finally:
sys.argv = orig_argv sys.argv = orig_argv
@@ -125,16 +148,7 @@ def compile_program(config):
def upload_program(config, args, port): def upload_program(config, args, port):
_LOGGER.info("Uploading binary...") _LOGGER.info("Uploading binary...")
if args.upload_port is not None:
if args.upload_port == 'HELLO':
return run_platformio('platformio', 'run', '-d', get_base_path(config),
'-t', 'upload')
else:
return run_platformio('platformio', 'run', '-d', get_base_path(config),
'-t', 'upload', '--upload-port', args.upload_port)
if port is not None: if port is not None:
_LOGGER.info("Serial device discovered, using it for upload")
return run_platformio('platformio', 'run', '-d', get_base_path(config), return run_platformio('platformio', 'run', '-d', get_base_path(config),
'-t', 'upload', '--upload-port', port) '-t', 'upload', '--upload-port', port)
@@ -160,7 +174,7 @@ def upload_program(config, args, port):
def show_logs(config, args, port): def show_logs(config, args, port):
if port is not None: if port is not None and port != 'OTA':
run_miniterm(config, port) run_miniterm(config, port)
return 0 return 0
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)
@@ -205,17 +219,14 @@ def main():
parser.add_argument('configuration', help='Your YAML configuration file.') parser.add_argument('configuration', help='Your YAML configuration file.')
subparsers = parser.add_subparsers(help='Commands', dest='command') subparsers = parser.add_subparsers(help='Commands', dest='command')
subparsers.required = True subparsers.required = True
parser_config = subparsers.add_parser('config', subparsers.add_parser('config', help='Validate the configuration and spit it out.')
help='Validate the configuration and spit it out.')
parser_compile = subparsers.add_parser('compile', subparsers.add_parser('compile', help='Read the configuration and compile a program.')
help='Read the configuration and compile a program.')
parser_upload = subparsers.add_parser('upload', help='Validate the configuration ' parser_upload = subparsers.add_parser('upload', help='Validate the configuration '
'and upload the latest binary.') 'and upload the latest binary.')
parser_upload.add_argument('--upload-port', help="Manually specify the upload port to use. " parser_upload.add_argument('--upload-port', help="Manually specify the upload port to use. "
"For example /dev/cu.SLAB_USBtoUAR.", "For example /dev/cu.SLAB_USBtoUART.")
nargs='?', const='HELLO')
parser_upload.add_argument('--host-port', help="Specify the host port.", type=int) parser_upload.add_argument('--host-port', help="Specify the host port.", type=int)
parser_logs = subparsers.add_parser('logs', help='Validate the configuration ' parser_logs = subparsers.add_parser('logs', help='Validate the configuration '
@@ -224,12 +235,13 @@ def main():
parser_logs.add_argument('--username', help='Manually set the username.') parser_logs.add_argument('--username', help='Manually set the username.')
parser_logs.add_argument('--password', help='Manually set the password.') parser_logs.add_argument('--password', help='Manually set the password.')
parser_logs.add_argument('--client-id', help='Manually set the client id.') parser_logs.add_argument('--client-id', help='Manually set the client id.')
parser_logs.add_argument('--serial-port', help="Manually specify a serial port to use"
"For example /dev/cu.SLAB_USBtoUART.")
parser_run = subparsers.add_parser('run', help='Validate the configuration, create a binary, ' parser_run = subparsers.add_parser('run', help='Validate the configuration, create a binary, '
'upload it, and start MQTT logs.') 'upload it, and start MQTT logs.')
parser_run.add_argument('--upload-port', help="Manually specify the upload port to use. " parser_run.add_argument('--upload-port', help="Manually specify the upload port to use. "
"For example /dev/cu.SLAB_USBtoUAR.", "For example /dev/cu.SLAB_USBtoUART.")
nargs='?', const='HELLO')
parser_run.add_argument('--host-port', help="Specify the host port to use for OTA", type=int) parser_run.add_argument('--host-port', help="Specify the host port to use for OTA", type=int)
parser_run.add_argument('--no-logs', help='Disable starting MQTT logs.', parser_run.add_argument('--no-logs', help='Disable starting MQTT logs.',
action='store_true') action='store_true')
@@ -245,7 +257,7 @@ def main():
parser_clean.add_argument('--password', help='Manually set the password.') parser_clean.add_argument('--password', help='Manually set the password.')
parser_clean.add_argument('--client-id', help='Manually set the client id.') parser_clean.add_argument('--client-id', help='Manually set the client id.')
parser_wizard = subparsers.add_parser('wizard', help="A helpful setup wizard that will guide " subparsers.add_parser('wizard', help="A helpful setup wizard that will guide "
"you through setting up esphomeyaml.") "you through setting up esphomeyaml.")
args = parser.parse_args() args = parser.parse_args()
@@ -260,6 +272,7 @@ def main():
if args.command == 'config': if args.command == 'config':
print(yaml_util.dump(config)) print(yaml_util.dump(config))
return 0
elif args.command == 'compile': elif args.command == 'compile':
exit_code = write_cpp(config) exit_code = write_cpp(config)
if exit_code != 0: if exit_code != 0:
@@ -270,14 +283,14 @@ def main():
_LOGGER.info(u"Successfully compiled program.") _LOGGER.info(u"Successfully compiled program.")
return 0 return 0
elif args.command == 'upload': elif args.command == 'upload':
port = discover_serial_ports() port = args.upload_port or discover_serial_ports()
exit_code = upload_program(config, args, port) exit_code = upload_program(config, args, port)
if exit_code != 0: if exit_code != 0:
return exit_code return exit_code
_LOGGER.info(u"Successfully uploaded program.") _LOGGER.info(u"Successfully uploaded program.")
return 0 return 0
elif args.command == 'logs': elif args.command == 'logs':
port = discover_serial_ports() port = args.serial_port or discover_serial_ports()
return show_logs(config, args, port) return show_logs(config, args, port)
elif args.command == 'clean-mqtt': elif args.command == 'clean-mqtt':
return clean_mqtt(config, args) return clean_mqtt(config, args)
@@ -290,14 +303,13 @@ def main():
return exit_code return exit_code
_LOGGER.info(u"Successfully compiled program.") _LOGGER.info(u"Successfully compiled program.")
if args.no_logs: if args.no_logs:
return return 0
port = discover_serial_ports() port = args.upload_port or discover_serial_ports()
exit_code = upload_program(config, args, port) exit_code = upload_program(config, args, port)
if exit_code != 0: if exit_code != 0:
return exit_code return exit_code
_LOGGER.info(u"Successfully uploaded program.") _LOGGER.info(u"Successfully uploaded program.")
return show_logs(config, args, port) return show_logs(config, args, port)
else:
print(u"Unknown command {}".format(args.command)) print(u"Unknown command {}".format(args.command))
return 1 return 1

View File

@@ -8,6 +8,8 @@ from esphomeyaml.helpers import App, Pvariable, RawExpression, add, exp_empty_op
LOG_LEVELS = ['NONE', 'ERROR', 'WARN', 'INFO', 'DEBUG', 'VERBOSE'] LOG_LEVELS = ['NONE', 'ERROR', 'WARN', 'INFO', 'DEBUG', 'VERBOSE']
# pylint: disable=invalid-name
is_log_level = vol.All(vol.Upper, vol.Any(*LOG_LEVELS)) is_log_level = vol.All(vol.Upper, vol.Any(*LOG_LEVELS))
CONFIG_SCHEMA = cv.ID_SCHEMA.extend({ CONFIG_SCHEMA = cv.ID_SCHEMA.extend({

View File

@@ -24,8 +24,8 @@ def to_code(config):
rhs = App.init_ota() rhs = App.init_ota()
ota = Pvariable('OTAComponent', config[CONF_ID], rhs) ota = Pvariable('OTAComponent', config[CONF_ID], rhs)
if CONF_PASSWORD in config: if CONF_PASSWORD in config:
h = hashlib.md5(config[CONF_PASSWORD].encode()).hexdigest() hash_ = hashlib.md5(config[CONF_PASSWORD].encode()).hexdigest()
add(ota.set_auth_password_hash(h)) add(ota.set_auth_password_hash(hash_))
if config[CONF_SAFE_MODE]: if config[CONF_SAFE_MODE]:
add(ota.start_safe_mode()) add(ota.start_safe_mode())

View File

@@ -46,6 +46,7 @@ MQTT_SENSOR_ID_SCHEMA = MQTT_SENSOR_SCHEMA.extend({
cv.GenerateID('mqtt_sensor'): cv.register_variable_id, cv.GenerateID('mqtt_sensor'): cv.register_variable_id,
}) })
# pylint: disable=invalid-name
OffsetFilter = MockObj('new sensor::OffsetFilter') OffsetFilter = MockObj('new sensor::OffsetFilter')
MultiplyFilter = MockObj('new sensor::MultiplyFilter') MultiplyFilter = MockObj('new sensor::MultiplyFilter')
FilterOutValueFilter = MockObj('new sensor::FilterOutValueFilter') FilterOutValueFilter = MockObj('new sensor::FilterOutValueFilter')

View File

@@ -38,6 +38,8 @@ PLATFORM_SCHEMA = switch.PLATFORM_SCHEMA.extend({
vol.Optional(CONF_IR_TRANSMITTER_ID): cv.variable_id, vol.Optional(CONF_IR_TRANSMITTER_ID): cv.variable_id,
}).extend(switch.MQTT_SWITCH_SCHEMA.schema) }).extend(switch.MQTT_SWITCH_SCHEMA.schema)
# pylint: disable=invalid-name
SendData = MockObj('switch_::ir::SendData', '::') SendData = MockObj('switch_::ir::SendData', '::')

View File

@@ -19,6 +19,8 @@ CONFIG_SCHEMA = cv.ID_SCHEMA.extend({
vol.Optional(CONF_HOSTNAME): cv.hostname, vol.Optional(CONF_HOSTNAME): cv.hostname,
}) })
# pylint: disable=invalid-name
IPAddress = MockObj('IPAddress') IPAddress = MockObj('IPAddress')

View File

@@ -18,7 +18,7 @@ from esphomeyaml.helpers import App, add, add_task, color
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
DEFAULT_LIBRARY_URI = u'https://github.com/OttoWinter/esphomelib.git#v1.2.1' DEFAULT_LIBRARY_URI = u'esphomelib@1.2.1'
CORE_SCHEMA = vol.Schema({ CORE_SCHEMA = vol.Schema({
vol.Required(CONF_NAME): cv.valid_name, vol.Required(CONF_NAME): cv.valid_name,
@@ -50,7 +50,6 @@ def get_component(domain):
module = importlib.import_module(path) module = importlib.import_module(path)
except ImportError as err: except ImportError as err:
_LOGGER.debug(err) _LOGGER.debug(err)
pass
else: else:
_COMPONENT_CACHE[domain] = module _COMPONENT_CACHE[domain] = module
return module return module
@@ -87,7 +86,7 @@ def validate_config(config):
for req in REQUIRED_COMPONENTS: for req in REQUIRED_COMPONENTS:
if req not in config: if req not in config:
raise ESPHomeYAMLError("Component %s is required for esphomeyaml.", req) raise ESPHomeYAMLError("Component {} is required for esphomeyaml.".format(req))
_ALL_COMPONENTS = list(config.keys()) _ALL_COMPONENTS = list(config.keys())
@@ -137,7 +136,7 @@ def validate_config(config):
continue continue
platforms = [] platforms = []
for i, p_config in enumerate(conf): for p_config in conf:
if not isinstance(p_config, dict): if not isinstance(p_config, dict):
result.add_error(u"Platform schemas mus have 'platform:' key") result.add_error(u"Platform schemas mus have 'platform:' key")
continue continue
@@ -197,7 +196,7 @@ def load_config(path):
try: try:
result = validate_config(config) result = validate_config(config)
except Exception as e: except Exception:
print(u"Unexpected exception while reading configuration:") print(u"Unexpected exception while reading configuration:")
raise raise
@@ -262,7 +261,11 @@ def dump_dict(layer, indent_count=3, listi=False, **kwargs):
def read_config(path): def read_config(path):
_LOGGER.debug("Reading configuration...") _LOGGER.debug("Reading configuration...")
try:
res = load_config(path) res = load_config(path)
except ESPHomeYAMLError as e:
_LOGGER.error(u"Error while reading config: %s", e)
return None
excepts = {} excepts = {}
for err in res.errors: for err in res.errors:
domain = err[1] or u"General Error" domain = err[1] or u"General Error"

View File

@@ -16,9 +16,11 @@ from esphomeyaml.helpers import ensure_unique_string
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
# pylint: disable=invalid-name
port = vol.All(vol.Coerce(int), vol.Range(min=1, max=65535)) port = vol.All(vol.Coerce(int), vol.Range(min=1, max=65535))
positive_float = vol.All(vol.Coerce(float), vol.Range(min=0)) positive_float = vol.All(vol.Coerce(float), vol.Range(min=0))
zero_to_one_float = vol.All(vol.Coerce(float), vol.Range(min=0, max=1)), zero_to_one_float = vol.All(vol.Coerce(float), vol.Range(min=0, max=1))
positive_int = vol.All(vol.Coerce(int), vol.Range(min=0)) positive_int = vol.All(vol.Coerce(int), vol.Range(min=0))
positive_not_null_int = vol.All(vol.Coerce(int), vol.Range(min=0, min_included=False)) positive_not_null_int = vol.All(vol.Coerce(int), vol.Range(min=0, min_included=False))
@@ -57,7 +59,7 @@ def alphanumeric(value):
def valid_name(value): def valid_name(value):
value = string_strict(value) value = string_strict(value)
if not all(c in ALLOWED_NAME_CHARS for c in value): if not all(c in ALLOWED_NAME_CHARS for c in value):
raise vol.Invalid(u"Valid characters for name are %s", ALLOWED_NAME_CHARS) raise vol.Invalid(u"Valid characters for name are {}".format(ALLOWED_NAME_CHARS))
return value return value
@@ -71,7 +73,7 @@ def string(value):
def string_strict(value): def string_strict(value):
"""Strictly only allow strings.""" """Strictly only allow strings."""
if isinstance(value, str) or isinstance(value, unicode): if isinstance(value, (str, unicode)):
return value return value
raise vol.Invalid("Must be string, did you forget putting quotes " raise vol.Invalid("Must be string, did you forget putting quotes "
"around the value?") "around the value?")
@@ -148,7 +150,6 @@ def only_on(platforms):
platforms = [platforms] platforms = [platforms]
def validator_(obj): def validator_(obj):
print(obj)
if ESP_PLATFORM not in platforms: if ESP_PLATFORM not in platforms:
raise vol.Invalid(u"This feature is only available on {}".format(platforms)) raise vol.Invalid(u"This feature is only available on {}".format(platforms))
return obj return obj

View File

@@ -2,7 +2,7 @@
MAJOR_VERSION = 1 MAJOR_VERSION = 1
MINOR_VERSION = 2 MINOR_VERSION = 2
PATCH_VERSION = '1' PATCH_VERSION = '2'
__short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION) __short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION)
__version__ = '{}.{}'.format(__short_version__, PATCH_VERSION) __version__ = '{}.{}'.format(__short_version__, PATCH_VERSION)

View File

@@ -43,6 +43,8 @@ import random
import socket import socket
import sys import sys
# pylint: disable=no-member
# Commands # Commands
FLASH = 0 FLASH = 0
SPIFFS = 100 SPIFFS = 100
@@ -62,7 +64,7 @@ def update_progress(progress):
:return: :return:
""" """
if PROGRESS: if PROGRESS:
barLength = 60 # Modify this to change the length of the progress bar bar_length = 60 # Modify this to change the length of the progress bar
status = "" status = ""
if isinstance(progress, int): if isinstance(progress, int):
progress = float(progress) progress = float(progress)
@@ -75,8 +77,8 @@ def update_progress(progress):
if progress >= 1: if progress >= 1:
progress = 1 progress = 1
status = "Done...\r\n" status = "Done...\r\n"
block = int(round(barLength * progress)) block = int(round(bar_length * progress))
text = "\rUploading: [{0}] {1}% {2}".format("=" * block + " " * (barLength - block), text = "\rUploading: [{0}] {1}% {2}".format("=" * block + " " * (bar_length - block),
int(progress * 100), status) int(progress * 100), status)
sys.stderr.write(text) sys.stderr.write(text)
sys.stderr.flush() sys.stderr.flush()
@@ -93,14 +95,14 @@ def serve(remote_host, local_addr, remote_port, local_port, password, filename,
try: try:
sock.bind(server_address) sock.bind(server_address)
sock.listen(1) sock.listen(1)
except Exception: except Exception: # pylint: disable=broad-except
_LOGGER.error("Listen Failed") _LOGGER.error("Listen Failed")
return 1 return 1
content_size = os.path.getsize(filename) content_size = os.path.getsize(filename)
f = open(filename, 'rb') f_handle = open(filename, 'rb')
file_md5 = hashlib.md5(f.read()).hexdigest() file_md5 = hashlib.md5(f_handle.read()).hexdigest()
f.close() f_handle.close()
_LOGGER.info('Upload size: %d', content_size) _LOGGER.info('Upload size: %d', content_size)
message = '%d %d %d %s\n' % (command, local_port, content_size, file_md5) message = '%d %d %d %s\n' % (command, local_port, content_size, file_md5)
@@ -116,7 +118,7 @@ def serve(remote_host, local_addr, remote_port, local_port, password, filename,
sock2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try: try:
sock2.sendto(message.encode(), remote_address) sock2.sendto(message.encode(), remote_address)
except Exception: except Exception: # pylint: disable=broad-except
_LOGGER.error('Failed') _LOGGER.error('Failed')
sock2.close() sock2.close()
_LOGGER.error('Host %s Not Found', remote_host) _LOGGER.error('Host %s Not Found', remote_host)
@@ -125,7 +127,7 @@ def serve(remote_host, local_addr, remote_port, local_port, password, filename,
try: try:
data = sock2.recv(37).decode() data = sock2.recv(37).decode()
break break
except Exception: except Exception: # pylint: disable=broad-except
sys.stderr.write('.') sys.stderr.write('.')
sys.stderr.flush() sys.stderr.flush()
sock2.close() sock2.close()
@@ -148,7 +150,7 @@ def serve(remote_host, local_addr, remote_port, local_port, password, filename,
sock2.settimeout(10) sock2.settimeout(10)
try: try:
data = sock2.recv(32).decode() data = sock2.recv(32).decode()
except Exception: except Exception: # pylint: disable=broad-except
_LOGGER.error('FAIL: No Answer to our Authentication') _LOGGER.error('FAIL: No Answer to our Authentication')
sock2.close() sock2.close()
return 1 return 1
@@ -166,35 +168,36 @@ def serve(remote_host, local_addr, remote_port, local_port, password, filename,
_LOGGER.info('Waiting for device...') _LOGGER.info('Waiting for device...')
try: try:
sock.settimeout(10) sock.settimeout(10)
connection, client_address = sock.accept() connection, _ = sock.accept()
sock.settimeout(None) sock.settimeout(None)
connection.settimeout(None) connection.settimeout(None)
except Exception: except Exception: # pylint: disable=broad-except
_LOGGER.error('No response from device') _LOGGER.error('No response from device')
sock.close() sock.close()
return 1 return 1
try: try:
f = open(filename, "rb") f_handle = open(filename, "rb")
if PROGRESS: if PROGRESS:
update_progress(0) update_progress(0)
else: else:
_LOGGER.info('Uploading...') _LOGGER.info('Uploading...')
offset = 0 offset = 0
while True: while True:
chunk = f.read(1024) chunk = f_handle.read(1024)
if not chunk: break if not chunk:
break
offset += len(chunk) offset += len(chunk)
update_progress(offset / float(content_size)) update_progress(offset / float(content_size))
connection.settimeout(10) connection.settimeout(10)
try: try:
connection.sendall(chunk) connection.sendall(chunk)
connection.recv(10) connection.recv(10)
except Exception: except Exception: # pylint: disable=broad-except
sys.stderr.write('\n') sys.stderr.write('\n')
_LOGGER.error('Error Uploading') _LOGGER.error('Error Uploading')
connection.close() connection.close()
f.close() f_handle.close()
sock.close() sock.close()
return 1 return 1
@@ -207,26 +210,26 @@ def serve(remote_host, local_addr, remote_port, local_port, password, filename,
break break
_LOGGER.info('Result: OK') _LOGGER.info('Result: OK')
connection.close() connection.close()
f.close() f_handle.close()
sock.close() sock.close()
if data != "OK": if data != "OK":
_LOGGER.error('%s', data) _LOGGER.error('%s', data)
return 1 return 1
except Exception: except Exception: # pylint: disable=broad-except
_LOGGER.error('No Result!') _LOGGER.error('No Result!')
connection.close() connection.close()
f.close() f_handle.close()
sock.close() sock.close()
return 1 return 1
finally: finally:
connection.close() connection.close()
f.close() f_handle.close()
return 0 return 0
def parser(unparsed_args): def parse_args(unparsed_args):
parser = optparse.OptionParser( parser = optparse.OptionParser(
usage="%prog [options]", usage="%prog [options]",
description="Transmit image over the air to the esp8266 module with OTA support." description="Transmit image over the air to the esp8266 module with OTA support."
@@ -234,25 +237,29 @@ def parser(unparsed_args):
# destination ip and port # destination ip and port
group = optparse.OptionGroup(parser, "Destination") group = optparse.OptionGroup(parser, "Destination")
group.add_option("-i", "--ip", group.add_option(
"-i", "--ip",
dest="esp_ip", dest="esp_ip",
action="store", action="store",
help="ESP8266 IP Address.", help="ESP8266 IP Address.",
default=False default=False
) )
group.add_option("-I", "--host_ip", group.add_option(
"-I", "--host_ip",
dest="host_ip", dest="host_ip",
action="store", action="store",
help="Host IP Address.", help="Host IP Address.",
default="0.0.0.0" default="0.0.0.0"
) )
group.add_option("-p", "--port", group.add_option(
"-p", "--port",
dest="esp_port", dest="esp_port",
type="int", type="int",
help="ESP8266 ota Port. Default 8266", help="ESP8266 ota Port. Default 8266",
default=8266 default=8266
) )
group.add_option("-P", "--host_port", group.add_option(
"-P", "--host_port",
dest="host_port", dest="host_port",
type="int", type="int",
help="Host server ota Port. Default random 10000-60000", help="Host server ota Port. Default random 10000-60000",
@@ -262,7 +269,8 @@ def parser(unparsed_args):
# auth # auth
group = optparse.OptionGroup(parser, "Authentication") group = optparse.OptionGroup(parser, "Authentication")
group.add_option("-a", "--auth", group.add_option(
"-a", "--auth",
dest="auth", dest="auth",
help="Set authentication password.", help="Set authentication password.",
action="store", action="store",
@@ -272,13 +280,15 @@ def parser(unparsed_args):
# image # image
group = optparse.OptionGroup(parser, "Image") group = optparse.OptionGroup(parser, "Image")
group.add_option("-f", "--file", group.add_option(
"-f", "--file",
dest="image", dest="image",
help="Image file.", help="Image file.",
metavar="FILE", metavar="FILE",
default=None default=None
) )
group.add_option("-s", "--spiffs", group.add_option(
"-s", "--spiffs",
dest="spiffs", dest="spiffs",
action="store_true", action="store_true",
help="Use this option to transmit a SPIFFS image and do not flash the " help="Use this option to transmit a SPIFFS image and do not flash the "
@@ -289,13 +299,15 @@ def parser(unparsed_args):
# output group # output group
group = optparse.OptionGroup(parser, "Output") group = optparse.OptionGroup(parser, "Output")
group.add_option("-d", "--debug", group.add_option(
"-d", "--debug",
dest="debug", dest="debug",
help="Show debug output. And override loglevel with debug.", help="Show debug output. And override loglevel with debug.",
action="store_true", action="store_true",
default=False default=False
) )
group.add_option("-r", "--progress", group.add_option(
"-r", "--progress",
dest="progress", dest="progress",
help="Show progress output. Does not work for ArduinoIDE", help="Show progress output. Does not work for ArduinoIDE",
action="store_true", action="store_true",
@@ -303,13 +315,13 @@ def parser(unparsed_args):
) )
parser.add_option_group(group) parser.add_option_group(group)
(options, args) = parser.parse_args(unparsed_args) options, _ = parser.parse_args(unparsed_args)
return options return options
def main(args): def main(args):
options = parser(args) options = parse_args(args)
_LOGGER.debug("Options: %s", str(options)) _LOGGER.debug("Options: %s", str(options))
# check options # check options

View File

@@ -48,7 +48,7 @@ class Expression(object):
pass pass
def __str__(self): def __str__(self):
raise NotImplemented raise NotImplementedError
class RawExpression(Expression): class RawExpression(Expression):
@@ -107,11 +107,11 @@ class StructInitializer(Expression):
self.args[key] = safe_exp(value) self.args[key] = safe_exp(value)
def __str__(self): def __str__(self):
s = u'{}{{\n'.format(self.base) cpp = u'{}{{\n'.format(self.base)
for key, value in self.args.iteritems(): for key, value in self.args.iteritems():
s += u' .{} = {},\n'.format(key, value) cpp += u' .{} = {},\n'.format(key, value)
s += u'}' cpp += u'}'
return s return cpp
class ArrayInitializer(Expression): class ArrayInitializer(Expression):
@@ -122,25 +122,25 @@ class ArrayInitializer(Expression):
def __str__(self): def __str__(self):
if not self.args: if not self.args:
return u'{}' return u'{}'
s = u'{\n' cpp = u'{\n'
for arg in self.args: for arg in self.args:
s += u' {},\n'.format(arg) cpp += u' {},\n'.format(arg)
s += u'}' cpp += u'}'
return s return cpp
class Literal(Expression): class Literal(Expression):
def __init__(self): def __str__(self):
super(Literal, self).__init__() raise NotImplementedError
class StringLiteral(Literal): class StringLiteral(Literal):
def __init__(self, s): def __init__(self, string):
super(StringLiteral, self).__init__() super(StringLiteral, self).__init__()
self.s = s self.string = string
def __str__(self): def __str__(self):
return u'"{}"'.format(self.s) return u'"{}"'.format(self.string)
class IntLiteral(Literal): class IntLiteral(Literal):
@@ -153,12 +153,12 @@ class IntLiteral(Literal):
class BoolLiteral(Literal): class BoolLiteral(Literal):
def __init__(self, b): def __init__(self, binary):
super(BoolLiteral, self).__init__() super(BoolLiteral, self).__init__()
self.b = b self.binary = binary
def __str__(self): def __str__(self):
return u"true" if self.b else u"false" return u"true" if self.binary else u"false"
class HexIntLiteral(Literal): class HexIntLiteral(Literal):
@@ -171,12 +171,12 @@ class HexIntLiteral(Literal):
class FloatLiteral(Literal): class FloatLiteral(Literal):
def __init__(self, f): def __init__(self, float_):
super(FloatLiteral, self).__init__() super(FloatLiteral, self).__init__()
self.f = f self.float_ = float_
def __str__(self): def __str__(self):
return u"{:f}f".format(self.f) return u"{:f}f".format(self.float_)
def safe_exp(obj): def safe_exp(obj):
@@ -184,7 +184,7 @@ def safe_exp(obj):
return obj return obj
elif isinstance(obj, bool): elif isinstance(obj, bool):
return BoolLiteral(obj) return BoolLiteral(obj)
elif isinstance(obj, str) or isinstance(obj, unicode): elif isinstance(obj, (str, unicode)):
return StringLiteral(obj) return StringLiteral(obj)
elif isinstance(obj, (int, long)): elif isinstance(obj, (int, long)):
return IntLiteral(obj) return IntLiteral(obj)
@@ -198,7 +198,7 @@ class Statement(object):
pass pass
def __str__(self): def __str__(self):
raise NotImplemented raise NotImplementedError
class RawStatement(Statement): class RawStatement(Statement):
@@ -225,6 +225,7 @@ def statement(expression):
return ExpressionStatement(expression) return ExpressionStatement(expression)
# pylint: disable=redefined-builtin, invalid-name
def variable(type, id, rhs): def variable(type, id, rhs):
lhs = RawExpression(u'{} {}'.format(type if not SIMPLIFY else u'auto', id)) lhs = RawExpression(u'{} {}'.format(type if not SIMPLIFY else u'auto', id))
rhs = safe_exp(rhs) rhs = safe_exp(rhs)

View File

@@ -13,7 +13,7 @@ _LOGGER = logging.getLogger(__name__)
def initialize(config, subscriptions, on_message, username, password, client_id): def initialize(config, subscriptions, on_message, username, password, client_id):
def on_connect(client, userdata, flags, rc): def on_connect(client, userdata, flags, return_code):
for topic in subscriptions: for topic in subscriptions:
client.subscribe(topic) client.subscribe(topic)
@@ -47,8 +47,8 @@ def show_logs(config, topic=None, username=None, password=None, client_id=None):
_LOGGER.info(u"Starting log output from %s", topic) _LOGGER.info(u"Starting log output from %s", topic)
def on_message(client, userdata, msg): def on_message(client, userdata, msg):
t = datetime.now().time().strftime(u'[%H:%M:%S] ') time = datetime.now().time().strftime(u'[%H:%M:%S] ')
print(t + msg.payload) print(time + msg.payload)
return initialize(config, [topic], on_message, username, password, client_id) return initialize(config, [topic], on_message, username, password, client_id)
@@ -58,7 +58,7 @@ def clear_topic(config, topic, username=None, password=None, client_id=None):
discovery_prefix = config[CONF_MQTT].get(CONF_DISCOVERY_PREFIX, u'homeassistant') discovery_prefix = config[CONF_MQTT].get(CONF_DISCOVERY_PREFIX, u'homeassistant')
name = config[CONF_ESPHOMEYAML][CONF_NAME] name = config[CONF_ESPHOMEYAML][CONF_NAME]
topic = u'{}/+/{}/#'.format(discovery_prefix, name) topic = u'{}/+/{}/#'.format(discovery_prefix, name)
_LOGGER.info(u"Clearing messages from {}".format(topic)) _LOGGER.info(u"Clearing messages from %s", topic)
def on_message(client, userdata, msg): def on_message(client, userdata, msg):
if not msg.payload: if not msg.payload:

View File

@@ -101,16 +101,16 @@ def _validate_gpio_pin(value):
if value < 0 or value > 39: if value < 0 or value > 39:
raise vol.Invalid(u"ESP32: Invalid pin number: {}".format(value)) raise vol.Invalid(u"ESP32: Invalid pin number: {}".format(value))
if 6 <= value <= 11: if 6 <= value <= 11:
_LOGGER.warning(u"ESP32: Pin {} (6-11) might already be used by the " _LOGGER.warning(u"ESP32: Pin %s (6-11) might already be used by the "
u"flash interface. Be warned.".format(value)) u"flash interface. Be warned.", value)
if value in (20, 24, 28, 29, 30, 31): if value in (20, 24, 28, 29, 30, 31):
_LOGGER.warning(u"ESP32: Pin {} (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.".format(value)) u"Be warned.", value)
return value return value
elif cv.ESP_PLATFORM == ESP_PLATFORM_ESP8266: elif cv.ESP_PLATFORM == ESP_PLATFORM_ESP8266:
if 6 <= value <= 11: if 6 <= value <= 11:
_LOGGER.warning(u"ESP8266: Pin {} (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.".format(value)) u"flash interface. Be warned.", value)
if value < 0 or value > 17: if value < 0 or value > 17:
raise vol.Invalid(u"ESP8266: Invalid pin number: {}".format(value)) raise vol.Invalid(u"ESP8266: Invalid pin number: {}".format(value))
return value return value
@@ -153,6 +153,7 @@ def analog_pin(value):
raise vol.Invalid(u"Invalid ESP platform.") raise vol.Invalid(u"Invalid ESP platform.")
# pylint: disable=invalid-name
input_output_pin = vol.All(input_pin, output_pin) input_output_pin = vol.All(input_pin, output_pin)
gpio_pin = vol.Any(input_pin, output_pin) gpio_pin = vol.Any(input_pin, output_pin)
PIN_MODES_ESP8266 = [ PIN_MODES_ESP8266 = [

View File

@@ -2,16 +2,18 @@ from __future__ import print_function
import codecs import codecs
import os import os
from time import sleep
import unicodedata import unicodedata
from time import sleep
import voluptuous as vol import voluptuous as vol
import esphomeyaml.config_validation as cv import esphomeyaml.config_validation as cv
from esphomeyaml.components import mqtt from esphomeyaml.components import mqtt
from esphomeyaml.const import ESP_PLATFORMS, ESP_PLATFORM_ESP32, ESP_BOARDS_FOR_PLATFORM from esphomeyaml.const import ESP_BOARDS_FOR_PLATFORM, ESP_PLATFORMS, ESP_PLATFORM_ESP32
from esphomeyaml.helpers import color from esphomeyaml.helpers import color
# pylint: disable=anomalous-backslash-in-string
CORE_BIG = """ _____ ____ _____ ______ CORE_BIG = """ _____ ____ _____ ______
/ ____/ __ \| __ \| ____| / ____/ __ \| __ \| ____|
| | | | | | |__) | |__ | | | | | | |__) | |__
@@ -20,7 +22,7 @@ CORE_BIG = """ _____ ____ _____ ______
\_____\____/|_| \_\______| \_____\____/|_| \_\______|
""" """
ESP_BIG = """ ______ _____ _____ ESP_BIG = """ ______ _____ _____
| ____|/ ____| __ \ | ____|/ ____| __ \\
| |__ | (___ | |__) | | |__ | (___ | |__) |
| __| \___ \| ___/ | __| \___ \| ___/
| |____ ____) | | | |____ ____) | |
@@ -41,10 +43,10 @@ MQTT_BIG = """ __ __ ____ _______ _______
|_| |_|\___\_\ |_| |_| |_| |_|\___\_\ |_| |_|
""" """
OTA_BIG = """ ____ _______ OTA_BIG = """ ____ _______
/ __ \__ __|/\ / __ \__ __|/\\
| | | | | | / \ | | | | | | / \\
| | | | | | / /\ \ | | | | | | / /\ \\
| |__| | | |/ ____ \ | |__| | | |/ ____ \\
\____/ |_/_/ \_\\ \____/ |_/_/ \_\\
""" """
@@ -85,8 +87,8 @@ def default_input(text, default):
# From https://stackoverflow.com/a/518232/8924614 # From https://stackoverflow.com/a/518232/8924614
def strip_accents(s): def strip_accents(string):
return u''.join(c for c in unicodedata.normalize('NFD', unicode(s)) return u''.join(c for c in unicodedata.normalize('NFD', unicode(string))
if unicodedata.category(c) != 'Mn') if unicodedata.category(c) != 'Mn')
@@ -230,9 +232,9 @@ def wizard(path):
try: try:
broker = mqtt.validate_broker(broker) broker = mqtt.validate_broker(broker)
break break
except vol.Invalid as e: except vol.Invalid as err:
print(color('red', "The broker address \"{}\" seems to be invalid: {} :(".format( print(color('red', "The broker address \"{}\" seems to be invalid: {} :(".format(
broker, e))) broker, err)))
print("Please try again.") print("Please try again.")
print() print()
sleep(1) sleep(1)
@@ -271,8 +273,8 @@ def wizard(path):
else: else:
config += "ota:\n" config += "ota:\n"
with codecs.open(path, 'w') as f: with codecs.open(path, 'w') as f_handle:
f.write(config) f_handle.write(config)
print() print()
print(color('cyan', "DONE! I've now written a new configuration file to ") + print(color('cyan', "DONE! I've now written a new configuration file to ") +
@@ -290,4 +292,3 @@ def wizard(path):
print(" > Then follow the rest of the getting started guide:") print(" > Then follow the rest of the getting started guide:")
print(" > https://esphomelib.com/esphomeyaml/getting-started.html") print(" > https://esphomelib.com/esphomeyaml/getting-started.html")
return 0 return 0

View File

@@ -6,7 +6,7 @@ import os
from esphomeyaml.config import get_component from esphomeyaml.config import get_component
from esphomeyaml.const import CONF_BOARD, CONF_ESPHOMEYAML, CONF_LIBRARY_URI, CONF_LOGGER, \ from esphomeyaml.const import CONF_BOARD, CONF_ESPHOMEYAML, CONF_LIBRARY_URI, CONF_LOGGER, \
CONF_NAME, CONF_OTA, CONF_PLATFORM, ESP_PLATFORM_ESP32, ESP_PLATFORM_ESP8266 CONF_NAME, CONF_PLATFORM, ESP_PLATFORM_ESP32, ESP_PLATFORM_ESP8266
from esphomeyaml.core import ESPHomeYAMLError from esphomeyaml.core import ESPHomeYAMLError
CPP_AUTO_GENERATE_BEGIN = u'// ========== AUTO GENERATED CODE BEGIN ===========' CPP_AUTO_GENERATE_BEGIN = u'// ========== AUTO GENERATED CODE BEGIN ==========='
@@ -63,7 +63,7 @@ PLATFORM_TO_PLATFORMIO = {
def get_ini_content(config): def get_ini_content(config):
d = { options = {
u'env': config[CONF_ESPHOMEYAML][CONF_NAME], u'env': config[CONF_ESPHOMEYAML][CONF_NAME],
u'platform': PLATFORM_TO_PLATFORMIO[config[CONF_ESPHOMEYAML][CONF_PLATFORM]], u'platform': PLATFORM_TO_PLATFORMIO[config[CONF_ESPHOMEYAML][CONF_PLATFORM]],
u'board': config[CONF_ESPHOMEYAML][CONF_BOARD], u'board': config[CONF_ESPHOMEYAML][CONF_BOARD],
@@ -73,8 +73,8 @@ def get_ini_content(config):
if CONF_LOGGER in config: if CONF_LOGGER in config:
build_flags = get_component(CONF_LOGGER).get_build_flags(config[CONF_LOGGER]) build_flags = get_component(CONF_LOGGER).get_build_flags(config[CONF_LOGGER])
if build_flags: if build_flags:
d[u'build_flags'] = u'\n ' + build_flags options[u'build_flags'] = u'\n ' + build_flags
return INI_CONTENT_FORMAT.format(**d) return INI_CONTENT_FORMAT.format(**options)
def mkdir_p(path): def mkdir_p(path):
@@ -109,8 +109,8 @@ def find_begin_end(text, begin_s, end_s):
def write_platformio_ini(content, path): def write_platformio_ini(content, path):
if os.path.isfile(path): if os.path.isfile(path):
try: try:
with codecs.open(path, 'r', encoding='utf-8') as f: with codecs.open(path, 'r', encoding='utf-8') as f_handle:
text = f.read() text = f_handle.read()
except OSError: except OSError:
raise ESPHomeYAMLError(u"Could not read ini file at {}".format(path)) raise ESPHomeYAMLError(u"Could not read ini file at {}".format(path))
prev_file = text prev_file = text
@@ -123,15 +123,15 @@ def write_platformio_ini(content, path):
content + INI_AUTO_GENERATE_END + content_format[1] content + INI_AUTO_GENERATE_END + content_format[1]
if prev_file == full_file: if prev_file == full_file:
return return
with codecs.open(path, mode='w+', encoding='utf-8') as f: with codecs.open(path, mode='w+', encoding='utf-8') as f_handle:
f.write(full_file) f_handle.write(full_file)
def write_cpp(code_s, path): def write_cpp(code_s, path):
if os.path.isfile(path): if os.path.isfile(path):
try: try:
with codecs.open(path, 'r', encoding='utf-8') as f: with codecs.open(path, 'r', encoding='utf-8') as f_handle:
text = f.read() text = f_handle.read()
except OSError: except OSError:
raise ESPHomeYAMLError(u"Could not read C++ file at {}".format(path)) raise ESPHomeYAMLError(u"Could not read C++ file at {}".format(path))
prev_file = text prev_file = text
@@ -145,5 +145,5 @@ def write_cpp(code_s, path):
code_s + CPP_AUTO_GENERATE_END + code_format[1] code_s + CPP_AUTO_GENERATE_END + code_format[1]
if prev_file == full_file: if prev_file == full_file:
return return
with codecs.open(path, 'w+', encoding='utf-8') as f: with codecs.open(path, 'w+', encoding='utf-8') as f_handle:
f.write(full_file) f_handle.write(full_file)

View File

@@ -1,7 +1,9 @@
from __future__ import print_function from __future__ import print_function
import codecs import codecs
import fnmatch
import logging import logging
from collections import OrderedDict from collections import OrderedDict
import os
import yaml import yaml
@@ -9,6 +11,11 @@ from esphomeyaml.core import ESPHomeYAMLError, HexInt, IPAddress
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
# Mostly copied from Home Assistant because that code works fine and
# let's not reinvent the wheel here
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."""
@@ -97,8 +104,107 @@ def _add_reference(obj, loader, node):
return obj return obj
def _env_var_yaml(loader, node):
"""Load environment variables and embed it into the configuration YAML."""
args = node.value.split()
# Check for a default value
if len(args) > 1:
return os.getenv(args[0], u' '.join(args[1:]))
elif args[0] in os.environ:
return os.environ[args[0]]
raise ESPHomeYAMLError(u"Environment variable {} not defined.".format(node.value))
def _include_yaml(loader, node):
"""Load another YAML file and embeds it using the !include tag.
Example:
device_tracker: !include device_tracker.yaml
"""
fname = os.path.join(os.path.dirname(loader.name), node.value)
return _add_reference(load_yaml(fname), loader, node)
def _is_file_valid(name):
"""Decide if a file is valid."""
return not name.startswith(u'.')
def _find_files(directory, pattern):
"""Recursively load files in a directory."""
for root, dirs, files in os.walk(directory, topdown=True):
dirs[:] = [d for d in dirs if _is_file_valid(d)]
for basename in files:
if _is_file_valid(basename) and fnmatch.fnmatch(basename, pattern):
filename = os.path.join(root, basename)
yield filename
def _include_dir_named_yaml(loader, node):
"""Load multiple files from directory as a dictionary."""
mapping = OrderedDict() # type: OrderedDict
loc = os.path.join(os.path.dirname(loader.name), node.value)
for fname in _find_files(loc, '*.yaml'):
filename = os.path.splitext(os.path.basename(fname))[0]
mapping[filename] = load_yaml(fname)
return _add_reference(mapping, loader, node)
def _include_dir_merge_named_yaml(loader, node):
"""Load multiple files from directory as a merged dictionary."""
mapping = OrderedDict() # type: OrderedDict
loc = os.path.join(os.path.dirname(loader.name), node.value)
for fname in _find_files(loc, '*.yaml'):
if os.path.basename(fname) == SECRET_YAML:
continue
loaded_yaml = load_yaml(fname)
if isinstance(loaded_yaml, dict):
mapping.update(loaded_yaml)
return _add_reference(mapping, loader, node)
def _include_dir_list_yaml(loader, node):
"""Load multiple files from directory as a list."""
loc = os.path.join(os.path.dirname(loader.name), node.value)
return [load_yaml(f) for f in _find_files(loc, '*.yaml')
if os.path.basename(f) != SECRET_YAML]
def _include_dir_merge_list_yaml(loader, node):
"""Load multiple files from directory as a merged list."""
path = os.path.join(os.path.dirname(loader.name), node.value)
merged_list = []
for fname in _find_files(path, '*.yaml'):
if os.path.basename(fname) == SECRET_YAML:
continue
loaded_yaml = load_yaml(fname)
if isinstance(loaded_yaml, list):
merged_list.extend(loaded_yaml)
return _add_reference(merged_list, loader, node)
# pylint: disable=protected-access
def _secret_yaml(loader, node):
"""Load secrets and embed it into the configuration YAML."""
secret_path = os.path.join(os.path.dirname(loader.name), SECRET_YAML)
secrets = load_yaml(secret_path)
if node.value not in secrets:
raise ESPHomeYAMLError(u"Secret {} not defined".format(node.value))
return secrets[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)
yaml.SafeLoader.add_constructor(yaml.resolver.BaseResolver.DEFAULT_SEQUENCE_TAG, _construct_seq) yaml.SafeLoader.add_constructor(yaml.resolver.BaseResolver.DEFAULT_SEQUENCE_TAG, _construct_seq)
yaml.SafeLoader.add_constructor('!env_var', _env_var_yaml)
yaml.SafeLoader.add_constructor('!secret', _secret_yaml)
yaml.SafeLoader.add_constructor('!include', _include_yaml)
yaml.SafeLoader.add_constructor('!include_dir_list', _include_dir_list_yaml)
yaml.SafeLoader.add_constructor('!include_dir_merge_list',
_include_dir_merge_list_yaml)
yaml.SafeLoader.add_constructor('!include_dir_named', _include_dir_named_yaml)
yaml.SafeLoader.add_constructor('!include_dir_merge_named',
_include_dir_merge_named_yaml)
# From: https://gist.github.com/miracle2k/3184458 # From: https://gist.github.com/miracle2k/3184458

22
pylintrc Normal file
View File

@@ -0,0 +1,22 @@
[MASTER]
reports=no
disable=
missing-docstring,
fixme,
unused-argument,
global-statement,
too-few-public-methods,
too-many-locals,
too-many-ancestors,
too-many-branches,
too-many-statements,
too-many-arguments,
too-many-return-statements,
duplicate-code,
additional-builtins=
unicode,
long,
raw_input

View File

@@ -1,2 +1,6 @@
[metadata] [metadata]
description-file = README.md description-file = README.md
[flake8]
max-line-length = 120
builtins = unicode, long, raw_input