esphome 2025.9.2__py3-none-any.whl → 2025.10.0b1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (344) hide show
  1. esphome/__main__.py +87 -31
  2. esphome/address_cache.py +142 -0
  3. esphome/automation.py +130 -32
  4. esphome/build_gen/platformio.py +1 -3
  5. esphome/codegen.py +1 -0
  6. esphome/components/animation/animation.cpp +2 -2
  7. esphome/components/api/__init__.py +167 -3
  8. esphome/components/api/api_connection.cpp +84 -41
  9. esphome/components/api/api_connection.h +22 -16
  10. esphome/components/api/api_frame_helper.cpp +33 -19
  11. esphome/components/api/api_frame_helper.h +19 -4
  12. esphome/components/api/api_frame_helper_noise.cpp +41 -53
  13. esphome/components/api/api_frame_helper_noise.h +1 -1
  14. esphome/components/api/api_frame_helper_plaintext.cpp +22 -31
  15. esphome/components/api/api_frame_helper_plaintext.h +1 -1
  16. esphome/components/api/api_pb2.cpp +189 -15
  17. esphome/components/api/api_pb2.h +132 -20
  18. esphome/components/api/api_pb2_dump.cpp +97 -9
  19. esphome/components/api/api_pb2_service.cpp +118 -160
  20. esphome/components/api/api_pb2_service.h +31 -3
  21. esphome/components/api/api_server.cpp +78 -11
  22. esphome/components/api/api_server.h +32 -4
  23. esphome/components/api/custom_api_device.h +8 -8
  24. esphome/components/api/homeassistant_service.h +123 -6
  25. esphome/components/api/proto.h +6 -2
  26. esphome/components/api/user_services.h +2 -2
  27. esphome/components/as7341/sensor.py +1 -1
  28. esphome/components/audio/__init__.py +1 -1
  29. esphome/components/audio/audio.cpp +1 -1
  30. esphome/components/audio/audio_decoder.cpp +9 -9
  31. esphome/components/bl0906/bl0906.cpp +2 -2
  32. esphome/components/bl0942/bl0942.cpp +2 -2
  33. esphome/components/ble_client/__init__.py +1 -1
  34. esphome/components/bluetooth_proxy/__init__.py +4 -30
  35. esphome/components/bluetooth_proxy/bluetooth_connection.cpp +11 -4
  36. esphome/components/bluetooth_proxy/bluetooth_connection.h +2 -2
  37. esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +2 -2
  38. esphome/components/camera_encoder/__init__.py +2 -4
  39. esphome/components/camera_encoder/esp32_camera_jpeg_encoder.cpp +4 -2
  40. esphome/components/camera_encoder/esp32_camera_jpeg_encoder.h +3 -1
  41. esphome/components/canbus/canbus.cpp +7 -5
  42. esphome/components/canbus/canbus.h +4 -4
  43. esphome/components/captive_portal/__init__.py +18 -1
  44. esphome/components/captive_portal/captive_portal.cpp +40 -46
  45. esphome/components/captive_portal/captive_portal.h +20 -22
  46. esphome/components/captive_portal/dns_server_esp32_idf.cpp +205 -0
  47. esphome/components/captive_portal/dns_server_esp32_idf.h +27 -0
  48. esphome/components/ccs811/ccs811.cpp +1 -1
  49. esphome/components/climate/climate.cpp +10 -7
  50. esphome/components/cm1106/cm1106.cpp +1 -1
  51. esphome/components/copy/lock/copy_lock.cpp +1 -1
  52. esphome/components/cover/cover.cpp +1 -0
  53. esphome/components/daikin_arc/daikin_arc.cpp +19 -12
  54. esphome/components/deep_sleep/__init__.py +9 -2
  55. esphome/components/deep_sleep/deep_sleep_component.h +11 -9
  56. esphome/components/deep_sleep/deep_sleep_esp32.cpp +51 -27
  57. esphome/components/ektf2232/touchscreen/__init__.py +8 -5
  58. esphome/components/ektf2232/touchscreen/ektf2232.cpp +4 -4
  59. esphome/components/ektf2232/touchscreen/ektf2232.h +2 -2
  60. esphome/components/epaper_spi/__init__.py +1 -0
  61. esphome/components/epaper_spi/display.py +80 -0
  62. esphome/components/epaper_spi/epaper_spi.cpp +227 -0
  63. esphome/components/epaper_spi/epaper_spi.h +93 -0
  64. esphome/components/epaper_spi/epaper_spi_model_7p3in_spectra_e6.cpp +42 -0
  65. esphome/components/epaper_spi/epaper_spi_model_7p3in_spectra_e6.h +45 -0
  66. esphome/components/epaper_spi/epaper_spi_spectra_e6.cpp +135 -0
  67. esphome/components/epaper_spi/epaper_spi_spectra_e6.h +23 -0
  68. esphome/components/es7210/es7210.cpp +3 -3
  69. esphome/components/esp32/__init__.py +254 -339
  70. esphome/components/esp32/boards.py +81 -0
  71. esphome/components/esp32/preferences.cpp +23 -17
  72. esphome/components/esp32_ble/__init__.py +159 -44
  73. esphome/components/esp32_ble/ble.cpp +47 -3
  74. esphome/components/esp32_ble/ble.h +18 -0
  75. esphome/components/esp32_ble/ble_advertising.cpp +7 -3
  76. esphome/components/esp32_ble/ble_advertising.h +4 -0
  77. esphome/components/esp32_ble/ble_uuid.cpp +16 -42
  78. esphome/components/esp32_ble_beacon/__init__.py +3 -4
  79. esphome/components/esp32_ble_client/ble_client_base.cpp +14 -12
  80. esphome/components/esp32_ble_server/__init__.py +28 -14
  81. esphome/components/esp32_ble_server/ble_characteristic.cpp +67 -57
  82. esphome/components/esp32_ble_server/ble_characteristic.h +27 -16
  83. esphome/components/esp32_ble_server/ble_descriptor.cpp +4 -3
  84. esphome/components/esp32_ble_server/ble_descriptor.h +13 -9
  85. esphome/components/esp32_ble_server/ble_server.cpp +59 -24
  86. esphome/components/esp32_ble_server/ble_server.h +38 -20
  87. esphome/components/esp32_ble_server/ble_server_automations.cpp +49 -33
  88. esphome/components/esp32_ble_server/ble_server_automations.h +39 -24
  89. esphome/components/esp32_ble_tracker/__init__.py +25 -80
  90. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +2 -4
  91. esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +0 -3
  92. esphome/components/esp32_camera/__init__.py +1 -3
  93. esphome/components/esp32_can/esp32_can.cpp +22 -4
  94. esphome/components/esp32_can/esp32_can.h +3 -0
  95. esphome/components/esp32_hosted/__init__.py +2 -1
  96. esphome/components/esp32_improv/esp32_improv_component.cpp +102 -44
  97. esphome/components/esp32_improv/esp32_improv_component.h +6 -1
  98. esphome/components/esp32_rmt_led_strip/led_strip.cpp +1 -1
  99. esphome/components/esp8266/__init__.py +3 -3
  100. esphome/components/esphome/ota/__init__.py +21 -2
  101. esphome/components/esphome/ota/ota_esphome.cpp +455 -145
  102. esphome/components/esphome/ota/ota_esphome.h +49 -2
  103. esphome/components/ethernet/__init__.py +39 -22
  104. esphome/components/ethernet/ethernet_component.cpp +28 -5
  105. esphome/components/ethernet/ethernet_component.h +5 -1
  106. esphome/components/external_components/__init__.py +8 -6
  107. esphome/components/fingerprint_grow/fingerprint_grow.cpp +1 -1
  108. esphome/components/fingerprint_grow/fingerprint_grow.h +2 -1
  109. esphome/components/font/__init__.py +5 -5
  110. esphome/components/graph/graph.cpp +1 -1
  111. esphome/components/graphical_display_menu/graphical_display_menu.cpp +3 -2
  112. esphome/components/haier/hon_climate.cpp +2 -2
  113. esphome/components/haier/hon_climate.h +1 -1
  114. esphome/components/hdc1080/hdc1080.cpp +42 -34
  115. esphome/components/hdc1080/hdc1080.h +1 -3
  116. esphome/components/homeassistant/number/homeassistant_number.cpp +2 -2
  117. esphome/components/homeassistant/switch/homeassistant_switch.cpp +2 -2
  118. esphome/components/http_request/__init__.py +3 -3
  119. esphome/components/htu21d/htu21d.cpp +13 -18
  120. esphome/components/htu21d/htu21d.h +1 -1
  121. esphome/components/i2s_audio/__init__.py +1 -2
  122. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +1 -1
  123. esphome/components/ili9xxx/ili9xxx_display.cpp +2 -2
  124. esphome/components/improv_serial/improv_serial_component.cpp +12 -15
  125. esphome/components/improv_serial/improv_serial_component.h +6 -8
  126. esphome/components/json/json_util.cpp +35 -43
  127. esphome/components/json/json_util.h +57 -0
  128. esphome/components/kamstrup_kmp/kamstrup_kmp.cpp +2 -2
  129. esphome/components/key_collector/key_collector.h +4 -4
  130. esphome/components/libretiny/__init__.py +6 -6
  131. esphome/components/libretiny/preferences.cpp +23 -16
  132. esphome/components/light/light_call.cpp +98 -120
  133. esphome/components/light/light_call.h +17 -7
  134. esphome/components/lm75b/__init__.py +0 -0
  135. esphome/components/lm75b/lm75b.cpp +39 -0
  136. esphome/components/lm75b/lm75b.h +19 -0
  137. esphome/components/lm75b/sensor.py +34 -0
  138. esphome/components/lock/lock.h +12 -6
  139. esphome/components/logger/__init__.py +15 -27
  140. esphome/components/logger/logger.cpp +10 -20
  141. esphome/components/logger/logger.h +105 -62
  142. esphome/components/logger/logger_esp32.cpp +0 -48
  143. esphome/components/logger/logger_zephyr.cpp +2 -3
  144. esphome/components/logger/select/logger_level_select.cpp +6 -7
  145. esphome/components/logger/select/logger_level_select.h +7 -0
  146. esphome/components/ltr501/ltr501.cpp +7 -6
  147. esphome/components/ltr_als_ps/ltr_als_ps.cpp +7 -6
  148. esphome/components/matrix_keypad/matrix_keypad.h +4 -4
  149. esphome/components/max7219digit/max7219digit.cpp +1 -1
  150. esphome/components/mcp2515/mcp2515.cpp +31 -3
  151. esphome/components/mcp2515/mcp2515_defs.h +3 -1
  152. esphome/components/md5/md5.cpp +0 -26
  153. esphome/components/md5/md5.h +10 -20
  154. esphome/components/mdns/__init__.py +19 -6
  155. esphome/components/mdns/mdns_component.cpp +27 -59
  156. esphome/components/mdns/mdns_component.h +23 -10
  157. esphome/components/mdns/mdns_esp32.cpp +7 -7
  158. esphome/components/mdns/mdns_esp8266.cpp +6 -6
  159. esphome/components/mdns/mdns_libretiny.cpp +3 -3
  160. esphome/components/mdns/mdns_rp2040.cpp +3 -3
  161. esphome/components/mipi/__init__.py +1 -5
  162. esphome/components/mipi_spi/display.py +24 -8
  163. esphome/components/mipi_spi/mipi_spi.h +3 -3
  164. esphome/components/mixer/speaker/mixer_speaker.cpp +3 -3
  165. esphome/components/mmc5603/mmc5603.cpp +3 -3
  166. esphome/components/modbus/modbus.cpp +27 -13
  167. esphome/components/modbus/modbus.h +5 -3
  168. esphome/components/modbus/modbus_definitions.h +86 -0
  169. esphome/components/modbus_controller/__init__.py +29 -1
  170. esphome/components/modbus_controller/const.py +4 -0
  171. esphome/components/modbus_controller/modbus_controller.cpp +38 -13
  172. esphome/components/modbus_controller/modbus_controller.h +18 -29
  173. esphome/components/mpr121/mpr121.cpp +41 -42
  174. esphome/components/mpr121/mpr121.h +0 -1
  175. esphome/components/nau7802/nau7802.cpp +2 -2
  176. esphome/components/network/__init__.py +7 -3
  177. esphome/components/nextion/display.py +4 -4
  178. esphome/components/nextion/nextion.cpp +8 -8
  179. esphome/components/number/__init__.py +2 -0
  180. esphome/components/number/number_call.cpp +23 -12
  181. esphome/components/number/number_call.h +5 -0
  182. esphome/components/online_image/bmp_image.cpp +2 -1
  183. esphome/components/online_image/jpeg_image.cpp +4 -2
  184. esphome/components/openthread/openthread.cpp +6 -7
  185. esphome/components/openthread/openthread.h +0 -1
  186. esphome/components/ota/ota_backend.h +1 -0
  187. esphome/components/packages/__init__.py +10 -8
  188. esphome/components/packet_transport/packet_transport.cpp +2 -0
  189. esphome/components/pid/pid_controller.cpp +1 -1
  190. esphome/components/prometheus/prometheus_handler.cpp +239 -239
  191. esphome/components/psram/__init__.py +30 -28
  192. esphome/components/qmc5883l/qmc5883l.cpp +15 -0
  193. esphome/components/qmc5883l/qmc5883l.h +3 -0
  194. esphome/components/qmc5883l/sensor.py +31 -12
  195. esphome/components/remote_base/gobox_protocol.cpp +3 -3
  196. esphome/components/remote_receiver/__init__.py +14 -2
  197. esphome/components/remote_receiver/{remote_receiver_esp8266.cpp → remote_receiver.cpp} +2 -2
  198. esphome/components/remote_receiver/remote_receiver.h +4 -0
  199. esphome/components/remote_receiver/remote_receiver_esp32.cpp +18 -1
  200. esphome/components/remote_transmitter/__init__.py +2 -2
  201. esphome/components/remote_transmitter/remote_transmitter.cpp +103 -0
  202. esphome/components/rp2040/__init__.py +11 -11
  203. esphome/components/rtttl/rtttl.cpp +2 -2
  204. esphome/components/scd30/sensor.py +1 -1
  205. esphome/components/script/__init__.py +1 -1
  206. esphome/components/script/script.h +7 -7
  207. esphome/components/select/select.cpp +5 -4
  208. esphome/components/select/select_call.cpp +1 -1
  209. esphome/components/sensirion_common/i2c_sensirion.cpp +2 -1
  210. esphome/components/sensor/__init__.py +2 -0
  211. esphome/components/sha256/__init__.py +22 -0
  212. esphome/components/sha256/sha256.cpp +116 -0
  213. esphome/components/sha256/sha256.h +60 -0
  214. esphome/components/sim800l/sim800l.cpp +8 -4
  215. esphome/components/socket/lwip_raw_tcp_impl.cpp +34 -6
  216. esphome/components/sonoff_d1/sonoff_d1.cpp +1 -1
  217. esphome/components/spi/__init__.py +0 -3
  218. esphome/components/split_buffer/__init__.py +5 -0
  219. esphome/components/split_buffer/split_buffer.cpp +133 -0
  220. esphome/components/split_buffer/split_buffer.h +40 -0
  221. esphome/components/sps30/sps30.cpp +14 -10
  222. esphome/components/sps30/sps30.h +2 -0
  223. esphome/components/st7567_i2c/st7567_i2c.cpp +3 -1
  224. esphome/components/st7789v/st7789v.cpp +3 -2
  225. esphome/components/statsd/statsd.cpp +1 -1
  226. esphome/components/substitutions/__init__.py +3 -1
  227. esphome/components/substitutions/jinja.py +13 -3
  228. esphome/components/sx126x/__init__.py +16 -0
  229. esphome/components/sx126x/sx126x.cpp +15 -1
  230. esphome/components/sx126x/sx126x.h +9 -1
  231. esphome/components/sx126x/sx126x_reg.h +2 -0
  232. esphome/components/text_sensor/text_sensor.cpp +16 -0
  233. esphome/components/text_sensor/text_sensor.h +3 -10
  234. esphome/components/tormatic/tormatic_cover.cpp +1 -1
  235. esphome/components/tuya/select/tuya_select.cpp +1 -1
  236. esphome/components/tuya/tuya.cpp +29 -4
  237. esphome/components/uart/__init__.py +36 -26
  238. esphome/components/uart/uart.h +6 -0
  239. esphome/components/uart/uart_component.cpp +8 -0
  240. esphome/components/uart/uart_component.h +28 -0
  241. esphome/components/uart/uart_component_esp_idf.cpp +64 -10
  242. esphome/components/uart/uart_component_esp_idf.h +5 -2
  243. esphome/components/uponor_smatrix/climate/uponor_smatrix_climate.cpp +1 -1
  244. esphome/components/uponor_smatrix/sensor/uponor_smatrix_sensor.cpp +1 -1
  245. esphome/components/uponor_smatrix/uponor_smatrix.cpp +3 -3
  246. esphome/components/usb_host/__init__.py +2 -1
  247. esphome/components/usb_host/usb_host.h +82 -13
  248. esphome/components/usb_host/usb_host_client.cpp +180 -24
  249. esphome/components/usb_host/usb_host_component.cpp +1 -1
  250. esphome/components/usb_uart/__init__.py +0 -1
  251. esphome/components/usb_uart/ch34x.cpp +4 -4
  252. esphome/components/usb_uart/cp210x.cpp +3 -3
  253. esphome/components/usb_uart/usb_uart.cpp +88 -32
  254. esphome/components/usb_uart/usb_uart.h +30 -6
  255. esphome/components/valve/valve.cpp +1 -0
  256. esphome/components/veml7700/veml7700.cpp +7 -6
  257. esphome/components/version/version_text_sensor.cpp +2 -1
  258. esphome/components/voice_assistant/voice_assistant.cpp +3 -3
  259. esphome/components/waveshare_epaper/waveshare_epaper.cpp +4 -4
  260. esphome/components/web_server/list_entities.cpp +3 -4
  261. esphome/components/web_server/list_entities.h +8 -10
  262. esphome/components/web_server/ota/__init__.py +1 -1
  263. esphome/components/web_server/ota/ota_web_server.cpp +9 -3
  264. esphome/components/web_server/web_server.cpp +509 -404
  265. esphome/components/web_server/web_server.h +5 -6
  266. esphome/components/web_server/web_server_v1.cpp +21 -19
  267. esphome/components/web_server_base/__init__.py +5 -2
  268. esphome/components/web_server_base/web_server_base.h +27 -7
  269. esphome/components/web_server_idf/__init__.py +1 -1
  270. esphome/components/web_server_idf/multipart.cpp +2 -2
  271. esphome/components/web_server_idf/multipart.h +2 -2
  272. esphome/components/web_server_idf/utils.cpp +2 -2
  273. esphome/components/web_server_idf/utils.h +2 -2
  274. esphome/components/web_server_idf/web_server_idf.cpp +118 -26
  275. esphome/components/web_server_idf/web_server_idf.h +12 -10
  276. esphome/components/wifi/__init__.py +13 -11
  277. esphome/components/wifi/wifi_component.cpp +73 -56
  278. esphome/components/wifi/wifi_component.h +4 -4
  279. esphome/components/wifi/wifi_component_esp8266.cpp +1 -1
  280. esphome/components/wifi/wifi_component_esp_idf.cpp +24 -4
  281. esphome/components/wireguard/__init__.py +1 -1
  282. esphome/components/wts01/__init__.py +0 -0
  283. esphome/components/wts01/sensor.py +41 -0
  284. esphome/components/wts01/wts01.cpp +91 -0
  285. esphome/components/wts01/wts01.h +27 -0
  286. esphome/components/zephyr/__init__.py +5 -5
  287. esphome/components/zwave_proxy/__init__.py +43 -0
  288. esphome/components/zwave_proxy/zwave_proxy.cpp +346 -0
  289. esphome/components/zwave_proxy/zwave_proxy.h +93 -0
  290. esphome/config.py +79 -24
  291. esphome/config_validation.py +13 -15
  292. esphome/const.py +9 -2
  293. esphome/core/__init__.py +31 -22
  294. esphome/core/component.cpp +28 -18
  295. esphome/core/component_iterator.h +2 -1
  296. esphome/core/config.py +15 -15
  297. esphome/core/defines.h +19 -0
  298. esphome/core/hash_base.h +56 -0
  299. esphome/core/helpers.cpp +19 -3
  300. esphome/core/helpers.h +26 -0
  301. esphome/core/scheduler.cpp +5 -21
  302. esphome/core/scheduler.h +19 -8
  303. esphome/core/string_ref.h +1 -1
  304. esphome/core/time.cpp +5 -5
  305. esphome/cpp_generator.py +4 -29
  306. esphome/dashboard/const.py +21 -4
  307. esphome/dashboard/core.py +10 -8
  308. esphome/dashboard/dns.py +15 -0
  309. esphome/dashboard/entries.py +15 -21
  310. esphome/dashboard/models.py +76 -0
  311. esphome/dashboard/settings.py +7 -7
  312. esphome/dashboard/status/mdns.py +46 -2
  313. esphome/dashboard/web_server.py +367 -93
  314. esphome/espota2.py +111 -31
  315. esphome/external_files.py +6 -7
  316. esphome/git.py +8 -0
  317. esphome/helpers.py +124 -77
  318. esphome/loader.py +8 -9
  319. esphome/platformio_api.py +25 -18
  320. esphome/storage_json.py +26 -21
  321. esphome/types.py +30 -2
  322. esphome/util.py +32 -16
  323. esphome/vscode.py +8 -8
  324. esphome/wizard.py +10 -10
  325. esphome/writer.py +50 -15
  326. esphome/yaml_util.py +37 -31
  327. esphome/zeroconf.py +12 -3
  328. {esphome-2025.9.2.dist-info → esphome-2025.10.0b1.dist-info}/METADATA +11 -11
  329. {esphome-2025.9.2.dist-info → esphome-2025.10.0b1.dist-info}/RECORD +333 -313
  330. esphome/components/event_emitter/__init__.py +0 -5
  331. esphome/components/event_emitter/event_emitter.cpp +0 -14
  332. esphome/components/event_emitter/event_emitter.h +0 -63
  333. esphome/components/remote_receiver/remote_receiver_libretiny.cpp +0 -125
  334. esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp +0 -107
  335. esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp +0 -110
  336. esphome/components/uart/uart_component_esp32_arduino.cpp +0 -214
  337. esphome/components/uart/uart_component_esp32_arduino.h +0 -60
  338. esphome/components/wifi/wifi_component_esp32_arduino.cpp +0 -860
  339. esphome/core/string_ref.cpp +0 -12
  340. esphome/dashboard/util/file.py +0 -63
  341. {esphome-2025.9.2.dist-info → esphome-2025.10.0b1.dist-info}/WHEEL +0 -0
  342. {esphome-2025.9.2.dist-info → esphome-2025.10.0b1.dist-info}/entry_points.txt +0 -0
  343. {esphome-2025.9.2.dist-info → esphome-2025.10.0b1.dist-info}/licenses/LICENSE +0 -0
  344. {esphome-2025.9.2.dist-info → esphome-2025.10.0b1.dist-info}/top_level.txt +0 -0
