在使用BDD时,想实现一种描述函数调用及赋值操作的 通用步骤,因此实现了以下正则解析
特性
- 支持函数调用,有参/无参,有返/无反
- 支持关键字参数和位置参数
- 支持变量赋值
TODO
- $a.b取值
- 支持字典/列表类型参数
代码实现
import re
from string import Template
# text = 'request'
# text = 'request get https://httpbin.org?a=1&b=2'
def smart_value(var: str):
if var.isnumeric(): # TODO float
return int(var)
return var
def render(text, context):
return Template(text).safe_substitute(context)
def parse(text, context=None):
# text = Template(text).safe_substitute(context)
patten = re.compile('((?P<var>\w+)\s*=\s*)?(?P<func>\S+)(\s+(?P<args>.*))?')
matched = re.match(patten, text)
if not matched:
raise ValueError('不匹配')
var_name = matched.group('var')
func_or_value_name = matched.group('func')
args_raw = matched.group('args')
args = []
kwargs = {}
if args_raw:
args_raw = render(args_raw, context)
_args = args_raw.split()
for arg in _args:
if arg.startswith('"') or arg.startswith("'"):
args.append(arg.strip('"|\''))
else:
if '=' not in arg:
args.append(smart_value(arg))
else:
key, value = arg.split('=', 1)
kwargs[key] = smart_value(value)
return var_name, func_or_value_name, args, kwargs
def call(text, context=None):
var_name, func_or_value_name, args, kwargs = parse(text, context)
func = context.get(func_or_value_name)
value = render(func_or_value_name, context)
if func:
if callable(func):
value = func(*args, **kwargs)
if var_name:
context[var_name] = value
if __name__ == '__main__':
import requests
context = {'request': requests.request, 'add': lambda a,b: a+b, 'a': '1'}
text = 'res = add $a b=2'
text = 'res = $a'
print(parse(text, context))
call(text, context)
print(context['res'])