From 8867a0fcfb8c5116c57358c737fe531edf0de705 Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Wed, 23 Oct 2019 14:43:27 +0200 Subject: [PATCH] Add additional custom lint checks (#790) --- .../components/binary_sensor_map/sensor.py | 3 +- esphome/components/coolix/climate.py | 8 +- esphome/components/custom/output/__init__.py | 3 +- esphome/components/dfplayer/__init__.py | 4 +- .../esp32_ble_beacon/esp32_ble_beacon.cpp | 2 +- .../esp32_ble_tracker/esp32_ble_tracker.cpp | 2 +- esphome/components/esp32_camera/__init__.py | 6 +- .../components/esp32_touch/esp32_touch.cpp | 8 +- esphome/components/esp32_touch/esp32_touch.h | 1 + esphome/components/mpr121/mpr121.cpp | 2 +- esphome/components/mqtt/mqtt_client.cpp | 2 +- esphome/components/ms5611/ms5611.cpp | 2 +- esphome/components/ota/ota_component.cpp | 2 +- esphome/components/pmsx003/sensor.py | 24 ++-- esphome/components/restart/restart_switch.cpp | 4 +- esphome/components/rotary_encoder/sensor.py | 4 +- esphome/components/scd30/sensor.py | 4 +- esphome/components/sgp30/sensor.py | 12 +- .../components/shutdown/shutdown_switch.cpp | 2 +- .../components/ssd1325_spi/ssd1325_spi.cpp | 2 +- .../sx1509/binary_sensor/__init__.py | 6 +- esphome/components/tcl112/climate.py | 8 +- .../components/template/output/__init__.py | 3 +- .../waveshare_epaper/waveshare_epaper.h | 8 +- esphome/components/wifi/wifi_component.cpp | 2 +- esphome/components/yashima/climate.py | 7 +- esphome/const.py | 66 ++++----- script/ci-custom.py | 126 +++++++++++++++++- 28 files changed, 214 insertions(+), 109 deletions(-) diff --git a/esphome/components/binary_sensor_map/sensor.py b/esphome/components/binary_sensor_map/sensor.py index 8b8cd8fc4e..27f4654ded 100644 --- a/esphome/components/binary_sensor_map/sensor.py +++ b/esphome/components/binary_sensor_map/sensor.py @@ -3,7 +3,7 @@ import esphome.config_validation as cv from esphome.components import sensor, binary_sensor from esphome.const import CONF_ID, CONF_CHANNELS, CONF_VALUE, CONF_TYPE, UNIT_EMPTY, \ - ICON_CHECK_CIRCLE_OUTLINE, CONF_BINARY_SENSOR + ICON_CHECK_CIRCLE_OUTLINE, CONF_BINARY_SENSOR, CONF_GROUP DEPENDENCIES = ['binary_sensor'] @@ -11,7 +11,6 @@ binary_sensor_map_ns = cg.esphome_ns.namespace('binary_sensor_map') BinarySensorMap = binary_sensor_map_ns.class_('BinarySensorMap', cg.Component, sensor.Sensor) SensorMapType = binary_sensor_map_ns.enum('SensorMapType') -CONF_GROUP = 'group' SENSOR_MAP_TYPES = { CONF_GROUP: SensorMapType.BINARY_SENSOR_MAP_TYPE_GROUP, } diff --git a/esphome/components/coolix/climate.py b/esphome/components/coolix/climate.py index fe74798689..14868a7be0 100644 --- a/esphome/components/coolix/climate.py +++ b/esphome/components/coolix/climate.py @@ -1,18 +1,14 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import climate, remote_transmitter, remote_receiver, sensor -from esphome.const import CONF_ID, CONF_SENSOR +from esphome.components.remote_base import CONF_TRANSMITTER_ID, CONF_RECEIVER_ID +from esphome.const import CONF_ID, CONF_SENSOR, CONF_SUPPORTS_COOL, CONF_SUPPORTS_HEAT AUTO_LOAD = ['sensor', 'climate_ir'] coolix_ns = cg.esphome_ns.namespace('coolix') CoolixClimate = coolix_ns.class_('CoolixClimate', climate.Climate, cg.Component) -CONF_TRANSMITTER_ID = 'transmitter_id' -CONF_RECEIVER_ID = 'receiver_id' -CONF_SUPPORTS_HEAT = 'supports_heat' -CONF_SUPPORTS_COOL = 'supports_cool' - CONFIG_SCHEMA = cv.All(climate.CLIMATE_SCHEMA.extend({ cv.GenerateID(): cv.declare_id(CoolixClimate), cv.GenerateID(CONF_TRANSMITTER_ID): cv.use_id(remote_transmitter.RemoteTransmitterComponent), diff --git a/esphome/components/custom/output/__init__.py b/esphome/components/custom/output/__init__.py index 6042863872..efe6f19dab 100644 --- a/esphome/components/custom/output/__init__.py +++ b/esphome/components/custom/output/__init__.py @@ -1,13 +1,12 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import output -from esphome.const import CONF_ID, CONF_LAMBDA, CONF_OUTPUTS, CONF_TYPE +from esphome.const import CONF_ID, CONF_LAMBDA, CONF_OUTPUTS, CONF_TYPE, CONF_BINARY from .. import custom_ns CustomBinaryOutputConstructor = custom_ns.class_('CustomBinaryOutputConstructor') CustomFloatOutputConstructor = custom_ns.class_('CustomFloatOutputConstructor') -CONF_BINARY = 'binary' CONF_FLOAT = 'float' CONFIG_SCHEMA = cv.typed_schema({ diff --git a/esphome/components/dfplayer/__init__.py b/esphome/components/dfplayer/__init__.py index 78bcfa80f4..890c2bede4 100644 --- a/esphome/components/dfplayer/__init__.py +++ b/esphome/components/dfplayer/__init__.py @@ -1,7 +1,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation -from esphome.const import CONF_ID, CONF_TRIGGER_ID +from esphome.const import CONF_ID, CONF_TRIGGER_ID, CONF_FILE, CONF_DEVICE from esphome.components import uart DEPENDENCIES = ['uart'] @@ -14,10 +14,8 @@ DFPlayerIsPlayingCondition = dfplayer_ns.class_('DFPlayerIsPlayingCondition', au MULTI_CONF = True CONF_FOLDER = 'folder' -CONF_FILE = 'file' CONF_LOOP = 'loop' CONF_VOLUME = 'volume' -CONF_DEVICE = 'device' CONF_EQ_PRESET = 'eq_preset' CONF_ON_FINISHED_PLAYBACK = 'on_finished_playback' diff --git a/esphome/components/esp32_ble_beacon/esp32_ble_beacon.cpp b/esphome/components/esp32_ble_beacon/esp32_ble_beacon.cpp index 1f3bf01a86..a61975d02f 100644 --- a/esphome/components/esp32_ble_beacon/esp32_ble_beacon.cpp +++ b/esphome/components/esp32_ble_beacon/esp32_ble_beacon.cpp @@ -50,7 +50,7 @@ void ESP32BLEBeacon::ble_core_task(void *params) { ble_setup(); while (true) { - delay(1000); + delay(1000); // NOLINT } } void ESP32BLEBeacon::ble_setup() { diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp index c578acdaea..7a5bd733a2 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp @@ -134,7 +134,7 @@ bool ESP32BLETracker::ble_setup() { } // BLE takes some time to be fully set up, 200ms should be more than enough - delay(200); + delay(200); // NOLINT return true; } diff --git a/esphome/components/esp32_camera/__init__.py b/esphome/components/esp32_camera/__init__.py index c69e0a5710..81980d9d38 100644 --- a/esphome/components/esp32_camera/__init__.py +++ b/esphome/components/esp32_camera/__init__.py @@ -2,7 +2,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import pins from esphome.const import CONF_FREQUENCY, CONF_ID, CONF_NAME, CONF_PIN, CONF_SCL, CONF_SDA, \ - ESP_PLATFORM_ESP32 + ESP_PLATFORM_ESP32, CONF_DATA_PINS, CONF_RESET_PIN, CONF_RESOLUTION, CONF_BRIGHTNESS ESP_PLATFORMS = [ESP_PLATFORM_ESP32] DEPENDENCIES = ['api'] @@ -35,23 +35,19 @@ FRAME_SIZES = { 'UXGA': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_1600X1200, } -CONF_DATA_PINS = 'data_pins' CONF_VSYNC_PIN = 'vsync_pin' CONF_HREF_PIN = 'href_pin' CONF_PIXEL_CLOCK_PIN = 'pixel_clock_pin' CONF_EXTERNAL_CLOCK = 'external_clock' CONF_I2C_PINS = 'i2c_pins' -CONF_RESET_PIN = 'reset_pin' CONF_POWER_DOWN_PIN = 'power_down_pin' CONF_MAX_FRAMERATE = 'max_framerate' CONF_IDLE_FRAMERATE = 'idle_framerate' -CONF_RESOLUTION = 'resolution' CONF_JPEG_QUALITY = 'jpeg_quality' CONF_VERTICAL_FLIP = 'vertical_flip' CONF_HORIZONTAL_MIRROR = 'horizontal_mirror' CONF_CONTRAST = 'contrast' -CONF_BRIGHTNESS = 'brightness' CONF_SATURATION = 'saturation' CONF_TEST_PATTERN = 'test_pattern' diff --git a/esphome/components/esp32_touch/esp32_touch.cpp b/esphome/components/esp32_touch/esp32_touch.cpp index 56bc407e84..ce0028159e 100644 --- a/esphome/components/esp32_touch/esp32_touch.cpp +++ b/esphome/components/esp32_touch/esp32_touch.cpp @@ -108,6 +108,8 @@ void ESP32TouchComponent::dump_config() { } void ESP32TouchComponent::loop() { + const uint32_t now = millis(); + bool should_print = this->setup_mode_ && now - this->setup_mode_last_log_print_ > 250; for (auto *child : this->children_) { uint16_t value; if (this->iir_filter_enabled_()) { @@ -119,14 +121,14 @@ void ESP32TouchComponent::loop() { child->value_ = value; child->publish_state(value < child->get_threshold()); - if (this->setup_mode_) { + if (should_print) { ESP_LOGD(TAG, "Touch Pad '%s' (T%u): %u", child->get_name().c_str(), child->get_touch_pad(), value); } } - if (this->setup_mode_) { + if (should_print) { // Avoid spamming logs - delay(250); + this->setup_mode_last_log_print_ = now; } } diff --git a/esphome/components/esp32_touch/esp32_touch.h b/esphome/components/esp32_touch/esp32_touch.h index 7adee23971..45d459a2ff 100644 --- a/esphome/components/esp32_touch/esp32_touch.h +++ b/esphome/components/esp32_touch/esp32_touch.h @@ -50,6 +50,7 @@ class ESP32TouchComponent : public Component { touch_volt_atten_t voltage_attenuation_{}; std::vector children_; bool setup_mode_{false}; + uint32_t setup_mode_last_log_print_{}; uint32_t iir_filter_{0}; }; diff --git a/esphome/components/mpr121/mpr121.cpp b/esphome/components/mpr121/mpr121.cpp index a24a703306..2025bc5b3f 100644 --- a/esphome/components/mpr121/mpr121.cpp +++ b/esphome/components/mpr121/mpr121.cpp @@ -10,7 +10,7 @@ void MPR121Component::setup() { ESP_LOGCONFIG(TAG, "Setting up MPR121..."); // soft reset device this->write_byte(MPR121_SOFTRESET, 0x63); - delay(100); + delay(100); // NOLINT if (!this->write_byte(MPR121_ECR, 0x0)) { this->error_code_ = COMMUNICATION_FAILED; this->mark_failed(); diff --git a/esphome/components/mqtt/mqtt_client.cpp b/esphome/components/mqtt/mqtt_client.cpp index e07204d559..2eb1c52153 100644 --- a/esphome/components/mqtt/mqtt_client.cpp +++ b/esphome/components/mqtt/mqtt_client.cpp @@ -201,7 +201,7 @@ void MQTTClientComponent::check_connected() { this->status_clear_warning(); ESP_LOGI(TAG, "MQTT Connected!"); // MQTT Client needs some time to be fully set up. - delay(100); + delay(100); // NOLINT this->resubscribe_subscriptions_(); diff --git a/esphome/components/ms5611/ms5611.cpp b/esphome/components/ms5611/ms5611.cpp index 33ed6b1899..39bce9f32c 100644 --- a/esphome/components/ms5611/ms5611.cpp +++ b/esphome/components/ms5611/ms5611.cpp @@ -19,7 +19,7 @@ void MS5611Component::setup() { this->mark_failed(); return; } - delay(100); + delay(100); // NOLINT for (uint8_t offset = 0; offset < 6; offset++) { if (!this->read_byte_16(MS5611_CMD_READ_PROM + (offset * 2), &this->prom_[offset])) { this->mark_failed(); diff --git a/esphome/components/ota/ota_component.cpp b/esphome/components/ota/ota_component.cpp index 6d2a0dd7c3..2041c688eb 100644 --- a/esphome/components/ota/ota_component.cpp +++ b/esphome/components/ota/ota_component.cpp @@ -266,7 +266,7 @@ void OTAComponent::handle_() { delay(10); ESP_LOGI(TAG, "OTA update finished!"); this->status_clear_warning(); - delay(100); + delay(100); // NOLINT App.safe_reboot(); error: diff --git a/esphome/components/pmsx003/sensor.py b/esphome/components/pmsx003/sensor.py index fa9a92d430..0cbaf1bf29 100644 --- a/esphome/components/pmsx003/sensor.py +++ b/esphome/components/pmsx003/sensor.py @@ -12,24 +12,24 @@ pmsx003_ns = cg.esphome_ns.namespace('pmsx003') PMSX003Component = pmsx003_ns.class_('PMSX003Component', uart.UARTDevice, cg.Component) PMSX003Sensor = pmsx003_ns.class_('PMSX003Sensor', sensor.Sensor) -CONF_PMSX003 = 'PMSX003' -CONF_PMS5003T = 'PMS5003T' -CONF_PMS5003ST = 'PMS5003ST' +TYPE_PMSX003 = 'PMSX003' +TYPE_PMS5003T = 'PMS5003T' +TYPE_PMS5003ST = 'PMS5003ST' PMSX003Type = pmsx003_ns.enum('PMSX003Type') PMSX003_TYPES = { - CONF_PMSX003: PMSX003Type.PMSX003_TYPE_X003, - CONF_PMS5003T: PMSX003Type.PMSX003_TYPE_5003T, - CONF_PMS5003ST: PMSX003Type.PMSX003_TYPE_5003ST, + TYPE_PMSX003: PMSX003Type.PMSX003_TYPE_X003, + TYPE_PMS5003T: PMSX003Type.PMSX003_TYPE_5003T, + TYPE_PMS5003ST: PMSX003Type.PMSX003_TYPE_5003ST, } SENSORS_TO_TYPE = { - CONF_PM_1_0: [CONF_PMSX003, CONF_PMS5003ST], - CONF_PM_2_5: [CONF_PMSX003, CONF_PMS5003T, CONF_PMS5003ST], - CONF_PM_10_0: [CONF_PMSX003, CONF_PMS5003ST], - CONF_TEMPERATURE: [CONF_PMS5003T, CONF_PMS5003ST], - CONF_HUMIDITY: [CONF_PMS5003T, CONF_PMS5003ST], - CONF_FORMALDEHYDE: [CONF_PMS5003ST], + CONF_PM_1_0: [TYPE_PMSX003, TYPE_PMS5003ST], + CONF_PM_2_5: [TYPE_PMSX003, TYPE_PMS5003T, TYPE_PMS5003ST], + CONF_PM_10_0: [TYPE_PMSX003, TYPE_PMS5003ST], + CONF_TEMPERATURE: [TYPE_PMS5003T, TYPE_PMS5003ST], + CONF_HUMIDITY: [TYPE_PMS5003T, TYPE_PMS5003ST], + CONF_FORMALDEHYDE: [TYPE_PMS5003ST], } diff --git a/esphome/components/restart/restart_switch.cpp b/esphome/components/restart/restart_switch.cpp index cd0979b9d3..f66ebc616e 100644 --- a/esphome/components/restart/restart_switch.cpp +++ b/esphome/components/restart/restart_switch.cpp @@ -13,8 +13,8 @@ void RestartSwitch::write_state(bool state) { if (state) { ESP_LOGI(TAG, "Restarting device..."); - // then execute - delay(100); // Let MQTT settle a bit + // Let MQTT settle a bit + delay(100); // NOLINT App.safe_reboot(); } } diff --git a/esphome/components/rotary_encoder/sensor.py b/esphome/components/rotary_encoder/sensor.py index 742096cd5a..214ccbd056 100644 --- a/esphome/components/rotary_encoder/sensor.py +++ b/esphome/components/rotary_encoder/sensor.py @@ -3,7 +3,7 @@ import esphome.config_validation as cv from esphome import pins, automation from esphome.components import sensor from esphome.const import CONF_ID, CONF_RESOLUTION, CONF_MIN_VALUE, CONF_MAX_VALUE, UNIT_STEPS, \ - ICON_ROTATE_RIGHT, CONF_VALUE + ICON_ROTATE_RIGHT, CONF_VALUE, CONF_PIN_A, CONF_PIN_B rotary_encoder_ns = cg.esphome_ns.namespace('rotary_encoder') RotaryEncoderResolution = rotary_encoder_ns.enum('RotaryEncoderResolution') @@ -13,8 +13,6 @@ RESOLUTIONS = { 4: RotaryEncoderResolution.ROTARY_ENCODER_4_PULSES_PER_CYCLE, } -CONF_PIN_A = 'pin_a' -CONF_PIN_B = 'pin_b' CONF_PIN_RESET = 'pin_reset' RotaryEncoderSensor = rotary_encoder_ns.class_('RotaryEncoderSensor', sensor.Sensor, cg.Component) diff --git a/esphome/components/scd30/sensor.py b/esphome/components/scd30/sensor.py index aa863b904a..7a60725276 100644 --- a/esphome/components/scd30/sensor.py +++ b/esphome/components/scd30/sensor.py @@ -3,15 +3,13 @@ import esphome.config_validation as cv from esphome.components import i2c, sensor from esphome.const import CONF_ID, UNIT_PARTS_PER_MILLION, \ CONF_HUMIDITY, CONF_TEMPERATURE, ICON_PERIODIC_TABLE_CO2, \ - UNIT_CELSIUS, ICON_THERMOMETER, ICON_WATER_PERCENT, UNIT_PERCENT + UNIT_CELSIUS, ICON_THERMOMETER, ICON_WATER_PERCENT, UNIT_PERCENT, CONF_CO2 DEPENDENCIES = ['i2c'] scd30_ns = cg.esphome_ns.namespace('scd30') SCD30Component = scd30_ns.class_('SCD30Component', cg.PollingComponent, i2c.I2CDevice) -CONF_CO2 = 'co2' - CONFIG_SCHEMA = cv.Schema({ cv.GenerateID(): cv.declare_id(SCD30Component), cv.Required(CONF_CO2): sensor.sensor_schema(UNIT_PARTS_PER_MILLION, diff --git a/esphome/components/sgp30/sensor.py b/esphome/components/sgp30/sensor.py index 0063c29bd3..6329b122fd 100644 --- a/esphome/components/sgp30/sensor.py +++ b/esphome/components/sgp30/sensor.py @@ -14,8 +14,8 @@ CONF_TVOC = 'tvoc' CONF_BASELINE = 'baseline' CONF_UPTIME = 'uptime' CONF_COMPENSATION = 'compensation' -CONF_COMPENSATION_HUMIDITY = 'humidity_source' -CONF_COMPENSATION_TEMPERATURE = 'temperature_source' +CONF_HUMIDITY_SOURCE = 'humidity_source' +CONF_TEMPERATURE_SOURCE = 'temperature_source' CONFIG_SCHEMA = cv.Schema({ cv.GenerateID(): cv.declare_id(SGP30Component), @@ -24,8 +24,8 @@ CONFIG_SCHEMA = cv.Schema({ cv.Required(CONF_TVOC): sensor.sensor_schema(UNIT_PARTS_PER_BILLION, ICON_RADIATOR, 0), cv.Optional(CONF_BASELINE): cv.hex_uint16_t, cv.Optional(CONF_COMPENSATION): cv.Schema({ - cv.Required(CONF_COMPENSATION_HUMIDITY): cv.use_id(sensor.Sensor), - cv.Required(CONF_COMPENSATION_TEMPERATURE): cv.use_id(sensor.Sensor) + cv.Required(CONF_HUMIDITY_SOURCE): cv.use_id(sensor.Sensor), + cv.Required(CONF_TEMPERATURE_SOURCE): cv.use_id(sensor.Sensor) }), }).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x58)) @@ -48,7 +48,7 @@ def to_code(config): if CONF_COMPENSATION in config: compensation_config = config[CONF_COMPENSATION] - sens = yield cg.get_variable(compensation_config[CONF_COMPENSATION_HUMIDITY]) + sens = yield cg.get_variable(compensation_config[CONF_HUMIDITY_SOURCE]) cg.add(var.set_humidity_sensor(sens)) - sens = yield cg.get_variable(compensation_config[CONF_COMPENSATION_TEMPERATURE]) + sens = yield cg.get_variable(compensation_config[CONF_TEMPERATURE_SOURCE]) cg.add(var.set_temperature_sensor(sens)) diff --git a/esphome/components/shutdown/shutdown_switch.cpp b/esphome/components/shutdown/shutdown_switch.cpp index d27bb8aadc..ce33cd187f 100644 --- a/esphome/components/shutdown/shutdown_switch.cpp +++ b/esphome/components/shutdown/shutdown_switch.cpp @@ -14,7 +14,7 @@ void ShutdownSwitch::write_state(bool state) { if (state) { ESP_LOGI(TAG, "Shutting down..."); - delay(100); // Let MQTT settle a bit + delay(100); // NOLINT App.run_safe_shutdown_hooks(); #ifdef ARDUINO_ARCH_ESP8266 diff --git a/esphome/components/ssd1325_spi/ssd1325_spi.cpp b/esphome/components/ssd1325_spi/ssd1325_spi.cpp index 1f547f8fd3..399700f1dd 100644 --- a/esphome/components/ssd1325_spi/ssd1325_spi.cpp +++ b/esphome/components/ssd1325_spi/ssd1325_spi.cpp @@ -14,7 +14,7 @@ void SPISSD1325::setup() { this->cs_->setup(); // OUTPUT this->init_reset_(); - delay(500); + delay(500); // NOLINT SSD1325::setup(); } void SPISSD1325::dump_config() { diff --git a/esphome/components/sx1509/binary_sensor/__init__.py b/esphome/components/sx1509/binary_sensor/__init__.py index e780505edb..9a65524383 100644 --- a/esphome/components/sx1509/binary_sensor/__init__.py +++ b/esphome/components/sx1509/binary_sensor/__init__.py @@ -5,7 +5,7 @@ from esphome.const import CONF_ID from .. import SX1509Component, sx1509_ns, CONF_SX1509_ID CONF_ROW = 'row' -CONF_COLUMN = 'col' +CONF_COL = 'col' DEPENDENCIES = ['sx1509'] @@ -15,7 +15,7 @@ CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend({ cv.GenerateID(): cv.declare_id(SX1509BinarySensor), cv.GenerateID(CONF_SX1509_ID): cv.use_id(SX1509Component), cv.Required(CONF_ROW): cv.int_range(min=0, max=4), - cv.Required(CONF_COLUMN): cv.int_range(min=0, max=4), + cv.Required(CONF_COL): cv.int_range(min=0, max=4), }) @@ -23,6 +23,6 @@ def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) yield binary_sensor.register_binary_sensor(var, config) hub = yield cg.get_variable(config[CONF_SX1509_ID]) - cg.add(var.set_row_col(config[CONF_ROW], config[CONF_COLUMN])) + cg.add(var.set_row_col(config[CONF_ROW], config[CONF_COL])) cg.add(hub.register_keypad_binary_sensor(var)) diff --git a/esphome/components/tcl112/climate.py b/esphome/components/tcl112/climate.py index d21300d946..66af291a17 100644 --- a/esphome/components/tcl112/climate.py +++ b/esphome/components/tcl112/climate.py @@ -1,18 +1,14 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import climate, remote_transmitter, remote_receiver, sensor -from esphome.const import CONF_ID, CONF_SENSOR +from esphome.components.remote_base import CONF_TRANSMITTER_ID, CONF_RECEIVER_ID +from esphome.const import CONF_ID, CONF_SENSOR, CONF_SUPPORTS_COOL, CONF_SUPPORTS_HEAT AUTO_LOAD = ['sensor', 'climate_ir'] tcl112_ns = cg.esphome_ns.namespace('tcl112') Tcl112Climate = tcl112_ns.class_('Tcl112Climate', climate.Climate, cg.Component) -CONF_TRANSMITTER_ID = 'transmitter_id' -CONF_RECEIVER_ID = 'receiver_id' -CONF_SUPPORTS_HEAT = 'supports_heat' -CONF_SUPPORTS_COOL = 'supports_cool' - CONFIG_SCHEMA = cv.All(climate.CLIMATE_SCHEMA.extend({ cv.GenerateID(): cv.declare_id(Tcl112Climate), cv.GenerateID(CONF_TRANSMITTER_ID): cv.use_id(remote_transmitter.RemoteTransmitterComponent), diff --git a/esphome/components/template/output/__init__.py b/esphome/components/template/output/__init__.py index 5cc9e089bd..cc85a9da68 100644 --- a/esphome/components/template/output/__init__.py +++ b/esphome/components/template/output/__init__.py @@ -2,13 +2,12 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation from esphome.components import output -from esphome.const import CONF_ID, CONF_TYPE +from esphome.const import CONF_ID, CONF_TYPE, CONF_BINARY from .. import template_ns TemplateBinaryOutput = template_ns.class_('TemplateBinaryOutput', output.BinaryOutput) TemplateFloatOutput = template_ns.class_('TemplateFloatOutput', output.FloatOutput) -CONF_BINARY = 'binary' CONF_FLOAT = 'float' CONF_WRITE_ACTION = 'write_action' diff --git a/esphome/components/waveshare_epaper/waveshare_epaper.h b/esphome/components/waveshare_epaper/waveshare_epaper.h index 13aebd4ec9..eff6b895a9 100644 --- a/esphome/components/waveshare_epaper/waveshare_epaper.h +++ b/esphome/components/waveshare_epaper/waveshare_epaper.h @@ -45,9 +45,9 @@ class WaveshareEPaper : public PollingComponent, void reset_() { if (this->reset_pin_ != nullptr) { this->reset_pin_->digital_write(false); - delay(200); + delay(200); // NOLINT this->reset_pin_->digital_write(true); - delay(200); + delay(200); // NOLINT } } @@ -144,7 +144,7 @@ class WaveshareEPaper4P2In : public WaveshareEPaper { // COMMAND PANEL SETTING this->command(0x00); - delay(100); + delay(100); // NOLINT // COMMAND POWER SETTING this->command(0x01); @@ -153,7 +153,7 @@ class WaveshareEPaper4P2In : public WaveshareEPaper { this->data(0x00); this->data(0x00); this->data(0x00); - delay(100); + delay(100); // NOLINT // COMMAND POWER OFF this->command(0x02); diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 0608f222f7..cb664d3cc3 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -481,7 +481,7 @@ void WiFiComponent::retry_connect() { // If retry failed for more than 5 times, let's restart STA ESP_LOGW(TAG, "Restarting WiFi adapter..."); this->wifi_mode_(false, {}); - delay(100); + delay(100); // NOLINT this->num_retried_ = 0; } else { this->num_retried_++; diff --git a/esphome/components/yashima/climate.py b/esphome/components/yashima/climate.py index 5d33670fb5..4c4b98d9e7 100644 --- a/esphome/components/yashima/climate.py +++ b/esphome/components/yashima/climate.py @@ -1,17 +1,14 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import climate, remote_transmitter, sensor -from esphome.const import CONF_ID, CONF_SENSOR +from esphome.components.remote_base import CONF_TRANSMITTER_ID +from esphome.const import CONF_ID, CONF_SENSOR, CONF_SUPPORTS_COOL, CONF_SUPPORTS_HEAT AUTO_LOAD = ['sensor'] yashima_ns = cg.esphome_ns.namespace('yashima') YashimaClimate = yashima_ns.class_('YashimaClimate', climate.Climate, cg.Component) -CONF_TRANSMITTER_ID = 'transmitter_id' -CONF_SUPPORTS_HEAT = 'supports_heat' -CONF_SUPPORTS_COOL = 'supports_cool' - CONFIG_SCHEMA = cv.All(climate.CLIMATE_SCHEMA.extend({ cv.GenerateID(): cv.declare_id(YashimaClimate), cv.GenerateID(CONF_TRANSMITTER_ID): cv.use_id(remote_transmitter.RemoteTransmitterComponent), diff --git a/esphome/const.py b/esphome/const.py index 84bef47e47..a7e0c2df93 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -63,8 +63,8 @@ CONF_BROKER = 'broker' CONF_BSSID = 'bssid' CONF_BUFFER_SIZE = 'buffer_size' CONF_BUILD_PATH = 'build_path' -CONF_BUSY_PIN = 'busy_pin' CONF_BUS_VOLTAGE = 'bus_voltage' +CONF_BUSY_PIN = 'busy_pin' CONF_CALIBRATE_LINEAR = 'calibrate_linear' CONF_CALIBRATION = 'calibration' CONF_CAPACITANCE = 'capacitance' @@ -84,23 +84,23 @@ CONF_CO2 = 'co2' CONF_CODE = 'code' CONF_COLD_WHITE = 'cold_white' CONF_COLD_WHITE_COLOR_TEMPERATURE = 'cold_white_color_temperature' -CONF_COLORS = 'colors' CONF_COLOR_CORRECT = 'color_correct' CONF_COLOR_TEMPERATURE = 'color_temperature' +CONF_COLORS = 'colors' CONF_COMMAND = 'command' CONF_COMMAND_TOPIC = 'command_topic' CONF_COMMENT = 'comment' CONF_COMMIT = 'commit' -CONF_COMPONENTS = 'components' CONF_COMPONENT_ID = 'component_id' +CONF_COMPONENTS = 'components' CONF_CONDITION = 'condition' CONF_CONDITION_ID = 'condition_id' CONF_CONDUCTIVITY = 'conductivity' CONF_COOL_ACTION = 'cool_action' CONF_COUNT_MODE = 'count_mode' CONF_CRON = 'cron' -CONF_CSS_URL = 'css_url' CONF_CS_PIN = 'cs_pin' +CONF_CSS_URL = 'css_url' CONF_CURRENT = 'current' CONF_CURRENT_OPERATION = 'current_operation' CONF_CURRENT_RESISTOR = 'current_resistor' @@ -122,12 +122,12 @@ CONF_DELTA = 'delta' CONF_DEVICE = 'device' CONF_DEVICE_CLASS = 'device_class' CONF_DIMENSIONS = 'dimensions' -CONF_DIRECTION = 'direction' CONF_DIR_PIN = 'dir_pin' +CONF_DIRECTION = 'direction' CONF_DISCOVERY = 'discovery' -CONF_DISTANCE = 'distance' CONF_DISCOVERY_PREFIX = 'discovery_prefix' CONF_DISCOVERY_RETAIN = 'discovery_retain' +CONF_DISTANCE = 'distance' CONF_DIV_RATIO = 'div_ratio' CONF_DNS1 = 'dns1' CONF_DNS2 = 'dns2' @@ -152,8 +152,8 @@ CONF_FAMILY = 'family' CONF_FAST_CONNECT = 'fast_connect' CONF_FILE = 'file' CONF_FILTER = 'filter' -CONF_FILTERS = 'filters' CONF_FILTER_OUT = 'filter_out' +CONF_FILTERS = 'filters' CONF_FLASH_LENGTH = 'flash_length' CONF_FOR = 'for' CONF_FORCE_UPDATE = 'force_update' @@ -172,8 +172,8 @@ CONF_GREEN = 'green' CONF_GROUP = 'group' CONF_HARDWARE_UART = 'hardware_uart' CONF_HEARTBEAT = 'heartbeat' -CONF_HEATER = 'heater' CONF_HEAT_ACTION = 'heat_action' +CONF_HEATER = 'heater' CONF_HIDDEN = 'hidden' CONF_HIGH = 'high' CONF_HIGH_VOLTAGE_REFERENCE = 'high_voltage_reference' @@ -207,8 +207,8 @@ CONF_INVERTED = 'inverted' CONF_IP_ADDRESS = 'ip_address' CONF_JS_URL = 'js_url' CONF_JVC = 'jvc' -CONF_KEEPALIVE = 'keepalive' CONF_KEEP_ON_TIME = 'keep_on_time' +CONF_KEEPALIVE = 'keepalive' CONF_LAMBDA = 'lambda' CONF_LEVEL = 'level' CONF_LG = 'lg' @@ -218,9 +218,9 @@ CONF_LIGHTNING_ENERGY = 'lightning_energy' CONF_LIGHTNING_THRESHOLD = 'lightning_threshold' CONF_LOADED_INTEGRATIONS = 'loaded_integrations' CONF_LOCAL = 'local' +CONF_LOG_TOPIC = 'log_topic' CONF_LOGGER = 'logger' CONF_LOGS = 'logs' -CONF_LOG_TOPIC = 'log_topic' CONF_LOW = 'low' CONF_LOW_VOLTAGE_REFERENCE = 'low_voltage_reference' CONF_MAC_ADDRESS = 'mac_address' @@ -240,13 +240,13 @@ CONF_MAX_VOLTAGE = 'max_voltage' CONF_MEASUREMENT_DURATION = 'measurement_duration' CONF_MEDIUM = 'medium' CONF_METHOD = 'method' -CONF_MINUTE = 'minute' -CONF_MINUTES = 'minutes' CONF_MIN_LENGTH = 'min_length' CONF_MIN_LEVEL = 'min_level' CONF_MIN_POWER = 'min_power' CONF_MIN_TEMPERATURE = 'min_temperature' CONF_MIN_VALUE = 'min_value' +CONF_MINUTE = 'minute' +CONF_MINUTES = 'minutes' CONF_MISO_PIN = 'miso_pin' CONF_MODE = 'mode' CONF_MODEL = 'model' @@ -262,14 +262,13 @@ CONF_NBITS = 'nbits' CONF_NEC = 'nec' CONF_NETWORKS = 'networks' CONF_NOISE_LEVEL = 'noise_level' -CONF_NUMBER = 'number' CONF_NUM_ATTEMPTS = 'num_attempts' CONF_NUM_CHANNELS = 'num_channels' CONF_NUM_CHIPS = 'num_chips' CONF_NUM_LEDS = 'num_leds' +CONF_NUMBER = 'number' CONF_OFFSET = 'offset' CONF_ON = 'on' -CONF_ONE = 'one' CONF_ON_BOOT = 'on_boot' CONF_ON_CLICK = 'on_click' CONF_ON_DOUBLE_CLICK = 'on_double_click' @@ -288,6 +287,7 @@ CONF_ON_TURN_OFF = 'on_turn_off' CONF_ON_TURN_ON = 'on_turn_on' CONF_ON_VALUE = 'on_value' CONF_ON_VALUE_RANGE = 'on_value_range' +CONF_ONE = 'one' CONF_OPEN_ACTION = 'open_action' CONF_OPEN_DURATION = 'open_duration' CONF_OPEN_ENDSTOP = 'open_endstop' @@ -299,11 +299,11 @@ CONF_OSCILLATION_OUTPUT = 'oscillation_output' CONF_OSCILLATION_STATE_TOPIC = 'oscillation_state_topic' CONF_OTA = 'ota' CONF_OUTPUT = 'output' -CONF_OUTPUTS = 'outputs' CONF_OUTPUT_ID = 'output_id' +CONF_OUTPUTS = 'outputs' CONF_OVERSAMPLING = 'oversampling' -CONF_PAGES = 'pages' CONF_PAGE_ID = 'page_id' +CONF_PAGES = 'pages' CONF_PANASONIC = 'panasonic' CONF_PASSWORD = 'password' CONF_PAYLOAD = 'payload' @@ -311,15 +311,15 @@ CONF_PAYLOAD_AVAILABLE = 'payload_available' CONF_PAYLOAD_NOT_AVAILABLE = 'payload_not_available' CONF_PHASE_BALANCER = 'phase_balancer' CONF_PIN = 'pin' -CONF_PINS = 'pins' CONF_PIN_A = 'pin_a' CONF_PIN_B = 'pin_b' CONF_PIN_C = 'pin_c' CONF_PIN_D = 'pin_d' +CONF_PINS = 'pins' CONF_PLATFORM = 'platform' CONF_PLATFORMIO_OPTIONS = 'platformio_options' -CONF_PM_10_0 = 'pm_10_0' CONF_PM_1_0 = 'pm_1_0' +CONF_PM_10_0 = 'pm_10_0' CONF_PM_2_5 = 'pm_2_5' CONF_PORT = 'port' CONF_POSITION = 'position' @@ -353,8 +353,8 @@ CONF_RESTORE_MODE = 'restore_mode' CONF_RESTORE_STATE = 'restore_state' CONF_RESTORE_VALUE = 'restore_value' CONF_RETAIN = 'retain' -CONF_RGBW = 'rgbw' CONF_RGB_ORDER = 'rgb_order' +CONF_RGBW = 'rgbw' CONF_RISING_EDGE = 'rising_edge' CONF_ROTATION = 'rotation' CONF_RS_PIN = 'rs_pin' @@ -377,14 +377,14 @@ CONF_SEL_PIN = 'sel_pin' CONF_SEND_EVERY = 'send_every' CONF_SEND_FIRST_AT = 'send_first_at' CONF_SENSOR = 'sensor' -CONF_SENSORS = 'sensors' CONF_SENSOR_ID = 'sensor_id' +CONF_SENSORS = 'sensors' +CONF_SEQUENCE = 'sequence' CONF_SERVERS = 'servers' CONF_SERVICE = 'service' CONF_SERVICES = 'services' CONF_SETUP_MODE = 'setup_mode' CONF_SETUP_PRIORITY = 'setup_priority' -CONF_SEQUENCE = 'sequence' CONF_SHUNT_RESISTANCE = 'shunt_resistance' CONF_SHUNT_VOLTAGE = 'shunt_voltage' CONF_SHUTDOWN_MESSAGE = 'shutdown_message' @@ -408,6 +408,8 @@ CONF_STEP_PIN = 'step_pin' CONF_STOP = 'stop' CONF_STOP_ACTION = 'stop_action' CONF_SUBNET = 'subnet' +CONF_SUPPORTS_COOL = 'supports_cool' +CONF_SUPPORTS_HEAT = 'supports_heat' CONF_SWITCHES = 'switches' CONF_SYNC = 'sync' CONF_TAG = 'tag' @@ -425,10 +427,10 @@ CONF_TILT = 'tilt' CONF_TILT_ACTION = 'tilt_action' CONF_TILT_LAMBDA = 'tilt_lambda' CONF_TIME = 'time' +CONF_TIME_ID = 'time_id' CONF_TIMEOUT = 'timeout' CONF_TIMES = 'times' CONF_TIMEZONE = 'timezone' -CONF_TIME_ID = 'time_id' CONF_TIMING = 'timing' CONF_TO = 'to' CONF_TOLERANCE = 'tolerance' @@ -449,8 +451,8 @@ CONF_UNIQUE = 'unique' CONF_UNIT_OF_MEASUREMENT = 'unit_of_measurement' CONF_UPDATE_INTERVAL = 'update_interval' CONF_UPDATE_ON_BOOT = 'update_on_boot' -CONF_USERNAME = 'username' CONF_USE_ADDRESS = 'use_address' +CONF_USERNAME = 'username' CONF_UUID = 'uuid' CONF_VALUE = 'value' CONF_VARIABLES = 'variables' @@ -470,8 +472,8 @@ CONF_WHITE = 'white' CONF_WIDTH = 'width' CONF_WIFI = 'wifi' CONF_WILL_MESSAGE = 'will_message' -CONF_WIND_SPEED = 'wind_speed' CONF_WIND_DIRECTION_DEGREES = 'wind_direction_degrees' +CONF_WIND_SPEED = 'wind_speed' CONF_WINDOW_SIZE = 'window_size' CONF_ZERO = 'zero' @@ -479,8 +481,8 @@ ICON_ARROW_EXPAND_VERTICAL = 'mdi:arrow-expand-vertical' ICON_BATTERY = 'mdi:battery' ICON_BRIEFCASE_DOWNLOAD = 'mdi:briefcase-download' ICON_BRIGHTNESS_5 = 'mdi:brightness-5' -ICON_CHEMICAL_WEAPON = 'mdi:chemical-weapon' ICON_CHECK_CIRCLE_OUTLINE = 'mdi:check-circle-outline' +ICON_CHEMICAL_WEAPON = 'mdi:chemical-weapon' ICON_CURRENT_AC = 'mdi:current-ac' ICON_EMPTY = '' ICON_FLASH = 'mdi:flash' @@ -499,26 +501,26 @@ ICON_RESTART = 'mdi:restart' ICON_ROTATE_RIGHT = 'mdi:rotate-right' ICON_SCALE = 'mdi:scale' ICON_SCREEN_ROTATION = 'mdi:screen-rotation' +ICON_SIGN_DIRECTION = 'mdi:sign-direction' ICON_SIGNAL = 'mdi: signal-distance-variant' ICON_SIGNAL_DISTANCE_VARIANT = 'mdi:signal' -ICON_SIGN_DIRECTION = 'mdi:sign-direction' -ICON_WEATHER_SUNSET = 'mdi:weather-sunset' -ICON_WEATHER_SUNSET_DOWN = 'mdi:weather-sunset-down' -ICON_WEATHER_SUNSET_UP = 'mdi:weather-sunset-up' ICON_THERMOMETER = 'mdi:thermometer' ICON_TIMER = 'mdi:timer' ICON_WATER_PERCENT = 'mdi:water-percent' +ICON_WEATHER_SUNSET = 'mdi:weather-sunset' +ICON_WEATHER_SUNSET_DOWN = 'mdi:weather-sunset-down' +ICON_WEATHER_SUNSET_UP = 'mdi:weather-sunset-up' ICON_WEATHER_WINDY = 'mdi:weather-windy' ICON_WIFI = 'mdi:wifi' UNIT_AMPERE = 'A' UNIT_CELSIUS = u'°C' UNIT_DECIBEL = 'dB' -UNIT_DEGREES = u'°' UNIT_DEGREE_PER_SECOND = u'°/s' +UNIT_DEGREES = u'°' UNIT_EMPTY = '' -UNIT_HZ = 'hz' UNIT_HECTOPASCAL = 'hPa' +UNIT_HZ = 'hz' UNIT_KELVIN = 'K' UNIT_KILOMETER = 'km' UNIT_KILOMETER_PER_HOUR = 'km/h' @@ -529,8 +531,8 @@ UNIT_MICROGRAMS_PER_CUBIC_METER = u'µg/m³' UNIT_MICROSIEMENS_PER_CENTIMETER = u'µS/cm' UNIT_MICROTESLA = u'µT' UNIT_OHM = u'Ω' -UNIT_PARTS_PER_MILLION = 'ppm' UNIT_PARTS_PER_BILLION = 'ppb' +UNIT_PARTS_PER_MILLION = 'ppm' UNIT_PERCENT = '%' UNIT_PULSES_PER_MINUTE = 'pulses/min' UNIT_SECOND = 's' diff --git a/script/ci-custom.py b/script/ci-custom.py index fff24df0dc..5a98bdd20d 100755 --- a/script/ci-custom.py +++ b/script/ci-custom.py @@ -7,6 +7,7 @@ import fnmatch import os.path import subprocess import sys +import re def find_all(a_str, sub): @@ -39,6 +40,7 @@ ignore_types = ('.ico', '.woff', '.woff2', '') LINT_FILE_CHECKS = [] LINT_CONTENT_CHECKS = [] +LINT_POST_CHECKS = [] def run_check(lint_obj, fname, *args): @@ -84,6 +86,31 @@ def lint_content_check(**kwargs): return decorator +def lint_post_check(func): + _add_check(LINT_POST_CHECKS, func) + return func + + +def lint_re_check(regex, **kwargs): + prog = re.compile(regex, re.MULTILINE) + decor = lint_content_check(**kwargs) + + def decorator(func): + def new_func(fname, content): + errors = [] + for match in prog.finditer(content): + if 'NOLINT' in match.group(0): + continue + lineno = content.count("\n", 0, match.start()) + 1 + err = func(fname, match) + if err is None: + continue + errors.append("{} See line {}.".format(err, lineno)) + return errors + return decor(new_func) + return decorator + + def lint_content_find_check(find, **kwargs): decor = lint_content_check(**kwargs) @@ -92,9 +119,12 @@ def lint_content_find_check(find, **kwargs): find_ = find if callable(find): find_ = find(fname, content) + errors = [] for line, col in find_all(content, find_): err = func(fname) - return "{err} See line {line}:{col}.".format(err=err, line=line+1, col=col+1) + errors.append("{err} See line {line}:{col}." + "".format(err=err, line=line+1, col=col+1)) + return errors return decor(new_func) return decorator @@ -143,6 +173,98 @@ def lint_end_newline(fname, content): return None +CPP_RE_EOL = r'\s*?(?://.*?)?$' + + +def highlight(s): + return '\033[36m{}\033[0m'.format(s) + + +@lint_re_check(r'^#define\s+([a-zA-Z0-9_]+)\s+([0-9bx]+)' + CPP_RE_EOL, + include=cpp_include, exclude=['esphome/core/log.h']) +def lint_no_defines(fname, match): + s = highlight('static const uint8_t {} = {};'.format(match.group(1), match.group(2))) + return ("#define macros for integer constants are not allowed, please use " + "{} style instead (replace uint8_t with the appropriate " + "datatype). See also Google style guide.".format(s)) + + +@lint_re_check(r'^\s*delay\((\d+)\);' + CPP_RE_EOL, include=cpp_include) +def lint_no_long_delays(fname, match): + duration_ms = int(match.group(1)) + if duration_ms < 50: + return None + return ( + "{} - long calls to delay() are not allowed in ESPHome because everything executes " + "in one thread. Calling delay() will block the main thread and slow down ESPHome.\n" + "If there's no way to work around the delay() and it doesn't execute often, please add " + "a '// NOLINT' comment to the line." + "".format(highlight(match.group(0).strip())) + ) + + +@lint_content_check(include=['esphome/const.py']) +def lint_const_ordered(fname, content): + lines = content.splitlines() + errors = [] + for start in ['CONF_', 'ICON_', 'UNIT_']: + matching = [(i+1, line) for i, line in enumerate(lines) if line.startswith(start)] + ordered = list(sorted(matching, key=lambda x: x[1].replace('_', ' '))) + ordered = [(mi, ol) for (mi, _), (_, ol) in zip(matching, ordered)] + for (mi, ml), (oi, ol) in zip(matching, ordered): + if ml == ol: + continue + target = next(i for i, l in ordered if l == ml) + target_text = next(l for i, l in matching if target == i) + errors.append("Constant {} is not ordered, please make sure all constants are ordered. " + "See line {} (should go to line {}, {})" + "".format(highlight(ml), mi, target, target_text)) + return errors + + +@lint_re_check(r'^\s*CONF_([A-Z_0-9a-z]+)\s+=\s+[\'"](.*?)[\'"]\s*?$', include=['*.py']) +def lint_conf_matches(fname, match): + const = match.group(1) + value = match.group(2) + const_norm = const.lower() + value_norm = value.replace('.', '_') + if const_norm == value_norm: + return None + return ("Constant {} does not match value {}! Please make sure the constant's name matches its " + "value!" + "".format(highlight('CONF_' + const), highlight(value))) + + +CONF_RE = r'^(CONF_[a-zA-Z0-9_]+)\s*=\s*[\'"].*?[\'"]\s*?$' +with codecs.open('esphome/const.py', 'r', encoding='utf-8') as f_handle: + constants_content = f_handle.read() +CONSTANTS = [m.group(1) for m in re.finditer(CONF_RE, constants_content, re.MULTILINE)] + +CONSTANTS_USES = collections.defaultdict(list) + + +@lint_re_check(CONF_RE, include=['*.py'], exclude=['esphome/const.py']) +def lint_conf_from_const_py(fname, match): + name = match.group(1) + if name not in CONSTANTS: + CONSTANTS_USES[name].append(fname) + return None + return ("Constant {} has already been defined in const.py - please import the constant from " + "const.py directly.".format(highlight(name))) + + +@lint_post_check +def lint_constants_usage(): + errors = [] + for constant, uses in CONSTANTS_USES.items(): + if len(uses) < 4: + continue + errors.append("Constant {} is defined in {} files. Please move all definitions of the " + "constant to const.py (Uses: {})" + "".format(highlight(constant), len(uses), ', '.join(uses))) + return errors + + def relative_cpp_search_text(fname, content): parts = fname.split('/') integration = parts[2] @@ -241,6 +363,8 @@ for fname in files: continue run_checks(LINT_CONTENT_CHECKS, fname, fname, content) +run_checks(LINT_POST_CHECKS, 'POST') + for f, errs in sorted(errors.items()): print("\033[0;32m************* File \033[1;32m{}\033[0m".format(f)) for err in errs: