Closes #35: Implemented logging
This commit is contained in:
@@ -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)
|
||||||
|
@@ -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:
|
||||||
|
@@ -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):
|
||||||
|
@@ -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
|
||||||
|
@@ -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)
|
||||||
|
@@ -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(
|
||||||
|
@@ -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,
|
||||||
|
@@ -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)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user