Tighter mypy testing, fixed up type hints
This commit is contained in:
parent
2394327d38
commit
5f3119be1f
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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]
|
||||
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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(),
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
"""
|
||||
|
||||
@ -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"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user