Skip to main content
robot中访问者模式

robot中访问者模式

一、访问者模式

在看robotframework源码中总是发现有visit这个单词,而且在整个运行中都是反复出现,所以自己就看了下关于这个访问者的设计模式。其实这个设计模式是非常少见的,我们平时使用中也并不常见,但是既然robot中出现了这个我们就来看一下这个设计模式。因为懂了这个设计模式也会更加方便我们看源码。

访问者模式(Visitor Pattern)是一种行为型设计模式,它能够将算法与对象结构分离,使得算法可以独立于对象结构而变化
该模式的核心概念是,定义一个访问者对象,它是对某个对象结构中各个元素的操作,这种操作可以改变元素的类或状态。
其工作原理是,访问者模式通过定义访问者接口和被访问者接口,将遍历和操作分离开来,从而提高代码的可维护性和可扩展性。


Y-aong...About 3 min源码分析设计模式robotframework源码分析robotframework访问者模式
关键字驱动的思路

关键字驱动的思路

robotframework是一个以关键字驱动的测试框架,我也在编写一个工作流的框架,其中也会用到动态生成关键字方面的需求。我觉得robot中关键字比较好用,是值得我来借鉴的地方,所以我想学习下robot 关键字相关的实现方式。

一、获取关键字

  • KeywordCreator使用library和name创建所用的关键字,并保存到keywords列表中
    • 具体实现需要KeywordCreator调用create方法,这里返回的是关键字library,关键字名称,参数,文档和tag的集合
      • create方法又是使用LibraryKeyword来进行创建的
      • DynamicKeyword作为LibraryKeyword的子类其中一个重要的属性method,这个method实际上就是一个可执行的对象
      • 这个method就是KeywordCreator调用create的返回值

Y-aong...About 5 min源码分析robotframework源码分析robotframework
robot的运行流程

robot的运行流程

一、RobotFrameWork类构造

class Application:

    def __init__(self, usage, name=None, version=None, arg_limits=None, env_options=None, logger=None, **auto_options):
        self._ap = ArgumentParser(usage, name, version, arg_limits, self.validate, env_options, **auto_options)
        self._logger = logger or DefaultLogger()


class RobotFramework(Application):
    def __init__(self):
        super().__init__(USAGE, arg_limits=(1,), env_options='ROBOT_OPTIONS', logger=LOGGER)


Y-aong...About 2 min源码分析robotframework源码分析robotframework
1、localstock到ContextVar

1、localstock到ContextVar

问题引入

当前flask版本为3.0.2,记得之前flask实现线程隔离的时候是使用localstock来实现的,现在再来看源码出现了ContextVar让我感觉比较陌生,接下来我们就来好好看看flask为什么要使用ContextVar。

源码对比

旧版本global.py


Y-aong...About 6 min源码分析flask源码分析flask
2、flask的启动过程

2、flask的启动过程

一、实例化对象的过程

我们需要首先明白一个对象实例化会做那些事情

def cls_instance():
    print('我是类属性')
    return 1


def init_instance():
    print('我是实例属性')
    return 2


class Demo:
    instance = cls_instance()

    def __init__(self):
        self.ini = init_instance()

    def __call__(self, *args, **kwargs):
        print('我是call方法')


app = Demo()
# 我是类属性
# 我是实例属性

Y-aong...About 6 min源码分析flask源码分析flask
3、Flask上下文Contextvars

3、Flask上下文Contextvars

一. 为什么迁移到 contextvars

Python 3.7 引入的 contextvars 模块提供了更灵活的上下文变量管理能力,支持 异步编程更细粒度的上下文绑定。Flask 3.0 的迁移主要基于以下优势:

  • 异步支持contextvars 天生支持异步/协程环境(如 asyncio),而 Werkzeug 的 Local 主要针对多线程。
  • 轻量级:标准库的 contextvars 性能更高,且无需依赖第三方库(如 Werkzeug)。
  • 更清晰的上下文管理:通过 Token 机制可更方便地管理上下文的嵌套和恢复。

Y-aong...About 3 min源码分析flask源码分析flask
4、路由分配,Endpoint

4、路由分配,Endpoint

一、路由

采用比较官方的话来介绍就是

网络原理中,路由指的是根据上一接口的数据包中的IP地址,查询路由表转发到另一个接口,它决定的是一个端到端的网络路径。

web里的话,路由概念也是类似的,根据URL来将请求分配到指定的一个‘端’,另外也可以这样用,在某一个节点设置个转发,将到达这里的每一个’包‘或者说URL重新定向到另一个端并且可以在这个过程中对这个包进行处理。

二、Endpoint

endpoint是flask中提出来的一个概念,我们先下结论就是视图函数和url的中间值,我们可以利用endpoint找到url,也可以使用endpoint找到视图函数。它是为了方便我们通过endpoint找到url,寻找视图函数的值。


Y-aong...About 6 min源码分析flask源码分析flask
5、请求的生命周期

5、请求的生命周期

请求的生命周期这个是比较复杂的我们通过两个方面来进行分析,分别用应用上下文和请求上下文,以及before_request,after_request等处理函数进行分析

源码部分

    def wsgi_app(
        self, environ: WSGIEnvironment, start_response: StartResponse
    ) -> cabc.Iterable[bytes]:
        ctx = self.request_context(environ)
        error: BaseException | None = None
        try:
            try:
                ctx.push()
                response = self.full_dispatch_request()
            except Exception as e:
                error = e
                response = self.handle_exception(e)
            except:  # noqa: B001
                error = sys.exc_info()[1]
                raise
            return response(environ, start_response)
        finally:
            if "werkzeug.debug.preserve_context" in environ:
                environ["werkzeug.debug.preserve_context"](_cv_app.get())
                environ["werkzeug.debug.preserve_context"](_cv_request.get())

            if error is not None and self.should_ignore_error(error):
                error = None

            ctx.pop(error)

Y-aong...About 4 min源码分析flask源码分析flask
6、可自定义的16个扩展点

6、可自定义的16个扩展点

一、自定义扩展点概述

flask是一个极其自由的框架,其实这也是我喜欢这个框架的原因就是我们可以根据自己的需求来自定义框架,这个就像是有一种养成系的感觉,会觉得这个框架越来越好用。

那么既然我们需要更加灵活的使用这个框架,其中框架中一些提供出来的方法我们肯定需要了解,其实flask中的自定义扩展点我们可以分为两类,其中一类是flask的信号机制,还有一类就是一些请求处理函数,包括但是不局限于before_request、after_request等请求处理函数。接下来我们就进入源码来分析flask提供的自定义扩展点。


Y-aong...About 7 min源码分析flask源码分析flask
7、Flask CBV 与 RESTful API

7、Flask CBV 与 RESTful API

我曾经在之前的工作中,使用20行代码实现使用传统视图100多行实现的增删改查的功能。之前使用的是flask_restful,但是这个模块没有swagger文档,还挺说这个模块的负责人是物理层面的找不到了,后面我又接触到flask_restx这个模块,实现了文档自动生成这个很重要的功能。

一、为什么需要 Class-Based Views(CBV)和 RESTful API

1.1 函数视图的局限性

传统的 Flask 函数视图(Function-Based Views)虽然简单,但在复杂场景下存在以下问题:


Y-aong...About 4 min源码分析flask源码分析flaskrestful
2