Closes #35: Implemented logging

This commit is contained in:
Sumner Evans
2020-01-20 14:33:54 -07:00
parent 07f8d81509
commit 072a8319b4
8 changed files with 100 additions and 43 deletions

View File

@@ -1,13 +1,50 @@
#! /usr/bin/env python3 #! /usr/bin/env python3
import sys import argparse
import logging
import gi import gi
gi.require_version('Gtk', '3.0') gi.require_version('Gtk', '3.0')
from gi.repository import Gtk # noqa: F401 from gi.repository import Gtk # noqa: F401
import sublime
from .app import SublimeMusicApp from .app import SublimeMusicApp
def main(): def main():
parser = argparse.ArgumentParser(description='Sublime Music')
parser.add_argument(
'-v',
'--version',
help='show version and exit',
action='store_true',
)
parser.add_argument(
'-l',
'--logfile',
help='the filename to send logs to',
)
parser.add_argument(
'-m',
'--loglevel',
help='the minium level of logging to do',
default='WARNING',
)
args, unknown_args = parser.parse_known_args()
if args.version:
print(f'Sublime Music v{sublime.__version__}')
return
min_log_level = getattr(logging, args.loglevel.upper(), None)
if not isinstance(min_log_level, int):
logging.error(f'Invalid log level: {args.loglevel.upper()}.')
min_log_level = logging.WARNING
logging.basicConfig(
filename=args.logfile,
level=min_log_level,
format='%(asctime)s:%(levelname)s:%(name)s:%(module)s:%(message)s',
)
app = SublimeMusicApp() app = SublimeMusicApp()
app.run(sys.argv) app.run(unknown_args)

View File