esphome/yaml_util.py CHANGED
@@ -1,7 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from collections.abc import Callable
4
- import fnmatch
5
4
  import functools
6
5
  import inspect
7
6
  from io import BytesIO, TextIOBase, TextIOWrapper
@@ -9,6 +8,7 @@ from ipaddress import _BaseAddress, _BaseNetwork
9
8
  import logging
10
9
  import math
11
10
  import os
11
+ from pathlib import Path
12
12
  from typing import Any
13
13
  import uuid
14
14
 
@@ -69,7 +69,7 @@ class ESPHomeDataBase:
69
69
  self._content_offset = database.content_offset
70
70
 
71
71
 
72
- class ESPForceValue:
72
+ class ESPLiteralValue:
73
73
  pass
74
74
 
75
75
 
@@ -109,7 +109,9 @@ def _add_data_ref(fn):
109
109
  class ESPHomeLoaderMixin:
110
110
  """Loader class that keeps track of line numbers."""
111
111
 
112
- def __init__(self, name: str, yaml_loader: Callable[[str], dict[str, Any]]) -> None:
112
+ def __init__(
113
+ self, name: Path, yaml_loader: Callable[[Path], dict[str, Any]]
114
+ ) -> None:
113
115
  """Initialize the loader."""
114
116
  self.name = name
