Tighter mypy testing, fixed up type hints

This commit is contained in:
Keith Edmunds 2024-07-08 19:03:35 +01:00
parent 2394327d38
commit 5f3119be1f
12 changed files with 61 additions and 44 deletions

View File

@ -15,7 +15,7 @@ class DatabaseManager:
__instance = None
def __init__(self, database_url: str, **kwargs):
def __init__(self, database_url: str, **kwargs: dict) -> None:
if DatabaseManager.__instance is None:
self.db = Alchemical(database_url, **kwargs)
self.db.create_all()
@ -24,7 +24,7 @@ class DatabaseManager:
raise Exception("Attempted to create a second DatabaseManager instance")
@staticmethod
def get_instance(database_url: str, **kwargs):
def get_instance(database_url: str, **kwargs: dict) -> Alchemical:
if DatabaseManager.__instance is None:
DatabaseManager(database_url, **kwargs)
return DatabaseManager.__instance

View File

@ -10,6 +10,7 @@ from PyQt6.QtWidgets import (
QListWidgetItem,
QMainWindow,
QTableWidgetItem,
QWidget,
)
# Third party imports
@ -39,10 +40,10 @@ class ReplaceFilesDialog(QDialog):
self,
session: Session,
main_window: QMainWindow,
*args,
**kwargs,
*args: Qt.WindowType,
**kwargs: Qt.WindowType,
) -> None:
super().__init__(*args, **kwargs)
super().__init__(main_window, *args, **kwargs)
self.session = session
self.main_window = main_window
self.ui = dlg_replace_files_ui.Ui_Dialog()
@ -232,18 +233,19 @@ class TrackSelectDialog(QDialog):
def __init__(
self,
parent: QMainWindow,
session: Session,
new_row_number: int,
source_model: PlaylistModel,
add_to_header: Optional[bool] = False,
*args,
**kwargs,
*args: Qt.WindowType,
**kwargs: Qt.WindowType,
) -> None:
"""
Subclassed QDialog to manage track selection
"""
super().__init__(*args, **kwargs)
super().__init__(parent, *args, **kwargs)
self.session = session
self.new_row_number = new_row_number
self.source_model = source_model

View File

