commit 0fc08732f13c3b5adc3c0c3f08d6943da6865cea Author: chenjunyi <314298729@qq.com> Date: Wed Jan 28 16:57:46 2026 +0800 v0.19 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9e4d72a --- /dev/null +++ b/.gitignore @@ -0,0 +1,163 @@ +# ---> Python +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +output +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ + diff --git a/.pylintrc b/.pylintrc new file mode 100644 index 0000000..e749d6b --- /dev/null +++ b/.pylintrc @@ -0,0 +1 @@ +extension-pkg-whitelist=PyQt5 \ No newline at end of file diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..d20cc2b --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.8.10 diff --git a/GUI.ui b/GUI.ui new file mode 100644 index 0000000..0943cfe --- /dev/null +++ b/GUI.ui @@ -0,0 +1,790 @@ + + + MainWindow + + + + 0 + 0 + 826 + 619 + + + + MainWindow + + + + + + + + + + 微软雅黑 + 10 + 50 + false + + + + 3 + + + + 文档生产工具 + + + + + + + + + 微软雅黑 + 10 + 50 + false + + + + 大纲转说明-鉴定模板 + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + false + + + + + + 选择大纲文档 + + + + + + + + + 设计人员: + + + + + + + + + + + + 测试记录转说明 + + + + + + + 开始转换 + + + + + + + + + + + 微软雅黑 + 10 + 50 + false + + + + 追踪关系填写 + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + false + + + + + + 选择文件 + + + + + + + 大纲追踪关系填写(依据大纲文件) + + + + + + + 测试说明追踪填写(依据说明文件) + + + + + + + 测试报告追踪填写(依据记录文件) + + + + + + + + + + + 微软雅黑 + 10 + 50 + false + + + + 根据说明生成测试记录 + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + false + + + + + + 选择文件 + + + + + + + + + 测试人员: + + + Qt::AutoText + + + Qt::AlignCenter + + + + + + + + + + + + + + 监测人员: + + + Qt::AutoText + + + Qt::AlignCenter + + + + + + + + + + + + + + 测试时间: + + + Qt::AutoText + + + Qt::AlignCenter + + + + + + + + + + + + + + 说明生成记录 + + + + + + + 记录反向生成说明 + + + + + + + + + + + + + + + 文档小工具 + + + + + + + + + 微软雅黑 + 10 + 50 + false + + + + UAS单元测试转换 + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + false + + + + + + + + 被测软件名: + + + + + + + + + + 被测软件标识: + + + + + + + + + + 请选择SAU报告文档 + + + + + + + 开始转换 + + + + + + + + + + + + + 微软雅黑 + 10 + 50 + false + + + + 自动填充 + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + false + + + + + + + + 选择文档 + + + + + + + + + 单元格左侧: + + + + + + + + + + + + + + 填充的内容: + + + + + + + + + + + + + + 填充的数量: + + + + + + + + + + + + + + 清空单元格 + + + + + + + 填充 + + + + + + + + + + + + + + + 微软雅黑 + 10 + 50 + false + + + + 提取单元格标题右侧的单元格内容 + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + false + + + + + + + + 选择文档 + + + + + + + + + 单元格标题: + + + + + + + + + + + + + + 单元格标题: + + + + + + + + + + + + + + 单元格标题: + + + + + + + + + + + + 点击提取 + + + + + + + + + + + + + + + 报告生成工具 + + + + + 5 + 5 + 161 + 211 + + + + 部件测试表格 + + + + + + 选择UAS文件 + + + + + + + 点击生成 + + + + + + + + + FPGA工具 + + + + + 5 + 5 + 246 + 211 + + + + FPGA记录自动填写 + + + + + + 选择FPGA记录文件 + + + + + + + + + + + 测试时间 + + + + + + + + + + + + + + 测试人员 + + + + + + + + + + + + + + 监测人员 + + + + + + + + + + + + + + 项目编号 + + + + + + + + + + + + + + 自动填写开始 + + + + + + + + + 255 + 5 + 191 + 211 + + + + FPGA记录转说明 + + + + + + 请选择完整FPGA记录文件 + + + + + + + + + 设计人员 + + + + + + + + + + + + 点击生成说明 + + + + + + + + + + + + + + + + + Qt::Horizontal + + + + 618 + 20 + + + + + + + + 清空消息 + + + + + + + 显示帮助 + + + + + + + + + + 0 + 0 + + + + 0 + + + + + + + + + + + 0 + 0 + 826 + 22 + + + + + 文件 + + + + + + + + 工具 + + + + + + + + + + + 打开文件 + + + + + close + + + + + 关于工具 + + + + + 退出 + + + + + IEEE转换工具 + + + + + + diff --git a/Icon.png b/Icon.png new file mode 100644 index 0000000..81564da Binary files /dev/null and b/Icon.png differ diff --git a/README.md b/README.md new file mode 100644 index 0000000..9d52199 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# newToolforTest +一个使用QT框架写的脚本工具集合,已弃用 \ No newline at end of file diff --git a/Ui_GUI.py b/Ui_GUI.py new file mode 100644 index 0000000..ef6977d --- /dev/null +++ b/Ui_GUI.py @@ -0,0 +1,510 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'GUI.ui' +# +# Created by: PyQt5 UI code generator 5.15.4 +# +# WARNING: Any manual changes made to this file will be lost when pyuic5 is +# run again. Do not edit this file unless you know what you are doing. + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_MainWindow(object): + def setupUi(self, MainWindow): + MainWindow.setObjectName("MainWindow") + MainWindow.resize(826, 619) + self.centralwidget = QtWidgets.QWidget(MainWindow) + self.centralwidget.setObjectName("centralwidget") + self.verticalLayout_8 = QtWidgets.QVBoxLayout(self.centralwidget) + self.verticalLayout_8.setObjectName("verticalLayout_8") + self.verticalLayout_7 = QtWidgets.QVBoxLayout() + self.verticalLayout_7.setObjectName("verticalLayout_7") + self.tabWidget = QtWidgets.QTabWidget(self.centralwidget) + font = QtGui.QFont() + font.setFamily("微软雅黑") + font.setPointSize(10) + font.setBold(False) + font.setWeight(50) + self.tabWidget.setFont(font) + self.tabWidget.setObjectName("tabWidget") + self.tab = QtWidgets.QWidget() + self.tab.setObjectName("tab") + self.gridLayout = QtWidgets.QGridLayout(self.tab) + self.gridLayout.setObjectName("gridLayout") + self.horizontalLayout_15 = QtWidgets.QHBoxLayout() + self.horizontalLayout_15.setObjectName("horizontalLayout_15") + self.groupBox = QtWidgets.QGroupBox(self.tab) + font = QtGui.QFont() + font.setFamily("微软雅黑") + font.setPointSize(10) + font.setBold(False) + font.setWeight(50) + self.groupBox.setFont(font) + self.groupBox.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) + self.groupBox.setFlat(False) + self.groupBox.setObjectName("groupBox") + self.verticalLayout = QtWidgets.QVBoxLayout(self.groupBox) + self.verticalLayout.setObjectName("verticalLayout") + self.pushButton = QtWidgets.QPushButton(self.groupBox) + self.pushButton.setObjectName("pushButton") + self.verticalLayout.addWidget(self.pushButton) + self.horizontalLayout = QtWidgets.QHBoxLayout() + self.horizontalLayout.setObjectName("horizontalLayout") + self.label = QtWidgets.QLabel(self.groupBox) + self.label.setObjectName("label") + self.horizontalLayout.addWidget(self.label) + self.lineEdit = QtWidgets.QLineEdit(self.groupBox) + self.lineEdit.setObjectName("lineEdit") + self.horizontalLayout.addWidget(self.lineEdit) + self.verticalLayout.addLayout(self.horizontalLayout) + self.pushButton_3 = QtWidgets.QPushButton(self.groupBox) + self.pushButton_3.setObjectName("pushButton_3") + self.verticalLayout.addWidget(self.pushButton_3) + self.pushButton_2 = QtWidgets.QPushButton(self.groupBox) + self.pushButton_2.setObjectName("pushButton_2") + self.verticalLayout.addWidget(self.pushButton_2) + self.horizontalLayout_15.addWidget(self.groupBox) + self.groupBox_2 = QtWidgets.QGroupBox(self.tab) + font = QtGui.QFont() + font.setFamily("微软雅黑") + font.setPointSize(10) + font.setBold(False) + font.setWeight(50) + self.groupBox_2.setFont(font) + self.groupBox_2.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) + self.groupBox_2.setFlat(False) + self.groupBox_2.setObjectName("groupBox_2") + self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.groupBox_2) + self.verticalLayout_2.setObjectName("verticalLayout_2") + self.pushButton_4 = QtWidgets.QPushButton(self.groupBox_2) + self.pushButton_4.setObjectName("pushButton_4") + self.verticalLayout_2.addWidget(self.pushButton_4) + self.pushButton_6 = QtWidgets.QPushButton(self.groupBox_2) + self.pushButton_6.setObjectName("pushButton_6") + self.verticalLayout_2.addWidget(self.pushButton_6) + self.pushButton_5 = QtWidgets.QPushButton(self.groupBox_2) + self.pushButton_5.setObjectName("pushButton_5") + self.verticalLayout_2.addWidget(self.pushButton_5) + self.pushButton_18 = QtWidgets.QPushButton(self.groupBox_2) + self.pushButton_18.setObjectName("pushButton_18") + self.verticalLayout_2.addWidget(self.pushButton_18) + self.horizontalLayout_15.addWidget(self.groupBox_2) + self.groupBox_4 = QtWidgets.QGroupBox(self.tab) + font = QtGui.QFont() + font.setFamily("微软雅黑") + font.setPointSize(10) + font.setBold(False) + font.setWeight(50) + self.groupBox_4.setFont(font) + self.groupBox_4.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) + self.groupBox_4.setFlat(False) + self.groupBox_4.setObjectName("groupBox_4") + self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.groupBox_4) + self.verticalLayout_4.setObjectName("verticalLayout_4") + self.pushButton_11 = QtWidgets.QPushButton(self.groupBox_4) + self.pushButton_11.setObjectName("pushButton_11") + self.verticalLayout_4.addWidget(self.pushButton_11) + self.horizontalLayout_2 = QtWidgets.QHBoxLayout() + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.label_4 = QtWidgets.QLabel(self.groupBox_4) + self.label_4.setTextFormat(QtCore.Qt.AutoText) + self.label_4.setAlignment(QtCore.Qt.AlignCenter) + self.label_4.setObjectName("label_4") + self.horizontalLayout_2.addWidget(self.label_4) + self.lineEdit_4 = QtWidgets.QLineEdit(self.groupBox_4) + self.lineEdit_4.setObjectName("lineEdit_4") + self.horizontalLayout_2.addWidget(self.lineEdit_4) + self.verticalLayout_4.addLayout(self.horizontalLayout_2) + self.horizontalLayout_3 = QtWidgets.QHBoxLayout() + self.horizontalLayout_3.setObjectName("horizontalLayout_3") + self.label_5 = QtWidgets.QLabel(self.groupBox_4) + self.label_5.setTextFormat(QtCore.Qt.AutoText) + self.label_5.setAlignment(QtCore.Qt.AlignCenter) + self.label_5.setObjectName("label_5") + self.horizontalLayout_3.addWidget(self.label_5) + self.lineEdit_5 = QtWidgets.QLineEdit(self.groupBox_4) + self.lineEdit_5.setObjectName("lineEdit_5") + self.horizontalLayout_3.addWidget(self.lineEdit_5) + self.verticalLayout_4.addLayout(self.horizontalLayout_3) + self.horizontalLayout_4 = QtWidgets.QHBoxLayout() + self.horizontalLayout_4.setObjectName("horizontalLayout_4") + self.label_6 = QtWidgets.QLabel(self.groupBox_4) + self.label_6.setTextFormat(QtCore.Qt.AutoText) + self.label_6.setAlignment(QtCore.Qt.AlignCenter) + self.label_6.setObjectName("label_6") + self.horizontalLayout_4.addWidget(self.label_6) + self.lineEdit_6 = QtWidgets.QLineEdit(self.groupBox_4) + self.lineEdit_6.setObjectName("lineEdit_6") + self.horizontalLayout_4.addWidget(self.lineEdit_6) + self.verticalLayout_4.addLayout(self.horizontalLayout_4) + self.horizontalLayout_5 = QtWidgets.QHBoxLayout() + self.horizontalLayout_5.setObjectName("horizontalLayout_5") + self.pushButton_12 = QtWidgets.QPushButton(self.groupBox_4) + self.pushButton_12.setObjectName("pushButton_12") + self.horizontalLayout_5.addWidget(self.pushButton_12) + self.pushButton_13 = QtWidgets.QPushButton(self.groupBox_4) + self.pushButton_13.setObjectName("pushButton_13") + self.horizontalLayout_5.addWidget(self.pushButton_13) + self.verticalLayout_4.addLayout(self.horizontalLayout_5) + self.horizontalLayout_15.addWidget(self.groupBox_4) + self.gridLayout.addLayout(self.horizontalLayout_15, 0, 0, 1, 1) + self.tabWidget.addTab(self.tab, "") + self.tab_2 = QtWidgets.QWidget() + self.tab_2.setObjectName("tab_2") + self.verticalLayout_12 = QtWidgets.QVBoxLayout(self.tab_2) + self.verticalLayout_12.setObjectName("verticalLayout_12") + self.horizontalLayout_13 = QtWidgets.QHBoxLayout() + self.horizontalLayout_13.setObjectName("horizontalLayout_13") + self.groupBox_3 = QtWidgets.QGroupBox(self.tab_2) + font = QtGui.QFont() + font.setFamily("微软雅黑") + font.setPointSize(10) + font.setBold(False) + font.setWeight(50) + self.groupBox_3.setFont(font) + self.groupBox_3.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) + self.groupBox_3.setFlat(False) + self.groupBox_3.setObjectName("groupBox_3") + self.verticalLayout_9 = QtWidgets.QVBoxLayout(self.groupBox_3) + self.verticalLayout_9.setObjectName("verticalLayout_9") + self.verticalLayout_3 = QtWidgets.QVBoxLayout() + self.verticalLayout_3.setObjectName("verticalLayout_3") + self.label_2 = QtWidgets.QLabel(self.groupBox_3) + self.label_2.setObjectName("label_2") + self.verticalLayout_3.addWidget(self.label_2) + self.lineEdit_2 = QtWidgets.QLineEdit(self.groupBox_3) + self.lineEdit_2.setObjectName("lineEdit_2") + self.verticalLayout_3.addWidget(self.lineEdit_2) + self.label_3 = QtWidgets.QLabel(self.groupBox_3) + self.label_3.setObjectName("label_3") + self.verticalLayout_3.addWidget(self.label_3) + self.lineEdit_3 = QtWidgets.QLineEdit(self.groupBox_3) + self.lineEdit_3.setObjectName("lineEdit_3") + self.verticalLayout_3.addWidget(self.lineEdit_3) + self.pushButton_7 = QtWidgets.QPushButton(self.groupBox_3) + self.pushButton_7.setObjectName("pushButton_7") + self.verticalLayout_3.addWidget(self.pushButton_7) + self.pushButton_8 = QtWidgets.QPushButton(self.groupBox_3) + self.pushButton_8.setObjectName("pushButton_8") + self.verticalLayout_3.addWidget(self.pushButton_8) + self.verticalLayout_9.addLayout(self.verticalLayout_3) + self.horizontalLayout_13.addWidget(self.groupBox_3) + self.groupBox_5 = QtWidgets.QGroupBox(self.tab_2) + font = QtGui.QFont() + font.setFamily("微软雅黑") + font.setPointSize(10) + font.setBold(False) + font.setWeight(50) + self.groupBox_5.setFont(font) + self.groupBox_5.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) + self.groupBox_5.setFlat(False) + self.groupBox_5.setObjectName("groupBox_5") + self.verticalLayout_10 = QtWidgets.QVBoxLayout(self.groupBox_5) + self.verticalLayout_10.setObjectName("verticalLayout_10") + self.verticalLayout_5 = QtWidgets.QVBoxLayout() + self.verticalLayout_5.setObjectName("verticalLayout_5") + self.pushButton_16 = QtWidgets.QPushButton(self.groupBox_5) + self.pushButton_16.setObjectName("pushButton_16") + self.verticalLayout_5.addWidget(self.pushButton_16) + self.horizontalLayout_6 = QtWidgets.QHBoxLayout() + self.horizontalLayout_6.setObjectName("horizontalLayout_6") + self.label_7 = QtWidgets.QLabel(self.groupBox_5) + self.label_7.setObjectName("label_7") + self.horizontalLayout_6.addWidget(self.label_7) + self.lineEdit_9 = QtWidgets.QLineEdit(self.groupBox_5) + self.lineEdit_9.setObjectName("lineEdit_9") + self.horizontalLayout_6.addWidget(self.lineEdit_9) + self.verticalLayout_5.addLayout(self.horizontalLayout_6) + self.horizontalLayout_7 = QtWidgets.QHBoxLayout() + self.horizontalLayout_7.setObjectName("horizontalLayout_7") + self.label_9 = QtWidgets.QLabel(self.groupBox_5) + self.label_9.setObjectName("label_9") + self.horizontalLayout_7.addWidget(self.label_9) + self.lineEdit_10 = QtWidgets.QLineEdit(self.groupBox_5) + self.lineEdit_10.setObjectName("lineEdit_10") + self.horizontalLayout_7.addWidget(self.lineEdit_10) + self.verticalLayout_5.addLayout(self.horizontalLayout_7) + self.horizontalLayout_8 = QtWidgets.QHBoxLayout() + self.horizontalLayout_8.setObjectName("horizontalLayout_8") + self.label_10 = QtWidgets.QLabel(self.groupBox_5) + self.label_10.setObjectName("label_10") + self.horizontalLayout_8.addWidget(self.label_10) + self.lineEdit_11 = QtWidgets.QLineEdit(self.groupBox_5) + self.lineEdit_11.setObjectName("lineEdit_11") + self.horizontalLayout_8.addWidget(self.lineEdit_11) + self.verticalLayout_5.addLayout(self.horizontalLayout_8) + self.horizontalLayout_9 = QtWidgets.QHBoxLayout() + self.horizontalLayout_9.setObjectName("horizontalLayout_9") + self.pushButton_14 = QtWidgets.QPushButton(self.groupBox_5) + self.pushButton_14.setObjectName("pushButton_14") + self.horizontalLayout_9.addWidget(self.pushButton_14) + self.pushButton_15 = QtWidgets.QPushButton(self.groupBox_5) + self.pushButton_15.setObjectName("pushButton_15") + self.horizontalLayout_9.addWidget(self.pushButton_15) + self.verticalLayout_5.addLayout(self.horizontalLayout_9) + self.verticalLayout_10.addLayout(self.verticalLayout_5) + self.horizontalLayout_13.addWidget(self.groupBox_5) + self.groupBox_6 = QtWidgets.QGroupBox(self.tab_2) + font = QtGui.QFont() + font.setFamily("微软雅黑") + font.setPointSize(10) + font.setBold(False) + font.setWeight(50) + self.groupBox_6.setFont(font) + self.groupBox_6.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) + self.groupBox_6.setFlat(False) + self.groupBox_6.setObjectName("groupBox_6") + self.verticalLayout_11 = QtWidgets.QVBoxLayout(self.groupBox_6) + self.verticalLayout_11.setObjectName("verticalLayout_11") + self.verticalLayout_6 = QtWidgets.QVBoxLayout() + self.verticalLayout_6.setObjectName("verticalLayout_6") + self.pushButton_17 = QtWidgets.QPushButton(self.groupBox_6) + self.pushButton_17.setObjectName("pushButton_17") + self.verticalLayout_6.addWidget(self.pushButton_17) + self.horizontalLayout_10 = QtWidgets.QHBoxLayout() + self.horizontalLayout_10.setObjectName("horizontalLayout_10") + self.label_8 = QtWidgets.QLabel(self.groupBox_6) + self.label_8.setObjectName("label_8") + self.horizontalLayout_10.addWidget(self.label_8) + self.lineEdit_12 = QtWidgets.QLineEdit(self.groupBox_6) + self.lineEdit_12.setObjectName("lineEdit_12") + self.horizontalLayout_10.addWidget(self.lineEdit_12) + self.verticalLayout_6.addLayout(self.horizontalLayout_10) + self.horizontalLayout_11 = QtWidgets.QHBoxLayout() + self.horizontalLayout_11.setObjectName("horizontalLayout_11") + self.label_11 = QtWidgets.QLabel(self.groupBox_6) + self.label_11.setObjectName("label_11") + self.horizontalLayout_11.addWidget(self.label_11) + self.lineEdit_13 = QtWidgets.QLineEdit(self.groupBox_6) + self.lineEdit_13.setObjectName("lineEdit_13") + self.horizontalLayout_11.addWidget(self.lineEdit_13) + self.verticalLayout_6.addLayout(self.horizontalLayout_11) + self.horizontalLayout_12 = QtWidgets.QHBoxLayout() + self.horizontalLayout_12.setObjectName("horizontalLayout_12") + self.label_12 = QtWidgets.QLabel(self.groupBox_6) + self.label_12.setObjectName("label_12") + self.horizontalLayout_12.addWidget(self.label_12) + self.lineEdit_14 = QtWidgets.QLineEdit(self.groupBox_6) + self.lineEdit_14.setObjectName("lineEdit_14") + self.horizontalLayout_12.addWidget(self.lineEdit_14) + self.verticalLayout_6.addLayout(self.horizontalLayout_12) + self.pushButton_19 = QtWidgets.QPushButton(self.groupBox_6) + self.pushButton_19.setObjectName("pushButton_19") + self.verticalLayout_6.addWidget(self.pushButton_19) + self.verticalLayout_11.addLayout(self.verticalLayout_6) + self.horizontalLayout_13.addWidget(self.groupBox_6) + self.verticalLayout_12.addLayout(self.horizontalLayout_13) + self.tabWidget.addTab(self.tab_2, "") + self.tab_3 = QtWidgets.QWidget() + self.tab_3.setObjectName("tab_3") + self.groupBox_10 = QtWidgets.QGroupBox(self.tab_3) + self.groupBox_10.setGeometry(QtCore.QRect(5, 5, 161, 211)) + self.groupBox_10.setObjectName("groupBox_10") + self.verticalLayout_19 = QtWidgets.QVBoxLayout(self.groupBox_10) + self.verticalLayout_19.setObjectName("verticalLayout_19") + self.pushButton_27 = QtWidgets.QPushButton(self.groupBox_10) + self.pushButton_27.setObjectName("pushButton_27") + self.verticalLayout_19.addWidget(self.pushButton_27) + self.pushButton_28 = QtWidgets.QPushButton(self.groupBox_10) + self.pushButton_28.setObjectName("pushButton_28") + self.verticalLayout_19.addWidget(self.pushButton_28) + self.tabWidget.addTab(self.tab_3, "") + self.tab_4 = QtWidgets.QWidget() + self.tab_4.setObjectName("tab_4") + self.groupBox_11 = QtWidgets.QGroupBox(self.tab_4) + self.groupBox_11.setGeometry(QtCore.QRect(5, 5, 246, 211)) + self.groupBox_11.setObjectName("groupBox_11") + self.verticalLayout_20 = QtWidgets.QVBoxLayout(self.groupBox_11) + self.verticalLayout_20.setObjectName("verticalLayout_20") + self.pushButton_29 = QtWidgets.QPushButton(self.groupBox_11) + self.pushButton_29.setObjectName("pushButton_29") + self.verticalLayout_20.addWidget(self.pushButton_29) + self.verticalLayout_13 = QtWidgets.QVBoxLayout() + self.verticalLayout_13.setObjectName("verticalLayout_13") + self.horizontalLayout_16 = QtWidgets.QHBoxLayout() + self.horizontalLayout_16.setObjectName("horizontalLayout_16") + self.label_13 = QtWidgets.QLabel(self.groupBox_11) + self.label_13.setObjectName("label_13") + self.horizontalLayout_16.addWidget(self.label_13) + self.lineEdit_7 = QtWidgets.QLineEdit(self.groupBox_11) + self.lineEdit_7.setObjectName("lineEdit_7") + self.horizontalLayout_16.addWidget(self.lineEdit_7) + self.verticalLayout_13.addLayout(self.horizontalLayout_16) + self.horizontalLayout_17 = QtWidgets.QHBoxLayout() + self.horizontalLayout_17.setObjectName("horizontalLayout_17") + self.label_14 = QtWidgets.QLabel(self.groupBox_11) + self.label_14.setObjectName("label_14") + self.horizontalLayout_17.addWidget(self.label_14) + self.lineEdit_8 = QtWidgets.QLineEdit(self.groupBox_11) + self.lineEdit_8.setObjectName("lineEdit_8") + self.horizontalLayout_17.addWidget(self.lineEdit_8) + self.verticalLayout_13.addLayout(self.horizontalLayout_17) + self.horizontalLayout_18 = QtWidgets.QHBoxLayout() + self.horizontalLayout_18.setObjectName("horizontalLayout_18") + self.label_15 = QtWidgets.QLabel(self.groupBox_11) + self.label_15.setObjectName("label_15") + self.horizontalLayout_18.addWidget(self.label_15) + self.lineEdit_15 = QtWidgets.QLineEdit(self.groupBox_11) + self.lineEdit_15.setObjectName("lineEdit_15") + self.horizontalLayout_18.addWidget(self.lineEdit_15) + self.verticalLayout_13.addLayout(self.horizontalLayout_18) + self.horizontalLayout_19 = QtWidgets.QHBoxLayout() + self.horizontalLayout_19.setObjectName("horizontalLayout_19") + self.label_16 = QtWidgets.QLabel(self.groupBox_11) + self.label_16.setObjectName("label_16") + self.horizontalLayout_19.addWidget(self.label_16) + self.lineEdit_16 = QtWidgets.QLineEdit(self.groupBox_11) + self.lineEdit_16.setObjectName("lineEdit_16") + self.horizontalLayout_19.addWidget(self.lineEdit_16) + self.verticalLayout_13.addLayout(self.horizontalLayout_19) + self.verticalLayout_20.addLayout(self.verticalLayout_13) + self.pushButton_30 = QtWidgets.QPushButton(self.groupBox_11) + self.pushButton_30.setObjectName("pushButton_30") + self.verticalLayout_20.addWidget(self.pushButton_30) + self.groupBox_12 = QtWidgets.QGroupBox(self.tab_4) + self.groupBox_12.setGeometry(QtCore.QRect(255, 5, 191, 211)) + self.groupBox_12.setObjectName("groupBox_12") + self.verticalLayout_21 = QtWidgets.QVBoxLayout(self.groupBox_12) + self.verticalLayout_21.setObjectName("verticalLayout_21") + self.pushButton_31 = QtWidgets.QPushButton(self.groupBox_12) + self.pushButton_31.setObjectName("pushButton_31") + self.verticalLayout_21.addWidget(self.pushButton_31) + self.horizontalLayout_20 = QtWidgets.QHBoxLayout() + self.horizontalLayout_20.setObjectName("horizontalLayout_20") + self.label_17 = QtWidgets.QLabel(self.groupBox_12) + self.label_17.setObjectName("label_17") + self.horizontalLayout_20.addWidget(self.label_17) + self.lineEdit_17 = QtWidgets.QLineEdit(self.groupBox_12) + self.lineEdit_17.setObjectName("lineEdit_17") + self.horizontalLayout_20.addWidget(self.lineEdit_17) + self.verticalLayout_21.addLayout(self.horizontalLayout_20) + self.pushButton_32 = QtWidgets.QPushButton(self.groupBox_12) + self.pushButton_32.setObjectName("pushButton_32") + self.verticalLayout_21.addWidget(self.pushButton_32) + self.tabWidget.addTab(self.tab_4, "") + self.verticalLayout_7.addWidget(self.tabWidget) + self.textBrowser = QtWidgets.QTextBrowser(self.centralwidget) + self.textBrowser.setObjectName("textBrowser") + self.verticalLayout_7.addWidget(self.textBrowser) + self.horizontalLayout_14 = QtWidgets.QHBoxLayout() + self.horizontalLayout_14.setObjectName("horizontalLayout_14") + spacerItem = QtWidgets.QSpacerItem(618, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout_14.addItem(spacerItem) + self.pushButton_9 = QtWidgets.QPushButton(self.centralwidget) + self.pushButton_9.setObjectName("pushButton_9") + self.horizontalLayout_14.addWidget(self.pushButton_9) + self.pushButton_10 = QtWidgets.QPushButton(self.centralwidget) + self.pushButton_10.setObjectName("pushButton_10") + self.horizontalLayout_14.addWidget(self.pushButton_10) + self.verticalLayout_7.addLayout(self.horizontalLayout_14) + self.progressBar = QtWidgets.QProgressBar(self.centralwidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.progressBar.sizePolicy().hasHeightForWidth()) + self.progressBar.setSizePolicy(sizePolicy) + self.progressBar.setProperty("value", 0) + self.progressBar.setObjectName("progressBar") + self.verticalLayout_7.addWidget(self.progressBar) + self.verticalLayout_8.addLayout(self.verticalLayout_7) + MainWindow.setCentralWidget(self.centralwidget) + self.menubar = QtWidgets.QMenuBar(MainWindow) + self.menubar.setGeometry(QtCore.QRect(0, 0, 826, 22)) + self.menubar.setObjectName("menubar") + self.menu = QtWidgets.QMenu(self.menubar) + self.menu.setObjectName("menu") + self.menu_2 = QtWidgets.QMenu(self.menubar) + self.menu_2.setObjectName("menu_2") + MainWindow.setMenuBar(self.menubar) + self.statusbar = QtWidgets.QStatusBar(MainWindow) + self.statusbar.setObjectName("statusbar") + MainWindow.setStatusBar(self.statusbar) + self.actionopen = QtWidgets.QAction(MainWindow) + self.actionopen.setObjectName("actionopen") + self.actionclose = QtWidgets.QAction(MainWindow) + self.actionclose.setObjectName("actionclose") + self.actionAbout = QtWidgets.QAction(MainWindow) + self.actionAbout.setObjectName("actionAbout") + self.action_3 = QtWidgets.QAction(MainWindow) + self.action_3.setObjectName("action_3") + self.actionIEEE754 = QtWidgets.QAction(MainWindow) + self.actionIEEE754.setObjectName("actionIEEE754") + self.menu.addAction(self.actionopen) + self.menu.addSeparator() + self.menu.addAction(self.action_3) + self.menu_2.addAction(self.actionAbout) + self.menu_2.addAction(self.actionIEEE754) + self.menubar.addAction(self.menu.menuAction()) + self.menubar.addAction(self.menu_2.menuAction()) + + self.retranslateUi(MainWindow) + self.tabWidget.setCurrentIndex(3) + QtCore.QMetaObject.connectSlotsByName(MainWindow) + + def retranslateUi(self, MainWindow): + _translate = QtCore.QCoreApplication.translate + MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) + self.groupBox.setTitle(_translate("MainWindow", "大纲转说明-鉴定模板")) + self.pushButton.setText(_translate("MainWindow", "选择大纲文档")) + self.label.setText(_translate("MainWindow", "设计人员:")) + self.pushButton_3.setText(_translate("MainWindow", "测试记录转说明")) + self.pushButton_2.setText(_translate("MainWindow", "开始转换")) + self.groupBox_2.setTitle(_translate("MainWindow", "追踪关系填写")) + self.pushButton_4.setText(_translate("MainWindow", "选择文件")) + self.pushButton_6.setText(_translate("MainWindow", "大纲追踪关系填写(依据大纲文件)")) + self.pushButton_5.setText(_translate("MainWindow", "测试说明追踪填写(依据说明文件)")) + self.pushButton_18.setText(_translate("MainWindow", "测试报告追踪填写(依据记录文件)")) + self.groupBox_4.setTitle(_translate("MainWindow", "根据说明生成测试记录")) + self.pushButton_11.setText(_translate("MainWindow", "选择文件")) + self.label_4.setText(_translate("MainWindow", "测试人员:")) + self.label_5.setText(_translate("MainWindow", "监测人员:")) + self.label_6.setText(_translate("MainWindow", "测试时间:")) + self.pushButton_12.setText(_translate("MainWindow", "说明生成记录")) + self.pushButton_13.setText(_translate("MainWindow", "记录反向生成说明")) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "文档生产工具")) + self.groupBox_3.setTitle(_translate("MainWindow", "UAS单元测试转换")) + self.label_2.setText(_translate("MainWindow", "被测软件名:")) + self.label_3.setText(_translate("MainWindow", "被测软件标识:")) + self.pushButton_7.setText(_translate("MainWindow", "请选择SAU报告文档")) + self.pushButton_8.setText(_translate("MainWindow", "开始转换")) + self.groupBox_5.setTitle(_translate("MainWindow", "自动填充")) + self.pushButton_16.setText(_translate("MainWindow", "选择文档")) + self.label_7.setText(_translate("MainWindow", "单元格左侧:")) + self.label_9.setText(_translate("MainWindow", "填充的内容:")) + self.label_10.setText(_translate("MainWindow", "填充的数量:")) + self.pushButton_14.setText(_translate("MainWindow", "清空单元格")) + self.pushButton_15.setText(_translate("MainWindow", "填充")) + self.groupBox_6.setTitle(_translate("MainWindow", "提取单元格标题右侧的单元格内容")) + self.pushButton_17.setText(_translate("MainWindow", "选择文档")) + self.label_8.setText(_translate("MainWindow", "单元格标题:")) + self.label_11.setText(_translate("MainWindow", "单元格标题:")) + self.label_12.setText(_translate("MainWindow", "单元格标题:")) + self.pushButton_19.setText(_translate("MainWindow", "点击提取")) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("MainWindow", "文档小工具")) + self.groupBox_10.setTitle(_translate("MainWindow", "部件测试表格")) + self.pushButton_27.setText(_translate("MainWindow", "选择UAS文件")) + self.pushButton_28.setText(_translate("MainWindow", "点击生成")) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_3), _translate("MainWindow", "报告生成工具")) + self.groupBox_11.setTitle(_translate("MainWindow", "FPGA记录自动填写")) + self.pushButton_29.setText(_translate("MainWindow", "选择FPGA记录文件")) + self.label_13.setText(_translate("MainWindow", "测试时间")) + self.label_14.setText(_translate("MainWindow", "测试人员")) + self.label_15.setText(_translate("MainWindow", "监测人员")) + self.label_16.setText(_translate("MainWindow", "项目编号")) + self.pushButton_30.setText(_translate("MainWindow", "自动填写开始")) + self.groupBox_12.setTitle(_translate("MainWindow", "FPGA记录转说明")) + self.pushButton_31.setText(_translate("MainWindow", "请选择完整FPGA记录文件")) + self.label_17.setText(_translate("MainWindow", "设计人员")) + self.pushButton_32.setText(_translate("MainWindow", "点击生成说明")) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_4), _translate("MainWindow", "FPGA工具")) + self.pushButton_9.setText(_translate("MainWindow", "清空消息")) + self.pushButton_10.setText(_translate("MainWindow", "显示帮助")) + self.menu.setTitle(_translate("MainWindow", "文件")) + self.menu_2.setTitle(_translate("MainWindow", "工具")) + self.actionopen.setText(_translate("MainWindow", "打开文件")) + self.actionclose.setText(_translate("MainWindow", "close")) + self.actionAbout.setText(_translate("MainWindow", "关于工具")) + self.action_3.setText(_translate("MainWindow", "退出")) + self.actionIEEE754.setText(_translate("MainWindow", "IEEE转换工具")) diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/bak/FPGA记录to说明模板.docx b/bak/FPGA记录to说明模板.docx new file mode 100644 index 0000000..f36e67f Binary files /dev/null and b/bak/FPGA记录to说明模板.docx differ diff --git a/bak/fpga_JtoS.py b/bak/fpga_JtoS.py new file mode 100644 index 0000000..377e5bc --- /dev/null +++ b/bak/fpga_JtoS.py @@ -0,0 +1,117 @@ +from PyQt5 import QtCore +from PyQt5.QtCore import pyqtSignal +from pathlib import * +from PyQt5.QtWidgets import QMessageBox +from docxtpl import DocxTemplate,InlineImage +from docx import Document +import io + + +class create_FPGA_JtoS(QtCore.QThread): + sin_out = pyqtSignal(str) + + def __init__(self,parent): + super().__init__() + self.parent = parent + + def run(self): + self.sin_out.emit("进入测试记录转说明线程......") + self.sin_out.emit("开始转换......") + #如果没有选择文件路径则退出 + if not self.parent.open_file_name: + self.sin_out.emit('nofile') + self.parent.tabWidget.setEnabled(True) + return + + #打开模板文件进行渲染,然后就是用docxtpl生成用例 + try: + tpl_path = Path.cwd() / "need" / "document_templates" / "FPGA记录to说明模板.docx" + self.sin_out.emit('导入模板文件路径为:' + str(tpl_path)) + tpl = DocxTemplate(tpl_path) #模板导入成功 + + except: + QMessageBox.warning(self.parent,"出错了","导入模板出错请检查模板文件是否存在或名字不正确") + return + + + try: + doc = Document(self.parent.open_file_name[0]) + self.sin_out.emit('已识别到FPGA测试记录文件...') + except: + self.sin_out.emit('open failed:选择的文档') + self.parent.tabWidget.setEnabled(True) + return + + self.sin_out.emit('复制测试说明文档模板到本程序所在目录...') + curpath = Path.cwd() / 'need' + shuoming_path_tmp = curpath / 'document_templates' / 'FPGA记录to说明模板.docx' + print(shuoming_path_tmp) + if shuoming_path_tmp.is_file(): + self.sin_out.emit('已检测到有说明模板文件...') + else: + self.sin_out.emit('open failed:选择的文档') + return + + #创建一个字典来储存单个用例 + data_list = [] + #获取表格数量 + tables = doc.tables + tb_count = len(tables) + self.sin_out.emit('total:'+ str(tb_count)) + + for i in range(tb_count): + if tables[i].cell(0,0).text == '测试用例名称': + try: + data = {'name':'','biaoshi':'','zhuizong':'','zongsu':'','init':'','qianti':'','step':[]} + self.sin_out.emit(str(i+1)) + self.sin_out.emit(f'正在处理第{i+1}个表格') + # 1、获取测试用例名称 + data['name'] = tables[i].cell(0,3).text + # 2、获取用例标识 + data['biaoshi'] = tables[i].cell(0,8).text + # 3、获取追踪关系 注意word中换行为\r\x07 + temp = tables[i].cell(1,3).text + data['zhuizong'] = temp.replace("\n", "\r\x07") + # 4、获取综述 + data['zongsu'] = tables[i].cell(2,3).text + # 5、初始化 + data['init'] = tables[i].cell(3,3).text + # 6、获取前提与约束 + data['qianti'] = tables[i].cell(4,3).text + # 7、获取步骤信息-总行数减去12为步骤行数 + row_count = len(tables[i].rows) + step_count = row_count - 12 + for j in range(step_count): + buzhou = {'shuru':'','yuqi':'','num':'','image':'','is_image':'0'} + buzhou['num'] = tables[i].rows[7+j].cells[0].text + buzhou['shuru'] = tables[i].rows[7+j].cells[2].text + cel = tables[i].rows[7+j].cells[2] + if len(cel._element.findall('.//{http://schemas.openxmlformats.org/wordprocessingml/2006/main}drawing'))>0: + img_ele = cel._element.xpath('.//pic:pic')[0] + embed = img_ele.xpath('.//a:blip/@r:embed')[0] + related_part = doc.part.related_parts[embed] + image = related_part.image + image_bytes = image.blob + buzhou['image'] = InlineImage(tpl, io.BytesIO(image_bytes)) + buzhou['is_image'] = '1' + buzhou['yuqi'] = tables[i].rows[7+j].cells[4].text + data['step'].append(buzhou) + # 8、最后加入data_list + data_list.append(data) + except: + self.sin_out.emit(f'第{i}个表格处理错误!') + pass + + + #开始渲染模板文件-有2层循环 + try: + context = { + "tables":data_list, + "renyuan":self.parent.lineEdit_17.text(), + } + tpl.render(context) + tpl.save("FPGA反向生成的说明文档.docx") + self.sin_out.emit('stopsuccess') + except: + self.sin_out.emit('stoperror') + return \ No newline at end of file diff --git a/demo/XXFPGA测试记录.doc b/demo/XXFPGA测试记录.doc new file mode 100644 index 0000000..0d8bb57 Binary files /dev/null and b/demo/XXFPGA测试记录.doc differ diff --git a/demo/XXFPGA测试记录.docx b/demo/XXFPGA测试记录.docx new file mode 100644 index 0000000..96f9a49 Binary files /dev/null and b/demo/XXFPGA测试记录.docx differ diff --git a/demo/XXPGA测试说明.doc b/demo/XXPGA测试说明.doc new file mode 100644 index 0000000..3479203 Binary files /dev/null and b/demo/XXPGA测试说明.doc differ diff --git a/demo/单元测试记录demo.docx b/demo/单元测试记录demo.docx new file mode 100644 index 0000000..29a4d78 Binary files /dev/null and b/demo/单元测试记录demo.docx differ diff --git a/index.py b/index.py new file mode 100644 index 0000000..1c342b5 --- /dev/null +++ b/index.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +import sys +from PyQt5.QtWidgets import QApplication +from PyQt5 import QtCore, QtGui +from need.main import userMain +import qtmodern.styles +import qtmodern.windows +# from qt_material import apply_stylesheet +#以下导入为打包导入所需-使用软件 +import os +import sys +import json +import docx +import docxtpl +import six +import docxcompose +import lxml +import markupsafe +import win32api +import win32com + +if __name__ == "__main__": + pyqt5_path = os.path.join(sys.prefix, 'Lib', 'site-packages', 'PyQt5', 'Qt5', 'plugins', 'platforms') + if os.path.exists(pyqt5_path) and os.path.exists(os.path.join(pyqt5_path, 'qwindows.dll')): + os.environ['QT_QPA_PLATFORM_PLUGIN_PATH'] = pyqt5_path + + QtCore.QCoreApplication.setAttribute(QtCore.Qt.ApplicationAttribute.AA_EnableHighDpiScaling) + app = QApplication(sys.argv) + # 设置任务栏软件图标 + app.setWindowIcon(QtGui.QIcon('Icon.png')) + win = userMain() + ##以下是qt_material样式加载 + # apply_stylesheet(app,theme = 'dark_teal.xml') + # win.show() + + qtmodern.styles.light(app) #还有dark可以选择 + mw = qtmodern.windows.ModernWindow(win) + mw.show() + ''' + #设置窗口有边框可拖动,但删除标题栏 + self.setWindowFlags( + Qt.Window | Qt.CustomizeWindowHint | Qt.WindowSystemMenuHint) + # win.show() + ''' + sys.exit(app.exec_()) diff --git a/need/Ui_GUI.py b/need/Ui_GUI.py new file mode 100644 index 0000000..ef6977d --- /dev/null +++ b/need/Ui_GUI.py @@ -0,0 +1,510 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'GUI.ui' +# +# Created by: PyQt5 UI code generator 5.15.4 +# +# WARNING: Any manual changes made to this file will be lost when pyuic5 is +# run again. Do not edit this file unless you know what you are doing. + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_MainWindow(object): + def setupUi(self, MainWindow): + MainWindow.setObjectName("MainWindow") + MainWindow.resize(826, 619) + self.centralwidget = QtWidgets.QWidget(MainWindow) + self.centralwidget.setObjectName("centralwidget") + self.verticalLayout_8 = QtWidgets.QVBoxLayout(self.centralwidget) + self.verticalLayout_8.setObjectName("verticalLayout_8") + self.verticalLayout_7 = QtWidgets.QVBoxLayout() + self.verticalLayout_7.setObjectName("verticalLayout_7") + self.tabWidget = QtWidgets.QTabWidget(self.centralwidget) + font = QtGui.QFont() + font.setFamily("微软雅黑") + font.setPointSize(10) + font.setBold(False) + font.setWeight(50) + self.tabWidget.setFont(font) + self.tabWidget.setObjectName("tabWidget") + self.tab = QtWidgets.QWidget() + self.tab.setObjectName("tab") + self.gridLayout = QtWidgets.QGridLayout(self.tab) + self.gridLayout.setObjectName("gridLayout") + self.horizontalLayout_15 = QtWidgets.QHBoxLayout() + self.horizontalLayout_15.setObjectName("horizontalLayout_15") + self.groupBox = QtWidgets.QGroupBox(self.tab) + font = QtGui.QFont() + font.setFamily("微软雅黑") + font.setPointSize(10) + font.setBold(False) + font.setWeight(50) + self.groupBox.setFont(font) + self.groupBox.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) + self.groupBox.setFlat(False) + self.groupBox.setObjectName("groupBox") + self.verticalLayout = QtWidgets.QVBoxLayout(self.groupBox) + self.verticalLayout.setObjectName("verticalLayout") + self.pushButton = QtWidgets.QPushButton(self.groupBox) + self.pushButton.setObjectName("pushButton") + self.verticalLayout.addWidget(self.pushButton) + self.horizontalLayout = QtWidgets.QHBoxLayout() + self.horizontalLayout.setObjectName("horizontalLayout") + self.label = QtWidgets.QLabel(self.groupBox) + self.label.setObjectName("label") + self.horizontalLayout.addWidget(self.label) + self.lineEdit = QtWidgets.QLineEdit(self.groupBox) + self.lineEdit.setObjectName("lineEdit") + self.horizontalLayout.addWidget(self.lineEdit) + self.verticalLayout.addLayout(self.horizontalLayout) + self.pushButton_3 = QtWidgets.QPushButton(self.groupBox) + self.pushButton_3.setObjectName("pushButton_3") + self.verticalLayout.addWidget(self.pushButton_3) + self.pushButton_2 = QtWidgets.QPushButton(self.groupBox) + self.pushButton_2.setObjectName("pushButton_2") + self.verticalLayout.addWidget(self.pushButton_2) + self.horizontalLayout_15.addWidget(self.groupBox) + self.groupBox_2 = QtWidgets.QGroupBox(self.tab) + font = QtGui.QFont() + font.setFamily("微软雅黑") + font.setPointSize(10) + font.setBold(False) + font.setWeight(50) + self.groupBox_2.setFont(font) + self.groupBox_2.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) + self.groupBox_2.setFlat(False) + self.groupBox_2.setObjectName("groupBox_2") + self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.groupBox_2) + self.verticalLayout_2.setObjectName("verticalLayout_2") + self.pushButton_4 = QtWidgets.QPushButton(self.groupBox_2) + self.pushButton_4.setObjectName("pushButton_4") + self.verticalLayout_2.addWidget(self.pushButton_4) + self.pushButton_6 = QtWidgets.QPushButton(self.groupBox_2) + self.pushButton_6.setObjectName("pushButton_6") + self.verticalLayout_2.addWidget(self.pushButton_6) + self.pushButton_5 = QtWidgets.QPushButton(self.groupBox_2) + self.pushButton_5.setObjectName("pushButton_5") + self.verticalLayout_2.addWidget(self.pushButton_5) + self.pushButton_18 = QtWidgets.QPushButton(self.groupBox_2) + self.pushButton_18.setObjectName("pushButton_18") + self.verticalLayout_2.addWidget(self.pushButton_18) + self.horizontalLayout_15.addWidget(self.groupBox_2) + self.groupBox_4 = QtWidgets.QGroupBox(self.tab) + font = QtGui.QFont() + font.setFamily("微软雅黑") + font.setPointSize(10) + font.setBold(False) + font.setWeight(50) + self.groupBox_4.setFont(font) + self.groupBox_4.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) + self.groupBox_4.setFlat(False) + self.groupBox_4.setObjectName("groupBox_4") + self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.groupBox_4) + self.verticalLayout_4.setObjectName("verticalLayout_4") + self.pushButton_11 = QtWidgets.QPushButton(self.groupBox_4) + self.pushButton_11.setObjectName("pushButton_11") + self.verticalLayout_4.addWidget(self.pushButton_11) + self.horizontalLayout_2 = QtWidgets.QHBoxLayout() + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.label_4 = QtWidgets.QLabel(self.groupBox_4) + self.label_4.setTextFormat(QtCore.Qt.AutoText) + self.label_4.setAlignment(QtCore.Qt.AlignCenter) + self.label_4.setObjectName("label_4") + self.horizontalLayout_2.addWidget(self.label_4) + self.lineEdit_4 = QtWidgets.QLineEdit(self.groupBox_4) + self.lineEdit_4.setObjectName("lineEdit_4") + self.horizontalLayout_2.addWidget(self.lineEdit_4) + self.verticalLayout_4.addLayout(self.horizontalLayout_2) + self.horizontalLayout_3 = QtWidgets.QHBoxLayout() + self.horizontalLayout_3.setObjectName("horizontalLayout_3") + self.label_5 = QtWidgets.QLabel(self.groupBox_4) + self.label_5.setTextFormat(QtCore.Qt.AutoText) + self.label_5.setAlignment(QtCore.Qt.AlignCenter) + self.label_5.setObjectName("label_5") + self.horizontalLayout_3.addWidget(self.label_5) + self.lineEdit_5 = QtWidgets.QLineEdit(self.groupBox_4) + self.lineEdit_5.setObjectName("lineEdit_5") + self.horizontalLayout_3.addWidget(self.lineEdit_5) + self.verticalLayout_4.addLayout(self.horizontalLayout_3) + self.horizontalLayout_4 = QtWidgets.QHBoxLayout() + self.horizontalLayout_4.setObjectName("horizontalLayout_4") + self.label_6 = QtWidgets.QLabel(self.groupBox_4) + self.label_6.setTextFormat(QtCore.Qt.AutoText) + self.label_6.setAlignment(QtCore.Qt.AlignCenter) + self.label_6.setObjectName("label_6") + self.horizontalLayout_4.addWidget(self.label_6) + self.lineEdit_6 = QtWidgets.QLineEdit(self.groupBox_4) + self.lineEdit_6.setObjectName("lineEdit_6") + self.horizontalLayout_4.addWidget(self.lineEdit_6) + self.verticalLayout_4.addLayout(self.horizontalLayout_4) + self.horizontalLayout_5 = QtWidgets.QHBoxLayout() + self.horizontalLayout_5.setObjectName("horizontalLayout_5") + self.pushButton_12 = QtWidgets.QPushButton(self.groupBox_4) + self.pushButton_12.setObjectName("pushButton_12") + self.horizontalLayout_5.addWidget(self.pushButton_12) + self.pushButton_13 = QtWidgets.QPushButton(self.groupBox_4) + self.pushButton_13.setObjectName("pushButton_13") + self.horizontalLayout_5.addWidget(self.pushButton_13) + self.verticalLayout_4.addLayout(self.horizontalLayout_5) + self.horizontalLayout_15.addWidget(self.groupBox_4) + self.gridLayout.addLayout(self.horizontalLayout_15, 0, 0, 1, 1) + self.tabWidget.addTab(self.tab, "") + self.tab_2 = QtWidgets.QWidget() + self.tab_2.setObjectName("tab_2") + self.verticalLayout_12 = QtWidgets.QVBoxLayout(self.tab_2) + self.verticalLayout_12.setObjectName("verticalLayout_12") + self.horizontalLayout_13 = QtWidgets.QHBoxLayout() + self.horizontalLayout_13.setObjectName("horizontalLayout_13") + self.groupBox_3 = QtWidgets.QGroupBox(self.tab_2) + font = QtGui.QFont() + font.setFamily("微软雅黑") + font.setPointSize(10) + font.setBold(False) + font.setWeight(50) + self.groupBox_3.setFont(font) + self.groupBox_3.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) + self.groupBox_3.setFlat(False) + self.groupBox_3.setObjectName("groupBox_3") + self.verticalLayout_9 = QtWidgets.QVBoxLayout(self.groupBox_3) + self.verticalLayout_9.setObjectName("verticalLayout_9") + self.verticalLayout_3 = QtWidgets.QVBoxLayout() + self.verticalLayout_3.setObjectName("verticalLayout_3") + self.label_2 = QtWidgets.QLabel(self.groupBox_3) + self.label_2.setObjectName("label_2") + self.verticalLayout_3.addWidget(self.label_2) + self.lineEdit_2 = QtWidgets.QLineEdit(self.groupBox_3) + self.lineEdit_2.setObjectName("lineEdit_2") + self.verticalLayout_3.addWidget(self.lineEdit_2) + self.label_3 = QtWidgets.QLabel(self.groupBox_3) + self.label_3.setObjectName("label_3") + self.verticalLayout_3.addWidget(self.label_3) + self.lineEdit_3 = QtWidgets.QLineEdit(self.groupBox_3) + self.lineEdit_3.setObjectName("lineEdit_3") + self.verticalLayout_3.addWidget(self.lineEdit_3) + self.pushButton_7 = QtWidgets.QPushButton(self.groupBox_3) + self.pushButton_7.setObjectName("pushButton_7") + self.verticalLayout_3.addWidget(self.pushButton_7) + self.pushButton_8 = QtWidgets.QPushButton(self.groupBox_3) + self.pushButton_8.setObjectName("pushButton_8") + self.verticalLayout_3.addWidget(self.pushButton_8) + self.verticalLayout_9.addLayout(self.verticalLayout_3) + self.horizontalLayout_13.addWidget(self.groupBox_3) + self.groupBox_5 = QtWidgets.QGroupBox(self.tab_2) + font = QtGui.QFont() + font.setFamily("微软雅黑") + font.setPointSize(10) + font.setBold(False) + font.setWeight(50) + self.groupBox_5.setFont(font) + self.groupBox_5.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) + self.groupBox_5.setFlat(False) + self.groupBox_5.setObjectName("groupBox_5") + self.verticalLayout_10 = QtWidgets.QVBoxLayout(self.groupBox_5) + self.verticalLayout_10.setObjectName("verticalLayout_10") + self.verticalLayout_5 = QtWidgets.QVBoxLayout() + self.verticalLayout_5.setObjectName("verticalLayout_5") + self.pushButton_16 = QtWidgets.QPushButton(self.groupBox_5) + self.pushButton_16.setObjectName("pushButton_16") + self.verticalLayout_5.addWidget(self.pushButton_16) + self.horizontalLayout_6 = QtWidgets.QHBoxLayout() + self.horizontalLayout_6.setObjectName("horizontalLayout_6") + self.label_7 = QtWidgets.QLabel(self.groupBox_5) + self.label_7.setObjectName("label_7") + self.horizontalLayout_6.addWidget(self.label_7) + self.lineEdit_9 = QtWidgets.QLineEdit(self.groupBox_5) + self.lineEdit_9.setObjectName("lineEdit_9") + self.horizontalLayout_6.addWidget(self.lineEdit_9) + self.verticalLayout_5.addLayout(self.horizontalLayout_6) + self.horizontalLayout_7 = QtWidgets.QHBoxLayout() + self.horizontalLayout_7.setObjectName("horizontalLayout_7") + self.label_9 = QtWidgets.QLabel(self.groupBox_5) + self.label_9.setObjectName("label_9") + self.horizontalLayout_7.addWidget(self.label_9) + self.lineEdit_10 = QtWidgets.QLineEdit(self.groupBox_5) + self.lineEdit_10.setObjectName("lineEdit_10") + self.horizontalLayout_7.addWidget(self.lineEdit_10) + self.verticalLayout_5.addLayout(self.horizontalLayout_7) + self.horizontalLayout_8 = QtWidgets.QHBoxLayout() + self.horizontalLayout_8.setObjectName("horizontalLayout_8") + self.label_10 = QtWidgets.QLabel(self.groupBox_5) + self.label_10.setObjectName("label_10") + self.horizontalLayout_8.addWidget(self.label_10) + self.lineEdit_11 = QtWidgets.QLineEdit(self.groupBox_5) + self.lineEdit_11.setObjectName("lineEdit_11") + self.horizontalLayout_8.addWidget(self.lineEdit_11) + self.verticalLayout_5.addLayout(self.horizontalLayout_8) + self.horizontalLayout_9 = QtWidgets.QHBoxLayout() + self.horizontalLayout_9.setObjectName("horizontalLayout_9") + self.pushButton_14 = QtWidgets.QPushButton(self.groupBox_5) + self.pushButton_14.setObjectName("pushButton_14") + self.horizontalLayout_9.addWidget(self.pushButton_14) + self.pushButton_15 = QtWidgets.QPushButton(self.groupBox_5) + self.pushButton_15.setObjectName("pushButton_15") + self.horizontalLayout_9.addWidget(self.pushButton_15) + self.verticalLayout_5.addLayout(self.horizontalLayout_9) + self.verticalLayout_10.addLayout(self.verticalLayout_5) + self.horizontalLayout_13.addWidget(self.groupBox_5) + self.groupBox_6 = QtWidgets.QGroupBox(self.tab_2) + font = QtGui.QFont() + font.setFamily("微软雅黑") + font.setPointSize(10) + font.setBold(False) + font.setWeight(50) + self.groupBox_6.setFont(font) + self.groupBox_6.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) + self.groupBox_6.setFlat(False) + self.groupBox_6.setObjectName("groupBox_6") + self.verticalLayout_11 = QtWidgets.QVBoxLayout(self.groupBox_6) + self.verticalLayout_11.setObjectName("verticalLayout_11") + self.verticalLayout_6 = QtWidgets.QVBoxLayout() + self.verticalLayout_6.setObjectName("verticalLayout_6") + self.pushButton_17 = QtWidgets.QPushButton(self.groupBox_6) + self.pushButton_17.setObjectName("pushButton_17") + self.verticalLayout_6.addWidget(self.pushButton_17) + self.horizontalLayout_10 = QtWidgets.QHBoxLayout() + self.horizontalLayout_10.setObjectName("horizontalLayout_10") + self.label_8 = QtWidgets.QLabel(self.groupBox_6) + self.label_8.setObjectName("label_8") + self.horizontalLayout_10.addWidget(self.label_8) + self.lineEdit_12 = QtWidgets.QLineEdit(self.groupBox_6) + self.lineEdit_12.setObjectName("lineEdit_12") + self.horizontalLayout_10.addWidget(self.lineEdit_12) + self.verticalLayout_6.addLayout(self.horizontalLayout_10) + self.horizontalLayout_11 = QtWidgets.QHBoxLayout() + self.horizontalLayout_11.setObjectName("horizontalLayout_11") + self.label_11 = QtWidgets.QLabel(self.groupBox_6) + self.label_11.setObjectName("label_11") + self.horizontalLayout_11.addWidget(self.label_11) + self.lineEdit_13 = QtWidgets.QLineEdit(self.groupBox_6) + self.lineEdit_13.setObjectName("lineEdit_13") + self.horizontalLayout_11.addWidget(self.lineEdit_13) + self.verticalLayout_6.addLayout(self.horizontalLayout_11) + self.horizontalLayout_12 = QtWidgets.QHBoxLayout() + self.horizontalLayout_12.setObjectName("horizontalLayout_12") + self.label_12 = QtWidgets.QLabel(self.groupBox_6) + self.label_12.setObjectName("label_12") + self.horizontalLayout_12.addWidget(self.label_12) + self.lineEdit_14 = QtWidgets.QLineEdit(self.groupBox_6) + self.lineEdit_14.setObjectName("lineEdit_14") + self.horizontalLayout_12.addWidget(self.lineEdit_14) + self.verticalLayout_6.addLayout(self.horizontalLayout_12) + self.pushButton_19 = QtWidgets.QPushButton(self.groupBox_6) + self.pushButton_19.setObjectName("pushButton_19") + self.verticalLayout_6.addWidget(self.pushButton_19) + self.verticalLayout_11.addLayout(self.verticalLayout_6) + self.horizontalLayout_13.addWidget(self.groupBox_6) + self.verticalLayout_12.addLayout(self.horizontalLayout_13) + self.tabWidget.addTab(self.tab_2, "") + self.tab_3 = QtWidgets.QWidget() + self.tab_3.setObjectName("tab_3") + self.groupBox_10 = QtWidgets.QGroupBox(self.tab_3) + self.groupBox_10.setGeometry(QtCore.QRect(5, 5, 161, 211)) + self.groupBox_10.setObjectName("groupBox_10") + self.verticalLayout_19 = QtWidgets.QVBoxLayout(self.groupBox_10) + self.verticalLayout_19.setObjectName("verticalLayout_19") + self.pushButton_27 = QtWidgets.QPushButton(self.groupBox_10) + self.pushButton_27.setObjectName("pushButton_27") + self.verticalLayout_19.addWidget(self.pushButton_27) + self.pushButton_28 = QtWidgets.QPushButton(self.groupBox_10) + self.pushButton_28.setObjectName("pushButton_28") + self.verticalLayout_19.addWidget(self.pushButton_28) + self.tabWidget.addTab(self.tab_3, "") + self.tab_4 = QtWidgets.QWidget() + self.tab_4.setObjectName("tab_4") + self.groupBox_11 = QtWidgets.QGroupBox(self.tab_4) + self.groupBox_11.setGeometry(QtCore.QRect(5, 5, 246, 211)) + self.groupBox_11.setObjectName("groupBox_11") + self.verticalLayout_20 = QtWidgets.QVBoxLayout(self.groupBox_11) + self.verticalLayout_20.setObjectName("verticalLayout_20") + self.pushButton_29 = QtWidgets.QPushButton(self.groupBox_11) + self.pushButton_29.setObjectName("pushButton_29") + self.verticalLayout_20.addWidget(self.pushButton_29) + self.verticalLayout_13 = QtWidgets.QVBoxLayout() + self.verticalLayout_13.setObjectName("verticalLayout_13") + self.horizontalLayout_16 = QtWidgets.QHBoxLayout() + self.horizontalLayout_16.setObjectName("horizontalLayout_16") + self.label_13 = QtWidgets.QLabel(self.groupBox_11) + self.label_13.setObjectName("label_13") + self.horizontalLayout_16.addWidget(self.label_13) + self.lineEdit_7 = QtWidgets.QLineEdit(self.groupBox_11) + self.lineEdit_7.setObjectName("lineEdit_7") + self.horizontalLayout_16.addWidget(self.lineEdit_7) + self.verticalLayout_13.addLayout(self.horizontalLayout_16) + self.horizontalLayout_17 = QtWidgets.QHBoxLayout() + self.horizontalLayout_17.setObjectName("horizontalLayout_17") + self.label_14 = QtWidgets.QLabel(self.groupBox_11) + self.label_14.setObjectName("label_14") + self.horizontalLayout_17.addWidget(self.label_14) + self.lineEdit_8 = QtWidgets.QLineEdit(self.groupBox_11) + self.lineEdit_8.setObjectName("lineEdit_8") + self.horizontalLayout_17.addWidget(self.lineEdit_8) + self.verticalLayout_13.addLayout(self.horizontalLayout_17) + self.horizontalLayout_18 = QtWidgets.QHBoxLayout() + self.horizontalLayout_18.setObjectName("horizontalLayout_18") + self.label_15 = QtWidgets.QLabel(self.groupBox_11) + self.label_15.setObjectName("label_15") + self.horizontalLayout_18.addWidget(self.label_15) + self.lineEdit_15 = QtWidgets.QLineEdit(self.groupBox_11) + self.lineEdit_15.setObjectName("lineEdit_15") + self.horizontalLayout_18.addWidget(self.lineEdit_15) + self.verticalLayout_13.addLayout(self.horizontalLayout_18) + self.horizontalLayout_19 = QtWidgets.QHBoxLayout() + self.horizontalLayout_19.setObjectName("horizontalLayout_19") + self.label_16 = QtWidgets.QLabel(self.groupBox_11) + self.label_16.setObjectName("label_16") + self.horizontalLayout_19.addWidget(self.label_16) + self.lineEdit_16 = QtWidgets.QLineEdit(self.groupBox_11) + self.lineEdit_16.setObjectName("lineEdit_16") + self.horizontalLayout_19.addWidget(self.lineEdit_16) + self.verticalLayout_13.addLayout(self.horizontalLayout_19) + self.verticalLayout_20.addLayout(self.verticalLayout_13) + self.pushButton_30 = QtWidgets.QPushButton(self.groupBox_11) + self.pushButton_30.setObjectName("pushButton_30") + self.verticalLayout_20.addWidget(self.pushButton_30) + self.groupBox_12 = QtWidgets.QGroupBox(self.tab_4) + self.groupBox_12.setGeometry(QtCore.QRect(255, 5, 191, 211)) + self.groupBox_12.setObjectName("groupBox_12") + self.verticalLayout_21 = QtWidgets.QVBoxLayout(self.groupBox_12) + self.verticalLayout_21.setObjectName("verticalLayout_21") + self.pushButton_31 = QtWidgets.QPushButton(self.groupBox_12) + self.pushButton_31.setObjectName("pushButton_31") + self.verticalLayout_21.addWidget(self.pushButton_31) + self.horizontalLayout_20 = QtWidgets.QHBoxLayout() + self.horizontalLayout_20.setObjectName("horizontalLayout_20") + self.label_17 = QtWidgets.QLabel(self.groupBox_12) + self.label_17.setObjectName("label_17") + self.horizontalLayout_20.addWidget(self.label_17) + self.lineEdit_17 = QtWidgets.QLineEdit(self.groupBox_12) + self.lineEdit_17.setObjectName("lineEdit_17") + self.horizontalLayout_20.addWidget(self.lineEdit_17) + self.verticalLayout_21.addLayout(self.horizontalLayout_20) + self.pushButton_32 = QtWidgets.QPushButton(self.groupBox_12) + self.pushButton_32.setObjectName("pushButton_32") + self.verticalLayout_21.addWidget(self.pushButton_32) + self.tabWidget.addTab(self.tab_4, "") + self.verticalLayout_7.addWidget(self.tabWidget) + self.textBrowser = QtWidgets.QTextBrowser(self.centralwidget) + self.textBrowser.setObjectName("textBrowser") + self.verticalLayout_7.addWidget(self.textBrowser) + self.horizontalLayout_14 = QtWidgets.QHBoxLayout() + self.horizontalLayout_14.setObjectName("horizontalLayout_14") + spacerItem = QtWidgets.QSpacerItem(618, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout_14.addItem(spacerItem) + self.pushButton_9 = QtWidgets.QPushButton(self.centralwidget) + self.pushButton_9.setObjectName("pushButton_9") + self.horizontalLayout_14.addWidget(self.pushButton_9) + self.pushButton_10 = QtWidgets.QPushButton(self.centralwidget) + self.pushButton_10.setObjectName("pushButton_10") + self.horizontalLayout_14.addWidget(self.pushButton_10) + self.verticalLayout_7.addLayout(self.horizontalLayout_14) + self.progressBar = QtWidgets.QProgressBar(self.centralwidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.progressBar.sizePolicy().hasHeightForWidth()) + self.progressBar.setSizePolicy(sizePolicy) + self.progressBar.setProperty("value", 0) + self.progressBar.setObjectName("progressBar") + self.verticalLayout_7.addWidget(self.progressBar) + self.verticalLayout_8.addLayout(self.verticalLayout_7) + MainWindow.setCentralWidget(self.centralwidget) + self.menubar = QtWidgets.QMenuBar(MainWindow) + self.menubar.setGeometry(QtCore.QRect(0, 0, 826, 22)) + self.menubar.setObjectName("menubar") + self.menu = QtWidgets.QMenu(self.menubar) + self.menu.setObjectName("menu") + self.menu_2 = QtWidgets.QMenu(self.menubar) + self.menu_2.setObjectName("menu_2") + MainWindow.setMenuBar(self.menubar) + self.statusbar = QtWidgets.QStatusBar(MainWindow) + self.statusbar.setObjectName("statusbar") + MainWindow.setStatusBar(self.statusbar) + self.actionopen = QtWidgets.QAction(MainWindow) + self.actionopen.setObjectName("actionopen") + self.actionclose = QtWidgets.QAction(MainWindow) + self.actionclose.setObjectName("actionclose") + self.actionAbout = QtWidgets.QAction(MainWindow) + self.actionAbout.setObjectName("actionAbout") + self.action_3 = QtWidgets.QAction(MainWindow) + self.action_3.setObjectName("action_3") + self.actionIEEE754 = QtWidgets.QAction(MainWindow) + self.actionIEEE754.setObjectName("actionIEEE754") + self.menu.addAction(self.actionopen) + self.menu.addSeparator() + self.menu.addAction(self.action_3) + self.menu_2.addAction(self.actionAbout) + self.menu_2.addAction(self.actionIEEE754) + self.menubar.addAction(self.menu.menuAction()) + self.menubar.addAction(self.menu_2.menuAction()) + + self.retranslateUi(MainWindow) + self.tabWidget.setCurrentIndex(3) + QtCore.QMetaObject.connectSlotsByName(MainWindow) + + def retranslateUi(self, MainWindow): + _translate = QtCore.QCoreApplication.translate + MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) + self.groupBox.setTitle(_translate("MainWindow", "大纲转说明-鉴定模板")) + self.pushButton.setText(_translate("MainWindow", "选择大纲文档")) + self.label.setText(_translate("MainWindow", "设计人员:")) + self.pushButton_3.setText(_translate("MainWindow", "测试记录转说明")) + self.pushButton_2.setText(_translate("MainWindow", "开始转换")) + self.groupBox_2.setTitle(_translate("MainWindow", "追踪关系填写")) + self.pushButton_4.setText(_translate("MainWindow", "选择文件")) + self.pushButton_6.setText(_translate("MainWindow", "大纲追踪关系填写(依据大纲文件)")) + self.pushButton_5.setText(_translate("MainWindow", "测试说明追踪填写(依据说明文件)")) + self.pushButton_18.setText(_translate("MainWindow", "测试报告追踪填写(依据记录文件)")) + self.groupBox_4.setTitle(_translate("MainWindow", "根据说明生成测试记录")) + self.pushButton_11.setText(_translate("MainWindow", "选择文件")) + self.label_4.setText(_translate("MainWindow", "测试人员:")) + self.label_5.setText(_translate("MainWindow", "监测人员:")) + self.label_6.setText(_translate("MainWindow", "测试时间:")) + self.pushButton_12.setText(_translate("MainWindow", "说明生成记录")) + self.pushButton_13.setText(_translate("MainWindow", "记录反向生成说明")) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "文档生产工具")) + self.groupBox_3.setTitle(_translate("MainWindow", "UAS单元测试转换")) + self.label_2.setText(_translate("MainWindow", "被测软件名:")) + self.label_3.setText(_translate("MainWindow", "被测软件标识:")) + self.pushButton_7.setText(_translate("MainWindow", "请选择SAU报告文档")) + self.pushButton_8.setText(_translate("MainWindow", "开始转换")) + self.groupBox_5.setTitle(_translate("MainWindow", "自动填充")) + self.pushButton_16.setText(_translate("MainWindow", "选择文档")) + self.label_7.setText(_translate("MainWindow", "单元格左侧:")) + self.label_9.setText(_translate("MainWindow", "填充的内容:")) + self.label_10.setText(_translate("MainWindow", "填充的数量:")) + self.pushButton_14.setText(_translate("MainWindow", "清空单元格")) + self.pushButton_15.setText(_translate("MainWindow", "填充")) + self.groupBox_6.setTitle(_translate("MainWindow", "提取单元格标题右侧的单元格内容")) + self.pushButton_17.setText(_translate("MainWindow", "选择文档")) + self.label_8.setText(_translate("MainWindow", "单元格标题:")) + self.label_11.setText(_translate("MainWindow", "单元格标题:")) + self.label_12.setText(_translate("MainWindow", "单元格标题:")) + self.pushButton_19.setText(_translate("MainWindow", "点击提取")) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("MainWindow", "文档小工具")) + self.groupBox_10.setTitle(_translate("MainWindow", "部件测试表格")) + self.pushButton_27.setText(_translate("MainWindow", "选择UAS文件")) + self.pushButton_28.setText(_translate("MainWindow", "点击生成")) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_3), _translate("MainWindow", "报告生成工具")) + self.groupBox_11.setTitle(_translate("MainWindow", "FPGA记录自动填写")) + self.pushButton_29.setText(_translate("MainWindow", "选择FPGA记录文件")) + self.label_13.setText(_translate("MainWindow", "测试时间")) + self.label_14.setText(_translate("MainWindow", "测试人员")) + self.label_15.setText(_translate("MainWindow", "监测人员")) + self.label_16.setText(_translate("MainWindow", "项目编号")) + self.pushButton_30.setText(_translate("MainWindow", "自动填写开始")) + self.groupBox_12.setTitle(_translate("MainWindow", "FPGA记录转说明")) + self.pushButton_31.setText(_translate("MainWindow", "请选择完整FPGA记录文件")) + self.label_17.setText(_translate("MainWindow", "设计人员")) + self.pushButton_32.setText(_translate("MainWindow", "点击生成说明")) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_4), _translate("MainWindow", "FPGA工具")) + self.pushButton_9.setText(_translate("MainWindow", "清空消息")) + self.pushButton_10.setText(_translate("MainWindow", "显示帮助")) + self.menu.setTitle(_translate("MainWindow", "文件")) + self.menu_2.setTitle(_translate("MainWindow", "工具")) + self.actionopen.setText(_translate("MainWindow", "打开文件")) + self.actionclose.setText(_translate("MainWindow", "close")) + self.actionAbout.setText(_translate("MainWindow", "关于工具")) + self.action_3.setText(_translate("MainWindow", "退出")) + self.actionIEEE754.setText(_translate("MainWindow", "IEEE转换工具")) diff --git a/need/about.py b/need/about.py new file mode 100644 index 0000000..f12b1c2 --- /dev/null +++ b/need/about.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'about.ui' +# +# Created by: PyQt5 UI code generator 5.12.1 +# +# WARNING! All changes made in this file will be lost! + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_Dialog(object): + def setupUi(self, Dialog): + Dialog.setObjectName("Dialog") + Dialog.resize(290, 80) + self.horizontalLayout = QtWidgets.QHBoxLayout(Dialog) + self.horizontalLayout.setObjectName("horizontalLayout") + self.label = QtWidgets.QLabel(Dialog) + self.label.setText("") + self.label.setPixmap(QtGui.QPixmap(r'need/static/zxlogo.gif')) + self.label.setObjectName("label") + self.horizontalLayout.addWidget(self.label) + self.verticalLayout = QtWidgets.QVBoxLayout() + self.verticalLayout.setObjectName("verticalLayout") + self.label_2 = QtWidgets.QLabel(Dialog) + self.label_2.setObjectName("label_2") + self.verticalLayout.addWidget(self.label_2) + self.label_5 = QtWidgets.QLabel(Dialog) + self.label_5.setText("") + self.label_5.setObjectName("label_5") + self.verticalLayout.addWidget(self.label_5) + self.label_3 = QtWidgets.QLabel(Dialog) + self.label_3.setObjectName("label_3") + self.verticalLayout.addWidget(self.label_3) + self.label_4 = QtWidgets.QLabel(Dialog) + self.label_4.setObjectName("label_4") + self.verticalLayout.addWidget(self.label_4) + spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.verticalLayout.addItem(spacerItem) + self.horizontalLayout.addLayout(self.verticalLayout) + + self.retranslateUi(Dialog) + QtCore.QMetaObject.connectSlotsByName(Dialog) + + def retranslateUi(self, Dialog): + _translate = QtCore.QCoreApplication.translate + Dialog.setWindowTitle(_translate("Dialog", "关于")) + self.label_2.setText(_translate("Dialog", "软件名称:CTTools测试工具集合")) + self.label_3.setText(_translate("Dialog", "版本:V0.12/2022")) + self.label_4.setText(_translate("Dialog", "作者:chen/wang")) diff --git a/need/document_templates/FPGA记录to说明模板.docx b/need/document_templates/FPGA记录to说明模板.docx new file mode 100644 index 0000000..278740f Binary files /dev/null and b/need/document_templates/FPGA记录to说明模板.docx differ diff --git a/need/document_templates/SunwiseAUnit单元测试转换模板.docx b/need/document_templates/SunwiseAUnit单元测试转换模板.docx new file mode 100644 index 0000000..92c1f54 Binary files /dev/null and b/need/document_templates/SunwiseAUnit单元测试转换模板.docx differ diff --git a/need/document_templates/cpu新记录to说明模版.docx b/need/document_templates/cpu新记录to说明模版.docx new file mode 100644 index 0000000..ce1b1fc Binary files /dev/null and b/need/document_templates/cpu新记录to说明模版.docx differ diff --git a/need/document_templates/get_content.docx b/need/document_templates/get_content.docx new file mode 100644 index 0000000..0a9f6c2 Binary files /dev/null and b/need/document_templates/get_content.docx differ diff --git a/need/document_templates/tpl模板文件.zip b/need/document_templates/tpl模板文件.zip new file mode 100644 index 0000000..a3fd7dc Binary files /dev/null and b/need/document_templates/tpl模板文件.zip differ diff --git a/need/document_templates/~$GA记录to说明模板.docx b/need/document_templates/~$GA记录to说明模板.docx new file mode 100644 index 0000000..3e56165 Binary files /dev/null and b/need/document_templates/~$GA记录to说明模板.docx differ diff --git a/need/document_templates/反向测试说明模板.docx b/need/document_templates/反向测试说明模板.docx new file mode 100644 index 0000000..1b96d04 Binary files /dev/null and b/need/document_templates/反向测试说明模板.docx differ diff --git a/need/document_templates/大纲追踪模板.docx b/need/document_templates/大纲追踪模板.docx new file mode 100644 index 0000000..caf4a1f Binary files /dev/null and b/need/document_templates/大纲追踪模板.docx differ diff --git a/need/document_templates/报告模板变量.md b/need/document_templates/报告模板变量.md new file mode 100644 index 0000000..bd2a1df --- /dev/null +++ b/need/document_templates/报告模板变量.md @@ -0,0 +1,13 @@ +# 报告模板变量 + +## 1.判断变量 + +- is_jianding-是否为鉴定文件变量,{% if is_jianding == ‘1’ %},string类型 + + + +## 2.用户输入变量 + +- proj_bianhao-项目编号,例如R2255 +- soft_name-软件名,例如XX图像处理软件 +- \ No newline at end of file diff --git a/need/document_templates/报告追踪模板.docx b/need/document_templates/报告追踪模板.docx new file mode 100644 index 0000000..0a38754 Binary files /dev/null and b/need/document_templates/报告追踪模板.docx differ diff --git a/need/document_templates/文档模板/测评大纲模板-2022年10月11日.docx b/need/document_templates/文档模板/测评大纲模板-2022年10月11日.docx new file mode 100644 index 0000000..6f15cc7 Binary files /dev/null and b/need/document_templates/文档模板/测评大纲模板-2022年10月11日.docx differ diff --git a/need/document_templates/文档模板/测评报告模板-2022年10月11日.docx b/need/document_templates/文档模板/测评报告模板-2022年10月11日.docx new file mode 100644 index 0000000..73c8f97 Binary files /dev/null and b/need/document_templates/文档模板/测评报告模板-2022年10月11日.docx differ diff --git a/need/document_templates/测评报告模板.docx b/need/document_templates/测评报告模板.docx new file mode 100644 index 0000000..af8e94e Binary files /dev/null and b/need/document_templates/测评报告模板.docx differ diff --git a/need/document_templates/测试说明模板.docx b/need/document_templates/测试说明模板.docx new file mode 100644 index 0000000..b161ceb Binary files /dev/null and b/need/document_templates/测试说明模板.docx differ diff --git a/need/document_templates/说明生成记录模板.docx b/need/document_templates/说明生成记录模板.docx new file mode 100644 index 0000000..74f1bb8 Binary files /dev/null and b/need/document_templates/说明生成记录模板.docx differ diff --git a/need/document_templates/说明追踪模板.docx b/need/document_templates/说明追踪模板.docx new file mode 100644 index 0000000..1830335 Binary files /dev/null and b/need/document_templates/说明追踪模板.docx differ diff --git a/need/document_templates/部件桩函数工具1.docx b/need/document_templates/部件桩函数工具1.docx new file mode 100644 index 0000000..68ec32e Binary files /dev/null and b/need/document_templates/部件桩函数工具1.docx differ diff --git a/need/fpga_JtoS.py b/need/fpga_JtoS.py new file mode 100644 index 0000000..7992bb3 --- /dev/null +++ b/need/fpga_JtoS.py @@ -0,0 +1,146 @@ +from PyQt5 import QtCore +from PyQt5.QtCore import pyqtSignal +from pathlib import * +from PyQt5.QtWidgets import QMessageBox +from docxtpl import DocxTemplate, InlineImage +from docx import Document +from docx.table import Table +from docx.text.paragraph import Paragraph +import io + +class create_FPGA_JtoS(QtCore.QThread): + sin_out = pyqtSignal(str) + + def __init__(self, parent): + super().__init__() + self.parent = parent + + def run(self): + self.sin_out.emit("进入测试记录转说明线程......") + self.sin_out.emit("开始转换......") + # 如果没有选择文件路径则退出 + if not self.parent.open_file_name: + self.sin_out.emit('nofile') + self.parent.tabWidget.setEnabled(True) + return + + # 打开模板文件进行渲染,然后就是用docxtpl生成用例 + try: + tpl_path = Path.cwd() / "need" / "document_templates" / "FPGA记录to说明模板.docx" + self.sin_out.emit('导入模板文件路径为:' + str(tpl_path)) + tpl = DocxTemplate(tpl_path) # 模板导入成功 + + except: + QMessageBox.warning(self.parent, "出错了", "导入模板出错请检查模板文件是否存在或名字不正确") + return + + try: + doc = Document(self.parent.open_file_name[0]) + self.sin_out.emit('已识别到FPGA测试记录文件...') + except: + self.sin_out.emit('open failed:选择的文档') + self.parent.tabWidget.setEnabled(True) + return + + self.sin_out.emit('复制测试说明文档模板到本程序所在目录...') + curpath = Path.cwd() / 'need' + shuoming_path_tmp = curpath / 'document_templates' / 'FPGA记录to说明模板.docx' + print(shuoming_path_tmp) + if shuoming_path_tmp.is_file(): + self.sin_out.emit('已检测到有说明模板文件...') + else: + self.sin_out.emit('open failed:选择的文档') + return + + # 获取表格数量 + tables = doc.tables + tb_count = len(tables) + self.sin_out.emit('total:' + str(tb_count)) + # 创建一个字典来储存单个用例 + data_list = [] + table_index = 1 + # 获取表格数量 + for ele in doc._element.body.iter(): + data = {'type': ''} + if ele.tag.endswith('}p'): + elePstyle = ele.findall('.//{http://schemas.openxmlformats.org/wordprocessingml/2006/main}pStyle') + if len(elePstyle) >= 1: + parag = Paragraph(ele, doc) + if parag.style.name.startswith("Heading") or parag.style.name.startswith("标题"): + rank = parag.style.name.split(" ")[-1] + text = parag.text + if text == "" or text.startswith("文档齐套性审查单") \ + or text.startswith("软件研制任务书审查单") \ + or text.startswith("附录") \ + or text.startswith("附件") \ + or text.startswith("需求文档审查单"): + pass + else: + data['type'] = rank + data['title'] = text + data_list.append(data) + elif ele.tag.endswith('}tbl'): + data = {'name': '', 'biaoshi': '', 'zhuizong': [], 'zongsu': '', 'init': '', 'qianti': '', 'step': []} + data['type'] = 'table' + table = Table(ele, doc) + if table.cell(0, 0).text == '测试用例名称': + self.sin_out.emit(str(table_index)) + + try: + self.sin_out.emit(str(table_index)) + self.sin_out.emit(f'正在处理第{table_index}个表格') + # 1、获取测试用例名称 + data['name'] = table.cell(0, 3).text + # 2、获取用例标识 + data['biaoshi'] = table.cell(0, 9).text + # 3、获取追踪关系 注意word中换行为\r\x07 + temp = table.cell(1, 3) + for tem in temp.paragraphs: + data['zhuizong'].append(tem.text) + # 4、获取综述 + data['zongsu'] = table.cell(2, 3).text + # 5、初始化 + data['init'] = table.cell(3, 3).text + # 6、获取前提与约束 + data['qianti'] = table.cell(4, 3).text + # 7、获取步骤信息-总行数减去12为步骤行数 + row_count = len(table.rows) + step_count = row_count - 12 + for j in range(step_count): + buzhou = {'shuru': '', 'yuqi': '', 'num': '', 'image': '', 'is_image': '0'} + buzhou['num'] = table.rows[7 + j].cells[0].text + buzhou['shuru'] = table.rows[7 + j].cells[2].text + cel = table.rows[7 + j].cells[2] + if len( + cel._element.findall('.//{http://schemas.openxmlformats.org/wordprocessingml/2006/main}drawing') + ) > 0: + img_ele = cel._element.xpath('.//pic:pic')[0] + embed = img_ele.xpath('.//a:blip/@r:embed')[0] + related_part = doc.part.related_parts[embed] + image = related_part.image + # blob属性就是二进制图片属性 + image_bytes = image.blob + buzhou['image'] = InlineImage(tpl, io.BytesIO(image_bytes)) + buzhou['is_image'] = '1' + buzhou['yuqi'] = table.rows[7 + j].cells[4].text + data['step'].append(buzhou) + # 8、最后加入data_list + data_list.append(data) + table_index += 1 + except: + self.sin_out.emit(f'第{table_index}个表格处理错误!') + table_index += 1 + pass + # 开始渲染模板文件 + try: + self.sin_out.emit(str(tb_count + 1)) + context = { + "tables": data_list, + "renyuan": self.parent.lineEdit_17.text(), + } + tpl.render(context) + tpl.save("FPGA反向生成的说明文档.docx") + self.sin_out.emit('stopsuccess') + except: + self.sin_out.emit('stoperror') + return diff --git a/need/fpga_record_thrend.py b/need/fpga_record_thrend.py new file mode 100644 index 0000000..ee810ae --- /dev/null +++ b/need/fpga_record_thrend.py @@ -0,0 +1,155 @@ +import pythoncom +from PyQt5 import QtCore +from PyQt5.QtCore import pyqtSignal +from pathlib import * +from docx import Document +import re +from docx.shared import Pt + +#常量 +TABLE_FONT_SIZE = Pt(10.5) + +class create_FPGA_record(QtCore.QThread): + sin_out = pyqtSignal(str) + + def __init__(self,parent): + super().__init__() + self.parent = parent + + def run(self): + + + self.sin_out.emit("开始填写FPGA记录......") + self.sin_out.emit("开始填写文档......") + + #如果没有选择路径则退出 + if not self.parent.open_file_name: + self.sin_out.emit('nofile') + self.parent.tabWidget.setEnabled(True) + return + + #告诉windows单线程 + pythoncom.CoInitialize() + #在用户选择的目录中查找UAS单位测试报告文档 + self.sin_out.emit('打开单元测试原文件...') + + try: + doc = Document(self.parent.open_file_name[0]) + except: + self.sin_out.emit('open failed:选择的文档') + pythoncom.CoUninitialize() + self.parent.tabWidget.setEnabled(True) + return + + table_count = len(doc.tables) + self.sin_out.emit('total:'+ str(table_count)) + # 如果大纲标识一致需要累加 + static_dagang_biaoshi = '' + index = 1 + num = 0 + for table in doc.tables: + num += 1 + self.sin_out.emit(str(num)) + self.sin_out.emit(f'正在处理第{num}个表格') + if table.cell(0,0).text == '测试用例名称': + + try: + #~~~~~~~~~~~~~~~第一步处理表格中所在标题填入~~~~~~~~~~~~~~~ + prev_para = table._element.getprevious() + # 如果找到前一个元素是paragraph、但没有找到子节点有pStyle节点,则再往上找 + while prev_para is not None and prev_para.tag.endswith('}p') and \ + len(prev_para.findall('.//{http://schemas.openxmlformats.org/wordprocessingml/2006/main}pStyle')) == 0: + prev_para = prev_para.getprevious() + if prev_para is not None and prev_para.tag.endswith('}p'): + t_ele = prev_para.findall('.//{http://schemas.openxmlformats.org/wordprocessingml/2006/main}t') + title = '' + for i in range(len(t_ele)): + title = title + t_ele[i].text + # 将title放入到cell(0,1)-完成第一步了 + table.cell(0,3).text = title + + + #~~~~~~~~~~~~~~~第二步找到追踪关系中大纲标识更改后填入~~~~~~~~~~~~~~~(要求用户必须3行!) + temp = table.cell(1,3).text.split("\n")[-1] + dagang_biaoshi = re.split('[::]',temp)[-1] + + # 如果大纲标识一致,则累加 + if dagang_biaoshi != static_dagang_biaoshi: + static_dagang_biaoshi = dagang_biaoshi + yongli_biaoshi = dagang_biaoshi.replace('XQ','R1_YL') + '_001' + # 填入标识 + table.cell(0,8).text = yongli_biaoshi + index = 1 + else: + index += 1 + if len(str(index)) <= 3: + str_index = (3-len(str(index)))*'0' + str(index) + yongli_biaoshi = dagang_biaoshi.replace('XQ','R1_YL') + '_' + str_index + table.cell(0,8).text = yongli_biaoshi + + #~~~~~~~~~~~~~~~输出用户知道~~~~~~~~~~~~~~~ + self.sin_out.emit(f'处理完毕测试项:{title},{yongli_biaoshi}') + + #~~~~~~~~~~~~~~~第三步填写“测试用例综述”~~~~~~~~~~~~~~~ + if title: + zongsu_string = f'使用功能仿真的方法,对{title}进行测试' + table.cell(2,3).text = zongsu_string + else: + print('注意:未识别到正确标题!,填入综述失败') + + #~~~~~~~~~~~~~~~第四步“执行状态”填写为已执行、“测试时间”、“测试人员”、“监测人员”为可更改项~~~~~~~~~~~~~~~ + #执行状态-固定! + table.rows[-4].cells[2].text = '已执行' + #测试人员 + table.rows[-3].cells[2].text = self.parent.lineEdit_8.text() + table.rows[-4].cells[7].text = self.parent.lineEdit_7.text() + table.rows[-3].cells[7].text = self.parent.lineEdit_15.text() + + #~~~~~~~~~~~~~~~第五步填写当通过与否为通过时,写"/"~~~~~~~~~~~~~~~ + table.rows[-2].cells[2].text = '/' + + # 判断有几个步骤-根据总行数判断,并循环查看是否为通过 + flag = 1 + for i in range(len(table.rows) - 12): + temp = table.rows[-6 - i].cells[-1].text + if temp == '不通过': + flag = 0 + if temp == '未通过': + flag = 0 + if flag == 1: + table.rows[-2].cells[2].text = '/' + else: + project_code = self.parent.lineEdit_16.text() + pro_biaoshi = f'PT_{project_code}_' + table.rows[-2].cells[2].text = pro_biaoshi + + #~~~~~~~~~~~~~~~第六步截图为空填写‘/’否则不变~~~~~~~~~~~~~~~ + cell = table.cell(-5,0) + has_image = False + for paragraph in cell.paragraphs: + tupian_list = paragraph._element.findall('.//{http://schemas.openxmlformats.org/wordprocessingml/2006/main}drawing') + if len(tupian_list) != 0: + has_image = True + if has_image: + pass + else: + table.cell(-5,0).text = '/' + except: + self.sin_out.emit(f'第{num}个表格处理失败,请查看!!!') + pass + + # 设置字体 + for row in table.rows: + for cell in row.cells: + for paragraph in cell.paragraphs: + for run in paragraph.runs: + run.font.size = TABLE_FONT_SIZE + # 保存文档 + try: + doc.save('~新生产的fpga记录~.docx') + self.sin_out.emit('stopsuccess') + except: + self.sin_out.emit('stoperror') + return + + \ No newline at end of file diff --git a/need/main.py b/need/main.py new file mode 100644 index 0000000..8140d14 --- /dev/null +++ b/need/main.py @@ -0,0 +1,2186 @@ +# -*- coding: utf-8 -*- +import logging + +LOG_FORMAT = "%(asctime)s>%(levelname)s>PID:%(process)d %(thread)d>%(module)s>%(funcName)s>%(lineno)d>%(message)s" +logging.basicConfig( + level=logging.DEBUG, + format=LOG_FORMAT, +) + +# 是否打印调试信息标志 +debug = True +if debug: + logging.debug("进入主程序,开始导入包...") + +# 导入常规库 +import sys, re, string +from pathlib import * +# 导入word文档操作库 +from win32com.client import DispatchEx +from docxtpl import DocxTemplate +import docx +from docx import Document +import shutil +import pythoncom +# 导入QT组件 +from PyQt5 import QtCore +from PyQt5.QtWidgets import QMainWindow, QFileDialog, QMessageBox, QDialog, QToolTip +from PyQt5.QtCore import pyqtSignal +from PyQt5.QtGui import QFont +# 导入UI转换PY文件 +from need.Ui_GUI import Ui_MainWindow +from need import about, zhuan +# 导入工具包文件-时间转换 +from need.utils import get_current_time, get_current_name, get_current_date, get_current_hour +from need.zhuan_tool import IEEE754_16_to_float, IEEE754_float_to_16 +# 导入其他线程 +from need.threads import create_bujian +from need.fpga_record_thrend import create_FPGA_record +from need.fpga_JtoS import create_FPGA_JtoS +from need.new_JtoS import create_new_JtoS + + +class zhuan_dlg(QDialog, zhuan.Ui_Dialog): + + def __init__(self): + super().__init__() + self.setupUi(self) + + if debug: + logging.debug("初始化转换程序:") + + #linetext信号连接 + self.lineEdit.editingFinished.connect(self.shiliu_zhuan) + self.lineEdit_2.editingFinished.connect(self.shi_zhuan) + # 设置气泡提示信息 + QToolTip.setFont(QFont("SansSerif", 12)) + self.lineEdit.setToolTip("注意,编辑输入框后需要点击其他控件才进行转换,且格式不正确不转换") + self.lineEdit_2.setToolTip("注意,编辑输入框后需要点击其他控件才进行转换,且格式不正确不转换") + + def shiliu_zhuan(self): + #获取当前文字 + x = self.lineEdit.text() + if len(x) == 8: + if self.radioButton.isChecked() == True: #说明选中了32位转换 + result = IEEE754_16_to_float(x, 32) + self.lineEdit_2.setText(str(result)) + elif len(x) == 16: + if self.radioButton_2.isChecked() == True: #说明选中了64位转换 + result = IEEE754_16_to_float(x, 64) + self.lineEdit_2.setText(str(result)) + + def shi_zhuan(self): + #获取当前文字 + x = self.lineEdit_2.text() + #字符串转浮点数 + # if str.isdigit(x): + # x = float(x) + # elif str.isdigit(x.replace(".","")): + try: + x = float(x) + except: + logging.debug('输入的内容无法转换为浮点数') + + if isinstance(x, float) == True: + print('进入转换函数里面') + if self.radioButton.isChecked() == True: #说明选中了32位转换 + result = IEEE754_float_to_16(x, 32) + print(result) + self.lineEdit.setText(str(result)) + else: + result = IEEE754_float_to_16(x, 64) + self.lineEdit.setText(str(result)) + + +class userMain(QMainWindow, Ui_MainWindow): + #自定义信号和槽 + + def __init__(self): + super().__init__() + self.setupUi(self) + if debug: + logging.debug("初始化主程序:") + + # 实例化翻译家 + self.trans = QtCore.QCoreApplication.translate + self.setWindowTitle('测试个人工具') + + #使用翻译家改变PYQT的空间名字等属性self.label_4.setText(self.trans("MainWindow", "文件名(自动识别):")) + + if debug: + logging.debug("初始化部分全局变量...") + # 存放文件夹路径变量 + self.open_dirs_name = '' + # 存放文件名称路径变量 + self.open_file_name = '' + + # 读取配置文件 + + #~~~~~~~~~~~~~~~连接线程函数~~~~~~~~~~~~~~~ + ## 连接大纲生成说明函数 + self.create_shuoming_trd = create_shuoming(self) + self.create_shuoming_trd.sin_out.connect(self.text_display) + self.pushButton_2.clicked.connect(self.create_shuoming_btn) + + ## 连接大纲追溯 + self.create_dagang_zhuisu_trd = create_dagang_zhuisu(self) + self.create_dagang_zhuisu_trd.sin_out.connect(self.text_display) + self.pushButton_5.clicked.connect(self.creat_shuoming_zhuisu_btn) + + ## 连接说明追踪线程 + self.create_shuoming_zhuisu_trd = create_shuoming_zhuisu(self) + self.create_shuoming_zhuisu_trd.sin_out.connect(self.text_display) + self.pushButton_6.clicked.connect(self.creat_dagang_zhuisu_btn) + + ## 连接报告追踪 + self.create_baogao_zhuisu_trd = create_baogao_zhuisu(self) + self.create_baogao_zhuisu_trd.sin_out.connect(self.text_display) + self.pushButton_18.clicked.connect(self.create_baogao_zhuisu_btn) + + ## 连接单元追踪线程 + self.create_danyuan_trd = create_danyuan(self) + self.create_danyuan_trd.sin_out.connect(self.text_display) + self.pushButton_8.clicked.connect(self.creat_danyuan_btn) + + ## 连接根据测试说明生成记录线程 + self.create_jilu_trd = create_jilu(self) + self.create_jilu_trd.sin_out.connect(self.text_display) + self.pushButton_12.clicked.connect(self.creat_jilu_btn) + + ## 记录反向生成说明线程 + self.create_shuomingfanxiang_trd = create_new_JtoS(self) + self.create_shuomingfanxiang_trd.sin_out.connect(self.text_display) + self.pushButton_13.clicked.connect(self.creat_shuomingfanxiang_btn) + + ## 自动填充空白表格线程 + self.create_zidong_trd = create_zidong(self) + self.create_zidong_trd.sin_out.connect(self.text_display) + self.pushButton_15.clicked.connect(self.creat_zidong_btn) + + ## 清空单元格线程 + self.clear_cell_trd = clear_cell(self) + self.clear_cell_trd.sin_out.connect(self.text_display) + self.pushButton_14.clicked.connect(self.clear_cell_btn) + + ## 提取表格内容线程 + self.get_content_trd = get_content(self) + self.get_content_trd.sin_out.connect(self.text_display) + self.pushButton_19.clicked.connect(self.get_content_btn) + + ## 部件测试调用关系表格线程 + self.create_bujian_trd = create_bujian(self) + self.create_bujian_trd.sin_out.connect(self.text_display) + self.pushButton_28.clicked.connect(self.create_bujian_btn) + + ## FPGA记录填写表格线程 + self.create_FPGA_record_trd = create_FPGA_record(self) + self.create_FPGA_record_trd.sin_out.connect(self.text_display) + self.pushButton_30.clicked.connect(self.create_FPGA_record_btn) + + ## FPGA记录转为说明线程 + self.create_FPGA_JtoS_trd = create_FPGA_JtoS(self) + self.create_FPGA_JtoS_trd.sin_out.connect(self.text_display) + self.pushButton_32.clicked.connect(self.create_FPGA_JtoS_btn) + + # 自定义信号连接 + # 获取状态栏对象 + self.user_statusbar = self.statusBar() + # 右下角窗口尺寸调整符号 + self.user_statusbar.setSizeGripEnabled(True) + self.user_statusbar.setStyleSheet("QStatusBar.item{border:10px}") + + #~~~~~~~~~~~~~~~按钮连接函数~~~~~~~~~~~~~~~~ + ##选择文件按钮连接 + self.pushButton.clicked.connect(self.choose_docx_func) + self.pushButton_4.clicked.connect(self.choose_docx_func) + self.pushButton_7.clicked.connect(self.choose_docx_func) + self.pushButton_11.clicked.connect(self.choose_docx_func) + self.pushButton_16.clicked.connect(self.choose_docx_func) + self.pushButton_17.clicked.connect(self.choose_docx_func) + self.pushButton_27.clicked.connect(self.choose_docx_func) + self.pushButton_29.clicked.connect(self.choose_docx_func) + self.pushButton_31.clicked.connect(self.choose_docx_func) + #清空显示区 + self.pushButton_9.clicked.connect(self.clear_textEdit_content) + #显示帮助 + self.pushButton_10.clicked.connect(self.display_help) + + #~~~~~~~~~~~~~~~导航栏按钮连接函数~~~~~~~~~~~~~~~~ + #显示关于本软件的菜单 + self.actionAbout.triggered.connect(self.display_about) + #打开文件夹 + self.actionopen.triggered.connect(self.choose_docx_func) + #打开IEEE754转换工具 + self.actionIEEE754.triggered.connect(self.open_zhuan_tool) + + if debug: + logging.debug("界面加载完成...") + +#~~~~~~~~~~~~~~~~~~~~初始化直接运行的函数(也就是起始运行一次)~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#~~~~~~~~~~~~~~~~~~~~间接按钮函数,用户点击后操作~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +#清空显示区函数 + + def clear_textEdit_content(self): + self.textBrowser.clear() + return + + #显示帮助函数 + def display_help(self): + txt_path = Path.cwd() / 'need' / 'others' / 'readme.txt' + with open(txt_path, 'r', encoding='utf-8') as f: + data = f.read() + self.textBrowser.append(data) + return + + #显示关于函数 + def display_about(self): + dlg = QDialog() + about_dlg = about.Ui_Dialog() + about_dlg.setupUi(dlg) + dlg.show() + dlg.exec_() + print("显示关于界面") + return + + #显示IEEE754转换工具 + def open_zhuan_tool(self): + dlg_zhuan = zhuan_dlg() #实例化界面 + dlg_zhuan.show() + dlg_zhuan.exec_() + return + +#~~~~~~~~~~~~~~~~~~~~线程区域函数,用于启动线程~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +#生成测试说明启动函数 + + def create_shuoming_btn(self): + self.create_shuoming_trd.start() + self.tabWidget.setEnabled(False) + return + +# 大纲追溯线程启动函数 + + def creat_dagang_zhuisu_btn(self): + self.create_dagang_zhuisu_trd.start() + self.tabWidget.setEnabled(False) + +# 说明追溯线程启动函数 + + def creat_shuoming_zhuisu_btn(self): + self.create_shuoming_zhuisu_trd.start() + self.tabWidget.setEnabled(False) + +# 提取单元格标题右侧内容线程启动函数 + + def create_baogao_zhuisu_btn(self): + self.create_baogao_zhuisu_trd.start() + self.tabWidget.setEnabled(False) + +# 记录反向生成说明线程 + + def creat_shuomingfanxiang_btn(self): + self.create_shuomingfanxiang_trd.start() + self.tabWidget.setEnabled(False) + +# 单元测试报告转换为我们的用例线程 + + def creat_danyuan_btn(self): + self.create_danyuan_trd.start() + self.tabWidget.setEnabled(False) + +# 单元测试报告转换为我们的用例线程 + + def creat_jilu_btn(self): + self.create_jilu_trd.start() + self.tabWidget.setEnabled(False) + +# 自动填充线程 + + def creat_zidong_btn(self): + self.create_zidong_trd.start() + self.tabWidget.setEnabled(False) + +# 清空表格单元格内容 + + def clear_cell_btn(self): + self.clear_cell_trd.start() + self.tabWidget.setEnabled(False) + +# 提取单元格标题右侧内容线程启动函数 + + def get_content_btn(self): + self.get_content_trd.start() + self.tabWidget.setEnabled(False) + +# 部件测试提取调用启动线程函数 + + def create_bujian_btn(self): + self.create_bujian_trd.start() + self.tabWidget.setEnabled(False) + +# FPGA记录填写 + + def create_FPGA_record_btn(self): + self.create_FPGA_record_trd.start() + self.tabWidget.setEnabled(False) + +# FPGA记录转说明 + + def create_FPGA_JtoS_btn(self): + self.create_FPGA_JtoS_trd.start() + self.tabWidget.setEnabled(False) + +#选择文档函数 + + def choose_docx_func(self): + self.open_file_name = QFileDialog.getOpenFileName( + self, '选择文件', '.', "Word files(*.docx)") + self.textBrowser.append('已选择文件路径:' + self.open_file_name[0]) + +#关闭线程函数 + + def stop_shuoming_thread(self): + self.tabWidget.setEnabled(True) + QMessageBox.warning(self, '处理完毕', '文档处理完毕!') + print("停止线程成功!") + +#~~~~~~~~~~~~~~~~~~~~显示函数~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + def text_display(self, texttmp): + if texttmp[:9] == 'stoperror': + QMessageBox.warning(self, '处理完毕', '文档处理失败!') + self.tabWidget.setEnabled(True) + return + + if texttmp[:11] == 'stopsuccess': + self.stop_shuoming_thread() + self.tabWidget.setEnabled(True) + return + + if texttmp[:6] == 'total:': + cnt = int(texttmp[6:]) + self.progressBar.setRange(0, cnt - 1) + + if texttmp == 'function success': + QMessageBox.information(self, '操作成功', '请查看本程序当前文件夹下的相关文档!') + self.textBrowser.append('完成!!!') + self.tabWidget.setEnabled(True) + return + if texttmp == '保存文件错': + QMessageBox.warning(self, '出错了', '保存文件失败!') + self.tabWidget.setEnabled(True) + return + if texttmp == 'no folder': + QMessageBox.information(self, '没有选择文件夹', '还没有选择文件夹,点击"文件"菜单进行选择!') + self.tabWidget.setEnabled(True) + return + if texttmp.find('warning:') != -1: + QMessageBox.information(self, 'WARNING', texttmp[8:]) + self.tabWidget.setEnabled(True) + return + + if texttmp.find('open failed:') != -1: + QMessageBox.warning( + self, '打开文件失败', + '打开' + texttmp[12:] + '失败' + '请确认文档是否打开或者模板文件存在且后缀名为docx!') + self.tabWidget.setEnabled(True) + return + if texttmp == 'nofile': + QMessageBox.information(self, '错误', + '还没有选择文件(夹),点击"文件"菜单或者工具栏进行选择!') + self.tabWidget.setEnabled(True) + return + if texttmp.isdigit() == True: + self.progressBar.setValue(int(texttmp)) + self.tabWidget.setEnabled(True) + else: + self.textBrowser.append(texttmp) + self.tabWidget.setEnabled(True) + # 如果前面是all_doned:则进度条填满 + if texttmp.find('all_doned:') != -1: + self.progressBar.setRange(0, 100) + self.progressBar.setValue(100) + + def closeEvent(self, event): + reply = QMessageBox.question(self, '提示', "是否要关闭所有窗口?", + QMessageBox.Yes | QMessageBox.No, + QMessageBox.No) + if reply == QMessageBox.Yes: + event.accept() + sys.exit(0) # 退出程序 + else: + event.ignore() + + +################################################################################## +#大纲生成测试说明线程 +################################################################################## +class create_shuoming(QtCore.QThread): + sin_out = pyqtSignal(str) + + def __init__(self, parent): + super().__init__() + self.parent = parent + + def run(self): + #用来储存测试项DC等转换 + zhuan_dict = {'DC':'文档审查','SU':'功能测试','CR':'代码审查','SA':'静态分析','AC':'性能测试',\ + 'IO':'接口测试','SE':'安全性测试','BT':'边界测试','RE':'恢复性测试','ST':'强度测试',\ + 'AT':'余量测试','GUI':'人机交互界面测试','DP':'数据处理测试','JR':'兼容性测试',\ + 'LG':'逻辑测试','AZ':'安装性测试','TT':'时序测试','PA':'功耗分析'} + + self.sin_out.emit("进入军品大纲转说明......") + self.sin_out.emit("开始转换......") + #如果没有选择路径则退出 + if not self.parent.open_file_name: + self.sin_out.emit('nofile') + self.parent.tabWidget.setEnabled(True) + return + #告诉windows单线程 + pythoncom.CoInitialize() + #在用户选择的目录中查找大纲文档 + self.sin_out.emit('打开测评大纲文档...') + + #使用win32com打开-记得关闭 + #打开word应用 + self.w = DispatchEx('Word.Application') + #self.w.visible=True + self.w.DisplayAlerts = 0 + try: + dagangfile = self.w.Documents.Open(self.parent.open_file_name[0]) + except: + self.sin_out.emit('open failed:选择的文档') + self.w.Quit() + pythoncom.CoUninitialize() + self.parent.tabWidget.setEnabled(True) + return + + self.sin_out.emit('复制测试说明文档模板到本程序所在目录...') + curpath = Path.cwd() / 'need' + shuoming_path_tmp = curpath / 'document_templates' / '测试说明模板.docx' + print(shuoming_path_tmp) + if shuoming_path_tmp.is_file(): + self.sin_out.emit('已检测到有说明模板文件...') + else: + self.sin_out.emit('open failed:选择的文档') + return + + #创建一个字典来储存单个用例 + + data_list = [] + + #获取表格数量 + try: + csx_tb_count = dagangfile.Tables.Count + self.sin_out.emit('total:' + str(csx_tb_count)) + except: + self.sin_out.emit('不存在表格!') + QMessageBox.warning(self.parent, '出错了', '测试说明文档格式错误或者没有正确表格') + try: + dagangfile.Close() + except: + pass + self.w.Quit() + pythoncom.CoUninitialize() + self.parent.tabWidget.setEnabled(True) + return + + #循环表格 + yongli_count = 0 + #用来储存章节号中的DC、SU等标识,用于章节号判断 + is_fire_su = "" + #用来储存基本_分割后个数 + num_fenge = 3 + for i in range(csx_tb_count): + self.sin_out.emit(str(i)) + if dagangfile.Tables[i].Rows.Count > 2: + #注意win32com的Cell从1开始不是从0开始 + if dagangfile.Tables[i].Cell(1, + 1).Range.Text.find('测试项名称') != -1: + #一个用例不变内容获取 + dagangfile.Tables[i].Rows.First.Select() + zhangjiehao = self.w.Selection.Bookmarks("\headinglevel").\ + Range.Paragraphs(1).Range.ListFormat.ListString + zhangjieming = self.w.Selection.Bookmarks("\headinglevel").\ + Range.Paragraphs(1).Range.Text.rstrip('\r') + print("测试项所在章节号:", zhangjiehao) + #获取用例标识不加上序号_1 + basic_biaoshi = dagangfile.Tables[i].Cell( + 1, 4).Range.Text.rstrip()[:-2] + print("测试项标识为:", basic_biaoshi) + + #储存num_fenge的数值,初始化 + if yongli_count == 0: + num_fenge = len(basic_biaoshi.split("_")) + #获取测试用例名称Cell(4,2)整行 + info_ceshi_buzhou = dagangfile.Tables[i].Cell(4, + 2).Range.Text + info_ceshi_yuqi = dagangfile.Tables[i].Cell(9, + 2).Range.Text + #判断是否只有一行,如果只有一行处理表格 + if dagangfile.Tables[i].Cell( + 4, 2).Range.Paragraphs.Count <= 1: + + #缓存一个用例的data填入数据 + data = {'zhangjie':'','mingcheng':'','biaoshi':'','is_first':'1', \ + 'yueshu':'软件正常工作,环境连接正常', 'yongli_biaoshi':'','renyuan':'陈俊亦',\ + 'chushi':'外接设备或软件运行正常','csx_mingcheng':'','is_begin':'0',\ + 'zongsu':'',"zuhe":[],'csxbs':""} + zuhe_dict = {"buzhou": "", "yuqi": "", "xuhao": "1"} + try: + #填写一行情况下表格 + data['mingcheng'] = dagangfile.Tables[i].Cell( + 1, 2).Range.Text.rstrip('\r\x07') + #注意word中后面都有2个字符 + data['yongli_biaoshi'] = (basic_biaoshi + + "_1").replace( + 'XQ', 'YL') + data['zhangjie'] = zhangjiehao + data['csx_mingcheng'] = zhangjieming + data['biaoshi'] = basic_biaoshi + data['zongsu'] = dagangfile.Tables[i].Cell( + 3, 2).Range.Text[:-2] + + zuhe_dict["buzhou"] = dagangfile.Tables[i].Cell( + 4, 2).Range.Text.rstrip('\r\x07') + zuhe_dict["yuqi"] = dagangfile.Tables[i].Cell( + 9, 2).Range.Text.rstrip('\r\x07') + zuhe_dict["xuhao"] = '1' + data["zuhe"].append(zuhe_dict) + #判断是否为第一个测试类型,如果是修改章节号标识,则将章节号展示,如果和储存相同 + #则章节号不展示 + #首先获取测试项标识,分割成列表 + fenge = data['biaoshi'].split("_") + #获取当前测试项分割后的个数 + if len(fenge) == 4: + if fenge[-2] != is_fire_su: + is_fire_su = fenge[-2] + data['is_begin'] = "1" + data['csxbs'] = zhuan_dict[fenge[-2]] + elif len(fenge) == 3: + if fenge[-1] == 'DC' or fenge[ + -1] == 'CR' or fenge[-1] == 'SA': + if fenge[-1] != is_fire_su: + is_fire_su = fenge[-1] + data['is_begin'] = "1" + data['csxbs'] = zhuan_dict[fenge[-1]] + else: + if fenge[-2] != is_fire_su: + is_fire_su = fenge[-2] + data['is_begin'] = "1" + data['csxbs'] = zhuan_dict[fenge[-2]] + else: + if fenge[-1] != is_fire_su: + is_fire_su = fenge[-1] + data['is_begin'] = "1" + data['csxbs'] = zhuan_dict[fenge[-1]] + + if self.parent.lineEdit.text(): + data['renyuan'] = self.parent.lineEdit.text() + #将data加入data_list + data['is_first'] = "1" + data_list.append(data) + yongli_count += 1 + + self.sin_out.emit( + '###获取用例序号:{}'.format(yongli_count)) + self.sin_out.emit('###该用例标识为:{}'.format( + data['yongli_biaoshi'])) + except: + self.sin_out.emit( + f'$$$$$$$$$$$$第{str(i+1)}个表格处理失败$$$$$$$$$$$$') + pass + + elif dagangfile.Tables[i].Cell( + 4, 2).Range.Paragraphs.Count > 1: + + try: + #下面拆分每行,使用\r(回车)分割 + info_buzhou_list = list( + filter(lambda x: x != "\x07" and x != "", + info_ceshi_buzhou.split('\r'))) + info_yuqi_list = list( + filter(lambda x: x != "\x07" and x != "", + info_ceshi_yuqi.split('\r'))) + + #去掉括号和以下字符 + rule = "[;;。]" #rule为去掉的符号(这个可以改TODO) + + #初始化去掉rule的列表 + buzhou_list = [] + yuqi_list = [] + + for item in info_buzhou_list: + index = item.find("(") + if index != -1: + item = item[index + 1:] + index = item.find("(") + if index != -1: + item = item[index + 1:] + index = item.find(")") + if index != -1: + item = item[index + 1:] + index = item.find(")") + if index != -1: + item = item[index + 1:] + buzhou_list.append( + re.sub(rule, "", + item).lstrip(string.digits)) + for item in info_yuqi_list: + index = item.find("(") + if index != -1: + item = item[index + 1:] + index = item.find("(") + if index != -1: + item = item[index + 1:] + index = item.find(")") + if index != -1: + item = item[index + 1:] + index = item.find(")") + if index != -1: + item = item[index + 1:] + yuqi_list.append( + re.sub(rule, "", + item).lstrip(string.digits)) + + #获取测试项综述-为该循环前不变内容 + basic_zongshu = buzhou_list.pop(0).strip() + print('获取的测试用例综述是:', data["zongsu"]) + + #获取字典中的buzhou和yuqi,找冒号 + j = -1 #自制列表索引 + substrict_list = [] #差值列表 + for item in buzhou_list: + #先找到冒号所在索引 + j = j + 1 + if item.find(":") != -1 or item.find( + ":") != -1: + #现在知道冒号所在行号,现在要确定每个用例几行 + substrict_list.append(j) + + #!!!注意差值计算步骤需要-1才是正确的步骤数量 + # self.sin_out.emit("解析测试项序号"+ str(i) + "|检测到冒号所在行号为:" \ + # + str(substrict_list)) + # self.sin_out.emit("|检测到步骤总行数(序号):" \ + # + str(len(buzhou_list))) + + #循环用例个数 + count_test = len(substrict_list) + temp_list = substrict_list + temp_list.append(len(buzhou_list)) + + for item in range(count_test): + #初始化data数据,包括步骤和预期、序号dict + data = {'zhangjie':'','mingcheng':'','biaoshi':'','is_first':'0', \ + 'yueshu':'软件正常工作,环境连接正常', 'yongli_biaoshi':'','renyuan':'陈俊亦',\ + 'chushi':'外接设备或软件运行正常','csx_mingcheng':'','is_begin':'0',\ + 'zongsu':'',"zuhe":[],'csxbs':""} + + #这里要求冒号最后一个 + data['mingcheng'] = buzhou_list[ + substrict_list[item]][:-1] + data['yongli_biaoshi'] = ( + basic_biaoshi + f'_{item+1}').replace( + 'XQ', 'YL') + #常规填入 + data['zhangjie'] = zhangjiehao + data['csx_mingcheng'] = zhangjieming + data['biaoshi'] = basic_biaoshi + data['zongsu'] = basic_zongshu + #步骤填入,首先根据substrict_list获取有几个步骤 + + #循环行数 + for x in range(temp_list[item + 1] - + (temp_list[item] + + 1)): #循环一个用例步骤预期数 + zuhe_dict = { + "buzhou": "", + "yuqi": "", + "xuhao": "" + } + #把每个步骤和预期都放进zuhe_dict中 + zuhe_dict["buzhou"] = buzhou_list[ + temp_list[item] + x + 1] + zuhe_dict["yuqi"] = yuqi_list[ + temp_list[item] + x + 1] + zuhe_dict["xuhao"] = str(x + 1) + data["zuhe"].append(zuhe_dict) + + if item == 0: + data['is_first'] = '1' + #判断是否为SU标题 + fenge = data['biaoshi'].split("_") + #获取当前测试项分割后的个数 + if len(fenge) == 4: + if fenge[-2] != is_fire_su: + is_fire_su = fenge[-2] + data['is_begin'] = "1" + data['csxbs'] = zhuan_dict[fenge[-2]] + elif len(fenge) == 3: + if fenge[-1] == 'DC' or fenge[ + -1] == 'CR' or fenge[-1] == 'SA': + if fenge[-1] != is_fire_su: + is_fire_su = fenge[-1] + data['is_begin'] = "1" + data['csxbs'] = zhuan_dict[ + fenge[-1]] + else: + if fenge[-2] != is_fire_su: + is_fire_su = fenge[-2] + data['is_begin'] = "1" + data['csxbs'] = zhuan_dict[ + fenge[-2]] + else: + if fenge[-1] != is_fire_su: + is_fire_su = fenge[-1] + data['is_begin'] = "1" + data['csxbs'] = zhuan_dict[fenge[-1]] + if self.parent.lineEdit.text(): + data[ + 'renyuan'] = self.parent.lineEdit.text( + ) + #加入data_list + data_list.append(data) + yongli_count += 1 #用例计数加一 + + self.sin_out.emit( + '###获取用例序号:{}'.format(yongli_count)) + self.sin_out.emit('###该用例标识为:{}'.format( + data['yongli_biaoshi'])) + except: + self.sin_out.emit( + f'$$$$$$$$$$$$第{str(i+1)}个表格处理失败$$$$$$$$$$$$') + pass + + #关闭大纲文档(因为以及提取完毕) + try: + dagangfile.Close() + self.w.Quit() + pythoncom.CoUninitialize() + except: + self.sin_out.emit('function fail') + self.w.Quit() + pythoncom.CoUninitialize() + return + + #打开模板文件进行渲染,然后就是用docxtpl生成用例 + try: + tpl_path = Path.cwd( + ) / "need" / "document_templates" / "测试说明模板.docx" + self.sin_out.emit('导入模板文件路径为:' + str(tpl_path)) + tpl = DocxTemplate(tpl_path) #模板导入成功 + + except: + QMessageBox.warning(self.parent, "出错了", "导入模板出错请检查模板文件是否存在或名字不正确") + return + + #开始渲染模板文件-有2层循环 + try: + context = { + "tables": data_list, + } + tpl.render(context) + tpl.save("生成的说明文档.docx") + self.sin_out.emit('stopsuccess') + except: + self.sin_out.emit('stoperror') + return + + +################################################################################## +#大纲生成追踪关系 +################################################################################## +class create_dagang_zhuisu(QtCore.QThread): + sin_out = pyqtSignal(str) + + def __init__(self, parent): + super().__init__() + self.parent = parent + + def run(self): + self.sin_out.emit("进入大纲追踪线程......") + self.sin_out.emit("开始填写追踪......") + + #如果没有选择路径则退出 + if not self.parent.open_file_name: + self.sin_out.emit('nofile') + self.parent.tabWidget.setEnabled(True) + return + #告诉windows单线程 + pythoncom.CoInitialize() + #在用户选择的目录中查找大纲文档 + self.sin_out.emit('打开测评大纲文档...') + + #使用win32com打开-记得关闭 + #打开word应用 + self.w = DispatchEx('Word.Application') + #self.w.visible=True + self.w.DisplayAlerts = 0 + try: + dagangfile = self.w.Documents.Open(self.parent.open_file_name[0]) + except: + self.sin_out.emit('open failed:选择的文档') + self.w.Quit() + pythoncom.CoUninitialize() + self.parent.tabWidget.setEnabled(True) + return + + curpath = Path.cwd() / 'need' + zhuisu_path_tmp = curpath / 'document_templates' / '大纲追踪模板.docx' + print(zhuisu_path_tmp) + + if zhuisu_path_tmp.is_file(): + self.sin_out.emit('已检测到有追溯模板文件...') + else: + self.sin_out.emit('open failed:选择的文档') + return + + #创建个列表放数据 + data_list = [] + data2_list = [] + + try: + csx_tb_count = dagangfile.Tables.Count + self.sin_out.emit('total:' + str(csx_tb_count)) + except: + self.sin_out.emit('不存在表格!') + QMessageBox.warning(self.parent, '出错了', '测试说明文档格式错误或者没有正确表格') + try: + dagangfile.Close() + except: + pass + self.w.Quit() + pythoncom.CoUninitialize() + self.parent.tabWidget.setEnabled(True) + return + + for i in range(csx_tb_count): + self.sin_out.emit(str(i)) + self.sin_out.emit("正在处理第{}个表格...".format(str(i))) + print("正在处理第{}个表格...".format(str(i))) + #准备填入的data + data = { + 'xuqiu': [], + 'dg_zhangjie': '', + 'mingcheng': '', + 'biaoshi': '' + } + data2 = { + 'xuqiu': [], + 'dg_zhangjie': '', + 'mingcheng': '', + 'biaoshi': '' + } + if dagangfile.Tables[i].Rows.Count > 2: + #注意win32com的Cell从1开始不是从0开始 + if dagangfile.Tables[i].Cell(1, + 1).Range.Text.find('测试项名称') != -1: + #一个用例不变内容获取 + dagangfile.Tables[i].Rows.First.Select() #获取测试项章节号 + zhangjiehao = self.w.Selection.Bookmarks("\headinglevel").\ + Range.Paragraphs(1).Range.ListFormat.ListString #获取测试项章节名 + zhangjieming = self.w.Selection.Bookmarks("\headinglevel").\ + Range.Paragraphs(1).Range.Text.rstrip('\r') + biaoshi = dagangfile.Tables[i].Cell( + 1, 4).Range.Text.rstrip()[:-2] + + #获取需规的章节号和描述 + if dagangfile.Tables[i].Cell( + 2, 1).Range.Text.find("追踪关系") != -1: + zhuizong_tmp = dagangfile.Tables[i].Cell( + 2, 2).Range.Text[:-2] + #由于有/的存在,先判断/和隐含需求 + zhuizong_list = zhuizong_tmp.split("\r") + print(zhuizong_list) + if zhuizong_tmp == "/" or zhuizong_tmp == "隐含需求": + xuqiu_dict = { + 'xq_zhangjie': '/', + 'xq_miaoshu': '/' + } + data['xuqiu'].append(xuqiu_dict) + data2['xuqiu'].append(xuqiu_dict) + else: + if len(zhuizong_list) >= 1: + for item in zhuizong_list: + xuqiu_dict = {} + if item.find("需求") != -1: + try: + match_string = re.search( + "\d(.\d+)+", item).group() + match_ming = item.split( + match_string)[-1] + xuqiu_dict[ + 'xq_zhangjie'] = match_string + xuqiu_dict[ + 'xq_miaoshu'] = match_ming.lstrip( + " ") + data['xuqiu'].append(xuqiu_dict) + except: + self.sin_out.emit( + f'$$$$$$$$$$$$第{str(i+1)}个表格无章节号$$$$$$$$$$$$' + ) + self.sin_out.emit( + "转换终止!请检查表格中追踪关系有无章节号") + pass + else: + try: + match_string = re.search( + "\d(.\d+)+", item).group() + match_ming = item.split( + match_string)[-1] + xuqiu_dict[ + 'xq_zhangjie'] = match_string + xuqiu_dict[ + 'xq_miaoshu'] = match_ming.lstrip( + " ") + data2['xuqiu'].append(xuqiu_dict) + except: + self.sin_out.emit( + f'$$$$$$$$$$$$第{str(i+1)}个表格无章节号$$$$$$$$$$$$' + ) + self.sin_out.emit( + "转换终止!请检查表格中追踪关系有无章节号") + pass + + #如果追踪关系行数小于1行的情况 + else: + xuqiu_dict = { + 'xq_zhangjie': '/', + 'xq_miaoshu': '/' + } + data['xuqiu'].append(xuqiu_dict) + data2['xuqiu'].append(xuqiu_dict) + + try: + data['dg_zhangjie'] = zhangjiehao + data['mingcheng'] = zhangjieming + data['biaoshi'] = biaoshi + data_list.append(data) + data2['dg_zhangjie'] = zhangjiehao + data2['mingcheng'] = zhangjieming + data2['biaoshi'] = biaoshi + data2_list.append(data2) + except: + print("获取追踪出错啦!") + self.sin_out.emit( + f'$$$$$$$$$$$$第{str(i+1)}个表格追踪处理失败$$$$$$$$$$$$' + ) + pass + + #最后关闭文档 + try: + self.w.Quit() + pythoncom.CoUninitialize() + self.parent.tabWidget.setEnabled(True) + except: + QMessageBox.warning(self.parent, "关闭文档失败", "关闭文档失败!") + return + + try: + tpl_path = Path.cwd( + ) / "need" / "document_templates" / "大纲追踪模板.docx" + self.sin_out.emit('导入模板文件路径为:' + str(tpl_path)) + tpl = DocxTemplate(tpl_path) #模板导入成功 + + except: + QMessageBox.warning(self.parent, "出错了", "导入模板出错请检查模板文件是否存在或名字不正确") + return + + #开始渲染模板文件 + try: + context = { + "tables": data_list, + "tables2": data2_list, + } + tpl.render(context) + tpl.save("生成的大纲追踪文档.docx") + self.sin_out.emit('stopsuccess') + except: + QMessageBox.warning(self.parent, "生成文档出错", + "生成文档错误,请确认模板文档是否已打开或格式错误") + self.sin_out.emit('stoperror') + return + + +################################################################################## +#单元测试UAS转换 +################################################################################## +class create_danyuan(QtCore.QThread): + sin_out = pyqtSignal(str) + + def __init__(self, parent): + super().__init__() + self.parent = parent + + def run(self): + self.sin_out.emit("进入单元测试SunwiseAUnit转换线程......") + self.sin_out.emit("开始填写文档......") + + #如果没有选择路径则退出 + if not self.parent.open_file_name: + self.sin_out.emit('nofile') + self.parent.tabWidget.setEnabled(True) + return + + #告诉windows单线程 + pythoncom.CoInitialize() + #在用户选择的目录中查找UAS单位测试报告文档 + self.sin_out.emit('打开单元测试原文件...') + + #使用win32com打开-记得关闭 + #打开word应用 + self.w = DispatchEx('Word.Application') + #self.w.visible=True + self.w.DisplayAlerts = 0 + try: + danyuanfile = self.w.Documents.Open(self.parent.open_file_name[0]) + except: + self.sin_out.emit('open failed:选择的文档') + self.w.Quit() + pythoncom.CoUninitialize() + self.parent.tabWidget.setEnabled(True) + return + + curpath = Path.cwd() / 'need' + danyuan_file_tmp = curpath / 'document_templates' / 'SunwiseAUnit单元测试转换模板.docx' + print(danyuan_file_tmp) + + if danyuan_file_tmp.is_file(): + self.sin_out.emit('已检测到有追溯模板文件...') + else: + self.sin_out.emit('open failed:选择的文档') + return + + #创建个列表放数据-important + data_list = [] + + #try统计表格数量 + try: + csx_tb_count = danyuanfile.Tables.Count + self.sin_out.emit('total:' + str(csx_tb_count)) + self.sin_out.emit("正在调用word文档操作接口,可能会有点慢...") + except: + self.sin_out.emit('不存在表格!') + QMessageBox.warning(self.parent, '出错了', '测试说明文档格式错误或者没有正确表格') + try: + danyuanfile.Close() + except: + pass + self.w.Quit() + pythoncom.CoUninitialize() + self.parent.tabWidget.setEnabled(True) + return + + #开始处理表格-important + #我先统计有多少个生成的表格-即用例有多少个呗 + yongli_count = 0 + for i in range(csx_tb_count): + if danyuanfile.Tables[i].Rows.Count > 2: + #注意win32com的Cell从1开始不是从0开始 + if danyuanfile.Tables[i].Cell(1, + 1).Range.Text.find('用例名称') != -1: + yongli_count += 1 + + #yongli_num指向当前处理的用例 + yongli_num = 0 + hanshuming = '' + hanshuming_duibi = '' + wenjian = '' + wenjian_duibi = '' + for i in range(csx_tb_count): + self.sin_out.emit('正在处理的表格序号:' + str(yongli_num + 1)) + self.sin_out.emit(str(i)) + #准备填入的data + data = {'ruanjian_ming':'','ruanjian_biaoshi':'yongli_biaoshi','wenjian_ming':'',\ + 'hanshu_ming':'','bianlian_and_canshu':'','zhuang':[],\ + 'yuqi_jieguo':'','ceshi_jieguo':'','is_begin':'0','is_wenjian':'0'} + + #填入用户输入的软件名 + try: + data['ruanjian_ming'] = self.parent.lineEdit_2.text() + data['ruanjian_biaoshi'] = self.parent.lineEdit_3.text() + + except: + QMessageBox.critical(self.parent, "未填入数据", "请先填入软件名和软件标识或.C名称") + self.w.Quit() + pythoncom.CoUninitialize() + self.parent.tabWidget.setEnabled(True) + pass + + #找到函数名,这里容易出问题 + if danyuanfile.Tables[i].Rows.Count > 2: + if danyuanfile.Tables[i].Cell(1, + 1).Range.Text.find('功能描述') != -1: + danyuanfile.Tables[i].Cell(1, 1).Range.Select() + self.w.Selection.MoveUp() + self.w.Selection.MoveUp() + self.w.Selection.MoveUp() + s = self.w.Selection.Paragraphs(1).Range.Text[:-1] + s1 = s.split(". ")[-1] + #放入函数名比对 + if s1 != hanshuming_duibi: + hanshuming_duibi = s1 + + #再向上看1行 + self.w.Selection.MoveUp() + temp2 = self.w.Selection.Paragraphs(1).Range.Text[:-1] + s2 = temp2.split("\\")[-1] + if '.' in temp2 and '\\' in temp2: + print('@@@@@@:', s2) + if s2 != wenjian_duibi: #这里有改动 + wenjian_duibi = s2 + + #找章节号 + if danyuanfile.Tables[i].Rows.Count > 2: + #注意win32com的Cell从1开始不是从0开始 + if danyuanfile.Tables[i].Cell(1, + 1).Range.Text.find('用例名称') != -1: + #TODO:如何找到测试模块? + biaoshi_temp = danyuanfile.Tables[i].Cell( + 1, 4).Range.Text[:-2] + data['yongli_biaoshi'] = biaoshi_temp + + #获取表格中参数组合() + quanju = danyuanfile.Tables[i].Cell(5, 3).Range.Text[:-2] + hcan = danyuanfile.Tables[i].Cell(6, 3).Range.Text[:-2] + qitashu = danyuanfile.Tables[i].Cell(7, 3).Range.Text[:-2] + + if quanju.find('无') != -1: + quanju = "" + if hcan.find('无') != -1: + hcan = "" + if qitashu.find('无') != -1: + qitashu = "" + + data['bianlian_and_canshu'] = quanju + hcan + qitashu + #将预期结果和测试结果填入 + data['yuqi_jieguo'] = danyuanfile.Tables[i].Cell( + 8, 2).Range.Text[:-2] + data['ceshi_jieguo'] = danyuanfile.Tables[i].Cell( + 13, 2).Range.Text[:-2] + #函数名获取 + if hanshuming_duibi != hanshuming: + hanshuming = hanshuming_duibi + data['is_begin'] = '1' + data['hanshu_ming'] = hanshuming_duibi + #文件名获取 + if wenjian_duibi != wenjian: + wenjian = wenjian_duibi + data['is_wenjian'] = '1' + data['wenjian_ming'] = wenjian_duibi + + data_list.append(data) + yongli_num += 1 #用例创建加一 + + elif danyuanfile.Tables[i].Cell(1, + 2).Range.Text.find('定义') != -1: + #定义个桩函数dict + zhuang_dict = {'zhuang_name':'','zhuang_dingyi':'','zhuang_fanhui':'',\ + 'zhuang_fuzuoyong':''} + + zhuang_dict['zhuang_name'] = danyuanfile.Tables[i].Cell( + 1, 1).Range.Text[:-2] + zhuang_dict['zhuang_dingyi'] = danyuanfile.Tables[i].Cell( + 1, 3).Range.Text[:-2] + zhuang_dict['zhuang_fanhui'] = danyuanfile.Tables[i].Cell(2, 3).Range.Paragraphs(1).\ + Range.Text[:-1] + + #副作用可能有多行 + fuzuoyong_temp = '' + for count_fuzuo in range( + len(danyuanfile.Tables[i].Cell( + 2, 3).Range.Paragraphs) - 2): + fuzuoyong_temp = fuzuoyong_temp + ';' + danyuanfile.Tables[i].Cell(2, 3).\ + Range.Paragraphs(count_fuzuo + 3).Range.Text[:-2].replace(" ", "") + zhuang_dict['zhuang_fuzuoyong'] = fuzuoyong_temp + + data_list[yongli_num - 1]['zhuang'].append(zhuang_dict) + + #最后关闭文档 + try: + self.w.Quit() + pythoncom.CoUninitialize() + self.parent.tabWidget.setEnabled(True) + except: + QMessageBox.warning(self.parent, "关闭文档失败", "关闭文档失败!") + return + + try: + tpl_path = Path.cwd( + ) / "need" / "document_templates" / "SunwiseAUnit单元测试转换模板.docx" + self.sin_out.emit('导入模板文件路径为:' + str(tpl_path)) + tpl = DocxTemplate(tpl_path) #模板导入成功 + except: + QMessageBox.warning(self.parent, "出错了", "导入模板出错请检查模板文件是否存在或名字不正确") + return + + #开始渲染模板文件 + try: + context = { + "tables": data_list, + } + tpl.render(context) + tpl.save("软件单元测试用例记录表.docx") + self.sin_out.emit('stopsuccess') + except: + self.sin_out.emit('stoperror') + return + + +################################################################################## +#测试说明追踪以及用例表 +################################################################################## +class create_shuoming_zhuisu(QtCore.QThread): + sin_out = pyqtSignal(str) + + def __init__(self, parent): + super().__init__() + self.parent = parent + + def run(self): + self.sin_out.emit("进入说明追踪线程......") + self.sin_out.emit("开始填写说明追踪以及用例表格......") + + # 如果没有选择文件 + if not self.parent.open_file_name: + self.sin_out.emit('nofile') + self.parent.tabWidget.setEnabled(True) + return + # 告诉windows单线程 + pythoncom.CoInitialize() + # 在用户选择的目录中查找大纲文档 + self.sin_out.emit('打开测试说明文档...') + + # 使用win32com打开-记得关闭 + # 打开word应用 + self.w = DispatchEx('Word.Application') + # self.w.visible=True + self.w.DisplayAlerts = 0 + try: + shuomingfile = self.w.Documents.Open(self.parent.open_file_name[0]) + except: + self.sin_out.emit('open failed:选择的文档') + self.w.Quit() + pythoncom.CoUninitialize() + self.parent.tabWidget.setEnabled(True) + return + + self.sin_out.emit('已正确打开说明文档...') + curpath = Path.cwd() / 'need' + zhuisu_path_tmp = curpath / 'document_templates' / '说明追踪模板.docx' + print("打开追踪模板文件", zhuisu_path_tmp) + + if zhuisu_path_tmp.is_file(): + self.sin_out.emit('已检测到有说明追溯模板文件...') + else: + self.sin_out.emit('open failed:选择的文档') + return + + # 创建个列表放数据 + data_list = [] + data2_list = [] + + #统计整个表格数量用于processbar显示进度 + try: + tb_count = shuomingfile.Tables.Count + self.sin_out.emit('total:' + str(tb_count)) + except: + self.sin_out.emit('不存在表格!') + QMessageBox.warning(self.parent, '出错了', '测试说明文档格式错误或者没有正确表格') + try: + shuomingfile.Close() + except: + QMessageBox.warning(self.parent, '错误', "未正确关闭Word文档!") + return + self.w.Quit() + pythoncom.CoUninitialize() + self.parent.tabWidget.setEnabled(True) + return + + #遍历循环表格,这里面就要初始化数据dict了 + #不能像大纲追踪一样data在循环表格里面 + #创建一个大纲测试项索引 + csx_name = '' + data = { + 'dg_zhangjie': '', + 'mingcheng': '', + 'biaoshi': '', + 'yongli': [], + 'index': 0 + } + for i in range(tb_count): + self.sin_out.emit(str(i)) + #self.sin_out.emit("正在处理第{}个表格...".format(str(i+1))) + print("正在处理第{}个表格...".format(str(i + 1))) + # 准备填入的data + data2 = { + 'yongli_ming': '', + 'yongli_biaoshi': '', + 'yongli_zongsu': '' + } + yongli_dict = {'yongli_ming': '', 'yongli_biaoshi': ''} + yongliming = '' + biaoshi = '' + zongsu = '' + zhui_temp = '' + + if shuomingfile.Tables[i].Rows.Count > 2: + try: + # 注意win32com的Cell从1开始不是从0开始 + if shuomingfile.Tables[i].Cell(1, 1).Range.Text.find('测试用例名称') != -1 or \ + shuomingfile.Tables[i].Cell(2, 1).Range.Text.find('测试用例名称') != -1: + #取出cell(1,,1)的数据 + table_heard = shuomingfile.Tables[i].Cell(1, + 1).Range.Text + if table_heard.find("测试用例名称") != -1: + yongliming = shuomingfile.Tables[i].Cell( + 1, 2).Range.Text.rstrip()[:-2] + biaoshi = shuomingfile.Tables[i].Cell( + 1, 4).Range.Text.rstrip()[:-2] + zongsu = shuomingfile.Tables[i].Cell( + 3, 2).Range.Text.rstrip()[:-2] + zhui_temp = shuomingfile.Tables[i].Cell( + 2, 2).Range.Text.rstrip()[:-2] + elif table_heard.find('用例') != -1: + yongliming = shuomingfile.Tables[i].Cell( + 2, 2).Range.Text.rstrip()[:-2] + biaoshi = shuomingfile.Tables[i].Cell( + 2, 4).Range.Text.rstrip()[:-2] + zongsu = shuomingfile.Tables[i].Cell( + 4, 2).Range.Text.rstrip()[:-2] + zhui_temp = shuomingfile.Tables[i].Cell( + 3, 2).Range.Text.rstrip()[:-2] + else: + self.sin_out.emit("未找到合适的填写数据,退出处理") + print("未找到合适的填写数据") + self.w.Quit() + pythoncom.CoUninitialize() + self.parent.tabWidget.setEnabled(True) + return + shuomingfile.Tables[i].Rows.First.Select() # 获取测试项章节号 + #############################目前模板不用获取用例章节号暂时省去 + # zhangjiehao = self.w.Selection.Bookmarks("\headinglevel"). \ + # Range.Paragraphs(1).Range.ListFormat.ListString # 获取测试项章节名 + ############################################################## + zhangjieming = self.w.Selection.Bookmarks("\headinglevel"). \ + Range.Paragraphs(1).Range.Text.rstrip('\r') + + yongli_dict['yongli_ming'] = yongliming + yongli_dict['yongli_biaoshi'] = biaoshi + data2['yongli_ming'] = yongliming + data2['yongli_biaoshi'] = biaoshi + data2['yongli_zongsu'] = zongsu + data2_list.append(data2) + print("当前yongli_dict为:", yongli_dict) + # 获取大纲的章节号和用例名,而且data按自己的来 + ## 按python行进行分割为列表 + zhui_list = zhui_temp.split("\r") + if len(zhui_list) == 3: + if zhui_list[1].find("需求") != -1: + #使用re模块正则表达式 + match_string = re.search( + "\d(.\d+)+", zhui_list[1]).group() + match_ming = zhui_list[1].split( + match_string)[-1] + #使用re.sub模块替换为空 + rules = "[)()(] " + match_ming = re.sub(rules, '', match_ming) + if zhui_list[2]: + rules = ":" + dg_biaoshi_temp = re.sub( + rules, ':', zhui_list[2]) + dg_biaoshi = dg_biaoshi_temp.split(":")[-1] + #判断是否是新的测试项,如果是新的索引index加1,创建新dict进入 + if zhangjieming != csx_name: + data_list.append(data) + data_index = data['index'] + 1 + data = { + 'dg_zhangjie': '', + 'mingcheng': '', + 'biaoshi': '', + 'yongli': [], + 'index': data_index + } + data['dg_zhangjie'] = match_string + data['mingcheng'] = match_ming + data['biaoshi'] = dg_biaoshi + data['yongli'].append(yongli_dict) + csx_name = zhangjieming + self.sin_out.emit("已处理第{}个测试项...".format( + data['index'])) + else: + data['yongli'].append(yongli_dict) + except: + self.sin_out.emit( + f'$$$$$$$$$$$$第{str(i+1)}个表格,获取单元格内容不存在$$$$$$$$$$$$') + pass + + # 最后关闭文档 + try: + self.w.Quit() + pythoncom.CoUninitialize() + self.parent.tabWidget.setEnabled(True) + except: + QMessageBox.warning(self.parent, "关闭文档失败", "关闭文档失败!") + return + + try: + tpl_path = Path.cwd( + ) / "need" / "document_templates" / "说明追踪模板.docx" + self.sin_out.emit('导入模板文件路径为:' + str(tpl_path)) + tpl = DocxTemplate(tpl_path) # 模板导入成功 + + except: + QMessageBox.warning(self.parent, "出错了", "导入模板出错请检查模板文件是否存在或名字不正确") + return + + # 开始渲染模板文件 + try: + context = { + "tables": data_list, + "tables2": data2_list, + } + tpl.render(context) + tpl.save("说明追踪文档.docx") + self.sin_out.emit('stopsuccess') + except: + self.sin_out.emit('stoperror') + return + + +################################################################################## +#根据说明生成测试记录线程 +################################################################################## +class create_jilu(QtCore.QThread): + sin_out = pyqtSignal(str) + + def __init__(self, parent): + super().__init__() + self.parent = parent + + def run(self): + #用来储存章节号转换 + zhuan_dict = {'DC':'文档审查','SU':'功能测试','CR':'代码审查','SA':'静态分析','AC':'性能测试',\ + 'IO':'接口测试','SE':'安全性测试','BT':'边界测试','RE':'恢复性测试','ST':'强度测试',\ + 'AT':'余量测试','GUI':'人机交互界面测试','DP':'数据处理测试','JR':'兼容性测试',\ + 'LG':'逻辑测试','AZ':'安装性测试','TT':'时序测试','PA':'功耗分析'} + + self.sin_out.emit("进入根据说明转换记录线程......") + self.sin_out.emit("开始转换......") + #如果没有选择文件则退出 + if not self.parent.open_file_name: + self.sin_out.emit('nofile') + self.parent.tabWidget.setEnabled(True) + return + pythoncom.CoInitialize() + self.sin_out.emit('打开说明文档...') + self.w = DispatchEx('Word.Application') + self.w.DisplayAlerts = 0 + try: + shuomingfile = self.w.Documents.Open(self.parent.open_file_name[0]) + except: + self.sin_out.emit('open failed:选择的文档') + self.w.Quit() + pythoncom.CoUninitialize() + self.parent.tabWidget.setEnabled(True) + return + self.sin_out.emit('复制测试记录文档模板到本程序所在目录...') + curpath = Path.cwd() / 'need' + shuoming_path_tmp = curpath / 'document_templates' / '说明生成记录模板.docx' + if shuoming_path_tmp.is_file(): + self.sin_out.emit('已检测到有记录模板文件...') + else: + self.sin_out.emit('open failed:选择的文档') + return + #创建一个字典来储存单个用例 + data_list = [] + #获取表格数量 + try: + csx_tb_count = shuomingfile.Tables.Count + self.sin_out.emit('total:' + str(csx_tb_count)) + except: + self.sin_out.emit('不存在表格,请检查文档!') + QMessageBox.warning(self.parent, '出错了', '测试说明文档格式错误或者没有正确表格') + try: + shuomingfile.Close() + except: + pass + self.w.Quit() + pythoncom.CoUninitialize() + self.parent.tabWidget.setEnabled(True) + return + + #用来储存章节号中的DC、SU等标识,用于章节号判断 + is_type_su = "" + #储存章节号标志 + is_fire_su = "" + for i in range(csx_tb_count): + self.sin_out.emit(str(i)) + self.sin_out.emit("正在处理第{}个表格".format(i + 1)) + try: + if shuomingfile.Tables[i].Rows.Count > 2: + if shuomingfile.Tables[i].Cell( + 2, 1).Range.Text.find('测试用例名称') != -1: + #一个用例不变内容获取 + try: + shuomingfile.Tables[i].Rows.First.Select() + #获取章节名,用于判断 + zhangjieming = self.w.Selection.Bookmarks("\headinglevel").\ + Range.Paragraphs(1).Range.Text.rstrip('\r') + #获取表格基本信息 + mingcheng = shuomingfile.Tables[i].Cell( + 2, 2).Range.Text[:-2] + biaoshi = shuomingfile.Tables[i].Cell( + 2, 4).Range.Text[:-2] + self.sin_out.emit(f"正在处理{biaoshi}用例{mingcheng}") + zhuizong = shuomingfile.Tables[i].Cell( + 3, 2).Range.Text[:-2] + zongsu = shuomingfile.Tables[i].Cell( + 4, 2).Range.Text[:-2] + chushihua = shuomingfile.Tables[i].Cell( + 5, 2).Range.Text[:-2] + qianti = shuomingfile.Tables[i].Cell( + 6, 2).Range.Text[:-2] + + #缓存一个data数据 + data = {'mingcheng':'','biaoshi':'','zhuizong':'','is_first':'0',\ + 'zongsu':'','chushihua':'','qianti':'','zuhe':[],'is_begin':'0',\ + 'csx_type':'','csx_name':''} + #获取步骤和预期 + step_count = shuomingfile.Tables[i].Rows.Count - 11 + for j in range(step_count): + buzhou_dict = { + 'buzhou': "", + 'yuqi': "", + 'xuhao': '' + } + buzhou_dict['buzhou'] = shuomingfile.Tables[ + i].Cell(j + 9, 2).Range.Text[:-2] + buzhou_dict['yuqi'] = shuomingfile.Tables[ + i].Cell(j + 9, 3).Range.Text[:-2] + buzhou_dict['xuhao'] = str(j + 1) + data['zuhe'].append(buzhou_dict) + + #开始判断当前是否为测试项的第一个,如果是第一个则is_first改为1 + if is_fire_su != zhangjieming: + is_fire_su = zhangjieming + data['is_first'] = '1' + + #判断测试类型,这里从标识里面获取 + biaoshi_list = biaoshi.split("_") + print('当前取的类型列表分割:', biaoshi_list) + if len(biaoshi_list) >= 4: + biaoshi_tmp = biaoshi_list[-3] + else: + biaoshi_tmp = biaoshi_list[1] + if biaoshi_tmp != is_type_su: + is_type_su = biaoshi_tmp + data['is_begin'] = '1' + if zhuan_dict[biaoshi_tmp] == '文档审查' or zhuan_dict[biaoshi_tmp] == '代码审查' or \ + zhuan_dict[biaoshi_tmp] == '静态分析': + data['is_first'] = '0' + + #data补全 + data['mingcheng'] = mingcheng + data['biaoshi'] = biaoshi + data['zhuizong'] = zhuizong.replace('\r', '\n') + data['zongsu'] = zongsu + data['chushihua'] = chushihua + data['qianti'] = qianti + data['csx_type'] = zhuan_dict[biaoshi_tmp] + data['csx_name'] = zhangjieming + data_list.append(data) + self.sin_out.emit("处理完毕{}用例".format(biaoshi)) + except: + self.sin_out.emit(f'错误!第{i+1}个表格处理失败!') + except: + self.sin_out.emit(f'错误!第{i+1}个表格处理失败!') + + #关闭大纲文档(因为以及提取完毕) + try: + shuomingfile.Close() + self.w.Quit() + pythoncom.CoUninitialize() + except: + self.sin_out.emit('function fail') + self.w.Quit() + pythoncom.CoUninitialize() + return + + #打开模板文件进行渲染,然后就是用docxtpl生成用例 + try: + tpl_path = Path.cwd( + ) / "need" / "document_templates" / "说明生成记录模板.docx" + self.sin_out.emit('导入模板文件路径为:' + str(tpl_path)) + tpl = DocxTemplate(tpl_path) #模板导入成功 + + except: + QMessageBox.warning(self.parent, "出错了", "导入模板出错请检查模板文件是否存在或名字不正确") + return + + #开始渲染模板文件-有2层循环 + try: + context = { + "tables": data_list, + "cs_renyuan": self.parent.lineEdit_4.text(), + "jc_renyuan": self.parent.lineEdit_5.text(), + "shijian": self.parent.lineEdit_6.text(), + } + tpl.render(context) + tpl.save("生成的测试记录文档.docx") + self.sin_out.emit('stopsuccess') + except: + self.sin_out.emit('stoperror') + return + + +################################################################################## +# 根据测试记录反向生成说明 +################################################################################## +class create_shuomingfanxiang(QtCore.QThread): + sin_out = pyqtSignal(str) + + def __init__(self, parent): + super().__init__() + self.parent = parent + + def run(self): + # 用来储存测试项DC等转换 + zhuan_dict = {'DC':'文档审查','SU':'功能测试','CR':'代码审查','SA':'静态分析','AC':'性能测试',\ + 'IO':'接口测试','SE':'安全性测试','BT':'边界测试','RE':'恢复性测试','ST':'强度测试',\ + 'AT':'余量测试','GUI':'人机交互界面测试','DP':'数据处理测试','JR':'兼容性测试',\ + 'LG':'逻辑测试','AZ':'安装性测试','TT':'时序测试','PA':'功耗分析'} + + self.sin_out.emit("进入测试记录转说明......") + self.sin_out.emit("开始转换......") + # 如果没有选择文件路径则退出 + if not self.parent.open_file_name: + self.sin_out.emit('nofile') + self.parent.tabWidget.setEnabled(True) + return + pythoncom.CoInitialize() + self.sin_out.emit('打开测试记录文件...') + self.w = DispatchEx('Word.Application') + #self.w.visible=True + self.w.DisplayAlerts = 0 + try: + jilufile = self.w.Documents.Open(self.parent.open_file_name[0]) + except: + self.sin_out.emit('open failed:选择的文档') + self.w.Quit() + pythoncom.CoUninitialize() + self.parent.tabWidget.setEnabled(True) + return + + self.sin_out.emit('复制测试说明文档模板到本程序所在目录...') + curpath = Path.cwd() / 'need' + shuoming_path_tmp = curpath / 'document_templates' / '反向测试说明模板.docx' + print(shuoming_path_tmp) + if shuoming_path_tmp.is_file(): + self.sin_out.emit('已检测到有说明模板文件...') + else: + self.sin_out.emit('open failed:选择的文档') + return + #创建一个字典来储存单个用例 + data_list = [] + #获取表格数量 + try: + csx_tb_count = jilufile.Tables.Count + self.sin_out.emit('total:' + str(csx_tb_count)) + except: + self.sin_out.emit('不存在表格!') + QMessageBox.warning(self.parent, '出错了', '测试说明文档格式错误或者没有正确表格') + try: + jilufile.Close() + except: + pass + self.w.Quit() + pythoncom.CoUninitialize() + self.parent.tabWidget.setEnabled(True) + return + + #初始化表格外全局变量 + is_fire_su = '' + is_type_su = '' + for i in range(csx_tb_count): + self.sin_out.emit(str(i)) + self.sin_out.emit(f"正在处理第{str(i+1)}个表格") + if jilufile.Tables[i].Rows.Count > 2: + if jilufile.Tables[i].Cell(2, + 1).Range.Text.find('测试用例名称') != -1: + #将表格中信息全部先拿出来 + try: + jilufile.Tables[i].Rows.First.Select() + zhangjieming = self.w.Selection.Bookmarks("\headinglevel").\ + Range.Paragraphs(1).Range.Text.rstrip('\r') + zhangjiehao = self.w.Selection.Bookmarks("\headinglevel").\ + Range.Paragraphs(1).Range.ListFormat.ListString + mingcheng = jilufile.Tables[i].Cell(2, + 2).Range.Text[:-2] + biaoshi = jilufile.Tables[i].Cell(2, 4).Range.Text[:-2] + self.sin_out.emit(f"正在处理{biaoshi}-用例{mingcheng}") + zhuizong = jilufile.Tables[i].Cell(3, + 2).Range.Text[:-2] + zongsu = jilufile.Tables[i].Cell(4, 2).Range.Text[:-2] + chushi = jilufile.Tables[i].Cell(5, 2).Range.Text[:-2] + qianti = jilufile.Tables[i].Cell(6, 2).Range.Text[:-2] + + #缓存一个data数据 + data = {'mingcheng':'','biaoshi':'','zhuizong':'','is_first':'0',\ + 'zongsu':'','chushi':'','qianti':'','zuhe':[],'is_begin':'0',\ + 'csx_type':'','csx_mingcheng':'','renyuan':''} + #获取步骤和预期 + step_count = jilufile.Tables[i].Rows.Count - 12 + #获取人员信息 + data['renyuan'] = jilufile.Tables[i].Cell( + 10 + step_count, 2).Range.Text[:-2] + for j in range(step_count): + buzhou_dict = { + 'buzhou': "", + 'yuqi': "", + 'xuhao': '' + } + buzhou_dict['buzhou'] = jilufile.Tables[i].Cell( + j + 9, 2).Range.Text[:-2] + buzhou_dict['yuqi'] = jilufile.Tables[i].Cell( + j + 9, 3).Range.Text[:-2] + buzhou_dict['xuhao'] = str(j + 1) + data['zuhe'].append(buzhou_dict) + + # 开始判断当前是否为测试项的第一个,如果是第一个则is_first改为1 + if is_fire_su != zhangjieming: + is_fire_su = zhangjieming + data['is_first'] = '1' + # 判断测试类型,这里从标识里面获取 + biaoshi_list = biaoshi.split("_") + print('当前取的类型列表分割:', biaoshi_list) + if len(biaoshi_list) >= 4: + biaoshi_tmp = biaoshi_list[-4] + else: + biaoshi_tmp = biaoshi_list[1] + if biaoshi_tmp != is_type_su: + is_type_su = biaoshi_tmp + data['is_begin'] = '1' + if zhuan_dict[biaoshi_tmp] == '文档审查' or zhuan_dict[biaoshi_tmp] == '代码审查' or \ + zhuan_dict[biaoshi_tmp] == '静态分析': + data['is_first'] = '0' + + #data补全 + data['mingcheng'] = mingcheng + data['biaoshi'] = biaoshi + data['zhuizong'] = zhuizong.replace('\r', '\n') + data['zongsu'] = zongsu + data['chushi'] = chushi + data['qianti'] = qianti + data['csx_type'] = zhuan_dict[biaoshi_tmp] + data['csx_mingcheng'] = zhangjieming + data_list.append(data) + self.sin_out.emit("处理完毕{}用例".format(biaoshi)) + except: + self.sin_out.emit("第{}个表格处理失败,请检查".format(str(i + 1))) + pass + + else: + self.sin_out.emit( + "该表格生成错误,请检查是否存在用例序号,每个用例必须有序号且必须包含【记录】两个字...") + else: + self.sin_out.emit("该表格生成错误,请检查表格是否存在并大于2行...") + + #关闭大纲文档(因为以及提取完毕) + try: + jilufile.Close() + self.w.Quit() + pythoncom.CoUninitialize() + except: + self.sin_out.emit('function fail') + self.w.Quit() + pythoncom.CoUninitialize() + return + + #打开模板文件进行渲染,然后就是用docxtpl生成用例 + try: + tpl_path = Path.cwd( + ) / "need" / "document_templates" / "反向测试说明模板.docx" + self.sin_out.emit('导入模板文件路径为:' + str(tpl_path)) + tpl = DocxTemplate(tpl_path) #模板导入成功 + + except: + QMessageBox.warning(self.parent, "出错了", "导入模板出错请检查模板文件是否存在或名字不正确") + return + + #开始渲染模板文件-有2层循环 + try: + context = { + "tables": data_list, + } + tpl.render(context) + tpl.save("反向生成的说明文档.docx") + self.sin_out.emit('stopsuccess') + except: + self.sin_out.emit('stoperror') + return + + +################################################################################## +#自动填充单元格线程 +################################################################################## +class create_zidong(QtCore.QThread): + sin_out = pyqtSignal(str) + + def __init__(self, parent): + super().__init__() + self.parent = parent + + def run(self): + self.sin_out.emit('开始...') + if self.parent.open_file_name == '': + self.sin_out.emit('请点击“选择文档”按钮选择要填充的文档') + self.parent.tabWidget.setEnabled(True) + QMessageBox.warning(self.parent, '出错了!', '请选择要填充的文档!') + return + try: + t_s_file = docx.Document(self.parent.open_file_name[0]) + except: + self.sin_out.emit('open failed:选择的文档') + self.parent.tabWidget.setEnabled(True) + QMessageBox.warning(self.parent, '出错了!', + '打开选择的文档失败,请确认文档类型为docx,且未被打开!') + return + if self.parent.lineEdit_9.text() == '': + self.sin_out.emit('单元格左侧不能为空!!!!') + self.parent.tabWidget.setEnabled(True) + QMessageBox.warning(self.parent, '出错了!', '单元格标题不能为空!') + return + if self.parent.lineEdit_10.text() == '': + self.sin_out.emit('确定填充内容为空吗?填充内容为空相当于清空操作。可直接点击清空按钮!!') + self.parent.tabWidget.setEnabled(True) + QMessageBox.warning(self.parent, '警告!', + '确定填充内容为空吗?填充内容为空相当于清空操作。可点击清空按钮!!') + return + tmp_fill = self.parent.lineEdit_11.text() + if tmp_fill == '': + tmp_fill = str(len(t_s_file.tables)) + + if (tmp_fill.strip().isdigit()) and (int(tmp_fill.strip()) < len( + t_s_file.tables)): + tmp_ran = int(tmp_fill) + else: + tmp_ran = len(t_s_file.tables) + + tmp_fillnum = 0 + k = 0 + + self.sin_out.emit('total:' + str(tmp_ran)) + + self.parent.progressBar.setRange(0, tmp_ran - 1) + for ft1 in t_s_file.tables: + k += 1 + self.sin_out.emit(str(k)) + self.parent.progressBar.setValue(k) + tmp_row = 0 + for r in ft1.rows: + tmpflag = 0 + tmp_column = 0 + for cell in r.cells: + if cell.text.strip() == self.parent.lineEdit_9.text(): + while ft1.cell(tmp_row, tmp_column).text.strip( + ) == self.parent.lineEdit_9.text(): + tmp_column += 1 + #这里如果需要替换还是不替换 + if ft1.cell(tmp_row, tmp_column).text == '': + ft1.cell(tmp_row, tmp_column + ).text = self.parent.lineEdit_10.text() + tmp_fillnum += 1 + else: + pass + tmpflag = 1 + break + else: + tmp_column += 1 + if tmpflag == 1: + break + tmp_row += 1 + if tmp_fillnum >= int(tmp_fill): + break + + try: + t_s_file.save(self.parent.open_file_name[0]) + self.sin_out.emit('function success') + self.parent.tabWidget.setEnabled(True) + return + except: + self.parent.tabWidget.setEnabled(True) + self.sin_out.emit('function fail') + QMessageBox.information(self.parent, '', '填充完成!') + return + + +################################################################################## +#清空单元格线程 +################################################################################## +class clear_cell(QtCore.QThread): + sin_out = pyqtSignal(str) + + def __init__(self, parent): + super().__init__() + self.parent = parent + + def run(self): + self.sin_out.emit('开始...') + if self.parent.open_file_name == '': + self.sin_out.emit('请点击“选择文档”按钮选择要填充的文档') + self.parent.tabWidget.setEnabled(True) + QMessageBox.warning(self.parent, '出错了!', '请选择要填充的文档!') + return + try: + t_s_file = docx.Document(self.parent.open_file_name[0]) + except: + self.sin_out.emit('open failed:要填充的文档') + QMessageBox.warning(self.parent, '出错了!', + '打开选择的文档失败,请确认文档类型为docx,且未被打开!') + self.parent.tabWidget.setEnabled(True) + return + if self.parent.lineEdit_9.text() == '': + self.parent.tabWidget.setEnabled(True) + self.sin_out.emit('单元格标题不能为空!') + QMessageBox.warning(self.parent, '出错了!', '单元格标题不能为空!') + return + tmp_tblcnt = len(t_s_file.tables) + k = 0 + self.sin_out.emit('total:' + str(tmp_tblcnt)) + for ft1 in t_s_file.tables: + k += 1 + self.sin_out.emit(str(k)) + tmp_row = 0 + for r in ft1.rows: + tmpflag = 0 + tmp_column = 0 + for cell in r.cells: + + if cell.text.strip() == self.parent.lineEdit_9.text(): + while ft1.cell(tmp_row, tmp_column).text.strip( + ) == self.parent.lineEdit_9.text(): + tmp_column += 1 + + ft1.cell(tmp_row, tmp_column).text = '' + tmpflag = 1 + break + else: + tmp_column += 1 + if tmpflag == 1: + break + tmp_row += 1 + try: + t_s_file.save(self.parent.open_file_name[0]) + self.sin_out.emit('function success') + self.parent.tabWidget.setEnabled(True) + return + except: + self.parent.tabWidget.setEnabled(True) + self.sin_out.emit('function fail') + QMessageBox.information(self.parent, '', '清空单元格成功!') + return + + +################################################################################## +#提取表格内容线程 +################################################################################## +class get_content(QtCore.QThread): + sin_out = pyqtSignal(str) + + def __init__(self, parent): + super().__init__() + self.parent = parent + + #获取文档中表格内容函数 + def run(self): + curpath = Path.cwd() + content_tmp = curpath / 'need' / 'document_templates' / 'get_content.docx' + shutil.copy(content_tmp, curpath) + content_tmp_path = curpath / 'get_content.docx' + print(content_tmp_path) + try: + #c_file = self.w.Documents.Add() + c_file = docx.Document(content_tmp_path) + except: + self.sin_out.emit('open failed:文档模板') + self.parent.tabWidget.setEnabled(True) + return + + try: + s_file = docx.Document(self.parent.open_file_name[0]) + s_tbls = s_file.tables + except: + self.sin_out.emit('open failed:选择的文档') + c_file.save(content_tmp_path) + self.parent.tabWidget.setEnabled(True) + return + #原来是5,6,7 + if self.parent.lineEdit_12.text( + ) == '' and self.parent.lineEdit_13.text( + ) == '' and self.parent.lineEdit_14.text() == '': + + self.sin_out.emit( + 'warning:请至少填写一个要提取的内容的标题,\n标题为要提取的单元格的前一单元格中的内容!') + c_file.save(content_tmp_path) + s_file.save(self.parent.open_file_name[0]) + self.parent.tabWidget.setEnabled(True) + return + + line_list = [ + self.parent.lineEdit_12.text(), + self.parent.lineEdit_13.text(), + self.parent.lineEdit_14.text() + ] + self.sin_out.emit('开始提取...') + rownum = 0 + self.sin_out.emit('total:' + str(len(s_tbls))) + for stb in s_tbls: + c_file.tables[0].add_row() + rownum += 1 + self.sin_out.emit(str(rownum)) + + row = 0 + for r1 in stb.rows: + col = 0 + for ce in r1.cells: + if line_list[0] != '' and ce.text == line_list[0]: + while stb.cell(row, col).text == line_list[0]: + col += 1 + c_file.tables[0].cell(rownum, + 0).text = stb.cell(row, col).text + break + col += 1 + col = 0 + for ce in r1.cells: + if line_list[1] != '' and ce.text == line_list[1]: + while stb.cell(row, col).text == line_list[1]: + col += 1 + c_file.tables[0].cell(rownum, + 1).text = stb.cell(row, col).text + break + col += 1 + col = 0 + for ce in r1.cells: + if line_list[2] != '' and ce.text == line_list[2]: + while stb.cell(row, col).text == line_list[2]: + col += 1 + c_file.tables[0].cell(rownum, + 2).text = stb.cell(row, col).text + break + col += 1 + row += 1 + try: + c_file.save(content_tmp_path) + s_file.save(self.parent.open_file_name[0]) + self.sin_out.emit('function success') + self.sin_out.emit('生成文件名为(get_content.docx),在根目录下查看') + self.parent.tabWidget.setEnabled(True) + return + except: + self.sin_out.emit('function fail') + self.parent.tabWidget.setEnabled(True) + return + + +################################################################################## +#测评报告追溯表 +################################################################################## +class create_baogao_zhuisu(QtCore.QThread): + sin_out = pyqtSignal(str) + + def __init__(self, parent): + super().__init__() + self.parent = parent + + def run(self): + self.sin_out.emit("进入报告追溯线程......") + self.sin_out.emit("开始填写报告追溯表......") + + # 如果没有选择文件 + if not self.parent.open_file_name: + self.sin_out.emit('nofile') + self.parent.tabWidget.setEnabled(True) + return + self.sin_out.emit('打开测试记录文档...') + # 打开word应用 + try: + doc_path = self.parent.open_file_name[0] + doc = Document(doc_path) + except: + self.sin_out.emit('open failed:选择的文档') + self.parent.tabWidget.setEnabled(True) + return + + self.sin_out.emit('已正确打开说明文档...') + curpath = Path.cwd() / 'need' + zhuisu_path_tmp = curpath / 'document_templates' / '报告追踪模板.docx' + if zhuisu_path_tmp.is_file(): + self.sin_out.emit('已检测到有报告追溯模板文件...') + else: + self.sin_out.emit('open failed:选择的文档') + return + + # 创建个列表放数据 + data_list = [] + # 由于docx的是列表,所以直接len函数统计count + count = len(doc.tables) + self.sin_out.emit('total:' + str(count)) + k = 0 + for tb in doc.tables: + k += 1 + self.sin_out.emit('total:' + str(k)) + #注意docx处理方式不一样从0开始,并且要算总行数 + try: + if tb.cell(1, 1).text.find('测试用例名称') != -1: + data = { + 'yongli_ming': '', + 'yongli_biaoshi': '', + 'yongli_qingkuang': '', + 'beizhu': '' + } + data['yongli_ming'] = tb.cell(1, 4).text + data['yongli_biaoshi'] = tb.cell(1, 8).text + wenti = tb.rows[-2].cells[2] + print('提取出来的信息:', wenti.text) + if wenti.text == '/' or wenti.text == '': + data['yongli_qingkuang'] = '通过' + data['beizhu'] = '/' + else: + data['yongli_qingkuang'] = '不通过' + data['beizhu'] = wenti.text + self.sin_out.emit(f'处理完毕({tb.cell(1,8).text})用例..') + data_list.append(data) + else: + self.sin_out.emit(f'当前表格({tb.cell(1,8).text})用例无法识别请检查') + except: + self.sin_out.emit(f'处理第{k}个表格失败,请检查该表格...') + pass + + try: + tpl_path = Path.cwd( + ) / "need" / "document_templates" / '报告追踪模板.docx' + self.sin_out.emit('导入模板文件路径为:' + str(tpl_path)) + tpl = DocxTemplate(tpl_path) # 模板导入成功 + + except: + QMessageBox.warning(self.parent, "出错了", "导入模板出错请检查模板文件是否存在或名字不正确") + return + + # 开始渲染模板文件 + print(data_list) + try: + context = { + "tables": data_list, + } + tpl.render(context) + tpl.save("说明追踪文档.docx") + self.sin_out.emit('stopsuccess') + except: + self.sin_out.emit('stoperror') + return + + +################################################################################## +## +################################################################################## diff --git a/need/new_JtoS.py b/need/new_JtoS.py new file mode 100644 index 0000000..984a6ba --- /dev/null +++ b/need/new_JtoS.py @@ -0,0 +1,170 @@ +from PyQt5 import QtCore +from PyQt5.QtCore import pyqtSignal +from pathlib import * # noqa: F403 +from PyQt5.QtWidgets import QMessageBox +from docxtpl import DocxTemplate, InlineImage # type:ignore +from docx import Document +from docx.table import Table +from docx.text.paragraph import Paragraph +import io + + +class create_new_JtoS(QtCore.QThread): + sin_out = pyqtSignal(str) + PREFIX = r'{http://schemas.openxmlformats.org/wordprocessingml/2006/main}' + + def __init__(self, parent): + super().__init__() + self.parent = parent + + def run(self): + self.sin_out.emit("进入CPU测试记录转说明线程......") + self.sin_out.emit("开始转换......") + # 如果没有选择文件路径则退出 + if not self.parent.open_file_name: + self.sin_out.emit('nofile') + self.parent.tabWidget.setEnabled(True) + return + + # 打开模板文件进行渲染,然后就是用docxtpl生成用例 + try: + tpl_path = Path.cwd( # noqa: F405 + ) / "need" / "document_templates" / "cpu新记录to说明模版.docx" + self.sin_out.emit('导入模板文件路径为:' + str(tpl_path)) + tpl = DocxTemplate(tpl_path) # 模板导入成功 + + except: # noqa: E722 + QMessageBox.warning(self.parent, "出错了", "导入模板出错请检查模板文件是否存在或名字不正确") + return + + try: + doc = Document(self.parent.open_file_name[0]) + self.sin_out.emit('已识别到CPU测试记录文件...') + except: # noqa: E722 + self.sin_out.emit('open failed:选择的文档') + self.parent.tabWidget.setEnabled(True) + return + + self.sin_out.emit('复制测试说明文档模板到本程序所在目录...') + curpath = Path.cwd() / 'need' # noqa: F405 + shuoming_path_tmp = curpath / 'document_templates' / 'cpu新记录to说明模版.docx' + print(shuoming_path_tmp) + if shuoming_path_tmp.is_file(): + self.sin_out.emit('已检测到有说明模板文件...') + else: + self.sin_out.emit('open failed:选择的文档') + return + + # 获取表格数量 + tables = doc.tables + tb_count = len(tables) + self.sin_out.emit('total:' + str(tb_count)) + # 创建一个字典来储存单个用例 + data_list = [] + table_index = 1 + # 获取表格数量 + for ele in doc._element.body.iter(): + data = {'type': ''} + if ele.tag.endswith('}p'): + for child in ele.iter(): + if child.tag.endswith('pStyle'): + rank = child.get(f"{self.PREFIX}val") + t_ele = ele.findall( + f".//{self.PREFIX}t") # type:ignore + title = '' + for i in range(len(t_ele)): + if not t_ele[i].text.isdigit(): + title = title + t_ele[i].text + data['type'] = rank + data['title'] = title + data_list.append(data) + + elif ele.tag.endswith('}tbl'): + data = { + 'name': '', + 'biaoshi': '', + 'zhuizong': [], + 'zongsu': '', + 'init': '', + 'qianti': '', + 'step': [] + } + data['type'] = 'table' + table = Table(ele, doc) + if table.cell(1, 0).text == '测试用例名称': + self.sin_out.emit(str(table_index)) + + try: + self.sin_out.emit(str(table_index)) + self.sin_out.emit(f'正在处理第{table_index}个表格') + # 1、获取测试用例名称 + data['name'] = table.cell(1, 3).text + # 2、获取用例标识 + data['biaoshi'] = table.cell(1, 9).text + # 3、获取追踪关系 注意word中换行为\r\x07 + temp = table.cell(2, 3) + for tem in temp.paragraphs: + data['zhuizong'].append(tem.text) + # 4、获取综述 + data['zongsu'] = table.cell(3, 3).text.replace( + '\n', '\a') + # 5、初始化 + data['init'] = table.cell(4, + 3).text.replace('\n', '\a') + # 6、获取前提与约束 + data['qianti'] = table.cell(5, 3).text.replace( + '\n', '\a') + # 7、获取步骤信息-总行数减去12为步骤行数 + row_count = len(table.rows) + step_count = row_count - 12 + for j in range(step_count): + buzhou = { + 'shuru': '', + 'yuqi': '', + 'num': '', + 'image': '', + 'is_image': '0' + } + buzhou['num'] = table.rows[8 + j].cells[0].text + if buzhou['num'] == '': + buzhou['num'] = j + 1 + buzhou['shuru'] = table.rows[ + 8 + j].cells[2].text.replace('\n', '\a') + cel = table.rows[8 + j].cells[2] + if len( + cel._element.findall( + './/{http://schemas.openxmlformats.org/wordprocessingml/2006/main}drawing' + )) > 0: + img_ele = cel._element.xpath('.//pic:pic')[0] + embed = img_ele.xpath('.//a:blip/@r:embed')[0] + related_part = doc.part.related_parts[embed] + image = related_part.image + # blob属性就是二进制图片属性 + image_bytes = image.blob + buzhou['image'] = InlineImage( + tpl, io.BytesIO(image_bytes)) + buzhou['is_image'] = '1' + buzhou['yuqi'] = table.rows[ + 8 + j].cells[4].text.replace('\n', '\a') + data['step'].append(buzhou) + # 8、最后加入data_list + data_list.append(data) + table_index += 1 + except: # noqa: E722 + self.sin_out.emit(f'第{table_index}个表格处理错误!') + table_index += 1 + pass + # 开始渲染模板文件 + try: + self.sin_out.emit('注意:如果生成文档没有标题,请检查您文档章节号格式是否正确!!!') + self.sin_out.emit('all_doned:') + context = { + "tables": data_list, + "renyuan": self.parent.lineEdit_17.text(), + } + tpl.render(context) + tpl.save("CPU新版反向生成说明.docx") + self.sin_out.emit('stopsuccess') + except: # noqa: E722 + self.sin_out.emit('stoperror') + return diff --git a/need/others/readme.txt b/need/others/readme.txt new file mode 100644 index 0000000..d55b822 --- /dev/null +++ b/need/others/readme.txt @@ -0,0 +1,14 @@ +注意事项: +1.本工具只能处理docx格式word文档,如果是doc的,需打开后另存为docx,不能直接改名称; +2.目前不支持文档路径中带特殊字符,如空格等; +3.document_templates为文档模板文档,其中非代码部分可以调整格式,调整后按新模板生成; + +功能说明: +1、大纲转说明,使用的是成都鉴定测评模板,注意测试项格式的“;”以及“\r”(换行) +2、追踪关系填写,可以根据大纲、说明和记录进行填写,说明和记录生成无需求规格说明的章节号和内容(需要根据大纲生成联合人工处理) +3、根据大纲生成说明、根据说明生成测试记录,如果有3级标题,则需要人工添加二级标题 +4、文档小工具-UAS单元测试转换:是对UAS工具生成文档转换成本单位测评中心的用例 +5、自动填充以及选择文档功能和TDP工具一样,无变化; +6、FPGA记录生产以及FPGA的记录转说明功能。 + + diff --git a/need/static/zxlogo.gif b/need/static/zxlogo.gif new file mode 100644 index 0000000..6d13071 Binary files /dev/null and b/need/static/zxlogo.gif differ diff --git a/need/threads.py b/need/threads.py new file mode 100644 index 0000000..e665ea1 --- /dev/null +++ b/need/threads.py @@ -0,0 +1,154 @@ +import pythoncom +from PyQt5 import QtCore +from PyQt5.QtCore import pyqtSignal +from win32com.client import DispatchEx +from pathlib import * +from PyQt5.QtWidgets import QMessageBox +from docxtpl import DocxTemplate + +class create_bujian(QtCore.QThread): + sin_out = pyqtSignal(str) + + def __init__(self,parent): + super().__init__() + self.parent = parent + + def run(self): + self.sin_out.emit("进入部件测试获取调用函数线程......") + self.sin_out.emit("开始填写文档......") + + #如果没有选择路径则退出 + if not self.parent.open_file_name: + self.sin_out.emit('nofile') + self.parent.tabWidget.setEnabled(True) + return + + #告诉windows单线程 + pythoncom.CoInitialize() + #在用户选择的目录中查找UAS单位测试报告文档 + self.sin_out.emit('打开单元测试原文件...') + + #使用win32com打开-记得关闭 + #打开word应用 + self.w = DispatchEx('Word.Application') + #self.w.visible=True + self.w.DisplayAlerts = 0 + try: + bujianfile = self.w.Documents.Open(self.parent.open_file_name[0]) + except: + self.sin_out.emit('open failed:选择的文档') + self.w.Quit() + pythoncom.CoUninitialize() + self.parent.tabWidget.setEnabled(True) + return + + curpath = Path.cwd() / 'need' + danyuan_file_tmp = curpath / 'document_templates' / '部件桩函数工具1.docx' + print(danyuan_file_tmp) + + if danyuan_file_tmp.is_file(): + self.sin_out.emit('已检测到有部件模板文件...') + else: + self.sin_out.emit('open failed:选择的文档') + return + + #创建个列表放数据-important + data_list = [] + + #try统计表格数量 + try: + csx_tb_count = bujianfile.Tables.Count + self.sin_out.emit('total:'+ str(csx_tb_count)) + self.sin_out.emit("正在调用word文档操作接口,可能会有点慢...") + except: + self.sin_out.emit('不存在表格!') + QMessageBox.warning(self.parent,'出错了','测试说明文档格式错误或者没有正确表格') + try: + bujianfile.Close() + except: + pass + self.w.Quit() + pythoncom.CoUninitialize() + self.parent.tabWidget.setEnabled(True) + return + + #开始处理表格-important + #我先统计有多少个生成的表格-即用例有多少个呗 + yongli_count = 0 + for i in range(csx_tb_count): + if bujianfile.Tables[i].Rows.Count > 2: + #注意win32com的Cell从1开始不是从0开始 + if bujianfile.Tables[i].Cell(1, 1).Range.Text.find('用例名称') != -1: + yongli_count += 1 + + + yongli_num = 0 + hanshuming_duibi = '' + alowFunctionInject = True + for i in range(csx_tb_count): + self.sin_out.emit(str(i)) + #准备填入的data + data = {'functionName':'','subitem':[]} + + #找到函数名,这里容易出问题~~~~~~~~~~~~~~~~ + if bujianfile.Tables[i].Rows.Count > 2: + if bujianfile.Tables[i].Cell(1, 1).Range.Text.find('功能描述') != -1: + bujianfile.Tables[i].Cell(1, 1).Range.Select() + self.w.Selection.MoveUp() + self.w.Selection.MoveUp() + self.w.Selection.MoveUp() + s = self.w.Selection.Paragraphs(1).Range.Text[:-1] + s1 = s.split(". ")[-1] + #放入函数名比对 + data['functionName'] = s1 + data_list.append(data) + yongli_num += 1 #用例创建加一 + + #找章节号~~~~~~~~~~~~~~~~~~~~~~~~ + if bujianfile.Tables[i].Rows.Count > 2: + if bujianfile.Tables[i].Cell(1, 1).Range.Text.find('用例名称') != -1: + #函数名获取 + if s1 != hanshuming_duibi: + hanshuming_duibi = s1 + alowFunctionInject = True + else: + alowFunctionInject = False + + elif bujianfile.Tables[i].Cell(1, 2).Range.Text.find('定义') != -1: + #定义个桩函数dict + if alowFunctionInject == True: + temp = bujianfile.Tables[i].Cell(1, 3).Range.Text[:-2] + temp1 = temp.split("(")[0] + temp2 = temp1.split(" ")[-1] + data_list[yongli_num - 1]['subitem'].append(temp2) + + + print('最后data_list',data_list) + #最后关闭文档 + try: + self.w.Quit() + pythoncom.CoUninitialize() + self.parent.tabWidget.setEnabled(True) + except: + QMessageBox.warning(self.parent,"关闭文档失败","关闭文档失败!") + return + + try: + tpl_path = Path.cwd() / "need" / "document_templates" / "部件桩函数工具1.docx" + self.sin_out.emit('导入模板文件路径为:' + str(tpl_path)) + tpl = DocxTemplate(tpl_path) #模板导入成功 + except: + QMessageBox.warning(self.parent,"出错了","导入模板出错请检查模板文件是否存在或名字不正确") + return + + #开始渲染模板文件 + try: + context = { + "tables":data_list, + } + tpl.render(context) + tpl.save("部件提起调用函数表格.docx") + self.sin_out.emit('stopsuccess') + except: + self.sin_out.emit('stoperror') + return \ No newline at end of file diff --git a/need/utils.py b/need/utils.py new file mode 100644 index 0000000..6911959 --- /dev/null +++ b/need/utils.py @@ -0,0 +1,18 @@ +import datetime + +def get_current_time(): + data = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f') + data = "[" + data + " R] " + return data + +def get_current_name(): + data = datetime.datetime.now().strftime('%Y-%m-%d-%H-%M-%S-%f') + return data + +def get_current_date(): + data = datetime.datetime.now().strftime('%Y-%m-%d %H-%M-%S') + return data + +def get_current_hour(): + data = datetime.datetime.now().strftime('%H.%M.%S') + return data diff --git a/need/zhuan.py b/need/zhuan.py new file mode 100644 index 0000000..ab9714b --- /dev/null +++ b/need/zhuan.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'zhuan.ui' +# +# Created by: PyQt5 UI code generator 5.15.4 +# +# WARNING: Any manual changes made to this file will be lost when pyuic5 is +# run again. Do not edit this file unless you know what you are doing. + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_Dialog(object): + def setupUi(self, Dialog): + Dialog.setObjectName("Dialog") + Dialog.resize(461, 70) + self.widget = QtWidgets.QWidget(Dialog) + self.widget.setGeometry(QtCore.QRect(10, 35, 446, 23)) + self.widget.setObjectName("widget") + self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.widget) + self.horizontalLayout_3.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout_3.setObjectName("horizontalLayout_3") + self.horizontalLayout = QtWidgets.QHBoxLayout() + self.horizontalLayout.setObjectName("horizontalLayout") + self.label = QtWidgets.QLabel(self.widget) + self.label.setObjectName("label") + self.horizontalLayout.addWidget(self.label) + self.lineEdit = QtWidgets.QLineEdit(self.widget) + self.lineEdit.setObjectName("lineEdit") + self.horizontalLayout.addWidget(self.lineEdit) + self.horizontalLayout_3.addLayout(self.horizontalLayout) + self.horizontalLayout_2 = QtWidgets.QHBoxLayout() + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.label_2 = QtWidgets.QLabel(self.widget) + self.label_2.setObjectName("label_2") + self.horizontalLayout_2.addWidget(self.label_2) + self.lineEdit_2 = QtWidgets.QLineEdit(self.widget) + self.lineEdit_2.setObjectName("lineEdit_2") + self.horizontalLayout_2.addWidget(self.lineEdit_2) + self.horizontalLayout_3.addLayout(self.horizontalLayout_2) + self.widget1 = QtWidgets.QWidget(Dialog) + self.widget1.setGeometry(QtCore.QRect(10, 10, 216, 18)) + self.widget1.setObjectName("widget1") + self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.widget1) + self.horizontalLayout_4.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout_4.setObjectName("horizontalLayout_4") + self.radioButton = QtWidgets.QRadioButton(self.widget1) + self.radioButton.setChecked(True) + self.radioButton.setObjectName("radioButton") + self.horizontalLayout_4.addWidget(self.radioButton) + self.radioButton_2 = QtWidgets.QRadioButton(self.widget1) + self.radioButton_2.setObjectName("radioButton_2") + self.horizontalLayout_4.addWidget(self.radioButton_2) + + self.retranslateUi(Dialog) + QtCore.QMetaObject.connectSlotsByName(Dialog) + + def retranslateUi(self, Dialog): + _translate = QtCore.QCoreApplication.translate + Dialog.setWindowTitle(_translate("Dialog", "IEEE754转换工具")) + self.label.setText(_translate("Dialog", "16进制表示")) + self.label_2.setText(_translate("Dialog", "float值")) + self.radioButton.setText(_translate("Dialog", "单精度(32位)")) + self.radioButton_2.setText(_translate("Dialog", "双精度(64位)")) diff --git a/need/zhuan_tool.py b/need/zhuan_tool.py new file mode 100644 index 0000000..3a59f7c --- /dev/null +++ b/need/zhuan_tool.py @@ -0,0 +1,21 @@ +#python处理floatIEE754格式转换 +import struct + +def IEEE754_16_to_float(x,byte_type): + if byte_type == 32: + return struct.unpack('>f',struct.pack('>I',int(x,16)))[0] + if byte_type == 64: + return struct.unpack('>d',struct.pack('>Q',int(x,16)))[0] + +def IEEE754_float_to_16(x,byte_type): + if byte_type == 32: + return hex(struct.unpack('>I',struct.pack('>f',x))[0])[2:].upper() + if byte_type == 64: + return hex(struct.unpack('>Q',struct.pack('>d',x))[0])[2:].upper() + +if __name__ == '__main__': + ##测试程序## + x = 'BE051EB8' + y = -0.13 + print(IEEE754_16_to_float(x,32)) + print(IEEE754_float_to_16(y,32)) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..c3f2643 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,16 @@ +[project] +name = "cttools" +version = "1.9.1" +description = "内网使用的东西" +readme = "README.md" +requires-python = ">=3.8.10" +dependencies = [ + "docxcompose>=1.4.0", + "docxtpl>=0.20.2", + "pyqt5==5.15.9", + "pyqt5-qt5==5.15.2", + "pyqt5-tools>=5.15.9.3.3", + "pywin32>=311", + "qtmodern>=0.2.0", + "six>=1.17.0", +] diff --git a/testDocumentGeneratorV0.01/document_template/测试大纲生成测试说明模版.docx b/testDocumentGeneratorV0.01/document_template/测试大纲生成测试说明模版.docx new file mode 100644 index 0000000..f08e0f3 Binary files /dev/null and b/testDocumentGeneratorV0.01/document_template/测试大纲生成测试说明模版.docx differ diff --git a/testDocumentGeneratorV0.01/main.py b/testDocumentGeneratorV0.01/main.py new file mode 100644 index 0000000..887548d --- /dev/null +++ b/testDocumentGeneratorV0.01/main.py @@ -0,0 +1,199 @@ +from pathlib import Path +import re +from docxtpl import DocxTemplate +from docx import Document +from docx.table import Table +from docx.text.paragraph import Paragraph +from nicegui import ui, app + +# 定义全局变量 +input_document_path = '' +# 匹配测试方法里面的标题 +re_title = re.compile(r'(\w{2}_\w+_[a-zA-Z0-9]+_\w+\d+)') +ui.html("

测试大纲生成测试说明demo

") + +# 进度全变量 +class DataModel: + content = 0.0 + +db = DataModel() + +def generat_document(): + global input_document_path + global db + # 定义当前四级标题的编号和名称 + current_level4_title = '' + # 定义储存标题的东西 + level1_title = [] + level2_title = [] + level3_title = [] + level4_title = [] + level5_title = [] + level6_title = [] + level7_title = [] + if input_document_path: + tpl_path = Path.cwd() / 'document_template' / '测试大纲生成测试说明模版.docx' + tpl = DocxTemplate(tpl_path) # 模板导入成功 + ui.notify('导入模版成功...') + try: + doc = Document(input_document_path) + except: + ui.notify('选择的文件格式不正确!!,请重新选择') + return + shuoming_path_tmp = Path.cwd() / 'generate_document' / '生成的测试说明.docx' + # 获取表格数量 + tables = doc.tables + # 创建一个字典来储存单个用例 + data_list = [] + # 定义开关-当识别到测试定义的标题时候 + open_title = False + ui.notify('开始生成测试说明...') + for ele in doc._element.body.iter(): + if ele.tag.endswith('}p'): + elePstyle = ele.findall('.//{http://schemas.openxmlformats.org/wordprocessingml/2006/main}pStyle') + if len(elePstyle) >= 1: + parag = Paragraph(ele, doc) + if parag.style.name.startswith("Heading") or parag.style.name.startswith("标题"): + data = {} + rank = parag.style.name.split(" ")[-1] # 标题等级str类型 + text = parag.text # 标题文字 + # 先将标题储存在一个地方 + if rank == '1' or rank == '10': + level1_title.append(1) + level2_title.clear() + level3_title.clear() + level4_title.clear() + level5_title.clear() + level6_title.clear() + level7_title.clear() + elif rank == '2' or rank == '20': + level2_title.append(1) + level3_title.clear() + level4_title.clear() + level5_title.clear() + level6_title.clear() + level7_title.clear() + elif rank == '3' or rank == '30': + level3_title.append(1) + level4_title.clear() + level5_title.clear() + level6_title.clear() + level7_title.clear() + elif rank == '4' or rank == '40': + level4_title.append(1) + level5_title.clear() + level6_title.clear() + level7_title.clear() + current_level4_title = f"({len(level1_title)}.{len(level2_title)}.{len(level3_title)}.{len(level4_title)}){text}" + elif rank == '5' or rank == '50': + level5_title.append(1) + level6_title.clear() + level7_title.clear() + elif rank == '6' or rank == '60': + level6_title.append(1) + level7_title.clear() + elif rank == '7' or rank == '70': + level7_title.append(1) + # 如果识别到标题为"测试定义"则打开获取标题开关 + if text == '功能测试': + open_title = True + if text == '测试进度': + open_title = False + if open_title: + data['type'] = rank + data['text'] = text + data_list.append(data) + elif ele.tag.endswith('}tbl'): + table = Table(ele, doc) + # 1识别到大纲的一个表格 + temp = table.cell(0, 0).text + if temp == '测试项名称' and table.cell(0, 1).text != '文档审查' \ + and table.cell(0, 1).text != '静态分析' and \ + table.cell(0, 1).text != '代码审查': + # 先提取表格其他信息 + csx_name = table.cell(0, 1).text + csx_ident = table.cell(0, 3).text + res_text = '' + prefix = '' + count = 1 + for para in table.cell(4, 2).paragraphs: + # 2.1 识别到测试方法的标题 + re_res = re_title.findall(para.text) + if re_res: + data = {} + count = 1 + data['type'] = '5' + data['text'] = re.sub(r'\d{1,2}[.]', '', para.text).strip() + prefix = re_res[0].replace('(', '').replace(")", "") + res_text = data['text'].split('(')[0] + data_list.append(data) + # print('生成五级标题为:', data['text']) + # 2.2 如果不是标题则需要生成表格了 + else: + tb_data = {'type': 'table'} + tb_data['name'] = f"{res_text}_{count}" + tb_data['ident'] = f"{prefix}_{count}" + tb_data['destination'] = f"验证{csx_name.replace('测试','')}是否正确" + tb_data['xqfx'] = current_level4_title + tb_data['xqident'] = prefix + tb_data['step'] = [] + # 步骤处理共4个字段 + # 要求每句话必须有;中文分号 + split_temp = para.text.split(';') + if len(split_temp) == 1: + split_temp.append("") + index = 1 + for sss in split_temp: + if sss: + # 根据“查看分割” + ck_split = sss.split('查看') + if len(ck_split) == 1: + ck_split.insert(0, "") + step = {} + step['index'] = index + step['shuru'] = '巡天主控软件' + step['guocheng'] = ck_split[0] + # 去掉guocheng里面逗号 + if step['guocheng']: + if step['guocheng'][-1] == ',': + step['guocheng'] = step['guocheng'][:-1] + else: + ui.notify('请检查,未有查看字样...', type = 'negative') + step['yuqi'] = ck_split[1] + tb_data['step'].append(step) + index += 1 + + count += 1 + data_list.append(tb_data) + db.content = 1 + try: + context = { + "tables": data_list, + } + tpl.render(context) + tpl.save(shuoming_path_tmp) + except: + ui.notify('在生成文档时报错', type = 'warning') + else: + ui.notify('请先选择需要转换的文件!') + + ui.notify('生成完成!', type = 'positive') + +async def choose_file(): + global input_document_path + files = await app.native.main_window.create_file_dialog(file_types = ("excel文件(*.docx)", )) + if files: + input_document_path = files[0] + # 设置界面label显示文件路径 + label.text = input_document_path + +# 按钮 +with ui.row().classes('flex justify-center items-center'): + ui.button("上传文件", on_click = choose_file) + label = ui.label("") +with ui.row().classes('flex justify-center items-center'): + ui.button('点击生成说明', on_click = generat_document) + # 定义进度条 + knob = ui.knob(0.0, show_value = True).bind_value(db, 'content') + +ui.run(native = True) diff --git a/testDocumentGeneratorV0.01/test.py b/testDocumentGeneratorV0.01/test.py new file mode 100644 index 0000000..f92fc74 --- /dev/null +++ b/testDocumentGeneratorV0.01/test.py @@ -0,0 +1,19 @@ +from nicegui import ui + +class DataModel: + content1 = '' + content2 = '' + count = 0 + + @property + def result(self): + print('运行了该函数', self.count) + return self.content1 + self.content2 + +dm = DataModel() + +label = ui.label('').bind_text_from(dm, 'result') +input = ui.input('演示').bind_value_to(dm, 'content1') +input = ui.input('演示').bind_value_to(dm, 'content2') + +ui.run() diff --git a/testDocumentGeneratorV0.01/tkmain.py b/testDocumentGeneratorV0.01/tkmain.py new file mode 100644 index 0000000..69d8c9b --- /dev/null +++ b/testDocumentGeneratorV0.01/tkmain.py @@ -0,0 +1,192 @@ +import tkinter +from tkinter import filedialog +from pathlib import Path +import re +from docxtpl import DocxTemplate +from docx import Document +from docx.table import Table +from docx.text.paragraph import Paragraph + +# 匹配测试方法里面的标题 +re_title = re.compile(r'(\w{2}_\w+_[a-zA-Z0-9]+_\w+\d+)') + +window = tkinter.Tk() +window.title("大纲转换软件V0.01-tk-丑版") + +# 窗口大小 +window.geometry('600x300') + +# label +label1 = tkinter.Label(window, text = '') +label1.grid(row = 0, column = 2) + +def btn1click(): + path = tkinter.filedialog.askopenfilename() + label1.config(text = path) + +# 选择文件按钮 +btn1 = tkinter.Button(window, text = "选择文件", command = btn1click) +btn1.grid(column = 1, row = 0) + +# 生成文档函数 +def generate_document(): + input_document_path = label1['text'] + # 定义当前四级标题的编号和名称 + current_level4_title = '' + # 定义储存标题的东西 + level1_title = [] + level2_title = [] + level3_title = [] + level4_title = [] + level5_title = [] + level6_title = [] + level7_title = [] + if input_document_path: + tpl_path = Path.cwd() / 'document_template' / '测试大纲生成测试说明模版.docx' + tpl = DocxTemplate(tpl_path) # 模板导入成功 + try: + doc = Document(input_document_path) + except: + return + shuoming_path_tmp = Path.cwd() / 'generate_document' / '生成的测试说明.docx' + # 获取表格数量 + tables = doc.tables + # 创建一个字典来储存单个用例 + data_list = [] + # 定义开关-当识别到测试定义的标题时候 + open_title = False + for ele in doc._element.body.iter(): + if ele.tag.endswith('}p'): + elePstyle = ele.findall('.//{http://schemas.openxmlformats.org/wordprocessingml/2006/main}pStyle') + if len(elePstyle) >= 1: + parag = Paragraph(ele, doc) + if parag.style.name.startswith("Heading") or parag.style.name.startswith("标题"): + data = {} + rank = parag.style.name.split(" ")[-1] # 标题等级str类型 + text = parag.text # 标题文字 + # 先将标题储存在一个地方 + if rank == '1' or rank == '10': + level1_title.append(1) + level2_title.clear() + level3_title.clear() + level4_title.clear() + level5_title.clear() + level6_title.clear() + level7_title.clear() + elif rank == '2' or rank == '20': + level2_title.append(1) + level3_title.clear() + level4_title.clear() + level5_title.clear() + level6_title.clear() + level7_title.clear() + elif rank == '3' or rank == '30': + level3_title.append(1) + level4_title.clear() + level5_title.clear() + level6_title.clear() + level7_title.clear() + elif rank == '4' or rank == '40': + level4_title.append(1) + level5_title.clear() + level6_title.clear() + level7_title.clear() + current_level4_title = f"({len(level1_title)}.{len(level2_title)}.{len(level3_title)}.{len(level4_title)}){text}" + elif rank == '5' or rank == '50': + level5_title.append(1) + level6_title.clear() + level7_title.clear() + elif rank == '6' or rank == '60': + level6_title.append(1) + level7_title.clear() + elif rank == '7' or rank == '70': + level7_title.append(1) + # 如果识别到标题为"测试定义"则打开获取标题开关 + if text == '功能测试': + open_title = True + if text == '测试进度': + open_title = False + if open_title: + data['type'] = rank + data['text'] = text + data_list.append(data) + elif ele.tag.endswith('}tbl'): + table = Table(ele, doc) + # 1识别到大纲的一个表格 + temp = table.cell(0, 0).text + if temp == '测试项名称' and table.cell(0, 1).text != '文档审查' \ + and table.cell(0, 1).text != '静态分析' and \ + table.cell(0, 1).text != '代码审查': + # 先提取表格其他信息 + csx_name = table.cell(0, 1).text + csx_ident = table.cell(0, 3).text + res_text = '' + prefix = '' + count = 1 + for para in table.cell(4, 2).paragraphs: + # 2.1 识别到测试方法的标题 + re_res = re_title.findall(para.text) + if re_res: + data = {} + count = 1 + data['type'] = '5' + data['text'] = re.sub(r'\d{1,2}[.]', '', para.text).strip() + prefix = re_res[0].replace('(', '').replace(")", "") + res_text = data['text'].split('(')[0] + data_list.append(data) + # print('生成五级标题为:', data['text']) + # 2.2 如果不是标题则需要生成表格了 + else: + tb_data = {'type': 'table'} + tb_data['name'] = f"{res_text}_{count}" + tb_data['ident'] = f"{prefix}_{count}" + tb_data['destination'] = f"验证{csx_name.replace('测试','')}是否正确" + tb_data['xqfx'] = current_level4_title + tb_data['xqident'] = prefix + tb_data['step'] = [] + # 步骤处理共4个字段 + # 要求每句话必须有;中文分号 + split_temp = para.text.split(';') + if len(split_temp) == 1: + split_temp.append("") + index = 1 + for sss in split_temp: + if sss: + # 根据“查看分割” + ck_split = sss.split('查看') + if len(ck_split) == 1: + ck_split.insert(0, "") + step = {} + step['index'] = index + step['shuru'] = '巡天主控软件' + step['guocheng'] = ck_split[0] + # 去掉guocheng里面逗号 + if step['guocheng']: + if step['guocheng'][-1] == ',': + step['guocheng'] = step['guocheng'][:-1] + else: + print('请检查,未有查看字样...') + step['yuqi'] = ck_split[1] + tb_data['step'].append(step) + index += 1 + + count += 1 + data_list.append(tb_data) + try: + context = { + "tables": data_list, + } + tpl.render(context) + tpl.save(shuoming_path_tmp) + except: + print('在生成文档时报错') + else: + print('请先选择需要转换的文件') + print('生成完成!') + +# 生成文档按钮 +btn2 = tkinter.Button(window, text = "生成文档", command = generate_document) +btn2.grid(column = 1, row = 1) + +# 进入消息循环 +window.mainloop() diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000..e1a7610 --- /dev/null +++ b/uv.lock @@ -0,0 +1,820 @@ +version = 1 +revision = 3 +requires-python = ">=3.8.10" +resolution-markers = [ + "python_full_version >= '3.10'", + "python_full_version == '3.9.*'", + "python_full_version < '3.9'", +] + +[[package]] +name = "babel" +version = "2.17.0" +source = { registry = "https://mirrors.aliyun.com/pypi/simple" } +dependencies = [ + { name = "pytz", marker = "python_full_version < '3.9'" }, +] +sdist = { url = "https://mirrors.aliyun.com/pypi/packages/7d/6b/d52e42361e1aa00709585ecc30b3f9684b3ab62530771402248b1b1d6240/babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d" } +wheels = [ + { url = "https://mirrors.aliyun.com/pypi/packages/b7/b8/3fe70c75fe32afc4bb507f75563d39bc5642255d1d94f1f23604725780bf/babel-2.17.0-py3-none-any.whl", hash = "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2" }, +] + +[[package]] +name = "click" +version = "8.1.8" +source = { registry = "https://mirrors.aliyun.com/pypi/simple" } +resolution-markers = [ + "python_full_version == '3.9.*'", + "python_full_version < '3.9'", +] +dependencies = [ + { name = "colorama", marker = "python_full_version < '3.10' and sys_platform == 'win32'" }, +] +sdist = { url = "https://mirrors.aliyun.com/pypi/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a" } +wheels = [ + { url = "https://mirrors.aliyun.com/pypi/packages/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2" }, +] + +[[package]] +name = "click" +version = "8.3.1" +source = { registry = "https://mirrors.aliyun.com/pypi/simple" } +resolution-markers = [ + "python_full_version >= '3.10'", +] +dependencies = [ + { name = "colorama", marker = "python_full_version >= '3.10' and sys_platform == 'win32'" }, +] +sdist = { url = "https://mirrors.aliyun.com/pypi/packages/3d/fa/656b739db8587d7b5dfa22e22ed02566950fbfbcdc20311993483657a5c0/click-8.3.1.tar.gz", hash = "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a" } +wheels = [ + { url = "https://mirrors.aliyun.com/pypi/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl", hash = "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6" }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://mirrors.aliyun.com/pypi/simple" } +sdist = { url = "https://mirrors.aliyun.com/pypi/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44" } +wheels = [ + { url = "https://mirrors.aliyun.com/pypi/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6" }, +] + +[[package]] +name = "cttools" +version = "1.9.1" +source = { virtual = "." } +dependencies = [ + { name = "docxcompose" }, + { name = "docxtpl" }, + { name = "pyqt5" }, + { name = "pyqt5-qt5" }, + { name = "pyqt5-tools" }, + { name = "pywin32" }, + { name = "qtmodern" }, + { name = "six" }, +] + +[package.metadata] +requires-dist = [ + { name = "docxcompose", specifier = ">=1.4.0" }, + { name = "docxtpl", specifier = ">=0.20.2" }, + { name = "pyqt5", specifier = "==5.15.9" }, + { name = "pyqt5-qt5", specifier = "==5.15.2" }, + { name = "pyqt5-tools", specifier = ">=5.15.9.3.3" }, + { name = "pywin32", specifier = ">=311" }, + { name = "qtmodern", specifier = ">=0.2.0" }, + { name = "six", specifier = ">=1.17.0" }, +] + +[[package]] +name = "docxcompose" +version = "1.4.0" +source = { registry = "https://mirrors.aliyun.com/pypi/simple" } +dependencies = [ + { name = "babel" }, + { name = "lxml" }, + { name = "python-docx", version = "1.1.2", source = { registry = "https://mirrors.aliyun.com/pypi/simple" }, marker = "python_full_version < '3.9'" }, + { name = "python-docx", version = "1.2.0", source = { registry = "https://mirrors.aliyun.com/pypi/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "setuptools", version = "75.3.2", source = { registry = "https://mirrors.aliyun.com/pypi/simple" }, marker = "python_full_version < '3.9'" }, + { name = "setuptools", version = "80.9.0", source = { registry = "https://mirrors.aliyun.com/pypi/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "six" }, +] +sdist = { url = "https://mirrors.aliyun.com/pypi/packages/5d/25/07597a0fda04adf2f2fc375f48f704612a91c0c1da64f4c18e78a4a26630/docxcompose-1.4.0.tar.gz", hash = "sha256:bcf2799a0b63c29eb77a3d799a2f28443ae0f69f8691ff3d753f706be515c3e9" } + +[[package]] +name = "docxtpl" +version = "0.20.2" +source = { registry = "https://mirrors.aliyun.com/pypi/simple" } +dependencies = [ + { name = "jinja2" }, + { name = "lxml" }, + { name = "python-docx", version = "1.1.2", source = { registry = "https://mirrors.aliyun.com/pypi/simple" }, marker = "python_full_version < '3.9'" }, + { name = "python-docx", version = "1.2.0", source = { registry = "https://mirrors.aliyun.com/pypi/simple" }, marker = "python_full_version >= '3.9'" }, +] +sdist = { url = "https://mirrors.aliyun.com/pypi/packages/b2/b4/4435f3fcb1357ec441079c4af1dda3ea926fad6dcead4aed2d93b369944e/docxtpl-0.20.2.tar.gz", hash = "sha256:eddf3350d70b4d123208e801d585bcb313d21044a377a14f75a66d0965841de1" } +wheels = [ + { url = "https://mirrors.aliyun.com/pypi/packages/a4/ad/e07939d8e020e513d3860400413ba1e0e06102c469639b440d921337efef/docxtpl-0.20.2-py3-none-any.whl", hash = "sha256:626d5c570a46a62b2ca73b4d08f1c240fa031a5bc45371e1466a4fe184923d10" }, +] + +[[package]] +name = "jinja2" +version = "3.1.6" +source = { registry = "https://mirrors.aliyun.com/pypi/simple" } +dependencies = [ + { name = "markupsafe", version = "2.1.5", source = { registry = "https://mirrors.aliyun.com/pypi/simple" }, marker = "python_full_version < '3.9'" }, + { name = "markupsafe", version = "3.0.3", source = { registry = "https://mirrors.aliyun.com/pypi/simple" }, marker = "python_full_version >= '3.9'" }, +] +sdist = { url = "https://mirrors.aliyun.com/pypi/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d" } +wheels = [ + { url = "https://mirrors.aliyun.com/pypi/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67" }, +] + +[[package]] +name = "lxml" +version = "6.0.2" +source = { registry = "https://mirrors.aliyun.com/pypi/simple" } +sdist = { url = "https://mirrors.aliyun.com/pypi/packages/aa/88/262177de60548e5a2bfc46ad28232c9e9cbde697bd94132aeb80364675cb/lxml-6.0.2.tar.gz", hash = "sha256:cd79f3367bd74b317dda655dc8fcfa304d9eb6e4fb06b7168c5cf27f96e0cd62" } +wheels = [ + { url = "https://mirrors.aliyun.com/pypi/packages/db/8a/f8192a08237ef2fb1b19733f709db88a4c43bc8ab8357f01cb41a27e7f6a/lxml-6.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e77dd455b9a16bbd2a5036a63ddbd479c19572af81b624e79ef422f929eef388" }, + { url = "https://mirrors.aliyun.com/pypi/packages/12/64/27bcd07ae17ff5e5536e8d88f4c7d581b48963817a13de11f3ac3329bfa2/lxml-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5d444858b9f07cefff6455b983aea9a67f7462ba1f6cbe4a21e8bf6791bf2153" }, + { url = "https://mirrors.aliyun.com/pypi/packages/02/5a/a7d53b3291c324e0b6e48f3c797be63836cc52156ddf8f33cd72aac78866/lxml-6.0.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f952dacaa552f3bb8834908dddd500ba7d508e6ea6eb8c52eb2d28f48ca06a31" }, + { url = "https://mirrors.aliyun.com/pypi/packages/f5/55/d465e9b89df1761674d8672bb3e4ae2c47033b01ec243964b6e334c6743f/lxml-6.0.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:71695772df6acea9f3c0e59e44ba8ac50c4f125217e84aab21074a1a55e7e5c9" }, + { url = "https://mirrors.aliyun.com/pypi/packages/62/38/3073cd7e3e8dfc3ba3c3a139e33bee3a82de2bfb0925714351ad3d255c13/lxml-6.0.2-cp310-cp310-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:17f68764f35fd78d7c4cc4ef209a184c38b65440378013d24b8aecd327c3e0c8" }, + { url = "https://mirrors.aliyun.com/pypi/packages/4a/d3/1e001588c5e2205637b08985597827d3827dbaaece16348c8822bfe61c29/lxml-6.0.2-cp310-cp310-manylinux_2_26_i686.manylinux_2_28_i686.whl", hash = "sha256:058027e261afed589eddcfe530fcc6f3402d7fd7e89bfd0532df82ebc1563dba" }, + { url = "https://mirrors.aliyun.com/pypi/packages/20/cf/cab09478699b003857ed6ebfe95e9fb9fa3d3c25f1353b905c9b73cfb624/lxml-6.0.2-cp310-cp310-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a8ffaeec5dfea5881d4c9d8913a32d10cfe3923495386106e4a24d45300ef79c" }, + { url = "https://mirrors.aliyun.com/pypi/packages/a3/84/02a2d0c38ac9a8b9f9e5e1bbd3f24b3f426044ad618b552e9549ee91bd63/lxml-6.0.2-cp310-cp310-manylinux_2_31_armv7l.whl", hash = "sha256:f2e3b1a6bb38de0bc713edd4d612969dd250ca8b724be8d460001a387507021c" }, + { url = "https://mirrors.aliyun.com/pypi/packages/56/87/e1ceadcc031ec4aa605fe95476892d0b0ba3b7f8c7dcdf88fdeff59a9c86/lxml-6.0.2-cp310-cp310-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d6690ec5ec1cce0385cb20896b16be35247ac8c2046e493d03232f1c2414d321" }, + { url = "https://mirrors.aliyun.com/pypi/packages/fe/13/5bb6cf42bb228353fd4ac5f162c6a84fd68a4d6f67c1031c8cf97e131fc6/lxml-6.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f2a50c3c1d11cad0ebebbac357a97b26aa79d2bcaf46f256551152aa85d3a4d1" }, + { url = "https://mirrors.aliyun.com/pypi/packages/e4/e2/ea0498552102e59834e297c5c6dff8d8ded3db72ed5e8aad77871476f073/lxml-6.0.2-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:3efe1b21c7801ffa29a1112fab3b0f643628c30472d507f39544fd48e9549e34" }, + { url = "https://mirrors.aliyun.com/pypi/packages/6a/9e/8de42b52a73abb8af86c66c969b3b4c2a96567b6ac74637c037d2e3baa60/lxml-6.0.2-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:59c45e125140b2c4b33920d21d83681940ca29f0b83f8629ea1a2196dc8cfe6a" }, + { url = "https://mirrors.aliyun.com/pypi/packages/28/a2/de776a573dfb15114509a37351937c367530865edb10a90189d0b4b9b70a/lxml-6.0.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:452b899faa64f1805943ec1c0c9ebeaece01a1af83e130b69cdefeda180bb42c" }, + { url = "https://mirrors.aliyun.com/pypi/packages/50/a0/3ae1b1f8964c271b5eec91db2043cf8c6c0bce101ebb2a633b51b044db6c/lxml-6.0.2-cp310-cp310-win32.whl", hash = "sha256:1e786a464c191ca43b133906c6903a7e4d56bef376b75d97ccbb8ec5cf1f0a4b" }, + { url = "https://mirrors.aliyun.com/pypi/packages/d1/70/bd42491f0634aad41bdfc1e46f5cff98825fb6185688dc82baa35d509f1a/lxml-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:dacf3c64ef3f7440e3167aa4b49aa9e0fb99e0aa4f9ff03795640bf94531bcb0" }, + { url = "https://mirrors.aliyun.com/pypi/packages/d2/d0/05c6a72299f54c2c561a6c6cbb2f512e047fca20ea97a05e57931f194ac4/lxml-6.0.2-cp310-cp310-win_arm64.whl", hash = "sha256:45f93e6f75123f88d7f0cfd90f2d05f441b808562bf0bc01070a00f53f5028b5" }, + { url = "https://mirrors.aliyun.com/pypi/packages/77/d5/becbe1e2569b474a23f0c672ead8a29ac50b2dc1d5b9de184831bda8d14c/lxml-6.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:13e35cbc684aadf05d8711a5d1b5857c92e5e580efa9a0d2be197199c8def607" }, + { url = "https://mirrors.aliyun.com/pypi/packages/28/66/1ced58f12e804644426b85d0bb8a4478ca77bc1761455da310505f1a3526/lxml-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3b1675e096e17c6fe9c0e8c81434f5736c0739ff9ac6123c87c2d452f48fc938" }, + { url = "https://mirrors.aliyun.com/pypi/packages/11/84/549098ffea39dfd167e3f174b4ce983d0eed61f9d8d25b7bf2a57c3247fc/lxml-6.0.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8ac6e5811ae2870953390452e3476694196f98d447573234592d30488147404d" }, + { url = "https://mirrors.aliyun.com/pypi/packages/ac/bd/f207f16abf9749d2037453d56b643a7471d8fde855a231a12d1e095c4f01/lxml-6.0.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5aa0fc67ae19d7a64c3fe725dc9a1bb11f80e01f78289d05c6f62545affec438" }, + { url = "https://mirrors.aliyun.com/pypi/packages/15/ae/bd813e87d8941d52ad5b65071b1affb48da01c4ed3c9c99e40abb266fbff/lxml-6.0.2-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:de496365750cc472b4e7902a485d3f152ecf57bd3ba03ddd5578ed8ceb4c5964" }, + { url = "https://mirrors.aliyun.com/pypi/packages/02/cd/9bfef16bd1d874fbe0cb51afb00329540f30a3283beb9f0780adbb7eec03/lxml-6.0.2-cp311-cp311-manylinux_2_26_i686.manylinux_2_28_i686.whl", hash = "sha256:200069a593c5e40b8f6fc0d84d86d970ba43138c3e68619ffa234bc9bb806a4d" }, + { url = "https://mirrors.aliyun.com/pypi/packages/b8/89/ea8f91594bc5dbb879734d35a6f2b0ad50605d7fb419de2b63d4211765cc/lxml-6.0.2-cp311-cp311-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7d2de809c2ee3b888b59f995625385f74629707c9355e0ff856445cdcae682b7" }, + { url = "https://mirrors.aliyun.com/pypi/packages/b9/37/9c735274f5dbec726b2db99b98a43950395ba3d4a1043083dba2ad814170/lxml-6.0.2-cp311-cp311-manylinux_2_31_armv7l.whl", hash = "sha256:b2c3da8d93cf5db60e8858c17684c47d01fee6405e554fb55018dd85fc23b178" }, + { url = "https://mirrors.aliyun.com/pypi/packages/20/28/7dfe1ba3475d8bfca3878365075abe002e05d40dfaaeb7ec01b4c587d533/lxml-6.0.2-cp311-cp311-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:442de7530296ef5e188373a1ea5789a46ce90c4847e597856570439621d9c553" }, + { url = "https://mirrors.aliyun.com/pypi/packages/e7/cf/5f14bc0de763498fc29510e3532bf2b4b3a1c1d5d0dff2e900c16ba021ef/lxml-6.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2593c77efde7bfea7f6389f1ab249b15ed4aa5bc5cb5131faa3b843c429fbedb" }, + { url = "https://mirrors.aliyun.com/pypi/packages/1c/b0/bb8275ab5472f32b28cfbbcc6db7c9d092482d3439ca279d8d6fa02f7025/lxml-6.0.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:3e3cb08855967a20f553ff32d147e14329b3ae70ced6edc2f282b94afbc74b2a" }, + { url = "https://mirrors.aliyun.com/pypi/packages/25/4c/7c222753bc72edca3b99dbadba1b064209bc8ed4ad448af990e60dcce462/lxml-6.0.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:2ed6c667fcbb8c19c6791bbf40b7268ef8ddf5a96940ba9404b9f9a304832f6c" }, + { url = "https://mirrors.aliyun.com/pypi/packages/6c/8c/478a0dc6b6ed661451379447cdbec77c05741a75736d97e5b2b729687828/lxml-6.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b8f18914faec94132e5b91e69d76a5c1d7b0c73e2489ea8929c4aaa10b76bbf7" }, + { url = "https://mirrors.aliyun.com/pypi/packages/2d/d9/5be3a6ab2784cdf9accb0703b65e1b64fcdd9311c9f007630c7db0cfcce1/lxml-6.0.2-cp311-cp311-win32.whl", hash = "sha256:6605c604e6daa9e0d7f0a2137bdc47a2e93b59c60a65466353e37f8272f47c46" }, + { url = "https://mirrors.aliyun.com/pypi/packages/e2/7d/ca6fb13349b473d5732fb0ee3eec8f6c80fc0688e76b7d79c1008481bf1f/lxml-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e5867f2651016a3afd8dd2c8238baa66f1e2802f44bc17e236f547ace6647078" }, + { url = "https://mirrors.aliyun.com/pypi/packages/ab/a2/51363b5ecd3eab46563645f3a2c3836a2fc67d01a1b87c5017040f39f567/lxml-6.0.2-cp311-cp311-win_arm64.whl", hash = "sha256:4197fb2534ee05fd3e7afaab5d8bfd6c2e186f65ea7f9cd6a82809c887bd1285" }, + { url = "https://mirrors.aliyun.com/pypi/packages/f3/c8/8ff2bc6b920c84355146cd1ab7d181bc543b89241cfb1ebee824a7c81457/lxml-6.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:a59f5448ba2ceccd06995c95ea59a7674a10de0810f2ce90c9006f3cbc044456" }, + { url = "https://mirrors.aliyun.com/pypi/packages/37/6f/9aae1008083bb501ef63284220ce81638332f9ccbfa53765b2b7502203cf/lxml-6.0.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e8113639f3296706fbac34a30813929e29247718e88173ad849f57ca59754924" }, + { url = "https://mirrors.aliyun.com/pypi/packages/f1/ca/31fb37f99f37f1536c133476674c10b577e409c0a624384147653e38baf2/lxml-6.0.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a8bef9b9825fa8bc816a6e641bb67219489229ebc648be422af695f6e7a4fa7f" }, + { url = "https://mirrors.aliyun.com/pypi/packages/da/87/f6cb9442e4bada8aab5ae7e1046264f62fdbeaa6e3f6211b93f4c0dd97f1/lxml-6.0.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:65ea18d710fd14e0186c2f973dc60bb52039a275f82d3c44a0e42b43440ea534" }, + { url = "https://mirrors.aliyun.com/pypi/packages/c8/20/a7760713e65888db79bbae4f6146a6ae5c04e4a204a3c48896c408cd6ed2/lxml-6.0.2-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c371aa98126a0d4c739ca93ceffa0fd7a5d732e3ac66a46e74339acd4d334564" }, + { url = "https://mirrors.aliyun.com/pypi/packages/a2/b0/7e64e0460fcb36471899f75831509098f3fd7cd02a3833ac517433cb4f8f/lxml-6.0.2-cp312-cp312-manylinux_2_26_i686.manylinux_2_28_i686.whl", hash = "sha256:700efd30c0fa1a3581d80a748157397559396090a51d306ea59a70020223d16f" }, + { url = "https://mirrors.aliyun.com/pypi/packages/b9/e1/e5df362e9ca4e2f48ed6411bd4b3a0ae737cc842e96877f5bf9428055ab4/lxml-6.0.2-cp312-cp312-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c33e66d44fe60e72397b487ee92e01da0d09ba2d66df8eae42d77b6d06e5eba0" }, + { url = "https://mirrors.aliyun.com/pypi/packages/c6/d1/232b3309a02d60f11e71857778bfcd4acbdb86c07db8260caf7d008b08f8/lxml-6.0.2-cp312-cp312-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:90a345bbeaf9d0587a3aaffb7006aa39ccb6ff0e96a57286c0cb2fd1520ea192" }, + { url = "https://mirrors.aliyun.com/pypi/packages/35/35/d955a070994725c4f7d80583a96cab9c107c57a125b20bb5f708fe941011/lxml-6.0.2-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:064fdadaf7a21af3ed1dcaa106b854077fbeada827c18f72aec9346847cd65d0" }, + { url = "https://mirrors.aliyun.com/pypi/packages/1e/be/667d17363b38a78c4bd63cfd4b4632029fd68d2c2dc81f25ce9eb5224dd5/lxml-6.0.2-cp312-cp312-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fbc74f42c3525ac4ffa4b89cbdd00057b6196bcefe8bce794abd42d33a018092" }, + { url = "https://mirrors.aliyun.com/pypi/packages/ea/47/62c70aa4a1c26569bc958c9ca86af2bb4e1f614e8c04fb2989833874f7ae/lxml-6.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6ddff43f702905a4e32bc24f3f2e2edfe0f8fde3277d481bffb709a4cced7a1f" }, + { url = "https://mirrors.aliyun.com/pypi/packages/bd/55/6ceddaca353ebd0f1908ef712c597f8570cc9c58130dbb89903198e441fd/lxml-6.0.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:6da5185951d72e6f5352166e3da7b0dc27aa70bd1090b0eb3f7f7212b53f1bb8" }, + { url = "https://mirrors.aliyun.com/pypi/packages/cf/e8/fd63e15da5e3fd4c2146f8bbb3c14e94ab850589beab88e547b2dbce22e1/lxml-6.0.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:57a86e1ebb4020a38d295c04fc79603c7899e0df71588043eb218722dabc087f" }, + { url = "https://mirrors.aliyun.com/pypi/packages/76/47/b3ec58dc5c374697f5ba37412cd2728f427d056315d124dd4b61da381877/lxml-6.0.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:2047d8234fe735ab77802ce5f2297e410ff40f5238aec569ad7c8e163d7b19a6" }, + { url = "https://mirrors.aliyun.com/pypi/packages/19/93/03ba725df4c3d72afd9596eef4a37a837ce8e4806010569bedfcd2cb68fd/lxml-6.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6f91fd2b2ea15a6800c8e24418c0775a1694eefc011392da73bc6cef2623b322" }, + { url = "https://mirrors.aliyun.com/pypi/packages/c6/80/c06de80bfce881d0ad738576f243911fccf992687ae09fd80b734712b39c/lxml-6.0.2-cp312-cp312-win32.whl", hash = "sha256:3ae2ce7d6fedfb3414a2b6c5e20b249c4c607f72cb8d2bb7cc9c6ec7c6f4e849" }, + { url = "https://mirrors.aliyun.com/pypi/packages/f7/d7/0cdfb6c3e30893463fb3d1e52bc5f5f99684a03c29a0b6b605cfae879cd5/lxml-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:72c87e5ee4e58a8354fb9c7c84cbf95a1c8236c127a5d1b7683f04bed8361e1f" }, + { url = "https://mirrors.aliyun.com/pypi/packages/ea/7b/93c73c67db235931527301ed3785f849c78991e2e34f3fd9a6663ffda4c5/lxml-6.0.2-cp312-cp312-win_arm64.whl", hash = "sha256:61cb10eeb95570153e0c0e554f58df92ecf5109f75eacad4a95baa709e26c3d6" }, + { url = "https://mirrors.aliyun.com/pypi/packages/53/fd/4e8f0540608977aea078bf6d79f128e0e2c2bba8af1acf775c30baa70460/lxml-6.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:9b33d21594afab46f37ae58dfadd06636f154923c4e8a4d754b0127554eb2e77" }, + { url = "https://mirrors.aliyun.com/pypi/packages/5d/f4/2a94a3d3dfd6c6b433501b8d470a1960a20ecce93245cf2db1706adf6c19/lxml-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6c8963287d7a4c5c9a432ff487c52e9c5618667179c18a204bdedb27310f022f" }, + { url = "https://mirrors.aliyun.com/pypi/packages/25/2e/4efa677fa6b322013035d38016f6ae859d06cac67437ca7dc708a6af7028/lxml-6.0.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1941354d92699fb5ffe6ed7b32f9649e43c2feb4b97205f75866f7d21aa91452" }, + { url = "https://mirrors.aliyun.com/pypi/packages/ce/0f/526e78a6d38d109fdbaa5049c62e1d32fdd70c75fb61c4eadf3045d3d124/lxml-6.0.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bb2f6ca0ae2d983ded09357b84af659c954722bbf04dea98030064996d156048" }, + { url = "https://mirrors.aliyun.com/pypi/packages/81/76/99de58d81fa702cc0ea7edae4f4640416c2062813a00ff24bd70ac1d9c9b/lxml-6.0.2-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eb2a12d704f180a902d7fa778c6d71f36ceb7b0d317f34cdc76a5d05aa1dd1df" }, + { url = "https://mirrors.aliyun.com/pypi/packages/b5/35/9e57d25482bc9a9882cb0037fdb9cc18f4b79d85df94fa9d2a89562f1d25/lxml-6.0.2-cp313-cp313-manylinux_2_26_i686.manylinux_2_28_i686.whl", hash = "sha256:6ec0e3f745021bfed19c456647f0298d60a24c9ff86d9d051f52b509663feeb1" }, + { url = "https://mirrors.aliyun.com/pypi/packages/a6/8e/cb99bd0b83ccc3e8f0f528e9aa1f7a9965dfec08c617070c5db8d63a87ce/lxml-6.0.2-cp313-cp313-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:846ae9a12d54e368933b9759052d6206a9e8b250291109c48e350c1f1f49d916" }, + { url = "https://mirrors.aliyun.com/pypi/packages/d0/34/9e591954939276bb679b73773836c6684c22e56d05980e31d52a9a8deb18/lxml-6.0.2-cp313-cp313-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ef9266d2aa545d7374938fb5c484531ef5a2ec7f2d573e62f8ce722c735685fd" }, + { url = "https://mirrors.aliyun.com/pypi/packages/8d/27/b29ff065f9aaca443ee377aff699714fcbffb371b4fce5ac4ca759e436d5/lxml-6.0.2-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:4077b7c79f31755df33b795dc12119cb557a0106bfdab0d2c2d97bd3cf3dffa6" }, + { url = "https://mirrors.aliyun.com/pypi/packages/2b/9f/f756f9c2cd27caa1a6ef8c32ae47aadea697f5c2c6d07b0dae133c244fbe/lxml-6.0.2-cp313-cp313-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a7c5d5e5f1081955358533be077166ee97ed2571d6a66bdba6ec2f609a715d1a" }, + { url = "https://mirrors.aliyun.com/pypi/packages/61/46/bb85ea42d2cb1bd8395484fd72f38e3389611aa496ac7772da9205bbda0e/lxml-6.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:8f8d0cbd0674ee89863a523e6994ac25fd5be9c8486acfc3e5ccea679bad2679" }, + { url = "https://mirrors.aliyun.com/pypi/packages/95/0c/443fc476dcc8e41577f0af70458c50fe299a97bb6b7505bb1ae09aa7f9ac/lxml-6.0.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:2cbcbf6d6e924c28f04a43f3b6f6e272312a090f269eff68a2982e13e5d57659" }, + { url = "https://mirrors.aliyun.com/pypi/packages/48/78/6ef0b359d45bb9697bc5a626e1992fa5d27aa3f8004b137b2314793b50a0/lxml-6.0.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:dfb874cfa53340009af6bdd7e54ebc0d21012a60a4e65d927c2e477112e63484" }, + { url = "https://mirrors.aliyun.com/pypi/packages/ff/ea/e1d33808f386bc1339d08c0dcada6e4712d4ed8e93fcad5f057070b7988a/lxml-6.0.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:fb8dae0b6b8b7f9e96c26fdd8121522ce5de9bb5538010870bd538683d30e9a2" }, + { url = "https://mirrors.aliyun.com/pypi/packages/4f/47/eba75dfd8183673725255247a603b4ad606f4ae657b60c6c145b381697da/lxml-6.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:358d9adae670b63e95bc59747c72f4dc97c9ec58881d4627fe0120da0f90d314" }, + { url = "https://mirrors.aliyun.com/pypi/packages/76/04/5c5e2b8577bc936e219becb2e98cdb1aca14a4921a12995b9d0c523502ae/lxml-6.0.2-cp313-cp313-win32.whl", hash = "sha256:e8cd2415f372e7e5a789d743d133ae474290a90b9023197fd78f32e2dc6873e2" }, + { url = "https://mirrors.aliyun.com/pypi/packages/fe/0a/4643ccc6bb8b143e9f9640aa54e38255f9d3b45feb2cbe7ae2ca47e8782e/lxml-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:b30d46379644fbfc3ab81f8f82ae4de55179414651f110a1514f0b1f8f6cb2d7" }, + { url = "https://mirrors.aliyun.com/pypi/packages/31/ef/dcf1d29c3f530577f61e5fe2f1bd72929acf779953668a8a47a479ae6f26/lxml-6.0.2-cp313-cp313-win_arm64.whl", hash = "sha256:13dcecc9946dca97b11b7c40d29fba63b55ab4170d3c0cf8c0c164343b9bfdcf" }, + { url = "https://mirrors.aliyun.com/pypi/packages/03/15/d4a377b385ab693ce97b472fe0c77c2b16ec79590e688b3ccc71fba19884/lxml-6.0.2-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:b0c732aa23de8f8aec23f4b580d1e52905ef468afb4abeafd3fec77042abb6fe" }, + { url = "https://mirrors.aliyun.com/pypi/packages/c8/e8/c128e37589463668794d503afaeb003987373c5f94d667124ffd8078bbd9/lxml-6.0.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:4468e3b83e10e0317a89a33d28f7aeba1caa4d1a6fd457d115dd4ffe90c5931d" }, + { url = "https://mirrors.aliyun.com/pypi/packages/00/ce/74903904339decdf7da7847bb5741fc98a5451b42fc419a86c0c13d26fe2/lxml-6.0.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:abd44571493973bad4598a3be7e1d807ed45aa2adaf7ab92ab7c62609569b17d" }, + { url = "https://mirrors.aliyun.com/pypi/packages/1f/d3/131dec79ce61c5567fecf82515bd9bc36395df42501b50f7f7f3bd065df0/lxml-6.0.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:370cd78d5855cfbffd57c422851f7d3864e6ae72d0da615fca4dad8c45d375a5" }, + { url = "https://mirrors.aliyun.com/pypi/packages/3a/ea/a43ba9bb750d4ffdd885f2cd333572f5bb900cd2408b67fdda07e85978a0/lxml-6.0.2-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:901e3b4219fa04ef766885fb40fa516a71662a4c61b80c94d25336b4934b71c0" }, + { url = "https://mirrors.aliyun.com/pypi/packages/60/23/6885b451636ae286c34628f70a7ed1fcc759f8d9ad382d132e1c8d3d9bfd/lxml-6.0.2-cp314-cp314-manylinux_2_26_i686.manylinux_2_28_i686.whl", hash = "sha256:a4bf42d2e4cf52c28cc1812d62426b9503cdb0c87a6de81442626aa7d69707ba" }, + { url = "https://mirrors.aliyun.com/pypi/packages/48/5b/fc2ddfc94ddbe3eebb8e9af6e3fd65e2feba4967f6a4e9683875c394c2d8/lxml-6.0.2-cp314-cp314-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b2c7fdaa4d7c3d886a42534adec7cfac73860b89b4e5298752f60aa5984641a0" }, + { url = "https://mirrors.aliyun.com/pypi/packages/29/9c/47293c58cc91769130fbf85531280e8cc7868f7fbb6d92f4670071b9cb3e/lxml-6.0.2-cp314-cp314-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:98a5e1660dc7de2200b00d53fa00bcd3c35a3608c305d45a7bbcaf29fa16e83d" }, + { url = "https://mirrors.aliyun.com/pypi/packages/9b/da/ba6eceb830c762b48e711ded880d7e3e89fc6c7323e587c36540b6b23c6b/lxml-6.0.2-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:dc051506c30b609238d79eda75ee9cab3e520570ec8219844a72a46020901e37" }, + { url = "https://mirrors.aliyun.com/pypi/packages/a5/24/7be3f82cb7990b89118d944b619e53c656c97dc89c28cfb143fdb7cd6f4d/lxml-6.0.2-cp314-cp314-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8799481bbdd212470d17513a54d568f44416db01250f49449647b5ab5b5dccb9" }, + { url = "https://mirrors.aliyun.com/pypi/packages/1b/bd/dcfb9ea1e16c665efd7538fc5d5c34071276ce9220e234217682e7d2c4a5/lxml-6.0.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:9261bb77c2dab42f3ecd9103951aeca2c40277701eb7e912c545c1b16e0e4917" }, + { url = "https://mirrors.aliyun.com/pypi/packages/21/04/a60b0ff9314736316f28316b694bccbbabe100f8483ad83852d77fc7468e/lxml-6.0.2-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:65ac4a01aba353cfa6d5725b95d7aed6356ddc0a3cd734de00124d285b04b64f" }, + { url = "https://mirrors.aliyun.com/pypi/packages/d6/bd/7d54bd1846e5a310d9c715921c5faa71cf5c0853372adf78aee70c8d7aa2/lxml-6.0.2-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:b22a07cbb82fea98f8a2fd814f3d1811ff9ed76d0fc6abc84eb21527596e7cc8" }, + { url = "https://mirrors.aliyun.com/pypi/packages/fd/32/5643d6ab947bc371da21323acb2a6e603cedbe71cb4c99c8254289ab6f4e/lxml-6.0.2-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:d759cdd7f3e055d6bc8d9bec3ad905227b2e4c785dc16c372eb5b5e83123f48a" }, + { url = "https://mirrors.aliyun.com/pypi/packages/33/da/34c1ec4cff1eea7d0b4cd44af8411806ed943141804ac9c5d565302afb78/lxml-6.0.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:945da35a48d193d27c188037a05fec5492937f66fb1958c24fc761fb9d40d43c" }, + { url = "https://mirrors.aliyun.com/pypi/packages/82/57/4eca3e31e54dc89e2c3507e1cd411074a17565fa5ffc437c4ae0a00d439e/lxml-6.0.2-cp314-cp314-win32.whl", hash = "sha256:be3aaa60da67e6153eb15715cc2e19091af5dc75faef8b8a585aea372507384b" }, + { url = "https://mirrors.aliyun.com/pypi/packages/e3/e0/c96cf13eccd20c9421ba910304dae0f619724dcf1702864fd59dd386404d/lxml-6.0.2-cp314-cp314-win_amd64.whl", hash = "sha256:fa25afbadead523f7001caf0c2382afd272c315a033a7b06336da2637d92d6ed" }, + { url = "https://mirrors.aliyun.com/pypi/packages/d5/5d/b3f03e22b3d38d6f188ef044900a9b29b2fe0aebb94625ce9fe244011d34/lxml-6.0.2-cp314-cp314-win_arm64.whl", hash = "sha256:063eccf89df5b24e361b123e257e437f9e9878f425ee9aae3144c77faf6da6d8" }, + { url = "https://mirrors.aliyun.com/pypi/packages/5e/5c/42c2c4c03554580708fc738d13414801f340c04c3eff90d8d2d227145275/lxml-6.0.2-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:6162a86d86893d63084faaf4ff937b3daea233e3682fb4474db07395794fa80d" }, + { url = "https://mirrors.aliyun.com/pypi/packages/bf/4f/12df843e3e10d18d468a7557058f8d3733e8b6e12401f30b1ef29360740f/lxml-6.0.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:414aaa94e974e23a3e92e7ca5b97d10c0cf37b6481f50911032c69eeb3991bba" }, + { url = "https://mirrors.aliyun.com/pypi/packages/e4/0c/9dc31e6c2d0d418483cbcb469d1f5a582a1cd00a1f4081953d44051f3c50/lxml-6.0.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:48461bd21625458dd01e14e2c38dd0aea69addc3c4f960c30d9f59d7f93be601" }, + { url = "https://mirrors.aliyun.com/pypi/packages/e7/2b/9b870c6ca24c841bdd887504808f0417aa9d8d564114689266f19ddf29c8/lxml-6.0.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:25fcc59afc57d527cfc78a58f40ab4c9b8fd096a9a3f964d2781ffb6eb33f4ed" }, + { url = "https://mirrors.aliyun.com/pypi/packages/bf/0c/4f5f2a4dd319a178912751564471355d9019e220c20d7db3fb8307ed8582/lxml-6.0.2-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5179c60288204e6ddde3f774a93350177e08876eaf3ab78aa3a3649d43eb7d37" }, + { url = "https://mirrors.aliyun.com/pypi/packages/12/64/554eed290365267671fe001a20d72d14f468ae4e6acef1e179b039436967/lxml-6.0.2-cp314-cp314t-manylinux_2_26_i686.manylinux_2_28_i686.whl", hash = "sha256:967aab75434de148ec80597b75062d8123cadf2943fb4281f385141e18b21338" }, + { url = "https://mirrors.aliyun.com/pypi/packages/7a/31/1d748aa275e71802ad9722df32a7a35034246b42c0ecdd8235412c3396ef/lxml-6.0.2-cp314-cp314t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d100fcc8930d697c6561156c6810ab4a508fb264c8b6779e6e61e2ed5e7558f9" }, + { url = "https://mirrors.aliyun.com/pypi/packages/8f/41/2c11916bcac09ed561adccacceaedd2bf0e0b25b297ea92aab99fd03d0fa/lxml-6.0.2-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2ca59e7e13e5981175b8b3e4ab84d7da57993eeff53c07764dcebda0d0e64ecd" }, + { url = "https://mirrors.aliyun.com/pypi/packages/99/05/4e5c2873d8f17aa018e6afde417c80cc5d0c33be4854cce3ef5670c49367/lxml-6.0.2-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:957448ac63a42e2e49531b9d6c0fa449a1970dbc32467aaad46f11545be9af1d" }, + { url = "https://mirrors.aliyun.com/pypi/packages/0f/c9/dcc2da1bebd6275cdc723b515f93edf548b82f36a5458cca3578bc899332/lxml-6.0.2-cp314-cp314t-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b7fc49c37f1786284b12af63152fe1d0990722497e2d5817acfe7a877522f9a9" }, + { url = "https://mirrors.aliyun.com/pypi/packages/9c/e2/5172e4e7468afca64a37b81dba152fc5d90e30f9c83c7c3213d6a02a5ce4/lxml-6.0.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e19e0643cc936a22e837f79d01a550678da8377d7d801a14487c10c34ee49c7e" }, + { url = "https://mirrors.aliyun.com/pypi/packages/a5/b3/15461fd3e5cd4ddcb7938b87fc20b14ab113b92312fc97afe65cd7c85de1/lxml-6.0.2-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:1db01e5cf14345628e0cbe71067204db658e2fb8e51e7f33631f5f4735fefd8d" }, + { url = "https://mirrors.aliyun.com/pypi/packages/05/33/f310b987c8bf9e61c4dd8e8035c416bd3230098f5e3cfa69fc4232de7059/lxml-6.0.2-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:875c6b5ab39ad5291588aed6925fac99d0097af0dd62f33c7b43736043d4a2ec" }, + { url = "https://mirrors.aliyun.com/pypi/packages/70/ff/51c80e75e0bc9382158133bdcf4e339b5886c6ee2418b5199b3f1a61ed6d/lxml-6.0.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:cdcbed9ad19da81c480dfd6dd161886db6096083c9938ead313d94b30aadf272" }, + { url = "https://mirrors.aliyun.com/pypi/packages/56/4d/4856e897df0d588789dd844dbed9d91782c4ef0b327f96ce53c807e13128/lxml-6.0.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:80dadc234ebc532e09be1975ff538d154a7fa61ea5031c03d25178855544728f" }, + { url = "https://mirrors.aliyun.com/pypi/packages/0f/85/86766dfebfa87bea0ab78e9ff7a4b4b45225df4b4d3b8cc3c03c5cd68464/lxml-6.0.2-cp314-cp314t-win32.whl", hash = "sha256:da08e7bb297b04e893d91087df19638dc7a6bb858a954b0cc2b9f5053c922312" }, + { url = "https://mirrors.aliyun.com/pypi/packages/fe/1a/b248b355834c8e32614650b8008c69ffeb0ceb149c793961dd8c0b991bb3/lxml-6.0.2-cp314-cp314t-win_amd64.whl", hash = "sha256:252a22982dca42f6155125ac76d3432e548a7625d56f5a273ee78a5057216eca" }, + { url = "https://mirrors.aliyun.com/pypi/packages/92/aa/df863bcc39c5e0946263454aba394de8a9084dbaff8ad143846b0d844739/lxml-6.0.2-cp314-cp314t-win_arm64.whl", hash = "sha256:bb4c1847b303835d89d785a18801a883436cdfd5dc3d62947f9c49e24f0f5a2c" }, + { url = "https://mirrors.aliyun.com/pypi/packages/5d/09/4d693ed4c8a407ceda14683bdbb6fcb6b72c7343382a06fe9d94ff18bdf1/lxml-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a656ca105115f6b766bba324f23a67914d9c728dafec57638e2b92a9dcd76c62" }, + { url = "https://mirrors.aliyun.com/pypi/packages/5e/f9/096e3a62d48438fbe2b70bb0e94d9652dfa5ac7b1ecf56c68a3c5143c2d5/lxml-6.0.2-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c54d83a2188a10ebdba573f16bd97135d06c9ef60c3dc495315c7a28c80a263f" }, + { url = "https://mirrors.aliyun.com/pypi/packages/54/0f/67d09bf12edcdbc308c0a66ad9d769aeb5c7742f35646ccede1771efafa3/lxml-6.0.2-cp38-cp38-manylinux_2_26_i686.manylinux_2_28_i686.whl", hash = "sha256:1ea99340b3c729beea786f78c38f60f4795622f36e305d9c9be402201efdc3b7" }, + { url = "https://mirrors.aliyun.com/pypi/packages/4e/f0/49a595035c6b329840452fe9c163b3b7e0b330d542e687a318ea2a21f6e6/lxml-6.0.2-cp38-cp38-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:af85529ae8d2a453feee4c780d9406a5e3b17cee0dd75c18bd31adcd584debc3" }, + { url = "https://mirrors.aliyun.com/pypi/packages/c8/f1/3bfa59b1397206624d8debddb23882cf09099901de15562028f7676916d4/lxml-6.0.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:fe659f6b5d10fb5a17f00a50eb903eb277a71ee35df4615db573c069bcf967ac" }, + { url = "https://mirrors.aliyun.com/pypi/packages/62/b3/59a1126e6d94cd95c37745599f252a634455b7bfd78b344177d32c870eff/lxml-6.0.2-cp38-cp38-win32.whl", hash = "sha256:5921d924aa5468c939d95c9814fa9f9b5935a6ff4e679e26aaf2951f74043512" }, + { url = "https://mirrors.aliyun.com/pypi/packages/e3/b0/f9a25749c3c076b2dcf1df6f427adb0cdcf387fe307d2b153b6f13cbb033/lxml-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:0aa7070978f893954008ab73bb9e3c24a7c56c054e00566a21b553dc18105fca" }, + { url = "https://mirrors.aliyun.com/pypi/packages/38/66/dd13c74fad495957374c8a81c932f4874d3dca5aa0db9e4369f06a399718/lxml-6.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2c8458c2cdd29589a8367c09c8f030f1d202be673f0ca224ec18590b3b9fb694" }, + { url = "https://mirrors.aliyun.com/pypi/packages/5e/f4/edb9d47dce464b5dd044d35775ee794364935b93ab6226c95e199118890d/lxml-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3fee0851639d06276e6b387f1c190eb9d7f06f7f53514e966b26bae46481ec90" }, + { url = "https://mirrors.aliyun.com/pypi/packages/66/f2/d80c97b6ed83a99bc24b2b29919d5e618af5322df6d3aa61064093712309/lxml-6.0.2-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b2142a376b40b6736dfc214fd2902409e9e3857eff554fed2d3c60f097e62a62" }, + { url = "https://mirrors.aliyun.com/pypi/packages/d5/f1/18b750f79f8889b9109b24749f23ac137870b4f685edc4be54be0ff2c730/lxml-6.0.2-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a6b5b39cc7e2998f968f05309e666103b53e2edd01df8dc51b90d734c0825444" }, + { url = "https://mirrors.aliyun.com/pypi/packages/cf/88/2b6a415dbad411c3e9c092128eb7db06054d2d9460aa56676d17ee4f4fd5/lxml-6.0.2-cp39-cp39-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d4aec24d6b72ee457ec665344a29acb2d35937d5192faebe429ea02633151aad" }, + { url = "https://mirrors.aliyun.com/pypi/packages/7c/d0/5354afaa0f2e53625e5f96f6bd049a4875c3ab79d96d6c4871dd1f4a98c4/lxml-6.0.2-cp39-cp39-manylinux_2_26_i686.manylinux_2_28_i686.whl", hash = "sha256:b42f4d86b451c2f9d06ffb4f8bbc776e04df3ba070b9fe2657804b1b40277c48" }, + { url = "https://mirrors.aliyun.com/pypi/packages/51/63/10dea35a01291dc529fa9d6ba204ea627a1c77b7fbb180d404f6cc4dd2fd/lxml-6.0.2-cp39-cp39-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6cdaefac66e8b8f30e37a9b4768a391e1f8a16a7526d5bc77a7928408ef68e93" }, + { url = "https://mirrors.aliyun.com/pypi/packages/37/58/51ef422d8bec58db600b3552e5f2d870ec01ffacf11d98689c42ffdcbf7f/lxml-6.0.2-cp39-cp39-manylinux_2_31_armv7l.whl", hash = "sha256:b738f7e648735714bbb82bdfd030203360cfeab7f6e8a34772b3c8c8b820568c" }, + { url = "https://mirrors.aliyun.com/pypi/packages/77/97/3f797820e82e3a58a19bc51068b40f3b9ab7d0934ba6e5ba6b147b618319/lxml-6.0.2-cp39-cp39-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:daf42de090d59db025af61ce6bdb2521f0f102ea0e6ea310f13c17610a97da4c" }, + { url = "https://mirrors.aliyun.com/pypi/packages/e2/14/a9306a8ab122e2f5dfbf4f71fb09beeadca26b0c275708432bbc33f40edc/lxml-6.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:66328dabea70b5ba7e53d94aa774b733cf66686535f3bc9250a7aab53a91caaf" }, + { url = "https://mirrors.aliyun.com/pypi/packages/ea/23/2118a1685277b9fa8726ec7ee903db55aa300dcea3d406a220cbe3710953/lxml-6.0.2-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:e237b807d68a61fc3b1e845407e27e5eb8ef69bc93fe8505337c1acb4ee300b6" }, + { url = "https://mirrors.aliyun.com/pypi/packages/4e/e8/d5be34da2059dc9a4ff8643fd6ad3f8234a27b2a44831b7fff58c4dbb3e3/lxml-6.0.2-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:ac02dc29fd397608f8eb15ac1610ae2f2f0154b03f631e6d724d9e2ad4ee2c84" }, + { url = "https://mirrors.aliyun.com/pypi/packages/61/84/5aebc8e150d5bf488815ea2d8798c7ff509cc37b5725caa3c1f11bdd3245/lxml-6.0.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:817ef43a0c0b4a77bd166dc9a09a555394105ff3374777ad41f453526e37f9cb" }, + { url = "https://mirrors.aliyun.com/pypi/packages/35/04/629ae603c1c17fb7adc9df2bc21aa5ac96afb84001700b13c1f038f3118c/lxml-6.0.2-cp39-cp39-win32.whl", hash = "sha256:bc532422ff26b304cfb62b328826bd995c96154ffd2bac4544f37dbb95ecaa8f" }, + { url = "https://mirrors.aliyun.com/pypi/packages/71/de/07b7b1249acbecbf48f7e42c3ce87a657af6ff38e30f12a1ad81f16010f2/lxml-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:995e783eb0374c120f528f807443ad5a83a656a8624c467ea73781fc5f8a8304" }, + { url = "https://mirrors.aliyun.com/pypi/packages/60/e3/02c4c55b281606f3c8e118300e16a9fcf5f3462cc46ce740ed0b82fc3f1b/lxml-6.0.2-cp39-cp39-win_arm64.whl", hash = "sha256:08b9d5e803c2e4725ae9e8559ee880e5328ed61aa0935244e0515d7d9dbec0aa" }, + { url = "https://mirrors.aliyun.com/pypi/packages/e7/9c/780c9a8fce3f04690b374f72f41306866b0400b9d0fdf3e17aaa37887eed/lxml-6.0.2-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:e748d4cf8fef2526bb2a589a417eba0c8674e29ffcb570ce2ceca44f1e567bf6" }, + { url = "https://mirrors.aliyun.com/pypi/packages/f5/5a/1ab260c00adf645d8bf7dec7f920f744b032f69130c681302821d5debea6/lxml-6.0.2-pp310-pypy310_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:4ddb1049fa0579d0cbd00503ad8c58b9ab34d1254c77bc6a5576d96ec7853dba" }, + { url = "https://mirrors.aliyun.com/pypi/packages/f2/37/565f3b3d7ffede22874b6d86be1a1763d00f4ea9fc5b9b6ccb11e4ec8612/lxml-6.0.2-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:cb233f9c95f83707dae461b12b720c1af9c28c2d19208e1be03387222151daf5" }, + { url = "https://mirrors.aliyun.com/pypi/packages/22/ec/f3a1b169b2fb9d03467e2e3c0c752ea30e993be440a068b125fc7dd248b0/lxml-6.0.2-pp310-pypy310_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bc456d04db0515ce3320d714a1eac7a97774ff0849e7718b492d957da4631dd4" }, + { url = "https://mirrors.aliyun.com/pypi/packages/77/a2/585a28fe3e67daa1cf2f06f34490d556d121c25d500b10082a7db96e3bcd/lxml-6.0.2-pp310-pypy310_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2613e67de13d619fd283d58bda40bff0ee07739f624ffee8b13b631abf33083d" }, + { url = "https://mirrors.aliyun.com/pypi/packages/7b/d9/a57dd8bcebd7c69386c20263830d4fa72d27e6b72a229ef7a48e88952d9a/lxml-6.0.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:24a8e756c982c001ca8d59e87c80c4d9dcd4d9b44a4cbeb8d9be4482c514d41d" }, + { url = "https://mirrors.aliyun.com/pypi/packages/0b/11/29d08bc103a62c0eba8016e7ed5aeebbf1e4312e83b0b1648dd203b0e87d/lxml-6.0.2-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:1c06035eafa8404b5cf475bb37a9f6088b0aca288d4ccc9d69389750d5543700" }, + { url = "https://mirrors.aliyun.com/pypi/packages/12/b3/52ab9a3b31e5ab8238da241baa19eec44d2ab426532441ee607165aebb52/lxml-6.0.2-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c7d13103045de1bdd6fe5d61802565f1a3537d70cd3abf596aa0af62761921ee" }, + { url = "https://mirrors.aliyun.com/pypi/packages/a0/33/1eaf780c1baad88224611df13b1c2a9dfa460b526cacfe769103ff50d845/lxml-6.0.2-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0a3c150a95fbe5ac91de323aa756219ef9cf7fde5a3f00e2281e30f33fa5fa4f" }, + { url = "https://mirrors.aliyun.com/pypi/packages/7a/c1/27428a2ff348e994ab4f8777d3a0ad510b6b92d37718e5887d2da99952a2/lxml-6.0.2-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:60fa43be34f78bebb27812ed90f1925ec99560b0fa1decdb7d12b84d857d31e9" }, + { url = "https://mirrors.aliyun.com/pypi/packages/f0/d0/3020fa12bcec4ab62f97aab026d57c2f0cfd480a558758d9ca233bb6a79d/lxml-6.0.2-pp311-pypy311_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:21c73b476d3cfe836be731225ec3421fa2f048d84f6df6a8e70433dff1376d5a" }, + { url = "https://mirrors.aliyun.com/pypi/packages/6c/77/d7f491cbc05303ac6801651aabeb262d43f319288c1ea96c66b1d2692ff3/lxml-6.0.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:27220da5be049e936c3aca06f174e8827ca6445a4353a1995584311487fc4e3e" }, +] + +[[package]] +name = "markupsafe" +version = "2.1.5" +source = { registry = "https://mirrors.aliyun.com/pypi/simple" } +resolution-markers = [ + "python_full_version < '3.9'", +] +sdist = { url = "https://mirrors.aliyun.com/pypi/packages/87/5b/aae44c6655f3801e81aa3eef09dbbf012431987ba564d7231722f68df02d/MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b" } +wheels = [ + { url = "https://mirrors.aliyun.com/pypi/packages/e4/54/ad5eb37bf9d51800010a74e4665425831a9db4e7c4e0fde4352e391e808e/MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc" }, + { url = "https://mirrors.aliyun.com/pypi/packages/6a/4a/a4d49415e600bacae038c67f9fecc1d5433b9d3c71a4de6f33537b89654c/MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5" }, + { url = "https://mirrors.aliyun.com/pypi/packages/0a/7b/85681ae3c33c385b10ac0f8dd025c30af83c78cec1c37a6aa3b55e67f5ec/MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46" }, + { url = "https://mirrors.aliyun.com/pypi/packages/7c/52/2b1b570f6b8b803cef5ac28fdf78c0da318916c7d2fe9402a84d591b394c/MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f" }, + { url = "https://mirrors.aliyun.com/pypi/packages/29/fe/a36ba8c7ca55621620b2d7c585313efd10729e63ef81e4e61f52330da781/MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900" }, + { url = "https://mirrors.aliyun.com/pypi/packages/60/ae/9c60231cdfda003434e8bd27282b1f4e197ad5a710c14bee8bea8a9ca4f0/MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff" }, + { url = "https://mirrors.aliyun.com/pypi/packages/65/dc/1510be4d179869f5dafe071aecb3f1f41b45d37c02329dfba01ff59e5ac5/MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad" }, + { url = "https://mirrors.aliyun.com/pypi/packages/30/39/8d845dd7d0b0613d86e0ef89549bfb5f61ed781f59af45fc96496e897f3a/MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd" }, + { url = "https://mirrors.aliyun.com/pypi/packages/c7/5c/356a6f62e4f3c5fbf2602b4771376af22a3b16efa74eb8716fb4e328e01e/MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4" }, + { url = "https://mirrors.aliyun.com/pypi/packages/69/48/acbf292615c65f0604a0c6fc402ce6d8c991276e16c80c46a8f758fbd30c/MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5" }, + { url = "https://mirrors.aliyun.com/pypi/packages/11/e7/291e55127bb2ae67c64d66cef01432b5933859dfb7d6949daa721b89d0b3/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f" }, + { url = "https://mirrors.aliyun.com/pypi/packages/6b/cb/aed7a284c00dfa7c0682d14df85ad4955a350a21d2e3b06d8240497359bf/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2" }, + { url = "https://mirrors.aliyun.com/pypi/packages/1c/cf/35fe557e53709e93feb65575c93927942087e9b97213eabc3fe9d5b25a55/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced" }, + { url = "https://mirrors.aliyun.com/pypi/packages/97/18/c30da5e7a0e7f4603abfc6780574131221d9148f323752c2755d48abad30/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5" }, + { url = "https://mirrors.aliyun.com/pypi/packages/0c/40/2e73e7d532d030b1e41180807a80d564eda53babaf04d65e15c1cf897e40/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c" }, + { url = "https://mirrors.aliyun.com/pypi/packages/18/46/5dca760547e8c59c5311b332f70605d24c99d1303dd9a6e1fc3ed0d73561/MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f" }, + { url = "https://mirrors.aliyun.com/pypi/packages/6d/c5/27febe918ac36397919cd4a67d5579cbbfa8da027fa1238af6285bb368ea/MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a" }, + { url = "https://mirrors.aliyun.com/pypi/packages/f8/81/56e567126a2c2bc2684d6391332e357589a96a76cb9f8e5052d85cb0ead8/MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f" }, + { url = "https://mirrors.aliyun.com/pypi/packages/00/0b/23f4b2470accb53285c613a3ab9ec19dc944eaf53592cb6d9e2af8aa24cc/MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906" }, + { url = "https://mirrors.aliyun.com/pypi/packages/b7/a2/c78a06a9ec6d04b3445a949615c4c7ed86a0b2eb68e44e7541b9d57067cc/MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617" }, + { url = "https://mirrors.aliyun.com/pypi/packages/53/bd/583bf3e4c8d6a321938c13f49d44024dbe5ed63e0a7ba127e454a66da974/MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1" }, + { url = "https://mirrors.aliyun.com/pypi/packages/48/d6/e7cd795fc710292c3af3a06d80868ce4b02bfbbf370b7cee11d282815a2a/MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4" }, + { url = "https://mirrors.aliyun.com/pypi/packages/51/b5/5d8ec796e2a08fc814a2c7d2584b55f889a55cf17dd1a90f2beb70744e5c/MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee" }, + { url = "https://mirrors.aliyun.com/pypi/packages/0a/0d/2454f072fae3b5a137c119abf15465d1771319dfe9e4acbb31722a0fff91/MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5" }, + { url = "https://mirrors.aliyun.com/pypi/packages/2d/75/fd6cb2e68780f72d47e6671840ca517bda5ef663d30ada7616b0462ad1e3/MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b" }, + { url = "https://mirrors.aliyun.com/pypi/packages/b0/81/147c477391c2750e8fc7705829f7351cf1cd3be64406edcf900dc633feb2/MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a" }, + { url = "https://mirrors.aliyun.com/pypi/packages/8b/ff/9a52b71839d7a256b563e85d11050e307121000dcebc97df120176b3ad93/MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f" }, + { url = "https://mirrors.aliyun.com/pypi/packages/88/07/2dc76aa51b481eb96a4c3198894f38b480490e834479611a4053fbf08623/MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169" }, + { url = "https://mirrors.aliyun.com/pypi/packages/96/0c/620c1fb3661858c0e37eb3cbffd8c6f732a67cd97296f725789679801b31/MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad" }, + { url = "https://mirrors.aliyun.com/pypi/packages/3f/14/c3554d512d5f9100a95e737502f4a2323a1959f6d0d01e0d0997b35f7b10/MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb" }, + { url = "https://mirrors.aliyun.com/pypi/packages/f8/ff/2c942a82c35a49df5de3a630ce0a8456ac2969691b230e530ac12314364c/MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a" }, + { url = "https://mirrors.aliyun.com/pypi/packages/4f/14/6f294b9c4f969d0c801a4615e221c1e084722ea6114ab2114189c5b8cbe0/MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46" }, + { url = "https://mirrors.aliyun.com/pypi/packages/81/d4/fd74714ed30a1dedd0b82427c02fa4deec64f173831ec716da11c51a50aa/MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532" }, + { url = "https://mirrors.aliyun.com/pypi/packages/c7/bd/50319665ce81bb10e90d1cf76f9e1aa269ea6f7fa30ab4521f14d122a3df/MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab" }, + { url = "https://mirrors.aliyun.com/pypi/packages/4c/6f/f2b0f675635b05f6afd5ea03c094557bdb8622fa8e673387444fe8d8e787/MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68" }, + { url = "https://mirrors.aliyun.com/pypi/packages/51/e0/393467cf899b34a9d3678e78961c2c8cdf49fb902a959ba54ece01273fb1/MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0" }, + { url = "https://mirrors.aliyun.com/pypi/packages/f6/02/5437e2ad33047290dafced9df741d9efc3e716b75583bbd73a9984f1b6f7/MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4" }, + { url = "https://mirrors.aliyun.com/pypi/packages/0e/7d/968284145ffd9d726183ed6237c77938c021abacde4e073020f920e060b2/MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3" }, + { url = "https://mirrors.aliyun.com/pypi/packages/bf/f3/ecb00fc8ab02b7beae8699f34db9357ae49d9f21d4d3de6f305f34fa949e/MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff" }, + { url = "https://mirrors.aliyun.com/pypi/packages/92/21/357205f03514a49b293e214ac39de01fadd0970a6e05e4bf1ddd0ffd0881/MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029" }, + { url = "https://mirrors.aliyun.com/pypi/packages/0f/31/780bb297db036ba7b7bbede5e1d7f1e14d704ad4beb3ce53fb495d22bc62/MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf" }, + { url = "https://mirrors.aliyun.com/pypi/packages/6c/77/d77701bbef72892affe060cdacb7a2ed7fd68dae3b477a8642f15ad3b132/MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2" }, + { url = "https://mirrors.aliyun.com/pypi/packages/d9/a7/1e558b4f78454c8a3a0199292d96159eb4d091f983bc35ef258314fe7269/MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8" }, + { url = "https://mirrors.aliyun.com/pypi/packages/5f/5a/360da85076688755ea0cceb92472923086993e86b5613bbae9fbc14136b0/MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3" }, + { url = "https://mirrors.aliyun.com/pypi/packages/6a/18/ae5a258e3401f9b8312f92b028c54d7026a97ec3ab20bfaddbdfa7d8cce8/MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465" }, + { url = "https://mirrors.aliyun.com/pypi/packages/0b/cc/48206bd61c5b9d0129f4d75243b156929b04c94c09041321456fd06a876d/MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e" }, + { url = "https://mirrors.aliyun.com/pypi/packages/d1/06/a41c112ab9ffdeeb5f77bc3e331fdadf97fa65e52e44ba31880f4e7f983c/MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea" }, + { url = "https://mirrors.aliyun.com/pypi/packages/02/8c/ab9a463301a50dab04d5472e998acbd4080597abc048166ded5c7aa768c8/MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6" }, + { url = "https://mirrors.aliyun.com/pypi/packages/bc/29/9bc18da763496b055d8e98ce476c8e718dcfd78157e17f555ce6dd7d0895/MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf" }, + { url = "https://mirrors.aliyun.com/pypi/packages/f6/f8/4da07de16f10551ca1f640c92b5f316f9394088b183c6a57183df6de5ae4/MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5" }, +] + +[[package]] +name = "markupsafe" +version = "3.0.3" +source = { registry = "https://mirrors.aliyun.com/pypi/simple" } +resolution-markers = [ + "python_full_version >= '3.10'", + "python_full_version == '3.9.*'", +] +sdist = { url = "https://mirrors.aliyun.com/pypi/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698" } +wheels = [ + { url = "https://mirrors.aliyun.com/pypi/packages/e8/4b/3541d44f3937ba468b75da9eebcae497dcf67adb65caa16760b0a6807ebb/markupsafe-3.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559" }, + { url = "https://mirrors.aliyun.com/pypi/packages/98/1b/fbd8eed11021cabd9226c37342fa6ca4e8a98d8188a8d9b66740494960e4/markupsafe-3.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419" }, + { url = "https://mirrors.aliyun.com/pypi/packages/40/01/e560d658dc0bb8ab762670ece35281dec7b6c1b33f5fbc09ebb57a185519/markupsafe-3.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ba88449deb3de88bd40044603fafffb7bc2b055d626a330323a9ed736661695" }, + { url = "https://mirrors.aliyun.com/pypi/packages/af/cd/ce6e848bbf2c32314c9b237839119c5a564a59725b53157c856e90937b7a/markupsafe-3.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f42d0984e947b8adf7dd6dde396e720934d12c506ce84eea8476409563607591" }, + { url = "https://mirrors.aliyun.com/pypi/packages/c9/2a/b5c12c809f1c3045c4d580b035a743d12fcde53cf685dbc44660826308da/markupsafe-3.0.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c0c0b3ade1c0b13b936d7970b1d37a57acde9199dc2aecc4c336773e1d86049c" }, + { url = "https://mirrors.aliyun.com/pypi/packages/cf/e3/9427a68c82728d0a88c50f890d0fc072a1484de2f3ac1ad0bfc1a7214fd5/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f" }, + { url = "https://mirrors.aliyun.com/pypi/packages/bc/36/23578f29e9e582a4d0278e009b38081dbe363c5e7165113fad546918a232/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:d2ee202e79d8ed691ceebae8e0486bd9a2cd4794cec4824e1c99b6f5009502f6" }, + { url = "https://mirrors.aliyun.com/pypi/packages/56/21/dca11354e756ebd03e036bd8ad58d6d7168c80ce1fe5e75218e4945cbab7/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:177b5253b2834fe3678cb4a5f0059808258584c559193998be2601324fdeafb1" }, + { url = "https://mirrors.aliyun.com/pypi/packages/87/99/faba9369a7ad6e4d10b6a5fbf71fa2a188fe4a593b15f0963b73859a1bbd/markupsafe-3.0.3-cp310-cp310-win32.whl", hash = "sha256:2a15a08b17dd94c53a1da0438822d70ebcd13f8c3a95abe3a9ef9f11a94830aa" }, + { url = "https://mirrors.aliyun.com/pypi/packages/d6/25/55dc3ab959917602c96985cb1253efaa4ff42f71194bddeb61eb7278b8be/markupsafe-3.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:c4ffb7ebf07cfe8931028e3e4c85f0357459a3f9f9490886198848f4fa002ec8" }, + { url = "https://mirrors.aliyun.com/pypi/packages/d0/9e/0a02226640c255d1da0b8d12e24ac2aa6734da68bff14c05dd53b94a0fc3/markupsafe-3.0.3-cp310-cp310-win_arm64.whl", hash = "sha256:e2103a929dfa2fcaf9bb4e7c091983a49c9ac3b19c9061b6d5427dd7d14d81a1" }, + { url = "https://mirrors.aliyun.com/pypi/packages/08/db/fefacb2136439fc8dd20e797950e749aa1f4997ed584c62cfb8ef7c2be0e/markupsafe-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad" }, + { url = "https://mirrors.aliyun.com/pypi/packages/e1/2e/5898933336b61975ce9dc04decbc0a7f2fee78c30353c5efba7f2d6ff27a/markupsafe-3.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a" }, + { url = "https://mirrors.aliyun.com/pypi/packages/1d/09/adf2df3699d87d1d8184038df46a9c80d78c0148492323f4693df54e17bb/markupsafe-3.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50" }, + { url = "https://mirrors.aliyun.com/pypi/packages/30/ac/0273f6fcb5f42e314c6d8cd99effae6a5354604d461b8d392b5ec9530a54/markupsafe-3.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf" }, + { url = "https://mirrors.aliyun.com/pypi/packages/19/ae/31c1be199ef767124c042c6c3e904da327a2f7f0cd63a0337e1eca2967a8/markupsafe-3.0.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f" }, + { url = "https://mirrors.aliyun.com/pypi/packages/b2/76/7edcab99d5349a4532a459e1fe64f0b0467a3365056ae550d3bcf3f79e1e/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a" }, + { url = "https://mirrors.aliyun.com/pypi/packages/a4/28/6e74cdd26d7514849143d69f0bf2399f929c37dc2b31e6829fd2045b2765/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115" }, + { url = "https://mirrors.aliyun.com/pypi/packages/62/7e/a145f36a5c2945673e590850a6f8014318d5577ed7e5920a4b3448e0865d/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a" }, + { url = "https://mirrors.aliyun.com/pypi/packages/0f/62/d9c46a7f5c9adbeeeda52f5b8d802e1094e9717705a645efc71b0913a0a8/markupsafe-3.0.3-cp311-cp311-win32.whl", hash = "sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19" }, + { url = "https://mirrors.aliyun.com/pypi/packages/83/8a/4414c03d3f891739326e1783338e48fb49781cc915b2e0ee052aa490d586/markupsafe-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01" }, + { url = "https://mirrors.aliyun.com/pypi/packages/35/73/893072b42e6862f319b5207adc9ae06070f095b358655f077f69a35601f0/markupsafe-3.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c" }, + { url = "https://mirrors.aliyun.com/pypi/packages/5a/72/147da192e38635ada20e0a2e1a51cf8823d2119ce8883f7053879c2199b5/markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e" }, + { url = "https://mirrors.aliyun.com/pypi/packages/9a/81/7e4e08678a1f98521201c3079f77db69fb552acd56067661f8c2f534a718/markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce" }, + { url = "https://mirrors.aliyun.com/pypi/packages/1e/2c/799f4742efc39633a1b54a92eec4082e4f815314869865d876824c257c1e/markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d" }, + { url = "https://mirrors.aliyun.com/pypi/packages/3c/2e/8d0c2ab90a8c1d9a24f0399058ab8519a3279d1bd4289511d74e909f060e/markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d" }, + { url = "https://mirrors.aliyun.com/pypi/packages/2c/54/887f3092a85238093a0b2154bd629c89444f395618842e8b0c41783898ea/markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a" }, + { url = "https://mirrors.aliyun.com/pypi/packages/c9/2f/336b8c7b6f4a4d95e91119dc8521402461b74a485558d8f238a68312f11c/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b" }, + { url = "https://mirrors.aliyun.com/pypi/packages/32/43/67935f2b7e4982ffb50a4d169b724d74b62a3964bc1a9a527f5ac4f1ee2b/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f" }, + { url = "https://mirrors.aliyun.com/pypi/packages/89/e0/4486f11e51bbba8b0c041098859e869e304d1c261e59244baa3d295d47b7/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b" }, + { url = "https://mirrors.aliyun.com/pypi/packages/2f/e1/78ee7a023dac597a5825441ebd17170785a9dab23de95d2c7508ade94e0e/markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d" }, + { url = "https://mirrors.aliyun.com/pypi/packages/aa/5b/bec5aa9bbbb2c946ca2733ef9c4ca91c91b6a24580193e891b5f7dbe8e1e/markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c" }, + { url = "https://mirrors.aliyun.com/pypi/packages/e5/f1/216fc1bbfd74011693a4fd837e7026152e89c4bcf3e77b6692fba9923123/markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f" }, + { url = "https://mirrors.aliyun.com/pypi/packages/38/2f/907b9c7bbba283e68f20259574b13d005c121a0fa4c175f9bed27c4597ff/markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795" }, + { url = "https://mirrors.aliyun.com/pypi/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219" }, + { url = "https://mirrors.aliyun.com/pypi/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6" }, + { url = "https://mirrors.aliyun.com/pypi/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676" }, + { url = "https://mirrors.aliyun.com/pypi/packages/7f/71/544260864f893f18b6827315b988c146b559391e6e7e8f7252839b1b846a/markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9" }, + { url = "https://mirrors.aliyun.com/pypi/packages/c2/28/b50fc2f74d1ad761af2f5dcce7492648b983d00a65b8c0e0cb457c82ebbe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1" }, + { url = "https://mirrors.aliyun.com/pypi/packages/ed/76/104b2aa106a208da8b17a2fb72e033a5a9d7073c68f7e508b94916ed47a9/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc" }, + { url = "https://mirrors.aliyun.com/pypi/packages/b5/99/16a5eb2d140087ebd97180d95249b00a03aa87e29cc224056274f2e45fd6/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12" }, + { url = "https://mirrors.aliyun.com/pypi/packages/19/bc/e7140ed90c5d61d77cea142eed9f9c303f4c4806f60a1044c13e3f1471d0/markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed" }, + { url = "https://mirrors.aliyun.com/pypi/packages/05/73/c4abe620b841b6b791f2edc248f556900667a5a1cf023a6646967ae98335/markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5" }, + { url = "https://mirrors.aliyun.com/pypi/packages/f0/3a/fa34a0f7cfef23cf9500d68cb7c32dd64ffd58a12b09225fb03dd37d5b80/markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485" }, + { url = "https://mirrors.aliyun.com/pypi/packages/e4/d7/e05cd7efe43a88a17a37b3ae96e79a19e846f3f456fe79c57ca61356ef01/markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73" }, + { url = "https://mirrors.aliyun.com/pypi/packages/99/9e/e412117548182ce2148bdeacdda3bb494260c0b0184360fe0d56389b523b/markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37" }, + { url = "https://mirrors.aliyun.com/pypi/packages/bc/e6/fa0ffcda717ef64a5108eaa7b4f5ed28d56122c9a6d70ab8b72f9f715c80/markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19" }, + { url = "https://mirrors.aliyun.com/pypi/packages/96/ec/2102e881fe9d25fc16cb4b25d5f5cde50970967ffa5dddafdb771237062d/markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025" }, + { url = "https://mirrors.aliyun.com/pypi/packages/4b/30/6f2fce1f1f205fc9323255b216ca8a235b15860c34b6798f810f05828e32/markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6" }, + { url = "https://mirrors.aliyun.com/pypi/packages/58/47/4a0ccea4ab9f5dcb6f79c0236d954acb382202721e704223a8aafa38b5c8/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f" }, + { url = "https://mirrors.aliyun.com/pypi/packages/6a/70/3780e9b72180b6fecb83a4814d84c3bf4b4ae4bf0b19c27196104149734c/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb" }, + { url = "https://mirrors.aliyun.com/pypi/packages/98/c5/c03c7f4125180fc215220c035beac6b9cb684bc7a067c84fc69414d315f5/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009" }, + { url = "https://mirrors.aliyun.com/pypi/packages/80/d6/2d1b89f6ca4bff1036499b1e29a1d02d282259f3681540e16563f27ebc23/markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354" }, + { url = "https://mirrors.aliyun.com/pypi/packages/2b/98/e48a4bfba0a0ffcf9925fe2d69240bfaa19c6f7507b8cd09c70684a53c1e/markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218" }, + { url = "https://mirrors.aliyun.com/pypi/packages/0e/72/e3cc540f351f316e9ed0f092757459afbc595824ca724cbc5a5d4263713f/markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287" }, + { url = "https://mirrors.aliyun.com/pypi/packages/33/8a/8e42d4838cd89b7dde187011e97fe6c3af66d8c044997d2183fbd6d31352/markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe" }, + { url = "https://mirrors.aliyun.com/pypi/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026" }, + { url = "https://mirrors.aliyun.com/pypi/packages/da/ef/e648bfd021127bef5fa12e1720ffed0c6cbb8310c8d9bea7266337ff06de/markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737" }, + { url = "https://mirrors.aliyun.com/pypi/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97" }, + { url = "https://mirrors.aliyun.com/pypi/packages/bc/20/b7fdf89a8456b099837cd1dc21974632a02a999ec9bf7ca3e490aacd98e7/markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d" }, + { url = "https://mirrors.aliyun.com/pypi/packages/9a/a7/591f592afdc734f47db08a75793a55d7fbcc6902a723ae4cfbab61010cc5/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda" }, + { url = "https://mirrors.aliyun.com/pypi/packages/7d/33/45b24e4f44195b26521bc6f1a82197118f74df348556594bd2262bda1038/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf" }, + { url = "https://mirrors.aliyun.com/pypi/packages/ff/0e/53dfaca23a69fbfbbf17a4b64072090e70717344c52eaaaa9c5ddff1e5f0/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe" }, + { url = "https://mirrors.aliyun.com/pypi/packages/46/11/f333a06fc16236d5238bfe74daccbca41459dcd8d1fa952e8fbd5dccfb70/markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9" }, + { url = "https://mirrors.aliyun.com/pypi/packages/28/52/182836104b33b444e400b14f797212f720cbc9ed6ba34c800639d154e821/markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581" }, + { url = "https://mirrors.aliyun.com/pypi/packages/6f/18/acf23e91bd94fd7b3031558b1f013adfa21a8e407a3fdb32745538730382/markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4" }, + { url = "https://mirrors.aliyun.com/pypi/packages/3c/f0/57689aa4076e1b43b15fdfa646b04653969d50cf30c32a102762be2485da/markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab" }, + { url = "https://mirrors.aliyun.com/pypi/packages/89/c3/2e67a7ca217c6912985ec766c6393b636fb0c2344443ff9d91404dc4c79f/markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175" }, + { url = "https://mirrors.aliyun.com/pypi/packages/f0/00/be561dce4e6ca66b15276e184ce4b8aec61fe83662cce2f7d72bd3249d28/markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634" }, + { url = "https://mirrors.aliyun.com/pypi/packages/50/09/c419f6f5a92e5fadde27efd190eca90f05e1261b10dbd8cbcb39cd8ea1dc/markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50" }, + { url = "https://mirrors.aliyun.com/pypi/packages/22/44/a0681611106e0b2921b3033fc19bc53323e0b50bc70cffdd19f7d679bb66/markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e" }, + { url = "https://mirrors.aliyun.com/pypi/packages/5f/57/1b0b3f100259dc9fffe780cfb60d4be71375510e435efec3d116b6436d43/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5" }, + { url = "https://mirrors.aliyun.com/pypi/packages/26/6a/4bf6d0c97c4920f1597cc14dd720705eca0bf7c787aebc6bb4d1bead5388/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523" }, + { url = "https://mirrors.aliyun.com/pypi/packages/14/c7/ca723101509b518797fedc2fdf79ba57f886b4aca8a7d31857ba3ee8281f/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc" }, + { url = "https://mirrors.aliyun.com/pypi/packages/fb/df/5bd7a48c256faecd1d36edc13133e51397e41b73bb77e1a69deab746ebac/markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d" }, + { url = "https://mirrors.aliyun.com/pypi/packages/1a/8a/0402ba61a2f16038b48b39bccca271134be00c5c9f0f623208399333c448/markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9" }, + { url = "https://mirrors.aliyun.com/pypi/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa" }, + { url = "https://mirrors.aliyun.com/pypi/packages/56/23/0d8c13a44bde9154821586520840643467aee574d8ce79a17da539ee7fed/markupsafe-3.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:15d939a21d546304880945ca1ecb8a039db6b4dc49b2c5a400387cdae6a62e26" }, + { url = "https://mirrors.aliyun.com/pypi/packages/fd/23/07a2cb9a8045d5f3f0890a8c3bc0859d7a47bfd9a560b563899bec7b72ed/markupsafe-3.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f71a396b3bf33ecaa1626c255855702aca4d3d9fea5e051b41ac59a9c1c41edc" }, + { url = "https://mirrors.aliyun.com/pypi/packages/bc/e4/6be85eb81503f8e11b61c0b6369b6e077dcf0a74adbd9ebf6b349937b4e9/markupsafe-3.0.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f4b68347f8c5eab4a13419215bdfd7f8c9b19f2b25520968adfad23eb0ce60c" }, + { url = "https://mirrors.aliyun.com/pypi/packages/6f/bc/4dc914ead3fe6ddaef035341fee0fc956949bbd27335b611829292b89ee2/markupsafe-3.0.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e8fc20152abba6b83724d7ff268c249fa196d8259ff481f3b1476383f8f24e42" }, + { url = "https://mirrors.aliyun.com/pypi/packages/89/6e/5fe81fbcfba4aef4093d5f856e5c774ec2057946052d18d168219b7bd9f9/markupsafe-3.0.3-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:949b8d66bc381ee8b007cd945914c721d9aba8e27f71959d750a46f7c282b20b" }, + { url = "https://mirrors.aliyun.com/pypi/packages/f6/f6/e0e5a3d3ae9c4020f696cd055f940ef86b64fe88de26f3a0308b9d3d048c/markupsafe-3.0.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:3537e01efc9d4dccdf77221fb1cb3b8e1a38d5428920e0657ce299b20324d758" }, + { url = "https://mirrors.aliyun.com/pypi/packages/c8/25/651753ef4dea08ea790f4fbb65146a9a44a014986996ca40102e237aa49a/markupsafe-3.0.3-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:591ae9f2a647529ca990bc681daebdd52c8791ff06c2bfa05b65163e28102ef2" }, + { url = "https://mirrors.aliyun.com/pypi/packages/dc/0a/c3cf2b4fef5f0426e8a6d7fce3cb966a17817c568ce59d76b92a233fdbec/markupsafe-3.0.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a320721ab5a1aba0a233739394eb907f8c8da5c98c9181d1161e77a0c8e36f2d" }, + { url = "https://mirrors.aliyun.com/pypi/packages/cd/1b/a7782984844bd519ad4ffdbebbba2671ec5d0ebbeac34736c15fb86399e8/markupsafe-3.0.3-cp39-cp39-win32.whl", hash = "sha256:df2449253ef108a379b8b5d6b43f4b1a8e81a061d6537becd5582fba5f9196d7" }, + { url = "https://mirrors.aliyun.com/pypi/packages/18/1f/8d9c20e1c9440e215a44be5ab64359e207fcb4f675543f1cf9a2a7f648d0/markupsafe-3.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:7c3fb7d25180895632e5d3148dbdc29ea38ccb7fd210aa27acbd1201a1902c6e" }, + { url = "https://mirrors.aliyun.com/pypi/packages/4e/d3/fe08482b5cd995033556d45041a4f4e76e7f0521112a9c9991d40d39825f/markupsafe-3.0.3-cp39-cp39-win_arm64.whl", hash = "sha256:38664109c14ffc9e7437e86b4dceb442b0096dfe3541d7864d9cbe1da4cf36c8" }, +] + +[[package]] +name = "packaging" +version = "25.0" +source = { registry = "https://mirrors.aliyun.com/pypi/simple" } +sdist = { url = "https://mirrors.aliyun.com/pypi/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f" } +wheels = [ + { url = "https://mirrors.aliyun.com/pypi/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484" }, +] + +[[package]] +name = "pyqt5" +version = "5.15.9" +source = { registry = "https://mirrors.aliyun.com/pypi/simple" } +dependencies = [ + { name = "pyqt5-qt5" }, + { name = "pyqt5-sip", version = "12.15.0", source = { registry = "https://mirrors.aliyun.com/pypi/simple" }, marker = "python_full_version < '3.9'" }, + { name = "pyqt5-sip", version = "12.17.1", source = { registry = "https://mirrors.aliyun.com/pypi/simple" }, marker = "python_full_version == '3.9.*'" }, + { name = "pyqt5-sip", version = "12.17.2", source = { registry = "https://mirrors.aliyun.com/pypi/simple" }, marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://mirrors.aliyun.com/pypi/packages/5c/46/b4b6eae1e24d9432905ef1d4e7c28b6610e28252527cdc38f2a75997d8b5/PyQt5-5.15.9.tar.gz", hash = "sha256:dc41e8401a90dc3e2b692b411bd5492ab559ae27a27424eed4bd3915564ec4c0" } +wheels = [ + { url = "https://mirrors.aliyun.com/pypi/packages/77/c7/82f92662afdd85b69d126353d498f71e0fce03cbf1c01b700e0e495adf16/PyQt5-5.15.9-cp37-abi3-macosx_10_13_x86_64.whl", hash = "sha256:883ba5c8a348be78c8be6a3d3ba014c798e679503bce00d76c666c2dc6afe828" }, + { url = "https://mirrors.aliyun.com/pypi/packages/28/99/78db05e606dbb4a9425c159e7f1f64b69683c16ee3dcd0f97ed9ede6b205/PyQt5-5.15.9-cp37-abi3-manylinux_2_17_x86_64.whl", hash = "sha256:dd5ce10e79fbf1df29507d2daf99270f2057cdd25e4de6fbf2052b46c652e3a5" }, + { url = "https://mirrors.aliyun.com/pypi/packages/f3/b5/00a3c80a4c738e92e9d9e144c9bb5bd9d0842bac5517c63d42e7c9633826/PyQt5-5.15.9-cp37-abi3-win32.whl", hash = "sha256:e45c5cc15d4fd26ab5cb0e5cdba60691a3e9086411f8e3662db07a5a4222a696" }, + { url = "https://mirrors.aliyun.com/pypi/packages/55/5d/8df8a2aa0de6588965d048fca9306cf15a5801be3078f195e8f8f41fa863/PyQt5-5.15.9-cp37-abi3-win_amd64.whl", hash = "sha256:e030d795df4cbbfcf4f38b18e2e119bcc9e177ef658a5094b87bb16cac0ce4c5" }, +] + +[[package]] +name = "pyqt5-plugins" +version = "5.15.9.2.3" +source = { registry = "https://mirrors.aliyun.com/pypi/simple" } +dependencies = [ + { name = "click", version = "8.1.8", source = { registry = "https://mirrors.aliyun.com/pypi/simple" }, marker = "python_full_version < '3.10'" }, + { name = "click", version = "8.3.1", source = { registry = "https://mirrors.aliyun.com/pypi/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "pyqt5" }, + { name = "pyqt5-qt5" }, + { name = "qt5-tools" }, +] +wheels = [ + { url = "https://mirrors.aliyun.com/pypi/packages/66/01/bbadae4076b0d96174d26f93d45676f92dc6a3387c7228ed7e6dff333612/pyqt5_plugins-5.15.9.2.3-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:798b9f7d212972ac3940425d0cfe3a90669520b29b113da9d63a0996b7e121f4" }, + { url = "https://mirrors.aliyun.com/pypi/packages/67/b5/93e6e22d6829fe090436ad8d330ddb6c6911ae4c9de2e83238b7937e9092/pyqt5_plugins-5.15.9.2.3-cp310-cp310-manylinux2014_x86_64.whl", hash = "sha256:a818862de6a19965fca26174d462097829f523e177025e96c415e0389d212616" }, + { url = "https://mirrors.aliyun.com/pypi/packages/bd/95/e343e662e951f90b50ba2b2c3059405d06dff439403001cfe24568c92524/pyqt5_plugins-5.15.9.2.3-cp310-cp310-win32.whl", hash = "sha256:a1abd0aaaf4bb1c0d35ed33eba9707f2212a235f45bf9bd103e65d60147d8865" }, + { url = "https://mirrors.aliyun.com/pypi/packages/42/0b/1499fabac51e183350b05c81b9e059e77dfc63c5aa74eab8ce50f9836a3f/pyqt5_plugins-5.15.9.2.3-cp310-cp310-win_amd64.whl", hash = "sha256:b3f2c1598a171c36bcc78f68d58370e6876afacdda66e0c1e2c1ce861907a7c9" }, + { url = "https://mirrors.aliyun.com/pypi/packages/e7/be/b6cb8bd5b2e05e74178e9bb2b2ecdce76b2067bac41919aff80cb8b17ad0/pyqt5_plugins-5.15.9.2.3-cp311-cp311-macosx_10_13_universal2.whl", hash = "sha256:078b1564a54c1549e40a87c32deb9cf9e77d72f004cd0f5f42a2acfd4d6aea36" }, + { url = "https://mirrors.aliyun.com/pypi/packages/fe/2b/11790a554b49d590cb02b466ea496670b2291c3e828bb9576219d812d0f8/pyqt5_plugins-5.15.9.2.3-cp311-cp311-manylinux2014_x86_64.whl", hash = "sha256:c883469f6d17859c8991d44d72fff6b2b9e3fa18b371c86ff002afb5e790f9c6" }, + { url = "https://mirrors.aliyun.com/pypi/packages/b1/56/616d43b195330f0f322a36fee70a0bea55b641baf57afc58b383d870f471/pyqt5_plugins-5.15.9.2.3-cp311-cp311-win32.whl", hash = "sha256:f48754c09ed46a0b6305109c0c19ed7cd8b13925ba81ef2df2e8a870437b3aa7" }, + { url = "https://mirrors.aliyun.com/pypi/packages/cd/29/b9e0ad2d345b425a111f22eac83e45c68afe8d3475a0adabc2da5dbfa5b3/pyqt5_plugins-5.15.9.2.3-cp311-cp311-win_amd64.whl", hash = "sha256:1d9acf423062c6694a5e68782fb54ce90355481d33281c9193da45c43426853c" }, + { url = "https://mirrors.aliyun.com/pypi/packages/04/fa/a071c78d58a4b7d9344a725d55fdf47dd996d86d7f191cabe47b5d62e2b3/pyqt5_plugins-5.15.9.2.3-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:b862c340b13cf782f77778cc9c5e28ceeb7ecbf9da0c7410b5c55050a59efe59" }, + { url = "https://mirrors.aliyun.com/pypi/packages/bd/35/53cc6d0df6bb84f11d1527c9e3930ab3b61eae39cc41ac8494435a1c6f17/pyqt5_plugins-5.15.9.2.3-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:b4225d531773c3c69814a05877651b29d639f1887f25b8b19dcc0e160427582a" }, + { url = "https://mirrors.aliyun.com/pypi/packages/b7/70/4d3b240f55aa937a93b80f5394ac2a9527d581b64b03b2f657f7d6b0812f/pyqt5_plugins-5.15.9.2.3-cp38-cp38-win32.whl", hash = "sha256:e0715d4149701fac3ad3b6777a272edab7ca375524d4c3742b3a6c11d46b2d35" }, + { url = "https://mirrors.aliyun.com/pypi/packages/ca/35/a9bdf51500444ef9121e1b3c97746dc405c1033fbbe4293d4c84867220a6/pyqt5_plugins-5.15.9.2.3-cp38-cp38-win_amd64.whl", hash = "sha256:ad82f31bfd6c7039909980628fcbcc7e843013dbdfcf3674f1ffaf53f90b71cc" }, + { url = "https://mirrors.aliyun.com/pypi/packages/ce/11/5dc8c6f7588374e0659ce12827f58ad935ee32815b252fcb84dfa57ea779/pyqt5_plugins-5.15.9.2.3-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:3e7ba7995e71ba06d536c8a36168ae03199a3983a727d627000f170d6e3a29f4" }, + { url = "https://mirrors.aliyun.com/pypi/packages/3c/27/991247ea590ce8d95ef25d24a1b97d18db2192caf330401c6ac54983dd58/pyqt5_plugins-5.15.9.2.3-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:b3e747cd3be0885b12e8bde32234df0ee082dfc9607751ce81fb2aa694462048" }, + { url = "https://mirrors.aliyun.com/pypi/packages/59/af/9a2bf5d46db2cbdcf0ab205f6e8a959142fad952a0d057488c9958b19e0f/pyqt5_plugins-5.15.9.2.3-cp39-cp39-win32.whl", hash = "sha256:e4670917c36b039b6d195af177afa369f603aa00376890fd540c955ec56c9284" }, + { url = "https://mirrors.aliyun.com/pypi/packages/72/c0/24afe113ea502a1f18e754241c4e28f1c96be12cc3c18f9de3f08d807148/pyqt5_plugins-5.15.9.2.3-cp39-cp39-win_amd64.whl", hash = "sha256:bacaae333802856871e24045f121967f73e2b5f95a55b633f76b78c6a87e034c" }, +] + +[[package]] +name = "pyqt5-qt5" +version = "5.15.2" +source = { registry = "https://mirrors.aliyun.com/pypi/simple" } +wheels = [ + { url = "https://mirrors.aliyun.com/pypi/packages/62/09/99a222b0360616250fb2e6003a54e43a2a06b0774f0f8d5daafb86a2c375/PyQt5_Qt5-5.15.2-py3-none-macosx_10_13_intel.whl", hash = "sha256:76980cd3d7ae87e3c7a33bfebfaee84448fd650bad6840471d6cae199b56e154" }, + { url = "https://mirrors.aliyun.com/pypi/packages/83/d4/241a6a518d0bcf0a9fcdcbad5edfed18d43e884317eab8d5230a2b27e206/PyQt5_Qt5-5.15.2-py3-none-manylinux2014_x86_64.whl", hash = "sha256:1988f364ec8caf87a6ee5d5a3a5210d57539988bf8e84714c7d60972692e2f4a" }, + { url = "https://mirrors.aliyun.com/pypi/packages/1c/7e/ce7c66a541a105fa98b41d6405fe84940564695e29fc7dccf6d9e8c5f898/PyQt5_Qt5-5.15.2-py3-none-win32.whl", hash = "sha256:9cc7a768b1921f4b982ebc00a318ccb38578e44e45316c7a4a850e953e1dd327" }, + { url = "https://mirrors.aliyun.com/pypi/packages/37/97/5d3b222b924fa2ed4c2488925155cd0b03fd5d09ee1cfcf7c553c11c9f66/PyQt5_Qt5-5.15.2-py3-none-win_amd64.whl", hash = "sha256:750b78e4dba6bdf1607febedc08738e318ea09e9b10aea9ff0d73073f11f6962" }, +] + +[[package]] +name = "pyqt5-sip" +version = "12.15.0" +source = { registry = "https://mirrors.aliyun.com/pypi/simple" } +resolution-markers = [ + "python_full_version < '3.9'", +] +sdist = { url = "https://mirrors.aliyun.com/pypi/packages/1b/15/78318d50f10062c428e97e7ce387e772616a4673c356018b905f247a6a85/PyQt5_sip-12.15.0.tar.gz", hash = "sha256:d23fdfcf363b5cedd9d39f8a9c5710e7d52804f5b08a58e91c638b36eafcb702" } +wheels = [ + { url = "https://mirrors.aliyun.com/pypi/packages/f9/cb/5989258c3d70c78eabaebe3ac900c56c863caf6de7961e4b7b556a8c9e7a/PyQt5_sip-12.15.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:749f7a3ffd6e3d2d5db65ed92c95cbd14490631595c61f0c0672c9238bfb17de" }, + { url = "https://mirrors.aliyun.com/pypi/packages/c1/06/3fffcc82005d83ce5f923c52a13fc40661c081c0aa7a2588af09351d9075/PyQt5_sip-12.15.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:b4adc529fa4ec05728e14ea55194d907cc51f18d6f2ac5cc9f6eb52ac038aa0f" }, + { url = "https://mirrors.aliyun.com/pypi/packages/64/29/9508798f4009a7ffcfb92818fbe6dbfdc63fbc300b32c6c193f5c0879c16/PyQt5_sip-12.15.0-cp310-cp310-win32.whl", hash = "sha256:83d247cdc43ef224410b14c97413067ea26356dfa39e9ed0fe702a31e25710b0" }, + { url = "https://mirrors.aliyun.com/pypi/packages/18/c2/a53caa812b3886550eb82ba7af63a8293a6ffbceaef1f6f192fe34fdd580/PyQt5_sip-12.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:13f0c6a78e781255863e3e160304648efaf62276b7102741af637b63a6e96930" }, + { url = "https://mirrors.aliyun.com/pypi/packages/e9/7e/4b87c65adf9cb74895acc129043d04bb300436cab1e39469f4a9fc40b602/PyQt5_sip-12.15.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:855563d4d3b59ce7438bbf2dd32fed2707787defa40f3efe94f204a19ef92b25" }, + { url = "https://mirrors.aliyun.com/pypi/packages/ec/90/8bf505a096553a253e1a65078ca1aeb6de8a83f27afa3a43bb89ae29da31/PyQt5_sip-12.15.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:0b718a362f4392430903bbb2a4b9bbff9841a16a52f0cfdd5b5bbd9d11457980" }, + { url = "https://mirrors.aliyun.com/pypi/packages/6b/80/ed1a360df9128e0e26e28c6341174a7e02efc57816799af5e3a3cb865fc8/PyQt5_sip-12.15.0-cp311-cp311-win32.whl", hash = "sha256:2575f428de584a12009fd29d00c89df16ed101a3b38beba818dfdcbc4a10709c" }, + { url = "https://mirrors.aliyun.com/pypi/packages/4e/d6/ea034ad64290c541042dc4c349d5aa854c8a0b54802a0759ec37671f0939/PyQt5_sip-12.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:c85be433fbafcb3d417581c0e1b67c8198d23858166e4f938e971c2262c13cdb" }, + { url = "https://mirrors.aliyun.com/pypi/packages/90/47/de48934a0d692c65b0833924a618786146c0869910c707a5e508351d5b91/PyQt5_sip-12.15.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:852b75cf208825602480e95ab63314108f872d0da251e9ad3deaaff5a183a6f5" }, + { url = "https://mirrors.aliyun.com/pypi/packages/d1/6c/9a2fe24f8970e092613f709283a2101403490a209a30de3de89a413d9915/PyQt5_sip-12.15.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:0cd21c3215e3c47fdd5fa7a2dc3dd1e07a7230b0626e905a7217925068c788b9" }, + { url = "https://mirrors.aliyun.com/pypi/packages/90/53/0a4dc2d448619f2a51849e124d375ec7a8e95c938eccfaf8711bb77a62b6/PyQt5_sip-12.15.0-cp312-cp312-win32.whl", hash = "sha256:b58eeedc9b2a3037b136bf96915196c391a33be470ed1c0723d7163ef0b727a2" }, + { url = "https://mirrors.aliyun.com/pypi/packages/aa/c2/c07c531fe5a6124d91942c48a85ff4e14918766cd37819f7841cf2debabb/PyQt5_sip-12.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:24a1d4937332bf0a38dd95bb2ce4d89723df449f6e912b52ef0e107e11fefac1" }, + { url = "https://mirrors.aliyun.com/pypi/packages/fe/c5/448f5757bfe8215ee570f490f4f600d4f92fdaf06690117eae369a5b3da0/PyQt5_sip-12.15.0-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:91b9538458a3a23e033c213bc879ce64f3d0a33d5a49cbd03e1e584efe307a35" }, + { url = "https://mirrors.aliyun.com/pypi/packages/13/ae/e48632f12f0186f9719b001e9fe0495233d8dfa807ecc9f4b54462cd76f5/PyQt5_sip-12.15.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:0c1c727ede7fdc464a1fe2e46109ba836509b2d7187a46fdeae443148ce51d1c" }, + { url = "https://mirrors.aliyun.com/pypi/packages/64/34/507fd1aedb0919137d9a3fd806462543a7697e877999efbbdcb890f41379/PyQt5_sip-12.15.0-cp38-cp38-win32.whl", hash = "sha256:dd241de9c569c07bbba62bff1049996e5b52478164f61f430073a87bf6d26d33" }, + { url = "https://mirrors.aliyun.com/pypi/packages/4f/fc/7d44e8f83eded93fa1517d8354529b7a21cae5d93c26e1681fd7e4bcbb2b/PyQt5_sip-12.15.0-cp38-cp38-win_amd64.whl", hash = "sha256:f600ae6f03e4bff91153c0dc7ebe52f90bd2b6afda58fd580e6990b3b951adc0" }, + { url = "https://mirrors.aliyun.com/pypi/packages/bc/76/302ace0f93ff919be5fcbc763372c3b07fdb06005becd2e53b3d425204e4/PyQt5_sip-12.15.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c0c543d604116af26694a8a5ba90f510551ff9124d503ae5ee14bb73a61363a3" }, + { url = "https://mirrors.aliyun.com/pypi/packages/1a/b6/85f21bc6d0edde6a64e29fd5e6493ab184cc8bad502b3394416db6fbd7ea/PyQt5_sip-12.15.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:97f2d6e8d9b7b3d3e795d576d7f56e6257f524221f6383b33ded7287763e9f06" }, + { url = "https://mirrors.aliyun.com/pypi/packages/d8/9f/c4bfa0dce78b15352bc750c3faef8bd884aadf66603eacaabfa7ef99d5b7/PyQt5_sip-12.15.0-cp39-cp39-win32.whl", hash = "sha256:ed5221c6241981bd98d39504823efb9cbe36841bf8917288f8fe8fc1d5569a41" }, + { url = "https://mirrors.aliyun.com/pypi/packages/bc/ff/239f3304db74fac086e9c1152256374a98ddab980e60e54b6f0df0ce79f4/PyQt5_sip-12.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:7f88c85702dce80ac2e1a162054f688ed394811d6dd03a5574b3fa8111b0a6db" }, +] + +[[package]] +name = "pyqt5-sip" +version = "12.17.1" +source = { registry = "https://mirrors.aliyun.com/pypi/simple" } +resolution-markers = [ + "python_full_version == '3.9.*'", +] +sdist = { url = "https://mirrors.aliyun.com/pypi/packages/ea/08/88a20c862f40b5c178c517cdc7e93767967dec5ac1b994e226d517991c9b/pyqt5_sip-12.17.1.tar.gz", hash = "sha256:0eab72bcb628f1926bf5b9ac51259d4fa18e8b2a81d199071135458f7d087ea8" } +wheels = [ + { url = "https://mirrors.aliyun.com/pypi/packages/8f/38/d03cef62cc03348249ce279c7e42159d1c902b1d550924403b1986a2b0f4/pyqt5_sip-12.17.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:bd4f73b1ebd5e0bd8d4539a8e55132318efc70a92f648ef0f9d93329ad50adeb" }, + { url = "https://mirrors.aliyun.com/pypi/packages/08/92/5aa38d8c17ee857fc3f7866dc84d4f4e7ab2180b5026e4f6ffd594ed2432/pyqt5_sip-12.17.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:b52e85520dbfe5c3d0c0c47aa2c10fc1853d892ae60ebebfe8154b052394da50" }, + { url = "https://mirrors.aliyun.com/pypi/packages/58/5c/0990f3a9a07346417a6728102cbe3d97b13786bce974b24a8d649a49db59/pyqt5_sip-12.17.1-cp310-cp310-win32.whl", hash = "sha256:71a67e2c9b77a74e943e220db0a341c702fd9bcf83c4a2e07342dfce691742ae" }, + { url = "https://mirrors.aliyun.com/pypi/packages/07/ad/f101338acf81cbd562362741aee9d0ee3c9242a6127c12ca698a15c851c6/pyqt5_sip-12.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:2710effb921bf6955b902779c763d890bb593da6325f0e128a0e3991cc855e9f" }, + { url = "https://mirrors.aliyun.com/pypi/packages/15/e4/451e465c75584a7cbd10e10404317b7443af83f56a64e02080b1f3cda5b5/pyqt5_sip-12.17.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5134d637efadd108a70306bab55b3d7feaa951bf6b8162161a67ae847bea9130" }, + { url = "https://mirrors.aliyun.com/pypi/packages/dc/b2/330f97434b21fbc99ab16f6ce71358ff5ea1bf1f09ed14dfe6b28b5ed8f5/pyqt5_sip-12.17.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:155cf755266c8bf64428916e2ff720d5efa1aec003d4ccc40c003b147dbdac03" }, + { url = "https://mirrors.aliyun.com/pypi/packages/3b/fd/53925099d0fc8aaf7adee613b6cebfb3fdfcd1238add64ff9edf6711e5f8/pyqt5_sip-12.17.1-cp311-cp311-win32.whl", hash = "sha256:9dfa7fe4ac93b60004430699c4bf56fef842a356d64dfea7cbc6d580d0427d6d" }, + { url = "https://mirrors.aliyun.com/pypi/packages/33/f8/f47a849c17676557c4220fbce9fcc24e15736af247c4dddcaf9ff0124b57/pyqt5_sip-12.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:2ddd214cf40119b86942a5da2da5a7345334955ab00026d8dcc56326b30e6d3c" }, + { url = "https://mirrors.aliyun.com/pypi/packages/a5/15/291f83f336558300626bebb0c403084ec171bbc8a70683e3376234422eb6/pyqt5_sip-12.17.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:c362606de782d2d46374a38523632786f145c517ee62de246a6069e5f2c5f336" }, + { url = "https://mirrors.aliyun.com/pypi/packages/45/85/ea1ae099260fd1859d71b31f51760b4226abfa778d5796b76d92c8fe6dcd/pyqt5_sip-12.17.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:140cc582151456103ebb149fefc678f3cae803e7720733db51212af5219cd45c" }, + { url = "https://mirrors.aliyun.com/pypi/packages/b4/b3/d5b50c721651a0f2ccbef6f8db3dabf3db296b9ec239ba007f5615f57dd7/pyqt5_sip-12.17.1-cp312-cp312-win32.whl", hash = "sha256:9dc1f1525d4d42c080f6cfdfc70d78239f8f67b0a48ea0745497251d8d848b1d" }, + { url = "https://mirrors.aliyun.com/pypi/packages/14/b6/474d8b17763683ab45fb364f3a44f25fdc25d97b47b29ad8819b95a15ac8/pyqt5_sip-12.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:d5e2e9e175559017cd161d661e0ee0b551684f824bb90800c5a8c8a3bea9355e" }, + { url = "https://mirrors.aliyun.com/pypi/packages/1d/58/9ecb688050e79ffe7bbd9fc917aa13f63856a5081ac46bbce87bb11ab971/pyqt5_sip-12.17.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:9ebbd7769ccdaaa6295e9c872553b6cde17f38e171056f17300d8af9a14d1fc8" }, + { url = "https://mirrors.aliyun.com/pypi/packages/b1/9f/ae691360a9f18e3e06fd297e854d7ad175367e35ea184fd2fcf6c79b8c25/pyqt5_sip-12.17.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:b023da906a70af2cf5e6fc1932f441ede07530f3e164dd52c6c2bb5ab7c6f424" }, + { url = "https://mirrors.aliyun.com/pypi/packages/d7/31/491c45423174a359a4b8a8d84a7b541c453f48497ae928cbe4006bcd3e01/pyqt5_sip-12.17.1-cp313-cp313-win32.whl", hash = "sha256:36dbef482bd638786b909f3bda65b7b3d5cbd6cbf16797496de38bae542da307" }, + { url = "https://mirrors.aliyun.com/pypi/packages/64/61/e28681dd5200094f7b2e6671e85c02a4d6693da36d23ad7d39ffbc70b15c/pyqt5_sip-12.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:d04e5551bbc3bcec98acc63b3b0618ddcbf31ff107349225b516fe7e7c0a7c8b" }, + { url = "https://mirrors.aliyun.com/pypi/packages/71/f9/06c09dc94474ffe3f518f80e47fc69d34abf8e4a971ae7e7c667d6ff30a7/pyqt5_sip-12.17.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:c49918287e1ad77956d1589f1d3d432a0be7630c646ea02cf652413a48e14458" }, + { url = "https://mirrors.aliyun.com/pypi/packages/40/ae/be6e338ea427deac5cd81a93f51ae3fb6505d99d6d5e5d5341bcc099327e/pyqt5_sip-12.17.1-cp314-cp314-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:944a4bf1e1ee18ad03a54964c1c6433fb6de582313a1f0b17673e7203e22fc83" }, + { url = "https://mirrors.aliyun.com/pypi/packages/fc/a3/8b758518bd0dd5d1581f7a6d522c9b4d9b58d05087b1d0b4dfaad5376434/pyqt5_sip-12.17.1-cp314-cp314-win32.whl", hash = "sha256:99a2935fd662a67748625b1e6ffa0a2d1f2da068b9df6db04fa59a4a5d4ee613" }, + { url = "https://mirrors.aliyun.com/pypi/packages/40/8c/e96f9877548810b1e537f46fc21ba74552dd4e8c498658114a8353bdf659/pyqt5_sip-12.17.1-cp314-cp314-win_amd64.whl", hash = "sha256:aaa33232cc80793d14fdb3b149b27eec0855612ed66aad480add5ac49b9cee63" }, + { url = "https://mirrors.aliyun.com/pypi/packages/1d/fd/097af91c0446c4877b2614f3e7e40729c7d0a276c401cef3ff95850cd236/pyqt5_sip-12.17.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6fdc457bd528e5909a5893db0a7dee0066d5f22e08234c9152db0ae6df9a367f" }, + { url = "https://mirrors.aliyun.com/pypi/packages/2c/cf/58143e15d0bfa1d1450071ad9a2d71adca82ebefbd7729d0c543463d4d31/pyqt5_sip-12.17.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:06ea59741c1bffb198d99b00d26594791f45fb11b10f774c8105aea5962e3835" }, + { url = "https://mirrors.aliyun.com/pypi/packages/e6/9b/8e8f1af1b500f0d4fcd48c9f7ee474731db8b046d3629151e382634eaf59/pyqt5_sip-12.17.1-cp39-cp39-win32.whl", hash = "sha256:b9ef23869d35c6740a95fcb1f387f4aea8d8fac80e19096fbaf1a64e18409c4b" }, + { url = "https://mirrors.aliyun.com/pypi/packages/64/1e/08bd86000c8294772c6c4aaaf53babd69b9b37e80d1c87583c1fe8eeab5b/pyqt5_sip-12.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:90eed15f19557dfab22e68c7763e3690053cc8dd30d93ade2523d1b5a04a87be" }, +] + +[[package]] +name = "pyqt5-sip" +version = "12.17.2" +source = { registry = "https://mirrors.aliyun.com/pypi/simple" } +resolution-markers = [ + "python_full_version >= '3.10'", +] +sdist = { url = "https://mirrors.aliyun.com/pypi/packages/1e/4a/195cf4d2a7e1ff480b4cabcd51aa5c0068c03a19a97282317536e4a82e1e/pyqt5_sip-12.17.2.tar.gz", hash = "sha256:7f66565c2a13d34d8ad6aad08e953d355ea3fe466d991d51aa5a0966a5289f05" } +wheels = [ + { url = "https://mirrors.aliyun.com/pypi/packages/44/16/96faed1e31658d27979f36f9a56642c6a348ff44a9a35ccbb267c9b66ab3/pyqt5_sip-12.17.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:43c2bc7e7d19eb67998374c49adbaa8072d4261a286bdf64d08382bacae84fb7" }, + { url = "https://mirrors.aliyun.com/pypi/packages/11/81/4237700a1154e908c9c5d3be332bf8c58e6a31ed773bccd42ce4248ee297/pyqt5_sip-12.17.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:dda1e7e6840935f17fbeb445ec5da63b9b8e7f673317019397611230faeb81a6" }, + { url = "https://mirrors.aliyun.com/pypi/packages/be/e3/2bce195fb0229d7d2d6b009c44638ec02f06b7a14e912d053f3d80aa658a/pyqt5_sip-12.17.2-cp310-cp310-win32.whl", hash = "sha256:2dca03cd1d6c2c843e5de4d0a7b33a7812ed37d576ea65249f1a97c17d9f988b" }, + { url = "https://mirrors.aliyun.com/pypi/packages/80/20/d3baa26aebe4c33f314f7ae4565b4cf922d1d68f98f4919a0e0ad50653e7/pyqt5_sip-12.17.2-cp310-cp310-win_amd64.whl", hash = "sha256:0005227f10a6221d68f764e24181fe15b770da364fd3a67529ac13f589523991" }, + { url = "https://mirrors.aliyun.com/pypi/packages/47/57/acd812ddfdde9991f4cfe2a738e3646ab66ad2561c3dc0ba8e7541883aff/pyqt5_sip-12.17.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a6ce4b763f17ac89ef44716dbfa77ed93677ac502aa402989989508715185e74" }, + { url = "https://mirrors.aliyun.com/pypi/packages/c2/2e/2ff71739ee601347f7b6f6bd3265a259f39d145dfa474c44372d369b06ec/pyqt5_sip-12.17.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:cf8e8a88a3c031dd35bb19c4d7d9a3d65cca84719bed1bc5dd7e2aaf0cf517d2" }, + { url = "https://mirrors.aliyun.com/pypi/packages/9f/bf/8bef9051e49178e18a0c345de95a982c7a4f3779208ab793381d613ea435/pyqt5_sip-12.17.2-cp311-cp311-win32.whl", hash = "sha256:291d0e2aeddd18081533804150cc59e183b3ab6b4da2b2cf701fdf3ea41ffdda" }, + { url = "https://mirrors.aliyun.com/pypi/packages/54/d1/377bdc729877f12bdf3841716a4e620aa51b50a0cddcfa8aeecc3a152c9b/pyqt5_sip-12.17.2-cp311-cp311-win_amd64.whl", hash = "sha256:d53bea28b881cd9a4536c27c0658ae182bfb514dc1ff9235d16d10288010fc59" }, + { url = "https://mirrors.aliyun.com/pypi/packages/4b/3e/f5c7bc43668147ddc00a1a579f22639dffdbfb9470ce3a5bc1cf27e0d541/pyqt5_sip-12.17.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0bd1a8e59124a90a05f078bceeb9d4d93c3986c349030487c202fffde6612969" }, + { url = "https://mirrors.aliyun.com/pypi/packages/b9/41/63f81a53704425092558f1ec17adbed11787f4322e60a849e0539516b3aa/pyqt5_sip-12.17.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:55ff374feb4bad783241649c7b946e05d7e83d60b0755526ed8fb25bf54e3408" }, + { url = "https://mirrors.aliyun.com/pypi/packages/b5/cd/2b749a174e61394085d61cafb7dc3c11ddf40307edfb2d71cb9b71b7f320/pyqt5_sip-12.17.2-cp312-cp312-win32.whl", hash = "sha256:45dc6e2121d175fdab1431c448fd3e88c97caf873a33cb65efa2e9ad0056337b" }, + { url = "https://mirrors.aliyun.com/pypi/packages/73/ac/7f6d6a6a4505b251f1174092f09d5611c2ed66602c40d3411d93a1d2a95f/pyqt5_sip-12.17.2-cp312-cp312-win_amd64.whl", hash = "sha256:e3bb16e43afd68dd013228075876cf8f8b1a7d86ba67767dd2c6a97be677c18d" }, + { url = "https://mirrors.aliyun.com/pypi/packages/38/b1/78432c271b2a5477f5fe1ad9eb69cdc482430230b8d552cf5cee393d7862/pyqt5_sip-12.17.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:cfeee3c27f28c091d6a46f8befe9afcfafc76846846bedf1112d403a7299e864" }, + { url = "https://mirrors.aliyun.com/pypi/packages/e8/d9/6451973300f7dffe70476cad7fc4a59ffe08417ee4add6afb3288c91bd85/pyqt5_sip-12.17.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:b5df33e198d5d7cccc8e081f80eb97b8d70100f887362074a029a6c19cb92c8b" }, + { url = "https://mirrors.aliyun.com/pypi/packages/c6/1e/241d9ddef5cb1bb3e3b5839b6f8c05ae727e196be82b4646ea4ef9475ef7/pyqt5_sip-12.17.2-cp313-cp313-win32.whl", hash = "sha256:2c0a278b8fc289d34d4e62bbb9ef6da96b45cc9ab3f6886397b1490d2b4a5604" }, + { url = "https://mirrors.aliyun.com/pypi/packages/fd/33/a393163b6299a7e0743fad86fbcb06cf219878fbdd629ee6cb46d2a4d9f7/pyqt5_sip-12.17.2-cp313-cp313-win_amd64.whl", hash = "sha256:7e0d663b583a4d3ac63c9fbade2228de6ee628b44a025f5fd964b97dbbcbebc9" }, + { url = "https://mirrors.aliyun.com/pypi/packages/58/29/b4943def737d3f8876bfd4f9af1909892ae1998099695b3e81870c39aaa7/pyqt5_sip-12.17.2-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:6f03c25a18294f2d66befc4f2adf3f35fceba877b937dc8a94783fa7da8b7345" }, + { url = "https://mirrors.aliyun.com/pypi/packages/18/62/e7ac79bb080d4e5a7d7fea50ca7d9231a7ded07e01f24d4e123f089e1630/pyqt5_sip-12.17.2-cp314-cp314-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a6d716801d512643b7b1f50dfbdcd16408fe9a6df907d8627b4ad82190604bec" }, + { url = "https://mirrors.aliyun.com/pypi/packages/92/11/b63ee88ffc2e04af90ced17dbe0d774f5f4e51122c13f8118e565707954e/pyqt5_sip-12.17.2-cp314-cp314-win32.whl", hash = "sha256:c617c29524fdcf826e619d77ffd0d6142622f8422adc2608ecc89edd3e605339" }, + { url = "https://mirrors.aliyun.com/pypi/packages/d0/70/efe47083dea494613fc41da55f25c07b4e73bb90c98dee8fe87afbfbc303/pyqt5_sip-12.17.2-cp314-cp314-win_amd64.whl", hash = "sha256:b008755d2222a064ec90c525fce5df3fe9d410371e47c43a21c049e07683b7fb" }, +] + +[[package]] +name = "pyqt5-tools" +version = "5.15.9.3.3" +source = { registry = "https://mirrors.aliyun.com/pypi/simple" } +dependencies = [ + { name = "click", version = "8.1.8", source = { registry = "https://mirrors.aliyun.com/pypi/simple" }, marker = "python_full_version < '3.10'" }, + { name = "click", version = "8.3.1", source = { registry = "https://mirrors.aliyun.com/pypi/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "pyqt5" }, + { name = "pyqt5-plugins" }, + { name = "python-dotenv", version = "1.0.1", source = { registry = "https://mirrors.aliyun.com/pypi/simple" }, marker = "python_full_version < '3.9'" }, + { name = "python-dotenv", version = "1.2.1", source = { registry = "https://mirrors.aliyun.com/pypi/simple" }, marker = "python_full_version >= '3.9'" }, +] +wheels = [ + { url = "https://mirrors.aliyun.com/pypi/packages/11/7e/3a5bce0e31650e091a16826d7a588be8bd56c2ac30871286b6c90d68ceeb/pyqt5_tools-5.15.9.3.3-py3-none-any.whl", hash = "sha256:4b45b26111c583a34fa364b98d7120f5aeca4f96ac72e251f1b37a9cca809f86" }, +] + +[[package]] +name = "python-docx" +version = "1.1.2" +source = { registry = "https://mirrors.aliyun.com/pypi/simple" } +resolution-markers = [ + "python_full_version < '3.9'", +] +dependencies = [ + { name = "lxml", marker = "python_full_version < '3.9'" }, + { name = "typing-extensions", version = "4.13.2", source = { registry = "https://mirrors.aliyun.com/pypi/simple" }, marker = "python_full_version < '3.9'" }, +] +sdist = { url = "https://mirrors.aliyun.com/pypi/packages/35/e4/386c514c53684772885009c12b67a7edd526c15157778ac1b138bc75063e/python_docx-1.1.2.tar.gz", hash = "sha256:0cf1f22e95b9002addca7948e16f2cd7acdfd498047f1941ca5d293db7762efd" } +wheels = [ + { url = "https://mirrors.aliyun.com/pypi/packages/3e/3d/330d9efbdb816d3f60bf2ad92f05e1708e4a1b9abe80461ac3444c83f749/python_docx-1.1.2-py3-none-any.whl", hash = "sha256:08c20d6058916fb19853fcf080f7f42b6270d89eac9fa5f8c15f691c0017fabe" }, +] + +[[package]] +name = "python-docx" +version = "1.2.0" +source = { registry = "https://mirrors.aliyun.com/pypi/simple" } +resolution-markers = [ + "python_full_version >= '3.10'", + "python_full_version == '3.9.*'", +] +dependencies = [ + { name = "lxml", marker = "python_full_version >= '3.9'" }, + { name = "typing-extensions", version = "4.15.0", source = { registry = "https://mirrors.aliyun.com/pypi/simple" }, marker = "python_full_version >= '3.9'" }, +] +sdist = { url = "https://mirrors.aliyun.com/pypi/packages/a9/f7/eddfe33871520adab45aaa1a71f0402a2252050c14c7e3009446c8f4701c/python_docx-1.2.0.tar.gz", hash = "sha256:7bc9d7b7d8a69c9c02ca09216118c86552704edc23bac179283f2e38f86220ce" } +wheels = [ + { url = "https://mirrors.aliyun.com/pypi/packages/d0/00/1e03a4989fa5795da308cd774f05b704ace555a70f9bf9d3be057b680bcf/python_docx-1.2.0-py3-none-any.whl", hash = "sha256:3fd478f3250fbbbfd3b94fe1e985955737c145627498896a8a6bf81f4baf66c7" }, +] + +[[package]] +name = "python-dotenv" +version = "1.0.1" +source = { registry = "https://mirrors.aliyun.com/pypi/simple" } +resolution-markers = [ + "python_full_version < '3.9'", +] +sdist = { url = "https://mirrors.aliyun.com/pypi/packages/bc/57/e84d88dfe0aec03b7a2d4327012c1627ab5f03652216c63d49846d7a6c58/python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca" } +wheels = [ + { url = "https://mirrors.aliyun.com/pypi/packages/6a/3e/b68c118422ec867fa7ab88444e1274aa40681c606d59ac27de5a5588f082/python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a" }, +] + +[[package]] +name = "python-dotenv" +version = "1.2.1" +source = { registry = "https://mirrors.aliyun.com/pypi/simple" } +resolution-markers = [ + "python_full_version >= '3.10'", + "python_full_version == '3.9.*'", +] +sdist = { url = "https://mirrors.aliyun.com/pypi/packages/f0/26/19cadc79a718c5edbec86fd4919a6b6d3f681039a2f6d66d14be94e75fb9/python_dotenv-1.2.1.tar.gz", hash = "sha256:42667e897e16ab0d66954af0e60a9caa94f0fd4ecf3aaf6d2d260eec1aa36ad6" } +wheels = [ + { url = "https://mirrors.aliyun.com/pypi/packages/14/1b/a298b06749107c305e1fe0f814c6c74aea7b2f1e10989cb30f544a1b3253/python_dotenv-1.2.1-py3-none-any.whl", hash = "sha256:b81ee9561e9ca4004139c6cbba3a238c32b03e4894671e181b671e8cb8425d61" }, +] + +[[package]] +name = "pytz" +version = "2025.2" +source = { registry = "https://mirrors.aliyun.com/pypi/simple" } +sdist = { url = "https://mirrors.aliyun.com/pypi/packages/f8/bf/abbd3cdfb8fbc7fb3d4d38d320f2441b1e7cbe29be4f23797b4a2b5d8aac/pytz-2025.2.tar.gz", hash = "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3" } +wheels = [ + { url = "https://mirrors.aliyun.com/pypi/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00" }, +] + +[[package]] +name = "pywin32" +version = "311" +source = { registry = "https://mirrors.aliyun.com/pypi/simple" } +wheels = [ + { url = "https://mirrors.aliyun.com/pypi/packages/7b/40/44efbb0dfbd33aca6a6483191dae0716070ed99e2ecb0c53683f400a0b4f/pywin32-311-cp310-cp310-win32.whl", hash = "sha256:d03ff496d2a0cd4a5893504789d4a15399133fe82517455e78bad62efbb7f0a3" }, + { url = "https://mirrors.aliyun.com/pypi/packages/5e/bf/360243b1e953bd254a82f12653974be395ba880e7ec23e3731d9f73921cc/pywin32-311-cp310-cp310-win_amd64.whl", hash = "sha256:797c2772017851984b97180b0bebe4b620bb86328e8a884bb626156295a63b3b" }, + { url = "https://mirrors.aliyun.com/pypi/packages/57/38/d290720e6f138086fb3d5ffe0b6caa019a791dd57866940c82e4eeaf2012/pywin32-311-cp310-cp310-win_arm64.whl", hash = "sha256:0502d1facf1fed4839a9a51ccbcc63d952cf318f78ffc00a7e78528ac27d7a2b" }, + { url = "https://mirrors.aliyun.com/pypi/packages/7c/af/449a6a91e5d6db51420875c54f6aff7c97a86a3b13a0b4f1a5c13b988de3/pywin32-311-cp311-cp311-win32.whl", hash = "sha256:184eb5e436dea364dcd3d2316d577d625c0351bf237c4e9a5fabbcfa5a58b151" }, + { url = "https://mirrors.aliyun.com/pypi/packages/51/8f/9bb81dd5bb77d22243d33c8397f09377056d5c687aa6d4042bea7fbf8364/pywin32-311-cp311-cp311-win_amd64.whl", hash = "sha256:3ce80b34b22b17ccbd937a6e78e7225d80c52f5ab9940fe0506a1a16f3dab503" }, + { url = "https://mirrors.aliyun.com/pypi/packages/44/7b/9c2ab54f74a138c491aba1b1cd0795ba61f144c711daea84a88b63dc0f6c/pywin32-311-cp311-cp311-win_arm64.whl", hash = "sha256:a733f1388e1a842abb67ffa8e7aad0e70ac519e09b0f6a784e65a136ec7cefd2" }, + { url = "https://mirrors.aliyun.com/pypi/packages/e7/ab/01ea1943d4eba0f850c3c61e78e8dd59757ff815ff3ccd0a84de5f541f42/pywin32-311-cp312-cp312-win32.whl", hash = "sha256:750ec6e621af2b948540032557b10a2d43b0cee2ae9758c54154d711cc852d31" }, + { url = "https://mirrors.aliyun.com/pypi/packages/d1/a8/a0e8d07d4d051ec7502cd58b291ec98dcc0c3fff027caad0470b72cfcc2f/pywin32-311-cp312-cp312-win_amd64.whl", hash = "sha256:b8c095edad5c211ff31c05223658e71bf7116daa0ecf3ad85f3201ea3190d067" }, + { url = "https://mirrors.aliyun.com/pypi/packages/ba/3a/2ae996277b4b50f17d61f0603efd8253cb2d79cc7ae159468007b586396d/pywin32-311-cp312-cp312-win_arm64.whl", hash = "sha256:e286f46a9a39c4a18b319c28f59b61de793654af2f395c102b4f819e584b5852" }, + { url = "https://mirrors.aliyun.com/pypi/packages/a5/be/3fd5de0979fcb3994bfee0d65ed8ca9506a8a1260651b86174f6a86f52b3/pywin32-311-cp313-cp313-win32.whl", hash = "sha256:f95ba5a847cba10dd8c4d8fefa9f2a6cf283b8b88ed6178fa8a6c1ab16054d0d" }, + { url = "https://mirrors.aliyun.com/pypi/packages/e3/28/e0a1909523c6890208295a29e05c2adb2126364e289826c0a8bc7297bd5c/pywin32-311-cp313-cp313-win_amd64.whl", hash = "sha256:718a38f7e5b058e76aee1c56ddd06908116d35147e133427e59a3983f703a20d" }, + { url = "https://mirrors.aliyun.com/pypi/packages/04/bf/90339ac0f55726dce7d794e6d79a18a91265bdf3aa70b6b9ca52f35e022a/pywin32-311-cp313-cp313-win_arm64.whl", hash = "sha256:7b4075d959648406202d92a2310cb990fea19b535c7f4a78d3f5e10b926eeb8a" }, + { url = "https://mirrors.aliyun.com/pypi/packages/c9/31/097f2e132c4f16d99a22bfb777e0fd88bd8e1c634304e102f313af69ace5/pywin32-311-cp314-cp314-win32.whl", hash = "sha256:b7a2c10b93f8986666d0c803ee19b5990885872a7de910fc460f9b0c2fbf92ee" }, + { url = "https://mirrors.aliyun.com/pypi/packages/90/4b/07c77d8ba0e01349358082713400435347df8426208171ce297da32c313d/pywin32-311-cp314-cp314-win_amd64.whl", hash = "sha256:3aca44c046bd2ed8c90de9cb8427f581c479e594e99b5c0bb19b29c10fd6cb87" }, + { url = "https://mirrors.aliyun.com/pypi/packages/c0/d2/21af5c535501a7233e734b8af901574572da66fcc254cb35d0609c9080dd/pywin32-311-cp314-cp314-win_arm64.whl", hash = "sha256:a508e2d9025764a8270f93111a970e1d0fbfc33f4153b388bb649b7eec4f9b42" }, + { url = "https://mirrors.aliyun.com/pypi/packages/75/20/6cd04d636a4c83458ecbb7c8220c13786a1a80d3f5fb568df39310e73e98/pywin32-311-cp38-cp38-win32.whl", hash = "sha256:6c6f2969607b5023b0d9ce2541f8d2cbb01c4f46bc87456017cf63b73f1e2d8c" }, + { url = "https://mirrors.aliyun.com/pypi/packages/ff/6c/94c10268bae5d0d0c6509bdfb5aa08882d11a9ccdf89ff1cde59a6161afb/pywin32-311-cp38-cp38-win_amd64.whl", hash = "sha256:c8015b09fb9a5e188f83b7b04de91ddca4658cee2ae6f3bc483f0b21a77ef6cd" }, + { url = "https://mirrors.aliyun.com/pypi/packages/59/42/b86689aac0cdaee7ae1c58d464b0ff04ca909c19bb6502d4973cdd9f9544/pywin32-311-cp39-cp39-win32.whl", hash = "sha256:aba8f82d551a942cb20d4a83413ccbac30790b50efb89a75e4f586ac0bb8056b" }, + { url = "https://mirrors.aliyun.com/pypi/packages/9f/8a/1403d0353f8c5a2f0829d2b1c4becbf9da2f0a4d040886404fc4a5431e4d/pywin32-311-cp39-cp39-win_amd64.whl", hash = "sha256:e0c4cfb0621281fe40387df582097fd796e80430597cb9944f0ae70447bacd91" }, + { url = "https://mirrors.aliyun.com/pypi/packages/60/22/e0e8d802f124772cec9c75430b01a212f86f9de7546bda715e54140d5aeb/pywin32-311-cp39-cp39-win_arm64.whl", hash = "sha256:62ea666235135fee79bb154e695f3ff67370afefd71bd7fea7512fc70ef31e3d" }, +] + +[[package]] +name = "qt5-applications" +version = "5.15.2.2.3" +source = { registry = "https://mirrors.aliyun.com/pypi/simple" } +wheels = [ + { url = "https://mirrors.aliyun.com/pypi/packages/14/32/a2fcd818fe62dfcd24600782c7b71bc7c476406bbb4c5680a992fcb7b9d9/qt5_applications-5.15.2.2.3-py3-none-macosx_10_14_x86_64.whl", hash = "sha256:45395074b742ca6765990d3645d5e24a59415c1d968c40c6a3443da22c621ba8" }, + { url = "https://mirrors.aliyun.com/pypi/packages/35/e3/f5ab9980d601e62a75bb4d5d01d2324cb0d2a414f36474e26a83de409548/qt5_applications-5.15.2.2.3-py3-none-manylinux_2_17_x86_64.whl", hash = "sha256:9ac537caf18fc339149391f58e6716c472296df4431d68e76670e75a14238de0" }, + { url = "https://mirrors.aliyun.com/pypi/packages/96/32/5f6b843992c28efde2c3dadbe67296064d09c506c2fc9f9ebe76090eb00a/qt5_applications-5.15.2.2.3-py3-none-win32.whl", hash = "sha256:8d4ebdd955653f693edac4697f80e016270efcf861ebb1b8b7e238fd6faba5f5" }, + { url = "https://mirrors.aliyun.com/pypi/packages/ae/a9/cd64cda6f58321c4a0021ced80117b225562efc42f1318ff2cea69c23eb7/qt5_applications-5.15.2.2.3-py3-none-win_amd64.whl", hash = "sha256:5156cc710ed3942f736ec2c46889f73d829fcd4093bed8dbddf2fd83929fdf0b" }, +] + +[[package]] +name = "qt5-tools" +version = "5.15.2.1.3" +source = { registry = "https://mirrors.aliyun.com/pypi/simple" } +dependencies = [ + { name = "click", version = "8.1.8", source = { registry = "https://mirrors.aliyun.com/pypi/simple" }, marker = "python_full_version < '3.10'" }, + { name = "click", version = "8.3.1", source = { registry = "https://mirrors.aliyun.com/pypi/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "qt5-applications" }, +] +wheels = [ + { url = "https://mirrors.aliyun.com/pypi/packages/e2/45/3062d0df2bbc88ee4ea04b1073072b337b9e287c0b4ac12109729b413e2e/qt5_tools-5.15.2.1.3-py3-none-any.whl", hash = "sha256:3e73b7aa3cd03abba6e703aa1d21a5934eff42a068292500a1f02c9bc6da95cb" }, +] + +[[package]] +name = "qtmodern" +version = "0.2.0" +source = { registry = "https://mirrors.aliyun.com/pypi/simple" } +dependencies = [ + { name = "qtpy" }, +] +sdist = { url = "https://mirrors.aliyun.com/pypi/packages/e3/17/bc8a3882571e852e96d79b8c5a6989f72e2b7eda22998cd6018bfc5644fb/qtmodern-0.2.0.tar.gz", hash = "sha256:d433a54fbb400d49790aff65d35f203de2a8cc67795ac5bb04c5e766433fafae" } +wheels = [ + { url = "https://mirrors.aliyun.com/pypi/packages/0a/24/499704896d57752a1d4b724f011f56a33bc163e96a77e572b81f2e5b0189/qtmodern-0.2.0-py3-none-any.whl", hash = "sha256:57e62617656494a9d8a27ac3bd51ae3ae61a265f43b92d6f6ea59dc8bed2179d" }, +] + +[[package]] +name = "qtpy" +version = "2.4.3" +source = { registry = "https://mirrors.aliyun.com/pypi/simple" } +dependencies = [ + { name = "packaging" }, +] +sdist = { url = "https://mirrors.aliyun.com/pypi/packages/70/01/392eba83c8e47b946b929d7c46e0f04b35e9671f8bb6fc36b6f7945b4de8/qtpy-2.4.3.tar.gz", hash = "sha256:db744f7832e6d3da90568ba6ccbca3ee2b3b4a890c3d6fbbc63142f6e4cdf5bb" } +wheels = [ + { url = "https://mirrors.aliyun.com/pypi/packages/69/76/37c0ccd5ab968a6a438f9c623aeecc84c202ab2fabc6a8fd927580c15b5a/QtPy-2.4.3-py3-none-any.whl", hash = "sha256:72095afe13673e017946cc258b8d5da43314197b741ed2890e563cf384b51aa1" }, +] + +[[package]] +name = "setuptools" +version = "75.3.2" +source = { registry = "https://mirrors.aliyun.com/pypi/simple" } +resolution-markers = [ + "python_full_version < '3.9'", +] +sdist = { url = "https://mirrors.aliyun.com/pypi/packages/5c/01/771ea46cce201dd42cff043a5eea929d1c030fb3d1c2ee2729d02ca7814c/setuptools-75.3.2.tar.gz", hash = "sha256:3c1383e1038b68556a382c1e8ded8887cd20141b0eb5708a6c8d277de49364f5" } +wheels = [ + { url = "https://mirrors.aliyun.com/pypi/packages/15/65/3f0dba35760d902849d39d38c0a72767794b1963227b69a587f8a336d08c/setuptools-75.3.2-py3-none-any.whl", hash = "sha256:90ab613b6583fc02d5369cbca13ea26ea0e182d1df2d943ee9cbe81d4c61add9" }, +] + +[[package]] +name = "setuptools" +version = "80.9.0" +source = { registry = "https://mirrors.aliyun.com/pypi/simple" } +resolution-markers = [ + "python_full_version >= '3.10'", + "python_full_version == '3.9.*'", +] +sdist = { url = "https://mirrors.aliyun.com/pypi/packages/18/5d/3bf57dcd21979b887f014ea83c24ae194cfcd12b9e0fda66b957c69d1fca/setuptools-80.9.0.tar.gz", hash = "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c" } +wheels = [ + { url = "https://mirrors.aliyun.com/pypi/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl", hash = "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922" }, +] + +[[package]] +name = "six" +version = "1.17.0" +source = { registry = "https://mirrors.aliyun.com/pypi/simple" } +sdist = { url = "https://mirrors.aliyun.com/pypi/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81" } +wheels = [ + { url = "https://mirrors.aliyun.com/pypi/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274" }, +] + +[[package]] +name = "typing-extensions" +version = "4.13.2" +source = { registry = "https://mirrors.aliyun.com/pypi/simple" } +resolution-markers = [ + "python_full_version < '3.9'", +] +sdist = { url = "https://mirrors.aliyun.com/pypi/packages/f6/37/23083fcd6e35492953e8d2aaaa68b860eb422b34627b13f2ce3eb6106061/typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef" } +wheels = [ + { url = "https://mirrors.aliyun.com/pypi/packages/8b/54/b1ae86c0973cc6f0210b53d508ca3641fb6d0c56823f288d108bc7ab3cc8/typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c" }, +] + +[[package]] +name = "typing-extensions" +version = "4.15.0" +source = { registry = "https://mirrors.aliyun.com/pypi/simple" } +resolution-markers = [ + "python_full_version >= '3.10'", + "python_full_version == '3.9.*'", +] +sdist = { url = "https://mirrors.aliyun.com/pypi/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466" } +wheels = [ + { url = "https://mirrors.aliyun.com/pypi/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548" }, +] diff --git a/zhuan.py b/zhuan.py new file mode 100644 index 0000000..ab9714b --- /dev/null +++ b/zhuan.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'zhuan.ui' +# +# Created by: PyQt5 UI code generator 5.15.4 +# +# WARNING: Any manual changes made to this file will be lost when pyuic5 is +# run again. Do not edit this file unless you know what you are doing. + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_Dialog(object): + def setupUi(self, Dialog): + Dialog.setObjectName("Dialog") + Dialog.resize(461, 70) + self.widget = QtWidgets.QWidget(Dialog) + self.widget.setGeometry(QtCore.QRect(10, 35, 446, 23)) + self.widget.setObjectName("widget") + self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.widget) + self.horizontalLayout_3.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout_3.setObjectName("horizontalLayout_3") + self.horizontalLayout = QtWidgets.QHBoxLayout() + self.horizontalLayout.setObjectName("horizontalLayout") + self.label = QtWidgets.QLabel(self.widget) + self.label.setObjectName("label") + self.horizontalLayout.addWidget(self.label) + self.lineEdit = QtWidgets.QLineEdit(self.widget) + self.lineEdit.setObjectName("lineEdit") + self.horizontalLayout.addWidget(self.lineEdit) + self.horizontalLayout_3.addLayout(self.horizontalLayout) + self.horizontalLayout_2 = QtWidgets.QHBoxLayout() + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.label_2 = QtWidgets.QLabel(self.widget) + self.label_2.setObjectName("label_2") + self.horizontalLayout_2.addWidget(self.label_2) + self.lineEdit_2 = QtWidgets.QLineEdit(self.widget) + self.lineEdit_2.setObjectName("lineEdit_2") + self.horizontalLayout_2.addWidget(self.lineEdit_2) + self.horizontalLayout_3.addLayout(self.horizontalLayout_2) + self.widget1 = QtWidgets.QWidget(Dialog) + self.widget1.setGeometry(QtCore.QRect(10, 10, 216, 18)) + self.widget1.setObjectName("widget1") + self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.widget1) + self.horizontalLayout_4.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout_4.setObjectName("horizontalLayout_4") + self.radioButton = QtWidgets.QRadioButton(self.widget1) + self.radioButton.setChecked(True) + self.radioButton.setObjectName("radioButton") + self.horizontalLayout_4.addWidget(self.radioButton) + self.radioButton_2 = QtWidgets.QRadioButton(self.widget1) + self.radioButton_2.setObjectName("radioButton_2") + self.horizontalLayout_4.addWidget(self.radioButton_2) + + self.retranslateUi(Dialog) + QtCore.QMetaObject.connectSlotsByName(Dialog) + + def retranslateUi(self, Dialog): + _translate = QtCore.QCoreApplication.translate + Dialog.setWindowTitle(_translate("Dialog", "IEEE754转换工具")) + self.label.setText(_translate("Dialog", "16进制表示")) + self.label_2.setText(_translate("Dialog", "float值")) + self.radioButton.setText(_translate("Dialog", "单精度(32位)")) + self.radioButton_2.setText(_translate("Dialog", "双精度(64位)")) diff --git a/zhuan.ui b/zhuan.ui new file mode 100644 index 0000000..230039e --- /dev/null +++ b/zhuan.ui @@ -0,0 +1,88 @@ + + + Dialog + + + + 0 + 0 + 461 + 84 + + + + IEEE754转换工具 + + + + + 10 + 35 + 446 + 23 + + + + + + + + + 16进制表示 + + + + + + + + + + + + + + float值 + + + + + + + + + + + + + + 10 + 10 + 216 + 18 + + + + + + + 单精度(32位) + + + true + + + + + + + 双精度(64位) + + + + + + + + + diff --git a/提交github的shell.py b/提交github的shell.py new file mode 100644 index 0000000..97534aa --- /dev/null +++ b/提交github的shell.py @@ -0,0 +1,7 @@ +#os.system(command) +import os,time +comment = input('请输入提交的标记名称:') +os.system("git add .") +os.system(f"git commit -m {comment}") +os.system("git push origin main --force") +os.system("pause") \ No newline at end of file diff --git a/版本记录.md b/版本记录.md new file mode 100644 index 0000000..b2fce45 --- /dev/null +++ b/版本记录.md @@ -0,0 +1,11 @@ +Ŀǰ汾V0.12 +Ŀǰ汾V0.13 -UIļĵֲԪתתIEEE754 +Ŀǰ汾V0.14 -޸ļʶ +Ŀǰ汾V0.14 - 3 -汾һҪ +Ŀǰ汾V0.15 +Ŀǰ汾V0.16 +Ŀǰ汾V0.17-fpgaĵ +Ŀǰ汾V0.18-fpga¼ת˵⣡ +Ŀǰ汾V0.19 - ޸ķɼ¼ƥʶ/ϰ汾CPU¼->˵Ϊ°汾 +Ŀǰ汾V0.19.1 - ŻCPU¼TO˵ + diff --git a/生成的说明文档.docx b/生成的说明文档.docx new file mode 100644 index 0000000..25f77b3 Binary files /dev/null and b/生成的说明文档.docx differ