115
117
  self.yaml_loader = yaml_loader
@@ -254,12 +256,8 @@ class ESPHomeLoaderMixin:
254
256
  f"Environment variable '{node.value}' not defined", node.start_mark
255
257
  )
256
258
 
257
- @property
258
- def _directory(self) -> str:
259
- return os.path.dirname(self.name)
260
-
261
- def _rel_path(self, *args: str) -> str:
262
- return os.path.join(self._directory, *args)
259
+ def _rel_path(self, *args: str) -> Path:
260
+ return self.name.parent / Path(*args)
263
261
 
264
262
  @_add_data_ref
265
263
  def construct_secret(self, node: yaml.Node) -> str:
@@ -269,8 +267,8 @@ class ESPHomeLoaderMixin:
269
267
  if self.name == CORE.config_path:
270
268
  raise e
271
269
  try:
272
- main_config_dir = os.path.dirname(CORE.config_path)
273
- main_secret_yml = os.path.join(main_config_dir, SECRET_YAML)
270
+ main_config_dir = CORE.config_path.parent
271
+ main_secret_yml = main_config_dir / SECRET_YAML
274
272
  secrets = self.yaml_loader(main_secret_yml)
275
273
  except EsphomeError as er:
276
274
  raise EsphomeError(f"{e}\n{er}") from er
