File header, type hints, Black
This commit is contained in:
parent
0cd5d97405
commit
3831ebb01d
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
11
app/log.py
11
app/log.py
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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()
|
||||||
|
|||||||
@ -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()
|
|
||||||
@ -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:
|
||||||
|
|||||||
@ -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
7
file_header.txt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# Standard library imports
|
||||||
|
|
||||||
|
# PyQt imports
|
||||||
|
|
||||||
|
# Third party imports
|
||||||
|
|
||||||
|
# App imports
|
||||||
Loading…
Reference in New Issue
Block a user