Adding tests for debug
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
Ad5001 2024-09-26 00:01:30 +02:00
parent f9af0c34dd
commit 309b0fafb0
Signed by: Ad5001
GPG key ID: EF45F9C6AFE20160
3 changed files with 132 additions and 34 deletions

View file

@ -16,15 +16,15 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
""" """
from PySide6.QtCore import QtMsgType, qInstallMessageHandler from PySide6.QtCore import QtMsgType, qInstallMessageHandler, QMessageLogContext
from math import ceil, log10 from math import ceil, log10
from sourcemap import loads
from os import path from os import path
CURRENT_PATH = path.dirname(path.realpath(__file__)) CURRENT_PATH = path.dirname(path.realpath(__file__))
SOURECMAP_PATH = path.realpath(f"{CURRENT_PATH}/../qml/eu/ad5001/LogarithmPlotter/js/index.mjs.map") SOURCEMAP_PATH = path.realpath(f"{CURRENT_PATH}/../qml/eu/ad5001/LogarithmPlotter/js/index.mjs.map")
SOURCEMAP_INDEX = None SOURCEMAP_INDEX = None
class LOG_COLORS: class LOG_COLORS:
GRAY = "\033[90m" GRAY = "\033[90m"
BLUE = "\033[94m" BLUE = "\033[94m"
@ -35,7 +35,6 @@ class LOG_COLORS:
RESET = "\033[0m" RESET = "\033[0m"
MODES = { MODES = {
QtMsgType.QtInfoMsg: ['info', LOG_COLORS.BLUE], QtMsgType.QtInfoMsg: ['info', LOG_COLORS.BLUE],
QtMsgType.QtWarningMsg: ['warning', LOG_COLORS.ORANGE], QtMsgType.QtWarningMsg: ['warning', LOG_COLORS.ORANGE],
@ -45,36 +44,59 @@ MODES = {
DEFAULT_MODE = ['debug', LOG_COLORS.GRAY] DEFAULT_MODE = ['debug', LOG_COLORS.GRAY]
def log_qt_debug(mode, context, message):
def map_javascript_source(source_file: str, line: str) -> tuple[str, str]:
""" """
Parses and renders qt log messages. Maps a line from the compiled javascript to its source.
""" """
if mode in MODES: try:
mode = MODES[mode] if SOURCEMAP_INDEX is not None:
else:
mode = DEFAULT_MODE
line = context.line
source_file = context.file
# Remove source and line from emssage
if source_file is not None:
if message.startswith(source_file):
message = message[len(source_file) + 1:]
source_file = source_file.split("/qml")[-1] # We're only interested in that part.
if line is not None and message.startswith(str(line)):
line_length = ceil(log10((line+1) if line > 0 else 1))
message = message[line_length + 2:]
# Check MJS
if line is not None and source_file is not None and source_file.endswith("index.mjs"):
try:
token = SOURCEMAP_INDEX.lookup(line, 20) token = SOURCEMAP_INDEX.lookup(line, 20)
source_file = source_file[:-len("index.mjs")] + token.src source_file = source_file[:-len("index.mjs")] + token.src
line = token.src_line line = token.src_line
except IndexError: except IndexError:
pass # Unable to find source, leave as is. pass # Unable to find source, leave as is.
print(f"{LOG_COLORS.INVERT}{mode[1]}[{mode[0].upper()}]{LOG_COLORS.RESET_INVERT} {message}{LOG_COLORS.RESET} ({context.function} at {source_file}:{line})") return source_file, line
def create_log_terminal_message(mode: QtMsgType, context: QMessageLogContext, message: str):
"""
Parses a qt log message and returns it.
"""
mode = MODES[mode] if mode in MODES else DEFAULT_MODE
line = context.line
source_file = context.file
# Remove source and line from message
if source_file is not None:
if message.startswith(source_file):
message = message[len(source_file) + 1:]
source_file = "LogarithmPlotter/qml/" + source_file.split("/qml/")[-1] # We're only interested in that part.
if line is not None and message.startswith(str(line)):
line_length = ceil(log10((line + 1) if line > 0 else 1))
message = message[line_length + 2:]
# Check MJS
if line is not None and source_file is not None and source_file.endswith("index.mjs"):
source_file, line = map_javascript_source(source_file, line)
prefix = f"{LOG_COLORS.INVERT}{mode[1]}[{mode[0].upper()}]{LOG_COLORS.RESET_INVERT}"
message = message + LOG_COLORS.RESET
context = f"{context.function} at {source_file}:{line}"
return f"{prefix} {message} ({context})"
def log_qt_debug(mode: QtMsgType, context: QMessageLogContext, message: str):
"""
Parses and renders qt log messages.
"""
print(create_log_terminal_message(mode, context, message))
def setup(): def setup():
global SOURCEMAP_INDEX global SOURCEMAP_INDEX
with open(SOURECMAP_PATH, "r") as f: try:
SOURCEMAP_INDEX = loads(f.read()) with open(SOURCEMAP_PATH, "r") as f:
qInstallMessageHandler(log_qt_debug) from sourcemap import loads
SOURCEMAP_INDEX = loads(f.read())
except Exception as e:
log_qt_debug(QtMsgType.QtWarningMsg, QMessageLogContext(),
f"Could not setup JavaScript source mapper in logs: {repr(e)}")
qInstallMessageHandler(log_qt_debug)

View file

@ -15,9 +15,19 @@
You can find more screenshots on the [app's website](https://apps.ad5001.eu/logarithmplotter/). You can find more screenshots on the [app's website](https://apps.ad5001.eu/logarithmplotter/).
## Run ## Build & Run
You can simply run LogarithmPlotter using `python3 run.py`. First, you'll need to install all the required dependencies:
- [Python 3](https://python.org) with [poetry](https://python-poetry.org/), and setup a virtual environment and call
`poetry install`.
- [npm](https://npmjs.com) (or [yarn](https://yarnpkg.com/)), and run `npm install` (or `yarn install`).
You can simply run LogarithmPlotter using `python3 run.py`. It automatically compiles the language files (requires
`lrelease` to be installed and in path), and the JavaScript modules.
If you do not wish do recompile the files again on every run, you can use
`python3 LogarithmPlotter/logarithmplotter.py`.
In order to test translations, you can use the `--lang=<lang code>` commandline option to force the locale. In order to test translations, you can use the `--lang=<lang code>` commandline option to force the locale.
@ -27,9 +37,7 @@ In order to test translations, you can use the `--lang=<lang code>` commandline
All scripts noted here can be found in the `scripts` directory. All scripts noted here can be found in the `scripts` directory.
You can generate installers for LogarithmPlotter after installing all the dependencies: You can generate installers for LogarithmPlotter after installing all the dependencies.
For all builds, you will need [Python 3](https://python.org) with [poetry](https://python-poetry.org/), and
`poetry install --with packaging`.
- Windows installer: - Windows installer:
- Run the `build-windows.bat` script (or `build-wine.sh` if you're cross-compiling with wine on Linux) to build an - Run the `build-windows.bat` script (or `build-wine.sh` if you're cross-compiling with wine on Linux) to build an

View file

@ -0,0 +1,68 @@
"""
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2021-2024 Ad5001
*
* 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 <https://www.gnu.org/licenses/>.
"""
import pytest
from os.path import exists
from PySide6.QtCore import QtMsgType, QMessageLogContext
from LogarithmPlotter.util import debug
def test_setup():
sourcemap_installed = False
try:
import sourcemap
sourcemap_installed = True
except:
pass
if sourcemap_installed:
file = debug.SOURCEMAP_PATH
debug.SOURCEMAP_PATH = None
debug.setup() # Nothing could be setup.
debug.SOURCEMAP_PATH = file
debug.setup()
assert (sourcemap_installed and exists(debug.SOURCEMAP_PATH)) == (debug.SOURCEMAP_INDEX is not None)
def test_map_source():
sourcemap_available = debug.SOURCEMAP_INDEX is not None
if sourcemap_available:
assert debug.map_javascript_source("js/index.mjs", 21) == ("js/module/interface.mjs", 21)
assert debug.map_javascript_source("js/index.mjs", 100000) == ("js/index.mjs", 100000) # Too long, not found
debug.SOURCEMAP_INDEX = None
assert debug.map_javascript_source("js/index.mjs", 21) == ("js/index.mjs", 21)
def test_log_terminal_message():
msg1 = debug.create_log_terminal_message(
QtMsgType.QtWarningMsg, QMessageLogContext(),
"a long and random message"
)
assert "[WARNING]" in msg1
assert "a long and random message" in msg1
msg2 = debug.create_log_terminal_message(
QtMsgType.QtCriticalMsg,
QMessageLogContext("LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Index.qml", 15, "anotherFunctionName",
"aCategoryDifferent"),
"LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Index.qml:15: a potentially potential error message"
)
assert "[CRITICAL]" in msg2
assert "Index.qml" in msg2
assert "a potentially potential error message" in msg2
assert "anotherFunctionName" in msg2