@@ -329,7 +327,7 @@ class ESPHomeLoaderMixin:
329
327
  files = filter_yaml_files(_find_files(self._rel_path(node.value), "*.yaml"))
330
328
  mapping = OrderedDict()
331
329
  for fname in files:
332
- filename = os.path.splitext(os.path.basename(fname))[0]
330
+ filename = fname.stem
333
331
  mapping[filename] = self.yaml_loader(fname)
334
332
  return mapping
335
333
 
@@ -350,9 +348,15 @@ class ESPHomeLoaderMixin:
350
348
  return Lambda(str(node.value))
351
349
 
352
350
  @_add_data_ref
353
- def construct_force(self, node: yaml.Node) -> ESPForceValue:
354
- obj = self.construct_scalar(node)
355
- return add_class_to_obj(obj, ESPForceValue)
351
+ def construct_literal(self, node: yaml.Node) -> ESPLiteralValue:
352
+ obj = None
353
+ if isinstance(node, yaml.ScalarNode):
354
+ obj = self.construct_scalar(node)
355
+ elif isinstance(node, yaml.SequenceNode):
356
+ obj = self.construct_sequence(node)
357
+ elif isinstance(node, yaml.MappingNode):
358
+ obj = self.construct_mapping(node)
359
+ return add_class_to_obj(obj, ESPLiteralValue)
356
360
 
