# Window.py -- Pamhyr # Copyright (C) 2023-2026 INRAE # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # -*- coding: utf-8 -*- import os import psutil import logging import traceback from tools import trace, timer from View.Tools.PamhyrWindow import PamhyrWindow from View.Tools.PamhyrPythonEditor import PamhyrPythonEditor from View.Debug.Table import TableModel from PyQt5.QtGui import ( QKeySequence, ) from PyQt5.QtCore import ( Qt, QVariant, QAbstractTableModel, QCoreApplication, QModelIndex, QRect, QThread, QTimer, pyqtSlot, pyqtSignal, ) from PyQt5.QtWidgets import ( QDialogButtonBox, QPushButton, QLineEdit, QFileDialog, QTableView, QAbstractItemView, QUndoStack, QShortcut, QAction, QItemDelegate, QComboBox, QVBoxLayout, QHeaderView, QTabWidget, QProgressBar, QLabel, QTextEdit, QHBoxLayout, ) from PyQt5.Qsci import QsciScintilla, QsciLexerPython logger = logging.getLogger() _translate = QCoreApplication.translate class ReplWindow(PamhyrWindow): _pamhyr_ui = "DebugRepl" _pamhyr_name = "Debug REPL" def __init__(self, study=None, config=None, solver=None, parent=None): title = _translate("Debug", "Debug REPL") super(ReplWindow, self).__init__( title=title, study=study, config=config, options=[], parent=parent ) self.__debug_exec_result__ = None self._history = [] self._history_ind = 0 self.setup_editor() self.setup_connections() def setup_editor(self): layout = self.find(QHBoxLayout, "horizontalLayout") self._editor = PamhyrPythonEditor() layout.insertWidget(0, self._editor) def setup_connections(self): self.find(QPushButton, "pushButton").clicked.connect(self.eval_python) def eval_python(self): code = self._editor.text() # Code to rich_code rich_code = code.strip().split("\n") # Add return variable for results display at last row rich_code[-1] = "self.__debug_exec_result__ = " + rich_code[-1] rich_code = "\n".join(rich_code) logger.debug(f"User debug command : \n{rich_code}") try: value = exec(rich_code) value = self.__debug_exec_result__ except Exception as e: value = f"" + str(e) + "\n" value += f"{traceback.format_exc()}" # Display code msg = f" # " + code + " #" self.find(QTextEdit, "textEdit").append(msg) # Display results self.find(QTextEdit, "textEdit").append(str(value)) class TimerWindow(PamhyrWindow): _pamhyr_ui = "DebugTimer" _pamhyr_name = "Debug Timer" def __init__(self, study=None, config=None, solver=None, parent=None): title = _translate("Debug", "Debug Timer") super(TimerWindow, self).__init__( title=title, study=study, config=config, options=[], parent=parent ) self._process = psutil.Process(os.getpid()) self.setup_table() self.setup_label() self.setup_alarm() self.setup_connections() def setup_table(self): table = self.find(QTableView, f"tableView") self._table = TableModel( table_view=table, table_headers={ "name": "Function name", "time": "Time (sec)", "calls": "Number of calls" }, data=None, ) def setup_label(self): label = self.find(QLabel, "label") label.setText( f" Memory usage:\t" + "" + f"{self._process.memory_info().rss / (1000 * 1000):.3f}" + " MB" ) def setup_alarm(self): self._alarm = QTimer() self._alarm.start(2000) def setup_connections(self): # self.find(QAction, "action_reset").triggered.connect(self.reset) self.find(QAction, "action_export").triggered.connect(self.export) self._alarm.timeout.connect(self.update) def update(self): self._table.update_lst() self.setup_label() # def reset(self): # self._table.reset_timers() def export(self): self.file_dialog( select_file="AnyFile", callback=lambda f: self.export_to(f[0]), default_suffix=".csv", file_filter=["CSV file (*.csv)"], ) def export_to(self, filename): csv = self._table.to_csv() with open(filename, 'w', newline='') as csvfile: csvfile.write(csv)