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
4 changed files with 37 additions and 27 deletions
|
@ -97,10 +97,10 @@ class Event(Message):
|
|||
'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' })
|
||||
|
||||
- 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={})
|
||||
"""
|
||||
|
||||
|
@ -117,15 +117,14 @@ class Event(Message):
|
|||
condition_tokens.pop(0)
|
||||
result.score += 1
|
||||
elif re.search(condition_token, event_token):
|
||||
# The only supported regex-match as of now is the equivalent of
|
||||
# the maybe operator.
|
||||
# e.g. "turn on (the)? lights" would match both "turn on the lights"
|
||||
# and "turn on lights". In such a case, we just consume the
|
||||
# condition token and proceed forward. TODO add a more
|
||||
# sophisticated regex-match handling
|
||||
m = re.search('({})'.format(condition_token), event_token)
|
||||
if m.group(1):
|
||||
event_tokens.pop(0)
|
||||
result.score += 1
|
||||
|
||||
condition_tokens.pop(0)
|
||||
else:
|
||||
m = re.match('[^\\\]*\$([\w\d_-]+)', condition_token)
|
||||
m = re.match('[^\\\]*\${(.+?)}', condition_token)
|
||||
if m:
|
||||
argname = m.group(1)
|
||||
if argname not in result.parsed_args:
|
||||
|
|
|
@ -88,22 +88,33 @@ class Request(Message):
|
|||
return event_args
|
||||
|
||||
|
||||
def _expand_value_from_context(self, value, **context):
|
||||
@classmethod
|
||||
def _expand_value_from_context(cls, value, **context):
|
||||
parsed_value = ''
|
||||
while value:
|
||||
m = re.match('([^\\\]*)\$([\w\d_-]+)(.*)', value)
|
||||
if m:
|
||||
context_argname = m.group(2)
|
||||
value = m.group(3)
|
||||
m = re.match('([^\$]*)(\${\s*(.+?)\s*})(.*)', value)
|
||||
if m and not m.group(1).endswith('\\'):
|
||||
prefix = m.group(1); expr = m.group(2);
|
||||
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:
|
||||
parsed_value += m.group(1) + context[context_argname]
|
||||
else:
|
||||
parsed_value += m.group(1) + '$' + m.group(2)
|
||||
try:
|
||||
context_value = eval("context['{}']{}".format(
|
||||
context_argname, path if path else ''))
|
||||
except: context_value = expr
|
||||
|
||||
parsed_value += prefix + str(context_value)
|
||||
else: parsed_value += prefix + expr
|
||||
else:
|
||||
parsed_value += value
|
||||
value = ''
|
||||
|
||||
return parsed_value
|
||||
try: return json.loads(parsed_value)
|
||||
except ValueError as e: return parsed_value
|
||||
|
||||
|
||||
def _send_response(self, response):
|
||||
|
@ -126,14 +137,12 @@ class Request(Message):
|
|||
context -- Key-valued context. Example:
|
||||
context = (group_name='Kitchen lights')
|
||||
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):
|
||||
if self.action.startswith('procedure.'):
|
||||
try:
|
||||
response = self._execute_procedure(n_tries=n_tries)
|
||||
finally:
|
||||
self._send_response(response)
|
||||
return response
|
||||
else:
|
||||
|
|
|
@ -54,8 +54,10 @@ class Procedure(object):
|
|||
request.execute(n_tries, async=True, **context)
|
||||
else:
|
||||
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['errors'] = response.errors
|
||||
|
|
|
@ -9,7 +9,7 @@ class TestEventParse(unittest.TestCase):
|
|||
def setUp(self):
|
||||
self.condition = EventCondition.build({
|
||||
'type': 'platypush.message.event.ping.PingEvent',
|
||||
'message': 'This is (the)? answer: $answer'
|
||||
'message': 'This is (the)? answer: ${answer}'
|
||||
})
|
||||
|
||||
def test_event_parse(self):
|
||||
|
|
Loading…
Reference in a new issue