357
361
  @_add_data_ref
358
362
  def construct_extend(self, node: yaml.Node) -> Extend:
@@ -369,8 +373,8 @@ class ESPHomeLoader(ESPHomeLoaderMixin, FastestAvailableSafeLoader):
369
373
  def __init__(
370
374
  self,
371
375
  stream: TextIOBase | BytesIO,
372
- name: str,
373
- yaml_loader: Callable[[str], dict[str, Any]],
376
+ name: Path,
377
+ yaml_loader: Callable[[Path], dict[str, Any]],
374
378
  ) -> None:
375
379
  FastestAvailableSafeLoader.__init__(self, stream)
376
380
  ESPHomeLoaderMixin.__init__(self, name, yaml_loader)
@@ -382,8 +386,8 @@ class ESPHomePurePythonLoader(ESPHomeLoaderMixin, PurePythonLoader):
382
386
  def __init__(
383
387
  self,
384
388
  stream: TextIOBase | BytesIO,
385
- name: str,
386
- yaml_loader: Callable[[str], dict[str, Any]],
389
+ name: Path,
390
+ yaml_loader: Callable[[Path], dict[str, Any]],
387
391
  ) -> None:
388
392
  PurePythonLoader.__init__(self, stream)
389
393
  ESPHomeLoaderMixin.__init__(self, name, yaml_loader)
