appdaemon 4.5.1__tar.gz → 4.5.3__tar.gz

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 (356) hide show
  1. appdaemon-4.5.3/PKG-INFO +80 -0
  2. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/adapi.py +20 -11
  3. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/adbase.py +5 -3
  4. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/app_management.py +13 -4
  5. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/dependency.py +22 -7
  6. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/dependency_manager.py +9 -3
  7. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/entity.py +0 -2
  8. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/exceptions.py +6 -3
  9. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/http.py +13 -10
  10. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/config/plugin.py +0 -1
  11. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/internal/app_management.py +1 -1
  12. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/plugins/hass/hassapi.py +14 -7
  13. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/plugins/mqtt/mqttapi.py +6 -12
  14. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/version.py +1 -1
  15. appdaemon-4.5.3/appdaemon.egg-info/PKG-INFO +80 -0
  16. {appdaemon-4.5.1 → appdaemon-4.5.3}/pyproject.toml +1 -2
  17. appdaemon-4.5.1/PKG-INFO +0 -276
  18. appdaemon-4.5.1/appdaemon.egg-info/PKG-INFO +0 -276
  19. {appdaemon-4.5.1 → appdaemon-4.5.3}/LICENSE.md +0 -0
  20. {appdaemon-4.5.1 → appdaemon-4.5.3}/MANIFEST.in +0 -0
  21. {appdaemon-4.5.1 → appdaemon-4.5.3}/README.md +0 -0
  22. {appdaemon-4.5.1 → appdaemon-4.5.3}/README.rst +0 -0
  23. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/__init__.py +0 -0
  24. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/__main__.py +0 -0
  25. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/admin.py +0 -0
  26. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/admin_loop.py +0 -0
  27. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/appdaemon.py +0 -0
  28. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/aui/appdaemon.png +0 -0
  29. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/aui/css/app.css +0 -0
  30. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/aui/css/chunk-vendors.css +0 -0
  31. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/aui/favicon.ico +0 -0
  32. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/aui/index.html +0 -0
  33. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/aui/js/app.js +0 -0
  34. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/aui/js/app.js.map +0 -0
  35. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/aui/js/chunk-vendors.js +0 -0
  36. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/aui/js/chunk-vendors.js.map +0 -0
  37. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/all.css +0 -0
  38. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/climacons-font.css +0 -0
  39. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/default/dashboard.css +0 -0
  40. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/default/variables.yaml +0 -0
  41. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/fontawesome.min.css +0 -0
  42. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/fonts.css +0 -0
  43. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/glassic/dashboard.css +0 -0
  44. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/glassic/img/carbon1.jpg +0 -0
  45. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/glassic/img/carbon2.jpg +0 -0
  46. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/glassic/img/carbon3.jpg +0 -0
  47. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/glassic/img/carbon4.jpg +0 -0
  48. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/glassic/img/glassic_bg.jpg +0 -0
  49. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/glassic/variables.yaml +0 -0
  50. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/images/ui-icons_444444_256x240.png +0 -0
  51. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/images/ui-icons_555555_256x240.png +0 -0
  52. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/images/ui-icons_777620_256x240.png +0 -0
  53. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/images/ui-icons_777777_256x240.png +0 -0
  54. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/images/ui-icons_cc0000_256x240.png +0 -0
  55. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/images/ui-icons_ffffff_256x240.png +0 -0
  56. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/jquery-ui.css +0 -0
  57. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/jquery.gridster.css +0 -0
  58. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/main.css +0 -0
  59. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/materialdesignicons.min.css +0 -0
  60. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/non_dashboard.css +0 -0
  61. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/obsidian/dashboard.css +0 -0
  62. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/obsidian/img/obsidian_bg.jpg +0 -0
  63. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/obsidian/img/obsidian_w_bg.jpg +0 -0
  64. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/obsidian/img/obsidianbg.jpg +0 -0
  65. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/obsidian/img/widgetbg.jpg +0 -0
  66. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/obsidian/variables.yaml +0 -0
  67. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/rickshaw.min.css +0 -0
  68. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/simplyred/dashboard.css +0 -0
  69. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/simplyred/img/goldgradient.png +0 -0
  70. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/simplyred/img/goldtexture.jpg +0 -0
  71. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/simplyred/js/timer.js +0 -0
  72. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/simplyred/variables.yaml +0 -0
  73. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/v4-shims.min.css +0 -0
  74. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/zen/dashboard.css +0 -0
  75. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/zen/img/zen_bg.jpg +0 -0
  76. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/zen/img/zen_bg2.jpg +0 -0
  77. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/zen/img/zen_weatherbg.jpg +0 -0
  78. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/zen/variables.yaml +0 -0
  79. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/fonts/TickingTimebombBB.ttf +0 -0
  80. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/fonts/climacons-webfont.eot +0 -0
  81. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/fonts/climacons-webfont.svg +0 -0
  82. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/fonts/climacons-webfont.ttf +0 -0
  83. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/fonts/climacons-webfont.woff +0 -0
  84. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/fonts/digital-7-mono.eot +0 -0
  85. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/fonts/digital-7-mono.ttf +0 -0
  86. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/fonts/materialdesignicons-webfont.eot +0 -0
  87. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/fonts/materialdesignicons-webfont.ttf +0 -0
  88. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/fonts/materialdesignicons-webfont.woff +0 -0
  89. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/fonts/materialdesignicons-webfont.woff2 +0 -0
  90. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/fonts/repetition.ttf +0 -0
  91. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/images/Blank.gif +0 -0
  92. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/images/android-chrome-192x192.png +0 -0
  93. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/images/android-chrome-512x512.png +0 -0
  94. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/images/apple-touch-icon.png +0 -0
  95. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/images/browserconfig.xml +0 -0
  96. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/images/favicon-16x16.png +0 -0
  97. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/images/favicon-32x32.png +0 -0
  98. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/images/favicon.ico +0 -0
  99. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/images/manifest.json +0 -0
  100. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/images/mstile-144x144.png +0 -0
  101. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/images/mstile-150x150.png +0 -0
  102. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/images/mstile-310x150.png +0 -0
  103. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/images/mstile-310x310.png +0 -0
  104. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/images/mstile-70x70.png +0 -0
  105. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/javascript/admin.js +0 -0
  106. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/javascript/d3.layout.min.js +0 -0
  107. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/javascript/d3.min.js +0 -0
  108. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/javascript/dashboard.js +0 -0
  109. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/javascript/gauge.min.js +0 -0
  110. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/javascript/jquery-3.1.1.min.js +0 -0
  111. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/javascript/jquery-ui.js +0 -0
  112. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/javascript/jquery.gridster.js +0 -0
  113. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/javascript/justgage.js +0 -0
  114. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/javascript/knockout-3.4.1.js +0 -0
  115. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/javascript/list.min.js +0 -0
  116. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/javascript/plotly.min.js +0 -0
  117. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/javascript/raphael-2.1.4.min.js +0 -0
  118. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/javascript/reconnecting-websocket.min.js +0 -0
  119. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/javascript/rickshaw.min.js +0 -0
  120. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/javascript/socket.io.js +0 -0
  121. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/javascript/sockjs.min.js +0 -0
  122. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/javascript/stream.js +0 -0
  123. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/templates/admin.jinja2 +0 -0
  124. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/templates/body_include.jinja2 +0 -0
  125. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/templates/dashboard.jinja2 +0 -0
  126. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/templates/dashinit.jinja2 +0 -0
  127. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/templates/error.jinja2 +0 -0
  128. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/templates/head_include.jinja2 +0 -0
  129. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/templates/list.jinja2 +0 -0
  130. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/templates/logon.jinja2 +0 -0
  131. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/webfonts/fa-brands-400.eot +0 -0
  132. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/webfonts/fa-brands-400.svg +0 -0
  133. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/webfonts/fa-brands-400.ttf +0 -0
  134. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/webfonts/fa-brands-400.woff +0 -0
  135. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/webfonts/fa-brands-400.woff2 +0 -0
  136. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/webfonts/fa-regular-400.eot +0 -0
  137. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/webfonts/fa-regular-400.svg +0 -0
  138. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/webfonts/fa-regular-400.ttf +0 -0
  139. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/webfonts/fa-regular-400.woff +0 -0
  140. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/webfonts/fa-regular-400.woff2 +0 -0
  141. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/webfonts/fa-solid-900.eot +0 -0
  142. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/webfonts/fa-solid-900.svg +0 -0
  143. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/webfonts/fa-solid-900.ttf +0 -0
  144. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/webfonts/fa-solid-900.woff +0 -0
  145. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/webfonts/fa-solid-900.woff2 +0 -0
  146. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/callbacks.py +0 -0
  147. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/dashboard.py +0 -0
  148. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/events.py +0 -0
  149. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/futures.py +0 -0
  150. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/logging.py +0 -0
  151. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/__init__.py +0 -0
  152. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/config/__init__.py +0 -0
  153. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/config/api.py +0 -0
  154. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/config/app.py +0 -0
  155. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/config/appdaemon.py +0 -0
  156. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/config/common.py +0 -0
  157. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/config/dashboard.py +0 -0
  158. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/config/http.py +0 -0
  159. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/config/log.py +0 -0
  160. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/config/misc.py +0 -0
  161. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/config/sequence.py +0 -0
  162. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/config/yaml.py +0 -0
  163. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/internal/__init__.py +0 -0
  164. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/internal/file_check.py +0 -0
  165. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/internal/plugin.py +0 -0
  166. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/internal/state.py +0 -0
  167. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/internal/threading.py +0 -0
  168. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/notification/__init__.py +0 -0
  169. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/notification/android.py +0 -0
  170. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/notification/base.py +0 -0
  171. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/notification/iOS.py +0 -0
  172. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/plugin_management.py +0 -0
  173. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/plugins/__init__.py +0 -0
  174. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/plugins/dummy/dummyapi.py +0 -0
  175. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/plugins/dummy/dummyplugin.py +0 -0
  176. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/plugins/hass/__init__.py +0 -0
  177. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/plugins/hass/exceptions.py +0 -0
  178. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/plugins/hass/hassplugin.py +0 -0
  179. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/plugins/hass/models.py +0 -0
  180. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/plugins/hass/notifications.py +0 -0
  181. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/plugins/hass/utils.py +0 -0
  182. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/plugins/mqtt/__init__.py +0 -0
  183. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/plugins/mqtt/mqttplugin.py +0 -0
  184. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/pyversions.py +0 -0
  185. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/scheduler.py +0 -0
  186. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/sequences.py +0 -0
  187. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/services.py +0 -0
  188. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/state.py +0 -0
  189. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/stream/__init__.py +0 -0
  190. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/stream/adstream.py +0 -0
  191. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/stream/socketio_handler.py +0 -0
  192. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/stream/sockjs_handler.py +0 -0
  193. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/stream/ws_handler.py +0 -0
  194. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/thread_async.py +0 -0
  195. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/threads.py +0 -0
  196. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/utility_loop.py +0 -0
  197. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/utils.py +0 -0
  198. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/AdminLog.yaml +0 -0
  199. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/AdminSummary.yaml +0 -0
  200. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/AdminTable.yaml +0 -0
  201. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/alarm.yaml +0 -0
  202. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basealarm/basealarm.css +0 -0
  203. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basealarm/basealarm.html +0 -0
  204. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basealarm/basealarm.js +0 -0
  205. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basecamera/basecamera.css +0 -0
  206. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basecamera/basecamera.html +0 -0
  207. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basecamera/basecamera.js +0 -0
  208. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseclimate/baseclimate.css +0 -0
  209. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseclimate/baseclimate.html +0 -0
  210. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseclimate/baseclimate.js +0 -0
  211. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseclock/baseclock.css +0 -0
  212. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseclock/baseclock.html +0 -0
  213. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseclock/baseclock.js +0 -0
  214. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basedatetime/basedatetime.css +0 -0
  215. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basedatetime/basedatetime.html +0 -0
  216. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basedatetime/basedatetime.js +0 -0
  217. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basedisplay/basedisplay.css +0 -0
  218. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basedisplay/basedisplay.html +0 -0
  219. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basedisplay/basedisplay.js +0 -0
  220. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseentitypicture/baseentitypicture.css +0 -0
  221. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseentitypicture/baseentitypicture.html +0 -0
  222. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseentitypicture/baseentitypicture.js +0 -0
  223. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseerror/baseerror.css +0 -0
  224. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseerror/baseerror.html +0 -0
  225. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseerror/baseerror.js +0 -0
  226. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basefan/basefan.css +0 -0
  227. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basefan/basefan.html +0 -0
  228. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basefan/basefan.js +0 -0
  229. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basegauge/basegauge.css +0 -0
  230. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basegauge/basegauge.html +0 -0
  231. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basegauge/basegauge.js +0 -0
  232. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseheater/baseheater.css +0 -0
  233. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseheater/baseheater.html +0 -0
  234. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseheater/baseheater.js +0 -0
  235. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseicon/baseicon.css +0 -0
  236. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseicon/baseicon.html +0 -0
  237. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseicon/baseicon.js +0 -0
  238. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseiframe/baseiframe.css +0 -0
  239. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseiframe/baseiframe.html +0 -0
  240. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseiframe/baseiframe.js +0 -0
  241. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseinputnumber/baseinputnumber.css +0 -0
  242. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseinputnumber/baseinputnumber.html +0 -0
  243. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseinputnumber/baseinputnumber.js +0 -0
  244. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basejavascript/basejavascript.css +0 -0
  245. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basejavascript/basejavascript.html +0 -0
  246. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basejavascript/basejavascript.js +0 -0
  247. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baselight/baselight.css +0 -0
  248. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baselight/baselight.html +0 -0
  249. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baselight/baselight.js +0 -0
  250. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basemedia/basemedia.css +0 -0
  251. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basemedia/basemedia.html +0 -0
  252. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basemedia/basemedia.js +0 -0
  253. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseradial/baseradial.css +0 -0
  254. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseradial/baseradial.html +0 -0
  255. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseradial/baseradial.js +0 -0
  256. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baserss/baserss.css +0 -0
  257. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baserss/baserss.html +0 -0
  258. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baserss/baserss.js +0 -0
  259. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseselect/baseselect.css +0 -0
  260. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseselect/baseselect.html +0 -0
  261. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseselect/baseselect.js +0 -0
  262. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseslider/baseslider.css +0 -0
  263. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseslider/baseslider.html +0 -0
  264. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseslider/baseslider.js +0 -0
  265. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseswitch/baseswitch.css +0 -0
  266. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseswitch/baseswitch.html +0 -0
  267. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseswitch/baseswitch.js +0 -0
  268. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basetemperature/basetemperature.css +0 -0
  269. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basetemperature/basetemperature.html +0 -0
  270. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basetemperature/basetemperature.js +0 -0
  271. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basetext/basetext.css +0 -0
  272. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basetext/basetext.html +0 -0
  273. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basetext/basetext.js +0 -0
  274. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseweather/baseweather.css +0 -0
  275. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseweather/baseweather.html +0 -0
  276. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseweather/baseweather.js +0 -0
  277. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/binary_sensor.yaml +0 -0
  278. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/camera.yaml +0 -0
  279. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/climate.yaml +0 -0
  280. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/clock.yaml +0 -0
  281. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/cover.yaml +0 -0
  282. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/device_tracker.yaml +0 -0
  283. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/entitypicture.yaml +0 -0
  284. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/fan.yaml +0 -0
  285. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/gauge.yaml +0 -0
  286. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/group.yaml +0 -0
  287. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/heater.yaml +0 -0
  288. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/icon.yaml +0 -0
  289. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/iframe.yaml +0 -0
  290. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/input_boolean.yaml +0 -0
  291. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/input_datetime.yaml +0 -0
  292. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/input_number.yaml +0 -0
  293. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/input_select.yaml +0 -0
  294. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/input_slider.yaml +0 -0
  295. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/input_text.yaml +0 -0
  296. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/javascript.yaml +0 -0
  297. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/label.yaml +0 -0
  298. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/light.yaml +0 -0
  299. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/lock.yaml +0 -0
  300. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/london_underground.yaml +0 -0
  301. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/media_player.yaml +0 -0
  302. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/mode.yaml +0 -0
  303. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/navigate.yaml +0 -0
  304. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/person.yaml +0 -0
  305. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/pirateweather.yaml +0 -0
  306. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/radial.yaml +0 -0
  307. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/reload.yaml +0 -0
  308. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/rss.yaml +0 -0
  309. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/scene.yaml +0 -0
  310. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/script.yaml +0 -0
  311. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/sensor.yaml +0 -0
  312. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/sequence.yaml +0 -0
  313. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/switch.yaml +0 -0
  314. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/temperature.yaml +0 -0
  315. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/text_sensor.yaml +0 -0
  316. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/weather.yaml +0 -0
  317. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/weather_summary.yaml +0 -0
  318. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon.egg-info/SOURCES.txt +0 -0
  319. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon.egg-info/dependency_links.txt +0 -0
  320. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon.egg-info/entry_points.txt +0 -0
  321. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon.egg-info/requires.txt +0 -0
  322. {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon.egg-info/top_level.txt +0 -0
  323. {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/apps/hello.py +0 -0
  324. {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/ObjectTracker/general_app_functions.py +0 -0
  325. {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/ObjectTracker/objectcontrole.py +0 -0
  326. {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/alexa.py +0 -0
  327. {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/battery.py +0 -0
  328. {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/bysykkel.py +0 -0
  329. {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/commute.py +0 -0
  330. {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/dark_day.py +0 -0
  331. {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/door_notification.py +0 -0
  332. {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/eventCache.py +0 -0
  333. {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/eventMonitor.py +0 -0
  334. {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/globals.py +0 -0
  335. {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/grandfather.py +0 -0
  336. {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/hwcheck.py +0 -0
  337. {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/ical.py +0 -0
  338. {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/minimote.py +0 -0
  339. {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/modes.py +0 -0
  340. {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/momentary_switch.py +0 -0
  341. {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/motion_lights.py +0 -0
  342. {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/motion_notification.py +0 -0
  343. {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/occusim.py +0 -0
  344. {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/outside_lights.py +0 -0
  345. {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/presence.py +0 -0
  346. {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/ruter.py +0 -0
  347. {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/secure.py +0 -0
  348. {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/sensor_notification.py +0 -0
  349. {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/sensor_notify.py +0 -0
  350. {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/sequence.py +0 -0
  351. {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/smart_heat.py +0 -0
  352. {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/sound.py +0 -0
  353. {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/switch_reset.py +0 -0
  354. {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/yr.py +0 -0
  355. {appdaemon-4.5.1 → appdaemon-4.5.3}/setup.cfg +0 -0
  356. {appdaemon-4.5.1 → appdaemon-4.5.3}/tests/test_main.py +0 -0
@@ -0,0 +1,80 @@
1
+ Metadata-Version: 2.4
2
+ Name: appdaemon
3
+ Version: 4.5.3
4
+ Summary: Apps for the Home Assistant home automation package.
5
+ Author-email: Andrew I Cockburn <appdaemon@acockburn.com>
6
+ Project-URL: documentation, https://appdaemon.readthedocs.io
7
+ Project-URL: repository, https://github.com/AppDaemon
8
+ Project-URL: changelog, https://github.com/AppDaemon/appdaemon/blob/master/docs/HISTORY.rst
9
+ Keywords: appdaemon,home,automation
10
+ Classifier: Development Status :: 5 - Production/Stable
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Natural Language :: English
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Topic :: Home Automation
17
+ Requires-Python: <3.13,>=3.10
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE.md
20
+ Requires-Dist: importlib-metadata; python_version < "3.8"
21
+ Requires-Dist: aiohttp<3.12.0,>=3.9.0
22
+ Requires-Dist: aiohttp_jinja2<1.7.0,>=1.5.1
23
+ Requires-Dist: astral~=3.2
24
+ Requires-Dist: bcrypt<4.3.0,>=4.0.1
25
+ Requires-Dist: deepdiff==8.2.0
26
+ Requires-Dist: feedparser~=6.0.10
27
+ Requires-Dist: iso8601<2.2,>=1.1
28
+ Requires-Dist: paho-mqtt<2.2.0,>=1.6.1
29
+ Requires-Dist: pid~=3.0.4
30
+ Requires-Dist: python-dateutil<2.10.0,>=2.8.2
31
+ Requires-Dist: python-socketio<5.12,>=5.5
32
+ Requires-Dist: pytz<2025.2.0,>=2022.7.1
33
+ Requires-Dist: pyyaml~=6.0.1
34
+ Requires-Dist: requests<2.33.0,>=2.28.2
35
+ Requires-Dist: sockjs<0.14,>=0.11
36
+ Requires-Dist: uvloop==0.21.0; sys_platform != "win32"
37
+ Requires-Dist: tomli==2.2.1
38
+ Requires-Dist: tomli_w<1.3,>=1.0
39
+ Requires-Dist: pydantic~=2.10.6
40
+ Provides-Extra: dev
41
+ Requires-Dist: pip-tools<7.5.0,>=6.12.3; extra == "dev"
42
+ Requires-Dist: build<1.3,>=0.10; extra == "dev"
43
+ Requires-Dist: flake8~=7.1.1; extra == "dev"
44
+ Requires-Dist: black<25.2,>=23.1; extra == "dev"
45
+ Requires-Dist: pre-commit<3.9.0,>=3.1.1; python_version > "3.7" and extra == "dev"
46
+ Requires-Dist: pytest<8.4.0,>=7.2.1; extra == "dev"
47
+ Requires-Dist: ruff<0.7.0,>=0.0.261; extra == "dev"
48
+ Requires-Dist: codespell>=2.4.1; extra == "dev"
49
+ Provides-Extra: doc
50
+ Requires-Dist: sphinx-autobuild<2024.10.0,>=2021.3.14; extra == "doc"
51
+ Requires-Dist: sphinx-rtd-theme==3.0.2; extra == "doc"
52
+ Requires-Dist: pygments<2.20,>=2.14; extra == "doc"
53
+ Requires-Dist: myst-parser==4.0.0; extra == "doc"
54
+ Dynamic: license-file
55
+
56
+ # Description
57
+
58
+ AppDaemon is a loosely coupled, multi-threaded, sandboxed python
59
+ execution environment for writing automation apps for various types of Home Automation Software including [Home
60
+ Assistant](https://home-assistant.io/) and MQTT. It has a pluggable architecture allowing it to be integrated with
61
+ practically any event driven application.
62
+
63
+ It also provides a configurable dashboard (HADashboard)
64
+ suitable for wall mounted tablets.
65
+
66
+ ## Getting started
67
+
68
+ For full instructions on installation and usage check out the [AppDaemon Project Documentation](http://appdaemon.readthedocs.io).
69
+
70
+ ## Release Cycle Frequency
71
+
72
+ AppDaemon has reached a very stable point, works reliably and is fairly feature rich at this point
73
+ in its development. For that reason, releases have been slow in recent months. This does not mean that AppDaemon has been abandoned -
74
+ it is used every day by the core developers and has an active discord server [here](https://discord.gg/sgSr79jW5x) - please join us for tips
75
+ and tricks, AppDaemon discussions and general home automation.
76
+
77
+ ## Contributing
78
+
79
+ This is an active open-source project. We are always open to people who want to use the code or contribute to it. Thank you for being involved!
80
+ Have a look at the [official documentation](https://appdaemon.readthedocs.io/en/latest/DEV.html) for more information.
@@ -489,7 +489,8 @@ class ADAPI:
489
489
  # Threading
490
490
  #
491
491
 
492
- def set_app_pin(self, pin: bool) -> None:
492
+ @utils.sync_decorator
493
+ async def set_app_pin(self, pin: bool) -> None:
493
494
  """Sets an App to be pinned or unpinned.
494
495
 
495
496
  Args:
@@ -506,7 +507,8 @@ class ADAPI:
506
507
  """
507
508
  self.AD.app_management.set_app_pin(self.name, pin)
508
509
 
509
- def get_app_pin(self) -> bool:
510
+ @utils.sync_decorator
511
+ async def get_app_pin(self) -> bool:
510
512
  """Finds out if the current App is currently pinned or not.
511
513
 
512
514
  Returns:
@@ -519,7 +521,8 @@ class ADAPI:
519
521
  """
520
522
  return self.AD.app_management.get_app_pin(self.name)
521
523
 
522
- def set_pin_thread(self, thread: int) -> None:
524
+ @utils.sync_decorator
525
+ async def set_pin_thread(self, thread: int) -> None:
523
526
  """Sets the thread that the App will be pinned to.
524
527
 
525
528
  Args:
@@ -537,7 +540,8 @@ class ADAPI:
537
540
  """
538
541
  self.AD.app_management.set_pin_thread(self.name, thread)
539
542
 
540
- def get_pin_thread(self) -> int:
543
+ @utils.sync_decorator
544
+ async def get_pin_thread(self) -> int:
541
545
  """Finds out which thread the App is pinned to.
542
546
 
543
547
  Returns:
@@ -590,7 +594,8 @@ class ADAPI:
590
594
  # Keeping namespace get/set functions for legacy compatibility
591
595
  return self.namespace
592
596
 
593
- def namespace_exists(self, namespace: str) -> bool:
597
+ @utils.sync_decorator
598
+ async def namespace_exists(self, namespace: str) -> bool:
594
599
  """Check the existence of a namespace in AppDaemon.
595
600
 
596
601
  See the `namespace documentation <APPGUIDE.html#namespaces>`__ for more information.
@@ -668,7 +673,8 @@ class ADAPI:
668
673
 
669
674
  return await self.AD.state.remove_namespace(namespace)
670
675
 
671
- def list_namespaces(self) -> list[str]:
676
+ @utils.sync_decorator
677
+ async def list_namespaces(self) -> list[str]:
672
678
  """Get a list of all the namespaces in AppDaemon.
673
679
 
674
680
  Examples:
@@ -909,7 +915,8 @@ class ADAPI:
909
915
  """
910
916
  return devices.split(",")
911
917
 
912
- def get_plugin_config(self, namespace: str | None = None) -> Any:
918
+ @utils.sync_decorator
919
+ async def get_plugin_config(self, namespace: str | None = None) -> Any:
913
920
  """Gets any useful metadata that the plugin may have available.
914
921
 
915
922
  For instance, for the HASS plugin, this will return Home Assistant configuration
@@ -931,7 +938,8 @@ class ADAPI:
931
938
  namespace = namespace or self.namespace
932
939
  return self.AD.plugins.get_plugin_meta(namespace)
933
940
 
934
- def friendly_name(self, entity_id: str, namespace: str | None = None) -> str:
941
+ @utils.sync_decorator
942
+ async def friendly_name(self, entity_id: str, namespace: str | None = None) -> str:
935
943
  """Gets the Friendly Name of an entity.
936
944
 
937
945
  Args:
@@ -1380,7 +1388,7 @@ class ADAPI:
1380
1388
  # State
1381
1389
  #
1382
1390
 
1383
- @overload
1391
+ @overload # single entity
1384
1392
  @utils.sync_decorator
1385
1393
  async def listen_state(
1386
1394
  self,
@@ -1399,7 +1407,7 @@ class ADAPI:
1399
1407
  **kwargs: Any
1400
1408
  ) -> str: ...
1401
1409
 
1402
- @overload
1410
+ @overload # multiple entities
1403
1411
  @utils.sync_decorator
1404
1412
  async def listen_state(
1405
1413
  self,
@@ -3642,7 +3650,8 @@ class ADAPI:
3642
3650
  self.AD.futures.add_future(self.name, future)
3643
3651
  return future
3644
3652
 
3645
- def create_task(
3653
+ @utils.sync_decorator
3654
+ async def create_task(
3646
3655
  self,
3647
3656
  coro: Coroutine[Any, Any, T],
3648
3657
  callback: Callable | None = None,
@@ -5,8 +5,9 @@ from pathlib import Path
5
5
  from typing import TYPE_CHECKING
6
6
 
7
7
  from appdaemon import adapi
8
+ from appdaemon import utils
8
9
  from appdaemon.models.config.app import AppConfig
9
- from appdaemon.utils import StateAttrs
10
+
10
11
 
11
12
  # Check if the module is being imported using the legacy method
12
13
  if __name__ == Path(__file__).name:
@@ -31,7 +32,7 @@ class Entities: # @todo
31
32
  pass
32
33
 
33
34
  def __get__(self, instance, owner):
34
- stateattrs = StateAttrs(instance.get_state())
35
+ stateattrs = utils.StateAttrs(instance.get_state())
35
36
  return stateattrs
36
37
 
37
38
 
@@ -165,7 +166,8 @@ class ADBase:
165
166
  def get_ad_api(self) -> adapi.ADAPI:
166
167
  return adapi.ADAPI(self.AD, self.config_model)
167
168
 
168
- def get_plugin_api(self, plugin_name: str):
169
+ @utils.sync_decorator
170
+ async def get_plugin_api(self, plugin_name: str):
169
171
  """Get the plugin API for a specific plugin."""
170
172
  if isinstance(cfg := self.app_config.root.get(self.name), AppConfig):
171
173
  return self.AD.plugins.get_plugin_api(plugin_name, cfg)
@@ -615,7 +615,7 @@ class AppManagement:
615
615
  self._compare_sequences(update_actions, cfg, files_to_read)
616
616
  continue
617
617
 
618
- if name in self.non_apps:
618
+ if name in self.non_apps or cfg.disable:
619
619
  continue
620
620
 
621
621
  # New config found
@@ -685,8 +685,14 @@ class AppManagement:
685
685
  if not module_name.startswith("appdaemon"):
686
686
  self.logger.debug("Importing '%s'", module_name)
687
687
  importlib.import_module(module_name)
688
- except SyntaxError as exc:
689
- path = Path(exc.filename)
688
+ except Exception as exc:
689
+ match exc:
690
+ case SyntaxError():
691
+ path = Path(exc.filename)
692
+ case NameError():
693
+ path = Path(traceback.extract_tb(exc.__traceback__)[-1].filename)
694
+ case _:
695
+ raise exc
690
696
  mtime = self.dependency_manager.python_deps.files.mtimes.get(path)
691
697
  self.dependency_manager.python_deps.bad_files.add((path, mtime))
692
698
  raise exc
@@ -989,13 +995,16 @@ class AppManagement:
989
995
  update_actions.apps.reload -= failed_to_stop
990
996
 
991
997
  async def _start_apps(self, update_actions: UpdateActions):
998
+ if failed := update_actions.apps.failed:
999
+ self.logger.warning('Failed to start apps: %s', failed)
1000
+
992
1001
  start_order = update_actions.apps.start_sort(self.dependency_manager)
993
1002
  if start_order:
994
1003
  self.logger.info("Starting apps: %s", update_actions.apps.init_set)
995
1004
  self.logger.debug("App start order: %s", start_order)
996
1005
 
997
1006
  for app_name in start_order:
998
- if isinstance((cfg := self.app_config.root[app_name]), AppConfig):
1007
+ if isinstance((cfg := self.app_config.root[app_name]), AppConfig) and not cfg.disable:
999
1008
  @ade.wrap_async(self.error, self.AD.app_dir, f"'{app_name}' instantiation")
1000
1009
  async def safe_create(self: "AppManagement"):
1001
1010
  try:
@@ -92,6 +92,7 @@ def get_file_deps(file_path: str | Path) -> set[str]:
92
92
  mod: ast.Module = ast.parse(file_content, filename=file_path)
93
93
  except Exception as e:
94
94
  logger.warning(f"Error parsing python module with AST: {e}")
95
+ raise e
95
96
  else:
96
97
  for node in get_imports(mod):
97
98
  match node:
@@ -107,18 +108,32 @@ def get_file_deps(file_path: str | Path) -> set[str]:
107
108
  return set(gen_modules())
108
109
 
109
110
 
110
- def get_dependency_graph(files: Iterable[Path], exclude: set[Path] | None = None):
111
- graph = {
112
- get_full_module_name(f): get_file_deps(f)
113
- for f in files
114
- if exclude is None or f not in exclude
115
- }
111
+ def get_dependency_graph(
112
+ files: Iterable[Path],
113
+ exclude: set[Path] | None = None
114
+ ) -> tuple[dict[str, set[str]], set[Path]]:
115
+ """Gets the dependency graph for some Python files.
116
+
117
+ Returns:
118
+ A tuple containing:
119
+ - A dictionary where keys are module names and values are sets of module names that the key module depends on.
120
+ - A set of paths that failed to parse or resolve dependencies.
121
+ """
122
+ graph = {}
123
+ failed = set()
124
+ for f in files:
125
+ if exclude is None or f not in exclude:
126
+ try:
127
+ graph[get_full_module_name(f)] = get_file_deps(f)
128
+ except Exception:
129
+ failed.add(f)
130
+ continue
116
131
 
117
132
  for mod, deps in graph.items():
118
133
  if mod in deps:
119
134
  deps.remove(mod)
120
135
 
121
- return graph
136
+ return graph, failed
122
137
 
123
138
 
124
139
  def get_all_nodes(deps: dict[str, set[str]]) -> set[str]:
@@ -1,4 +1,5 @@
1
1
  from abc import ABC
2
+ from copy import deepcopy
2
3
  from dataclasses import InitVar, dataclass, field
3
4
  from pathlib import Path
4
5
  from typing import Iterable
@@ -16,14 +17,14 @@ class Dependencies(ABC):
16
17
  ext: str = field(init=False) # this has to be defined by the children classes
17
18
  dep_graph: dict[str, set[str]] = field(init=False)
18
19
  rev_graph: dict[str, set[str]] = field(init=False)
19
- bad_files: set[Path] = field(default_factory=set, init=False)
20
+ bad_files: set[tuple[Path, float]] = field(default_factory=set, init=False)
20
21
 
21
22
  def __post_init__(self):
22
23
  self.refresh_dep_graph()
23
24
 
24
25
  def update(self, new_files: Iterable[Path]):
25
26
  self.files.update(new_files)
26
- for bf, mtime in self.bad_files:
27
+ for bf, mtime in deepcopy(self.bad_files):
27
28
  new_mtime = self.files.mtimes.get(bf)
28
29
  if new_mtime != mtime:
29
30
  assert new_mtime > mtime, f"File {bf} was modified in the future"
@@ -65,7 +66,12 @@ class PythonDeps(Dependencies):
65
66
  if self.bad_files:
66
67
  bad_files, _ = zip(*self.bad_files)
67
68
  bad_files = set(bad_files)
68
- self.dep_graph = get_dependency_graph(self.files, exclude=bad_files)
69
+
70
+ self.dep_graph, failed = get_dependency_graph(self.files, exclude=bad_files)
71
+
72
+ for file in failed:
73
+ self.bad_files.add((file, self.files.mtimes.get(file, 0)))
74
+
69
75
  self.rev_graph = reverse_graph(self.dep_graph)
70
76
 
71
77
  def modules_to_import(self) -> set[str]:
@@ -355,8 +355,6 @@ class Entity:
355
355
 
356
356
  Args:
357
357
  service (str): The service name, without the domain (e.g "toggle")
358
- return_result(bool, option): If `return_result` is provided and set to `True` AD will attempt
359
- to wait for the result, and return it after execution
360
358
  callback: The non-async callback to be executed when complete.
361
359
  **kwargs: Each service has different parameter requirements. This argument
362
360
  allows you to specify a comma-separated list of keyword value pairs, e.g.,
@@ -54,9 +54,10 @@ def user_exception_block(logger: Logger, exception: AppDaemonException, app_dir:
54
54
  """Function to generate a user-friendly block of text for an exception. Gets the whole chain of exception causes to decide what to do.
55
55
  """
56
56
  width = 75
57
+ spacing = 4
57
58
  inset = 5
58
59
  if header is not None:
59
- header = f'{"=" * inset} {header} {"=" * (width - inset - len(header))}'
60
+ header = f'{"=" * inset} {header} {"=" * (width - spacing - inset - len(header))}'
60
61
  else:
61
62
  header = '=' * width
62
63
  logger.error(header)
@@ -86,10 +87,12 @@ def user_exception_block(logger: Logger, exception: AppDaemonException, app_dir:
86
87
  logger.error(f'{indent}{filename} line {line} in {func_name}')
87
88
  case OSError() if str(exc).endswith('address already in use'):
88
89
  logger.error(f'{indent}{exc.__class__.__name__}: {exc}')
89
- case NameError():
90
+ case NameError() | ImportError():
90
91
  logger.error(f'{indent}{exc.__class__.__name__}: {exc}')
91
92
  if tb := traceback.extract_tb(exc.__traceback__):
92
93
  frame = tb[-1]
94
+ file = Path(frame.filename).relative_to(app_dir.parent)
95
+ logger.error(f'{indent} line {frame.lineno} in {file.name}')
93
96
  logger.error(f'{indent} {frame._line.rstrip()}')
94
97
  error_len = frame.end_colno - frame.colno
95
98
  logger.error(f'{indent} {" " * (frame.colno - 1)}{"^" * error_len}')
@@ -112,7 +115,7 @@ def user_exception_block(logger: Logger, exception: AppDaemonException, app_dir:
112
115
  for line in lines:
113
116
  logger.error(f'{indent}{line}')
114
117
 
115
- logger.error('=' * 75)
118
+ logger.error('=' * width)
116
119
 
117
120
 
118
121
  def unexpected_block(logger: Logger, exception: Exception):
@@ -96,9 +96,7 @@ def route_secure(myfunc):
96
96
  return await myfunc(*args)
97
97
 
98
98
  elif "adcreds" in request.cookies:
99
- match = await utils.run_in_executor(
100
- self, bcrypt.checkpw, str.encode(self.password), str.encode(request.cookies["adcreds"])
101
- )
99
+ match = await utils.run_in_executor(self, bcrypt.checkpw, str.encode(self.password), str.encode(request.cookies["adcreds"]))
102
100
  if match:
103
101
  return await myfunc(*args)
104
102
 
@@ -176,12 +174,19 @@ class HTTP:
176
174
 
177
175
  try:
178
176
  url = urlparse(self.url)
179
-
180
177
  self.host = url.hostname
181
- try:
178
+ self.scheme = url.scheme
179
+
180
+ if url.port is None:
181
+ match url.scheme:
182
+ case "http":
183
+ self.port = 80
184
+ case "https":
185
+ self.port = 443
186
+ case _:
187
+ self.port = None # let the validation catch it
188
+ else:
182
189
  self.port = url.port
183
- except IndexError:
184
- self.port = 80
185
190
 
186
191
  if self.host == "":
187
192
  raise ValueError("Invalid host for 'url'")
@@ -373,9 +378,7 @@ class HTTP:
373
378
 
374
379
  self._process_arg("url", http)
375
380
  if not self.url:
376
- self.logger.warning(
377
- "'{arg}' is '{value}'. Please configure appdaemon.yaml".format(arg="url", value=self.url)
378
- )
381
+ self.logger.warning("'{arg}' is '{value}'. Please configure appdaemon.yaml".format(arg="url", value=self.url))
379
382
  exit(0)
380
383
 
381
384
  self._process_arg("transport", http)
@@ -100,7 +100,6 @@ class HASSConfig(PluginConfig):
100
100
  BeforeValidator(utils.parse_timedelta)
101
101
  ] = Field(default_factory=lambda: timedelta(seconds=10))
102
102
  """Default timeout for waiting for responses from the websocket connection"""
103
- # return_result: bool | None = None
104
103
  suppress_log_messages: bool = False
105
104
  retry_secs: int = 5
106
105
  services_sleep_time: int = 60
@@ -71,7 +71,7 @@ class LoadingActions:
71
71
  Uses a dependency graph to sort the internal ``init`` and ``reload`` sets together
72
72
  """
73
73
  items = copy(self.init_set)
74
- items |= find_all_dependents(items, dm.app_deps.rev_graph)
74
+ items |= find_all_dependents(items, dm.app_deps.dep_graph)
75
75
  priorities = {
76
76
  app_name: dm.app_deps.app_config.root[app_name].priority
77
77
  for app_name in items
@@ -260,7 +260,8 @@ class Hass(ADBase, ADAPI):
260
260
  """
261
261
  return self.get_state(*args, **kwargs)
262
262
 
263
- def anyone_home(self, person: bool = True, namespace: str | None = None) -> bool:
263
+ @utils.sync_decorator
264
+ async def anyone_home(self, person: bool = True, namespace: str | None = None) -> bool:
264
265
  """Determines if the house/apartment is occupied.
265
266
 
266
267
  A convenience function to determine if one or more person is home. Use
@@ -285,10 +286,11 @@ class Hass(ADBase, ADAPI):
285
286
  >>> do something
286
287
 
287
288
  """
288
- details = self.get_tracker_details(person, namespace, copy=False)
289
+ details = await self.get_tracker_details(person, namespace, copy=False)
289
290
  return any(state['state'] == 'home' for state in details.values())
290
291
 
291
- def everyone_home(self, person: bool = True, namespace: str | None = None) -> bool:
292
+ @utils.sync_decorator
293
+ async def everyone_home(self, person: bool = True, namespace: str | None = None) -> bool:
292
294
  """Determine if all family's members at home.
293
295
 
294
296
  A convenience function to determine if everyone is home. Use this in
@@ -312,10 +314,11 @@ class Hass(ADBase, ADAPI):
312
314
  >>> do something
313
315
 
314
316
  """
315
- details = self.get_tracker_details(person, namespace, copy=False)
317
+ details = await self.get_tracker_details(person, namespace, copy=False)
316
318
  return all(state['state'] == 'home' for state in details.values())
317
319
 
318
- def noone_home(self, person: bool = True, namespace: str | None = None) -> bool:
320
+ @utils.sync_decorator
321
+ async def noone_home(self, person: bool = True, namespace: str | None = None) -> bool:
319
322
  """Determines if the house/apartment is empty.
320
323
 
321
324
  A convenience function to determine if no people are at home. Use this
@@ -340,7 +343,7 @@ class Hass(ADBase, ADAPI):
340
343
  >>> do something
341
344
 
342
345
  """
343
- return not self.anyone_home(person, namespace)
346
+ return not await self.anyone_home(person, namespace)
344
347
 
345
348
  #
346
349
  # Built-in constraints
@@ -1375,7 +1378,7 @@ class Hass(ADBase, ADAPI):
1375
1378
  except (SyntaxError, ValueError):
1376
1379
  return result
1377
1380
 
1378
- def _template_command(self, command: str, *args: tuple[str, ...]) -> str | list[str]:
1381
+ def _template_command(self, command: str, *args: str) -> str | list[str]:
1379
1382
  """Internal AppDaemon function to format calling a single template command correctly."""
1380
1383
  if len(args) == 0:
1381
1384
  return self.render_template(f'{{{{ {command}() }}}}')
@@ -1478,6 +1481,10 @@ class Hass(ADBase, ADAPI):
1478
1481
  <https://www.home-assistant.io/docs/configuration/templating/#entities-for-an-integration>`_ for more
1479
1482
  information.
1480
1483
  """
1484
+ entities = self._template_command('integration_entities', integration)
1485
+ assert isinstance(entities, list) and all(isinstance(e, str) for e in entities), \
1486
+ 'Invalid return type from integration_entities'
1487
+ return entities
1481
1488
 
1482
1489
  # Labels
1483
1490
  # https://www.home-assistant.io/docs/configuration/templating/#labels
@@ -229,23 +229,17 @@ class Mqtt(adbase.ADBase, adapi.ADAPI):
229
229
  result = self.call_service(service, **kwargs)
230
230
  return result
231
231
 
232
- def _run_service_call(self, task: str, topic: Union[str, list], **kwargs: Optional[Any]) -> None:
232
+ def _run_service_call(self, task: str, topic: str | list[str], **kwargs: Optional[Any]) -> None:
233
233
  """Used to process the subscribe/unsubscribe service calls"""
234
234
 
235
235
  # first we validate the topic
236
236
  if not isinstance(topic, (str, list)):
237
237
  raise ValueError(f"The given topic {topic} is not supported. Please only strs and lists are supported")
238
238
 
239
- if isinstance(topic, str):
240
- kwargs["topic"] = topic
241
- service = f"mqtt/{task}"
242
- self.call_service(service, **kwargs)
239
+ kwargs["topic"] = topic
240
+ service = f"mqtt/{task}"
241
+ return self.call_service(service, **kwargs)
243
242
 
244
- else: # its a list
245
- for t in topic:
246
- kwargs["topic"] = t
247
- service = f"mqtt/{task}"
248
- self.call_service(service, **kwargs)
249
243
 
250
244
  def mqtt_subscribe(self, topic: Union[str, list], **kwargs: Optional[Any]) -> None:
251
245
  """Subscribes to a MQTT topic.
@@ -284,7 +278,7 @@ class Mqtt(adbase.ADBase, adapi.ADAPI):
284
278
 
285
279
  """
286
280
 
287
- self._run_service_call("subscribe", topic, **kwargs)
281
+ return self._run_service_call("subscribe", topic, **kwargs)
288
282
 
289
283
  def mqtt_unsubscribe(self, topic: Union[str, list], **kwargs: Optional[Any]) -> None:
290
284
  """Unsubscribes from a MQTT topic.
@@ -323,7 +317,7 @@ class Mqtt(adbase.ADBase, adapi.ADAPI):
323
317
 
324
318
  """
325
319
 
326
- self._run_service_call("unsubscribe", topic, **kwargs)
320
+ return self._run_service_call("unsubscribe", topic, **kwargs)
327
321
 
328
322
  @utils.sync_decorator
329
323
  async def is_client_connected(self, **kwargs: Optional[Any]) -> bool:
@@ -1,2 +1,2 @@
1
- __version__ = "4.5.1"
1
+ __version__ = "4.5.3"
2
2
  __version_comments__ = ""
@@ -0,0 +1,80 @@
1
+ Metadata-Version: 2.4
2
+ Name: appdaemon
3
+ Version: 4.5.3
4
+ Summary: Apps for the Home Assistant home automation package.
5
+ Author-email: Andrew I Cockburn <appdaemon@acockburn.com>
6
+ Project-URL: documentation, https://appdaemon.readthedocs.io
7
+ Project-URL: repository, https://github.com/AppDaemon
8
+ Project-URL: changelog, https://github.com/AppDaemon/appdaemon/blob/master/docs/HISTORY.rst
9
+ Keywords: appdaemon,home,automation
10
+ Classifier: Development Status :: 5 - Production/Stable
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Natural Language :: English
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Topic :: Home Automation
17
+ Requires-Python: <3.13,>=3.10
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE.md
20
+ Requires-Dist: importlib-metadata; python_version < "3.8"
21
+ Requires-Dist: aiohttp<3.12.0,>=3.9.0
22
+ Requires-Dist: aiohttp_jinja2<1.7.0,>=1.5.1
23
+ Requires-Dist: astral~=3.2
24
+ Requires-Dist: bcrypt<4.3.0,>=4.0.1
25
+ Requires-Dist: deepdiff==8.2.0
26
+ Requires-Dist: feedparser~=6.0.10
27
+ Requires-Dist: iso8601<2.2,>=1.1
28
+ Requires-Dist: paho-mqtt<2.2.0,>=1.6.1
29
+ Requires-Dist: pid~=3.0.4
30
+ Requires-Dist: python-dateutil<2.10.0,>=2.8.2
31
+ Requires-Dist: python-socketio<5.12,>=5.5
32
+ Requires-Dist: pytz<2025.2.0,>=2022.7.1
33
+ Requires-Dist: pyyaml~=6.0.1
34
+ Requires-Dist: requests<2.33.0,>=2.28.2
35
+ Requires-Dist: sockjs<0.14,>=0.11
36
+ Requires-Dist: uvloop==0.21.0; sys_platform != "win32"
37
+ Requires-Dist: tomli==2.2.1
38
+ Requires-Dist: tomli_w<1.3,>=1.0
39
+ Requires-Dist: pydantic~=2.10.6
40
+ Provides-Extra: dev
41
+ Requires-Dist: pip-tools<7.5.0,>=6.12.3; extra == "dev"
42
+ Requires-Dist: build<1.3,>=0.10; extra == "dev"
43
+ Requires-Dist: flake8~=7.1.1; extra == "dev"
44
+ Requires-Dist: black<25.2,>=23.1; extra == "dev"
45
+ Requires-Dist: pre-commit<3.9.0,>=3.1.1; python_version > "3.7" and extra == "dev"
46
+ Requires-Dist: pytest<8.4.0,>=7.2.1; extra == "dev"
47
+ Requires-Dist: ruff<0.7.0,>=0.0.261; extra == "dev"
48
+ Requires-Dist: codespell>=2.4.1; extra == "dev"
49
+ Provides-Extra: doc
50
+ Requires-Dist: sphinx-autobuild<2024.10.0,>=2021.3.14; extra == "doc"
51
+ Requires-Dist: sphinx-rtd-theme==3.0.2; extra == "doc"
52
+ Requires-Dist: pygments<2.20,>=2.14; extra == "doc"
53
+ Requires-Dist: myst-parser==4.0.0; extra == "doc"
54
+ Dynamic: license-file
55
+
56
+ # Description
57
+
58
+ AppDaemon is a loosely coupled, multi-threaded, sandboxed python
59
+ execution environment for writing automation apps for various types of Home Automation Software including [Home
60
+ Assistant](https://home-assistant.io/) and MQTT. It has a pluggable architecture allowing it to be integrated with
61
+ practically any event driven application.
62
+
63
+ It also provides a configurable dashboard (HADashboard)
64
+ suitable for wall mounted tablets.
65
+
66
+ ## Getting started
67
+
68
+ For full instructions on installation and usage check out the [AppDaemon Project Documentation](http://appdaemon.readthedocs.io).
69
+
70
+ ## Release Cycle Frequency
71
+
72
+ AppDaemon has reached a very stable point, works reliably and is fairly feature rich at this point
73
+ in its development. For that reason, releases have been slow in recent months. This does not mean that AppDaemon has been abandoned -
74
+ it is used every day by the core developers and has an active discord server [here](https://discord.gg/sgSr79jW5x) - please join us for tips
75
+ and tricks, AppDaemon discussions and general home automation.
76
+
77
+ ## Contributing
78
+
79
+ This is an active open-source project. We are always open to people who want to use the code or contribute to it. Thank you for being involved!
80
+ Have a look at the [official documentation](https://appdaemon.readthedocs.io/en/latest/DEV.html) for more information.