Skip to content

Commit

Permalink
Feature/linting (#794)
Browse files Browse the repository at this point in the history
* removed unneeded state from sweep worker
* moved screenshot data conversion in own module
* linting
  • Loading branch information
zarath authored Feb 9, 2025
1 parent bb562ff commit 92b6b30
Show file tree
Hide file tree
Showing 36 changed files with 199 additions and 199 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ MANIFEST
.flatpak-builder/*
macbuildenv/*
NanoVNASaver.spec
nanovna-saver.py
src/NanoVNASaver/Windows/ui/about.py

# Per-project virtualenvs
Expand Down
2 changes: 1 addition & 1 deletion .pylintrc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[MESSAGES CONTROL]
disable=W0614,C0410,C0321,C0111,I0011,C0103
disable=W0614,C0410,C0321,C0111,I0011,C0103,R0401
# allow _ for ignored variables
# allow generic names like a,b,c and i,j,k,l,m,n and x,y,z
# allow k,v for key/value
Expand Down
6 changes: 5 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ dev = [
"pre-commit~=4.1",
"mypy~=1.14",
"pylint~=3.3",
"types-pyserial~=3.5",

# Testing
"pytest~=8.3",
Expand Down Expand Up @@ -132,7 +133,10 @@ fix = true
show-fixes = true
unsafe-fixes = false
# TODO use https://docs.astral.sh/ruff/configuration/#config-file-discovery for test and UI generated files
extend-exclude = ["ui/*.py"]
extend-exclude = [
"**/ui/*.py",
"src/tools/setuptools_wrapper.py"
]


[tool.ruff.lint]
Expand Down
2 changes: 1 addition & 1 deletion src/NanoVNASaver/Analysis/BandPassAnalysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ def runAnalysis(self) -> None:

for label, val in cutoff_freq.items():
self.label[label].setText(
f"{format_frequency(val)}" f" ({cutoff_gain[label]:.1f} dB)"
f"{format_frequency(val)} ({cutoff_gain[label]:.1f} dB)"
)
for label in ("freq_center", "span_3.0dB", "span_6.0dB"):
self.label[label].setText(format_frequency(result[label]))
Expand Down
2 changes: 1 addition & 1 deletion src/NanoVNASaver/Analysis/HighPassAnalysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def runAnalysis(self):

for label, val in cutoff_freq.items():
self.label[label].setText(
f"{format_frequency(val)}" f" ({cutoff_gain[label]:.1f} dB)"
f"{format_frequency(val)} ({cutoff_gain[label]:.1f} dB)"
)

self.label["octave"].setText(f"{octave:.3f}dB/octave")
Expand Down
5 changes: 1 addition & 4 deletions src/NanoVNASaver/Charts/Frequency.py
Original file line number Diff line number Diff line change
Expand Up @@ -628,10 +628,7 @@ def drawFrequencyTicks(self, qp):
ticks = math.floor(self.dim.width / 100)

# try to adapt format to span
if (
self.fstart == 0
or int(fspan / ticks / self.fstart * 10000) > 2
):
if self.fstart == 0 or int(fspan / ticks / self.fstart * 10000) > 2:
my_format_frequency = format_frequency_chart
else:
my_format_frequency = format_frequency_chart_2
Expand Down
4 changes: 1 addition & 3 deletions src/NanoVNASaver/Charts/RI.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,9 +312,7 @@ def imag_scaling_constraints(self, min_imag, max_imag):
if 0 < min_imag < 2:
min_imag = 0

if (
max_imag - min_imag
) > 8 and min_imag < 0 < max_imag:
if (max_imag - min_imag) > 8 and min_imag < 0 < max_imag:
# We should show a "0" line for the reactive part
span = max_imag - min_imag
step_size = span / 8
Expand Down
14 changes: 8 additions & 6 deletions src/NanoVNASaver/Charts/TDR.py
Original file line number Diff line number Diff line change
Expand Up @@ -354,9 +354,11 @@ def _draw_ticks(self, height, width, x_step, min_index) -> None:
qp.drawText(
self.leftMargin - 10,
self.topMargin + height + 15,
f"""{round(
self.tdrWindow.distance_axis[min_index] / 2, self.decimals)
!s}m""",
f"""{
round(
self.tdrWindow.distance_axis[min_index] / 2, self.decimals
)!s
}m""",
)

def _draw_y_ticks(
Expand Down Expand Up @@ -411,9 +413,9 @@ def _draw_marker(self, height, x_step, y_step, min_index):
qp.drawText(
marker_point.x() - 10,
marker_point.y() - 5,
f"""{round(
self.tdrWindow.distance_axis[self.marker_location] / 2,
2)}m""",
f"""{
round(self.tdrWindow.distance_axis[self.marker_location] / 2, 2)
}m""",
)

def _draw_graph(self, height, width):
Expand Down
4 changes: 1 addition & 3 deletions src/NanoVNASaver/Controls/MarkerControl.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@ class ShowButton(QtWidgets.QPushButton):
def setText(self, text: str = ""):
app_config = get_app_config()
if not text:
text = (
"Show data" if app_config.gui.markers_hidden else "Hide data"
)
text = "Show data" if app_config.gui.markers_hidden else "Hide data"
super().setText(text)
self.setToolTip("Toggle visibility of marker readings area")

Expand Down
1 change: 0 additions & 1 deletion src/NanoVNASaver/Controls/SerialControl.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@


class SerialControl(Control):

# true when serial port was connected and false when it was disconnected
connected = Signal(bool)

Expand Down
10 changes: 5 additions & 5 deletions src/NanoVNASaver/Controls/SweepControl.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

logger = logging.getLogger(__name__)


class FrequencyInputWidget(QtWidgets.QLineEdit):
def __init__(self, text=""):
super().__init__(text)
Expand All @@ -48,6 +49,7 @@ def setText(self, text: str) -> None:
def get_freq(self) -> int:
return parse_frequency(self.text())


class SweepControl(Control):
def __init__(self, app: NanoVNASaver):
super().__init__(app, "Sweep control")
Expand Down Expand Up @@ -130,9 +132,7 @@ def _build_start_button(self) -> QtWidgets.QPushButton:
btn = QtWidgets.QPushButton("Sweep")
btn.setFixedHeight(20)
btn.clicked.connect(self.app.sweep_start)
btn.setShortcut(
QtCore.Qt.Key.Key_Control + QtCore.Qt.Key.Key_W
)
btn.setShortcut(QtCore.Qt.Key.Key_Control + QtCore.Qt.Key.Key_W)
# Will be enabled when VNA is connected
btn.setEnabled(False)
return btn
Expand Down Expand Up @@ -260,13 +260,13 @@ def update_text(self) -> None:
start = self.get_start()
stop = self.get_end()
if cal_ds.data:
oor_text=(
oor_text = (
f"Out of calibration range ("
f"{format_frequency_inputs(cal_ds.freq_min())} - "
f"{format_frequency_inputs(cal_ds.freq_max())})"
)
else:
oor_text="No calibration data"
oor_text = "No calibration data"
self.inputs["Start"].setStyleSheet("QLineEdit {}")
self.inputs["Stop"].setStyleSheet("QLineEdit {}")
self.inputs["Start"].setToolTip("")
Expand Down
36 changes: 25 additions & 11 deletions src/NanoVNASaver/Defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,7 @@ class ChartColorsConfig: # pylint: disable=too-many-instance-attributes
default_factory=lambda: QColor(QColorConstants.DarkMagenta)
)
swr: QColor = field(default_factory=lambda: QColor(255, 0, 0, 128))
text: QColor = field(
default_factory=lambda: QColor(QColorConstants.Black)
)
text: QColor = field(default_factory=lambda: QColor(QColorConstants.Black))
bands: QColor = field(default_factory=lambda: QColor(128, 128, 128, 48))


Expand Down Expand Up @@ -123,6 +121,7 @@ class MarkersConfig:
default_factory=lambda: QColor(QColorConstants.LightGray)
)


@dataclass
class SweepConfig:
start: str = ""
Expand All @@ -131,10 +130,13 @@ class SweepConfig:
span: str = ""
segments: str = "1"


@dataclass
class AppConfig:
gui: GuiConfig = field(default_factory=GuiConfig)
charts_selected: ChartsSelectedConfig = field(default_factory=ChartsSelectedConfig)
charts_selected: ChartsSelectedConfig = field(
default_factory=ChartsSelectedConfig
)
chart: ChartConfig = field(default_factory=ChartConfig)
chart_colors: ChartColorsConfig = field(default_factory=ChartColorsConfig)
markers: MarkersConfig = field(default_factory=MarkersConfig)
Expand All @@ -143,13 +145,17 @@ class AppConfig:

# noinspection PyDataclass
class AppSettings(QSettings):

def __init__(self, organization: str = "NanoVNASaver", application: str = "NanoVNASaver") -> None:
def __init__(
self,
organization: str = "NanoVNASaver",
application: str = "NanoVNASaver",
) -> None:
super().__init__(
QSettings.Format.IniFormat,
QSettings.Scope.UserScope,
organization,
application)
application,
)

self._app_config = AppConfig()

Expand Down Expand Up @@ -187,7 +193,11 @@ def _restore_dataclass(self, name: str, data: object) -> object:
setattr(result, field_it.name, default)
continue
try:
setattr(result, field_it.name, AppSettings._to_type(value, field_it.type))
setattr(
result,
field_it.name,
AppSettings._to_type(value, field_it.type),
)
except TypeError:
setattr(result, field_it.name, default)
self.endGroup()
Expand All @@ -206,7 +216,6 @@ def restore_config(self) -> AppConfig:
self._app_config = result
return self.get_app_config()


def store_config(self) -> None:
logger.info("Saving settings to: %s", self.fileName())

Expand All @@ -224,7 +233,9 @@ def _from_type(data) -> str:
QByteArray: QByteArray.toHex,
}
return (
f"{type_map[type(data)](data)}" if type(data) in type_map else f"{data}"
f"{type_map[type(data)](data)}"
if type(data) in type_map
else f"{data}"
)

@staticmethod
Expand All @@ -238,11 +249,14 @@ def _to_type(data: object, data_type: type) -> object:
QByteArray: lambda x: QByteArray.fromHex(literal_eval(x)),
}
return (
type_map[data_type](data) if data_type in type_map else data_type(data)
type_map[data_type](data)
if data_type in type_map
else data_type(data)
)


APP_SETTINGS = AppSettings()


def get_app_config() -> AppConfig:
return APP_SETTINGS.get_app_config()
4 changes: 2 additions & 2 deletions src/NanoVNASaver/Formatting.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ def format_group_delay(val: float) -> str:


def format_phase(val: float) -> str:
return f"{math.degrees(val):.2f}" "\N{DEGREE SIGN}"
return f"{math.degrees(val):.2f}\N{DEGREE SIGN}"


def format_complex_adm(z: complex, allow_negative: bool = False) -> str:
Expand All @@ -139,7 +139,7 @@ def format_complex_imp(z: complex, allow_negative: bool = False) -> str:
fmt_re = FMT_COMPLEX_NEG if allow_negative else FMT_COMPLEX
re = SITools.Value(z.real, fmt=fmt_re)
im = SITools.Value(abs(z.imag), fmt=FMT_COMPLEX)
return f"{re}{'-' if z.imag < 0 else '+'}j{im} " "\N{OHM SIGN}"
return f"{re}{'-' if z.imag < 0 else '+'}j{im} \N{OHM SIGN}"


def format_wavelength(length: Number) -> str:
Expand Down
52 changes: 52 additions & 0 deletions src/NanoVNASaver/Hardware/Convert.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# NanoVNASaver
#
# A python program to view and export Touchstone data from a NanoVNA
# Copyright (C) 2019, 2020 Rune B. Broberg
# Copyright (C) 2020ff NanoVNA-Saver Authors
#
# 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 struct

import numpy as np
from PySide6.QtGui import QImage, QPixmap


def get_argb32_pixmap(image_data: bytes, width, height) -> QPixmap:
rgb_data = struct.unpack(f">{width * height}H", image_data)
rgb_array = np.array(rgb_data, dtype=np.uint32)
rgba = (
0xFF000000
+ ((rgb_array & 0xF800) << 8)
+ ((rgb_array & 0x07E0) << 5)
+ ((rgb_array & 0x001F) << 3)
)
return QPixmap(
QImage(
rgba,
width,
height,
QImage.Format.Format_ARGB32,
)
)


def get_rgb16_pixmap(image_data: bytes, width, height) -> QPixmap:
return QPixmap(
QImage(
image_data,
width,
height,
QImage.Format.Format_RGB16,
)
)
2 changes: 1 addition & 1 deletion src/NanoVNASaver/Hardware/Hardware.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ def get_comment(iface: Interface) -> str:
vna_version = detect_version(iface)
if vna_version == "v2":
return "S-A-A-2"
elif vna_version == "lite_vna_64":
if vna_version == "lite_vna_64":
return "LiteVNA64"

logger.info("Finding firmware variant...")
Expand Down
14 changes: 5 additions & 9 deletions src/NanoVNASaver/Hardware/JNCRadio_VNA_3G.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@
import logging

import serial
from PySide6.QtGui import QImage, QPixmap
from PySide6.QtGui import QPixmap

from .Convert import get_rgb16_pixmap
from .NanoVNA import NanoVNA
from .Serial import Interface

Expand Down Expand Up @@ -50,15 +51,10 @@ def getScreenshot(self) -> QPixmap:
if not self.connected():
return QPixmap()
try:
rgba_array = self._capture_data()
image = QImage(
rgba_array,
self.screenwidth,
self.screenheight,
QImage.Format.Format_RGB16,
)
logger.debug("Captured screenshot")
return QPixmap(image)
return get_rgb16_pixmap(
self._capture_data(), self.screenwidth, self.screenheight
)
except serial.SerialException as exc:
logger.exception("Exception while capturing screenshot: %s", exc)
return QPixmap()
Expand Down
6 changes: 5 additions & 1 deletion src/NanoVNASaver/Hardware/LiteVNA64.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
SUPPORTED_PIXEL_FORMAT = 16


# TODO: move screenshot conversation to Convert module
class ScreenshotData:
header_size = 2 + 2 + 1

Expand All @@ -51,7 +52,10 @@ def data_size(self) -> int:
return self.width * self.height * int(self.pixel_size / 8)

def __repr__(self) -> str:
return f"{self.width}x{self.height} {self.pixel_size}bits ({self.data_size()} Bytes)"
return (
f"{self.width}x{self.height} {self.pixel_size}bits "
f"({self.data_size()} Bytes)"
)

@staticmethod
def from_header(header_data: bytes) -> "ScreenshotData":
Expand Down
Loading

0 comments on commit 92b6b30

Please sign in to comment.