@@ -1,4 +1,5 @@
import os import os
import logging
import math import math
import random import random
@@ -381,7 +382,8 @@ class SublimeMusicApp(Gtk.Application):
} }
method = method_call_map.get(interface, {}).get(method) method = method_call_map.get(interface, {}).get(method)
if method is None: if method is None:
print(f'Unknown/unimplemented method: {interface}.{method}') logging.warning(
f'Unknown/unimplemented method: {interface}.{method}.')
invocation.return_value(method(*params) if callable(method) else None) invocation.return_value(method(*params) if callable(method) else None)
def on_dbus_set_property( def on_dbus_set_property(
@@ -416,7 +418,7 @@ class SublimeMusicApp(Gtk.Application):
setter = setter_map.get(interface).get(property_name) setter = setter_map.get(interface).get(property_name)
if setter is None: if setter is None:
print('Set: Unknown property:', setter) logging.warning('Set: Unknown property: {property_name}.')
return return
if callable(setter): if callable(setter):
setter(value) setter(value)
@@ -883,10 +885,9 @@ class SublimeMusicApp(Gtk.Application):
cover_art_future.add_done_callback( cover_art_future.add_done_callback(
lambda f: on_cover_art_download_complete(f.result())) lambda f: on_cover_art_download_complete(f.result()))
except Exception: except Exception:
print( logging.warning(
'Unable to display notification.', 'Unable to display notification. Is a notification '
'Is a notification daemon running?', 'daemon running?')
)
def on_song_download_complete(song_id): def on_song_download_complete(song_id):
if self.state.current_song.id != song.id: if self.state.current_song.id != song.id:

View File

@@ -1,4 +1,5 @@
import os import os
import logging
import glob import glob
import itertools import itertools
import threading import threading
@@ -227,9 +228,9 @@ class CacheManager(metaclass=Singleton):
@staticmethod @staticmethod
def shutdown(): def shutdown():
CacheManager.should_exit = True CacheManager.should_exit = True
print('Shutdown start') logging.info('CacheManager shutdown start')
CacheManager.executor.shutdown() CacheManager.executor.shutdown()
print('Shutdown complete') logging.info('CacheManager shutdown complete')
@staticmethod @staticmethod
def calculate_server_hash(server: Optional[ServerConfiguration]): def calculate_server_hash(server: Optional[ServerConfiguration]):
@@ -402,7 +403,7 @@ class CacheManager(metaclass=Singleton):
self.current_downloads.add(abs_path_str) self.current_downloads.add(abs_path_str)
if resource_downloading: if resource_downloading:
print(abs_path, 'already being downloaded.') logging.info(f'{abs_path} already being downloaded.')
# The resource is already being downloaded. Busy loop until # The resource is already being downloaded. Busy loop until
# it has completed. Then, just return the path to the # it has completed. Then, just return the path to the
# resource. # resource.
@@ -411,7 +412,7 @@ class CacheManager(metaclass=Singleton):
while abs_path_str in self.current_downloads: while abs_path_str in self.current_downloads:
sleep(0.2) sleep(0.2)
else: else:
print(abs_path, 'not found. Downloading...') logging.info(f'{abs_path} not found. Downloading...')
os.makedirs(download_path.parent, exist_ok=True) os.makedirs(download_path.parent, exist_ok=True)
self.save_file(download_path, download_fn()) self.save_file(download_path, download_fn())
@@ -421,7 +422,7 @@ class CacheManager(metaclass=Singleton):
if download_path.exists(): if download_path.exists():
shutil.move(download_path, abs_path) shutil.move(download_path, abs_path)
print(abs_path, 'downloaded. Returning.') logging.info(f'{abs_path} downloaded. Returning.')
return abs_path_str return abs_path_str
def after_download(path: str): def after_download(path: str):

View File

@@ -1,3 +1,4 @@
import logging
import math import math
import os import os
@@ -93,10 +94,10 @@ class Server:
# def _get(self, url, timeout=(3.05, 2), **params): # def _get(self, url, timeout=(3.05, 2), **params):
def _get(self, url, **params): def _get(self, url, **params):
params = {**self._get_params(), **params} params = {**self._get_params(), **params}
print(f'[START] get: {url}') logging.info(f'[START] get: {url}')
if os.environ.get('SUBLIME_MUSIC_DEBUG_DELAY'): if os.environ.get('SUBLIME_MUSIC_DEBUG_DELAY'):
print( logging.info(
"SUBLIME_MUSIC_DEBUG_DELAY enabled. Pausing for", "SUBLIME_MUSIC_DEBUG_DELAY enabled. Pausing for",
f"{os.environ['SUBLIME_MUSIC_DEBUG_DELAY']} seconds.", f"{os.environ['SUBLIME_MUSIC_DEBUG_DELAY']} seconds.",
) )
@@ -117,7 +118,7 @@ class Server:
if result.status_code != 200: if result.status_code != 200:
raise Exception(f'[FAIL] get: {url} status={result.status_code}') raise Exception(f'[FAIL] get: {url} status={result.status_code}')
print(f'[FINISH] get: {url}') logging.info(f'[FINISH] get: {url}')
return result return result
def _get_json( def _get_json(
@@ -156,7 +157,6 @@ class Server:
return response return response
def do_download(self, url, **params) -> bytes: def do_download(self, url, **params) -> bytes:
print('download', url)
download = self._get(url, **params) download = self._get(url, **params)
if 'json' in download.headers.get('Content-Type'): if 'json' in download.headers.get('Content-Type'):
# TODO make better # TODO make better

View File

@@ -1,3 +1,5 @@
import logging
import gi import gi
from typing import Union from typing import Union
@@ -111,9 +113,9 @@ class AlbumsPanel(Gtk.Box):
return combo return combo
def populate_genre_combo( def populate_genre_combo(
self, self,
state: ApplicationState, state: ApplicationState,
force: bool = False, force: bool = False,
): ):
if not CacheManager.ready(): if not CacheManager.ready():
return return
@@ -223,7 +225,8 @@ class AlbumsPanel(Gtk.Box):
year = int(entry.get_text()) year = int(entry.get_text())
except Exception: except Exception:
# TODO prevent input of non-numerals # TODO prevent input of non-numerals
print('failed, should do something to prevent non-numeric input') logging.error(
'failed, should do something to prevent non-numeric input')
return return
if self.to_year_entry == entry: if self.to_year_entry == entry:
@@ -301,12 +304,12 @@ class AlbumsGrid(Gtk.Overlay):
server_hash = None server_hash = None
def update_params( def update_params(
self, self,
type_: str = None, type_: str = None,
alphabetical_type: str = None, alphabetical_type: str = None,
from_year: int = None, from_year: int = None,
to_year: int = None, to_year: int = None,
genre: str = None, genre: str = None,
): ):
self.type_ = type_ or self.type_ self.type_ = type_ or self.type_
self.alphabetical_type = alphabetical_type or self.alphabetical_type self.alphabetical_type = alphabetical_type or self.alphabetical_type
@@ -386,10 +389,10 @@ class AlbumsGrid(Gtk.Overlay):
self.add_overlay(self.spinner) self.add_overlay(self.spinner)
def update( def update(
self, self,
state: ApplicationState, state: ApplicationState,
force: bool = False, force: bool = False,
selected_id: str = None, selected_id: str = None,
): ):
new_hash = CacheManager.calculate_server_hash(state.config.server) new_hash = CacheManager.calculate_server_hash(state.config.server)
if self.server_hash != new_hash: if self.server_hash != new_hash:
@@ -562,9 +565,9 @@ class AlbumsGrid(Gtk.Overlay):
return widget_box return widget_box
def reflow_grids( def reflow_grids(
self, self,
force_reload_from_master=False, force_reload_from_master=False,
selection_changed=False, selection_changed=False,
): ):
# Determine where the cuttoff is between the top and bottom grids. # Determine where the cuttoff is between the top and bottom grids.
entries_before_fold = len(self.list_store) entries_before_fold = len(self.list_store)

View File

@@ -287,8 +287,8 @@ class ArtistDetailPanel(Gtk.Box):
# stuff and un-cache things. # stuff and un-cache things.
@util.async_callback( @util.async_callback(
lambda *a, **k: CacheManager.get_artist(*a, **k), lambda *a, **k: CacheManager.get_artist(*a, **k),
before_download=lambda self: self.set_all_loading(), before_download=lambda self: self.set_all_loading(True),
on_failure=lambda self, e: print('fail a', e), on_failure=lambda self, e: self.set_all_loading(False),
) )
def update_artist_view( def update_artist_view(
self, self,
@@ -382,10 +382,14 @@ class ArtistDetailPanel(Gtk.Box):
# Helper Methods # Helper Methods
# ========================================================================= # =========================================================================
def set_all_loading(self): def set_all_loading(self, loading_state):
self.albums_list.spinner.start() if loading_state:
self.albums_list.spinner.show() self.albums_list.spinner.start()
self.artist_artwork.set_loading(True) self.albums_list.spinner.show()
self.artist_artwork.set_loading(True)
else:
self.albums_list.spinner.hide()
self.artist_artwork.set_loading(False)
def make_label(self, text=None, name=None, **params): def make_label(self, text=None, name=None, **params):
return Gtk.Label( return Gtk.Label(

View File

@@ -1,3 +1,4 @@
import logging
import threading import threading
from uuid import UUID from uuid import UUID
from urllib.parse import urlparse from urllib.parse import urlparse
@@ -248,10 +249,21 @@ class ChromecastPlayer(Player):
def run(self): def run(self):
bottle.run(self.app, host=self.host, port=self.port) bottle.run(self.app, host=self.host, port=self.port)
getting_chromecasts = False
@classmethod @classmethod
def get_chromecasts(cls) -> Future: def get_chromecasts(cls) -> Future:
def do_get_chromecasts(): def do_get_chromecasts():
ChromecastPlayer.chromecasts = pychromecast.get_chromecasts() if not ChromecastPlayer.getting_chromecasts:
logging.info('Getting Chromecasts')
ChromecastPlayer.getting_chromecasts = True
ChromecastPlayer.chromecasts = pychromecast.get_chromecasts()
else:
logging.info('Already getting Chromecasts... busy wait')
while ChromecastPlayer.getting_chromecasts:
sleep(0.1)
ChromecastPlayer.getting_chromecasts = False
return ChromecastPlayer.chromecasts return ChromecastPlayer.chromecasts
return ChromecastPlayer.executor.submit(do_get_chromecasts) return ChromecastPlayer.executor.submit(do_get_chromecasts)
@@ -266,7 +278,7 @@ class ChromecastPlayer(Player):
self.chromecast.register_status_listener( self.chromecast.register_status_listener(
ChromecastPlayer.cast_status_listener) ChromecastPlayer.cast_status_listener)
self.chromecast.wait() self.chromecast.wait()
print(f'Using: {self.chromecast.device.friendly_name}') logging.info(f'Using: {self.chromecast.device.friendly_name}')
def __init__( def __init__(
self, self,

View File

@@ -220,7 +220,6 @@ class PlaylistList(Gtk.Box):
def create_playlist(self, playlist_name): def create_playlist(self, playlist_name):
def on_playlist_created(f): def on_playlist_created(f):
print(f)
CacheManager.invalidate_playlists_cache() CacheManager.invalidate_playlists_cache()
self.update(force=True) self.update(force=True)