@@ -409,29 +413,29 @@ for _loader in (ESPHomeLoader, ESPHomePurePythonLoader):
409
413
  "!include_dir_merge_named", _loader.construct_include_dir_merge_named
410
414
  )
411
415
  _loader.add_constructor("!lambda", _loader.construct_lambda)
412
- _loader.add_constructor("!force", _loader.construct_force)
416
+ _loader.add_constructor("!literal", _loader.construct_literal)
413
417
  _loader.add_constructor("!extend", _loader.construct_extend)
414
418
  _loader.add_constructor("!remove", _loader.construct_remove)
415
419
 
416
420
 
417
- def load_yaml(fname: str, clear_secrets: bool = True) -> Any:
421
+ def load_yaml(fname: Path, clear_secrets: bool = True) -> Any:
418
422
  if clear_secrets:
419
423
  _SECRET_VALUES.clear()
420
424
  _SECRET_CACHE.clear()
421
425
  return _load_yaml_internal(fname)
422
426
 
423
427
 
424
- def _load_yaml_internal(fname: str) -> Any:
428
+ def _load_yaml_internal(fname: Path) -> Any:
425
429
  """Load a YAML file."""
426
430
  try:
427
- with open(fname, encoding="utf-8") as f_handle:
431
+ with fname.open(encoding="utf-8") as f_handle:
428
432
  return parse_yaml(fname, f_handle)