@ -2,12 +2,12 @@
import urllib.parse
import datetime as dt
from slugify import slugify # type: ignore
from typing import Dict
from typing import Dict, Optional
# PyQt imports
from PyQt6.QtCore import QUrl # type: ignore
from PyQt6.QtCore import QUrl
from PyQt6.QtWebEngineWidgets import QWebEngineView
from PyQt6.QtWidgets import QTabWidget
from PyQt6.QtWidgets import QTabWidget, QWidget
# Third party imports
@ -22,7 +22,7 @@ class InfoTabs(QTabWidget):
Class to manage info tabs
"""
def __init__(self, parent=None) -> None:
def __init__(self, parent: Optional[QWidget] = None) -> None:
super().__init__(parent)
self.signals = MusicMusterSignals()

View File

@ -19,7 +19,7 @@ from config import Config
class LevelTagFilter(logging.Filter):
"""Add leveltag"""
def filter(self, record: logging.LogRecord):
def filter(self, record: logging.LogRecord) -> bool:
# Extract the first character of the level name
record.leveltag = record.levelname[0]

View File

@ -110,7 +110,7 @@ class Playdates(dbtables.PlaydatesTable):
@staticmethod
def last_playdates(
session: Session, track_id: int, limit=5
session: Session, track_id: int, limit: int = 5
) -> Sequence["Playdates"]:
"""
Return a list of the last limit playdates for this track, sorted
@ -143,7 +143,7 @@ class Playdates(dbtables.PlaydatesTable):
return Config.EPOCH # pragma: no cover
@staticmethod
def last_played_tracks(session: Session, limit=5) -> Sequence["Playdates"]:
def last_played_tracks(session: Session, limit: int = 5) -> Sequence["Playdates"]:
"""
Return a list of the last limit tracks played, sorted
earliest to latest.
@ -628,7 +628,7 @@ class Tracks(dbtables.TracksTable):
raise ValueError(error)
@classmethod
def get_all(cls, session) -> List["Tracks"]:
def get_all(cls, session: Session) -> Sequence["Tracks"]:
"""Return a list of all tracks"""
return session.scalars(select(cls)).unique().all()

View File

@ -37,6 +37,7 @@ from PyQt6.QtWidgets import (
QListWidgetItem,
QMainWindow,
QMessageBox,
QWidget,
)
# Third party imports
@ -257,7 +258,7 @@ class PreviewManager:
class Window(QMainWindow, Ui_MainWindow):
def __init__(self, parent=None, *args, **kwargs) -> None:
def __init__(self, parent: Optional[QWidget] = None, *args: list, **kwargs: dict) -> None:
super().__init__(parent)
self.setupUi(self)
@ -866,6 +867,7 @@ class Window(QMainWindow, Ui_MainWindow):
)
with db.Session() as session:
dlg = TrackSelectDialog(
parent=self,
session=session,
new_row_number=new_row_number,
source_model=self.active_proxy_model(),

View File

@ -70,6 +70,7 @@ Released under terms of the GNU General Public License version 2:
"""
from io import TextIOWrapper
import os
import sys
import threading
@ -77,6 +78,7 @@ import time
import errno
import argparse
from typing import Optional
if sys.version_info[0] < 3:
raise RuntimeError("PipeClient Error: Python 3.x required")
@ -135,11 +137,11 @@ class PipeClient:
self.__dict__ = cls._shared_state
return self
def __init__(self):
self.timer: bool = False # type: ignore
self._start_time: float = 0 # type: ignore
self._write_pipe = None
self.reply: str = "" # type: ignore
def __init__(self) -> None:
self.timer: bool = False
self._start_time: float = 0
self._write_pipe: Optional[TextIOWrapper] = None
self.reply: str = ""
if not self._write_pipe:
self._write_thread_start()
self._read_thread_start()
@ -166,7 +168,7 @@ class PipeClient:
read_thread.daemon = True
read_thread.start()
def write(self, command, timer=False) -> None:
def write(self, command: str, timer: Optional[bool] = False) -> None:
"""Write a command to _write_pipe.
Parameters
@ -181,7 +183,13 @@ class PipeClient:
write("GetInfo: Type=Labels", timer=True):
"""
self.timer = timer
# If write pipe not defined, return
if self._write_pipe is None:
return
if timer:
self.timer = timer
self._write_pipe.write(command + EOL)
# Check that read pipe is alive
if PipeClient.reader_pipe_broken.is_set():
@ -240,7 +248,7 @@ class PipeClient:
return self.reply
def bool_from_string(strval) -> bool:
def bool_from_string(strval: str) -> bool:
"""Return boolean value from string"""
if strval.lower() in ("true", "t", "1", "yes", "y"):
return True

View File

