forked from platypush/platypush
Better management of the context and support for proper expression expansion from the context in the action execution through eval
This commit is contained in:
parent
2871583c75
commit
252f503e4d
|
@ -97,10 +97,10 @@ class Event(Message):
|
||||||
'phrase': 'Hey dude turn on the living room lights'
|
'phrase': 'Hey dude turn on the living room lights'
|
||||||
}
|
}
|
||||||
|
|
||||||
- self._matches_argument(argname='phrase', condition_value='Turn on the $lights lights')
|
- self._matches_argument(argname='phrase', condition_value='Turn on the ${lights} lights')
|
||||||
will return EventMatchResult(is_match=True, parsed_args={ 'lights': 'living room' })
|
will return EventMatchResult(is_match=True, parsed_args={ 'lights': 'living room' })
|
||||||
|
|
||||||
- self._matches_argument(argname='phrase', condition_value='Turn off the $lights lights')
|
- self._matches_argument(argname='phrase', condition_value='Turn off the ${lights} lights')
|
||||||
will return EventMatchResult(is_match=False, parsed_args={})
|
will return EventMatchResult(is_match=False, parsed_args={})
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -117,15 +117,14 @@ class Event(Message):
|
||||||
condition_tokens.pop(0)
|
condition_tokens.pop(0)
|
||||||
result.score += 1
|
result.score += 1
|
||||||
elif re.search(condition_token, event_token):
|
elif re.search(condition_token, event_token):
|
||||||
# The only supported regex-match as of now is the equivalent of
|
m = re.search('({})'.format(condition_token), event_token)
|
||||||
# the maybe operator.
|
if m.group(1):
|
||||||
# e.g. "turn on (the)? lights" would match both "turn on the lights"
|
event_tokens.pop(0)
|
||||||
# and "turn on lights". In such a case, we just consume the
|
result.score += 1
|
||||||
# condition token and proceed forward. TODO add a more
|
|
||||||
# sophisticated regex-match handling
|
|
||||||
condition_tokens.pop(0)
|
condition_tokens.pop(0)
|
||||||
else:
|
else:
|
||||||
m = re.match('[^\\\]*\$([\w\d_-]+)', condition_token)
|
m = re.match('[^\\\]*\${(.+?)}', condition_token)
|
||||||
if m:
|
if m:
|
||||||
argname = m.group(1)
|
argname = m.group(1)
|
||||||
if argname not in result.parsed_args:
|
if argname not in result.parsed_args:
|
||||||
|
|
|
@ -88,22 +88,33 @@ class Request(Message):
|
||||||
return event_args
|
return event_args
|
||||||
|
|
||||||
|
|
||||||
def _expand_value_from_context(self, value, **context):
|
@classmethod
|
||||||
|
def _expand_value_from_context(cls, value, **context):
|
||||||
parsed_value = ''
|
parsed_value = ''
|
||||||
while value:
|
while value:
|
||||||
m = re.match('([^\\\]*)\$([\w\d_-]+)(.*)', value)
|
m = re.match('([^\$]*)(\${\s*(.+?)\s*})(.*)', value)
|
||||||
if m:
|
if m and not m.group(1).endswith('\\'):
|
||||||
context_argname = m.group(2)
|
prefix = m.group(1); expr = m.group(2);
|
||||||
value = m.group(3)
|
inner_expr = m.group(3); value = m.group(4)
|
||||||
|
|
||||||
|
m = re.match('([^.\[\]()]+)(.*)', inner_expr)
|
||||||
|
context_argname = m.group(1)
|
||||||
|
path = m.group(2)
|
||||||
|
|
||||||
if context_argname in context:
|
if context_argname in context:
|
||||||
parsed_value += m.group(1) + context[context_argname]
|
try:
|
||||||
else:
|
context_value = eval("context['{}']{}".format(
|
||||||
parsed_value += m.group(1) + '$' + m.group(2)
|
context_argname, path if path else ''))
|
||||||
|
except: context_value = expr
|
||||||
|
|
||||||
|
parsed_value += prefix + str(context_value)
|
||||||
|
else: parsed_value += prefix + expr
|
||||||
else:
|
else:
|
||||||
parsed_value += value
|
parsed_value += value
|
||||||
value = ''
|
value = ''
|
||||||
|
|
||||||
return parsed_value
|
try: return json.loads(parsed_value)
|
||||||
|
except ValueError as e: return parsed_value
|
||||||
|
|
||||||
|
|
||||||
def _send_response(self, response):
|
def _send_response(self, response):
|
||||||
|
@ -126,16 +137,14 @@ class Request(Message):
|
||||||
context -- Key-valued context. Example:
|
context -- Key-valued context. Example:
|
||||||
context = (group_name='Kitchen lights')
|
context = (group_name='Kitchen lights')
|
||||||
request.args:
|
request.args:
|
||||||
- group: $group_name # will be expanded as "Kitchen lights")
|
- group: ${group_name} # will be expanded as "Kitchen lights")
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def _thread_func(n_tries):
|
def _thread_func(n_tries):
|
||||||
if self.action.startswith('procedure.'):
|
if self.action.startswith('procedure.'):
|
||||||
try:
|
response = self._execute_procedure(n_tries=n_tries)
|
||||||
response = self._execute_procedure(n_tries=n_tries)
|
self._send_response(response)
|
||||||
finally:
|
return response
|
||||||
self._send_response(response)
|
|
||||||
return response
|
|
||||||
else:
|
else:
|
||||||
(module_name, method_name) = get_module_and_method_from_action(self.action)
|
(module_name, method_name) = get_module_and_method_from_action(self.action)
|
||||||
plugin = get_plugin(module_name)
|
plugin = get_plugin(module_name)
|
||||||
|
|
|
@ -54,8 +54,10 @@ class Procedure(object):
|
||||||
request.execute(n_tries, async=True, **context)
|
request.execute(n_tries, async=True, **context)
|
||||||
else:
|
else:
|
||||||
response = request.execute(n_tries, async=False, **context)
|
response = request.execute(n_tries, async=False, **context)
|
||||||
context = { k:v for (k,v) in response.output.items() } \
|
|
||||||
if isinstance(response.output, dict) else {}
|
if isinstance(response.output, dict):
|
||||||
|
for (k,v) in response.output.items():
|
||||||
|
context[k] = v
|
||||||
|
|
||||||
context['output'] = response.output
|
context['output'] = response.output
|
||||||
context['errors'] = response.errors
|
context['errors'] = response.errors
|
||||||
|
|
|
@ -9,7 +9,7 @@ class TestEventParse(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.condition = EventCondition.build({
|
self.condition = EventCondition.build({
|
||||||
'type': 'platypush.message.event.ping.PingEvent',
|
'type': 'platypush.message.event.ping.PingEvent',
|
||||||
'message': 'This is (the)? answer: $answer'
|
'message': 'This is (the)? answer: ${answer}'
|
||||||
})
|
})
|
||||||
|
|
||||||
def test_event_parse(self):
|
def test_event_parse(self):
|
||||||
|
|
Loading…
Reference in a new issue