429
433
  except (UnicodeDecodeError, OSError) as err:
430
434
  raise EsphomeError(f"Error reading file {fname}: {err}") from err
431
435
 
432
436
 
433
437
  def parse_yaml(
434
- file_name: str, file_handle: TextIOWrapper, yaml_loader=_load_yaml_internal
438
+ file_name: Path, file_handle: TextIOWrapper, yaml_loader=_load_yaml_internal
435
439
  ) -> Any:
436
440
  """Parse a YAML file."""
437
441
  try:
@@ -483,9 +487,9 @@ def substitute_vars(config, vars):
483
487
 
484
488
  def _load_yaml_internal_with_type(
485
489
  loader_type: type[ESPHomeLoader] | type[ESPHomePurePythonLoader],
486
- fname: str,
490
+ fname: Path,
487
491
  content: TextIOWrapper,
488
- yaml_loader: Any,
492
+ yaml_loader: Callable[[Path], dict[str, Any]],
489
493
  ) -> Any:
490
494
  """Load a YAML file."""
491
495
  loader = loader_type(content, fname, yaml_loader)
@@ -512,13 +516,14 @@ def _is_file_valid(name: str) -> bool:
512
516
  return not name.startswith(".")
513
517
 
514
518
 
515
- def _find_files(directory, pattern):
519
+ def _find_files(directory: Path, pattern):
516
520
  """Recursively load files in a directory."""
517
- for root, dirs, files in os.walk(directory, topdown=True):
521
+ for root, dirs, files in os.walk(directory):
518
522
  dirs[:] = [d for d in dirs if _is_file_valid(d)]
519
- for basename in files:
520
- if _is_file_valid(basename) and fnmatch.fnmatch(basename, pattern):
521
- filename = os.path.join(root, basename)
523
+ for f in files:
524
+ filename = Path(f)
525
+ if _is_file_valid(f) and filename.match(pattern):
526
+ filename = Path(root) / filename
522
527
  yield filename
523
528
 
524
529
 
