diff --git a/main.py b/main.py index 2abd127..a092ced 100644 --- a/main.py +++ b/main.py @@ -1,25 +1,19 @@ -"""main.py - MIL SDK 测试示例""" -from pathlib import Path - -from src.core import ( - setup_logging, - read_excel_data, - read_excel_case, - create_excel_case, - update_case_excel, -) +from main_ui import Ui_MainWindow +from PySide6.QtWidgets import QApplication, QMainWindow +import sys +from qt_material import apply_stylesheet -def main() -> None: - """MIL SDK 示例程序主函数""" - setup_logging() +class MainWindow(QMainWindow,Ui_MainWindow): + def __init__(self): + super().__init__() + self.setupUi(self) - excel_path = Path(__file__).parent - - data_dict = read_excel_data("new_data.xlsx", return_object=False) - old_data_dict = read_excel_data("old_data.xlsx", return_object=False) - update_case_excel("new_case.xlsx", old_data_dict, data_dict) + apply_stylesheet(self, style=None,theme='dark_teal.xml') -if __name__ == "__main__": - main() \ No newline at end of file +if __name__ == '__main__': + app = QApplication(sys.argv) + main: MainWindow = MainWindow() + main.show() + sys.exit(app.exec()) \ No newline at end of file diff --git a/main.ui b/main.ui new file mode 100644 index 0000000..e514374 --- /dev/null +++ b/main.ui @@ -0,0 +1,52 @@ + + + MainWindow + + + + 0 + 0 + 800 + 600 + + + + MainWindow + + + + + + + QFrame::Shape::StyledPanel + + + QFrame::Shadow::Raised + + + + + + + + + 0 + 0 + 800 + 21 + + + + + + + + FrameMILTool + QFrame +
src.h
+ 1 +
+
+ + +
diff --git a/main_ui.py b/main_ui.py new file mode 100644 index 0000000..cc26f8e --- /dev/null +++ b/main_ui.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- + +################################################################################ +## Form generated from reading UI file 'main.ui' +## +## Created by: Qt User Interface Compiler version 6.11.1 +## +## WARNING! All changes made in this file will be lost when recompiling UI file! +################################################################################ + +from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, + QMetaObject, QObject, QPoint, QRect, + QSize, QTime, QUrl, Qt) +from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, + QFont, QFontDatabase, QGradient, QIcon, + QImage, QKeySequence, QLinearGradient, QPainter, + QPalette, QPixmap, QRadialGradient, QTransform) +from PySide6.QtWidgets import (QApplication, QFrame, QGridLayout, QMainWindow, + QMenuBar, QSizePolicy, QStatusBar, QWidget) + +from mil import FrameMILTool + +class Ui_MainWindow(object): + def setupUi(self, MainWindow): + if not MainWindow.objectName(): + MainWindow.setObjectName(u"MainWindow") + MainWindow.resize(800, 600) + self.centralwidget = QWidget(MainWindow) + self.centralwidget.setObjectName(u"centralwidget") + self.gridLayout = QGridLayout(self.centralwidget) + self.gridLayout.setObjectName(u"gridLayout") + self.frame = FrameMILTool(self.centralwidget) + self.frame.setObjectName(u"frame") + self.frame.setFrameShape(QFrame.Shape.StyledPanel) + self.frame.setFrameShadow(QFrame.Shadow.Raised) + + self.gridLayout.addWidget(self.frame, 0, 0, 1, 1) + + MainWindow.setCentralWidget(self.centralwidget) + self.menubar = QMenuBar(MainWindow) + self.menubar.setObjectName(u"menubar") + self.menubar.setGeometry(QRect(0, 0, 800, 21)) + MainWindow.setMenuBar(self.menubar) + self.statusbar = QStatusBar(MainWindow) + self.statusbar.setObjectName(u"statusbar") + MainWindow.setStatusBar(self.statusbar) + + self.retranslateUi(MainWindow) + + QMetaObject.connectSlotsByName(MainWindow) + # setupUi + + def retranslateUi(self, MainWindow): + MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None)) + # retranslateUi + diff --git a/mil.pyi b/mil.pyi new file mode 100644 index 0000000..8254abb --- /dev/null +++ b/mil.pyi @@ -0,0 +1,27 @@ +# This file was generated by Nuitka + +# Stubs included by default +from openpyxl import Workbook +from ui.mil_tool import FrameMILTool + +def create_mil_tool(parent: typing.Any) -> typing.Any: + ... + +__name__ = ... + + + +# Modules used internally, to allow implicit dependencies to be seen: +import os +import openpyxl +import logging +import dataclasses +import typing +import copy +import openpyxl.worksheet +import openpyxl.worksheet.worksheet +import _frozen_importlib_external +import PySide6 +import PySide6.QtWidgets +import PySide6.QtCore +import PySide6.QtGui \ No newline at end of file diff --git a/mil/__init__.py b/mil/__init__.py new file mode 100644 index 0000000..6de39c9 --- /dev/null +++ b/mil/__init__.py @@ -0,0 +1,5 @@ +from .ui.mil_tool import FrameMILTool +from openpyxl import Workbook + +def create_mil_tool(parent=None): + return FrameMILTool(parent) diff --git a/src/core/__init__.py b/mil/core/__init__.py similarity index 87% rename from src/core/__init__.py rename to mil/core/__init__.py index 7d992b6..770647c 100644 --- a/src/core/__init__.py +++ b/mil/core/__init__.py @@ -3,9 +3,8 @@ 提供 MIL 仿真数据读取功能 使用示例: - from src.core import setup_logging, read_excel_data + from src.core import read_excel_data - setup_logging() result = read_excel_data("simulation.xlsx") """ import logging @@ -23,7 +22,6 @@ from .exceptions import ( CaseDataError, ExcelWriteError, ) -from .logging_config import setup_logging, get_logger __all__ = [ "DataLog", diff --git a/src/core/base.py b/mil/core/base.py similarity index 100% rename from src/core/base.py rename to mil/core/base.py diff --git a/src/core/exceptions.py b/mil/core/exceptions.py similarity index 100% rename from src/core/exceptions.py rename to mil/core/exceptions.py diff --git a/src/core/mil_create_data_excel.py b/mil/core/mil_create_data_excel.py similarity index 100% rename from src/core/mil_create_data_excel.py rename to mil/core/mil_create_data_excel.py diff --git a/src/core/mil_read_case_excel.py b/mil/core/mil_read_case_excel.py similarity index 100% rename from src/core/mil_read_case_excel.py rename to mil/core/mil_read_case_excel.py diff --git a/src/core/mil_read_data_excel.py b/mil/core/mil_read_data_excel.py similarity index 100% rename from src/core/mil_read_data_excel.py rename to mil/core/mil_read_data_excel.py diff --git a/src/core/mil_update_excel.py b/mil/core/mil_update_excel.py similarity index 100% rename from src/core/mil_update_excel.py rename to mil/core/mil_update_excel.py diff --git a/mil/ui/mil_tool.py b/mil/ui/mil_tool.py new file mode 100644 index 0000000..8f889c3 --- /dev/null +++ b/mil/ui/mil_tool.py @@ -0,0 +1,17 @@ +import logging + +from .mil_tool_ui import Ui_FrameMILTool +from PySide6.QtWidgets import QFrame + +logger = logging.getLogger(__name__) + +class FrameMILTool(QFrame,Ui_FrameMILTool): + def __init__(self,parent=None): + super().__init__(parent) + self.setupUi(self) + + def init_ui(self): + pass + # logger.info("FrameMILTool 初始化完成") + + diff --git a/mil/ui/mil_tool.ui b/mil/ui/mil_tool.ui new file mode 100644 index 0000000..8f5f655 --- /dev/null +++ b/mil/ui/mil_tool.ui @@ -0,0 +1,367 @@ + + + FrameMILTool + + + + 0 + 0 + 706 + 308 + + + + Frame + + + + + + QTabWidget::TabPosition::South + + + 0 + + + + 功能面板 + + + + + + QFrame::Shape::StyledPanel + + + QFrame::Shadow::Raised + + + + + + + + 项目 + + + + + + + + 0 + 0 + + + + color: rgb(255, 255, 255); + + + + + + + + + + + + 0 + 0 + + + + color: rgb(255, 255, 255); + + + + + + + + 0 + 0 + + + + color: rgb(255, 255, 255); + + + + + + + + 0 + 0 + + + + ... + + + + + + + 累计时间 + + + + + + + + + + + + + + + 0 + 0 + + + + 生成 + + + + + + + 测试用例 + + + + + + + 数据文件 + + + + + + + + 0 + 0 + + + + ... + + + + + + + + + + true + + + + + + + + + + + + QFrame::Shape::StyledPanel + + + QFrame::Shadow::Raised + + + + + + + + + 0 + 0 + + + + 名称 + + + + + + + + + + + 0 + 0 + + + + 名称 + + + + + + + + + + + 0 + 0 + + + + 类型 + + + + + + + + + + + 0 + 0 + + + + 类型 + + + + + + + + + + + 0 + 0 + + + + 值定义 + + + + + + + + 0 + 0 + + + + 值定义 + + + + + + + + + + + + + + + + + + 0 + 0 + + + + 加载测试用例 + + + + + + + 删除 + + + + + + + 查找 + + + + + + + 替换 + + + + + + + + 0 + 0 + + + + 更新 + + + + + + + + + + + + Qt::Orientation::Vertical + + + + 20 + 40 + + + + + + + + + 项目列表 + + + + + + + + + + + + + + diff --git a/mil/ui/mil_tool_ui.py b/mil/ui/mil_tool_ui.py new file mode 100644 index 0000000..029f9dd --- /dev/null +++ b/mil/ui/mil_tool_ui.py @@ -0,0 +1,316 @@ +# -*- coding: utf-8 -*- + +################################################################################ +## Form generated from reading UI file 'mil_tool.ui' +## +## Created by: Qt User Interface Compiler version 6.11.1 +## +## WARNING! All changes made in this file will be lost when recompiling UI file! +################################################################################ + +from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, + QMetaObject, QObject, QPoint, QRect, + QSize, QTime, QUrl, Qt) +from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, + QFont, QFontDatabase, QGradient, QIcon, + QImage, QKeySequence, QLinearGradient, QPainter, + QPalette, QPixmap, QRadialGradient, QTransform) +from PySide6.QtWidgets import (QApplication, QCheckBox, QComboBox, QFrame, + QGridLayout, QLabel, QLineEdit, QListWidget, + QListWidgetItem, QPushButton, QRadioButton, QSizePolicy, + QSpacerItem, QTabWidget, QWidget) + +class Ui_FrameMILTool(object): + def setupUi(self, FrameMILTool): + if not FrameMILTool.objectName(): + FrameMILTool.setObjectName(u"FrameMILTool") + FrameMILTool.resize(706, 308) + self.gridLayout_8 = QGridLayout(FrameMILTool) + self.gridLayout_8.setObjectName(u"gridLayout_8") + self.tabWidget = QTabWidget(FrameMILTool) + self.tabWidget.setObjectName(u"tabWidget") + self.tabWidget.setTabPosition(QTabWidget.TabPosition.South) + self.widget = QWidget() + self.widget.setObjectName(u"widget") + self.gridLayout_12 = QGridLayout(self.widget) + self.gridLayout_12.setObjectName(u"gridLayout_12") + self.frame_3 = QFrame(self.widget) + self.frame_3.setObjectName(u"frame_3") + self.frame_3.setFrameShape(QFrame.Shape.StyledPanel) + self.frame_3.setFrameShadow(QFrame.Shadow.Raised) + self.gridLayout_3 = QGridLayout(self.frame_3) + self.gridLayout_3.setObjectName(u"gridLayout_3") + self.gridLayout_2 = QGridLayout() + self.gridLayout_2.setObjectName(u"gridLayout_2") + self.label = QLabel(self.frame_3) + self.label.setObjectName(u"label") + + self.gridLayout_2.addWidget(self.label, 0, 0, 1, 1) + + self.comboBox = QComboBox(self.frame_3) + self.comboBox.setObjectName(u"comboBox") + sizePolicy = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.comboBox.sizePolicy().hasHeightForWidth()) + self.comboBox.setSizePolicy(sizePolicy) + self.comboBox.setStyleSheet(u"color: rgb(255, 255, 255);") + + self.gridLayout_2.addWidget(self.comboBox, 0, 1, 1, 1) + + + self.gridLayout_3.addLayout(self.gridLayout_2, 0, 0, 1, 1) + + self.gridLayout = QGridLayout() + self.gridLayout.setObjectName(u"gridLayout") + self.FilePath = QLineEdit(self.frame_3) + self.FilePath.setObjectName(u"FilePath") + sizePolicy1 = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Preferred) + sizePolicy1.setHorizontalStretch(0) + sizePolicy1.setVerticalStretch(0) + sizePolicy1.setHeightForWidth(self.FilePath.sizePolicy().hasHeightForWidth()) + self.FilePath.setSizePolicy(sizePolicy1) + self.FilePath.setStyleSheet(u"color: rgb(255, 255, 255);") + + self.gridLayout.addWidget(self.FilePath, 1, 2, 1, 1) + + self.DataPath = QLineEdit(self.frame_3) + self.DataPath.setObjectName(u"DataPath") + sizePolicy1.setHeightForWidth(self.DataPath.sizePolicy().hasHeightForWidth()) + self.DataPath.setSizePolicy(sizePolicy1) + self.DataPath.setStyleSheet(u"color: rgb(255, 255, 255);") + + self.gridLayout.addWidget(self.DataPath, 0, 2, 1, 1) + + self.FileButton = QPushButton(self.frame_3) + self.FileButton.setObjectName(u"FileButton") + sizePolicy2 = QSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Preferred) + sizePolicy2.setHorizontalStretch(0) + sizePolicy2.setVerticalStretch(0) + sizePolicy2.setHeightForWidth(self.FileButton.sizePolicy().hasHeightForWidth()) + self.FileButton.setSizePolicy(sizePolicy2) + + self.gridLayout.addWidget(self.FileButton, 1, 3, 1, 1) + + self.checkBox = QCheckBox(self.frame_3) + self.checkBox.setObjectName(u"checkBox") + + self.gridLayout.addWidget(self.checkBox, 0, 4, 1, 1) + + self.radioButtonFile = QRadioButton(self.frame_3) + self.radioButtonFile.setObjectName(u"radioButtonFile") + + self.gridLayout.addWidget(self.radioButtonFile, 1, 0, 1, 1) + + self.pushButton = QPushButton(self.frame_3) + self.pushButton.setObjectName(u"pushButton") + sizePolicy2.setHeightForWidth(self.pushButton.sizePolicy().hasHeightForWidth()) + self.pushButton.setSizePolicy(sizePolicy2) + + self.gridLayout.addWidget(self.pushButton, 1, 4, 1, 1) + + self.label_3 = QLabel(self.frame_3) + self.label_3.setObjectName(u"label_3") + + self.gridLayout.addWidget(self.label_3, 1, 1, 1, 1) + + self.label_2 = QLabel(self.frame_3) + self.label_2.setObjectName(u"label_2") + + self.gridLayout.addWidget(self.label_2, 0, 1, 1, 1) + + self.DataButton = QPushButton(self.frame_3) + self.DataButton.setObjectName(u"DataButton") + sizePolicy2.setHeightForWidth(self.DataButton.sizePolicy().hasHeightForWidth()) + self.DataButton.setSizePolicy(sizePolicy2) + + self.gridLayout.addWidget(self.DataButton, 0, 3, 1, 1) + + self.radioButtonData = QRadioButton(self.frame_3) + self.radioButtonData.setObjectName(u"radioButtonData") + self.radioButtonData.setChecked(True) + + self.gridLayout.addWidget(self.radioButtonData, 0, 0, 1, 1) + + + self.gridLayout_3.addLayout(self.gridLayout, 1, 0, 1, 1) + + + self.gridLayout_12.addWidget(self.frame_3, 0, 0, 1, 1) + + self.frame = QFrame(self.widget) + self.frame.setObjectName(u"frame") + self.frame.setFrameShape(QFrame.Shape.StyledPanel) + self.frame.setFrameShadow(QFrame.Shadow.Raised) + self.gridLayout_6 = QGridLayout(self.frame) + self.gridLayout_6.setObjectName(u"gridLayout_6") + self.gridLayout_5 = QGridLayout() + self.gridLayout_5.setObjectName(u"gridLayout_5") + self.label_4 = QLabel(self.frame) + self.label_4.setObjectName(u"label_4") + sizePolicy3 = QSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Expanding) + sizePolicy3.setHorizontalStretch(0) + sizePolicy3.setVerticalStretch(0) + sizePolicy3.setHeightForWidth(self.label_4.sizePolicy().hasHeightForWidth()) + self.label_4.setSizePolicy(sizePolicy3) + + self.gridLayout_5.addWidget(self.label_4, 0, 0, 1, 1) + + self.lineEdit = QLineEdit(self.frame) + self.lineEdit.setObjectName(u"lineEdit") + + self.gridLayout_5.addWidget(self.lineEdit, 0, 1, 1, 1) + + self.label_7 = QLabel(self.frame) + self.label_7.setObjectName(u"label_7") + sizePolicy3.setHeightForWidth(self.label_7.sizePolicy().hasHeightForWidth()) + self.label_7.setSizePolicy(sizePolicy3) + + self.gridLayout_5.addWidget(self.label_7, 0, 2, 1, 1) + + self.lineEdit_4 = QLineEdit(self.frame) + self.lineEdit_4.setObjectName(u"lineEdit_4") + + self.gridLayout_5.addWidget(self.lineEdit_4, 0, 3, 1, 1) + + self.label_5 = QLabel(self.frame) + self.label_5.setObjectName(u"label_5") + sizePolicy3.setHeightForWidth(self.label_5.sizePolicy().hasHeightForWidth()) + self.label_5.setSizePolicy(sizePolicy3) + + self.gridLayout_5.addWidget(self.label_5, 1, 0, 1, 1) + + self.lineEdit_2 = QLineEdit(self.frame) + self.lineEdit_2.setObjectName(u"lineEdit_2") + + self.gridLayout_5.addWidget(self.lineEdit_2, 1, 1, 2, 1) + + self.label_8 = QLabel(self.frame) + self.label_8.setObjectName(u"label_8") + sizePolicy3.setHeightForWidth(self.label_8.sizePolicy().hasHeightForWidth()) + self.label_8.setSizePolicy(sizePolicy3) + + self.gridLayout_5.addWidget(self.label_8, 1, 2, 1, 1) + + self.lineEdit_5 = QLineEdit(self.frame) + self.lineEdit_5.setObjectName(u"lineEdit_5") + + self.gridLayout_5.addWidget(self.lineEdit_5, 1, 3, 2, 1) + + self.label_6 = QLabel(self.frame) + self.label_6.setObjectName(u"label_6") + sizePolicy3.setHeightForWidth(self.label_6.sizePolicy().hasHeightForWidth()) + self.label_6.setSizePolicy(sizePolicy3) + + self.gridLayout_5.addWidget(self.label_6, 2, 0, 2, 1) + + self.label_9 = QLabel(self.frame) + self.label_9.setObjectName(u"label_9") + sizePolicy3.setHeightForWidth(self.label_9.sizePolicy().hasHeightForWidth()) + self.label_9.setSizePolicy(sizePolicy3) + + self.gridLayout_5.addWidget(self.label_9, 2, 2, 2, 1) + + self.lineEdit_3 = QLineEdit(self.frame) + self.lineEdit_3.setObjectName(u"lineEdit_3") + + self.gridLayout_5.addWidget(self.lineEdit_3, 3, 1, 1, 1) + + self.lineEdit_6 = QLineEdit(self.frame) + self.lineEdit_6.setObjectName(u"lineEdit_6") + + self.gridLayout_5.addWidget(self.lineEdit_6, 3, 3, 1, 1) + + + self.gridLayout_6.addLayout(self.gridLayout_5, 0, 0, 1, 1) + + self.gridLayout_10 = QGridLayout() + self.gridLayout_10.setObjectName(u"gridLayout_10") + self.pushButton_2 = QPushButton(self.frame) + self.pushButton_2.setObjectName(u"pushButton_2") + sizePolicy.setHeightForWidth(self.pushButton_2.sizePolicy().hasHeightForWidth()) + self.pushButton_2.setSizePolicy(sizePolicy) + + self.gridLayout_10.addWidget(self.pushButton_2, 0, 0, 1, 1) + + self.pushButton_4 = QPushButton(self.frame) + self.pushButton_4.setObjectName(u"pushButton_4") + + self.gridLayout_10.addWidget(self.pushButton_4, 0, 4, 1, 1) + + self.pushButton_5 = QPushButton(self.frame) + self.pushButton_5.setObjectName(u"pushButton_5") + + self.gridLayout_10.addWidget(self.pushButton_5, 0, 2, 1, 1) + + self.pushButton_3 = QPushButton(self.frame) + self.pushButton_3.setObjectName(u"pushButton_3") + + self.gridLayout_10.addWidget(self.pushButton_3, 0, 3, 1, 1) + + self.UpdateButton = QPushButton(self.frame) + self.UpdateButton.setObjectName(u"UpdateButton") + sizePolicy2.setHeightForWidth(self.UpdateButton.sizePolicy().hasHeightForWidth()) + self.UpdateButton.setSizePolicy(sizePolicy2) + + self.gridLayout_10.addWidget(self.UpdateButton, 0, 5, 1, 1) + + + self.gridLayout_6.addLayout(self.gridLayout_10, 1, 0, 1, 1) + + + self.gridLayout_12.addWidget(self.frame, 1, 0, 1, 1) + + self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) + + self.gridLayout_12.addItem(self.verticalSpacer, 2, 0, 1, 1) + + self.tabWidget.addTab(self.widget, "") + self.tab_2 = QWidget() + self.tab_2.setObjectName(u"tab_2") + self.gridLayout_11 = QGridLayout(self.tab_2) + self.gridLayout_11.setObjectName(u"gridLayout_11") + self.listWidget = QListWidget(self.tab_2) + self.listWidget.setObjectName(u"listWidget") + + self.gridLayout_11.addWidget(self.listWidget, 0, 0, 1, 1) + + self.tabWidget.addTab(self.tab_2, "") + + self.gridLayout_8.addWidget(self.tabWidget, 0, 0, 1, 1) + + + self.retranslateUi(FrameMILTool) + + self.tabWidget.setCurrentIndex(0) + + + QMetaObject.connectSlotsByName(FrameMILTool) + # setupUi + + def retranslateUi(self, FrameMILTool): + FrameMILTool.setWindowTitle(QCoreApplication.translate("FrameMILTool", u"Frame", None)) + self.label.setText(QCoreApplication.translate("FrameMILTool", u"\u9879\u76ee", None)) + self.FileButton.setText(QCoreApplication.translate("FrameMILTool", u"...", None)) + self.checkBox.setText(QCoreApplication.translate("FrameMILTool", u"\u7d2f\u8ba1\u65f6\u95f4", None)) + self.radioButtonFile.setText("") + self.pushButton.setText(QCoreApplication.translate("FrameMILTool", u"\u751f\u6210", None)) + self.label_3.setText(QCoreApplication.translate("FrameMILTool", u"\u6d4b\u8bd5\u7528\u4f8b ", None)) + self.label_2.setText(QCoreApplication.translate("FrameMILTool", u"\u6570\u636e\u6587\u4ef6 ", None)) + self.DataButton.setText(QCoreApplication.translate("FrameMILTool", u"...", None)) + self.radioButtonData.setText("") + self.label_4.setText(QCoreApplication.translate("FrameMILTool", u"\u540d\u79f0", None)) + self.label_7.setText(QCoreApplication.translate("FrameMILTool", u"\u540d\u79f0", None)) + self.label_5.setText(QCoreApplication.translate("FrameMILTool", u"\u7c7b\u578b", None)) + self.label_8.setText(QCoreApplication.translate("FrameMILTool", u"\u7c7b\u578b", None)) + self.label_6.setText(QCoreApplication.translate("FrameMILTool", u"\u503c\u5b9a\u4e49", None)) + self.label_9.setText(QCoreApplication.translate("FrameMILTool", u"\u503c\u5b9a\u4e49", None)) + self.pushButton_2.setText(QCoreApplication.translate("FrameMILTool", u"\u52a0\u8f7d\u6d4b\u8bd5\u7528\u4f8b", None)) + self.pushButton_4.setText(QCoreApplication.translate("FrameMILTool", u"\u5220\u9664", None)) + self.pushButton_5.setText(QCoreApplication.translate("FrameMILTool", u"\u67e5\u627e", None)) + self.pushButton_3.setText(QCoreApplication.translate("FrameMILTool", u"\u66ff\u6362", None)) + self.UpdateButton.setText(QCoreApplication.translate("FrameMILTool", u"\u66f4\u65b0", None)) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.widget), QCoreApplication.translate("FrameMILTool", u"\u529f\u80fd\u9762\u677f", None)) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), QCoreApplication.translate("FrameMILTool", u"\u9879\u76ee\u5217\u8868", None)) + # retranslateUi + diff --git a/src/core/logging_config.py b/src/core/logging_config.py deleted file mode 100644 index 1edac08..0000000 --- a/src/core/logging_config.py +++ /dev/null @@ -1,61 +0,0 @@ -"""日志配置模块""" -import logging -import sys -from pathlib import Path -from typing import Literal - - -def setup_logging( - level: Literal["DEBUG", "INFO", "WARNING", "ERROR"] = "INFO", - log_file: str | Path | None = "logs/mil_sdk.log", - console_output: bool = True, -) -> logging.Logger: - """配置日志系统 - - Args: - level: 日志级别,默认 INFO - log_file: 日志文件路径,默认 logs/mil_sdk.log。设为 None 则不写入文件 - console_output: 是否输出到控制台,默认 True - - Returns: - 根日志记录器 - """ - logger = logging.getLogger() - logger.setLevel(level) - - if logger.hasHandlers(): - logger.handlers.clear() - - formatter = logging.Formatter( - "%(asctime)s [%(levelname)s] %(message)s", - datefmt="%Y-%m-%d %H:%M:%S" - ) - - if log_file is not None: - log_path = Path(log_file) - log_path.parent.mkdir(parents=True, exist_ok=True) - - file_handler = logging.FileHandler(log_path, encoding="utf-8") - file_handler.setLevel(logging.DEBUG) - file_handler.setFormatter(formatter) - logger.addHandler(file_handler) - - if console_output: - console_handler = logging.StreamHandler(sys.stdout) - console_handler.setLevel(level) - console_handler.setFormatter(formatter) - logger.addHandler(console_handler) - - return logger - - -def get_logger(name: str) -> logging.Logger: - """获取指定名称的日志记录器 - - Args: - name: 日志记录器名称,通常使用 __name__ - - Returns: - 日志记录器实例 - """ - return logging.getLogger(name) \ No newline at end of file diff --git a/tests/__init__.py b/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/conftest.py b/tests/conftest.py deleted file mode 100644 index b47d61b..0000000 --- a/tests/conftest.py +++ /dev/null @@ -1,47 +0,0 @@ -import pytest -from pathlib import Path -from openpyxl import Workbook - - -@pytest.fixture -def sample_excel_path() -> Path: - """返回根目录下的 sample.xlsx 路径""" - path = Path(__file__).parent.parent / "sample.xlsx" - if not path.exists(): - pytest.skip(f"测试文件 {path} 不存在") - return path - - -@pytest.fixture -def invalid_excel_path(tmp_path: Path) -> Path: - """创建缺少 Scenario1 表的无效 Excel 文件""" - wb = Workbook() - wb.save(tmp_path / "invalid.xlsx") - return tmp_path / "invalid.xlsx" - - -@pytest.fixture -def sample_data_dict() -> dict: - """返回示例数据字典""" - return { - "Scenario1": { - "headers": ["Column1", "Column2", "Column3"], - "rows": [ - ["Value1", "Value2", "Value3"], - ["Value4", "Value5", "Value6"] - ] - } - } - - -@pytest.fixture -def sample_sheets_dict() -> dict: - """返回示例工作表字典""" - return { - "Scenario1": { - "A1": "Header1", - "B1": "Header2", - "A2": "Data1", - "B2": "Data2" - } - } \ No newline at end of file diff --git a/tests/test_base.py b/tests/test_base.py deleted file mode 100644 index f7153c9..0000000 --- a/tests/test_base.py +++ /dev/null @@ -1,20 +0,0 @@ -import pytest -from src.core.base import DataLog - - -def test_datalog_defaults(): - log = DataLog() - assert log.time == 0.0 - assert log.value == "" - - -def test_datalog_with_values(): - log = DataLog(time=1.5, value="test") - assert log.time == 1.5 - assert log.value == "test" - - -def test_datalog_equality(): - log1 = DataLog(time=1.0, value="a") - log2 = DataLog(time=1.0, value="a") - assert log1 == log2 \ No newline at end of file diff --git a/tests/test_mil_case_excel.py b/tests/test_mil_case_excel.py deleted file mode 100644 index 1ca9c75..0000000 --- a/tests/test_mil_case_excel.py +++ /dev/null @@ -1,292 +0,0 @@ -import pytest -from pathlib import Path -from openpyxl import Workbook - -from src.core.mil_read_case_excel import ( - read_excel_case, - _get_template_version, - _analysis_action, -) -from src.core.mil_create_data_excel import ( - create_excel_case, - _init_data_log, - _analysis_case, - _analysis_step, -) -from src.core.exceptions import ExcelReadError, ExcelFormatError, CaseDataError -from src.core.base import DataLog - - -@pytest.fixture -def sample_data_dict(): - """返回示例数据字典""" - return { - "signal1": { - "type": "Type1", - "column": 2, - "datalog": [DataLog(0.0, "initial"), DataLog(1.0, "value1")] - }, - "signal2": { - "type": "Type2", - "column": 3, - "datalog": [DataLog(0.0, "init2"), DataLog(1.0, "value2")] - } - } - - -@pytest.fixture -def sample_sheets_dict(): - """返回示例工作表字典""" - return { - "TestSheet": { - "TestCase1": { - "enable": False, - "step": { - "step0": { - "name": "Step1", - "time": 1.0, - "action": {"signal1": "new_value1"} - }, - "step1": { - "name": "Step2", - "time": 2.0, - "action": {"signal2": "new_value2"} - } - } - }, - "TestCase2": { - "enable": True, - "step": {} - } - } - } - - -def test_get_template_version(): - """验证获取模板版本号""" - wb = Workbook() - sheet = wb.active - sheet.cell(2, 1, "v1.0.0") - sheet.cell(3, 1, None) - - version = _get_template_version(sheet) - assert version == "v1.0.0" - - -def test_get_template_version_empty(): - """验证空工作表的版本号""" - wb = Workbook() - sheet = wb.active - - version = _get_template_version(sheet) - assert version is None - - -def test_analysis_action_valid(sample_data_dict): - """验证解析有效操作字符串""" - wb = Workbook() - sheet = wb.create_sheet("TestSheet") - sheet.cell(1, 1, "Test") - - action = _analysis_action(sheet, 1, 3, "signal1=newvalue", sample_data_dict, "test.xlsx") - assert "signal1" in action - assert action["signal1"] == "newvalue" - - -def test_analysis_action_multiple(sample_data_dict): - """验证解析多个操作""" - wb = Workbook() - sheet = wb.create_sheet("TestSheet") - sheet.cell(1, 1, "Test") - - action = _analysis_action(sheet, 1, 3, "signal1=v1; signal2=v2", sample_data_dict, "test.xlsx") - assert "signal1" in action - assert "signal2" in action - assert action["signal1"] == "v1" - assert action["signal2"] == "v2" - - -def test_analysis_action_invalid_signal(sample_data_dict): - """验证解析无效信号时抛出异常""" - wb = Workbook() - sheet = wb.create_sheet("TestSheet") - sheet.cell(1, 1, "Test") - - with pytest.raises(CaseDataError, match="信号 .* 不存在"): - _analysis_action(sheet, 1, 3, "invalid_signal=value", sample_data_dict, "test.xlsx") - - -def test_init_data_log(sample_data_dict): - """验证初始化数据日志""" - data_copy = {k: v.copy() for k, v in sample_data_dict.items()} - for name in data_copy: - data_copy[name]["datalog"] = data_copy[name]["datalog"].copy() - - _init_data_log(data_copy) - - for name in data_copy: - assert len(data_copy[name]["datalog"]) == 1 - assert data_copy[name]["datalog"][0].time == 0.0 - - -def test_analysis_step_with_action(sample_data_dict): - """验证分析带操作的步骤""" - step_dict = { - "step0": { - "name": "TestStep", - "time": 1.5, - "action": {"signal1": "newvalue"} - } - } - - data_copy = {k: v.copy() for k, v in sample_data_dict.items()} - for name in data_copy: - data_copy[name]["datalog"] = data_copy[name]["datalog"].copy() - - _analysis_step(step_dict, data_copy) - - assert len(data_copy["signal1"]["datalog"]) == 3 - assert data_copy["signal1"]["datalog"][-1].time == 1.5 - assert data_copy["signal1"]["datalog"][-1].value == "newvalue" - - -def test_analysis_step_without_action(sample_data_dict): - """验证分析不带操作的步骤""" - step_dict = { - "step0": { - "name": "TestStep", - "time": 1.0 - } - } - - data_copy = {k: v.copy() for k, v in sample_data_dict.items()} - for name in data_copy: - data_copy[name]["datalog"] = data_copy[name]["datalog"].copy() - - initial_length = len(data_copy["signal1"]["datalog"]) - _analysis_step(step_dict, data_copy) - - assert len(data_copy["signal1"]["datalog"]) == initial_length + 1 - - -def test_analysis_case(sample_data_dict, sample_sheets_dict): - """验证用例分析""" - result = _analysis_case(sample_data_dict, sample_sheets_dict) - - assert "TestCase1" in result - assert "TestCase2" not in result - - -def test_analysis_case_skips_enabled_cases(sample_data_dict): - """验证跳过早启用的用例""" - sheets_dict = { - "TestSheet": { - "EnabledCase": { - "enable": True, - "step": {} - } - } - } - - result = _analysis_case(sample_data_dict, sheets_dict) - assert "EnabledCase" not in result - - -def test_read_excel_case_file_not_found(): - """验证文件不存在时抛出异常""" - with pytest.raises(ExcelReadError, match="不存在"): - read_excel_case("nonexistent.xlsx", {}, False) - - -def test_read_excel_case_missing_atech_sheet(tmp_path: Path): - """验证缺少 Atech-Hefei 表时抛出异常""" - wb = Workbook() - wb.create_sheet("OtherSheet") - invalid_path = tmp_path / "invalid.xlsx" - wb.save(invalid_path) - - with pytest.raises(ExcelFormatError, match="缺少 Atech-Hefei 表"): - read_excel_case(invalid_path, {}, False) - - -def test_read_excel_case_missing_version(tmp_path: Path, sample_data_dict): - """验证缺少版本号时抛出异常""" - wb = Workbook() - wb.create_sheet("Atech-Hefei") - wb.create_sheet("TestSheet") - invalid_path = tmp_path / "no_version.xlsx" - wb.save(invalid_path) - - with pytest.raises(ExcelFormatError, match="缺少模板版本号"): - read_excel_case(invalid_path, sample_data_dict, False) - - -def test_read_excel_case_success(tmp_path: Path, sample_data_dict): - """验证成功读取用例模板""" - wb = Workbook() - wb.remove(wb.active) - - version_sheet = wb.create_sheet("Atech-Hefei") - version_sheet.cell(2, 1, "v1.0.0") - - test_sheet = wb.create_sheet("TestSheet") - test_sheet.cell(2, 1, "TestCase1") - test_sheet.cell(2, 2, "未完成") - test_sheet.cell(2, 3, None) - test_sheet.cell(2, 4, "Step1") - test_sheet.cell(2, 5, 1.0) - test_sheet.cell(2, 6, None) - - test_sheet.cell(3, 1, "TestCase1") - test_sheet.cell(3, 2, "未完成") - test_sheet.cell(3, 3, None) - test_sheet.cell(3, 4, "Step2") - test_sheet.cell(3, 5, 2.0) - test_sheet.cell(3, 6, None) - - valid_path = tmp_path / "valid.xlsx" - wb.save(valid_path) - - result = read_excel_case(valid_path, sample_data_dict, False) - - assert "TestSheet" in result - assert "TestCase1" in result["TestSheet"] - - -def test_read_excel_case_missing_title(tmp_path: Path, sample_data_dict): - """验证缺少标题时抛出异常""" - wb = Workbook() - - version_sheet = wb.create_sheet("Atech-Hefei") - version_sheet.cell(2, 1, "v1.0.0") - - test_sheet = wb.create_sheet("TestSheet") - test_sheet.cell(2, 1, None) - - invalid_path = tmp_path / "missing_title.xlsx" - wb.save(invalid_path) - - with pytest.raises(CaseDataError, match="必须有标题名"): - read_excel_case(invalid_path, sample_data_dict, False) - - -def test_read_excel_case_invalid_time(tmp_path: Path, sample_data_dict): - """验证时间格式错误时抛出异常""" - wb = Workbook() - wb.remove(wb.active) - - version_sheet = wb.create_sheet("Atech-Hefei") - version_sheet.cell(2, 1, "v1.0.0") - - test_sheet = wb.create_sheet("TestSheet") - test_sheet.cell(2, 1, "TestCase1") - test_sheet.cell(2, 2, "未完成") - test_sheet.cell(2, 4, "Step1") - test_sheet.cell(2, 5, "invalid_time") - test_sheet.cell(2, 6, None) - - invalid_path = tmp_path / "invalid_time.xlsx" - wb.save(invalid_path) - - with pytest.raises(CaseDataError, match="时间必须是数字"): - read_excel_case(invalid_path, sample_data_dict, False) diff --git a/tests/test_mil_data_excel.py b/tests/test_mil_data_excel.py deleted file mode 100644 index c2051a7..0000000 --- a/tests/test_mil_data_excel.py +++ /dev/null @@ -1,150 +0,0 @@ -import pytest -from pathlib import Path -from openpyxl import Workbook - -from src.core.mil_read_data_excel import read_excel_data, ExcelReaderConfig -from src.core.exceptions import ExcelReadError, ExcelFormatError - - -def test_read_excel_data_returns_required_keys(sample_excel_path: Path): - """验证返回结果包含必需键""" - result = read_excel_data(sample_excel_path) - assert "wb" in result - assert "sheet" in result - assert "source_row" in result - - -def test_read_excel_data_contains_signals(sample_excel_path: Path): - """验证能解析出信号数据""" - result = read_excel_data(sample_excel_path) - signal_keys = [k for k in result.keys() if k not in ("wb", "sheet", "source_row")] - assert len(signal_keys) > 0, "应至少包含一个信号" - for name in signal_keys: - assert "type" in result[name] - assert "column" in result[name] - assert "datalog" in result[name] - - -def test_read_excel_file_not_found(): - """文件不存在时抛出 ExcelReadError""" - with pytest.raises(ExcelReadError, match="不存在"): - read_excel_data("nonexistent.xlsx") - - -def test_read_excel_missing_sheet(tmp_path: Path): - """缺少 Scenario1 表时抛出 ExcelFormatError""" - wb = Workbook() - wb.create_sheet("WrongSheet") - invalid_path = tmp_path / "invalid.xlsx" - wb.save(invalid_path) - with pytest.raises(ExcelFormatError, match="缺少"): - read_excel_data(invalid_path) - - -def test_read_excel_missing_source_header(tmp_path: Path): - """缺少 Source: Input 标记时抛出 ExcelFormatError""" - wb = Workbook() - sheet = wb.active - sheet.title = ExcelReaderConfig().sheet_name - sheet.cell(1, 1, "time") - sheet.cell(1, 2, "signal1") - invalid_path = tmp_path / "missing_header.xlsx" - wb.save(invalid_path) - with pytest.raises(ExcelFormatError, match="缺少"): - read_excel_data(invalid_path) - - -def test_datalog_is_list(sample_excel_path: Path): - """验证 datalog 是 DataLog 对象列表""" - result = read_excel_data(sample_excel_path) - signal_keys = [k for k in result.keys() if k not in ("wb", "sheet", "source_row")] - assert len(signal_keys) > 0 - first_signal = result[signal_keys[0]] - assert len(first_signal["datalog"]) > 0 - assert hasattr(first_signal["datalog"][0], "time") - assert hasattr(first_signal["datalog"][0], "value") - - - - - -def test_read_excel_data_return_object(sample_excel_path: Path): - """验证 return_object=True 时返回 ExcelDataResult 对象""" - from src.core.base import ExcelDataResult, SignalData - - result = read_excel_data(sample_excel_path, return_object=True) - assert isinstance(result, ExcelDataResult) - assert result.sheet_name == "Scenario1" - assert result.source_row > 0 - assert len(result.signals) > 0 - - -def test_read_excel_data_signal_data_access(sample_excel_path: Path): - """验证 ExcelDataResult 的信号访问方法""" - from src.core.base import SignalData - - result = read_excel_data(sample_excel_path, return_object=True) - signal_names = result.get_signal_names() - assert len(signal_names) > 0 - - first_signal_name = signal_names[0] - signal = result.get_signal(first_signal_name) - assert isinstance(signal, SignalData) - assert signal.datalog is not None - - -def test_excel_reader_config_defaults(): - """验证 ExcelReaderConfig 默认值""" - config = ExcelReaderConfig() - assert config.sheet_name == "Scenario1" - assert config.source_header == "Source: Input" - assert config.time_column == 1 - assert config.header_row == 1 - assert config.type_row == 3 - assert config.data_start_row_offset == 1 - - -def test_excel_reader_config_custom(): - """验证 ExcelReaderConfig 自定义值""" - config = ExcelReaderConfig( - sheet_name="CustomSheet", - source_header="CustomHeader", - time_column=2, - header_row=2, - type_row=4, - data_start_row_offset=2 - ) - assert config.sheet_name == "CustomSheet" - assert config.source_header == "CustomHeader" - assert config.time_column == 2 - assert config.header_row == 2 - assert config.type_row == 4 - assert config.data_start_row_offset == 2 - - -def test_read_excel_with_custom_config(tmp_path: Path): - """验证使用自定义配置读取 Excel""" - wb = Workbook() - sheet = wb.active - sheet.title = "CustomSheet" - - sheet.cell(1, 1, "time") - sheet.cell(1, 2, "signal1") - sheet.cell(2, 1, "CustomHeader") - sheet.cell(2, 2, "CustomHeader") - sheet.cell(3, 1, "Type1") - sheet.cell(4, 1, 0.0) - sheet.cell(4, 2, "value1") - sheet.cell(5, 1, 1.0) - sheet.cell(5, 2, "value2") - - custom_path = tmp_path / "custom.xlsx" - wb.save(custom_path) - - config = ExcelReaderConfig( - sheet_name="CustomSheet", - source_header="CustomHeader" - ) - result = read_excel_data(custom_path, return_object=True, config=config) - assert result.sheet_name == "CustomSheet" - assert "signal1" in result.signals \ No newline at end of file