File header, type hints, Black

This commit is contained in:
Keith Edmunds 2024-06-22 21:51:41 +01:00
parent 0cd5d97405
commit 3831ebb01d
13 changed files with 65 additions and 84 deletions

View File

@ -1,8 +1,15 @@
# Standard library imports
import datetime as dt import datetime as dt
import logging import logging
import os import os
from typing import List, Optional from typing import List, Optional
# PyQt imports
# Third party imports
# App imports
class Config(object): class Config(object):
AUDACITY_TIMEOUT_TENTHS = 100 AUDACITY_TIMEOUT_TENTHS = 100

View File

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

View File

@ -4,6 +4,7 @@ import os
# PyQt imports # PyQt imports
from PyQt6.QtCore import QEvent, Qt from PyQt6.QtCore import QEvent, Qt
from PyQt6.QtGui import QKeyEvent
from PyQt6.QtWidgets import ( from PyQt6.QtWidgets import (
QDialog, QDialog,
QListWidgetItem, QListWidgetItem,
@ -28,8 +29,7 @@ from helpers import (
from log import log from log import log
from models import db, Settings, Tracks from models import db, Settings, Tracks
from playlistmodel import PlaylistModel from playlistmodel import PlaylistModel
from ui import dlg_TrackSelect_ui from ui import dlg_TrackSelect_ui, dlg_replace_files_ui
from ui import dlg_replace_files_ui
class ReplaceFilesDialog(QDialog): class ReplaceFilesDialog(QDialog):
@ -386,7 +386,7 @@ class TrackSelectDialog(QDialog):
event.accept() event.accept()
def keyPressEvent(self, event): def keyPressEvent(self, event: QKeyEvent) -> None:
""" """
Clear selection on ESC if there is one Clear selection on ESC if there is one
""" """

View File

@ -1,3 +1,4 @@
# Standard library imports
import datetime as dt import datetime as dt
from email.message import EmailMessage from email.message import EmailMessage
from typing import Any, Dict, Optional from typing import Any, Dict, Optional
@ -9,15 +10,20 @@ import smtplib
import ssl import ssl
import tempfile import tempfile
# PyQt imports
from PyQt6.QtWidgets import QMainWindow, QMessageBox
# Third party imports
from mutagen.flac import FLAC # type: ignore from mutagen.flac import FLAC # type: ignore
from mutagen.mp3 import MP3 # type: ignore from mutagen.mp3 import MP3 # type: ignore
from pydub import AudioSegment, effects from pydub import AudioSegment, effects
from pydub.utils import mediainfo from pydub.utils import mediainfo
from PyQt6.QtWidgets import QMainWindow, QMessageBox
from tinytag import TinyTag # type: ignore from tinytag import TinyTag # type: ignore
# App imports
from config import Config from config import Config
from log import log from log import log
from models import Tracks
start_time_re = re.compile(r"@\d\d:\d\d") start_time_re = re.compile(r"@\d\d:\d\d")
@ -266,7 +272,7 @@ def ms_to_mmss(
return f"{sign}{minutes:.0f}:{seconds:02.{decimals}f}" return f"{sign}{minutes:.0f}:{seconds:02.{decimals}f}"
def normalise_track(path): def normalise_track(path: str) -> None:
"""Normalise track""" """Normalise track"""
# Check type # Check type
@ -319,7 +325,7 @@ def normalise_track(path):
os.remove(temp_path) os.remove(temp_path)
def send_mail(to_addr, from_addr, subj, body): def send_mail(to_addr: str, from_addr: str, subj: str, body: str) -> None:
# From https://docs.python.org/3/library/email.examples.html # From https://docs.python.org/3/library/email.examples.html
# Create a text/plain message # Create a text/plain message
@ -345,7 +351,7 @@ def send_mail(to_addr, from_addr, subj, body):
s.quit() s.quit()
def set_track_metadata(track): def set_track_metadata(track: Tracks) -> None:
"""Set/update track metadata in database""" """Set/update track metadata in database"""
audio_metadata = get_audio_metadata(track.path) audio_metadata = get_audio_metadata(track.path)

View File

@ -1,13 +1,18 @@
# Standard library imports
import urllib.parse import urllib.parse
import datetime as dt import datetime as dt
from slugify import slugify # type: ignore from slugify import slugify # type: ignore
from typing import Dict from typing import Dict
# PyQt imports
from PyQt6.QtCore import QUrl # type: ignore from PyQt6.QtCore import QUrl # type: ignore
from PyQt6.QtWebEngineWidgets import QWebEngineView from PyQt6.QtWebEngineWidgets import QWebEngineView
from PyQt6.QtWidgets import QTabWidget from PyQt6.QtWidgets import QTabWidget
from config import Config
# Third party imports
# App imports
from config import Config
from classes import MusicMusterSignals from classes import MusicMusterSignals
from log import log from log import log
@ -34,7 +39,7 @@ class InfoTabs(QTabWidget):
self.last_update[widget] = dt.datetime.now() self.last_update[widget] = dt.datetime.now()
_ = self.addTab(widget, "") _ = self.addTab(widget, "")
def open_in_songfacts(self, title): def open_in_songfacts(self, title: str) -> None:
"""Search Songfacts for title""" """Search Songfacts for title"""
slug = slugify(title, replacements=([["'", ""]])) slug = slugify(title, replacements=([["'", ""]]))
@ -43,7 +48,7 @@ class InfoTabs(QTabWidget):
self.open_tab(url, title) self.open_tab(url, title)
def open_in_wikipedia(self, title): def open_in_wikipedia(self, title: str) -> None:
"""Search Wikipedia for title""" """Search Wikipedia for title"""
str = urllib.parse.quote_plus(title) str = urllib.parse.quote_plus(title)

View File

@ -1,13 +1,18 @@
#!/usr/bin/python3 #!/usr/bin/python3
# Standard library imports
import colorlog
import logging import logging
import logging.handlers import logging.handlers
import os import os
import stackprinter # type: ignore
import sys import sys
from traceback import print_exception from traceback import print_exception
# PyQt imports
# Third party imports
import colorlog
import stackprinter # type: ignore
# App imports
from config import Config from config import Config

View File

@ -1044,6 +1044,7 @@ class Window(QMainWindow, Ui_MainWindow):
if self.btnPreview.isChecked(): if self.btnPreview.isChecked():
# Get track_id for first selected track if there is one # Get track_id for first selected track if there is one
track_id = None
row_number_and_track_id = self.active_tab().get_selected_row_and_track_id() row_number_and_track_id = self.active_tab().get_selected_row_and_track_id()
if row_number_and_track_id: if row_number_and_track_id:
row_number, track_id = row_number_and_track_id row_number, track_id = row_number_and_track_id

View File

@ -1,8 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from log import log
"""Automate Audacity via mod-script-pipe. """Automate Audacity via mod-script-pipe.
Pipe Client may be used as a command-line script to send commands to Pipe Client may be used as a command-line script to send commands to

View File

@ -1141,14 +1141,14 @@ class PlaylistModel(QAbstractTableModel):
# Check the track_sequence next, current and previous plrs and # Check the track_sequence next, current and previous plrs and
# update the row number # update the row number
with db.Session() as session: with db.Session() as session:
for ts in [track_sequence.next, track_sequence.current, track_sequence.previous]: for ts in [
track_sequence.next,
track_sequence.current,
track_sequence.previous,
]:
if ts and ts.row_number: if ts and ts.row_number:
plr = session.get(PlaylistRows, ts.plr_id) plr = session.get(PlaylistRows, ts.plr_id)
if plr and plr.plr_rownum != ts.row_number: if plr and plr.plr_rownum != ts.row_number:
log.error(
"reset_track_sequence_row_numbers: "
f"from {ts=} to {plr.plr_rownum=}"
)
ts.row_number = plr.plr_rownum ts.row_number = plr.plr_rownum
self.update_track_times() self.update_track_times()

View File

@ -1,54 +0,0 @@
#!/usr/bin/env python
#
# Script to manage renaming existing files in given directory and
# propagating that change to database. Typical usage: renaming files
# from 'title.mp3' to title - artist.mp3'
#
# Actions:
#
# - record all filenames and inode numbers
# - external: rename the files
# - update records with new filenames for each inode number
# - update external database with new paths
import os
import sqlite3
PHASE = 2
# Check file of same name exists in parent directory
source_dir = '/home/kae/tmp/Singles' # os.getcwd()
db = "/home/kae/tmp/singles.sqlite"
def main():
with sqlite3.connect(db) as connection:
cursor = connection.cursor()
if PHASE == 1:
cursor.execute(
"CREATE TABLE IF NOT EXISTS mp3s "
"(inode INTEGER, oldname TEXT, newname TEXT)"
)
for fname in os.listdir(source_dir):
fullpath = os.path.join(source_dir, fname)
inode = os.stat(fullpath).st_ino
sql = f'INSERT INTO mp3s VALUES ({inode}, "{fname}", "")'
cursor.execute(sql)
if PHASE == 2:
for fname in os.listdir(source_dir):
fullpath = os.path.join(source_dir, fname)
inode = os.stat(fullpath).st_ino
sql = (
f'UPDATE mp3s SET newname = "{fname}" WHERE inode={inode}'
)
try:
cursor.execute(sql)
except sqlite3.OperationalError:
print(f"Error with {inode} -> {fname}")
cursor.close()
main()

View File

@ -47,14 +47,14 @@ class _AddFadeCurve(QObject):
track_path: str, track_path: str,
track_fade_at: int, track_fade_at: int,
track_silence_at: int, track_silence_at: int,
): ) -> None:
super().__init__() super().__init__()
self.track_manager = track_manager self.track_manager = track_manager
self.track_path = track_path self.track_path = track_path
self.track_fade_at = track_fade_at self.track_fade_at = track_fade_at
self.track_silence_at = track_silence_at self.track_silence_at = track_silence_at
def run(self): def run(self) -> None:
""" """
Create fade curve and add to PlaylistTrack object Create fade curve and add to PlaylistTrack object
""" """
@ -102,7 +102,7 @@ class _FadeCurve:
if self.GraphWidget: if self.GraphWidget:
self.GraphWidget.clear() self.GraphWidget.clear()
def plot(self): def plot(self) -> None:
self.curve = self.GraphWidget.plot(self.graph_array) self.curve = self.GraphWidget.plot(self.graph_array)
self.curve.setPen(Config.FADE_CURVE_FOREGROUND) self.curve.setPen(Config.FADE_CURVE_FOREGROUND)
@ -328,7 +328,7 @@ class _Music:
if self.player: if self.player:
self.player.set_position(position) self.player.set_position(position)
def set_volume(self, volume=None, set_default=True) -> None: def set_volume(self, volume: Optional[int] = None, set_default: bool = True) -> None:
"""Set maximum volume used for player""" """Set maximum volume used for player"""
if not self.player: if not self.player:

View File

@ -1,7 +1,13 @@
#!/usr/bin/env python #!/usr/bin/env python
# # Standard library imports
import os import os
# PyQt imports
# Third party imports
from sqlalchemy.orm.session import Session
# App imports
from config import Config from config import Config
from helpers import ( from helpers import (
get_tags, get_tags,
@ -10,7 +16,7 @@ from log import log
from models import Tracks from models import Tracks
def check_db(session): def check_db(session: Session):
""" """
Database consistency check. Database consistency check.
@ -78,7 +84,7 @@ def check_db(session):
print("There were more paths than listed that were not found") print("There were more paths than listed that were not found")
def update_bitrates(session): def update_bitrates(session: Session):
""" """
Update bitrates on all tracks in database Update bitrates on all tracks in database
""" """

7
file_header.txt Normal file
View File

@ -0,0 +1,7 @@
# Standard library imports
# PyQt imports
# Third party imports
# App imports