@@ -627,3 +632,4 @@ ESPHomeDumper.add_multi_representer(TimePeriod, ESPHomeDumper.represent_stringif
627
632
  ESPHomeDumper.add_multi_representer(Lambda, ESPHomeDumper.represent_lambda)
628
633
  ESPHomeDumper.add_multi_representer(core.ID, ESPHomeDumper.represent_id)
629
634
  ESPHomeDumper.add_multi_representer(uuid.UUID, ESPHomeDumper.represent_stringify)
635
+ ESPHomeDumper.add_multi_representer(Path, ESPHomeDumper.represent_stringify)
esphome/zeroconf.py CHANGED
@@ -68,8 +68,11 @@ class DashboardBrowser(AsyncServiceBrowser):
68
68
 
69
69
 
70
70
  class DashboardImportDiscovery:
71
- def __init__(self) -> None:
71
+ def __init__(
72
+ self, on_update: Callable[[str, DiscoveredImport | None], None] | None = None
73
+ ) -> None:
72
74
  self.import_state: dict[str, DiscoveredImport] = {}
75
+ self.on_update = on_update
73
76
 
74
77
  def browser_callback(
75
78
  self,
@@ -85,7 +88,9 @@ class DashboardImportDiscovery:
85
88
  state_change,
86
89
  )
87
90
  if state_change == ServiceStateChange.Removed:
88
- self.import_state.pop(name, None)
91
+ removed = self.import_state.pop(name, None)
92
+ if removed and self.on_update:
93
+ self.on_update(name, None)
89
94
  return
90
95
 
91
96
  if state_change == ServiceStateChange.Updated and name not in self.import_state:
@@ -139,7 +144,7 @@ class DashboardImportDiscovery:
139
144
  if friendly_name is not None:
140
145
  friendly_name = friendly_name.decode()
141
146
 
142
- self.import_state[name] = DiscoveredImport(
147
+ discovered = DiscoveredImport(
143
148
  friendly_name=friendly_name,
144
149
  device_name=node_name,
145
150
  package_import_url=import_url,
@@ -147,6 +152,10 @@ class DashboardImportDiscovery:
147
152
  project_version=project_version,
148
153
  network=network,
149
154
  )
155
+ is_new = name not in self.import_state
156
+ self.import_state[name] = discovered
157
+ if is_new and self.on_update:
158
+ self.on_update(name, discovered)
150
159
 
151
160
  def update_device_mdns(self, node_name: str, version: str):
152
161
  storage_path = ext_storage_path(node_name + ".yaml")
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: esphome
3
- Version: 2025.9.2
3
+ Version: 2025.10.0b1
4
4
  Summary: ESPHome is a system to configure your microcontrollers by simple yet powerful configuration files and control them remotely through Home Automation systems.
5
5
  Author-email: The ESPHome Authors <esphome@openhomefoundation.org>
6
- License: MIT
6
+ License-Expression: MIT
7
7
  Project-URL: Documentation, https://esphome.io
8
8
  Project-URL: Source Code, https://github.com/esphome/esphome
9
9
  Project-URL: Bug Tracker, https://github.com/esphome/esphome/issues
@@ -16,7 +16,6 @@ Platform: any
16
16
  Classifier: Environment :: Console
17
17
  Classifier: Intended Audience :: Developers
18
18
  Classifier: Intended Audience :: End Users/Desktop
19
- Classifier: License :: OSI Approved :: MIT License
20
19
  Classifier: Programming Language :: C++
21
20
  Classifier: Programming Language :: Python :: 3
22
21
  Classifier: Topic :: Home Automation
@@ -25,7 +24,7 @@ Description-Content-Type: text/markdown
25
24
  License-File: LICENSE
26
25
  Requires-Dist: cryptography==45.0.1
27
26
  Requires-Dist: voluptuous==0.15.2
28
- Requires-Dist: PyYAML==6.0.2
27
+ Requires-Dist: PyYAML==6.0.3
29
28
  Requires-Dist: paho-mqtt==1.6.1
30
29
  Requires-Dist: colorama==0.4.6
31
30
  Requires-Dist: icmplib==3.0.4
@@ -34,13 +33,14 @@ Requires-Dist: tzlocal==5.3.1
34
33
  Requires-Dist: tzdata>=2021.1
35
34
  Requires-Dist: pyserial==3.5
36
35
  Requires-Dist: platformio==6.1.18
37
- Requires-Dist: esptool==5.0.2
36
+ Requires-Dist: esptool==5.1.0
38
37
  Requires-Dist: click==8.1.7
39
38
  Requires-Dist: esphome-dashboard==20250904.0
40
- Requires-Dist: aioesphomeapi==40.2.1
41
- Requires-Dist: zeroconf==0.147.2
39
+ Requires-Dist: aioesphomeapi==41.13.0
40
+ Requires-Dist: zeroconf==0.148.0
42
41
  Requires-Dist: puremagic==1.30
43
42
  Requires-Dist: ruamel.yaml==0.18.15
43
+ Requires-Dist: ruamel.yaml.clib==0.2.12
44
44
  Requires-Dist: esphome-glyphsets==0.2.0
45
45
  Requires-Dist: pillow==10.4.0
46
46
  Requires-Dist: cairosvg==2.8.2
@@ -54,15 +54,15 @@ Requires-Dist: clang-format==13.0.1; extra == "dev"
54
54
  Requires-Dist: clang-tidy==18.1.8; extra == "dev"
55
55
  Requires-Dist: yamllint==1.37.1; extra == "dev"
56
56
  Provides-Extra: test
57
- Requires-Dist: pylint==3.3.8; extra == "test"
57
+ Requires-Dist: pylint==3.3.9; extra == "test"
58
58
  Requires-Dist: flake8==7.3.0; extra == "test"
59
- Requires-Dist: ruff==0.12.12; extra == "test"
59
+ Requires-Dist: ruff==0.14.0; extra == "test"
60
60
  Requires-Dist: pyupgrade==3.20.0; extra == "test"
61
61
  Requires-Dist: pre-commit; extra == "test"
62
62
  Requires-Dist: pytest==8.4.2; extra == "test"
63
63
  Requires-Dist: pytest-cov==7.0.0; extra == "test"
64
- Requires-Dist: pytest-mock==3.15.0; extra == "test"
65
- Requires-Dist: pytest-asyncio==1.1.0; extra == "test"
64
+ Requires-Dist: pytest-mock==3.15.1; extra == "test"
65
+ Requires-Dist: pytest-asyncio==1.2.0; extra == "test"
66
66
  Requires-Dist: pytest-xdist==3.8.0; extra == "test"
67
67
  Requires-Dist: asyncmock==0.4.2; extra == "test"
68
68
  Requires-Dist: hypothesis==6.92.1; extra == "test"