|
|
|
@ -19,7 +19,20 @@ FireTrace由一系列FireTraceElement对象组成,内部用list表示。在需
|
|
|
|
|
一个函数,则该Error将在trace中被capture并且final component将被设定为None。
|
|
|
|
|
|
|
|
|
|
## inspect.py/inspectutils.py
|
|
|
|
|
提供inspection操作的功能支持
|
|
|
|
|
提供inspection操作的功能支持。也就是对callable对象参数的解析。
|
|
|
|
|
主要的核心函数如下:
|
|
|
|
|
```
|
|
|
|
|
def Py3GetFullArgSpec(fn):
|
|
|
|
|
```
|
|
|
|
|
内置getfullargspec的替代方法。
|
|
|
|
|
其实现使用库的_signature_from_callable()
|
|
|
|
|
```
|
|
|
|
|
sig = inspect._signature_from_callable( # pylint: disable=protected-access
|
|
|
|
|
fn,
|
|
|
|
|
skip_bound_arg=True,
|
|
|
|
|
follow_wrapper_chains=True,
|
|
|
|
|
sigcls=inspect.Signature)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## decorators.py
|
|
|
|
|
这些decorators为python fire提供函数metadata。
|
|
|
|
@ -51,7 +64,7 @@ fire的一般执行过程如下:
|
|
|
|
|
* 否则,如果是callable的示例,调用
|
|
|
|
|
1. 返回上一个步骤重复,直到所有args被消耗
|
|
|
|
|
|
|
|
|
|
当不再能够继续执行时,fire将结果序列化后输出。
|
|
|
|
|
当不再能够继续执行时,fire将结果序列化后输出。以上就是对fire主要功能的简单描述。其比较具体的实现如下。
|
|
|
|
|
我们可以注意到其比较核心的功能需要用到代码分析技术,而fire的实现如下:
|
|
|
|
|
```
|
|
|
|
|
is_callable = inspect.isclass(component) or inspect.isroutine(component)
|
|
|
|
@ -67,4 +80,41 @@ fire的一般执行过程如下:
|
|
|
|
|
|
|
|
|
|
当检测到component是class, routine, callable object时,调用_CallAndUpdateTrace()
|
|
|
|
|
|
|
|
|
|
#### _CallAndUpdateTrace()实现
|
|
|
|
|
### _CallAndUpdateTrace()实现
|
|
|
|
|
重要部分:
|
|
|
|
|
```
|
|
|
|
|
# 返回filename, line number
|
|
|
|
|
filename, lineno = inspectutils.GetFileAndLine(component)
|
|
|
|
|
|
|
|
|
|
# 生成当前component的metadata
|
|
|
|
|
metadata = decorators.GetMetadata(component)
|
|
|
|
|
|
|
|
|
|
# fn是在这个阶段工作中被调用的Callable对象
|
|
|
|
|
fn = component.__call__ if treatment == 'callable' else component
|
|
|
|
|
|
|
|
|
|
# 生成fn的parse function
|
|
|
|
|
parse = _MakeParseFn(fn, metadata)
|
|
|
|
|
|
|
|
|
|
# 把被调用fn的参数解析出来,把args列表变为
|
|
|
|
|
# (varargs, kwargs), remaining_args的形式
|
|
|
|
|
(varargs, kwargs), consumed_args, remaining_args, capacity = parse(args)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
metadata:用以描述属性的数据,在fire中使用一个<属性,值>的字典存储。
|
|
|
|
|
它的生成主要依靠 **getattr()**。 源代码如下:
|
|
|
|
|
```
|
|
|
|
|
def GetMetadata(fn):
|
|
|
|
|
# ...
|
|
|
|
|
metadata = getattr(fn, FIRE_METADATA, default)
|
|
|
|
|
# ...
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
最后,也是最关键的调用部分,非常直接。我们把已经处理好的(varargs, kwargs)传入:
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
if inspectutils.IsCoroutineFunction(fn):
|
|
|
|
|
loop = asyncio.get_event_loop()
|
|
|
|
|
component = loop.run_until_complete(fn(*varargs, **kwargs))
|
|
|
|
|
else:
|
|
|
|
|
component = fn(*varargs, **kwargs)
|
|
|
|
|
```
|