diff --git a/Source_code_learning.md b/Source_code_learning.md index c35ac38..91715bd 100644 --- a/Source_code_learning.md +++ b/Source_code_learning.md @@ -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()实现 \ No newline at end of file +### _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) +``` \ No newline at end of file