@ -12,6 +12,7 @@ import re
from PyQt6.QtCore import (
QAbstractTableModel,
QModelIndex,
QObject,
QRegularExpression,
QSortFilterProxyModel,
Qt,
@ -113,9 +114,9 @@ class PlaylistModel(QAbstractTableModel):
def __init__(
self,
playlist_id: int,
*args,
**kwargs,
):
*args: Optional[QObject],
**kwargs: Optional[QObject],
) -> None:
log.debug(f"PlaylistModel.__init__({playlist_id=})")
self.playlist_id = playlist_id
@ -309,7 +310,7 @@ class PlaylistModel(QAbstractTableModel):
session.commit()
def data(self, index: QModelIndex, role: int = Qt.ItemDataRole.DisplayRole):
def data(self, index: QModelIndex, role: int = Qt.ItemDataRole.DisplayRole) -> QVariant:
"""Return data to view"""
if not index.isValid() or not (0 <= index.row() < len(self.playlist_rows)):
@ -330,7 +331,7 @@ class PlaylistModel(QAbstractTableModel):
}
if role in dispatch_table:
return dispatch_table[role](row, column, prd)
return QVariant(dispatch_table[role](row, column, prd))
# Document other roles but don't use them
if role in [
@ -1081,7 +1082,7 @@ class PlaylistModel(QAbstractTableModel):
# Update display
self.invalidate_row(track_sequence.previous.row_number)
def refresh_data(self, session: db.session):
def refresh_data(self, session: db.session) -> None:
"""Populate dicts for data calls"""
# Populate self.playlist_rows with playlist data
@ -1500,9 +1501,9 @@ class PlaylistProxyModel(QSortFilterProxyModel):
def __init__(
self,
source_model: PlaylistModel,
*args,
**kwargs,
):
*args: QObject,
**kwargs: QObject,
) -> None:
self.source_model = source_model
super().__init__(*args, **kwargs)

View File

@ -60,7 +60,7 @@ class EscapeDelegate(QStyledItemDelegate):
- checks with user before abandoning edit on Escape
"""
def __init__(self, parent, source_model: PlaylistModel) -> None:
def __init__(self, parent: QWidget, source_model: PlaylistModel) -> None:
super().__init__(parent)
self.source_model = source_model
self.signals = MusicMusterSignals()
@ -70,7 +70,7 @@ class EscapeDelegate(QStyledItemDelegate):
parent: Optional[QWidget],
option: QStyleOptionViewItem,
index: QModelIndex,
):
) -> Optional[QWidget]:
"""
Intercept createEditor call and make row just a little bit taller
"""
@ -378,6 +378,7 @@ class PlaylistTab(QTableView):
with db.Session() as session:
dlg = TrackSelectDialog(
parent=self.musicmuster,
session=session,
new_row_number=model_row_number,
source_model=self.source_model,

View File

@ -113,7 +113,7 @@ class _FadeCurve:
if self.curve:
self.curve.setPen(Config.FADE_CURVE_FOREGROUND)
def tick(self, play_time) -> None:
def tick(self, play_time: int) -> None:
"""Update volume fade curve"""
if not self.GraphWidget:
@ -136,10 +136,10 @@ class _FadeCurve:
class _FadeTrack(QRunnable):
def __init__(self, player: vlc.MediaPlayer, fade_seconds) -> None:
def __init__(self, player: vlc.MediaPlayer, fade_seconds: int) -> None:
super().__init__()
self.player: vlc.MediaPlayer = player
self.fade_seconds: int = fade_seconds
self.player = player
self.fade_seconds = fade_seconds
def run(self) -> None:
"""
@ -172,11 +172,11 @@ class _Music:
Manage the playing of music tracks
"""
def __init__(self, name) -> None:
def __init__(self, name: str) -> None:
self.VLC = vlc.Instance()
self.VLC.set_user_agent(name, name)
self.player: Optional[vlc.MediaPlayer] = None
self.name: str = name
self.name = name
self.max_volume: int = Config.VLC_VOLUME_DEFAULT
self.start_dt: Optional[dt.datetime] = None

View File

@ -16,7 +16,7 @@ from log import log
from models import Tracks
def check_db(session: Session):
def check_db(session: Session) -> None:
"""
Database consistency check.
@ -84,7 +84,7 @@ def check_db(session: Session):
print("There were more paths than listed that were not found")
def update_bitrates(session: Session):
def update_bitrates(session: Session) -> None:
"""
Update bitrates on all tracks in database
"""

View File

@ -52,6 +52,9 @@ build-backend = "poetry.core.masonry.api"
[tool.mypy]
mypy_path = "/home/kae/git/musicmuster/app"
explicit_package_bases = true
python_version = 3.11
warn_unused_configs = true
disallow_incomplete_defs = true
[tool.pytest.ini_options]
addopts = "--exitfirst --showlocals --capture=no"