【pytest框架源碼分析五】pytest插件的注冊流程

前文介紹到pytest整體是運用插件來實現其運行流程的。這里仔細介紹下具體過程。
首先進入main方法

def main(args: list[str] | os.PathLike[str] | None = None,plugins: Sequence[str | _PluggyPlugin] | None = None,
) -> int | ExitCode:"""Perform an in-process test run.:param args:List of command line arguments. If `None` or not given, defaults to readingarguments directly from the process command line (:data:`sys.argv`).:param plugins: List of plugin objects to be auto-registered during initialization.:returns: An exit code."""old_pytest_version = os.environ.get("PYTEST_VERSION")try:os.environ["PYTEST_VERSION"] = __version__try:config = _prepareconfig(args, plugins)except ConftestImportFailure as e:exc_info = ExceptionInfo.from_exception(e.cause)tw = TerminalWriter(sys.stderr)tw.line(f"ImportError while loading conftest '{e.path}'.", red=True)exc_info.traceback = exc_info.traceback.filter(filter_traceback_for_conftest_import_failure)exc_repr = (exc_info.getrepr(style="short", chain=False)if exc_info.tracebackelse exc_info.exconly())formatted_tb = str(exc_repr)for line in formatted_tb.splitlines():tw.line(line.rstrip(), red=True)return ExitCode.USAGE_ERRORelse:try:ret: ExitCode | int = config.hook.pytest_cmdline_main(config=config)try:return ExitCode(ret)except ValueError:return retfinally:config._ensure_unconfigure()except UsageError as e:tw = TerminalWriter(sys.stderr)for msg in e.args:tw.line(f"ERROR: {msg}\n", red=True)return ExitCode.USAGE_ERRORfinally:if old_pytest_version is None:os.environ.pop("PYTEST_VERSION", None)else:os.environ["PYTEST_VERSION"] = old_pytest_version

這個main方法,最重要的有兩步,第一步是
config = _prepareconfig(args, plugins)
這一步就是讀取配置以及注冊插件等動作。這里附下_prepareconfig方法

