forked from AlexxIT/PythonScriptsPro
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path__init__.py
More file actions
83 lines (59 loc) · 2.27 KB
/
Copy path__init__.py
File metadata and controls
83 lines (59 loc) · 2.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
"""Component to allow running Python scripts.
https://docs.python.org/3/library/functions.html#compile
"""
import hashlib
import logging
import voluptuous as vol
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.typing import HomeAssistantType, ServiceCallType
from homeassistant.requirements import async_process_requirements
_LOGGER = logging.getLogger(__name__)
DOMAIN = "python_script"
CONF_REQUIREMENTS = 'requirements'
CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.Schema({
vol.Optional(CONF_REQUIREMENTS): cv.ensure_list,
})
}, extra=vol.ALLOW_EXTRA)
def md5(data: str):
return hashlib.md5(data.encode()).hexdigest()
async def async_setup(hass: HomeAssistantType, hass_config: dict):
config: dict = hass_config[DOMAIN]
if CONF_REQUIREMENTS in config:
hass.async_create_task(async_process_requirements(
hass, DOMAIN, config[CONF_REQUIREMENTS]
))
cache_code = {}
def handler(call: ServiceCallType):
# Run with SyncWorker
file = call.data.get('file')
srcid = md5(call.data['source']) if 'source' in call.data else None
cache = call.data.get('cache', True)
if not (file or srcid):
_LOGGER.error("Either file or source is required in params")
return
code = cache_code.get(file or srcid)
if not cache or not code:
if file:
_LOGGER.debug("Load code from file")
file = hass.config.path(file)
with open(file, encoding='utf-8') as f:
code = compile(f.read(), file, 'exec')
if cache:
cache_code[file] = code
else:
_LOGGER.debug("Load inline code")
code = compile(call.data['source'], '<string>', 'exec')
if cache:
cache_code[srcid] = code
else:
_LOGGER.debug("Load code from cache")
execute_script(hass, call.data, _LOGGER, code)
hass.services.async_register(DOMAIN, "exec", handler)
return True
def execute_script(hass, data, logger, code):
try:
_LOGGER.debug("Run python script")
exec(code)
except Exception as e:
_LOGGER.exception(f"Error executing script: {e}")