def _prepareconfig(args: list[str] | os.PathLike[str] | None = None,plugins: Sequence[str | _PluggyPlugin] | None = None,
) -> Config:if args is None:args = sys.argv[1:]elif isinstance(args, os.PathLike):args = [os.fspath(args)]elif not isinstance(args, list):msg = (  # type:ignore[unreachable]"`args` parameter expected to be a list of strings, got: {!r} (type: {})")raise TypeError(msg.format(args, type(args)))config = get_config(args, plugins)pluginmanager = config.pluginmanagertry:if plugins:for plugin in plugins:if isinstance(plugin, str):pluginmanager.consider_pluginarg(plugin)else:pluginmanager.register(plugin)config = pluginmanager.hook.pytest_cmdline_parse(pluginmanager=pluginmanager, args=args)return configexcept BaseException:config._ensure_unconfigure()raise

這里這個方法可以看到,如果有plugin傳入,則會注冊。但是我們知道有些默認的插件是沒有傳入的,也注冊了。其是通過get_config(args, plugins)這個方法來注冊的

def get_config(args: list[str] | None = None,plugins: Sequence[str | _PluggyPlugin] | None = None,
) -> Config:# subsequent calls to main will create a fresh instancepluginmanager = PytestPluginManager()config = Config(pluginmanager,invocation_params=Config.InvocationParams(args=args or (),plugins=plugins,dir=pathlib.Path.cwd(),),)if args is not None:# Handle any "-p no:plugin" args.pluginmanager.consider_preparse(args, exclude_only=True)for spec in default_plugins:pluginmanager.import_plugin(spec)return config

這里初始化pluginmanager時,添加了默認的插件接口類
在這里插入圖片描述
可以看到這個文件里都是插件的接口類,并且都是以pytest_開頭的。
在這里插入圖片描述
注意這里有些方法沒有加@hookspec的裝飾器,但是也添加進去了,這是因為pytest對其做了一層處理。我們知道add hooksepcs時,主要是判斷其有無對應的spec_opts,沒有添加@hooksepc的就沒有sepc_opts。

在這里插入圖片描述
在這里插入圖片描述
對于這種沒有添加@hookspec的方法,pytest重寫了parse_hookspec_opts方法
在這里插入圖片描述
這里可以看到,其先取了下對應的接口方法有無opts參數,如果沒有,則判斷一下方法是否是以pytest_開頭的,如果是,則添加opts參數。所以這里添加了hooksepc.py文件中所有的接口類方法。
然后PytestPluginManager類中self.register(self)注冊了它自己類中的插件,然后運行到get_config方法中的

    for spec in default_plugins:pluginmanager.import_plugin(spec)

這里將default_plugins中的插件也都注冊了,default_plugin如下
在這里插入圖片描述
import_plugin方法如下

   def import_plugin(self, modname: str, consider_entry_points: bool = False) -> None:"""Import a plugin with ``modname``.If ``consider_entry_points`` is True, entry point names are alsoconsidered to find a plugin."""# Most often modname refers to builtin modules, e.g. "pytester",# "terminal" or "capture".  Those plugins are registered under their# basename for historic purposes but must be imported with the# _pytest prefix.assert isinstance(modname, str), f"module name as text required, got {modname!r}"if self.is_blocked(modname) or self.get_plugin(modname) is not None:returnimportspec = "_pytest." + modname if modname in builtin_plugins else modnameself.rewrite_hook.mark_rewrite(importspec)if consider_entry_points:loaded = self.load_setuptools_entrypoints("pytest11", name=modname)if loaded:returntry:__import__(importspec)except ImportError as e:raise ImportError(f'Error importing plugin "{modname}": {e.args[0]}').with_traceback(e.__traceback__) from eexcept Skipped as e:self.skipped_plugins.append((modname, e.msg or ""))else:mod = sys.modules[importspec]self.register(mod, modname)

這里主要就是把default_plugins中提到的文件中的插件實現都注冊了。(注意這里有些接口實現方法也是未加hookimpl裝飾器的,但是也能注冊,同上面添加spec的方法 ,pytest重新實現了parse_hookimpl_opts方法,只要是以pytest_開頭的方法都可以正常注冊)
回到main方法,_prepareconfig這一步就是將配置讀取完,將默認插件注冊完成。
接下來main方法執行到config.hook.pytest_cmdline_main(config=config),這個方法在hookspec中有接口,實現的方法也有多處。
在這里插入圖片描述

對比可以看到這些文件中都有實現,其中mark,setuonly,setupplan中的實現方法都加了@pytest.hookimpl(tryfirst=True),按照之前介紹的原則,后加的先執行,加了tryfirst的先執行,這里的執行順序為setupplan,setuponly,mark,cacheprovider,…中實現的pytest_cmdline_main方法。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/74072.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/74072.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/74072.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

IoTDB日志提示Too many open files

問題 時序數據庫 IoTDB 1.3.3 版本 IoTDB 執行查詢操作失敗,日志打印提示 Too many open files。通過命令查看打開文件數,結果如下: [root0002 DataReceiver]# lsof|grep 28347|wc -l DataNode 55444 [root0002 DataReceiver]# lsof|g…

prometheus 添加alertmanager添加dingtalk機器人告警

1、dingtalk創建機器人,目前我們采用加白名單的方式校驗 2、定位到如下圖 test結果如下

C 語 言 --- 操 作 符 2

C 語 言 --- 操 作 符 2 移 位 操 作 符定 義原 碼 補 碼 和 反 碼左 移&#xff08;<<&#xff09;右 移&#xff08;>>&#xff09;算 術 右 移邏 輯 右 移 按 位 與、按 位 或、和 按 位 異 或按 位 與按 位 或按 位 異 或 邏 輯 反 操 作負 值 操 作按 位 取 反…

基于Spring Boot的公司資產網站的設計與實現(LW+源碼+講解)

專注于大學生項目實戰開發,講解,畢業答疑輔導&#xff0c;歡迎高校老師/同行前輩交流合作?。 技術范圍&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬蟲、數據可視化、安卓app、大數據、物聯網、機器學習等設計與開發。 主要內容&#xff1a;…

零碳工廠能源管理系統的核心技術與應用實踐

零碳工廠能源管理系統是一種高效的解決方案&#xff0c;旨在優化能源使用并減少碳排放&#xff0c;以幫助工廠實現低碳或零碳的生產目標。以下是該系統的詳細構成和功能&#xff1a; 1. 核心組件 傳感器和監測設備&#xff1a;用于實時監測工廠內的能源使用情況&#xff0c;包…

美攝接入DeepSeek等大模型,用多模態融合重構視頻創作新邊界!

今年以來&#xff0c;DeepSeek憑借其強大的深度推理分析能力&#xff0c;在AI領域掀起新的熱潮。美攝科技快速響應市場需求&#xff0c;迅速接入以DeepSeek、通義千問、商湯、文心一言為代表的大模型&#xff0c;為企業視頻創作生產帶來全新體驗。 傳統視頻創作面臨著同質化、…

JAVA————十五萬字匯總

JAVA語言概述 JAVA語句結構 JAVA面向對象程序設計&#xff08;一&#xff09; JAVA面向對象程序設計&#xff08;二&#xff09; JAVA面向對象程序設計&#xff08;三&#xff09;工具類的實現 JAVA面向對象程序設計&#xff08;四&#xff09;錄入異常處理 JAVA圖形用戶界面設…

力扣熱題100(方便自己復習,自用)

力扣熱題100 1. 兩數之和 - 力扣&#xff08;LeetCode&#xff09; 查找兩數之和是不是等于target也就是我們找到一個數之后&#xff0c;用target將其減掉&#xff0c;再尋找應當對應的元素是什么每找到一個數&#xff0c;我們就將其放在集合中&#xff0c;因為集合中可以去重…

【yolo】yolo訓練報錯,以及解決方案

背景&#xff1a; 剛剛&#xff0c;寫了《【yolo】yolo推理報錯&#xff0c;以及解決方案》&#xff0c;馬上訓練就遇到類似的報錯。 我對我標注的圖像進行了300輪的訓練&#xff0c;但是訓練完300輪后&#xff0c;報錯了。。。 報錯信息 300 epochs completed in 0.085 hou…

vscode/cursor中python運行路徑設置 模塊導入問題

vscode/cursor中python運行路徑設置 ## 文件路徑設置 問題描述 pycharm的項目用cursor運行&#xff0c;出現目錄找不到 后來利用 os.getcwd()&#xff0c;經過打印調試發現是IDE的本身配置問題 pycharm中&#xff0c;os.getcwd()默認打開當前腳本所在目錄 vscode/cursor中…

理解線性動力學中的模態疊加法

線性動力學中的模態疊加方法 模態疊加法是線性動力學中一種有價值的工具&#xff0c;可以有效地確定頻域或時域中的系統響應。對于某些類型的線性動力學分析&#xff0c;有必要使用此方法&#xff0c;因此了解該過程對于獲得準確的結果至關重要。在本博客中&#xff0c;我們將…

報錯 - redis - Unit redis.service could not be found.

報錯&#xff1a; Unit redis.service could not be found.Could not connect to Redis at 127.0.0.1:6379: Connection refused解決方法&#xff1a; 檢查狀態、有必要的話 重新安裝 Linux 上查看狀態 systemctl status redis顯示以下內容&#xff0c;代表正常服務 出現下面…

CMS網站模板定制設計與安全評估

內容概要 現代CMS&#xff08;內容管理系統&#xff09;作為網站建設的核心載體&#xff0c;其模板架構與安全防護體系的協同設計已成為企業數字化轉型的關鍵環節。隨著網絡攻擊向量日益復雜化&#xff0c;基于HTTPS協議的端到端加密部署不僅成為基礎安全配置&#xff0c;更直…

【React】useEffect、useLayoutEffect底層機制

目錄 useEffect不設置依賴設置空數組&#xff0c;無依賴設置多個依賴返回值是一個函數總結useEffect的使用環境useEffect 中發送請求錯誤示例用.then獲取數據在useEffect創建一個函數 總結 useLayoutEffectuseLayoutEffect 和useEffect區別執行時機&#xff1a;瀏覽器渲染的關系…

深度解析學術論文成果評估(Artifact Evaluation):從歷史到現狀

深度解析學術論文成果評估(Artifact Evaluation)&#xff1a;從歷史到現狀 引言 在計算機科學和工程領域的學術研究中&#xff0c;可重復性和可驗證性越來越受到重視。隨著實驗性研究的復雜性不斷增加&#xff0c;確保研究成果可以被其他研究者驗證和構建變得尤為重要。這一需…

VSCode創建VUE項目(四)增加用戶Session管理

將用戶信息存儲或者更新到Session sessionStorage.setItem("userID",loginform.value.username); sessionStorage.setItem(loginTime, Date.now()); 獲取Session信息 const storedUserInfo sessionStorage.getItem(userID); const loginTime sessionStorage.get…

威聯通 后臺可用命令查看Bash

一、查看所有可用命令的方法 列出所有外部命令&#xff08;二進制文件&#xff09; 外部命令通常存放在系統路徑&#xff08;如 /bin, /usr/bin, /sbin, /usr/sbin&#xff09;中&#xff1a; bash ls /bin /usr/bin /sbin /usr/sbin # 直接列出命令目錄&#xff08;結果較長&…

游戲MOD伴隨盜號風險,仿冒網站借“風靈月影”竊密【火絨企業版V2.0】

游戲MOD&#xff08;即游戲修改器&#xff09;是一種能夠對游戲進行修改或增強的程序&#xff0c;因其能夠提升游戲體驗&#xff0c;在玩家群體中擁有一定的市場。然而&#xff0c;這類程序大多由第三方開發者制作&#xff0c;容易缺乏完善的安全保障機制&#xff0c;這就為不法…

Kubernetes Init 容器:實現 Nginx 和 PHP 對 MySQL 的依賴檢查

在設計 Kubernetes Pod 時&#xff0c;如果需要在啟動 Nginx 和 PHP 之前等待 MySQL 啟動完成&#xff0c;可以通過 初始化容器&#xff08;initC&#xff09; 來實現。初始化容器可以用于檢查 MySQL 是否可用&#xff0c;只有在 MySQL 可用后&#xff0c;才會繼續啟動主容器&a…

SSL/TLS 和 SSH 介紹以及他們的區別

目錄 SSL/TLS SSL/TLS工作原理的核心步驟握手階段&#xff08;Handshake Protocol&#xff09;加密通信階段&#xff08;Encrypted Communication Phase&#xff09;會話恢復&#xff08;Session Resumption&#xff09; SSH SSH 加密機制的核心步驟 SSH 和 SSL 區別 SSL/TLS …