From 8972525e73650638ccee5d16c25d8491d7f6ee67 Mon Sep 17 00:00:00 2001 From: Allen Wittenauer Date: Fri, 2 Jun 2023 22:54:57 -0700 Subject: [PATCH] switch yapf to 100 columns (#833) --- .yapfignore | 3 - NowPlaying.spec | 3 +- conftest.py | 13 +- docs/conf.py | 6 +- nowplaying/__main__.py | 3 +- nowplaying/artistextras/__init__.py | 4 +- nowplaying/artistextras/discogs.py | 46 ++-- nowplaying/artistextras/fanarttv.py | 61 ++---- nowplaying/artistextras/theaudiodb.py | 86 +++----- nowplaying/beam/inputs/beam.py | 30 +-- nowplaying/beam/processes/beamsender.py | 57 ++--- nowplaying/bootstrap.py | 10 +- nowplaying/config.py | 80 +++---- nowplaying/db.py | 59 ++--- nowplaying/frozen.py | 3 +- nowplaying/hostmeta.py | 11 +- nowplaying/imagecache.py | 88 +++----- nowplaying/inputs/icecast.py | 21 +- nowplaying/inputs/jsonreader.py | 8 +- nowplaying/inputs/m3u.py | 27 +-- nowplaying/inputs/mpris2.py | 6 +- nowplaying/inputs/serato.py | 120 ++++------- nowplaying/inputs/traktor.py | 60 ++---- nowplaying/inputs/virtualdj.py | 58 ++--- nowplaying/inputs/winmedia.py | 17 +- nowplaying/metadata.py | 152 +++++-------- nowplaying/musicbrainz.py | 127 +++++------ nowplaying/pluginimporter.py | 1 + nowplaying/processes/discordbot.py | 26 +-- nowplaying/processes/obsws.py | 16 +- nowplaying/processes/trackpoll.py | 162 ++++++-------- nowplaying/processes/twitchbot.py | 10 +- nowplaying/processes/webserver.py | 124 ++++------- nowplaying/recognition/__init__.py | 4 +- nowplaying/recognition/acoustidmb.py | 165 ++++++-------- nowplaying/settingsui.py | 273 +++++++++--------------- nowplaying/subprocesses.py | 7 +- nowplaying/systemtray.py | 28 +-- nowplaying/textoutput.py | 6 +- nowplaying/trackrequests.py | 214 +++++++------------ nowplaying/twitch/__init__.py | 36 ++-- nowplaying/twitch/chat.py | 151 +++++-------- nowplaying/twitch/redemptions.py | 47 ++-- nowplaying/twitch/utils.py | 35 +-- nowplaying/uihelp.py | 6 +- nowplaying/upgrade.py | 55 ++--- nowplaying/upgradeutils.py | 13 +- nowplaying/utils.py | 13 +- pyproject.toml | 17 +- test_settingsui.py | 22 +- tests-qt/test_settingsui.py | 3 +- tests/test_acoustidmb.py | 36 +--- tests/test_artistextras.py | 72 +++---- tests/test_config.py | 10 +- tests/test_db.py | 17 +- tests/test_imagecache.py | 34 +-- tests/test_m3u.py | 71 ++---- tests/test_metadata.py | 185 ++++++++-------- tests/test_musicbrainz.py | 62 ++---- tests/test_serato.py | 21 +- tests/test_templatehandler.py | 3 +- tests/test_trackpoll.py | 24 +-- tests/test_trackrequests.py | 98 ++++----- tests/test_upgradetemplates.py | 8 +- tests/test_upgradeutils.py | 3 +- tests/test_utils.py | 3 +- tests/test_virtualdj.py | 110 +++------- tests/test_webserver.py | 28 +-- tests/upgrade/test_300.py | 6 +- tests/upgrade/test_noconfig.py | 4 +- updateshas.py | 3 +- 71 files changed, 1207 insertions(+), 2184 deletions(-) delete mode 100644 .yapfignore diff --git a/.yapfignore b/.yapfignore deleted file mode 100644 index 169578ef..00000000 --- a/.yapfignore +++ /dev/null @@ -1,3 +0,0 @@ -nowplaying/version.py -nowplaying/vendor/ -nowplaying/qtrc.py diff --git a/NowPlaying.spec b/NowPlaying.spec index 96681c84..61e99f11 100644 --- a/NowPlaying.spec +++ b/NowPlaying.spec @@ -117,8 +117,7 @@ for execname, execpy in executables.items(): binaries=[], datas=[('nowplaying/resources/*', 'resources/'), ('nowplaying/templates/*', 'templates/')], - hiddenimports=ARTEXTRAS_MODULES + INPUT_MODULES + - RECOGNITION_MODULES, + hiddenimports=ARTEXTRAS_MODULES + INPUT_MODULES + RECOGNITION_MODULES, hookspath=[('nowplaying/__pyinstaller')], runtime_hooks=[], excludes=[], diff --git a/conftest.py b/conftest.py index f6940470..a4fe1166 100755 --- a/conftest.py +++ b/conftest.py @@ -59,9 +59,7 @@ def bootstrap(getroot): # pylint: disable=redefined-outer-name with tempfile.TemporaryDirectory() as newpath: bundledir = pathlib.Path(getroot).joinpath('nowplaying') nowplaying.bootstrap.set_qt_names(domain=DOMAIN, appname='testsuite') - config = nowplaying.config.ConfigFile(bundledir=bundledir, - logpath=newpath, - testmode=True) + config = nowplaying.config.ConfigFile(bundledir=bundledir, logpath=newpath, testmode=True) config.cparser.setValue('acoustidmb/enabled', False) config.cparser.sync() yield config @@ -81,20 +79,17 @@ def clear_old_testsuite(): qsettingsformat = QSettings.NativeFormat nowplaying.bootstrap.set_qt_names(appname='testsuite') - config = QSettings(qsettingsformat, QSettings.SystemScope, - QCoreApplication.organizationName(), + config = QSettings(qsettingsformat, QSettings.SystemScope, QCoreApplication.organizationName(), QCoreApplication.applicationName()) config.clear() config.sync() - cachedir = pathlib.Path( - QStandardPaths.standardLocations(QStandardPaths.CacheLocation)[0]) + cachedir = pathlib.Path(QStandardPaths.standardLocations(QStandardPaths.CacheLocation)[0]) if 'testsuite' in cachedir.name and cachedir.exists(): logging.info('Removing %s', cachedir) shutil.rmtree(cachedir) - config = QSettings(qsettingsformat, QSettings.UserScope, - QCoreApplication.organizationName(), + config = QSettings(qsettingsformat, QSettings.UserScope, QCoreApplication.organizationName(), QCoreApplication.applicationName()) config.clear() config.sync() diff --git a/docs/conf.py b/docs/conf.py index 8624865c..04c13b6e 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -82,8 +82,6 @@ def get_release_data(): extlinks = { 'stabledownloadlink': - (f'{basedownload}/{stablerelease}/NowPlaying-{stablerelease}-%s.zip', - '%s'), - 'rcdownloadlink': - (f'{basedownload}/{rcrelease}/NowPlaying-{rcrelease}-%s.zip', '%s') + (f'{basedownload}/{stablerelease}/NowPlaying-{stablerelease}-%s.zip', '%s'), + 'rcdownloadlink': (f'{basedownload}/{rcrelease}/NowPlaying-{rcrelease}-%s.zip', '%s') } diff --git a/nowplaying/__main__.py b/nowplaying/__main__.py index 972d8156..ce6da9b3 100755 --- a/nowplaying/__main__.py +++ b/nowplaying/__main__.py @@ -66,8 +66,7 @@ def actualmain(beam=False): # pragma: no cover if not nowplaying.bootstrap.verify_python_version(): sys.exit(1) - config = nowplaying.config.ConfigFile(logpath=logpath, - bundledir=bundledir) + config = nowplaying.config.ConfigFile(logpath=logpath, bundledir=bundledir) logging.getLogger().setLevel(config.loglevel) logging.captureWarnings(True) logging.debug('Using pidfile %s/%s', pid.piddir, pid.pidname) diff --git a/nowplaying/artistextras/__init__.py b/nowplaying/artistextras/__init__.py index 9615f2ea..fc9674ce 100755 --- a/nowplaying/artistextras/__init__.py +++ b/nowplaying/artistextras/__init__.py @@ -63,9 +63,7 @@ def calculate_delay(self): ''' determine a reasonable, minimal delay ''' try: - delay = self.config.cparser.value('settings/delay', - type=float, - defaultValue=10.0) + delay = self.config.cparser.value('settings/delay', type=float, defaultValue=10.0) except ValueError: delay = 10.0 diff --git a/nowplaying/artistextras/discogs.py b/nowplaying/artistextras/discogs.py index 5083401e..9847f592 100755 --- a/nowplaying/artistextras/discogs.py +++ b/nowplaying/artistextras/discogs.py @@ -27,8 +27,7 @@ def __init__(self, config=None, qsettings=None): def _find_discogs_releaselist(self, metadata): try: - logging.debug('Fetching %s - %s', metadata['artist'], - metadata['album']) + logging.debug('Fetching %s - %s', metadata['artist'], metadata['album']) resultlist = self.client.search(metadata['album'], artist=metadata['artist'], type='title').page(1) @@ -44,8 +43,8 @@ def _find_discogs_releaselist(self, metadata): return None return next( - (result.artists[0] for result in resultlist if isinstance( - result, nowplaying.vendor.discogs_client.models.Release)), + (result.artists[0] for result in resultlist + if isinstance(result, nowplaying.vendor.discogs_client.models.Release)), None, ) @@ -54,14 +53,12 @@ def download(self, metadata=None, imagecache=None): # pylint: disable=too-many- apikey = self.config.cparser.value('discogs/apikey') - if not apikey or not self.config.cparser.value('discogs/enabled', - type=bool): + if not apikey or not self.config.cparser.value('discogs/enabled', type=bool): return None # discogs basically works by search for a combination of # artist and album so we need both - if not metadata or not metadata.get('artist') or not metadata.get( - 'album'): + if not metadata or not metadata.get('artist') or not metadata.get('album'): logging.debug('artist or album is empty, skipping') return None @@ -69,8 +66,8 @@ def download(self, metadata=None, imagecache=None): # pylint: disable=too-many- if not self.client: delay = self.calculate_delay() - self.client = nowplaying.vendor.discogs_client.Client( - f'whatsnowplaying/{self.version}', user_token=apikey) + self.client = nowplaying.vendor.discogs_client.Client(f'whatsnowplaying/{self.version}', + user_token=apikey) self.client.set_timeout(connect=delay, read=delay) artistresultlist = self._find_discogs_releaselist(metadata) @@ -100,28 +97,23 @@ def download(self, metadata=None, imagecache=None): # pylint: disable=too-many- metadata['artistfanarturls'] = [] for record in artistresultlist.images: - if record['type'] == 'primary' and record.get( - 'uri150') and self.config.cparser.value( - 'discogs/thumbnails', type=bool): + if record['type'] == 'primary' and record.get('uri150') and self.config.cparser.value( + 'discogs/thumbnails', type=bool): imagecache.fill_queue(config=self.config, artist=oldartist, imagetype='artistthumb', urllist=[record['uri150']]) - if record['type'] == 'secondary' and record.get( - 'uri') and self.config.cparser.value( - 'discogs/fanart', type=bool - ) and record['uri'] not in metadata['artistfanarturls']: + if record['type'] == 'secondary' and record.get('uri') and self.config.cparser.value( + 'discogs/fanart', + type=bool) and record['uri'] not in metadata['artistfanarturls']: metadata['artistfanarturls'].append(record['uri']) return metadata def providerinfo(self): # pylint: disable=no-self-use ''' return list of what is provided by this plug-in ''' - return [ - 'artistlongbio', 'artistthumbraw', 'discogs-artistfanarturls', - 'artistwebsites' - ] + return ['artistlongbio', 'artistthumbraw', 'discogs-artistfanarturls', 'artistwebsites'] def connect_settingsui(self, qwidget, uihelp): ''' pass ''' @@ -132,13 +124,11 @@ def load_settingsui(self, qwidget): qwidget.discogs_checkbox.setChecked(True) else: qwidget.discogs_checkbox.setChecked(False) - qwidget.apikey_lineedit.setText( - self.config.cparser.value('discogs/apikey')) + qwidget.apikey_lineedit.setText(self.config.cparser.value('discogs/apikey')) for field in ['bio', 'fanart', 'thumbnails', 'websites']: func = getattr(qwidget, f'{field}_checkbox') - func.setChecked( - self.config.cparser.value(f'discogs/{field}', type=bool)) + func.setChecked(self.config.cparser.value(f'discogs/{field}', type=bool)) def verify_settingsui(self, qwidget): ''' pass ''' @@ -146,10 +136,8 @@ def verify_settingsui(self, qwidget): def save_settingsui(self, qwidget): ''' take the settings page and save it ''' - self.config.cparser.setValue('discogs/enabled', - qwidget.discogs_checkbox.isChecked()) - self.config.cparser.setValue('discogs/apikey', - qwidget.apikey_lineedit.text()) + self.config.cparser.setValue('discogs/enabled', qwidget.discogs_checkbox.isChecked()) + self.config.cparser.setValue('discogs/apikey', qwidget.apikey_lineedit.text()) for field in ['bio', 'fanart', 'thumbnails', 'websites']: func = getattr(qwidget, f'{field}_checkbox') diff --git a/nowplaying/artistextras/fanarttv.py b/nowplaying/artistextras/fanarttv.py index 9c71b33f..85df1dd6 100755 --- a/nowplaying/artistextras/fanarttv.py +++ b/nowplaying/artistextras/fanarttv.py @@ -31,8 +31,7 @@ def _fetch(self, apikey, artistid): try: baseurl = f'http://webservice.fanart.tv/v3/music/{artistid}' logging.debug('fanarttv: calling %s', baseurl) - artistrequest = requests.get(f'{baseurl}?api_key={apikey}', - timeout=delay) + artistrequest = requests.get(f'{baseurl}?api_key={apikey}', timeout=delay) except ( requests.exceptions.ReadTimeout, # pragma: no cover urllib3.exceptions.ReadTimeoutError, @@ -47,8 +46,7 @@ def download(self, metadata=None, imagecache=None): # pylint: disable=too-many- ''' download the extra data ''' apikey = self.config.cparser.value('fanarttv/apikey') - if not apikey or not self.config.cparser.value('fanarttv/enabled', - type=bool): + if not apikey or not self.config.cparser.value('fanarttv/enabled', type=bool): return None if not metadata or not metadata.get('artist'): @@ -63,8 +61,7 @@ def download(self, metadata=None, imagecache=None): # pylint: disable=too-many- return None fnstr = nowplaying.utils.normalize(metadata['artist']) - logging.debug('got musicbrainzartistid: %s', - metadata['musicbrainzartistid']) + logging.debug('got musicbrainzartistid: %s', metadata['musicbrainzartistid']) for artistid in metadata['musicbrainzartistid']: artistrequest = self._fetch(apikey, artistid) if not artistrequest: @@ -72,19 +69,15 @@ def download(self, metadata=None, imagecache=None): # pylint: disable=too-many- artist = artistrequest.json() - if artist.get('name') and nowplaying.utils.normalize( - artist['name']) in fnstr: + if artist.get('name') and nowplaying.utils.normalize(artist['name']) in fnstr: logging.debug("fanarttv Trusting : %s", artist['name']) else: - logging.debug("fanarttv Not trusting: %s vs %s", - artist.get('name'), fnstr) + logging.debug("fanarttv Not trusting: %s vs %s", artist.get('name'), fnstr) continue - if artist.get('musicbanner') and self.config.cparser.value( - 'fanarttv/banners', type=bool): - banner = sorted(artist['musicbanner'], - key=lambda x: x['likes'], - reverse=True) + if artist.get('musicbanner') and self.config.cparser.value('fanarttv/banners', + type=bool): + banner = sorted(artist['musicbanner'], key=lambda x: x['likes'], reverse=True) imagecache.fill_queue(config=self.config, artist=metadata['artist'], imagetype='artistbanner', @@ -93,32 +86,25 @@ def download(self, metadata=None, imagecache=None): # pylint: disable=too-many- if self.config.cparser.value('fanarttv/logos', type=bool): logo = None if artist.get('hdmusiclogo'): - logo = sorted(artist['hdmusiclogo'], - key=lambda x: x['likes'], - reverse=True) + logo = sorted(artist['hdmusiclogo'], key=lambda x: x['likes'], reverse=True) elif artist.get('musiclogo'): - logo = sorted(artist['musiclogo'], - key=lambda x: x['likes'], - reverse=True) + logo = sorted(artist['musiclogo'], key=lambda x: x['likes'], reverse=True) if logo: imagecache.fill_queue(config=self.config, artist=metadata['artist'], imagetype='artistlogo', urllist=[x['url'] for x in logo]) - if artist.get('artistthumb') and self.config.cparser.value( - 'fanarttv/thumbnails', type=bool): - thumbnail = sorted(artist['artistthumb'], - key=lambda x: x['likes'], - reverse=True) + if artist.get('artistthumb') and self.config.cparser.value('fanarttv/thumbnails', + type=bool): + thumbnail = sorted(artist['artistthumb'], key=lambda x: x['likes'], reverse=True) imagecache.fill_queue(config=self.config, artist=metadata['artist'], imagetype='artistthumb', urllist=[x['url'] for x in thumbnail]) - if self.config.cparser.value( - 'fanarttv/fanart', - type=bool) and artist.get('artistbackground'): + if self.config.cparser.value('fanarttv/fanart', + type=bool) and artist.get('artistbackground'): for image in artist['artistbackground']: if not metadata.get('artistfanarturls'): metadata['artistfanarturls'] = [] @@ -128,10 +114,7 @@ def download(self, metadata=None, imagecache=None): # pylint: disable=too-many- def providerinfo(self): # pylint: disable=no-self-use ''' return list of what is provided by this plug-in ''' - return [ - 'artistbannerraw', 'artistlogoraw', 'artistthumbraw', - 'fanarttv-artistfanarturls' - ] + return ['artistbannerraw', 'artistlogoraw', 'artistthumbraw', 'fanarttv-artistfanarturls'] def connect_settingsui(self, qwidget, uihelp): ''' pass ''' @@ -142,13 +125,11 @@ def load_settingsui(self, qwidget): qwidget.fanarttv_checkbox.setChecked(True) else: qwidget.fanarttv_checkbox.setChecked(False) - qwidget.apikey_lineedit.setText( - self.config.cparser.value('fanarttv/apikey')) + qwidget.apikey_lineedit.setText(self.config.cparser.value('fanarttv/apikey')) for field in ['banners', 'logos', 'fanart', 'thumbnails']: func = getattr(qwidget, f'{field}_checkbox') - func.setChecked( - self.config.cparser.value(f'fanarttv/{field}', type=bool)) + func.setChecked(self.config.cparser.value(f'fanarttv/{field}', type=bool)) def verify_settingsui(self, qwidget): ''' pass ''' @@ -156,10 +137,8 @@ def verify_settingsui(self, qwidget): def save_settingsui(self, qwidget): ''' take the settings page and save it ''' - self.config.cparser.setValue('fanarttv/enabled', - qwidget.fanarttv_checkbox.isChecked()) - self.config.cparser.setValue('fanarttv/apikey', - qwidget.apikey_lineedit.text()) + self.config.cparser.setValue('fanarttv/enabled', qwidget.fanarttv_checkbox.isChecked()) + self.config.cparser.setValue('fanarttv/apikey', qwidget.apikey_lineedit.text()) for field in ['banners', 'logos', 'fanart', 'thumbnails']: func = getattr(qwidget, f'{field}_checkbox') diff --git a/nowplaying/artistextras/theaudiodb.py b/nowplaying/artistextras/theaudiodb.py index 47f2ea7e..b33efd78 100755 --- a/nowplaying/artistextras/theaudiodb.py +++ b/nowplaying/artistextras/theaudiodb.py @@ -37,9 +37,7 @@ def _fetch(self, apikey, api): delay = self.calculate_delay() try: logging.debug('Fetching %s', api) - page = requests.get( - f'https://theaudiodb.com/api/v1/json/{apikey}/{api}', - timeout=delay) + page = requests.get(f'https://theaudiodb.com/api/v1/json/{apikey}/{api}', timeout=delay) except ( requests.exceptions.ReadTimeout, # pragma: no cover urllib3.exceptions.ReadTimeoutError, @@ -57,13 +55,11 @@ def _check_artist(self, artdata): for fieldname in ['strArtist', 'strArtistAlternate']: if artdata.get(fieldname) and nowplaying.utils.normalize( artdata[fieldname]) in self.fnstr: - logging.debug('theaudiodb Trusting %s: %s', fieldname, - artdata[fieldname]) + logging.debug('theaudiodb Trusting %s: %s', fieldname, artdata[fieldname]) found = True else: - logging.debug( - 'theaudiodb not Trusting %s vs. %s', self.fnstr, - nowplaying.utils.normalize(artdata.get(fieldname))) + logging.debug('theaudiodb not Trusting %s vs. %s', self.fnstr, + nowplaying.utils.normalize(artdata.get(fieldname))) return found def _handle_extradata(self, extradata, metadata, imagecache): # pylint: disable=too-many-branches @@ -78,18 +74,16 @@ def _handle_extradata(self, extradata, metadata, imagecache): # pylint: disable if not self._check_artist(artdata): continue - if not metadata.get('artistlongbio') and self.config.cparser.value( - 'theaudiodb/bio', type=bool): + if not metadata.get('artistlongbio') and self.config.cparser.value('theaudiodb/bio', + type=bool): if f'strBiography{lang1}' in artdata: bio += self._filter(artdata[f'strBiography{lang1}']) - elif self.config.cparser.value( - 'theaudiodb/bio_iso_en_fallback', - type=bool) and 'strBiographyEN' in artdata: + elif self.config.cparser.value('theaudiodb/bio_iso_en_fallback', + type=bool) and 'strBiographyEN' in artdata: bio += self._filter(artdata['strBiographyEN']) - if self.config.cparser.value( - 'theaudiodb/websites', - type=bool) and artdata.get('strWebsite'): + if self.config.cparser.value('theaudiodb/websites', + type=bool) and artdata.get('strWebsite'): webstr = 'https://' + artdata['strWebsite'] if not metadata.get('artistwebsites'): metadata['artistwebsites'] = [] @@ -97,24 +91,24 @@ def _handle_extradata(self, extradata, metadata, imagecache): # pylint: disable if imagecache: if not metadata.get('artistbannerraw') and artdata.get( - 'strArtistBanner') and self.config.cparser.value( - 'theaudiodb/banners', type=bool): + 'strArtistBanner') and self.config.cparser.value('theaudiodb/banners', + type=bool): imagecache.fill_queue(config=self.config, artist=oldartist, imagetype='artistbanner', urllist=[artdata['strArtistBanner']]) if not metadata.get('artistlogoraw') and artdata.get( - 'strArtistLogo') and self.config.cparser.value( - 'theaudiodb/logos', type=bool): + 'strArtistLogo') and self.config.cparser.value('theaudiodb/logos', + type=bool): imagecache.fill_queue(config=self.config, artist=oldartist, imagetype='artistlogo', urllist=[artdata['strArtistLogo']]) if not metadata.get('artistthumbraw') and artdata.get( - 'strArtistThumb') and self.config.cparser.value( - 'theaudiodb/thumbnails', type=bool): + 'strArtistThumb') and self.config.cparser.value('theaudiodb/thumbnails', + type=bool): imagecache.fill_queue(config=self.config, artist=oldartist, imagetype='artistthumb', @@ -126,8 +120,7 @@ def _handle_extradata(self, extradata, metadata, imagecache): # pylint: disable if artdata.get(artstring): if not metadata.get('artistfanarturls'): metadata['artistfanarturls'] = [] - metadata['artistfanarturls'].append( - artdata[artstring]) + metadata['artistfanarturls'].append(artdata[artstring]) if bio: metadata['artistlongbio'] = bio @@ -153,26 +146,22 @@ def download(self, metadata=None, imagecache=None): # pylint: disable=too-many- self.fnstr = nowplaying.utils.normalize(metadata['artist']) if metadata.get('musicbrainzartistid'): - logging.debug('got musicbrainzartistid: %s', - metadata['musicbrainzartistid']) + logging.debug('got musicbrainzartistid: %s', metadata['musicbrainzartistid']) for mbid in metadata['musicbrainzartistid']: if newdata := self.artistdatafrommbid(apikey, mbid): extradata.extend(artist for artist in newdata['artists'] if self._check_artist(artist)) if not extradata and metadata.get('artist'): logging.debug('got artist') - if artistdata := self.artistdatafromname(apikey, - metadata['artist']): + if artistdata := self.artistdatafromname(apikey, metadata['artist']): extradata.extend(artist for artist in artistdata.get('artists') if self._check_artist(artist)) elif self.there.match(metadata['artist']): logging.debug('Trying without a leading \'The\'') oldartist = metadata['artist'] metadata['artist'] = self.there.sub('', metadata['artist']) - if artistdata := self.artistdatafromname( - apikey, metadata['artist']): - extradata.extend(artist - for artist in artistdata.get('artists') + if artistdata := self.artistdatafromname(apikey, metadata['artist']): + extradata.extend(artist for artist in artistdata.get('artists') if self._check_artist(artist)) else: metadata['artist'] = oldartist @@ -202,8 +191,8 @@ def artistdatafromname(self, apikey, artist): def providerinfo(self): # pylint: disable=no-self-use ''' return list of what is provided by this plug-in ''' return [ - 'artistbannerraw', 'artistlongbio', 'artistlogoraw', - 'artistthumbraw', 'theaudiodb-artistfanarturls' + 'artistbannerraw', 'artistlongbio', 'artistlogoraw', 'artistthumbraw', + 'theaudiodb-artistfanarturls' ] def connect_settingsui(self, qwidget, uihelp): @@ -215,15 +204,12 @@ def load_settingsui(self, qwidget): qwidget.theaudiodb_checkbox.setChecked(True) else: qwidget.theaudiodb_checkbox.setChecked(False) - qwidget.apikey_lineedit.setText( - self.config.cparser.value('theaudiodb/apikey')) - qwidget.bio_iso_lineedit.setText( - self.config.cparser.value('theaudiodb/bio_iso')) + qwidget.apikey_lineedit.setText(self.config.cparser.value('theaudiodb/apikey')) + qwidget.bio_iso_lineedit.setText(self.config.cparser.value('theaudiodb/bio_iso')) for field in ['banners', 'bio', 'fanart', 'logos', 'thumbnails']: func = getattr(qwidget, f'{field}_checkbox') - func.setChecked( - self.config.cparser.value(f'theaudiodb/{field}', type=bool)) + func.setChecked(self.config.cparser.value(f'theaudiodb/{field}', type=bool)) def verify_settingsui(self, qwidget): ''' pass ''' @@ -231,26 +217,18 @@ def verify_settingsui(self, qwidget): def save_settingsui(self, qwidget): ''' take the settings page and save it ''' - self.config.cparser.setValue('theaudiodb/enabled', - qwidget.theaudiodb_checkbox.isChecked()) - self.config.cparser.setValue('theaudiodb/apikey', - qwidget.apikey_lineedit.text()) - self.config.cparser.setValue('theaudiodb/bio_iso', - qwidget.bio_iso_lineedit.text()) + self.config.cparser.setValue('theaudiodb/enabled', qwidget.theaudiodb_checkbox.isChecked()) + self.config.cparser.setValue('theaudiodb/apikey', qwidget.apikey_lineedit.text()) + self.config.cparser.setValue('theaudiodb/bio_iso', qwidget.bio_iso_lineedit.text()) self.config.cparser.setValue('theaudiodb/bio_iso_en_fallback', qwidget.bio_iso_en_checkbox.isChecked()) - for field in [ - 'banners', 'bio', 'fanart', 'logos', 'thumbnails', 'websites' - ]: + for field in ['banners', 'bio', 'fanart', 'logos', 'thumbnails', 'websites']: func = getattr(qwidget, f'{field}_checkbox') - self.config.cparser.setValue(f'theaudiodb/{field}', - func.isChecked()) + self.config.cparser.setValue(f'theaudiodb/{field}', func.isChecked()) def defaults(self, qsettings): - for field in [ - 'banners', 'bio', 'fanart', 'logos', 'thumbnails', 'websites' - ]: + for field in ['banners', 'bio', 'fanart', 'logos', 'thumbnails', 'websites']: qsettings.setValue(f'theaudiodb/{field}', False) qsettings.setValue('theaudiodb/enabled', False) diff --git a/nowplaying/beam/inputs/beam.py b/nowplaying/beam/inputs/beam.py index 3738d0b7..eb7aad4f 100644 --- a/nowplaying/beam/inputs/beam.py +++ b/nowplaying/beam/inputs/beam.py @@ -40,8 +40,8 @@ def __init__(self, config=None, qsettings=None): self.loop = None self.testmode = False self.site = None - self.trackrequests = nowplaying.trackrequests.Requests( - config=self.config, stopevent=self.stopevent) + self.trackrequests = nowplaying.trackrequests.Requests(config=self.config, + stopevent=self.stopevent) self.tasks = set() def install(self): @@ -68,8 +68,7 @@ def row_load(host_status, **kwargs): valuelist = ['time', 'clientname', 'ipaddr', 'source', 'version'] for column, cbtype in enumerate(valuelist): - host_status.setItem( - row, column, QTableWidgetItem(str(kwargs.get(cbtype, '')))) + host_status.setItem(row, column, QTableWidgetItem(str(kwargs.get(cbtype, '')))) host_status.resizeColumnsToContents() port = self.config.cparser.value('control/beamport', type=int) @@ -78,8 +77,7 @@ def row_load(host_status, **kwargs): return try: - beamhosts = requests.get(f'http://localhost:{port}/v1/beamhosts', - timeout=3) + beamhosts = requests.get(f'http://localhost:{port}/v1/beamhosts', timeout=3) except Exception as error: #pylint: disable=broad-except logging.error('unable to get beam hosts: %s', error) return @@ -167,12 +165,10 @@ async def _broadcast_location(self): port=None, family=socket.AF_INET) allips = [ip[-1][0] for ip in interfaces] - msg = struct.pack(f' TIMEDELTA) or not HOSTNAME: + if not TIMESTAMP or (datetime.datetime.now() - TIMESTAMP > TIMEDELTA) or not HOSTNAME: trysocket() # sourcery skip: hoist-repeated-if-condition if not HOSTIP and IFACES: diff --git a/nowplaying/imagecache.py b/nowplaying/imagecache.py index dccf5223..4ab50312 100644 --- a/nowplaying/imagecache.py +++ b/nowplaying/imagecache.py @@ -43,11 +43,7 @@ class ImageCache: ''' database operations for caches ''' - def __init__(self, - sizelimit=1, - initialize=False, - cachedir=None, - stopevent=None): + def __init__(self, sizelimit=1, initialize=False, cachedir=None, stopevent=None): if not cachedir: self.cachedir = pathlib.Path( QStandardPaths.standardLocations( @@ -61,11 +57,10 @@ def __init__(self, if not self.databasefile.exists(): initialize = True self.httpcachefile = self.cachedir.joinpath('http') - self.cache = diskcache.Cache( - directory=self.cachedir.joinpath('diskcache'), - timeout=30, - eviction_policy='least-frequently-used', - size_limit=sizelimit * 1024 * 1024 * 1024) + self.cache = diskcache.Cache(directory=self.cachedir.joinpath('diskcache'), + timeout=30, + eviction_policy='least-frequently-used', + size_limit=sizelimit * 1024 * 1024 * 1024) if initialize: self.setup_sql(initialize=True) self.session = None @@ -127,8 +122,7 @@ def random_fetch(self, artist, imagetype): msg = str(error) error_code = error.sqlite_errorcode error_name = error.sqlite_name - logging.error('Error %s [Errno %s]: %s', msg, error_code, - error_name) + logging.error('Error %s [Errno %s]: %s', msg, error_code, error_name) return None row = cursor.fetchone() @@ -140,8 +134,7 @@ def random_fetch(self, artist, imagetype): 'cachekey': row['cachekey'], 'url': row['url'], } - logging.debug('random got %s/%s/%s', imagetype, row['artist'], - row['cachekey']) + logging.debug('random got %s/%s/%s', imagetype, row['artist'], row['cachekey']) return data @@ -170,14 +163,12 @@ def find_url(self, url): connection.row_factory = sqlite3.Row cursor = connection.cursor() try: - cursor.execute('''SELECT * FROM artistsha WHERE url=?''', - (url, )) + cursor.execute('''SELECT * FROM artistsha WHERE url=?''', (url, )) except sqlite3.OperationalError as error: msg = str(error) error_code = error.sqlite_errorcode error_name = error.sqlite_name - logging.error('Error %s [Errno %s]: %s', msg, error_code, - error_name) + logging.error('Error %s [Errno %s]: %s', msg, error_code, error_name) return None if row := cursor.fetchone(): @@ -202,8 +193,7 @@ def find_cachekey(self, cachekey): connection.row_factory = sqlite3.Row cursor = connection.cursor() try: - cursor.execute('''SELECT * FROM artistsha WHERE cachekey=?''', - (cachekey, )) + cursor.execute('''SELECT * FROM artistsha WHERE cachekey=?''', (cachekey, )) except sqlite3.OperationalError: return None @@ -225,24 +215,16 @@ def fill_queue(self, config, artist, imagetype, urllist): self.setup_sql() if 'logo' in imagetype: - maxart = config.cparser.value('artistextras/logos', - defaultValue=3, - type=int) + maxart = config.cparser.value('artistextras/logos', defaultValue=3, type=int) elif 'banner' in imagetype: - maxart = config.cparser.value('artistextras/banners', - defaultValue=3, - type=int) + maxart = config.cparser.value('artistextras/banners', defaultValue=3, type=int) elif 'thumb' in imagetype: - maxart = config.cparser.value('artistextras/thumbnails', - defaultValue=3, - type=int) + maxart = config.cparser.value('artistextras/thumbnails', defaultValue=3, type=int) else: - maxart = config.cparser.value('artistextras/fanart', - defaultValue=20, - type=int) + maxart = config.cparser.value('artistextras/fanart', defaultValue=20, type=int) - logging.debug('Putting %s unfiltered for %s/%s', - min(len(urllist), maxart), imagetype, artist) + logging.debug('Putting %s unfiltered for %s/%s', min(len(urllist), maxart), imagetype, + artist) normalartist = self._normalize_artist(artist) for url in random.sample(urllist, min(len(urllist), maxart)): self.put_db_url(artist=normalartist, imagetype=imagetype, url=url) @@ -265,8 +247,7 @@ def dict_factory(cursor, row): connection.row_factory = dict_factory cursor = connection.cursor() try: - cursor.execute( - '''SELECT * FROM artistsha WHERE cachekey IS NULL + cursor.execute('''SELECT * FROM artistsha WHERE cachekey IS NULL AND EXISTS (SELECT * FROM artistsha WHERE imagetype='artistthumb' OR imagetype='artistbanner' OR imagetype='artistlogo') ORDER BY TIMESTAMP DESC''') @@ -281,8 +262,7 @@ def dict_factory(cursor, row): return dataset try: - cursor.execute( - '''SELECT * FROM artistsha WHERE cachekey IS NULL + cursor.execute('''SELECT * FROM artistsha WHERE cachekey IS NULL ORDER BY TIMESTAMP DESC''') except sqlite3.OperationalError as error: logging.error(error) @@ -321,8 +301,7 @@ def put_db_cachekey(self, artist, url, imagetype, cachekey=None): msg = str(error) error_code = error.sqlite_errorcode error_name = error.sqlite_name - logging.error('Error %s [Errno %s]: %s', msg, error_code, - error_name) + logging.error('Error %s [Errno %s]: %s', msg, error_code, error_name) return def put_db_url(self, artist, url, imagetype=None): @@ -385,12 +364,9 @@ def erase_cachekey(self, cachekey): # It was retrieved once before so put it back in the queue # if it fails in the queue, it will be deleted - logging.debug('Cache %s url %s has left cache, requeue it.', cachekey, - data['url']) + logging.debug('Cache %s url %s has left cache, requeue it.', cachekey, data['url']) self.erase_url(data['url']) - self.put_db_url(artist=data['artist'], - imagetype=data['imagetype'], - url=data['url']) + self.put_db_url(artist=data['artist'], imagetype=data['imagetype'], url=data['url']) return def image_dl(self, imagedict): @@ -448,8 +424,7 @@ async def verify_cache(self): try: logging.debug('Starting image cache verification') - async with aiosqlite.connect(self.databasefile, - timeout=30) as connection: + async with aiosqlite.connect(self.databasefile, timeout=30) as connection: connection.row_factory = sqlite3.Row sql = 'SELECT cachekey, url FROM artistsha' async with connection.execute(sql) as cursor: @@ -476,8 +451,7 @@ async def verify_cache(self): count -= 1 logging.debug('%s/%s expired', key, url) self.erase_url(url) - logging.debug('Finished image cache verification: %s/%s images', count, - startsize) + logging.debug('Finished image cache verification: %s/%s images', count, startsize) def queue_process(self, logpath, maxworkers=5): ''' Process to download stuff in the background to avoid the GIL ''' @@ -488,8 +462,7 @@ def queue_process(self, logpath, maxworkers=5): self.erase_url('STOPWNP') endloop = False oldset = [] - with concurrent.futures.ProcessPoolExecutor( - max_workers=maxworkers) as executor: + with concurrent.futures.ProcessPoolExecutor(max_workers=maxworkers) as executor: while not endloop and not self.stopevent.is_set(): if dataset := self.get_next_dlset(): # sometimes images are downloaded but not @@ -498,10 +471,7 @@ def queue_process(self, logpath, maxworkers=5): newset = [] newdataset = [] for entry in dataset: - newset.append({ - 'url': entry['url'], - 'time': int(time.time()) - }) + newset.append({'url': entry['url'], 'time': int(time.time())}) if entry['url'] == 'STOPWNP': endloop = True break @@ -509,12 +479,10 @@ def queue_process(self, logpath, maxworkers=5): for oldentry in oldcopy: if int(time.time()) - oldentry['time'] > 180: oldset.remove(oldentry) - logging.debug( - 'removing %s from the previously processed queue', - oldentry['url']) + logging.debug('removing %s from the previously processed queue', + oldentry['url']) if all(u['url'] != entry['url'] for u in oldset): - logging.debug('skipping in-progress url %s ', - entry['url']) + logging.debug('skipping in-progress url %s ', entry['url']) else: newdataset.append(entry) oldset = newset diff --git a/nowplaying/inputs/icecast.py b/nowplaying/inputs/icecast.py index 3ff35a65..ac218119 100755 --- a/nowplaying/inputs/icecast.py +++ b/nowplaying/inputs/icecast.py @@ -96,8 +96,7 @@ def _query_parse(data): logging.debug('Processing updinfo') METADATA = {} - text = data.decode('utf-8').replace('GET ', - 'http://localhost').split()[0] + text = data.decode('utf-8').replace('GET ', 'http://localhost').split()[0] url = urllib.parse.urlparse(text) if url.path == '/admin/metadata': query = urllib.parse.parse_qs(url.query) @@ -107,8 +106,7 @@ def _query_parse(data): if query.get('title'): METADATA['title'] = query['title'][0] if query.get('song'): - METADATA['title'], METADATA['artist'] = query['song'][ - 0].split('-') + METADATA['title'], METADATA['artist'] = query['song'][0].split('-') @staticmethod def _parse_vorbis_comment(fh): # pylint: disable=invalid-name @@ -169,19 +167,16 @@ def defaults(self, qsettings): def load_settingsui(self, qwidget): ''' load values from config and populate page ''' - qwidget.port_lineedit.setText( - self.config.cparser.value('icecast/port')) + qwidget.port_lineedit.setText(self.config.cparser.value('icecast/port')) def save_settingsui(self, qwidget): ''' take the settings page and save it ''' - self.config.cparser.setValue('icecast/port', - qwidget.port_lineedit.text()) + self.config.cparser.setValue('icecast/port', qwidget.port_lineedit.text()) def desc_settingsui(self, qwidget): ''' provide a description for the plugins page ''' - qwidget.setText( - 'Icecast is a streaming broadcast protocol.' - ' This setting should be used for butt, MIXXX, and many others.') + qwidget.setText('Icecast is a streaming broadcast protocol.' + ' This setting should be used for butt, MIXXX, and many others.') #### Data feed methods @@ -207,9 +202,7 @@ async def start_port(self, port): async def start(self): ''' any initialization before actual polling starts ''' - port = self.config.cparser.value('icecast/port', - type=int, - defaultValue=8000) + port = self.config.cparser.value('icecast/port', type=int, defaultValue=8000) await self.start_port(port) async def stop(self): diff --git a/nowplaying/inputs/jsonreader.py b/nowplaying/inputs/jsonreader.py index 920afbe1..61b83dba 100755 --- a/nowplaying/inputs/jsonreader.py +++ b/nowplaying/inputs/jsonreader.py @@ -25,12 +25,8 @@ def __init__(self, config=None, qsettings=None): async def getplayingtrack(self): ''' Get the currently playing track ''' - await asyncio.sleep( - self.config.cparser.value('jsoninput/delay', - type=int, - defaultValue=5)) - filepath = pathlib.Path( - self.config.cparser.value('jsoninput/filename')) + await asyncio.sleep(self.config.cparser.value('jsoninput/delay', type=int, defaultValue=5)) + filepath = pathlib.Path(self.config.cparser.value('jsoninput/filename')) if not filepath.exists(): logging.error('%s does not exist', filepath) diff --git a/nowplaying/inputs/m3u.py b/nowplaying/inputs/m3u.py index ccf49a44..167dac04 100755 --- a/nowplaying/inputs/m3u.py +++ b/nowplaying/inputs/m3u.py @@ -70,11 +70,10 @@ async def setup_watcher(self, configkey): #if len(os.listdir(self.m3udir)) < 1: # pathlib.Path(os.path.join(self.m3udir, 'empty.m3u')).touch() - self.event_handler = PatternMatchingEventHandler( - patterns=['*.m3u', '*.m3u8'], - ignore_patterns=['.DS_Store'], - ignore_directories=True, - case_sensitive=False) + self.event_handler = PatternMatchingEventHandler(patterns=['*.m3u', '*.m3u8'], + ignore_patterns=['.DS_Store'], + ignore_directories=True, + case_sensitive=False) self.event_handler.on_modified = self._read_track self.event_handler.on_created = self._read_track @@ -84,9 +83,7 @@ async def setup_watcher(self, configkey): else: logging.debug('Using fsevent observer') self.observer = Observer() - self.observer.schedule(self.event_handler, - self.m3udir, - recursive=False) + self.observer.schedule(self.event_handler, self.m3udir, recursive=False) self.observer.start() def _verify_file(self, m3ufilename, filestring): @@ -162,8 +159,8 @@ def _read_track(self, event): return filename = event.src_path - logging.debug('event type: %s, syn: %s, path: %s', event.event_type, - event.is_synthetic, filename) + logging.debug('event type: %s, syn: %s, path: %s', event.event_type, event.is_synthetic, + filename) # file is empty so ignore it if os.stat(filename).st_size == 0: @@ -189,8 +186,7 @@ def _read_track(self, event): continue trackfile = newline - logging.debug('attempting to parse \'%s\' with various encodings', - trackfile) + logging.debug('attempting to parse \'%s\' with various encodings', trackfile) audiofilename = None if trackfile: @@ -237,9 +233,7 @@ def on_m3u_dir_button(self): startdir = self.qwidget.dir_lineedit.text() else: startdir = QDir.homePath() - if dirname := QFileDialog.getExistingDirectory(self.qwidget, - 'Select directory', - startdir): + if dirname := QFileDialog.getExistingDirectory(self.qwidget, 'Select directory', startdir): self.qwidget.dir_lineedit.setText(dirname) def connect_settingsui(self, qwidget, uihelp): @@ -250,8 +244,7 @@ def connect_settingsui(self, qwidget, uihelp): def load_settingsui(self, qwidget): ''' draw the plugin's settings page ''' - qwidget.dir_lineedit.setText( - self.config.cparser.value('m3u/directory')) + qwidget.dir_lineedit.setText(self.config.cparser.value('m3u/directory')) def verify_settingsui(self, qwidget): ''' no verification to do ''' diff --git a/nowplaying/inputs/mpris2.py b/nowplaying/inputs/mpris2.py index 688024a8..44f30fd5 100755 --- a/nowplaying/inputs/mpris2.py +++ b/nowplaying/inputs/mpris2.py @@ -81,8 +81,7 @@ def getplayingtrack(self): # pylint: disable=too-many-branches logging.error('Unknown service: %s', self.service) return builddata - properties = dbus.Interface( - self.proxy, dbus_interface='org.freedesktop.DBus.Properties') + properties = dbus.Interface(self.proxy, dbus_interface='org.freedesktop.DBus.Properties') if not properties: logging.error('Unknown service: %s', self.service) return builddata @@ -235,8 +234,7 @@ def load_settingsui(self, qwidget): servicelist = self.mpris2.get_mpris2_services() qwidget.list_widget.clear() qwidget.list_widget.addItems(servicelist) - if curbutton := qwidget.list_widget.findItems(currentservice, - Qt.MatchContains): + if curbutton := qwidget.list_widget.findItems(currentservice, Qt.MatchContains): curbutton[0].setSelected(True) def save_settingsui(self, qwidget): diff --git a/nowplaying/inputs/serato.py b/nowplaying/inputs/serato.py index c4f24a6d..f8e0d5af 100755 --- a/nowplaying/inputs/serato.py +++ b/nowplaying/inputs/serato.py @@ -112,8 +112,7 @@ def getfilenames(self): for subtag in otrk: if subtag[0] != 'ptrk': continue - filelist.extend(f'{anchor}{filepart}' - for filepart in subtag[1:]) + filelist.extend(f'{anchor}{filepart}' for filepart in subtag[1:]) return filelist @@ -340,11 +339,10 @@ async def start(self): async def _setup_watcher(self): logging.debug('setting up watcher') - self.event_handler = PatternMatchingEventHandler( - patterns=['*.session'], - ignore_patterns=['.DS_Store'], - ignore_directories=True, - case_sensitive=False) + self.event_handler = PatternMatchingEventHandler(patterns=['*.session'], + ignore_patterns=['.DS_Store'], + ignore_directories=True, + case_sensitive=False) self.event_handler.on_modified = self.process_sessions if self.pollingobserver: @@ -354,10 +352,9 @@ async def _setup_watcher(self): self.observer = Observer() logging.debug('Using fsevent observer') - self.observer.schedule( - self.event_handler, - str(self.seratodir.joinpath("History", "Sessions")), - recursive=False) + self.observer.schedule(self.event_handler, + str(self.seratodir.joinpath("History", "Sessions")), + recursive=False) self.observer.start() # process what is already there @@ -392,8 +389,7 @@ async def _async_process_sessions(self): sessionpath = self.seratodir.joinpath("History", "Sessions") - sessionlist = sorted(sessionpath.glob('*.session'), - key=lambda path: int(path.stem)) + sessionlist = sorted(sessionpath.glob('*.session'), key=lambda path: int(path.stem)) #sessionlist = sorted(seratopath.glob('*.session'), # key=lambda path: path.stat().st_mtime) @@ -438,8 +434,8 @@ def computedecks(self, deckskiplist=None): if not adat.get('played'): # wasn't played, so skip it continue - if adat['deck'] in self.decks and adat.get( - 'starttime') < self.decks[adat['deck']].get('starttime'): + if adat['deck'] in self.decks and adat.get('starttime') < self.decks[adat['deck']].get( + 'starttime'): # started after a deck that is already set continue self.decks[adat['deck']] = adat @@ -489,29 +485,24 @@ def computeplaying(self): if self.mixmode == 'newest': self.playingadat['starttime'] = datetime.datetime.fromtimestamp(0) else: - self.playingadat['starttime'] = datetime.datetime.fromtimestamp( - time.time()) + self.playingadat['starttime'] = datetime.datetime.fromtimestamp(time.time()) self.playingadat['updatedat'] = self.playingadat['starttime'] logging.debug('Find the current playing deck. Starting at time: %s', self.playingadat.get('starttime')) for deck, adat in self.decks.items(): - if self.mixmode == 'newest' and adat.get( - 'starttime') > self.playingadat.get('starttime'): + if self.mixmode == 'newest' and adat.get('starttime') > self.playingadat.get( + 'starttime'): self.playingadat = adat - logging.debug( - 'Playing = time: %s deck: %d artist: %s title %s', - self.playingadat.get('starttime'), deck, - self.playingadat.get('artist'), - self.playingadat.get('title')) - elif self.mixmode == 'oldest' and adat.get( - 'starttime') < self.playingadat.get('starttime'): + logging.debug('Playing = time: %s deck: %d artist: %s title %s', + self.playingadat.get('starttime'), deck, + self.playingadat.get('artist'), self.playingadat.get('title')) + elif self.mixmode == 'oldest' and adat.get('starttime') < self.playingadat.get( + 'starttime'): self.playingadat = adat - logging.debug( - 'Playing = time: %s deck: %d artist: %s title %s', - self.playingadat.get('starttime'), deck, - self.playingadat.get('artist'), - self.playingadat.get('title')) + logging.debug('Playing = time: %s deck: %d artist: %s title %s', + self.playingadat.get('starttime'), deck, + self.playingadat.get('artist'), self.playingadat.get('title')) def getlocalplayingtrack(self, deckskiplist=None): ''' parse out last track from binary session file @@ -555,8 +546,7 @@ def getremoteplayingtrack(self): # pylint: disable=too-many-return-statements, try: tree = lxml.html.fromstring(page.text) # [\n(spaces)artist - title (tabs)] - item = tree.xpath( - '(//div[@class="playlist-trackname"]/text())[last()]') + item = tree.xpath('(//div[@class="playlist-trackname"]/text())[last()]') except Exception as error: # pylint: disable=broad-except logging.error("Cannot process %s: %s", self.url, error) return @@ -607,8 +597,7 @@ def _get_tidal_cover(self, filename): ''' try to get the cover from tidal ''' if tmatch := TIDAL_FORMAT.search(str(filename)): imgfile = f'{tmatch.group(1)}.jpg' - tidalimgpath = self.seratodir.joinpath('Metadata', 'Tidal', - imgfile) + tidalimgpath = self.seratodir.joinpath('Metadata', 'Tidal', imgfile) logging.debug('using tidal image path: %s', tidalimgpath) if tidalimgpath.exists(): with open(tidalimgpath, 'rb') as fhin: @@ -626,10 +615,8 @@ def getplayingtrack(self, deckskiplist=None): if not self.playingadat: return {} - if self.playingadat.get('filename') and '.tdl' in self.playingadat.get( - 'filename'): - if coverimage := self._get_tidal_cover( - self.playingadat['filename']): + if self.playingadat.get('filename') and '.tdl' in self.playingadat.get('filename'): + if coverimage := self._get_tidal_cover(self.playingadat['filename']): self.playingadat['coverimageraw'] = coverimage return { @@ -687,9 +674,8 @@ def __init__(self, config=None, qsettings=None): def install(self): ''' auto-install for Serato ''' - seratodir = pathlib.Path( - QStandardPaths.standardLocations( - QStandardPaths.MusicLocation)[0]).joinpath("_Serato_") + seratodir = pathlib.Path(QStandardPaths.standardLocations( + QStandardPaths.MusicLocation)[0]).joinpath("_Serato_") if seratodir.exists(): self.config.cparser.value('settings/input', 'serato') @@ -702,8 +688,7 @@ async def gethandler(self): ''' setup the SeratoHandler for this session ''' stilllocal = self.config.cparser.value('serato/local', type=bool) - usepoll = self.config.cparser.value('quirks/pollingobserver', - type=bool) + usepoll = self.config.cparser.value('quirks/pollingobserver', type=bool) # now configured as remote! if not stilllocal: @@ -767,8 +752,7 @@ async def getplayingtrack(self): if self.local: interval = 1 else: - interval = self.config.cparser.value('settings/interval', - type=float) + interval = self.config.cparser.value('settings/interval', type=float) time.sleep(interval) @@ -810,8 +794,7 @@ def defaults(self, qsettings): qsettings.setValue( 'serato/libpath', os.path.join( - QStandardPaths.standardLocations( - QStandardPaths.MusicLocation)[0], "_Serato_")) + QStandardPaths.standardLocations(QStandardPaths.MusicLocation)[0], "_Serato_")) qsettings.setValue('serato/interval', 10.0) qsettings.setValue('serato/local', True) qsettings.setValue('serato/mixmode', "newest") @@ -855,17 +838,14 @@ def on_serato_lib_button(self): startdir = self.qwidget.local_dir_lineedit.text() if not startdir: startdir = str(pathlib.Path.home()) - if libdir := QFileDialog.getExistingDirectory(self.qwidget, - 'Select directory', - startdir): + if libdir := QFileDialog.getExistingDirectory(self.qwidget, 'Select directory', startdir): self.qwidget.local_dir_lineedit.setText(libdir) def connect_settingsui(self, qwidget, uihelp): ''' connect serato local dir button ''' self.qwidget = qwidget self.uihelp = uihelp - self.qwidget.local_dir_button.clicked.connect( - self.on_serato_lib_button) + self.qwidget.local_dir_button.clicked.connect(self.on_serato_lib_button) def load_settingsui(self, qwidget): ''' draw the plugin's settings page ''' @@ -901,40 +881,30 @@ def handle_deckskip(cparser, qwidget): else: qwidget.local_dir_button.setChecked(False) qwidget.remote_button.setChecked(True) - qwidget.local_dir_lineedit.setText( - self.config.cparser.value('serato/libpath')) - qwidget.remote_url_lineedit.setText( - self.config.cparser.value('serato/url')) - qwidget.remote_poll_lineedit.setText( - str(self.config.cparser.value('serato/interval'))) + qwidget.local_dir_lineedit.setText(self.config.cparser.value('serato/libpath')) + qwidget.remote_url_lineedit.setText(self.config.cparser.value('serato/url')) + qwidget.remote_poll_lineedit.setText(str(self.config.cparser.value('serato/interval'))) handle_deckskip(self.config.cparser, qwidget) def verify_settingsui(self, qwidget): ''' no verification to do ''' if qwidget.remote_button.isChecked() and ( - 'https://serato.com/playlists' - not in qwidget.remote_url_lineedit.text() - and 'https://www.serato.com/playlists' - not in qwidget.remote_url_lineedit.text() + 'https://serato.com/playlists' not in qwidget.remote_url_lineedit.text() + and 'https://www.serato.com/playlists' not in qwidget.remote_url_lineedit.text() or len(qwidget.remote_url_lineedit.text()) < 30): raise PluginVerifyError('Serato Live Playlist URL is invalid') - if qwidget.local_button.isChecked() and ( - '_Serato_' not in qwidget.local_dir_lineedit.text()): + if qwidget.local_button.isChecked() and ('_Serato_' + not in qwidget.local_dir_lineedit.text()): raise PluginVerifyError( - r'Serato Library Path is required. Should point to "\_Serato\_" folder' - ) + r'Serato Library Path is required. Should point to "\_Serato\_" folder') def save_settingsui(self, qwidget): ''' take the settings page and save it ''' - self.config.cparser.setValue('serato/libpath', - qwidget.local_dir_lineedit.text()) - self.config.cparser.setValue('serato/local', - qwidget.local_button.isChecked()) - self.config.cparser.setValue('serato/url', - qwidget.remote_url_lineedit.text()) - self.config.cparser.setValue('serato/interval', - qwidget.remote_poll_lineedit.text()) + self.config.cparser.setValue('serato/libpath', qwidget.local_dir_lineedit.text()) + self.config.cparser.setValue('serato/local', qwidget.local_button.isChecked()) + self.config.cparser.setValue('serato/url', qwidget.remote_url_lineedit.text()) + self.config.cparser.setValue('serato/interval', qwidget.remote_poll_lineedit.text()) deckskip = [] if qwidget.deck1_checkbox.isChecked(): diff --git a/nowplaying/inputs/traktor.py b/nowplaying/inputs/traktor.py index cfb9cb68..592dd490 100755 --- a/nowplaying/inputs/traktor.py +++ b/nowplaying/inputs/traktor.py @@ -34,9 +34,8 @@ class Traktor: def __init__(self, config=None): self.databasefile = pathlib.Path( - QStandardPaths.standardLocations( - QStandardPaths.CacheLocation)[0]).joinpath( - 'traktor', 'traktor.db') + QStandardPaths.standardLocations(QStandardPaths.CacheLocation)[0]).joinpath( + 'traktor', 'traktor.db') self.database = None self.config = config @@ -54,10 +53,8 @@ def _write_playlist(sqlcursor, traktortree): for tracks in node: for keys in tracks: for primarykey in keys: - filepathcomps = primarykey.attrib['KEY'].split( - '/:') - filename = str( - pathlib.Path('/').joinpath(*filepathcomps[1:])) + filepathcomps = primarykey.attrib['KEY'].split('/:') + filename = str(pathlib.Path('/').joinpath(*filepathcomps[1:])) sql = 'INSERT INTO playlists (name,filename) VALUES (?,?)' datatuple = playlist, filename sqlcursor.execute(sql, datatuple) @@ -82,8 +79,8 @@ def _write_filelist(sqlcursor, traktortree): if volume[0].isalpha() and volume[1] == ':': metadata['filename'] = volume - metadata['filename'] += subnode.get('DIR').replace( - '/:', '/') + subnode.get('FILE') + metadata['filename'] += subnode.get('DIR').replace('/:', + '/') + subnode.get('FILE') elif subnode.tag == 'TEMPO': metadata['bpm'] = subnode.get('BPM') sql = 'INSERT INTO songs (' @@ -98,8 +95,7 @@ def rewrite_db(self, collectionsfile=None): collectionsfile = self.config.cparser.value('traktor/collections') if not collectionsfile or not pathlib.Path(collectionsfile).exists(): - logging.error('collection.nml (%s) does not exist', - collectionsfile) + logging.error('collection.nml (%s) does not exist', collectionsfile) return self.databasefile.parent.mkdir(parents=True, exist_ok=True) @@ -132,8 +128,7 @@ async def lookup(self, artist=None, title=None): cursor = await connection.cursor() try: await cursor.execute( - '''SELECT * FROM songs WHERE artist=? AND title=? ORDER BY id DESC LIMIT 1''', - ( + '''SELECT * FROM songs WHERE artist=? AND title=? ORDER BY id DESC LIMIT 1''', ( artist, title, )) @@ -187,8 +182,7 @@ def install(self): if entry.is_dir() and 'Traktor' in entry.name: cmlpath = pathlib.Path(entry).joinpath('collection.nml') if cmlpath.exists(): - self.config.cparser.value('traktor/collections', - str(cmlpath)) + self.config.cparser.value('traktor/collections', str(cmlpath)) self.config.cparser.value('settings/input', 'traktor') self.config.cparser.value('traktor/port', 8000) return True @@ -208,32 +202,26 @@ def connect_settingsui(self, qwidget, uihelp): ''' connect any UI elements such as buttons ''' self.qwidget = qwidget self.uihelp = uihelp - self.qwidget.traktor_browse_button.clicked.connect( - self._on_traktor_browse_button) - self.qwidget.traktor_rebuild_button.clicked.connect( - self._on_traktor_rebuild_button) + self.qwidget.traktor_browse_button.clicked.connect(self._on_traktor_browse_button) + self.qwidget.traktor_rebuild_button.clicked.connect(self._on_traktor_rebuild_button) def _on_traktor_browse_button(self): ''' user clicked traktor browse button ''' startdir = self.qwidget.traktor_collection_lineedit.text() if not startdir: - startdir = str(pathlib.Path.home().joinpath( - 'Documents', 'Native Instruments')) - if filename := QFileDialog.getOpenFileName(self.qwidget, - 'Open collection file', - startdir, '*.nml'): + startdir = str(pathlib.Path.home().joinpath('Documents', 'Native Instruments')) + if filename := QFileDialog.getOpenFileName(self.qwidget, 'Open collection file', startdir, + '*.nml'): self.qwidget.traktor_collection_lineedit.setText(filename[0]) def _on_traktor_rebuild_button(self): ''' user clicked re-read collections ''' rewritedb = Traktor(config=self.config) - rewritedb.rewrite_db( - collectionsfile=self.qwidget.traktor_collection_lineedit.text()) + rewritedb.rewrite_db(collectionsfile=self.qwidget.traktor_collection_lineedit.text()) def load_settingsui(self, qwidget): ''' load values from config and populate page ''' - qwidget.port_lineedit.setText( - self.config.cparser.value('traktor/port')) + qwidget.port_lineedit.setText(self.config.cparser.value('traktor/port')) qwidget.traktor_collection_lineedit.setText( self.config.cparser.value('traktor/collections')) @@ -248,10 +236,9 @@ def verify_settingsui(self, qwidget): #pylint: disable=no-self-use def save_settingsui(self, qwidget): ''' take the settings page and save it ''' - self.config.cparser.setValue('traktor/port', - qwidget.port_lineedit.text()) - self.config.cparser.setValue( - 'traktor/collections', qwidget.traktor_collection_lineedit.text()) + self.config.cparser.setValue('traktor/port', qwidget.port_lineedit.text()) + self.config.cparser.setValue('traktor/collections', + qwidget.traktor_collection_lineedit.text()) def desc_settingsui(self, qwidget): ''' provide a description for the plugins page ''' @@ -262,9 +249,8 @@ def desc_settingsui(self, qwidget): async def getplayingtrack(self): ''' give back the metadata global ''' icmetadata = await super().getplayingtrack() - if self.lastmetadata.get('artist') == icmetadata.get( - 'artist') and self.lastmetadata.get('title') == icmetadata.get( - 'title'): + if self.lastmetadata.get('artist') == icmetadata.get('artist') and self.lastmetadata.get( + 'title') == icmetadata.get('title'): return self.lastmetadata metadata = None @@ -292,7 +278,5 @@ async def getrandomtrack(self, playlist): async def start(self): ''' any initialization before actual polling starts ''' - port = self.config.cparser.value('traktor/port', - type=int, - defaultValue=8000) + port = self.config.cparser.value('traktor/port', type=int, defaultValue=8000) await self.start_port(port) diff --git a/nowplaying/inputs/virtualdj.py b/nowplaying/inputs/virtualdj.py index 7f011e98..4f5c08ed 100755 --- a/nowplaying/inputs/virtualdj.py +++ b/nowplaying/inputs/virtualdj.py @@ -24,9 +24,8 @@ def __init__(self, config=None, m3udir=None, qsettings=None): super().__init__(config=config, m3udir=m3udir, qsettings=qsettings) self.displayname = "VirtualDJ" self.databasefile = pathlib.Path( - QStandardPaths.standardLocations( - QStandardPaths.CacheLocation)[0]).joinpath( - 'virtualdj', 'virtualdj.db') + QStandardPaths.standardLocations(QStandardPaths.CacheLocation)[0]).joinpath( + 'virtualdj', 'virtualdj.db') self.database = None def initdb(self): @@ -79,10 +78,8 @@ def install(self): vdjdir = pathlib.Path.home().joinpath('Documents', 'VirtualDJ') if vdjdir.exists(): self.config.cparser.value('settings/input', 'virtualdj') - self.config.cparser.value('virtualdj/history', - str(vdjdir.joinpath('History'))) - self.config.cparser.value('virtualdj/playlists', - str(vdjdir.joinpath('Playlists'))) + self.config.cparser.value('virtualdj/history', str(vdjdir.joinpath('History'))) + self.config.cparser.value('virtualdj/playlists', str(vdjdir.joinpath('Playlists'))) return True return False @@ -128,10 +125,8 @@ async def stop(self): def defaults(self, qsettings): ''' (re-)set the default configuration values for this plugin ''' vdjdir = pathlib.Path.home().joinpath('Documents', 'VirtualDJ') - qsettings.setValue('virtualdj/history', - str(vdjdir.joinpath('History'))) - qsettings.setValue('virtualdj/playlists', - str(vdjdir.joinpath('Playlists'))) + qsettings.setValue('virtualdj/history', str(vdjdir.joinpath('History'))) + qsettings.setValue('virtualdj/playlists', str(vdjdir.joinpath('Playlists'))) qsettings.setValue('virtualdj/useremix', True) def on_playlist_reread_button(self): @@ -142,10 +137,8 @@ def on_playlistdir_button(self): ''' filename button clicked action''' startdir = self.qwidget.playlistdir_lineedit.text() if not startdir: - startdir = str(pathlib.Path.home().joinpath( - 'Documents', 'VirtualDJ')) - if filename := QFileDialog.getExistingDirectory( - self.qwidget, 'Select directory', startdir): + startdir = str(pathlib.Path.home().joinpath('Documents', 'VirtualDJ')) + if filename := QFileDialog.getExistingDirectory(self.qwidget, 'Select directory', startdir): self.qwidget.playlistdir_lineedit.setText(filename[0]) def on_history_dir_button(self): @@ -153,11 +146,8 @@ def on_history_dir_button(self): if self.qwidget.historydir_lineedit.text(): startdir = self.qwidget.historydir_lineedit.text() else: - startdir = str(pathlib.Path.home().joinpath( - 'Documents', 'VirtualDJ', 'History')) - if dirname := QFileDialog.getExistingDirectory(self.qwidget, - 'Select directory', - startdir): + startdir = str(pathlib.Path.home().joinpath('Documents', 'VirtualDJ', 'History')) + if dirname := QFileDialog.getExistingDirectory(self.qwidget, 'Select directory', startdir): self.qwidget.historydir_lineedit.setText(dirname) def connect_settingsui(self, qwidget, uihelp): @@ -166,37 +156,27 @@ def connect_settingsui(self, qwidget, uihelp): self.uihelp = uihelp qwidget.historydir_button.clicked.connect(self.on_history_dir_button) qwidget.playlistdir_button.clicked.connect(self.on_playlistdir_button) - qwidget.playlist_reread_button.clicked.connect( - self.on_playlist_reread_button) + qwidget.playlist_reread_button.clicked.connect(self.on_playlist_reread_button) def load_settingsui(self, qwidget): ''' draw the plugin's settings page ''' - qwidget.historydir_lineedit.setText( - self.config.cparser.value('virtualdj/history')) - qwidget.playlistdir_lineedit.setText( - self.config.cparser.value('virtualdj/playlists')) + qwidget.historydir_lineedit.setText(self.config.cparser.value('virtualdj/history')) + qwidget.playlistdir_lineedit.setText(self.config.cparser.value('virtualdj/playlists')) qwidget.remix_checkbox.setChecked( - self.config.cparser.value('virtualdj/useremix', - type=bool, - defaultValue=True)) + self.config.cparser.value('virtualdj/useremix', type=bool, defaultValue=True)) def verify_settingsui(self, qwidget): ''' verify settings ''' if not os.path.exists(qwidget.historydir_lineedit.text()): - raise PluginVerifyError( - r'Virtual DJ History directory must exist.') + raise PluginVerifyError(r'Virtual DJ History directory must exist.') if not os.path.exists(qwidget.playlistdir_lineedit.text()): - raise PluginVerifyError( - r'Virtual DJ Playlists directory must exist.') + raise PluginVerifyError(r'Virtual DJ Playlists directory must exist.') def save_settingsui(self, qwidget): ''' take the settings page and save it ''' - self.config.cparser.setValue('virtualdj/history', - qwidget.historydir_lineedit.text()) - self.config.cparser.setValue('virtualdj/playlists', - qwidget.playlistdir_lineedit.text()) - self.config.cparser.setValue('virtualdj/useremix', - qwidget.remix_checkbox.isChecked()) + self.config.cparser.setValue('virtualdj/history', qwidget.historydir_lineedit.text()) + self.config.cparser.setValue('virtualdj/playlists', qwidget.playlistdir_lineedit.text()) + self.config.cparser.setValue('virtualdj/useremix', qwidget.remix_checkbox.isChecked()) def desc_settingsui(self, qwidget): ''' description ''' diff --git a/nowplaying/inputs/winmedia.py b/nowplaying/inputs/winmedia.py index e1192e86..34a77797 100644 --- a/nowplaying/inputs/winmedia.py +++ b/nowplaying/inputs/winmedia.py @@ -10,8 +10,7 @@ from winsdk.windows.media.control import \ GlobalSystemMediaTransportControlsSessionManager as MediaManager - from winsdk.windows.storage.streams import (DataReader, Buffer, - InputStreamOptions) + from winsdk.windows.storage.streams import (DataReader, Buffer, InputStreamOptions) WINMEDIA_STATUS = True except ImportError: WINMEDIA_STATUS = False @@ -43,9 +42,8 @@ def install(self): def desc_settingsui(self, qwidget): ''' provide a description for the plugins page ''' - qwidget.setText( - 'WinMedia will read data from Windows Media Transport' - ' -compatible software such as Soundcloud and Spotify.') + qwidget.setText('WinMedia will read data from Windows Media Transport' + ' -compatible software such as Soundcloud and Spotify.') @staticmethod async def _getcoverimage(thumbref): @@ -54,13 +52,11 @@ async def _getcoverimage(thumbref): thumb_read_buffer = Buffer(5000000) readable_stream = await thumbref.open_read_async() - readable_stream.read_async(thumb_read_buffer, - thumb_read_buffer.capacity, + readable_stream.read_async(thumb_read_buffer, thumb_read_buffer.capacity, InputStreamOptions.READ_AHEAD) buffer_reader = DataReader.from_buffer(thumb_read_buffer) if byte_buffer := bytearray( - buffer_reader.read_buffer( - buffer_reader.unconsumed_buffer_length)): + buffer_reader.read_buffer(buffer_reader.unconsumed_buffer_length)): return nowplaying.utils.image2png(byte_buffer) except: # pylint: disable=bare-except for line in traceback.format_exc().splitlines(): @@ -99,8 +95,7 @@ async def _data_loop(self): # avoid expensive image2png call diff = any( - newdata.get(cmpval) != self.metadata.get(cmpval) - for cmpval in mapping.values()) + newdata.get(cmpval) != self.metadata.get(cmpval) for cmpval in mapping.values()) if not diff: continue diff --git a/nowplaying/metadata.py b/nowplaying/metadata.py index 58db0e87..233a83eb 100755 --- a/nowplaying/metadata.py +++ b/nowplaying/metadata.py @@ -31,10 +31,7 @@ def __init__(self, config=None): else: self.config = nowplaying.config.ConfigFile() - async def getmoremetadata(self, - metadata=None, - imagecache=None, - skipplugins=False): + async def getmoremetadata(self, metadata=None, imagecache=None, skipplugins=False): ''' take metadata and process it ''' self.metadata = metadata self.imagecache = imagecache @@ -65,8 +62,7 @@ async def getmoremetadata(self, self.metadata['date'] = self.metadata['year'] del self.metadata['year'] - if self.metadata.get( - 'artistlongbio') and not self.metadata.get('artistshortbio'): + if self.metadata.get('artistlongbio') and not self.metadata.get('artistshortbio'): self._generate_short_bio() self._uniqlists() @@ -82,8 +78,7 @@ def _fix_duration(self): try: duration = int(self.metadata['duration']) except ValueError: - logging.debug('Cannot convert duration = %s', - self.metadata['duration']) + logging.debug('Cannot convert duration = %s', self.metadata['duration']) del self.metadata['duration'] return @@ -94,15 +89,13 @@ def _strip_identifiers(self): if self.config.cparser.value('settings/stripextras', type=bool) and self.metadata.get('title'): self.metadata['title'] = nowplaying.utils.titlestripper_advanced( - title=self.metadata['title'], - title_regex_list=self.config.getregexlist()) + title=self.metadata['title'], title_regex_list=self.config.getregexlist()) def _uniqlists(self): if self.metadata.get('artistwebsites'): newlist = [ - url_normalize.url_normalize(url) - for url in self.metadata.get('artistwebsites') + url_normalize.url_normalize(url) for url in self.metadata.get('artistwebsites') ] self.metadata['artistwebsites'] = newlist @@ -127,15 +120,13 @@ def _uniqlists(self): def _process_hostmeta(self): ''' add the host metadata so other subsystems can use it ''' if self.config.cparser.value('weboutput/httpenabled', type=bool): - self.metadata['httpport'] = self.config.cparser.value( - 'weboutput/httpport', type=int) + self.metadata['httpport'] = self.config.cparser.value('weboutput/httpport', type=int) hostmeta = nowplaying.hostmeta.gethostmeta() for key, value in hostmeta.items(): self.metadata[key] = value def _process_audio_metadata(self): - self.metadata = AudioMetadataRunner(config=self.config).process( - metadata=self.metadata) + self.metadata = AudioMetadataRunner(config=self.config).process(metadata=self.metadata) def _process_tinytag(self): ''' given a chunk of metadata, try to fill in more ''' @@ -145,19 +136,16 @@ def _process_tinytag(self): try: tag = tinytag.TinyTag.get(self.metadata['filename'], image=True) except tinytag.tinytag.TinyTagException as error: - logging.error('tinytag could not process %s: %s', - self.metadata['filename'], error) + logging.error('tinytag could not process %s: %s', self.metadata['filename'], error) return if tag: for key in [ - 'album', 'albumartist', 'artist', 'bitrate', 'bpm', - 'comments', 'composer', 'disc', 'disc_total', 'duration', - 'genre', 'key', 'lang', 'publisher', 'title', 'track', - 'track_total', 'year' + 'album', 'albumartist', 'artist', 'bitrate', 'bpm', 'comments', 'composer', + 'disc', 'disc_total', 'duration', 'genre', 'key', 'lang', 'publisher', 'title', + 'track', 'track_total', 'year' ]: - if key not in self.metadata and hasattr(tag, key) and getattr( - tag, key): + if key not in self.metadata and hasattr(tag, key) and getattr(tag, key): self.metadata[key] = getattr(tag, key) if getattr(tag, 'extra'): @@ -166,8 +154,7 @@ def _process_tinytag(self): if extra.get(key): self.metadata[key] = extra[key].split('/') - if 'date' not in self.metadata and hasattr( - tag, 'year') and getattr(tag, 'year'): + if 'date' not in self.metadata and hasattr(tag, 'year') and getattr(tag, 'year'): self.metadata['date'] = getattr(tag, 'year') if 'coverimageraw' not in self.metadata: @@ -176,28 +163,23 @@ def _process_tinytag(self): def _process_image2png(self): # always convert to png - if 'coverimageraw' not in self.metadata or not self.metadata[ - 'coverimageraw']: + if 'coverimageraw' not in self.metadata or not self.metadata['coverimageraw']: return - self.metadata['coverimageraw'] = nowplaying.utils.image2png( - self.metadata['coverimageraw']) + self.metadata['coverimageraw'] = nowplaying.utils.image2png(self.metadata['coverimageraw']) self.metadata['coverimagetype'] = 'png' self.metadata['coverurl'] = 'cover.png' def _musicbrainz(self): - musicbrainz = nowplaying.musicbrainz.MusicBrainzHelper( - config=self.config) + musicbrainz = nowplaying.musicbrainz.MusicBrainzHelper(config=self.config) metalist = musicbrainz.providerinfo() addmeta = {} if self.metadata.get('musicbrainzrecordingid'): - logging.debug( - 'musicbrainz recordingid detected; attempting shortcuts') + logging.debug('musicbrainz recordingid detected; attempting shortcuts') if any(meta not in self.metadata for meta in metalist): - addmeta = musicbrainz.recordingid( - self.metadata['musicbrainzrecordingid']) + addmeta = musicbrainz.recordingid(self.metadata['musicbrainzrecordingid']) self.metadata = recognition_replacement(config=self.config, metadata=self.metadata, addmeta=addmeta) @@ -211,8 +193,7 @@ def _musicbrainz(self): elif self.metadata.get('musicbrainzartistid'): logging.debug('Preprocessing with musicbrainz artistid') if any(meta not in self.metadata for meta in metalist): - addmeta = musicbrainz.artistids( - self.metadata['musicbrainzartistid']) + addmeta = musicbrainz.artistids(self.metadata['musicbrainzartistid']) self.metadata = recognition_replacement(config=self.config, metadata=self.metadata, addmeta=addmeta) @@ -227,18 +208,15 @@ def _mb_fallback(self): return # either missing key data or has already been processed - if (self.metadata.get('isrc') - or self.metadata.get('musicbrainzartistid') - or self.metadata.get('musicbrainzrecordingid') - or not self.metadata.get('artist') + if (self.metadata.get('isrc') or self.metadata.get('musicbrainzartistid') + or self.metadata.get('musicbrainzrecordingid') or not self.metadata.get('artist') or not self.metadata.get('title')): return logging.debug('Attempting musicbrainz fallback') try: - musicbrainz = nowplaying.musicbrainz.MusicBrainzHelper( - config=self.config) + musicbrainz = nowplaying.musicbrainz.MusicBrainzHelper(config=self.config) addmeta = musicbrainz.lastditcheffort(self.metadata) self.metadata = recognition_replacement(config=self.config, metadata=self.metadata, @@ -252,54 +230,43 @@ async def _process_plugins(self): addmeta = self._musicbrainz() for plugin in self.config.plugins['recognition']: - metalist = self.config.pluginobjs['recognition'][ - plugin].providerinfo() + metalist = self.config.pluginobjs['recognition'][plugin].providerinfo() provider = any(meta not in self.metadata for meta in metalist) if provider: try: - if addmeta := self.config.pluginobjs['recognition'][ - plugin].recognize(metadata=self.metadata): - self.metadata = recognition_replacement( - config=self.config, - metadata=self.metadata, - addmeta=addmeta) + if addmeta := self.config.pluginobjs['recognition'][plugin].recognize( + metadata=self.metadata): + self.metadata = recognition_replacement(config=self.config, + metadata=self.metadata, + addmeta=addmeta) except Exception as error: # pylint: disable=broad-except - logging.error('%s threw exception %s', - plugin, - error, - exc_info=True) + logging.error('%s threw exception %s', plugin, error, exc_info=True) self._mb_fallback() if self.config.cparser.value( 'artistextras/enabled', - type=bool) and not self.config.cparser.value('control/beam', - type=bool): + type=bool) and not self.config.cparser.value('control/beam', type=bool): tasks = [] - with concurrent.futures.ThreadPoolExecutor( - max_workers=3, thread_name_prefix='artistextras') as pool: + with concurrent.futures.ThreadPoolExecutor(max_workers=3, + thread_name_prefix='artistextras') as pool: for plugin in self.config.plugins['artistextras']: - metalist = self.config.pluginobjs['artistextras'][ - plugin].providerinfo() + metalist = self.config.pluginobjs['artistextras'][plugin].providerinfo() loop = asyncio.get_running_loop() tasks.append( loop.run_in_executor( - pool, self.config.pluginobjs['artistextras'] - [plugin].download, self.metadata, self.imagecache)) + pool, self.config.pluginobjs['artistextras'][plugin].download, + self.metadata, self.imagecache)) for task in tasks: try: if addmeta := await task: - self.metadata = recognition_replacement( - config=self.config, - metadata=self.metadata, - addmeta=addmeta) + self.metadata = recognition_replacement(config=self.config, + metadata=self.metadata, + addmeta=addmeta) except Exception as error: # pylint: disable=broad-except - logging.error('%s threw exception %s', - plugin, - error, - exc_info=True) + logging.error('%s threw exception %s', plugin, error, exc_info=True) def _generate_short_bio(self): message = self.metadata['artistlongbio'] @@ -309,9 +276,7 @@ def _generate_short_bio(self): text = textwrap.TextWrapper(width=450).wrap(message)[0] tokens = nltk.sent_tokenize(text) - if tokens[-1][-1] in string.punctuation and tokens[-1][-1] not in [ - ':', ',', ';', '-' - ]: + if tokens[-1][-1] in string.punctuation and tokens[-1][-1] not in [':', ',', ';', '-']: self.metadata['artistshortbio'] = ' '.join(tokens) else: self.metadata['artistshortbio'] = ' '.join(tokens[:-1]) @@ -347,8 +312,7 @@ def _itunes(tempdata, freeform): for src, dest in convdict.items(): if freeform['name'] == src and not tempdata.get(dest): - tempdata[dest] = MP4FreeformDecoders[freeform.data_type]( - freeform.value) + tempdata[dest] = MP4FreeformDecoders[freeform.data_type](freeform.value) convdict = { 'MusicBrainz Artist Id': 'musicbrainzartistid', @@ -361,13 +325,11 @@ def _itunes(tempdata, freeform): if freeform['name'] == src: if tempdata.get(dest): tempdata[dest].append( - str(MP4FreeformDecoders[freeform.data_type]( - freeform.value))) + str(MP4FreeformDecoders[freeform.data_type](freeform.value))) else: tempdata[dest] = [ - str(MP4FreeformDecoders[freeform.data_type]( - freeform.value)) + str(MP4FreeformDecoders[freeform.data_type](freeform.value)) ] return tempdata @@ -399,16 +361,14 @@ def _process_audio_metadata_othertags(self, tags): if 'discnumber' in tags and 'disc' not in self.metadata: text = tags['discnumber'][0].replace('[', '').replace(']', '') try: - self.metadata['disc'], self.metadata[ - 'disc_total'] = text.split('/') + self.metadata['disc'], self.metadata['disc_total'] = text.split('/') except: # pylint: disable=bare-except pass if 'tracknumber' in tags and 'track' not in self.metadata: text = tags['tracknumber'][0].replace('[', '').replace(']', '') try: - self.metadata['track'], self.metadata[ - 'track_total'] = text.split('/') + self.metadata['track'], self.metadata['track_total'] = text.split('/') except: # pylint: disable=bare-except pass @@ -461,11 +421,10 @@ def _process_audio_metadata_remaps(self, tags): def _process_audio_metadata(self): # pylint: disable=too-many-branches try: - base = nowplaying.vendor.audio_metadata.load( - self.metadata['filename']) + base = nowplaying.vendor.audio_metadata.load(self.metadata['filename']) except Exception as error: # pylint: disable=broad-except - logging.error('audio_metadata could not process %s: %s', - self.metadata['filename'], error) + logging.error('audio_metadata could not process %s: %s', self.metadata['filename'], + error) return for key in [ @@ -484,17 +443,14 @@ def _process_audio_metadata(self): # pylint: disable=too-many-branches ]: if key not in self.metadata and key in base.tags: if isinstance(base.tags[key], list): - self.metadata[key] = '/'.join( - str(x) for x in base.tags[key]) + self.metadata[key] = '/'.join(str(x) for x in base.tags[key]) else: self.metadata[key] = str(base.tags[key]) if 'ufid' in base.tags: for index in base.tags.ufid: if index.owner == 'http://musicbrainz.org': - self.metadata[ - 'musicbrainzrecordingid'] = index.identifier.decode( - 'utf-8') + self.metadata['musicbrainzrecordingid'] = index.identifier.decode('utf-8') self._process_audio_metadata_remaps(base.tags) self._process_audio_metadata_othertags(base.tags) @@ -514,8 +470,7 @@ def recognition_replacement(config=None, metadata=None, addmeta=None): for meta in addmeta: if meta in ['artist', 'title', 'artistwebsites']: - if config.cparser.value(f'recognition/replace{meta}', - type=bool) and addmeta.get(meta): + if config.cparser.value(f'recognition/replace{meta}', type=bool) and addmeta.get(meta): metadata[meta] = addmeta[meta] elif not metadata.get(meta) and addmeta.get(meta): metadata[meta] = addmeta[meta] @@ -527,9 +482,8 @@ def recognition_replacement(config=None, metadata=None, addmeta=None): def main(): ''' entry point as a standalone app''' logging.basicConfig( - format= - '%(asctime)s %(process)d %(threadName)s %(module)s:%(funcName)s:%(lineno)d ' - + '%(levelname)s %(message)s', + format='%(asctime)s %(process)d %(threadName)s %(module)s:%(funcName)s:%(lineno)d ' + + '%(levelname)s %(message)s', datefmt='%Y-%m-%dT%H:%M:%S%z', level=logging.DEBUG) logging.captureWarnings(True) diff --git a/nowplaying/musicbrainz.py b/nowplaying/musicbrainz.py index bbe14332..54585350 100755 --- a/nowplaying/musicbrainz.py +++ b/nowplaying/musicbrainz.py @@ -31,14 +31,12 @@ def _setemail(self): ''' make sure the musicbrainz fetch has an email address set according to their requirements ''' if not self.emailaddressset: - emailaddress = self.config.cparser.value( - 'musicbrainz/emailaddress') + emailaddress = self.config.cparser.value('musicbrainz/emailaddress') if not emailaddress: emailaddress = 'aw@effectivemachines.com' - musicbrainzngs.set_useragent('whats-now-playing', - self.config.version, emailaddress) + musicbrainzngs.set_useragent('whats-now-playing', self.config.version, emailaddress) self.emailaddressset = True def _pickarecording(self, testdata, mbdata, allowothers=False): #pylint: disable=too-many-branches @@ -58,9 +56,8 @@ def _pickarecording(self, testdata, mbdata, allowothers=False): #pylint: disabl if testdata.get('album') and testdata['album'] != title: logging.debug('skipped %s <> %s', title, testdata['album']) continue - if release.get( - 'artist-credit' - ) and 'Various Artists' in release['artist-credit'][0]['name']: + if release.get('artist-credit' + ) and 'Various Artists' in release['artist-credit'][0]['name']: logging.debug('skipped %s -- VA', title) continue relgroup = release['release-group'] @@ -73,8 +70,7 @@ def _pickarecording(self, testdata, mbdata, allowothers=False): #pylint: disabl continue if relgroup.get('secondary-type-list'): if 'Compilation' in relgroup['secondary-type-list']: - logging.debug('skipped %s -- 2nd compilation', - title) + logging.debug('skipped %s -- 2nd compilation', title) continue if 'Live' in relgroup['secondary-type-list']: logging.debug('skipped %s -- 2nd live', title) @@ -89,9 +85,9 @@ def _pickarecording(self, testdata, mbdata, allowothers=False): #pylint: disabl def lastditcheffort(self, metadata): ''' there is like no data, so... ''' - if not self.config.cparser.value( - 'musicbrainz/enabled', type=bool) or self.config.cparser.value( - 'control/beam', type=bool): + if not self.config.cparser.value('musicbrainz/enabled', + type=bool) or self.config.cparser.value('control/beam', + type=bool): return None self._setemail() @@ -105,19 +101,16 @@ def lastditcheffort(self, metadata): logging.debug('Starting data: %s', addmeta) if addmeta['album']: - mydict = musicbrainzngs.search_recordings( - artist=addmeta['artist'], - recording=addmeta['title'], - release=addmeta['album']) + mydict = musicbrainzngs.search_recordings(artist=addmeta['artist'], + recording=addmeta['title'], + release=addmeta['album']) riddata = self._pickarecording(addmeta, mydict) if not riddata: - riddata = self._pickarecording(addmeta, - mydict, - allowothers=True) + riddata = self._pickarecording(addmeta, mydict, allowothers=True) if not riddata: - mydict = musicbrainzngs.search_recordings( - artist=metadata['artist'], recording=metadata['title']) + mydict = musicbrainzngs.search_recordings(artist=metadata['artist'], + recording=metadata['title']) riddata = self._pickarecording(addmeta, mydict) if not riddata: riddata = self._pickarecording(addmeta, mydict, allowothers=True) @@ -126,9 +119,9 @@ def lastditcheffort(self, metadata): def recognize(self, metadata): ''' fill in any blanks from musicbrainz ''' - if not self.config.cparser.value( - 'musicbrainz/enabled', type=bool) or self.config.cparser.value( - 'control/beam', type=bool): + if not self.config.cparser.value('musicbrainz/enabled', + type=bool) or self.config.cparser.value('control/beam', + type=bool): return None addmeta = {} @@ -146,25 +139,25 @@ def recognize(self, metadata): def isrc(self, isrclist): ''' lookup musicbrainz information based upon isrc ''' - if not self.config.cparser.value( - 'musicbrainz/enabled', type=bool) or self.config.cparser.value( - 'control/beam', type=bool): + if not self.config.cparser.value('musicbrainz/enabled', + type=bool) or self.config.cparser.value('control/beam', + type=bool): return None self._setemail() for isrc in isrclist: try: - mbdata = musicbrainzngs.get_recordings_by_isrc( - isrc, includes=['releases'], release_status=['official']) + mbdata = musicbrainzngs.get_recordings_by_isrc(isrc, + includes=['releases'], + release_status=['official']) except: # pylint: disable=bare-except pass if not mbdata: for isrc in isrclist: try: - mbdata = musicbrainzngs.get_recordings_by_isrc( - isrc, includes=['releases']) + mbdata = musicbrainzngs.get_recordings_by_isrc(isrc, includes=['releases']) except: # pylint: disable=bare-except logging.info('musicbrainz cannot find ISRC %s', isrc) @@ -178,9 +171,9 @@ def isrc(self, isrclist): def recordingid(self, recordingid): # pylint: disable=too-many-branches, too-many-return-statements, too-many-statements ''' lookup the musicbrainz information based upon recording id ''' - if not self.config.cparser.value( - 'musicbrainz/enabled', type=bool) or self.config.cparser.value( - 'control/beam', type=bool): + if not self.config.cparser.value('musicbrainz/enabled', + type=bool) or self.config.cparser.value('control/beam', + type=bool): return None self._setemail() @@ -207,19 +200,17 @@ def releaselookup_noartist(recordingid): self._setemail() try: - mbdata = musicbrainzngs.browse_releases( - recording=recordingid, - includes=['labels', 'artist-credits'], - release_status=['official']) + mbdata = musicbrainzngs.browse_releases(recording=recordingid, + includes=['labels', 'artist-credits'], + release_status=['official']) except Exception as error: # pylint: disable=broad-except logging.error('MusicBrainz threw an error: %s', error) return None if 'release-count' not in mbdata or mbdata['release-count'] == 0: try: - mbdata = musicbrainzngs.browse_releases( - recording=recordingid, - includes=['labels', 'artist-credits']) + mbdata = musicbrainzngs.browse_releases(recording=recordingid, + includes=['labels', 'artist-credits']) except: # pylint: disable=bare-except logging.error('MusicBrainz threw an error: %s', error) return None @@ -230,11 +221,9 @@ def _pickarelease(newdata, mbdata): variousartist = [] for release in mbdata['release-list']: if len(newdata['musicbrainzartistid']) > 1 and newdata.get( - 'artist' - ) and release['artist-credit-phrase'] in newdata['artist']: + 'artist') and release['artist-credit-phrase'] in newdata['artist']: namedartist.append(release) - elif 'artist' in newdata and release[ - 'artist-credit-phrase'] == newdata['artist']: + elif 'artist' in newdata and release['artist-credit-phrase'] == newdata['artist']: namedartist.append(release) elif release['artist-credit-phrase'] == 'Various Artists': variousartist.append(release) @@ -247,17 +236,14 @@ def _pickarelease(newdata, mbdata): newdata = {'musicbrainzrecordingid': recordingid} try: logging.debug('looking up recording id %s', recordingid) - mbdata = musicbrainzngs.get_recording_by_id(recordingid, - includes=['artists']) + mbdata = musicbrainzngs.get_recording_by_id(recordingid, includes=['artists']) except Exception as error: # pylint: disable=broad-except - logging.error('MusicBrainz does not know recording id %s: %s', - recordingid, error) + logging.error('MusicBrainz does not know recording id %s: %s', recordingid, error) return None if 'recording' in mbdata and 'title' in mbdata['recording']: newdata['title'] = mbdata['recording']['title'] - if 'recording' in mbdata and 'artist-credit-phrase' in mbdata[ - 'recording']: + if 'recording' in mbdata and 'artist-credit-phrase' in mbdata['recording']: newdata['artist'] = mbdata['recording']['artist-credit-phrase'] for artist in mbdata['recording']['artist-credit']: if not isinstance(artist, dict): @@ -268,8 +254,7 @@ def _pickarelease(newdata, mbdata): mbdata = releaselookup_noartist(recordingid) - if not mbdata or 'release-count' not in mbdata or mbdata[ - 'release-count'] == 0: + if not mbdata or 'release-count' not in mbdata or mbdata['release-count'] == 0: return newdata mbdata = _pickarelease(newdata, mbdata) @@ -286,17 +271,14 @@ def _pickarelease(newdata, mbdata): if label: newdata['label'] = label - if 'cover-art-archive' in release and 'artwork' in release[ - 'cover-art-archive'] and release['cover-art-archive'][ - 'artwork']: + if 'cover-art-archive' in release and 'artwork' in release['cover-art-archive'] and release[ + 'cover-art-archive']['artwork']: try: - newdata['coverimageraw'] = musicbrainzngs.get_image( - release['id'], 'front') + newdata['coverimageraw'] = musicbrainzngs.get_image(release['id'], 'front') except Exception as error: # pylint: disable=broad-except logging.error('Failed to get cover art: %s', error) - newdata['artistwebsites'] = self._websites( - newdata['musicbrainzartistid']) + newdata['artistwebsites'] = self._websites(newdata['musicbrainzartistid']) return newdata def artistids(self, idlist): @@ -304,16 +286,15 @@ def artistids(self, idlist): self._setemail() - if not self.config.cparser.value( - 'musicbrainz/enabled', type=bool) or self.config.cparser.value( - 'control/beam', type=bool): + if not self.config.cparser.value('musicbrainz/enabled', + type=bool) or self.config.cparser.value('control/beam', + type=bool): return None return {'artistwebsites': self._websites(idlist)} def _websites(self, idlist): - if not self.config.cparser.value('acoustidmb/websites', - type=bool) or not idlist: + if not self.config.cparser.value('acoustidmb/websites', type=bool) or not idlist: return None sitelist = [] @@ -321,15 +302,12 @@ def _websites(self, idlist): if self.config.cparser.value('acoustidmb/musicbrainz', type=bool): sitelist.append(f'https://musicbrainz.org/artist/{artistid}') try: - webdata = musicbrainzngs.get_artist_by_id( - artistid, includes=['url-rels']) + webdata = musicbrainzngs.get_artist_by_id(artistid, includes=['url-rels']) except Exception as error: # pylint: disable=broad-except - logging.error('MusicBrainz does not know artistid id %s: %s', - artistid, error) + logging.error('MusicBrainz does not know artistid id %s: %s', artistid, error) return None - if not webdata.get('artist') or not webdata['artist'].get( - 'url-relation-list'): + if not webdata.get('artist') or not webdata['artist'].get('url-relation-list'): continue convdict = { @@ -342,8 +320,8 @@ def _websites(self, idlist): for urlrel in webdata['artist']['url-relation-list']: logging.debug('checking %s', urlrel['type']) for src, dest in convdict.items(): - if urlrel['type'] == src and self.config.cparser.value( - f'acoustidmb/{dest}', type=bool): + if urlrel['type'] == src and self.config.cparser.value(f'acoustidmb/{dest}', + type=bool): sitelist.append(urlrel['target']) logging.debug('placed %s', dest) @@ -371,8 +349,7 @@ def main(): nowplaying.bootstrap.set_qt_names() # need to make sure config is initialized with something nowplaying.config.ConfigFile(bundledir=bundledir) - musicbrainz = MusicBrainzHelper(config=nowplaying.config.ConfigFile( - bundledir=bundledir)) + musicbrainz = MusicBrainzHelper(config=nowplaying.config.ConfigFile(bundledir=bundledir)) metadata = musicbrainz.recordingid(isrc) if not metadata: print('No information') diff --git a/nowplaying/pluginimporter.py b/nowplaying/pluginimporter.py index b9fce765..b6739d88 100644 --- a/nowplaying/pluginimporter.py +++ b/nowplaying/pluginimporter.py @@ -8,6 +8,7 @@ import nowplaying # pylint: disable=unused-import, cyclic-import + def import_plugins(namespace: types.ModuleType) -> dict[str, types.ModuleType]: ''' import plugins and return an object with all of them ''' diff --git a/nowplaying/processes/discordbot.py b/nowplaying/processes/discordbot.py index b8ccc366..e9763764 100644 --- a/nowplaying/processes/discordbot.py +++ b/nowplaying/processes/discordbot.py @@ -56,8 +56,7 @@ async def _setup_bot_client(self): task = loop.create_task(self.client['bot'].connect(reconnect=True)) self.tasks.add(task) task.add_done_callback(self.tasks.discard) - while not self.stopevent.is_set() and not self.client['bot'].is_ready( - ): + while not self.stopevent.is_set() and not self.client['bot'].is_ready(): await asyncio.sleep(1) logging.debug('bot setup') @@ -92,12 +91,10 @@ async def _setup_ipc_client(self): async def _update_bot(self, templateout): if channelname := self.config.cparser.value( - 'twitchbot/channel') and self.config.cparser.value( - 'twitchbot/enabled', type=bool): - activity = discord.Streaming( - platform='Twitch', - name=templateout, - url=f'https://twitch.tv/{channelname}') + 'twitchbot/channel') and self.config.cparser.value('twitchbot/enabled', type=bool): + activity = discord.Streaming(platform='Twitch', + name=templateout, + url=f'https://twitch.tv/{channelname}') else: activity = discord.Game(templateout) try: @@ -108,8 +105,7 @@ async def _update_bot(self, templateout): async def _update_ipc(self, templateout): try: - await self.client['ipc'].update(state='Streaming', - details=templateout) + await self.client['ipc'].update(state='Streaming', details=templateout) except ConnectionRefusedError: logging.error('Cannot connect to discord client.') del self.client['ipc'] @@ -161,8 +157,7 @@ async def start(self): if not metadata: continue - templatehandler = nowplaying.utils.TemplateHandler( - filename=template) + templatehandler = nowplaying.utils.TemplateHandler(filename=template) mytime = watcher.updatetime templateout = templatehandler.generate(metadata) for mode, func in client.items(): @@ -202,11 +197,8 @@ def start(stopevent, bundledir, testmode=False): #pylint: disable=unused-argume nowplaying.bootstrap.set_qt_names(appname='testsuite') else: nowplaying.bootstrap.set_qt_names() - logpath = nowplaying.bootstrap.setuplogging(logname='debug.log', - rotate=False) - config = nowplaying.config.ConfigFile(bundledir=bundledir, - logpath=logpath, - testmode=testmode) + logpath = nowplaying.bootstrap.setuplogging(logname='debug.log', rotate=False) + config = nowplaying.config.ConfigFile(bundledir=bundledir, logpath=logpath, testmode=testmode) logging.info('boot up') try: discordsupport = DiscordSupport(stopevent=stopevent, config=config) diff --git a/nowplaying/processes/obsws.py b/nowplaying/processes/obsws.py index 4679ff73..7a5b5f59 100755 --- a/nowplaying/processes/obsws.py +++ b/nowplaying/processes/obsws.py @@ -45,8 +45,7 @@ def __init__(self, config=None, stopevent=None, testmode=None): def start(self): ''' run our thread ''' - if self.config.cparser.value('obsws/enabled', - type=bool) and not self.watcher: + if self.config.cparser.value('obsws/enabled', type=bool) and not self.watcher: self.watcher = self.metadb.watcher() self.watcher.start(customhandler=self.process_update) self.process_update(None) @@ -112,8 +111,7 @@ def generate_text(self, clear=False): return None template = self.config.cparser.value('obsws/template') - if templatehandler := nowplaying.utils.TemplateHandler( - filename=template): + if templatehandler := nowplaying.utils.TemplateHandler(filename=template): return templatehandler.generate(metadatadict=metadata) if clear: @@ -150,8 +148,7 @@ async def check_reconnect(self): self.obswsport = obswsport self.obswshost = obswshost try: - parameters = simpleobsws.IdentificationParameters( - ignoreNonFatalRequestChecks=False) + parameters = simpleobsws.IdentificationParameters(ignoreNonFatalRequestChecks=False) self.client = simpleobsws.WebSocketClient( url=f'ws://{self.obswshost}:{self.obswsport}', password=self.obswssecret, @@ -187,11 +184,8 @@ def start(stopevent, bundledir, testmode=False): #pylint: disable=unused-argume nowplaying.bootstrap.set_qt_names(appname='testsuite') else: nowplaying.bootstrap.set_qt_names() - logpath = nowplaying.bootstrap.setuplogging(logname='debug.log', - rotate=False) - config = nowplaying.config.ConfigFile(bundledir=bundledir, - logpath=logpath, - testmode=testmode) + logpath = nowplaying.bootstrap.setuplogging(logname='debug.log', rotate=False) + config = nowplaying.config.ConfigFile(bundledir=bundledir, logpath=logpath, testmode=testmode) try: OBSWebSocketHandler( # pylint: disable=unused-variable stopevent=stopevent, diff --git a/nowplaying/processes/trackpoll.py b/nowplaying/processes/trackpoll.py index e9b98b7c..11aa4ed2 100755 --- a/nowplaying/processes/trackpoll.py +++ b/nowplaying/processes/trackpoll.py @@ -58,14 +58,13 @@ def __init__(self, stopevent=None, config=None, testmode=False): self.trackrequests = None if not self.config.cparser.value('control/beam', type=bool): self._setup_imagecache() - self.trackrequests = nowplaying.trackrequests.Requests( - config=self.config, stopevent=self.stopevent) + self.trackrequests = nowplaying.trackrequests.Requests(config=self.config, + stopevent=self.stopevent) self.trackrequests.clear_roulette_artist_dupes() self.tasks = set() nowplaying.textoutput.deltxttrack(self.config) - self.metadataprocessors = nowplaying.metadata.MetadataProcessors( - config=self.config) + self.metadataprocessors = nowplaying.metadata.MetadataProcessors(config=self.config) self.create_tasks() if not testmode: self.loop.run_forever() @@ -81,13 +80,11 @@ def create_tasks(self): task.add_done_callback(self.tasks.remove) self.tasks.add(task) if self.trackrequests: - task = self.loop.create_task( - self.trackrequests.watch_for_respin(self.stopevent)) + task = self.loop.create_task(self.trackrequests.watch_for_respin(self.stopevent)) task.add_done_callback(self.tasks.remove) self.tasks.add(task) if self.imagecache: - task = self.loop.create_task( - self.imagecache.verify_cache_timer(self.stopevent)) + task = self.loop.create_task(self.imagecache.verify_cache_timer(self.stopevent)) task.add_done_callback(self.tasks.remove) self.tasks.add(task) @@ -99,9 +96,8 @@ async def switch_input_plugin(self): logging.info('stopping %s', self.previousinput) await self.input.stop() self.previousinput = self.config.cparser.value('settings/input') - self.input = self.plugins[ - f'nowplaying.inputs.{self.previousinput}'].Plugin( - config=self.config) + self.input = self.plugins[f'nowplaying.inputs.{self.previousinput}'].Plugin( + config=self.config) logging.info('Starting %s plugin', self.previousinput) if not self.input: return False @@ -125,8 +121,7 @@ async def run(self): # sleep until we have something to do while not self.stopevent.is_set() and not self.config.getpause( - ) and not self.config.cparser.value('settings/input', - defaultValue=None): + ) and not self.config.cparser.value('settings/input', defaultValue=None): await asyncio.sleep(.5) self.config.get() @@ -140,12 +135,9 @@ async def run(self): try: await self.gettrack() except Exception as error: #pylint: disable=broad-except - logging.error('Failed attempting to get a track: %s', - error, - exc_info=True) + logging.error('Failed attempting to get a track: %s', error, exc_info=True) - if not self.testmode and self.config.cparser.value('setlist/enabled', - type=bool): + if not self.testmode and self.config.cparser.value('setlist/enabled', type=bool): nowplaying.db.create_setlist(self.config) await self.stop() logging.debug('Trackpoll stopped gracefully.') @@ -175,12 +167,11 @@ def _verify_filename(self, metadata): if metadata.get('filename'): filepath = pathlib.Path(metadata['filename']) if not filepath.exists(): - metadata['filename'] = nowplaying.utils.songpathsubst( - self.config, metadata['filename']) + metadata['filename'] = nowplaying.utils.songpathsubst(self.config, + metadata['filename']) filepath = pathlib.Path(metadata['filename']) if not filepath.exists(): - logging.error('cannot find %s; removing from metadata', - metadata['filename']) + logging.error('cannot find %s; removing from metadata', metadata['filename']) del metadata['filename'] return metadata @@ -234,8 +225,7 @@ def _isignored(metadata): async def checkskip(self, nextmeta): ''' check if this metadata is meant to be skipped ''' for skiptype in ['comment', 'genre']: - skipdata = self.config.cparser.value(f'trackskip/{skiptype}', - defaultValue=None) + skipdata = self.config.cparser.value(f'trackskip/{skiptype}', defaultValue=None) if not skipdata: continue if skipdata in nextmeta.get(skiptype, ''): @@ -263,19 +253,18 @@ async def _fillinmetadata(self, metadata): if metadata.get('title'): (metadata['title'], - metadata['filename']) = self._check_title_for_path( - metadata['title'], metadata.get('filename')) + metadata['filename']) = self._check_title_for_path(metadata['title'], + metadata.get('filename')) for key in COREMETA: if key in metadata and not metadata[key]: del metadata[key] try: - metadata = await self.metadataprocessors.getmoremetadata( - metadata=metadata, imagecache=self.imagecache) + metadata = await self.metadataprocessors.getmoremetadata(metadata=metadata, + imagecache=self.imagecache) if duration := metadata.get('duration'): - metadata['duration_hhmmss'] = nowplaying.utils.humanize_time( - duration) + metadata['duration_hhmmss'] = nowplaying.utils.humanize_time(duration) except Exception: # pylint: disable=broad-except for line in traceback.format_exc().splitlines(): logging.error(line) @@ -283,8 +272,7 @@ async def _fillinmetadata(self, metadata): for key in COREMETA: if key not in metadata: - logging.info('Track missing %s data, setting it to blank.', - key) + logging.info('Track missing %s data, setting it to blank.', key) metadata[key] = '' return metadata @@ -306,8 +294,7 @@ async def gettrack(self): # pylint: disable=too-many-branches, await asyncio.sleep(5) return - if self._ismetaempty(nextmeta) or self._ismetasame( - nextmeta) or self._isignored(nextmeta): + if self._ismetaempty(nextmeta) or self._ismetasame(nextmeta) or self._isignored(nextmeta): return # fill in the blanks and make it live @@ -321,12 +308,11 @@ async def gettrack(self): # pylint: disable=too-many-branches, logging.error('Ignoring the crash and just keep going!') self.currentmeta = nextmeta - logging.info('Potential new track: %s / %s', - self.currentmeta['artist'], self.currentmeta['title']) + logging.info('Potential new track: %s / %s', self.currentmeta['artist'], + self.currentmeta['title']) if await self.checkskip(nextmeta): - logging.info('Skipping %s / %s', self.currentmeta['artist'], - self.currentmeta['title']) + logging.info('Skipping %s / %s', self.currentmeta['artist'], self.currentmeta['title']) return # try to interleave downloads in-between the delay @@ -339,16 +325,14 @@ async def gettrack(self): # pylint: disable=too-many-branches, # checkagain nextcheck = await self.input.getplayingtrack() - if not self._ismetaempty(nextcheck) and not self._ismetasame( - nextcheck): + if not self._ismetaempty(nextcheck) and not self._ismetasame(nextcheck): logging.info('Track changed during delay, skipping') self.currentmeta = oldmeta return if self.config.cparser.value( 'settings/requests', - type=bool) and not self.config.cparser.value('control/beam', - type=bool): + type=bool) and not self.config.cparser.value('control/beam', type=bool): if data := await self.trackrequests.get_request(self.currentmeta): self.currentmeta.update(data) @@ -361,38 +345,30 @@ async def gettrack(self): # pylint: disable=too-many-branches, def _artfallbacks(self): if self.config.cparser.value( - 'artistextras/coverfornologos', - type=bool) and not self.currentmeta.get( - 'artistlogoraw') and self.currentmeta.get('coverimageraw'): - self.currentmeta['artistlogoraw'] = self.currentmeta[ - 'coverimageraw'] + 'artistextras/coverfornologos', type=bool + ) and not self.currentmeta.get('artistlogoraw') and self.currentmeta.get('coverimageraw'): + self.currentmeta['artistlogoraw'] = self.currentmeta['coverimageraw'] if self.config.cparser.value( 'artistextras/coverfornothumbs', type=bool - ) and not self.currentmeta.get( - 'artistthumbraw') and self.currentmeta.get('coverimageraw'): - self.currentmeta['artistthumbraw'] = self.currentmeta[ - 'coverimageraw'] + ) and not self.currentmeta.get('artistthumbraw') and self.currentmeta.get('coverimageraw'): + self.currentmeta['artistthumbraw'] = self.currentmeta['coverimageraw'] def _write_to_text(self): if configfile := self.config.cparser.value('textoutput/file'): - if configtemplate := self.config.cparser.value( - 'textoutput/txttemplate'): + if configtemplate := self.config.cparser.value('textoutput/txttemplate'): if not self.previoustxttemplate or self.previoustxttemplate != configtemplate: self.txttemplatehandler = nowplaying.utils.TemplateHandler( filename=configtemplate) self.previoustxttemplate = configtemplate - nowplaying.textoutput.writetxttrack( - config=self.config, - filename=configfile, - templatehandler=self.txttemplatehandler, - metadata=self.currentmeta) + nowplaying.textoutput.writetxttrack(config=self.config, + filename=configfile, + templatehandler=self.txttemplatehandler, + metadata=self.currentmeta) async def _half_delay_write(self): try: - delay = self.config.cparser.value('settings/delay', - type=float, - defaultValue=1.0) + delay = self.config.cparser.value('settings/delay', type=float, defaultValue=1.0) except ValueError: delay = 1.0 delay /= 2 @@ -404,63 +380,56 @@ def _setup_imagecache(self): return workers = self.config.cparser.value('artistextras/processes', type=int) - sizelimit = self.config.cparser.value('artistextras/cachesize', - type=int) - - self.imagecache = nowplaying.imagecache.ImageCache( - sizelimit=sizelimit, stopevent=self.stopevent) - self.config.cparser.setValue('artistextras/cachedbfile', - self.imagecache.databasefile) - self.icprocess = multiprocessing.Process( - target=self.imagecache.queue_process, - name='ICProcess', - args=( - self.config.logpath, - workers, - )) + sizelimit = self.config.cparser.value('artistextras/cachesize', type=int) + + self.imagecache = nowplaying.imagecache.ImageCache(sizelimit=sizelimit, + stopevent=self.stopevent) + self.config.cparser.setValue('artistextras/cachedbfile', self.imagecache.databasefile) + self.icprocess = multiprocessing.Process(target=self.imagecache.queue_process, + name='ICProcess', + args=( + self.config.logpath, + workers, + )) self.icprocess.start() def _start_artistfanartpool(self): - if not self.config.cparser.value( - 'artistextras/enabled', - type=bool) or self.config.cparser.value('control/beam', - type=bool): + if not self.config.cparser.value('artistextras/enabled', + type=bool) or self.config.cparser.value('control/beam', + type=bool): return if self.currentmeta.get('artistfanarturls'): dedupe = list(dict.fromkeys(self.currentmeta['artistfanarturls'])) self.currentmeta['artistfanarturls'] = dedupe - self.imagecache.fill_queue( - config=self.config, - artist=self.currentmeta['artist'], - imagetype='artistfanart', - urllist=self.currentmeta['artistfanarturls']) + self.imagecache.fill_queue(config=self.config, + artist=self.currentmeta['artist'], + imagetype='artistfanart', + urllist=self.currentmeta['artistfanarturls']) del self.currentmeta['artistfanarturls'] async def _process_imagecache(self): if not self.currentmeta.get('artist') or self.config.cparser.value( - 'control/beam', type=bool) or not self.config.cparser.value( - 'artistextras/enabled', type=bool): + 'control/beam', + type=bool) or not self.config.cparser.value('artistextras/enabled', type=bool): return def fillin(self): tryagain = False if not self.imagecache: - logging.debug( - 'Artist Extras was enabled without restart; skipping image downloads' - ) + logging.debug('Artist Extras was enabled without restart; skipping image downloads') return True for key in ['artistthumb', 'artistlogo', 'artistbanner']: logging.debug('Calling %s', key) rawkey = f'{key}raw' if not self.currentmeta.get(rawkey): - image = self.imagecache.random_image_fetch( - artist=self.currentmeta['artist'], imagetype=key) + image = self.imagecache.random_image_fetch(artist=self.currentmeta['artist'], + imagetype=key) if not image: - logging.debug('did not get an image for %s %s %s', key, - rawkey, self.currentmeta['artist']) + logging.debug('did not get an image for %s %s %s', key, rawkey, + self.currentmeta['artist']) tryagain = True self.currentmeta[rawkey] = image return tryagain @@ -489,11 +458,8 @@ def start(stopevent, bundledir, testmode=False): #pylint: disable=unused-argume nowplaying.bootstrap.set_qt_names(appname='testsuite') else: nowplaying.bootstrap.set_qt_names() - logpath = nowplaying.bootstrap.setuplogging(logname='debug.log', - rotate=False) - config = nowplaying.config.ConfigFile(bundledir=bundledir, - logpath=logpath, - testmode=testmode) + logpath = nowplaying.bootstrap.setuplogging(logname='debug.log', rotate=False) + config = nowplaying.config.ConfigFile(bundledir=bundledir, logpath=logpath, testmode=testmode) try: TrackPoll( # pylint: disable=unused-variable stopevent=stopevent, diff --git a/nowplaying/processes/twitchbot.py b/nowplaying/processes/twitchbot.py index e9d0a05b..2c2ed539 100755 --- a/nowplaying/processes/twitchbot.py +++ b/nowplaying/processes/twitchbot.py @@ -49,15 +49,11 @@ def start(stopevent, bundledir, testmode=False): #pylint: disable=unused-argume nowplaying.bootstrap.set_qt_names(appname='testsuite') else: nowplaying.bootstrap.set_qt_names() - logpath = nowplaying.bootstrap.setuplogging(logname='debug.log', - rotate=False) - config = nowplaying.config.ConfigFile(bundledir=bundledir, - logpath=logpath, - testmode=testmode) + logpath = nowplaying.bootstrap.setuplogging(logname='debug.log', rotate=False) + config = nowplaying.config.ConfigFile(bundledir=bundledir, logpath=logpath, testmode=testmode) logging.info('boot up') try: - twitchbot = nowplaying.twitch.TwitchSupport(stopevent=stopevent, - config=config) # pylint: disable=unused-variable + twitchbot = nowplaying.twitch.TwitchSupport(stopevent=stopevent, config=config) # pylint: disable=unused-variable twitchbot.start() except Exception as error: #pylint: disable=broad-except logging.error('TrackPoll crashed: %s', error, exc_info=True) diff --git a/nowplaying/processes/webserver.py b/nowplaying/processes/webserver.py index 2c0e686c..3f24c77b 100755 --- a/nowplaying/processes/webserver.py +++ b/nowplaying/processes/webserver.py @@ -52,23 +52,17 @@ class WebHandler(): # pylint: disable=too-many-public-methods ''' aiohttp built server that does both http and websocket ''' - def __init__(self, - bundledir=None, - config=None, - stopevent=None, - testmode=False): + def __init__(self, bundledir=None, config=None, stopevent=None, testmode=False): threading.current_thread().name = 'WebServer' self.tasks = set() self.testmode = testmode if not config: - config = nowplaying.config.ConfigFile(bundledir=bundledir, - testmode=testmode) + config = nowplaying.config.ConfigFile(bundledir=bundledir, testmode=testmode) self.port = config.cparser.value('weboutput/httpport', type=int) enabled = config.cparser.value('weboutput/httpenabled', type=bool) self.databasefile = pathlib.Path( - QStandardPaths.standardLocations( - QStandardPaths.CacheLocation)[0]).joinpath( - 'webserver', 'web.db') + QStandardPaths.standardLocations(QStandardPaths.CacheLocation)[0]).joinpath( + 'webserver', 'web.db') self._init_webdb() self.stopevent = stopevent @@ -76,13 +70,11 @@ def __init__(self, try: time.sleep(5) config.get() - enabled = config.cparser.value('weboutput/httpenabled', - type=bool) + enabled = config.cparser.value('weboutput/httpenabled', type=bool) except KeyboardInterrupt: sys.exit(0) - self.magicstopurl = ''.join( - secrets.choice(string.ascii_letters) for _ in range(32)) + self.magicstopurl = ''.join(secrets.choice(string.ascii_letters) for _ in range(32)) logging.info('Secret url to quit websever: %s', self.magicstopurl) @@ -92,8 +84,7 @@ def __init__(self, except RuntimeError: self.loop = asyncio.new_event_loop() - self.loop.run_until_complete( - self.start_server(host='0.0.0.0', port=self.port)) + self.loop.run_until_complete(self.start_server(host='0.0.0.0', port=self.port)) self.loop.run_forever() def _init_webdb(self): @@ -119,8 +110,7 @@ def _base64ifier(metadata): for key in nowplaying.db.METADATABLOBLIST: if metadata.get(key): newkey = key.replace('raw', 'base64') - metadata[newkey] = base64.b64encode( - metadata[key]).decode('utf-8') + metadata[newkey] = base64.b64encode(metadata[key]).decode('utf-8') del metadata[key] if metadata.get('dbid'): del metadata['dbid'] @@ -136,46 +126,39 @@ def _transparentifier(self, metadata): async def index_htm_handler(self, request): ''' handle web output ''' return await self._metacheck_htm_handler( - request, - request.app['config'].cparser.value('weboutput/htmltemplate')) + request, request.app['config'].cparser.value('weboutput/htmltemplate')) async def artistbanner_htm_handler(self, request): ''' handle web output ''' return await self._metacheck_htm_handler( - request, request.app['config'].cparser.value( - 'weboutput/artistbannertemplate')) + request, request.app['config'].cparser.value('weboutput/artistbannertemplate')) async def artistlogo_htm_handler(self, request): ''' handle web output ''' return await self._metacheck_htm_handler( - request, request.app['config'].cparser.value( - 'weboutput/artistlogotemplate')) + request, request.app['config'].cparser.value('weboutput/artistlogotemplate')) async def artistthumb_htm_handler(self, request): ''' handle web output ''' return await self._metacheck_htm_handler( - request, request.app['config'].cparser.value( - 'weboutput/artistthumbtemplate')) + request, request.app['config'].cparser.value('weboutput/artistthumbtemplate')) async def artistfanartlaunch_htm_handler(self, request): ''' handle web output ''' return await self._metacheck_htm_handler( - request, request.app['config'].cparser.value( - 'weboutput/artistfanarttemplate')) + request, request.app['config'].cparser.value('weboutput/artistfanarttemplate')) async def gifwords_launch_htm_handler(self, request): ''' handle gifwords output ''' htmloutput = await self._htm_handler( - request, - request.app['config'].cparser.value('weboutput/gifwordstemplate')) + request, request.app['config'].cparser.value('weboutput/gifwordstemplate')) return web.Response(content_type='text/html', text=htmloutput) async def requesterlaunch_htm_handler(self, request): ''' handle web output ''' return await self._metacheck_htm_handler( - request, - request.app['config'].cparser.value('weboutput/requestertemplate')) + request, request.app['config'].cparser.value('weboutput/requestertemplate')) @staticmethod async def _htm_handler(request, template, metadata=None): # pylint: disable=unused-argument @@ -186,10 +169,9 @@ async def _htm_handler(request, template, metadata=None): # pylint: disable=unu metadata = await request.app['metadb'].read_last_meta_async() if not metadata: metadata = nowplaying.hostmeta.gethostmeta() - metadata['httpport'] = request.app['config'].cparser.value( - 'weboutput/httpport', type=int) - templatehandler = nowplaying.utils.TemplateHandler( - filename=template) + metadata['httpport'] = request.app['config'].cparser.value('weboutput/httpport', + type=int) + templatehandler = nowplaying.utils.TemplateHandler(filename=template) htmloutput = templatehandler.generate(metadata) except: #pylint: disable=bare-except for line in traceback.format_exc().splitlines(): @@ -215,15 +197,11 @@ async def _metacheck_htm_handler(self, request, template): # pylint: disable=un # | | NA | | -> send refresh because not ready or something broke if not metadata or not metadata.get('dbid') or not template: - return web.Response(status=202, - content_type='text/html', - text=INDEXREFRESH) + return web.Response(status=202, content_type='text/html', text=INDEXREFRESH) if lastid == 0 or lastid != metadata['dbid'] or not once: await self.setlastid(request, metadata['dbid'], source) - htmloutput = await self._htm_handler(request, - template, - metadata=metadata) + htmloutput = await self._htm_handler(request, template, metadata=metadata) return web.Response(content_type='text/html', text=htmloutput) return web.Response(content_type='text/html', text=INDEXREFRESH) @@ -232,8 +210,7 @@ async def _metacheck_htm_handler(self, request, template): # pylint: disable=un async def setlastid(request, lastid, source): ''' get the lastid sent by http/html ''' await request.app['statedb'].execute( - 'INSERT OR REPLACE INTO lastprocessed(lastid, source) VALUES (?,?) ', - [lastid, source]) + 'INSERT OR REPLACE INTO lastprocessed(lastid, source) VALUES (?,?) ', [lastid, source]) await request.app['statedb'].commit() @staticmethod @@ -258,8 +235,7 @@ async def indextxt_handler(request): request.app['config'].get() try: templatehandler = nowplaying.utils.TemplateHandler( - filename=request.app['config'].cparser.value( - 'textoutput/txttemplate')) + filename=request.app['config'].cparser.value('textoutput/txttemplate')) txtoutput = templatehandler.generate(metadata) except Exception as error: #pylint: disable=broad-except logging.error('indextxt_handler: %s', error) @@ -325,16 +301,14 @@ async def websocket_gifwords_streamer(self, request): trackrequest = nowplaying.trackrequests.Requests(request.app['config']) try: - while (not self.stopevent.is_set() and not endloop - and not websocket.closed): + while (not self.stopevent.is_set() and not endloop and not websocket.closed): metadata = await trackrequest.check_for_gifwords() if not metadata.get('image'): await websocket.send_json({'noimage': True}) await asyncio.sleep(5) continue - metadata['imagebase64'] = base64.b64encode( - metadata['image']).decode('utf-8') + metadata['imagebase64'] = base64.b64encode(metadata['image']).decode('utf-8') del metadata['image'] try: if websocket.closed: @@ -362,8 +336,7 @@ async def websocket_artistfanart_streamer(self, request): endloop = False try: - while not self.stopevent.is_set( - ) and not endloop and not websocket.closed: + while not self.stopevent.is_set() and not endloop and not websocket.closed: metadata = await request.app['metadb'].read_last_meta_async() if not metadata or not metadata.get('artist'): await asyncio.sleep(5) @@ -379,12 +352,11 @@ async def websocket_artistfanart_streamer(self, request): if imagedata: metadata['artistfanartraw'] = imagedata - elif request.app['config'].cparser.value( - 'artistextras/coverfornofanart', type=bool): + elif request.app['config'].cparser.value('artistextras/coverfornofanart', + type=bool): metadata['artistfanartraw'] = metadata.get('coverimageraw') else: - metadata[ - 'artistfanartraw'] = nowplaying.utils.TRANSPARENT_PNG_BIN + metadata['artistfanartraw'] = nowplaying.utils.TRANSPARENT_PNG_BIN try: if websocket.closed: @@ -393,14 +365,12 @@ async def websocket_artistfanart_streamer(self, request): except ConnectionResetError: logging.debug('Lost a client') endloop = True - delay = request.app['config'].cparser.value( - 'artistextras/fanartdelay', type=int) + delay = request.app['config'].cparser.value('artistextras/fanartdelay', type=int) await asyncio.sleep(delay) if not websocket.closed: await websocket.send_json({'last': True}) except Exception as error: #pylint: disable=broad-except - logging.error('websocket artistfanart streamer exception: %s', - error) + logging.error('websocket artistfanart streamer exception: %s', error) finally: await websocket.close() request.app['websockets'].discard(websocket) @@ -436,15 +406,12 @@ async def websocket_streamer(self, request): request.app['websockets'].add(websocket) try: - mytime = await self._wss_do_update(websocket, - request.app['metadb']) + mytime = await self._wss_do_update(websocket, request.app['metadb']) while not self.stopevent.is_set() and not websocket.closed: - while mytime > request.app[ - 'watcher'].updatetime and not self.stopevent.is_set(): + while mytime > request.app['watcher'].updatetime and not self.stopevent.is_set(): await asyncio.sleep(1) - mytime = await self._wss_do_update(websocket, - request.app['metadb']) + mytime = await self._wss_do_update(websocket, request.app['metadb']) await asyncio.sleep(1) if not websocket.closed: await websocket.send_json({'last': True}) @@ -469,14 +436,11 @@ async def websocket_handler(self, request): await websocket.close() elif msg.data == 'last': logging.debug('got last') - await self.websocket_lastjson_handler( - request, websocket) + await self.websocket_lastjson_handler(request, websocket) else: - await websocket.send_str( - 'some websocket message payload') + await websocket.send_str('some websocket message payload') elif msg.type == aiohttp.WSMsgType.ERROR: - logging.error('ws connection closed with exception %s', - websocket.exception()) + logging.error('ws connection closed with exception %s', websocket.exception()) except Exception as error: #pylint: disable=broad-except logging.error('Websocket handler error: %s', error) finally: @@ -511,8 +475,7 @@ def create_runner(self): web.get('/request.htm', self.requesterlaunch_htm_handler), web.get('/ws', self.websocket_handler), web.get('/wsstream', self.websocket_streamer), - web.get('/wsartistfanartstream', - self.websocket_artistfanart_streamer), + web.get('/wsartistfanartstream', self.websocket_artistfanart_streamer), web.get('/wsgifwordsstream', self.websocket_gifwords_streamer), web.get(f'/{self.magicstopurl}', self.stop_server), ]) @@ -557,8 +520,7 @@ async def on_startup(self, app): async def on_shutdown(app): ''' handle shutdown ''' for websocket in set(app['websockets']): - await websocket.close(code=WSCloseCode.GOING_AWAY, - message='Server shutdown') + await websocket.close(code=WSCloseCode.GOING_AWAY, message='Server shutdown') @staticmethod async def on_cleanup(app): @@ -579,8 +541,7 @@ def forced_stop(self, signum=None, frame=None): # pylint: disable=unused-argume ''' caught an int signal so tell the world to stop ''' try: logging.debug('telling webserver to stop via http') - requests.get(f'http://localhost:{self.port}/{self.magicstopurl}', - timeout=5) + requests.get(f'http://localhost:{self.port}/{self.magicstopurl}', timeout=5) except Exception as error: # pylint: disable=broad-except logging.info(error) for task in self.tasks: @@ -608,11 +569,8 @@ def start(stopevent=None, bundledir=None, testmode=False): else: testmode = False nowplaying.bootstrap.set_qt_names() - logpath = nowplaying.bootstrap.setuplogging(logname='debug.log', - rotate=False) - config = nowplaying.config.ConfigFile(bundledir=bundledir, - logpath=logpath, - testmode=testmode) + logpath = nowplaying.bootstrap.setuplogging(logname='debug.log', rotate=False) + config = nowplaying.config.ConfigFile(bundledir=bundledir, logpath=logpath, testmode=testmode) logging.info('boot up') diff --git a/nowplaying/recognition/__init__.py b/nowplaying/recognition/__init__.py index 4702111f..561a38d6 100755 --- a/nowplaying/recognition/__init__.py +++ b/nowplaying/recognition/__init__.py @@ -31,9 +31,7 @@ def calculate_delay(self): ''' determine a reasonable, minimal delay ''' try: - delay = self.config.cparser.value('settings/delay', - type=float, - defaultValue=10.0) + delay = self.config.cparser.value('settings/delay', type=float, defaultValue=10.0) except ValueError: delay = 10.0 diff --git a/nowplaying/recognition/acoustidmb.py b/nowplaying/recognition/acoustidmb.py index cbdb0bb5..fcf978ee 100755 --- a/nowplaying/recognition/acoustidmb.py +++ b/nowplaying/recognition/acoustidmb.py @@ -32,8 +32,7 @@ class Plugin(RecognitionPlugin): def __init__(self, config=None, qsettings=None): super().__init__(config=config, qsettings=qsettings) - self.musicbrainz = nowplaying.musicbrainz.MusicBrainzHelper( - self.config) + self.musicbrainz = nowplaying.musicbrainz.MusicBrainzHelper(self.config) self.acoustidmd = {} self.fpcalcexe = None self.displayname = "AcoustID/MusicBrainz" @@ -47,12 +46,11 @@ def _fpcalc(filename): completedprocess = None try: if sys.platform == "win32": - completedprocess = subprocess.run( - command, - stdin=subprocess.DEVNULL, - capture_output=True, - check=True, - creationflags=subprocess.CREATE_NO_WINDOW) + completedprocess = subprocess.run(command, + stdin=subprocess.DEVNULL, + capture_output=True, + check=True, + creationflags=subprocess.CREATE_NO_WINDOW) else: completedprocess = subprocess.run(command, stdin=subprocess.DEVNULL, @@ -60,8 +58,7 @@ def _fpcalc(filename): check=True) except Exception as error: # pylint: disable=broad-except if completedprocess: - logging.error('Exception: %s stderr: %s', error, - completedprocess.stderr) + logging.error('Exception: %s stderr: %s', error, completedprocess.stderr) else: logging.error('Exception: %s', error) return None @@ -82,20 +79,15 @@ def _fetch_from_acoustid(self, apikey, fingerprint, duration): counter = 0 while counter < 3: logging.debug('Performing acoustid lookup') - results = acoustid.lookup(apikey, - fingerprint, - duration, - meta=[ - 'recordings', 'recordingids', - 'releases', 'tracks', 'usermeta' - ], - timeout=delay) - if ('error' not in results - or 'rate limit' not in results['error']['message']): + results = acoustid.lookup( + apikey, + fingerprint, + duration, + meta=['recordings', 'recordingids', 'releases', 'tracks', 'usermeta'], + timeout=delay) + if ('error' not in results or 'rate limit' not in results['error']['message']): break - logging.info( - 'acoustid complaining about rate limiting. Sleeping then rying again.' - ) + logging.info('acoustid complaining about rate limiting. Sleeping then rying again.') time.sleep(.5) counter += 1 except acoustid.NoBackendError: @@ -106,14 +98,12 @@ def _fetch_from_acoustid(self, apikey, fingerprint, duration): logging.error("web service request failed: %s", error) except Exception as error: # pylint: disable=broad-except results = None - logging.error('Problem getting a response from Acoustid: %s', - error) + logging.error('Problem getting a response from Acoustid: %s', error) if not results: return None if 'error' in results: - logging.error('Aborting. acoustid responded with: %s', - results['error']['message']) + logging.error('Aborting. acoustid responded with: %s', results['error']['message']) return None return results['results'] @@ -151,8 +141,7 @@ def _read_acoustid_tuples(self, metadata, results): # pylint: disable=too-many- acoustidid = result['id'] score = result['score'] if 'recordings' not in result: - logging.debug('No recordings for this match, skipping %s', - acoustidid) + logging.debug('No recordings for this match, skipping %s', acoustidid) continue logging.debug('Processing %s', acoustidid) @@ -182,33 +171,29 @@ def _read_acoustid_tuples(self, metadata, results): # pylint: disable=too-many- album = release['title'] else: album = None - if title and nowplaying.utils.normalize( - title) in completenstr: + if title and nowplaying.utils.normalize(title) in completenstr: score = score + .10 artistlist = [] artistidlist = [] - for trackartist in release['mediums'][0]['tracks'][0][ - 'artists']: + for trackartist in release['mediums'][0]['tracks'][0]['artists']: if 'name' in trackartist: artistlist.append(trackartist['name']) artistidlist.append(trackartist['id']) elif isinstance(trackartist, str): artistlist.append(trackartist) if trackartist and artistnstr: - if nowplaying.utils.normalize( - trackartist) == artistnstr: + if nowplaying.utils.normalize(trackartist) == artistnstr: score = score + .30 else: score = score - .50 - if trackartist and nowplaying.utils.normalize( - trackartist) in completenstr: + if trackartist and nowplaying.utils.normalize(trackartist) in completenstr: score = score + .10 artist = ' & '.join(artistlist) logging.debug( - 'weighted score = %s, rid = %s, title = %s, artist = %s album = %s', - score, rid, title, artist, album) + 'weighted score = %s, rid = %s, title = %s, artist = %s album = %s', score, + rid, title, artist, album) if score > lastscore: newdata = {'acoustidid': acoustidid} @@ -227,11 +212,10 @@ def _read_acoustid_tuples(self, metadata, results): # pylint: disable=too-many- for key, value in newdata.items(): self.acoustidmd[key] = value - logging.debug( - 'picked weighted score = %s, rid = %s, title = %s, artist = %s album = %s', - lastscore, self.acoustidmd.get('musicbrainzrecordingid'), - self.acoustidmd.get('title'), self.acoustidmd.get('artist'), - self.acoustidmd.get('album')) + logging.debug('picked weighted score = %s, rid = %s, title = %s, artist = %s album = %s', + lastscore, self.acoustidmd.get('musicbrainzrecordingid'), + self.acoustidmd.get('title'), self.acoustidmd.get('artist'), + self.acoustidmd.get('album')) def _configure_fpcalc(self, fpcalcexe=None): # pylint: disable=too-many-return-statements ''' deal with all the potential issues of finding and running fpcalc ''' @@ -262,14 +246,11 @@ def _configure_fpcalc(self, fpcalcexe=None): # pylint: disable=too-many-return- if sys.platform == 'win32': try: - exts = [ - ext.lower() for ext in os.environ["PATHEXT"].split(";") - ] + exts = [ext.lower() for ext in os.environ["PATHEXT"].split(";")] testex = '.' + fpcalcexepath.name.split('.')[1].lower() logging.debug('Checking %s against %s', testex, exts) if testex not in exts: - logging.error('defined fpcalc [%s] is not executable.', - fpcalcexe) + logging.error('defined fpcalc [%s] is not executable.', fpcalcexe) return False except Exception as error: # pylint: disable=broad-except logging.error('Testing fpcalc on windows hit: %s', error) @@ -289,16 +270,14 @@ def recognize(self, metadata=None): #pylint: disable=too-many-statements, too-m if not self.acoustidmd.get('musicbrainzrecordingid'): - logging.debug( - 'No musicbrainzrecordingid in metadata, so use acoustid') - if not metadata.get('fpcalcduration') and not metadata.get( - 'fpcalcfingerprint'): + logging.debug('No musicbrainzrecordingid in metadata, so use acoustid') + if not metadata.get('fpcalcduration') and not metadata.get('fpcalcfingerprint'): if not metadata.get('filename'): logging.warning('No filename in metadata') return None - if not self._configure_fpcalc(fpcalcexe=self.config.cparser. - value('acoustidmb/fpcalcexe')): + if not self._configure_fpcalc( + fpcalcexe=self.config.cparser.value('acoustidmb/fpcalcexe')): logging.error('fpcalc is not configured') return None @@ -326,9 +305,8 @@ def recognize(self, metadata=None): #pylint: disable=too-many-statements, too-m ) if not results: if metadata.get('filename'): - logging.warning( - 'acoustid could not recognize %s. Will need to be tagged.', - metadata['filename']) + logging.warning('acoustid could not recognize %s. Will need to be tagged.', + metadata['filename']) else: logging.warning('could not recognize this track. tag it.') return self.acoustidmd @@ -336,16 +314,14 @@ def recognize(self, metadata=None): #pylint: disable=too-many-statements, too-m self._read_acoustid_tuples(metadata, results) if not self.acoustidmd.get('musicbrainzrecordingid'): - logging.info( - 'acoustidmb: no musicbrainz rid %s. Returning everything else.', - metadata['filename']) + logging.info('acoustidmb: no musicbrainz rid %s. Returning everything else.', + metadata['filename']) return self.acoustidmd if musicbrainzlookup := self.musicbrainz.recordingid( self.acoustidmd['musicbrainzrecordingid']): - if self.acoustidmd.get( - 'musicbrainzartistid') and musicbrainzlookup.get( - 'musicbrainzartistid'): + if self.acoustidmd.get('musicbrainzartistid') and musicbrainzlookup.get( + 'musicbrainzartistid'): del musicbrainzlookup['musicbrainzartistid'] self.acoustidmd.update(musicbrainzlookup) return self.acoustidmd @@ -367,8 +343,8 @@ def on_fpcalcexe_button(self): startdir = os.path.dirname(self.qwidget.fpcalcexe_lineedit.text()) else: startdir = QDir.homePath() - dirname = QFileDialog.getOpenFileName(self.qwidget, 'Select fpcalc', - startdir, 'fpcalc fpcalc.exe') + dirname = QFileDialog.getOpenFileName(self.qwidget, 'Select fpcalc', startdir, + 'fpcalc fpcalc.exe') if dirname and dirname[0]: self.qwidget.fpcalcexe_lineedit.setText(dirname[0]) @@ -386,14 +362,11 @@ def load_settingsui(self, qwidget): qwidget.mb_fallback_checkbox.setChecked( self.config.cparser.value('musicbrainz/fallback', type=bool)) - qwidget.emailaddress_lineedit.setText( - self.config.cparser.value('musicbrainz/emailaddress')) + qwidget.emailaddress_lineedit.setText(self.config.cparser.value('musicbrainz/emailaddress')) - qwidget.apikey_lineedit.setText( - self.config.cparser.value('acoustidmb/acoustidapikey')) + qwidget.apikey_lineedit.setText(self.config.cparser.value('acoustidmb/acoustidapikey')) - qwidget.fpcalcexe_lineedit.setText( - self.config.cparser.value('acoustidmb/fpcalcexe')) + qwidget.fpcalcexe_lineedit.setText(self.config.cparser.value('acoustidmb/fpcalcexe')) qwidget.websites_checkbox.setChecked( self.config.cparser.value('acoustidmb/websites', type=bool)) @@ -406,50 +379,37 @@ def load_settingsui(self, qwidget): 'discogs', ]: guiattr = getattr(qwidget, f'ws_{website}_checkbox') - guiattr.setChecked( - self.config.cparser.value(f'acoustidmb/{website}', type=bool)) + guiattr.setChecked(self.config.cparser.value(f'acoustidmb/{website}', type=bool)) def verify_settingsui(self, qwidget): ''' no verification to do ''' - if qwidget.acoustid_checkbox.isChecked( - ) and not qwidget.apikey_lineedit.text(): - raise PluginVerifyError( - 'Acoustid enabled, but no API Key provided.') - - if qwidget.musicbrainz_checkbox.isChecked( - ) and not qwidget.emailaddress_lineedit.text(): - raise PluginVerifyError( - 'Acoustid enabled, but no email address provided.') - - if qwidget.acoustid_checkbox.isChecked( - ) and not qwidget.fpcalcexe_lineedit.text(): - raise PluginVerifyError( - 'Acoustid enabled, but no fpcalc binary provided.') - - if qwidget.acoustid_checkbox.isChecked( - ) and qwidget.fpcalcexe_lineedit.text(): + if qwidget.acoustid_checkbox.isChecked() and not qwidget.apikey_lineedit.text(): + raise PluginVerifyError('Acoustid enabled, but no API Key provided.') + + if qwidget.musicbrainz_checkbox.isChecked() and not qwidget.emailaddress_lineedit.text(): + raise PluginVerifyError('Acoustid enabled, but no email address provided.') + + if qwidget.acoustid_checkbox.isChecked() and not qwidget.fpcalcexe_lineedit.text(): + raise PluginVerifyError('Acoustid enabled, but no fpcalc binary provided.') + + if qwidget.acoustid_checkbox.isChecked() and qwidget.fpcalcexe_lineedit.text(): fpcalcexe = qwidget.fpcalcexe_lineedit.text() if not self._configure_fpcalc(fpcalcexe=fpcalcexe): - raise PluginVerifyError( - 'Acoustid enabled, but fpcalc is not executable.') + raise PluginVerifyError('Acoustid enabled, but fpcalc is not executable.') def save_settingsui(self, qwidget): ''' take the settings page and save it ''' - self.config.cparser.setValue('acoustidmb/enabled', - qwidget.acoustid_checkbox.isChecked()) + self.config.cparser.setValue('acoustidmb/enabled', qwidget.acoustid_checkbox.isChecked()) self.config.cparser.setValue('musicbrainz/enabled', qwidget.musicbrainz_checkbox.isChecked()) self.config.cparser.setValue('musicbrainz/fallback', qwidget.mb_fallback_checkbox.isChecked()) - self.config.cparser.setValue('acoustidmb/acoustidapikey', - qwidget.apikey_lineedit.text()) + self.config.cparser.setValue('acoustidmb/acoustidapikey', qwidget.apikey_lineedit.text()) self.config.cparser.setValue('musicbrainz/emailaddress', qwidget.emailaddress_lineedit.text()) - self.config.cparser.setValue('acoustidmb/fpcalcexe', - qwidget.fpcalcexe_lineedit.text()) + self.config.cparser.setValue('acoustidmb/fpcalcexe', qwidget.fpcalcexe_lineedit.text()) - self.config.cparser.setValue('acoustidmb/websites', - qwidget.websites_checkbox.isChecked()) + self.config.cparser.setValue('acoustidmb/websites', qwidget.websites_checkbox.isChecked()) for website in [ 'bandcamp', @@ -459,8 +419,7 @@ def save_settingsui(self, qwidget): 'discogs', ]: guiattr = getattr(qwidget, f'ws_{website}_checkbox') - self.config.cparser.setValue(f'acoustidmb/{website}', - guiattr.isChecked()) + self.config.cparser.setValue(f'acoustidmb/{website}', guiattr.isChecked()) def defaults(self, qsettings): qsettings.setValue('acoustidmb/enabled', False) diff --git a/nowplaying/settingsui.py b/nowplaying/settingsui.py index f29b5de8..6d903e7d 100755 --- a/nowplaying/settingsui.py +++ b/nowplaying/settingsui.py @@ -8,8 +8,7 @@ # pylint: disable=no-name-in-module from PySide6.QtCore import Slot, QFile, Qt -from PySide6.QtWidgets import (QErrorMessage, QFileDialog, QWidget, - QListWidgetItem) +from PySide6.QtWidgets import (QErrorMessage, QFileDialog, QWidget, QListWidgetItem) from PySide6.QtGui import QIcon from PySide6.QtUiTools import QUiLoader import PySide6.QtXml # pylint: disable=unused-import, import-error @@ -58,8 +57,7 @@ def post_tray_init(self): # if system hasn't been initialized, then # twitch chat files are irrelevant if self.config.initialized: - self.settingsclasses['twitchchat'].update_twitchbot_commands( - self.config) + self.settingsclasses['twitchchat'].update_twitchbot_commands(self.config) def _setup_widgets(self, uiname, displayname=None): self.widgets[uiname] = load_widget_ui(self.config, f'{uiname}') @@ -91,9 +89,8 @@ def load_qtui(self): # pylint: disable=too-many-branches, too-many-statements else: baseuis = [ - 'general', 'source', 'filter', 'trackskip', 'textoutput', - 'webserver', 'twitch', 'twitchchat', 'requests', - 'artistextras', 'obsws', 'discordbot', 'quirks' + 'general', 'source', 'filter', 'trackskip', 'textoutput', 'webserver', 'twitch', + 'twitchchat', 'requests', 'artistextras', 'obsws', 'discordbot', 'quirks' ] for uiname in baseuis: @@ -110,12 +107,10 @@ def load_qtui(self): # pylint: disable=too-many-branches, too-many-statements if plugintype == "inputs": self.widgets['source'].sourcelist.addItem( self.config.pluginobjs[plugintype][key].displayname) - self.widgets[ - 'source'].sourcelist.currentRowChanged.connect( - self._set_source_description) - self._setup_widgets( - f'{plugintype}_{pkey}', - self.config.pluginobjs[plugintype][key].displayname) + self.widgets['source'].sourcelist.currentRowChanged.connect( + self._set_source_description) + self._setup_widgets(f'{plugintype}_{pkey}', + self.config.pluginobjs[plugintype][key].displayname) self._setup_widgets('about') @@ -126,19 +121,16 @@ def load_qtui(self): # pylint: disable=too-many-branches, too-many-statements 'requests', ]: self.settingsclasses[key].load(self.config, self.widgets[key]) - self.settingsclasses[key].connect(self.uihelp, - self.widgets[key]) + self.settingsclasses[key].connect(self.uihelp, self.widgets[key]) self._connect_plugins() - self.qtui.settings_list.currentRowChanged.connect( - self._set_stacked_display) + self.qtui.settings_list.currentRowChanged.connect(self._set_stacked_display) self.qtui.cancel_button.clicked.connect(self.on_cancel_button) self.qtui.reset_button.clicked.connect(self.on_reset_button) self.qtui.save_button.clicked.connect(self.on_save_button) self.errormessage = QErrorMessage(self.qtui) - if curbutton := self.qtui.settings_list.findItems( - 'general', Qt.MatchContains): + if curbutton := self.qtui.settings_list.findItems('general', Qt.MatchContains): self.qtui.settings_list.setCurrentItem(curbutton[0]) def _load_list_item(self, name, qobject, displayname): @@ -156,8 +148,7 @@ def _set_stacked_display(self, index): def _connect_beamstatus_widget(self, qobject): ''' refresh the status''' - qobject.refresh_button.clicked.connect( - self.on_beamstatus_refresh_button) + qobject.refresh_button.clicked.connect(self.on_beamstatus_refresh_button) def _connect_webserver_widget(self, qobject): ''' file in the hostname/ip and connect the template button''' @@ -173,19 +164,16 @@ def _connect_webserver_widget(self, qobject): def _connect_textoutput_widget(self, qobject): ''' connect the general buttons to non-built-ins ''' - qobject.texttemplate_button.clicked.connect( - self.on_text_template_button) + qobject.texttemplate_button.clicked.connect(self.on_text_template_button) qobject.textoutput_button.clicked.connect(self.on_text_saveas_button) def _connect_discordbot_widget(self, qobject): ''' connect the artistextras buttons to non-built-ins ''' - qobject.template_button.clicked.connect( - self.on_discordbot_template_button) + qobject.template_button.clicked.connect(self.on_discordbot_template_button) def _connect_artistextras_widget(self, qobject): ''' connect the artistextras buttons to non-built-ins ''' - qobject.clearcache_button.clicked.connect( - self.on_artistextras_clearcache_button) + qobject.clearcache_button.clicked.connect(self.on_artistextras_clearcache_button) def _connect_obsws_widget(self, qobject): ''' connect obsws button to template picker''' @@ -193,8 +181,7 @@ def _connect_obsws_widget(self, qobject): def _connect_filter_widget(self, qobject): ''' connect regex filter to template picker''' - qobject.add_recommended_button.clicked.connect( - self.on_filter_add_recommended_button) + qobject.add_recommended_button.clicked.connect(self.on_filter_add_recommended_button) qobject.test_button.clicked.connect(self.on_filter_test_button) qobject.add_button.clicked.connect(self.on_filter_regex_add_button) qobject.del_button.clicked.connect(self.on_filter_regex_del_button) @@ -206,8 +193,7 @@ def _connect_plugins(self): def _set_source_description(self, index): item = self.widgets['source'].sourcelist.item(index) plugin = item.text().lower() - self.config.plugins_description('inputs', plugin, - self.widgets['source'].description) + self.config.plugins_description('inputs', plugin, self.widgets['source'].description) def upd_win(self): ''' update the settings window ''' @@ -243,8 +229,7 @@ def _upd_win_textoutput(self): ''' textoutput settings ''' self.widgets['textoutput'].textoutput_lineedit.setText( self.config.cparser.value('textoutput/file')) - self.widgets['textoutput'].texttemplate_lineedit.setText( - self.config.txttemplate) + self.widgets['textoutput'].texttemplate_lineedit.setText(self.config.txttemplate) self.widgets['textoutput'].append_checkbox.setChecked( self.config.cparser.value('textoutput/fileappend', type=bool)) self.widgets['textoutput'].clear_checkbox.setChecked( @@ -256,22 +241,15 @@ def _upd_win_artistextras(self): self.widgets['artistextras'].artistextras_checkbox.setChecked( self.config.cparser.value('artistextras/enabled', type=bool)) self.widgets['artistextras'].missingfanart_checkbox.setChecked( - self.config.cparser.value('artistextras/coverfornofanart', - type=bool)) + self.config.cparser.value('artistextras/coverfornofanart', type=bool)) self.widgets['artistextras'].missinglogos_checkbox.setChecked( - self.config.cparser.value('artistextras/coverfornologos', - type=bool)) + self.config.cparser.value('artistextras/coverfornologos', type=bool)) self.widgets['artistextras'].missingthumbs_checkbox.setChecked( - self.config.cparser.value('artistextras/coverfornothumbs', - type=bool)) + self.config.cparser.value('artistextras/coverfornothumbs', type=bool)) - for art in [ - 'banners', 'processes', 'fanart', 'logos', 'thumbnails', - 'sizelimit' - ]: + for art in ['banners', 'processes', 'fanart', 'logos', 'thumbnails', 'sizelimit']: guiattr = getattr(self.widgets['artistextras'], f'{art}_spin') - guiattr.setValue( - self.config.cparser.value(f'artistextras/{art}', type=int)) + guiattr.setValue(self.config.cparser.value(f'artistextras/{art}', type=int)) def _upd_win_filters(self): ''' update the filter settings ''' @@ -282,8 +260,7 @@ def _upd_win_filters(self): for configitem in self.config.cparser.allKeys(): if 'regex_filter/' in configitem: - self._filter_regex_load( - regex=self.config.cparser.value(configitem)) + self._filter_regex_load(regex=self.config.cparser.value(configitem)) def _upd_win_trackskip(self): ''' update the trackskip settings to match config ''' @@ -298,15 +275,13 @@ def _upd_win_recognition(self): self.widgets['general'].recog_artist_checkbox.setChecked( self.config.cparser.value('recognition/replaceartist', type=bool)) self.widgets['general'].recog_artistwebsites_checkbox.setChecked( - self.config.cparser.value('recognition/replaceartistwebsites', - type=bool)) + self.config.cparser.value('recognition/replaceartistwebsites', type=bool)) def _upd_win_input(self): ''' this is totally wrong and will need to get dealt with as part of ui code redesign ''' currentinput = self.config.cparser.value('settings/input') - if curbutton := self.widgets['source'].sourcelist.findItems( - currentinput, Qt.MatchContains): + if curbutton := self.widgets['source'].sourcelist.findItems(currentinput, Qt.MatchContains): self.widgets['source'].sourcelist.setCurrentItem(curbutton[0]) def _upd_win_webserver(self): @@ -324,16 +299,11 @@ def _upd_win_obsws(self): ''' update the obsws settings to match config ''' self.widgets['obsws'].enable_checkbox.setChecked( self.config.cparser.value('obsws/enabled', type=bool)) - self.widgets['obsws'].source_lineedit.setText( - self.config.cparser.value('obsws/source')) - self.widgets['obsws'].host_lineedit.setText( - self.config.cparser.value('obsws/host')) - self.widgets['obsws'].port_lineedit.setText( - str(self.config.cparser.value('obsws/port'))) - self.widgets['obsws'].secret_lineedit.setText( - self.config.cparser.value('obsws/secret')) - self.widgets['obsws'].template_lineedit.setText( - self.config.cparser.value('obsws/template')) + self.widgets['obsws'].source_lineedit.setText(self.config.cparser.value('obsws/source')) + self.widgets['obsws'].host_lineedit.setText(self.config.cparser.value('obsws/host')) + self.widgets['obsws'].port_lineedit.setText(str(self.config.cparser.value('obsws/port'))) + self.widgets['obsws'].secret_lineedit.setText(self.config.cparser.value('obsws/secret')) + self.widgets['obsws'].template_lineedit.setText(self.config.cparser.value('obsws/template')) def _upd_win_discordbot(self): ''' update the obsws settings to match config ''' @@ -394,8 +364,7 @@ def disable_web(self): self.upd_win() self.widgets['webserver'].enable_checkbox.setChecked(False) self.upd_conf() - self.errormessage.showMessage( - 'HTTP Server settings are invalid. Bad port?') + self.errormessage.showMessage('HTTP Server settings are invalid. Bad port?') def disable_obsws(self): ''' if the OBS WebSocket gets in trouble, this gets called ''' @@ -409,16 +378,15 @@ def disable_obsws(self): def upd_conf(self): ''' update the configuration ''' - self.config.cparser.setValue( - 'settings/delay', self.widgets['general'].delay_lineedit.text()) + self.config.cparser.setValue('settings/delay', + self.widgets['general'].delay_lineedit.text()) loglevel = self.widgets['general'].logging_combobox.currentText() self._upd_conf_input() - self.config.put( - initialized=True, - notif=self.widgets['general'].notify_checkbox.isChecked(), - loglevel=loglevel) + self.config.put(initialized=True, + notif=self.widgets['general'].notify_checkbox.isChecked(), + loglevel=loglevel) logging.getLogger().setLevel(loglevel) @@ -446,59 +414,44 @@ def upd_conf(self): self.config.cparser.sync() def _upd_conf_textoutput(self): - self.config.cparser.setValue( - 'setlist/enabled', - self.widgets['textoutput'].setlist_checkbox.isChecked()) - self.config.txttemplate = self.widgets[ - 'textoutput'].texttemplate_lineedit.text() - self.config.cparser.setValue( - 'textoutput/file', - self.widgets['textoutput'].textoutput_lineedit.text()) - self.config.cparser.setValue('textoutput/txttemplate', - self.config.txttemplate) - self.config.cparser.setValue( - 'textoutput/fileappend', - self.widgets['textoutput'].append_checkbox.isChecked()) - self.config.cparser.setValue( - 'textoutput/clearonstartup', - self.widgets['textoutput'].clear_checkbox.isChecked()) + self.config.cparser.setValue('setlist/enabled', + self.widgets['textoutput'].setlist_checkbox.isChecked()) + self.config.txttemplate = self.widgets['textoutput'].texttemplate_lineedit.text() + self.config.cparser.setValue('textoutput/file', + self.widgets['textoutput'].textoutput_lineedit.text()) + self.config.cparser.setValue('textoutput/txttemplate', self.config.txttemplate) + self.config.cparser.setValue('textoutput/fileappend', + self.widgets['textoutput'].append_checkbox.isChecked()) + self.config.cparser.setValue('textoutput/clearonstartup', + self.widgets['textoutput'].clear_checkbox.isChecked()) def _upd_conf_trackskip(self): - self.config.cparser.setValue( - 'trackskip/genre', self.widgets['trackskip'].genre_lineedit.text()) - self.config.cparser.setValue( - 'trackskip/comment', - self.widgets['trackskip'].comment_lineedit.text()) + self.config.cparser.setValue('trackskip/genre', + self.widgets['trackskip'].genre_lineedit.text()) + self.config.cparser.setValue('trackskip/comment', + self.widgets['trackskip'].comment_lineedit.text()) def _upd_conf_artistextras(self): - self.config.cparser.setValue( - 'artistextras/enabled', - self.widgets['artistextras'].artistextras_checkbox.isChecked()) + self.config.cparser.setValue('artistextras/enabled', + self.widgets['artistextras'].artistextras_checkbox.isChecked()) self.config.cparser.setValue( 'artistextras/coverfornofanart', self.widgets['artistextras'].missingfanart_checkbox.isChecked()) - self.config.cparser.setValue( - 'artistextras/coverfornologos', - self.widgets['artistextras'].missinglogos_checkbox.isChecked()) + self.config.cparser.setValue('artistextras/coverfornologos', + self.widgets['artistextras'].missinglogos_checkbox.isChecked()) self.config.cparser.setValue( 'artistextras/coverfornothumbs', self.widgets['artistextras'].missingthumbs_checkbox.isChecked()) - for art in [ - 'banners', 'processes', 'fanart', 'logos', 'thumbnails', - 'fanartdelay' - ]: + for art in ['banners', 'processes', 'fanart', 'logos', 'thumbnails', 'fanartdelay']: guiattr = getattr(self.widgets['artistextras'], f'{art}_spin') - self.config.cparser.setValue(f'artistextras/{art}', - guiattr.value()) + self.config.cparser.setValue(f'artistextras/{art}', guiattr.value()) def _upd_conf_recognition(self): - self.config.cparser.setValue( - 'recognition/replacetitle', - self.widgets['general'].recog_title_checkbox.isChecked()) - self.config.cparser.setValue( - 'recognition/replaceartist', - self.widgets['general'].recog_artist_checkbox.isChecked()) + self.config.cparser.setValue('recognition/replacetitle', + self.widgets['general'].recog_title_checkbox.isChecked()) + self.config.cparser.setValue('recognition/replaceartist', + self.widgets['general'].recog_artist_checkbox.isChecked()) self.config.cparser.setValue( 'recognition/replaceartistwebsites', self.widgets['general'].recog_artistwebsites_checkbox.isChecked()) @@ -521,8 +474,7 @@ def _upd_conf_webserver(self): # itself. Hitting stop makes it go through # the loop again - oldenabled = self.config.cparser.value('weboutput/httpenabled', - type=bool) + oldenabled = self.config.cparser.value('weboutput/httpenabled', type=bool) oldport = self.config.cparser.value('weboutput/httpport', type=int) httpenabled = self.widgets['webserver'].enable_checkbox.isChecked() @@ -533,12 +485,10 @@ def _upd_conf_webserver(self): self.config.cparser.setValue('weboutput/httpenabled', httpenabled) self.config.cparser.setValue('weboutput/httpport', httpport) - self.config.cparser.setValue( - 'weboutput/htmltemplate', - self.widgets['webserver'].template_lineedit.text()) - self.config.cparser.setValue( - 'weboutput/once', - self.widgets['webserver'].once_checkbox.isChecked()) + self.config.cparser.setValue('weboutput/htmltemplate', + self.widgets['webserver'].template_lineedit.text()) + self.config.cparser.setValue('weboutput/once', + self.widgets['webserver'].once_checkbox.isChecked()) if oldenabled != httpenabled or oldport != httpport: self.tray.subprocesses.restart_webserver() @@ -549,16 +499,12 @@ def _upd_conf_obsws(self): oldenabled = self.config.cparser.value('obsws/enabled', type=bool) newenabled = self.widgets['obsws'].enable_checkbox.isChecked() - self.config.cparser.setValue( - 'obsws/source', self.widgets['obsws'].source_lineedit.text()) - self.config.cparser.setValue( - 'obsws/host', self.widgets['obsws'].host_lineedit.text()) - self.config.cparser.setValue( - 'obsws/port', self.widgets['obsws'].port_lineedit.text()) - self.config.cparser.setValue( - 'obsws/secret', self.widgets['obsws'].secret_lineedit.text()) - self.config.cparser.setValue( - 'obsws/template', self.widgets['obsws'].template_lineedit.text()) + self.config.cparser.setValue('obsws/source', self.widgets['obsws'].source_lineedit.text()) + self.config.cparser.setValue('obsws/host', self.widgets['obsws'].host_lineedit.text()) + self.config.cparser.setValue('obsws/port', self.widgets['obsws'].port_lineedit.text()) + self.config.cparser.setValue('obsws/secret', self.widgets['obsws'].secret_lineedit.text()) + self.config.cparser.setValue('obsws/template', + self.widgets['obsws'].template_lineedit.text()) self.config.cparser.setValue('obsws/enabled', newenabled) if oldenabled != newenabled: @@ -569,14 +515,12 @@ def _upd_conf_discordbot(self): enabled = self.widgets['discordbot'].enable_checkbox.isChecked() - self.config.cparser.setValue( - 'discord/clientid', - self.widgets['discordbot'].clientid_lineedit.text()) - self.config.cparser.setValue( - 'discord/token', self.widgets['discordbot'].token_lineedit.text()) - self.config.cparser.setValue( - 'discord/template', - self.widgets['discordbot'].template_lineedit.text()) + self.config.cparser.setValue('discord/clientid', + self.widgets['discordbot'].clientid_lineedit.text()) + self.config.cparser.setValue('discord/token', + self.widgets['discordbot'].token_lineedit.text()) + self.config.cparser.setValue('discord/template', + self.widgets['discordbot'].template_lineedit.text()) self.config.cparser.setValue('discord/enabled', enabled) def verify_regex_filters(self): @@ -589,8 +533,7 @@ def verify_regex_filters(self): try: re.compile(item) except re.error as error: - self.errormessage.showMessage( - f'Filter error with \'{item}\': {error.msg}') + self.errormessage.showMessage(f'Filter error with \'{item}\': {error.msg}') return False return True @@ -611,23 +554,20 @@ def reset_filters(widget, config): if not self.verify_regex_filters(): return - self.config.cparser.setValue( - 'settings/stripextras', - self.widgets['filter'].stripextras_checkbox.isChecked()) + self.config.cparser.setValue('settings/stripextras', + self.widgets['filter'].stripextras_checkbox.isChecked()) reset_filters(self.widgets['filter'].regex_list, self.config.cparser) def _upd_conf_quirks(self): ''' update the quirks settings to match config ''' # file system notification method - self.config.cparser.value( - 'quirks/pollingobserver', - self.widgets['quirks'].fs_poll_button.isChecked()) + self.config.cparser.value('quirks/pollingobserver', + self.widgets['quirks'].fs_poll_button.isChecked()) # s,in,out,g - self.config.cparser.setValue( - 'quirks/filesubst', - self.widgets['quirks'].song_subst_checkbox.isChecked()) + self.config.cparser.setValue('quirks/filesubst', + self.widgets['quirks'].song_subst_checkbox.isChecked()) if self.widgets['quirks'].slash_toback.isChecked(): self.config.cparser.setValue('quirks/slashmode', 'toback') @@ -636,12 +576,10 @@ def _upd_conf_quirks(self): if self.widgets['quirks'].slash_nochange.isChecked(): self.config.cparser.setValue('quirks/slashmode', 'nochange') - self.config.cparser.setValue( - 'quirks/filesubstin', - self.widgets['quirks'].song_in_path_lineedit.text()) - self.config.cparser.setValue( - 'quirks/filesubstout', - self.widgets['quirks'].song_out_path_lineedit.text()) + self.config.cparser.setValue('quirks/filesubstin', + self.widgets['quirks'].song_in_path_lineedit.text()) + self.config.cparser.setValue('quirks/filesubstout', + self.widgets['quirks'].song_out_path_lineedit.text()) @Slot() def on_text_saveas_button(self): @@ -650,8 +588,7 @@ def on_text_saveas_button(self): startdir = os.path.dirname(startfile) else: startdir = '.' - if filename := QFileDialog.getSaveFileName(self, 'Open file', startdir, - '*.txt'): + if filename := QFileDialog.getSaveFileName(self, 'Open file', startdir, '*.txt'): self.widgets['textoutput'].textoutput_lineedit.setText(filename[0]) @Slot() @@ -672,34 +609,30 @@ def on_beamstatus_refresh_button(self): ipaddr = self.config.cparser.value('control/beamserverip') idname = self.config.cparser.value('control/beamservername') if port := self.config.cparser.value('control/beamserverport'): - self.widgets['beamstatus'].server_label.setText( - f'{idname}({ipaddr}):{port}') + self.widgets['beamstatus'].server_label.setText(f'{idname}({ipaddr}):{port}') else: self.widgets['beamstatus'].server_label.setText('Not connected') @Slot() def on_text_template_button(self): ''' file template button clicked action ''' - self.uihelp.template_picker_lineedit( - self.widgets['textoutput'].texttemplate_lineedit) + self.uihelp.template_picker_lineedit(self.widgets['textoutput'].texttemplate_lineedit) @Slot() def on_discordbot_template_button(self): ''' discordbot template button clicked action ''' - self.uihelp.template_picker_lineedit( - self.widgets['discordbot'].template_lineedit) + self.uihelp.template_picker_lineedit(self.widgets['discordbot'].template_lineedit) @Slot() def on_obsws_template_button(self): ''' obsws template button clicked action ''' - self.uihelp.template_picker_lineedit( - self.widgets['obsws'].template_lineedit) + self.uihelp.template_picker_lineedit(self.widgets['obsws'].template_lineedit) @Slot() def on_html_template_button(self): ''' html template button clicked action ''' - self.uihelp.template_picker_lineedit( - self.widgets['webserver'].template_lineedit, limit='*.htm *.html') + self.uihelp.template_picker_lineedit(self.widgets['webserver'].template_lineedit, + limit='*.htm *.html') def _filter_regex_load(self, regex=None): ''' setup the filter table ''' @@ -737,8 +670,7 @@ def on_filter_test_button(self): for row in range(rowcount): item = self.widgets['filter'].regex_list.item(row).text() striprelist.append(re.compile(item)) - result = nowplaying.utils.titlestripper_advanced( - title=title, title_regex_list=striprelist) + result = nowplaying.utils.titlestripper_advanced(title=title, title_regex_list=striprelist) self.widgets['filter'].result_label.setText(result) result = nowplaying.utils.titlestripper_advanced( title=title, title_regex_list=self.config.getregexlist()) @@ -763,19 +695,16 @@ def on_cancel_button(self): self.upd_win() self.qtui.close() - if not self.config.cparser.value( - 'settings/input', - defaultValue=None) or not self.config.initialized: + if not self.config.cparser.value('settings/input', + defaultValue=None) or not self.config.initialized: self.tray.cleanquit() @Slot() def on_reset_button(self): ''' cancel button clicked action ''' self.config.reset() - SettingsUI.httpenabled = self.config.cparser.value( - 'weboutput/httpenabled', type=bool) - SettingsUI.httpport = self.config.cparser.value('weboutput/httpport', - type=int) + SettingsUI.httpenabled = self.config.cparser.value('weboutput/httpenabled', type=bool) + SettingsUI.httpport = self.config.cparser.value('weboutput/httpport', type=int) self.upd_win() @Slot() diff --git a/nowplaying/subprocesses.py b/nowplaying/subprocesses.py index d4d8dfd1..36390192 100644 --- a/nowplaying/subprocesses.py +++ b/nowplaying/subprocesses.py @@ -18,14 +18,11 @@ def __init__(self, config=None, testmode=False): if self.config.cparser.value('control/beam', type=bool): processlist = ['trackpoll', 'beamsender'] else: - processlist = [ - 'trackpoll', 'obsws', 'twitchbot', 'discordbot', 'webserver' - ] + processlist = ['trackpoll', 'obsws', 'twitchbot', 'discordbot', 'webserver'] for name in processlist: self.processes[name] = { - 'module': - importlib.import_module(f'nowplaying.processes.{name}'), + 'module': importlib.import_module(f'nowplaying.processes.{name}'), 'process': None, 'stopevent': self.manager.Event(), } diff --git a/nowplaying/systemtray.py b/nowplaying/systemtray.py index 314c04cc..0713fe89 100755 --- a/nowplaying/systemtray.py +++ b/nowplaying/systemtray.py @@ -33,18 +33,15 @@ def __init__(self, beam=False): #pylint: disable=too-many-statements self.menu = QMenu() # create systemtray options and actions - self.aboutwindow = nowplaying.settingsui.load_widget_ui( - self.config, 'about') + self.aboutwindow = nowplaying.settingsui.load_widget_ui(self.config, 'about') nowplaying.settingsui.about_version_text(self.config, self.aboutwindow) self.about_action = QAction('About What\'s Now Playing') self.menu.addAction(self.about_action) self.about_action.setEnabled(True) self.about_action.triggered.connect(self.aboutwindow.show) - self.subprocesses = nowplaying.subprocesses.SubprocessManager( - self.config) - self.settingswindow = nowplaying.settingsui.SettingsUI(tray=self, - beam=beam) + self.subprocesses = nowplaying.subprocesses.SubprocessManager(self.config) + self.settingswindow = nowplaying.settingsui.SettingsUI(tray=self, beam=beam) self.settings_action = QAction("Settings") self.settings_action.triggered.connect(self.settingswindow.show) @@ -100,8 +97,7 @@ def _configure_beamstatus(self, beam): self.config.cparser.remove('control/beamserverip') def _configure_twitchrequests(self): - self.requestswindow = nowplaying.trackrequests.Requests( - config=self.config) + self.requestswindow = nowplaying.trackrequests.Requests(config=self.config) self.requestswindow.initial_ui() def _requestswindow(self): @@ -153,8 +149,7 @@ def pause(self): def fix_mixmode_menu(self): ''' update the mixmode based upon current rules ''' - plugins = self.config.cparser.value('settings/input', - defaultValue=None) + plugins = self.config.cparser.value('settings/input', defaultValue=None) if not plugins: return @@ -200,8 +195,7 @@ def tracknotify(self): # pylint: disable=unused-argument # don't announce empty content if not metadata['artist'] and not metadata['title']: - logging.warning( - 'Both artist and title are empty; skipping notify') + logging.warning('Both artist and title are empty; skipping notify') return if 'artist' in metadata: @@ -223,9 +217,7 @@ def tracknotify(self): # pylint: disable=unused-argument tip = f'{artist} - {title}' self.tray.setIcon(self.icon) - self.tray.showMessage('Now Playing ▶ ', - tip, - icon=QSystemTrayIcon.NoIcon) + self.tray.showMessage('Now Playing ▶ ', tip, icon=QSystemTrayIcon.NoIcon) self.tray.show() def cleanquit(self): @@ -257,8 +249,7 @@ def installer(self): if plugin and not self.config.validate_source(plugin): self.config.cparser.remove('settings/input') msgbox = QErrorMessage() - msgbox.showMessage( - f'Configured source {plugin} is not supported. Reconfiguring.') + msgbox.showMessage(f'Configured source {plugin} is not supported. Reconfiguring.') msgbox.show() msgbox.exec() elif not plugin: @@ -274,8 +265,7 @@ def installer(self): for plugin in plugins: if plugins[plugin].install(): - self.config.cparser.setValue('settings/input', - plugin.split('.')[-1]) + self.config.cparser.setValue('settings/input', plugin.split('.')[-1]) break twitchchatsettings = nowplaying.twitch.chat.TwitchChatSettings() diff --git a/nowplaying/textoutput.py b/nowplaying/textoutput.py index 16f1f7a7..1f9344f4 100644 --- a/nowplaying/textoutput.py +++ b/nowplaying/textoutput.py @@ -18,11 +18,7 @@ def deltxttrack(config=None): writetxttrack(config, clear=True) -def writetxttrack(config=None, - filename=None, - templatehandler=None, - metadata=None, - clear=False): +def writetxttrack(config=None, filename=None, templatehandler=None, metadata=None, clear=False): ''' write new track info ''' if not filename and not config: diff --git a/nowplaying/trackrequests.py b/nowplaying/trackrequests.py index 08b41075..93bda86b 100644 --- a/nowplaying/trackrequests.py +++ b/nowplaying/trackrequests.py @@ -23,15 +23,14 @@ from nowplaying.utils import TRANSPARENT_PNG_BIN USERREQUEST_TEXT = [ - 'artist', 'title', 'displayname', 'type', 'playlist', 'username', - 'filename', 'user_input', 'normalizedartist', 'normalizedtitle' + 'artist', 'title', 'displayname', 'type', 'playlist', 'username', 'filename', 'user_input', + 'normalizedartist', 'normalizedtitle' ] USERREQUEST_BLOB = ['userimage'] REQUEST_WINDOW_FIELDS = [ - 'artist', 'title', 'type', 'playlist', 'username', 'filename', 'timestamp', - 'reqid' + 'artist', 'title', 'type', 'playlist', 'username', 'filename', 'timestamp', 'reqid' ] REQUEST_SETTING_MAPPING = { @@ -83,19 +82,14 @@ class Requests: #pylint: disable=too-many-instance-attributes, too-many-public- ''' - def __init__(self, - config=None, - stopevent=None, - testmode=False, - upgrade=False): + def __init__(self, config=None, stopevent=None, testmode=False, upgrade=False): self.config = config self.stopevent = stopevent self.testmode = testmode self.filelists = None self.databasefile = pathlib.Path( - QStandardPaths.standardLocations( - QStandardPaths.CacheLocation)[0]).joinpath( - 'requests', 'request.db') + QStandardPaths.standardLocations(QStandardPaths.CacheLocation)[0]).joinpath( + 'requests', 'request.db') self.widgets = None self.watcher = None if not self.databasefile.exists() or upgrade: @@ -112,8 +106,7 @@ def setupdb(self): cursor = connection.cursor() try: sql = ('CREATE TABLE IF NOT EXISTS userrequest (' + - ' TEXT COLLATE NOCASE, '.join(USERREQUEST_TEXT) + - ' TEXT COLLATE NOCASE, ' + + ' TEXT COLLATE NOCASE, '.join(USERREQUEST_TEXT) + ' TEXT COLLATE NOCASE, ' + ' BLOB, '.join(USERREQUEST_BLOB) + ' BLOB, ' ' reqid INTEGER PRIMARY KEY AUTOINCREMENT,' ' timestamp DATETIME DEFAULT CURRENT_TIMESTAMP)') @@ -121,8 +114,7 @@ def setupdb(self): connection.commit() sql = ('CREATE TABLE IF NOT EXISTS gifwords (' + - ' TEXT COLLATE NOCASE, '.join(GIFWORDS_TEXT) + - ' TEXT COLLATE NOCASE, ' + + ' TEXT COLLATE NOCASE, '.join(GIFWORDS_TEXT) + ' TEXT COLLATE NOCASE, ' + ' BLOB, '.join(GIFWORDS_BLOB) + ' BLOB, ' ' reqid INTEGER PRIMARY KEY AUTOINCREMENT,' ' timestamp DATETIME DEFAULT CURRENT_TIMESTAMP)') @@ -154,15 +146,13 @@ def clear_roulette_artist_dupes(self): async def add_roulette_dupelist(self, artist, playlist): ''' add a record to the dupe list ''' if not self.databasefile.exists(): - logging.error('%s does not exist, refusing to add.', - self.databasefile) + logging.error('%s does not exist, refusing to add.', self.databasefile) return logging.debug('marking %s as played against %s', artist, playlist) sql = 'INSERT INTO rouletteartist (artist,playlist) VALUES (?,?)' datatuple = (artist, playlist) - async with aiosqlite.connect(self.databasefile, - timeout=30) as connection: + async with aiosqlite.connect(self.databasefile, timeout=30) as connection: connection.row_factory = sqlite3.Row cursor = await connection.cursor() await cursor.execute(sql, datatuple) @@ -171,13 +161,11 @@ async def add_roulette_dupelist(self, artist, playlist): async def get_roulette_dupe_list(self, playlist=None): ''' get the artist dupelist ''' if not self.databasefile.exists(): - logging.error('%s does not exist, refusing to add.', - self.databasefile) + logging.error('%s does not exist, refusing to add.', self.databasefile) return sql = 'SELECT artist FROM rouletteartist' - async with aiosqlite.connect(self.databasefile, - timeout=30) as connection: + async with aiosqlite.connect(self.databasefile, timeout=30) as connection: connection.row_factory = lambda cursor, row: row[0] cursor = await connection.cursor() try: @@ -207,8 +195,7 @@ def normalize(crazystring): async def add_to_db(self, data): ''' add an entry to the db ''' if not self.databasefile.exists(): - logging.error('%s does not exist, refusing to add.', - self.databasefile) + logging.error('%s does not exist, refusing to add.', self.databasefile) return data['normalizedartist'] = self.normalize(data.get('artist')) @@ -231,11 +218,9 @@ async def add_to_db(self, data): datatuple = tuple(list(data.values())) try: - logging.debug( - 'Request artist: >%s< / title: >%s< has made it to the requestdb', - data.get('artist'), data.get('title')) - async with aiosqlite.connect(self.databasefile, - timeout=30) as connection: + logging.debug('Request artist: >%s< / title: >%s< has made it to the requestdb', + data.get('artist'), data.get('title')) + async with aiosqlite.connect(self.databasefile, timeout=30) as connection: connection.row_factory = sqlite3.Row cursor = await connection.cursor() await cursor.execute(sql, datatuple) @@ -247,8 +232,7 @@ async def add_to_db(self, data): async def add_to_gifwordsdb(self, data): ''' add an entry to the db ''' if not self.databasefile.exists(): - logging.error('%s does not exist, refusing to add.', - self.databasefile) + logging.error('%s does not exist, refusing to add.', self.databasefile) return sql = 'INSERT OR REPLACE INTO gifwords (' @@ -257,11 +241,9 @@ async def add_to_gifwordsdb(self, data): datatuple = tuple(list(data.values())) try: - logging.debug( - 'Request gifwords: >%s< / url: >%s< has made it to the requestdb', - data.get('keywords'), data.get('imageurl')) - async with aiosqlite.connect(self.databasefile, - timeout=30) as connection: + logging.debug('Request gifwords: >%s< / url: >%s< has made it to the requestdb', + data.get('keywords'), data.get('imageurl')) + async with aiosqlite.connect(self.databasefile, timeout=30) as connection: connection.row_factory = sqlite3.Row cursor = await connection.cursor() await cursor.execute(sql, datatuple) @@ -273,8 +255,7 @@ async def add_to_gifwordsdb(self, data): def respin_a_reqid(self, reqid): ''' given a reqid, set to respin ''' if not self.databasefile.exists(): - logging.error('%s does not exist, refusing to respin.', - self.databasefile) + logging.error('%s does not exist, refusing to respin.', self.databasefile) return sql = 'UPDATE userrequest SET filename=? WHERE reqid=?' @@ -291,16 +272,14 @@ def respin_a_reqid(self, reqid): def erase_id(self, reqid): ''' remove entry from requests ''' if not self.databasefile.exists(): - logging.error('%s does not exist, refusing to erase.', - self.databasefile) + logging.error('%s does not exist, refusing to erase.', self.databasefile) return with sqlite3.connect(self.databasefile, timeout=30) as connection: connection.row_factory = sqlite3.Row cursor = connection.cursor() try: - cursor.execute('DELETE FROM userrequest WHERE reqid=?;', - (reqid, )) + cursor.execute('DELETE FROM userrequest WHERE reqid=?;', (reqid, )) connection.commit() except sqlite3.OperationalError as error: logging.error(error) @@ -309,37 +288,31 @@ def erase_id(self, reqid): async def erase_gifwords_id(self, reqid): ''' remove entry from gifwords ''' if not self.databasefile.exists(): - logging.error('%s does not exist, refusing to erase.', - self.databasefile) + logging.error('%s does not exist, refusing to erase.', self.databasefile) return - async with aiosqlite.connect(self.databasefile, - timeout=30) as connection: + async with aiosqlite.connect(self.databasefile, timeout=30) as connection: connection.row_factory = sqlite3.Row cursor = await connection.cursor() try: - await cursor.execute('DELETE FROM gifwords WHERE reqid=?;', - (reqid, )) + await cursor.execute('DELETE FROM gifwords WHERE reqid=?;', (reqid, )) await connection.commit() except sqlite3.OperationalError as error: logging.error(error) return async def _find_good_request(self, setting): - artistdupes = await self.get_roulette_dupe_list( - playlist=setting['playlist']) + artistdupes = await self.get_roulette_dupe_list(playlist=setting['playlist']) plugin = self.config.cparser.value('settings/input') tryagain = True counter = 10 while tryagain and counter > 0: counter -= 1 - roulette = await self.config.pluginobjs['inputs'][ - f'nowplaying.inputs.{plugin}'].getrandomtrack( - setting['playlist']) + roulette = await self.config.pluginobjs['inputs'][f'nowplaying.inputs.{plugin}' + ].getrandomtrack(setting['playlist']) metadata = await nowplaying.metadata.MetadataProcessors( - config=self.config - ).getmoremetadata(metadata={'filename': roulette}, - skipplugins=True) + config=self.config).getmoremetadata(metadata={'filename': roulette}, + skipplugins=True) if not artistdupes or metadata.get('artist') not in artistdupes: tryagain = False @@ -348,19 +321,13 @@ async def _find_good_request(self, setting): logging.debug('Duped on %s. Retrying.', metadata['artist']) return metadata - async def user_roulette_request(self, - setting, - user, - user_input, - reqid=None): + async def user_roulette_request(self, setting, user, user_input, reqid=None): ''' roulette request ''' if not setting.get('playlist'): - logging.error('%s does not have a playlist defined', - setting.get('displayname')) + logging.error('%s does not have a playlist defined', setting.get('displayname')) return - logging.debug('%s requested roulette %s | %s', user, - setting['playlist'], user_input) + logging.debug('%s requested roulette %s | %s', user, setting['playlist'], user_input) plugin = self.config.cparser.value('settings/input') if plugin not in ['beam']: @@ -382,29 +349,23 @@ async def user_roulette_request(self, if reqid: data['reqid'] = reqid await self.add_to_db(data) - return { - 'requester': user, - 'requestdisplayname': setting.get('displayname') - } + return {'requester': user, 'requestdisplayname': setting.get('displayname')} async def _get_and_del_request_lookup(self, sql, datatuple): ''' run sql for request ''' if not self.databasefile.exists(): - logging.error('%s does not exist, refusing to lookup.', - self.databasefile) + logging.error('%s does not exist, refusing to lookup.', self.databasefile) return None try: - async with aiosqlite.connect(self.databasefile, - timeout=30) as connection: + async with aiosqlite.connect(self.databasefile, timeout=30) as connection: connection.row_factory = sqlite3.Row cursor = await connection.cursor() await cursor.execute(sql, datatuple) row = await cursor.fetchone() if row: if row['type'] == 'Roulette': - await self.add_roulette_dupelist( - row['artist'], row['playlist']) + await self.add_roulette_dupelist(row['artist'], row['playlist']) self.erase_id(row['reqid']) return { 'requester': row['username'], @@ -426,8 +387,7 @@ async def _request_lookup_by_artist_title(self, artist='', title=''): if not newdata: artist = self.normalize(artist) title = self.normalize(title) - logging.debug('trying normalized artist >%s< / title >%s<', artist, - title) + logging.debug('trying normalized artist >%s< / title >%s<', artist, title) sql = 'SELECT * FROM userrequest WHERE normalizedartist=? AND normalizedtitle=?' datatuple = artist, title logging.debug('request db lookup: %s', datatuple) @@ -447,16 +407,14 @@ async def get_request(self, metadata): newdata = await self._get_and_del_request_lookup(sql, datatuple) if not newdata and metadata.get('artist') and metadata.get('title'): - newdata = await self._request_lookup_by_artist_title( - artist=metadata.get('artist'), title=metadata.get('title')) + newdata = await self._request_lookup_by_artist_title(artist=metadata.get('artist'), + title=metadata.get('title')) if not newdata and metadata.get('artist'): - newdata = await self._request_lookup_by_artist_title( - artist=metadata.get('artist')) + newdata = await self._request_lookup_by_artist_title(artist=metadata.get('artist')) if not newdata and metadata.get('title'): - newdata = await self._request_lookup_by_artist_title( - title=metadata.get('title')) + newdata = await self._request_lookup_by_artist_title(title=metadata.get('title')) if not newdata: logging.debug('not a request') @@ -476,20 +434,17 @@ async def watch_for_respin(self, stopevent): continue try: - async with aiosqlite.connect(self.databasefile, - timeout=30) as connection: + async with aiosqlite.connect(self.databasefile, timeout=30) as connection: connection.row_factory = sqlite3.Row cursor = await connection.cursor() await cursor.execute( 'SELECT * from userrequest WHERE filename=? ORDER BY timestamp DESC', datatuple) while row := await cursor.fetchone(): - logging.debug( - 'calling user_roulette_request: %s %s %s', - row['username'], row['playlist'], row['reqid']) - await self.user_roulette_request( - {'playlist': row['playlist']}, row['username'], '', - row['reqid']) + logging.debug('calling user_roulette_request: %s %s %s', row['username'], + row['playlist'], row['reqid']) + await self.user_roulette_request({'playlist': row['playlist']}, + row['username'], '', row['reqid']) except Exception as error: #pylint: disable=broad-except logging.error(error) @@ -497,12 +452,10 @@ async def check_for_gifwords(self): ''' check if a gifword has been requested ''' content = {'reqeuster': None, 'image': None, 'keywords': None} try: - async with aiosqlite.connect(self.databasefile, - timeout=30) as connection: + async with aiosqlite.connect(self.databasefile, timeout=30) as connection: connection.row_factory = sqlite3.Row cursor = await connection.cursor() - await cursor.execute( - 'SELECT * from gifwords ORDER BY timestamp DESC') + await cursor.execute('SELECT * from gifwords ORDER BY timestamp DESC') if row := await cursor.fetchone(): content = { 'requester': row['requester'], @@ -527,8 +480,7 @@ async def find_command(self, command): tvtext = self.config.cparser.value(f'{configitem}/command') if tvtext == command: for key in nowplaying.trackrequests.REQUEST_SETTING_MAPPING: - setting[key] = self.config.cparser.value( - f'{configitem}/{key}') + setting[key] = self.config.cparser.value(f'{configitem}/{key}') break return setting @@ -543,8 +495,7 @@ async def find_twitchtext(self, twitchtext): tvtext = self.config.cparser.value(f'{configitem}/twitchtext') if tvtext == twitchtext: for key in nowplaying.trackrequests.REQUEST_SETTING_MAPPING: - setting[key] = self.config.cparser.value( - f'{configitem}/{key}') + setting[key] = self.config.cparser.value(f'{configitem}/{key}') break return setting @@ -559,8 +510,7 @@ async def user_track_request(self, setting, user, user_input): user_input = user_input.replace('-', ' - ') if user_input := WEIRDAL_RE.sub('Weird Al', user_input): weirdal = True - if user_input[0] != '"' and (atmatch := - ARTIST_TITLE_RE.search(user_input)): + if user_input[0] != '"' and (atmatch := ARTIST_TITLE_RE.search(user_input)): artist = atmatch.group(1) title = atmatch.group(2) elif tmatch := TITLE_ARTIST_RE.search(user_input): @@ -622,18 +572,15 @@ async def _tenor_request(self, search_terms): } async with aiohttp.ClientSession() as session: - async with session.get(BASE_URL, params=params, - timeout=10) as response: + async with session.get(BASE_URL, params=params, timeout=10) as response: if response.status == 200: # load the GIFs using the urls for the smaller GIF sizes result = await response.json() if result: - content['imageurl'] = result['results'][0]['media_formats']['gif'][ - 'url'] + content['imageurl'] = result['results'][0]['media_formats']['gif']['url'] async with aiohttp.ClientSession() as session: - async with session.get(content['imageurl'], - timeout=10) as response: + async with session.get(content['imageurl'], timeout=10) as response: if response.status == 200: # load the GIFs using the urls for the smaller GIF sizes content['image'] = await response.read() @@ -714,8 +661,7 @@ def on_respin_button(self): if items := self.widgets.request_table.selectedItems(): for item in items: row = item.row() - reqidlist.append( - self.widgets.request_table.item(row, 7).text()) + reqidlist.append(self.widgets.request_table.item(row, 7).text()) for reqid in reqidlist: try: @@ -729,8 +675,7 @@ def on_del_button(self): if items := self.widgets.request_table.selectedItems(): for item in items: row = item.row() - reqidlist.append( - self.widgets.request_table.item(row, 7).text()) + reqidlist.append(self.widgets.request_table.item(row, 7).text()) for reqid in reqidlist: try: @@ -745,8 +690,7 @@ def dict_factory(cursor, row): fields = [column[0] for column in cursor.description] return dict(zip(fields, row)) - async with aiosqlite.connect(self.databasefile, - timeout=30) as connection: + async with aiosqlite.connect(self.databasefile, timeout=30) as connection: connection.row_factory = dict_factory cursor = await connection.cursor() try: @@ -760,8 +704,7 @@ def dict_factory(cursor, row): def get_dataset(self): ''' get the current request list for display ''' if not self.databasefile.exists(): - logging.error('%s does not exist, refusing to get_dataset.', - self.databasefile) + logging.error('%s does not exist, refusing to get_dataset.', self.databasefile) return None with sqlite3.connect(self.databasefile, timeout=30) as connection: @@ -786,11 +729,10 @@ def _request_window_load(self, **kwargs): if cbtype == 'displayname': continue if kwargs.get(cbtype): - self.widgets.request_table.setItem( - row, column, QTableWidgetItem(str(kwargs[cbtype]))) - else: self.widgets.request_table.setItem(row, column, - QTableWidgetItem('')) + QTableWidgetItem(str(kwargs[cbtype]))) + else: + self.widgets.request_table.setItem(row, column, QTableWidgetItem('')) def update_window(self): ''' redraw the request window ''' @@ -811,8 +753,7 @@ def clear_table(widget): for configitem in dataset: self._request_window_load(**configitem) - self.widgets.request_table.horizontalHeader().ResizeMode( - QHeaderView.Stretch) + self.widgets.request_table.horizontalHeader().ResizeMode(QHeaderView.Stretch) self.widgets.request_table.resizeColumnsToContents() self.widgets.request_table.adjustSize() self.widgets.adjustSize() @@ -826,8 +767,7 @@ def initial_ui(self): ui_file.open(QFile.ReadOnly) self.widgets = loader.load(ui_file) self.widgets.setLayout(self.widgets.window_layout) - self.widgets.request_table.horizontalHeader().ResizeMode( - QHeaderView.Stretch) + self.widgets.request_table.horizontalHeader().ResizeMode(QHeaderView.Stretch) ui_file.close() self._connect_request_widgets() self.update_window() @@ -876,14 +816,12 @@ def _typebox(current, enablegifwords=False): row = widget.request_table.rowCount() widget.request_table.insertRow(row) - for column, cbtype in enumerate( - nowplaying.trackrequests.REQUEST_SETTING_MAPPING): + for column, cbtype in enumerate(nowplaying.trackrequests.REQUEST_SETTING_MAPPING): if cbtype == 'type': box = _typebox(kwargs.get('type'), self.enablegifwords) widget.request_table.setCellWidget(row, column, box) elif kwargs.get(cbtype): - widget.request_table.setItem( - row, column, QTableWidgetItem(str(kwargs.get(cbtype)))) + widget.request_table.setItem(row, column, QTableWidgetItem(str(kwargs.get(cbtype)))) else: widget.request_table.setItem(row, column, QTableWidgetItem('')) widget.request_table.resizeColumnsToContents() @@ -914,8 +852,7 @@ def clear_table(widget): config.cparser.value('twitchbot/chatrequests', type=bool)) widget.enable_redemptions_checkbox.setChecked( config.cparser.value('twitchbot/redemptions', type=bool)) - widget.enable_checkbox.setChecked( - config.cparser.value('settings/requests', type=bool)) + widget.enable_checkbox.setChecked(config.cparser.value('settings/requests', type=bool)) @staticmethod def save(config, widget, subprocesses): #pylint: disable=unused-argument @@ -929,8 +866,7 @@ def reset_commands(widget, config): rowcount = widget.rowCount() for row in range(rowcount): - for column, cbtype in enumerate( - nowplaying.trackrequests.REQUEST_SETTING_MAPPING): + for column, cbtype in enumerate(nowplaying.trackrequests.REQUEST_SETTING_MAPPING): if cbtype == 'type': item = widget.cellWidget(row, column) value = item.currentText() @@ -943,10 +879,8 @@ def reset_commands(widget, config): config.cparser.setValue('twitchbot/redemptions', widget.enable_redemptions_checkbox.isChecked()) - config.cparser.setValue('twitchbot/chatrequests', - widget.enable_chat_checkbox.isChecked()) - config.cparser.setValue('settings/requests', - widget.enable_checkbox.isChecked()) + config.cparser.setValue('twitchbot/chatrequests', widget.enable_chat_checkbox.isChecked()) + config.cparser.setValue('settings/requests', widget.enable_checkbox.isChecked()) reset_commands(widget.request_table, config.cparser) @staticmethod @@ -959,14 +893,12 @@ def verify(widget): item1 = widget.request_table.item(row, 1) item2 = widget.request_table.cellWidget(row, 2) if not item0.text() and not item1.text(): - raise PluginVerifyError( - 'Request must have either a command or redemption text.') + raise PluginVerifyError('Request must have either a command or redemption text.') if item2.currentText() in 'Roulette': playlistitem = widget.request_table.item(row, 4) if not playlistitem.text(): - raise PluginVerifyError( - 'Roulette request has an empty playlist') + raise PluginVerifyError('Roulette request has an empty playlist') @Slot() def on_add_button(self): diff --git a/nowplaying/twitch/__init__.py b/nowplaying/twitch/__init__.py index 5cfbfbe5..98f91147 100644 --- a/nowplaying/twitch/__init__.py +++ b/nowplaying/twitch/__init__.py @@ -24,10 +24,7 @@ import nowplaying.twitch.redemptions import nowplaying.twitch.utils -USER_SCOPE = [ - AuthScope.CHANNEL_READ_REDEMPTIONS, AuthScope.CHAT_READ, - AuthScope.CHAT_EDIT -] +USER_SCOPE = [AuthScope.CHANNEL_READ_REDEMPTIONS, AuthScope.CHAT_READ, AuthScope.CHAT_EDIT] class TwitchSupport: # pylint: disable=too-many-instance-attributes @@ -62,8 +59,7 @@ async def bootstrap(self): self.tasks.add(task) task.add_done_callback(self.tasks.discard) await asyncio.sleep(5) - task = self.loop.create_task( - self.redemptions.run_redemptions(self.twitchlogin, self.chat)) + task = self.loop.create_task(self.redemptions.run_redemptions(self.twitchlogin, self.chat)) self.tasks.add(task) task.add_done_callback(self.tasks.discard) @@ -75,8 +71,8 @@ async def _watch_for_exit(self): def start(self): ''' start twitch support ''' try: - self.chat = nowplaying.twitch.chat.TwitchChat( - config=self.config, stopevent=self.stopevent) + self.chat = nowplaying.twitch.chat.TwitchChat(config=self.config, + stopevent=self.stopevent) self.redemptions = nowplaying.twitch.redemptions.TwitchRedemptions( config=self.config, stopevent=self.stopevent) if not self.loop: @@ -123,24 +119,18 @@ def connect(self, uihelp, widget): # pylint: disable=unused-argument ''' connect twitch ''' self.widget = widget widget.chatbot_username_line.setBuddy(widget.token_lineedit) - self.widget.token_lineedit.editingFinished.connect( - self.update_token_name) + self.widget.token_lineedit.editingFinished.connect(self.update_token_name) def load(self, config, widget): ''' load the settings window ''' self.widget = widget - widget.enable_checkbox.setChecked( - config.cparser.value('twitchbot/enabled', type=bool)) - widget.clientid_lineedit.setText( - config.cparser.value('twitchbot/clientid')) - widget.channel_lineedit.setText( - config.cparser.value('twitchbot/channel')) + widget.enable_checkbox.setChecked(config.cparser.value('twitchbot/enabled', type=bool)) + widget.clientid_lineedit.setText(config.cparser.value('twitchbot/clientid')) + widget.channel_lineedit.setText(config.cparser.value('twitchbot/channel')) #widget.username_lineedit.setText( # config.cparser.value('twitchbot/username')) - widget.token_lineedit.setText( - config.cparser.value('twitchbot/chattoken')) - widget.secret_lineedit.setText( - config.cparser.value('twitchbot/secret')) + widget.token_lineedit.setText(config.cparser.value('twitchbot/chattoken')) + widget.secret_lineedit.setText(config.cparser.value('twitchbot/secret')) self.update_token_name() @staticmethod @@ -156,8 +146,7 @@ def save(config, widget, subprocesses): newchattoken = widget.token_lineedit.text() newchattoken = newchattoken.replace('oauth:', '') - config.cparser.setValue('twitchbot/enabled', - widget.enable_checkbox.isChecked()) + config.cparser.setValue('twitchbot/enabled', widget.enable_checkbox.isChecked()) config.cparser.setValue('twitchbot/channel', newchannel) config.cparser.setValue('twitchbot/clientid', newclientid) config.cparser.setValue('twitchbot/secret', newsecret) @@ -194,8 +183,7 @@ def update_token_name(self): if self.token == token: return if token := token.replace('oauth:', ''): - if username := nowplaying.twitch.utils.qtsafe_validate_token( - token): + if username := nowplaying.twitch.utils.qtsafe_validate_token(token): self.widget.chatbot_username_line.setText(username) else: self.widget.chatbot_username_line.setText('(Invalid token?)') diff --git a/nowplaying/twitch/chat.py b/nowplaying/twitch/chat.py index 5a6760fc..23e99343 100644 --- a/nowplaying/twitch/chat.py +++ b/nowplaying/twitch/chat.py @@ -22,8 +22,7 @@ from PySide6.QtCore import QCoreApplication, QStandardPaths, Slot # pylint: disable=import-error, no-name-in-module from PySide6.QtWidgets import ( # pylint: disable=import-error, no-name-in-module - QCheckBox, QDialog, QDialogButtonBox, QVBoxLayout, QLabel, - QTableWidgetItem) + QCheckBox, QDialog, QDialogButtonBox, QVBoxLayout, QLabel, QTableWidgetItem) import nowplaying.bootstrap import nowplaying.config @@ -37,8 +36,7 @@ # needs to match ui file TWITCHBOT_CHECKBOXES = [ - 'anyone', 'broadcaster', 'moderator', 'subscriber', 'founder', 'conductor', - 'vip', 'bits' + 'anyone', 'broadcaster', 'moderator', 'subscriber', 'founder', 'conductor', 'vip', 'bits' ] @@ -49,13 +47,11 @@ def __init__(self, config=None, stopevent=None): self.config = config self.stopevent = stopevent self.watcher = None - self.requests = nowplaying.trackrequests.Requests(config=config, - stopevent=stopevent) + self.requests = nowplaying.trackrequests.Requests(config=config, stopevent=stopevent) self.metadb = nowplaying.db.MetadataDB() self.templatedir = pathlib.Path( - QStandardPaths.standardLocations( - QStandardPaths.DocumentsLocation)[0]).joinpath( - QCoreApplication.applicationName(), 'templates') + QStandardPaths.standardLocations(QStandardPaths.DocumentsLocation)[0]).joinpath( + QCoreApplication.applicationName(), 'templates') self.jinja2 = self.setup_jinja2(self.templatedir) self.twitch = None self.twitchcustom = False @@ -118,8 +114,8 @@ async def run_chat(self, twitchlogin): # pylint: disable=too-many-branches, too # otherwise, use the existing authentication and run as # the user - while not self.config.cparser.value( - 'twitchbot/chat', type=bool) and not self.stopevent.is_set(): + while not self.config.cparser.value('twitchbot/chat', + type=bool) and not self.stopevent.is_set(): await asyncio.sleep(1) self.config.get() @@ -154,25 +150,19 @@ async def run_chat(self, twitchlogin): # pylint: disable=too-many-branches, too await twitchlogin.cache_token_del() if not self.twitch: - logging.error( - 'No valid credentials to start Twitch Chat support.') + logging.error('No valid credentials to start Twitch Chat support.') await asyncio.sleep(60) continue self.chat = await Chat( - self.twitch, - initial_channel=self.config.cparser.value( - 'twitchbot/channel')) - self.chat.register_event(ChatEvent.READY, - self.on_twitchchat_ready) - self.chat.register_command( - 'whatsnowplayingversion', - self.on_twitchchat_whatsnowplayingversion) + self.twitch, initial_channel=self.config.cparser.value('twitchbot/channel')) + self.chat.register_event(ChatEvent.READY, self.on_twitchchat_ready) + self.chat.register_command('whatsnowplayingversion', + self.on_twitchchat_whatsnowplayingversion) for configitem in self.config.cparser.childGroups(): if 'twitchbot-command-' in configitem: command = configitem.replace('twitchbot-command-', '') - self.chat.register_command(command, - self.on_twitchchat_message) + self.chat.register_command(command, self.on_twitchchat_message) self.chat.start() loggedin = True @@ -184,8 +174,7 @@ async def run_chat(self, twitchlogin): # pylint: disable=too-many-branches, too task = loop.create_task(self._setup_timer()) self.tasks.add(task) task.add_done_callback(self.tasks.discard) - except (aiohttp.client_exceptions.ClientConnectorError, - socket.gaierror) as error: + except (aiohttp.client_exceptions.ClientConnectorError, socket.gaierror) as error: logging.error(error) await asyncio.sleep(60) continue @@ -202,8 +191,7 @@ async def run_chat(self, twitchlogin): # pylint: disable=too-many-branches, too async def on_twitchchat_ready(self, ready_event): ''' twitch chatbot has connected, now join ''' - await ready_event.chat.join_room( - self.config.cparser.value('twitchbot/channel')) + await ready_event.chat.join_room(self.config.cparser.value('twitchbot/channel')) async def on_twitchchat_message(self, msg): ''' twitch chatbot incoming message ''' @@ -220,16 +208,14 @@ async def on_twitchchat_whatsnowplayingversion(self, cmd): inputsource = self.config.cparser.value('settings/input') delta = datetime.datetime.utcnow() - self.starttime plat = platform.platform() - content = ( - f'whatsnowplaying v{self.config.version} by @modernmeerkat. ' - f'Using {inputsource} on {plat}. Running for {delta}.') + content = (f'whatsnowplaying v{self.config.version} by @modernmeerkat. ' + f'Using {inputsource} on {plat}. Running for {delta}.') try: await cmd.reply(content) except: #pylint: disable=bare-except for line in traceback.format_exc().splitlines(): logging.error(line) - await self.chat.send_message( - self.config.cparser.value('twitchbot/channel'), content) + await self.chat.send_message(self.config.cparser.value('twitchbot/channel'), content) return def check_command_perms(self, profile, command): @@ -237,8 +223,7 @@ def check_command_perms(self, profile, command): self.config.get() # shortcut the 'anyone' commands - if self.config.cparser.value(f'twitchbot-command-{command}/anyone', - type=bool): + if self.config.cparser.value(f'twitchbot-command-{command}/anyone', type=bool): return True self.config.cparser.beginGroup(f'twitchbot-command-{command}') @@ -250,8 +235,7 @@ def check_command_perms(self, profile, command): if perms: return any( - profile.get(usertype) and profile[usertype] > 0 - for usertype in perms.items()) + profile.get(usertype) and profile[usertype] > 0 for usertype in perms.items()) return True @@ -273,23 +257,19 @@ async def do_command(self, msg): # pylint: disable=unused-argument if not self.check_command_perms(msg.user.badges, commandlist[0]): return - if self.config.cparser.value('settings/requests', - type=bool) and self.config.cparser.value( - 'twitchbot/chatrequests', type=bool): - if reply := await self.handle_request(commandlist[0], - commandlist[1:], + if self.config.cparser.value('settings/requests', type=bool) and self.config.cparser.value( + 'twitchbot/chatrequests', type=bool): + if reply := await self.handle_request(commandlist[0], commandlist[1:], msg.user.display_name): metadata |= reply - await self._post_template(msg=msg, - template=cmdfile, - moremetadata=metadata) + await self._post_template(msg=msg, template=cmdfile, moremetadata=metadata) async def redemption_to_chat_request_bridge(self, command, metadata): ''' respond in chat when a redemption request triggers ''' if self.config.cparser.value('twitchbot/chatrequests', - type=bool) and self.config.cparser.value( - 'twitchbot/chat', type=bool): + type=bool) and self.config.cparser.value('twitchbot/chat', + type=bool): cmdfile = f'twitchbot_{command}.txt' await self._post_template(template=cmdfile, moremetadata=metadata) @@ -302,18 +282,15 @@ async def handle_request(self, command, params, username): # pylint: disable=un logging.debug('got commandlist: %s', commandlist) if setting := await self.requests.find_command(command): logging.debug(setting) - setting[ - 'userimage'] = await nowplaying.twitch.utils.get_user_image( - self.twitch, username) + setting['userimage'] = await nowplaying.twitch.utils.get_user_image( + self.twitch, username) if setting.get('type') == 'Generic': - reply = await self.requests.user_track_request( - setting, username, commandlist) + reply = await self.requests.user_track_request(setting, username, commandlist) elif setting.get('type') == 'Roulette': - reply = await self.requests.user_roulette_request( - setting, username, commandlist[1:]) + reply = await self.requests.user_roulette_request(setting, username, + commandlist[1:]) elif setting.get('type') == 'GifWords': - reply = await self.requests.gifwords_request( - setting, username, commandlist) + reply = await self.requests.gifwords_request(setting, username, commandlist) return reply @staticmethod @@ -384,8 +361,7 @@ async def _async_announce_track(self): return if not pathlib.Path(anntemplate).exists(): - logging.error('Annoucement template %s does not exist.', - anntemplate) + logging.error('Annoucement template %s does not exist.', anntemplate) return metadata = await self.metadb.read_last_meta_async() @@ -396,15 +372,13 @@ async def _async_announce_track(self): # don't announce empty content if not metadata['artist'] and not metadata['title']: - logging.warning( - 'Both artist and title are empty; skipping announcement') + logging.warning('Both artist and title are empty; skipping announcement') return if metadata['artist'] == LASTANNOUNCED['artist'] and \ metadata['title'] == LASTANNOUNCED['title']: logging.warning( - 'Same artist and title or doubled event notification; skipping announcement.' - ) + 'Same artist and title or doubled event notification; skipping announcement.') return LASTANNOUNCED['artist'] = metadata['artist'] @@ -412,11 +386,10 @@ async def _async_announce_track(self): await self._delay_write() - logging.info('Announcing %s', - self.config.cparser.value('twitchbot/announce')) + logging.info('Announcing %s', self.config.cparser.value('twitchbot/announce')) - await self._post_template(template=pathlib.Path( - self.config.cparser.value('twitchbot/announce')).name) + await self._post_template( + template=pathlib.Path(self.config.cparser.value('twitchbot/announce')).name) except: #pylint: disable=bare-except for line in traceback.format_exc().splitlines(): logging.error(line) @@ -441,17 +414,14 @@ async def _post_template(self, msg=None, template=None, moremetadata=None): #py j2template = self.jinja2.get_template(template) message = j2template.render(metadata) except Exception as error: # pylint: disable=broad-except - logging.error('template %s rendering failure: %s', template, - error) + logging.error('template %s rendering failure: %s', template, error) return messages = message.split(SPLITMESSAGETEXT) try: for content in messages: if not self.chat.is_connected(): - logging.error( - 'Twitch chat is not connected. Not sending message.' - ) + logging.error('Twitch chat is not connected. Not sending message.') return if msg: try: @@ -460,15 +430,12 @@ async def _post_template(self, msg=None, template=None, moremetadata=None): #py for line in traceback.format_exc().splitlines(): logging.error(line) await self.chat.send_message( - self.config.cparser.value('twitchbot/channel'), - content) + self.config.cparser.value('twitchbot/channel'), content) else: - await self.chat.send_message( - self.config.cparser.value('twitchbot/channel'), - content) + await self.chat.send_message(self.config.cparser.value('twitchbot/channel'), + content) except ConnectionResetError: - logging.debug( - 'Twitch appears to be down. Cannot send message.') + logging.debug('Twitch appears to be down. Cannot send message.') except: #pylint: disable=bare-except for line in traceback.format_exc().splitlines(): logging.error(line) @@ -502,8 +469,7 @@ def connect(self, uihelp, widget): @Slot() def on_announce_button(self): ''' twitchbot announce button clicked action ''' - self.uihelp.template_picker_lineedit(self.widget.announce_lineedit, - limit='twitchbot_*.txt') + self.uihelp.template_picker_lineedit(self.widget.announce_lineedit, limit='twitchbot_*.txt') def _twitchbot_command_load(self, command=None, **kwargs): if not command: @@ -521,8 +487,7 @@ def _twitchbot_command_load(self, command=None, **kwargs): checkbox.setChecked(kwargs[cbtype]) else: checkbox.setChecked(True) - self.widget.command_perm_table.setCellWidget( - row, column + 1, checkbox) + self.widget.command_perm_table.setCellWidget(row, column + 1, checkbox) @Slot() def on_add_button(self): @@ -567,15 +532,11 @@ def clear_table(widget): type=bool) self._twitchbot_command_load(**setting) - widget.enable_checkbox.setChecked( - config.cparser.value('twitchbot/chat', type=bool)) + widget.enable_checkbox.setChecked(config.cparser.value('twitchbot/chat', type=bool)) widget.command_perm_table.resizeColumnsToContents() - widget.announce_lineedit.setText( - config.cparser.value('twitchbot/announce')) - widget.commandchar_lineedit.setText( - config.cparser.value('twitchbot/commandchar')) - widget.announce_delay_lineedit.setText( - config.cparser.value('twitchbot/announcedelay')) + widget.announce_lineedit.setText(config.cparser.value('twitchbot/announce')) + widget.commandchar_lineedit.setText(config.cparser.value('twitchbot/commandchar')) + widget.announce_delay_lineedit.setText(config.cparser.value('twitchbot/announcedelay')) @staticmethod def save(config, widget, subprocesses): #pylint: disable=unused-argument @@ -602,13 +563,10 @@ def reset_commands(widget, config): config.cparser.setValue('twitchbot/chat', newenabled) - config.cparser.setValue('twitchbot/announce', - widget.announce_lineedit.text()) - config.cparser.setValue('twitchbot/commandchar', - widget.commandchar_lineedit.text()) + config.cparser.setValue('twitchbot/announce', widget.announce_lineedit.text()) + config.cparser.setValue('twitchbot/commandchar', widget.commandchar_lineedit.text()) - config.cparser.setValue('twitchbot/announcedelay', - widget.announce_delay_lineedit.text()) + config.cparser.setValue('twitchbot/announcedelay', widget.announce_delay_lineedit.text()) reset_commands(widget.command_perm_table, config.cparser) @@ -640,8 +598,7 @@ def verify(widget): ''' verify the settings are good ''' char = widget.commandchar_lineedit.text() if char and char[0] in ['/', '.']: - raise PluginVerifyError( - 'Twitch command character cannot start with / or .') + raise PluginVerifyError('Twitch command character cannot start with / or .') class ChatTemplateUpgradeDialog(QDialog): # pylint: disable=too-few-public-methods diff --git a/nowplaying/twitch/redemptions.py b/nowplaying/twitch/redemptions.py index 5829616b..c5d664be 100644 --- a/nowplaying/twitch/redemptions.py +++ b/nowplaying/twitch/redemptions.py @@ -16,10 +16,7 @@ import nowplaying.trackrequests import nowplaying.twitch.utils -USER_SCOPE = [ - AuthScope.CHANNEL_READ_REDEMPTIONS, AuthScope.CHAT_READ, - AuthScope.CHAT_EDIT -] +USER_SCOPE = [AuthScope.CHANNEL_READ_REDEMPTIONS, AuthScope.CHAT_READ, AuthScope.CHAT_EDIT] class TwitchRedemptions: #pylint: disable=too-many-instance-attributes @@ -39,8 +36,7 @@ def __init__(self, config=None, stopevent=None): self.chat = None self.uuid = None self.pubsub = None - self.requests = nowplaying.trackrequests.Requests(config=config, - stopevent=stopevent) + self.requests = nowplaying.trackrequests.Requests(config=config, stopevent=stopevent) self.widgets = None self.watcher = None self.twitch = None @@ -55,25 +51,18 @@ async def callback_redemption(self, uuid, data): # pylint: disable=unused-argum user_input = None if setting := await self.requests.find_twitchtext(redemptitle): - setting[ - 'userimage'] = await nowplaying.twitch.utils.get_user_image( - self.twitch, user) + setting['userimage'] = await nowplaying.twitch.utils.get_user_image(self.twitch, user) if setting.get('type') == 'Generic': - reply = await self.requests.user_track_request( - setting, user, user_input) + reply = await self.requests.user_track_request(setting, user, user_input) elif setting.get('type') == 'Roulette': - reply = await self.requests.user_roulette_request( - setting, user, user_input) + reply = await self.requests.user_roulette_request(setting, user, user_input) elif setting.get('type') == 'Twofer': - reply = await self.requests.twofer_request( - setting, user, user_input) + reply = await self.requests.twofer_request(setting, user, user_input) elif setting.get('type') == 'GifWords': - reply = await self.requests.gifwords_request( - setting, user, user_input) + reply = await self.requests.gifwords_request(setting, user, user_input) if self.chat and setting.get('command'): - await self.chat.redemption_to_chat_request_bridge( - setting['command'], reply) + await self.chat.redemption_to_chat_request_bridge(setting['command'], reply) async def run_redemptions(self, twitchlogin, chat): # pylint: disable=too-many-branches ''' twitch redemptions ''' @@ -90,9 +79,8 @@ async def run_redemptions(self, twitchlogin, chat): # pylint: disable=too-many- # while not self.stopevent.is_set() and ( - not self.config.cparser.value('twitchbot/redemptions', - type=bool) or - not self.config.cparser.value('settings/requests', type=bool)): + not self.config.cparser.value('twitchbot/redemptions', type=bool) + or not self.config.cparser.value('settings/requests', type=bool)): await asyncio.sleep(1) self.config.get() @@ -107,8 +95,7 @@ async def run_redemptions(self, twitchlogin, chat): # pylint: disable=too-many- break if loggedin and self.pubsub and not self.pubsub.is_connected(): - logging.debug( - 'Was logged in; but not connected to pubsub anymore') + logging.debug('Was logged in; but not connected to pubsub anymore') await self.stop() loggedin = False @@ -120,9 +107,7 @@ async def run_redemptions(self, twitchlogin, chat): # pylint: disable=too-many- try: self.twitch = await twitchlogin.api_login() if not self.twitch: - logging.debug( - "something happened getting twitch api_login; aborting" - ) + logging.debug("something happened getting twitch api_login; aborting") await twitchlogin.cache_token_del() continue # starting up PubSub @@ -138,9 +123,7 @@ async def run_redemptions(self, twitchlogin, chat): # pylint: disable=too-many- try: user = await first( - self.twitch.get_users(logins=[ - self.config.cparser.value('twitchbot/channel') - ])) + self.twitch.get_users(logins=[self.config.cparser.value('twitchbot/channel')])) except: #pylint: disable=bare-except for line in traceback.format_exc().splitlines(): logging.error(line) @@ -150,8 +133,8 @@ async def run_redemptions(self, twitchlogin, chat): # pylint: disable=too-many- # you can either start listening before or after you started pubsub. try: - self.uuid = await self.pubsub.listen_channel_points( - user.id, self.callback_redemption) + self.uuid = await self.pubsub.listen_channel_points(user.id, + self.callback_redemption) loggedin = True except: #pylint: disable=bare-except for line in traceback.format_exc().splitlines(): diff --git a/nowplaying/twitch/utils.py b/nowplaying/twitch/utils.py index 670153ba..be312de4 100644 --- a/nowplaying/twitch/utils.py +++ b/nowplaying/twitch/utils.py @@ -16,10 +16,7 @@ import nowplaying.utils -USER_SCOPE = [ - AuthScope.CHANNEL_READ_REDEMPTIONS, AuthScope.CHAT_READ, - AuthScope.CHAT_EDIT -] +USER_SCOPE = [AuthScope.CHANNEL_READ_REDEMPTIONS, AuthScope.CHAT_READ, AuthScope.CHAT_EDIT] async def get_user_image(twitch, loginname): @@ -72,8 +69,7 @@ async def attempt_user_auth(self, token, refresh_token): return False try: - await TwitchLogin.TWITCH.set_user_authentication( - token, USER_SCOPE, refresh_token) + await TwitchLogin.TWITCH.set_user_authentication(token, USER_SCOPE, refresh_token) TwitchLogin.TWITCH.user_auth_refresh_callback = self.save_refreshed_tokens await TwitchLogin.TWITCH.refresh_used_token() except Exception as error: #pylint: disable=broad-except @@ -91,40 +87,31 @@ async def api_login(self): async with TwitchLogin.TWITCH_LOCK: try: - if self.config.cparser.value( - 'twitchbot/clientid') and self.config.cparser.value( - 'twitchbot/secret'): + if self.config.cparser.value('twitchbot/clientid') and self.config.cparser.value( + 'twitchbot/secret'): TwitchLogin.TWITCH = await Twitch( self.config.cparser.value('twitchbot/clientid'), self.config.cparser.value('twitchbot/secret'), session_timeout=self.timeout) token = self.config.cparser.value('twitchbot/oldusertoken') - refresh_token = self.config.cparser.value( - 'twitchbot/oldrefreshtoken') - oldscopes = self.config.cparser.value( - 'twitchbot/oldscopes') + refresh_token = self.config.cparser.value('twitchbot/oldrefreshtoken') + oldscopes = self.config.cparser.value('twitchbot/oldscopes') if oldscopes != USER_SCOPE: token = None if not await self.attempt_user_auth(token, refresh_token): - auth = UserAuthenticator(TwitchLogin.TWITCH, - USER_SCOPE, - force_verify=False) + auth = UserAuthenticator(TwitchLogin.TWITCH, USER_SCOPE, force_verify=False) token, refresh_token = await auth.authenticate() oldscopes = USER_SCOPE await self.attempt_user_auth(token, refresh_token) - self.config.cparser.setValue('twitchbot/oldusertoken', - token) - self.config.cparser.setValue('twitchbot/oldrefreshtoken', - refresh_token) - self.config.cparser.setValue('twitchbot/oldscopes', - USER_SCOPE) - except (aiohttp.client_exceptions.ClientConnectorError, - socket.gaierror) as error: + self.config.cparser.setValue('twitchbot/oldusertoken', token) + self.config.cparser.setValue('twitchbot/oldrefreshtoken', refresh_token) + self.config.cparser.setValue('twitchbot/oldscopes', USER_SCOPE) + except (aiohttp.client_exceptions.ClientConnectorError, socket.gaierror) as error: logging.error(error) except: # pylint: disable=bare-except for line in traceback.format_exc().splitlines(): diff --git a/nowplaying/uihelp.py b/nowplaying/uihelp.py index 45f23d94..98646bd4 100644 --- a/nowplaying/uihelp.py +++ b/nowplaying/uihelp.py @@ -19,13 +19,11 @@ def template_picker(self, startfile=None, startdir=None, limit='*.txt'): startdir = os.path.dirname(startfile) elif not startdir: startdir = os.path.join(self.config.templatedir, "templates") - if filename := QFileDialog.getOpenFileName(self.qtui, 'Open file', - startdir, limit): + if filename := QFileDialog.getOpenFileName(self.qtui, 'Open file', startdir, limit): return filename[0] return None def template_picker_lineedit(self, qwidget, limit='*.txt'): ''' generic code to pick a template file ''' - if filename := self.template_picker(startfile=qwidget.text(), - limit=limit): + if filename := self.template_picker(startfile=qwidget.text(), limit=limit): qwidget.setText(filename) diff --git a/nowplaying/upgrade.py b/nowplaying/upgrade.py index 57f97a75..e3052a6b 100644 --- a/nowplaying/upgrade.py +++ b/nowplaying/upgrade.py @@ -34,8 +34,7 @@ def __init__(self, parent=None): def fill_it_in(self, oldversion, newversion): ''' fill in the upgrade versions and message ''' messages = [ - f'Your version: {oldversion}', f'New version: {newversion}', - 'Download new version?' + f'Your version: {oldversion}', f'New version: {newversion}', 'Download new version?' ] for msg in messages: @@ -60,8 +59,7 @@ def __init__(self, testdir=None): def _getconfig(self): return QSettings(self.qsettingsformat, QSettings.UserScope, - QCoreApplication.organizationName(), - QCoreApplication.applicationName()) + QCoreApplication.organizationName(), QCoreApplication.applicationName()) def backup_config(self): ''' back up the old config ''' @@ -71,13 +69,11 @@ def backup_config(self): if self.testdir: docpath = self.testdir else: # pragma: no cover - docpath = QStandardPaths.standardLocations( - QStandardPaths.DocumentsLocation)[0] - backupdir = pathlib.Path(docpath).joinpath( - QCoreApplication.applicationName(), 'configbackup') + docpath = QStandardPaths.standardLocations(QStandardPaths.DocumentsLocation)[0] + backupdir = pathlib.Path(docpath).joinpath(QCoreApplication.applicationName(), + 'configbackup') - logging.info('Making a backup of config prior to upgrade: %s', - backupdir) + logging.info('Making a backup of config prior to upgrade: %s', backupdir) try: pathlib.Path(backupdir).mkdir(parents=True, exist_ok=True) backup = backupdir.joinpath(f'{datestr}-config.bak') @@ -104,17 +100,14 @@ def upgrade(self): return # these got moved in 3.1.0 - npsqldb = pathlib.Path( - QStandardPaths.standardLocations( - QStandardPaths.CacheLocation)[0]).joinpath('npsql.db') + npsqldb = pathlib.Path(QStandardPaths.standardLocations( + QStandardPaths.CacheLocation)[0]).joinpath('npsql.db') npsqldb.unlink(missing_ok=True) - webdb = pathlib.Path( - QStandardPaths.standardLocations( - QStandardPaths.CacheLocation)[0]).joinpath('web.db') + webdb = pathlib.Path(QStandardPaths.standardLocations( + QStandardPaths.CacheLocation)[0]).joinpath('web.db') webdb.unlink(missing_ok=True) - oldversstr = config.value('settings/configversion', - defaultValue='3.0.0') + oldversstr = config.value('settings/configversion', defaultValue='3.0.0') thisverstr = nowplaying.version.__VERSION__ #pylint: disable=no-member oldversion = nowplaying.upgradeutils.Version(oldversstr) @@ -158,8 +151,7 @@ def upgrade(self): try: oldval = rawconfig.value(oldkey) except: # pylint: disable=bare-except - logging.debug('%s vs %s: skipped, no new value', oldkey, - newkey) + logging.debug('%s vs %s: skipped, no new value', oldkey, newkey) continue if oldval: @@ -184,8 +176,7 @@ def __init__(self, bundledir=None, testdir=None): QCoreApplication.applicationName(), 'templates') else: # pragma: no cover self.usertemplatedir = pathlib.Path( - QStandardPaths.standardLocations( - QStandardPaths.DocumentsLocation)[0], + QStandardPaths.standardLocations(QStandardPaths.DocumentsLocation)[0], QCoreApplication.applicationName()).joinpath('templates') self.usertemplatedir.mkdir(parents=True, exist_ok=True) self.alert = False @@ -217,8 +208,8 @@ def check_preload(self, filename, userhash): for version, hexdigest in self.oldshas[filename].items(): if userhash == hexdigest: found = version - logging.debug('filename = %s, found = %s userhash = %s hexdigest = %s', - filename, found, userhash, hexdigest) + logging.debug('filename = %s, found = %s userhash = %s hexdigest = %s', filename, found, + userhash, hexdigest) return found def setup_templates(self): @@ -231,8 +222,7 @@ def setup_templates(self): if not userpath.exists(): shutil.copyfile(apppath, userpath) - logging.info('Added %s to %s', apppath.name, - self.usertemplatedir) + logging.info('Added %s to %s', apppath.name, self.usertemplatedir) continue apphash = checksum(apppath) @@ -244,8 +234,8 @@ def setup_templates(self): if version := self.check_preload(apppath.name, userhash): userpath.unlink() shutil.copyfile(apppath, userpath) - logging.info('Replaced %s from %s with %s', apppath.name, - version, self.usertemplatedir) + logging.info('Replaced %s from %s with %s', apppath.name, version, + self.usertemplatedir) continue destpath = str(userpath).replace('.txt', '.new') @@ -257,8 +247,7 @@ def setup_templates(self): destpath.unlink() self.alert = True - logging.info('New version of %s copied to %s', apppath.name, - destpath) + logging.info('New version of %s copied to %s', apppath.name, destpath) shutil.copyfile(apppath, destpath) self.copied.append(apppath.name) @@ -268,8 +257,7 @@ def upgrade_m3u(config, testdir=None): if 'VirtualDJ' in config.value('m3u/directory'): historypath = pathlib.Path(config.value('m3u/directory')) config.setValue('virtualdj/history', config.value('m3u/directory')) - config.setValue('virtualdj/playlists', - str(historypath.parent.joinpath('Playlists'))) + config.setValue('virtualdj/playlists', str(historypath.parent.joinpath('Playlists'))) config.setValue('settings/input', 'virtualdj') if not testdir: msgbox = QMessageBox() @@ -280,8 +268,7 @@ def upgrade_m3u(config, testdir=None): def upgrade_filters(config): ''' setup the recommended filters ''' - if config.value('settings/stripextras', - type=bool) and not config.value('regex_filter/0'): + if config.value('settings/stripextras', type=bool) and not config.value('regex_filter/0'): stripworldlist = ['clean', 'dirty', 'explicit', 'official music video'] joinlist = '|'.join(stripworldlist) config.setValue('regex_filter/0', f' \\((?i:{joinlist})\\)') diff --git a/nowplaying/upgradeutils.py b/nowplaying/upgradeutils.py index 7b1494f0..da3fb9d2 100644 --- a/nowplaying/upgradeutils.py +++ b/nowplaying/upgradeutils.py @@ -84,8 +84,8 @@ def __lt__(self, other): if self.chunk.get('commitnum') and not other.chunk.get('commitnum'): return False - if (self.chunk.get('commitnum') and other.chunk.get('commitnum') and - self.chunk.get('commitnum') != other.chunk.get('commitnum')): + if (self.chunk.get('commitnum') and other.chunk.get('commitnum') + and self.chunk.get('commitnum') != other.chunk.get('commitnum')): return self.chunk.get('commitnum') < other.chunk.get('commitnum') return False @@ -108,12 +108,9 @@ def get_versions(self, testdata=None): try: if not testdata: headers = { - 'X-GitHub-Api-Version': - '2022-11-28', - 'Accept': - 'application/vnd.github.v3+json', - 'User-Agent': - 'What\'s Now Playing/{nowplaying.version.__VERSION__}', + 'X-GitHub-Api-Version': '2022-11-28', + 'Accept': 'application/vnd.github.v3+json', + 'User-Agent': 'What\'s Now Playing/{nowplaying.version.__VERSION__}', } if token := os.getenv('GITHUB_TOKEN'): logging.debug('Using GITHUB_TOKEN') diff --git a/nowplaying/utils.py b/nowplaying/utils.py index 14f1bc9f..310a28cf 100755 --- a/nowplaying/utils.py +++ b/nowplaying/utils.py @@ -84,8 +84,7 @@ def setup_jinja2(self, directory): ''' set up the environment ''' return jinja2.Environment(loader=jinja2.FileSystemLoader(directory), finalize=self._finalize, - autoescape=jinja2.select_autoescape( - ['htm', 'html', 'xml'])) + autoescape=jinja2.select_autoescape(['htm', 'html', 'xml'])) def generate(self, metadatadict=None): ''' get the generated template ''' @@ -93,8 +92,7 @@ def generate(self, metadatadict=None): rendertext = 'Template has syntax errors' try: - if not self.filename or not os.path.exists( - self.filename) or not self.template: + if not self.filename or not os.path.exists(self.filename) or not self.template: return " No template found; check Now Playing settings." rendertext = self.template.render(**metadatadict) except: #pylint: disable=bare-except @@ -178,8 +176,8 @@ def songpathsubst(config, filename): try: newname = filename.replace(songin, songout) except Exception as error: # pylint: disable=broad-except - logging.error('Unable to do path replacement (%s -> %s on %s): %s', - songin, songout, filename, error) + logging.error('Unable to do path replacement (%s -> %s on %s): %s', songin, songout, + filename, error) return filename logging.debug('filename substitution: %s -> %s', origfilename, newname) @@ -199,8 +197,7 @@ def titlestripper_basic(title=None, title_regex_list=None): ''' Basic title removal ''' if not title_regex_list or len(title_regex_list) == 0: title_regex_list = STRIPRELIST - return titlestripper_advanced(title=title, - title_regex_list=title_regex_list) + return titlestripper_advanced(title=title, title_regex_list=title_regex_list) def titlestripper_advanced(title=None, title_regex_list=None): diff --git a/pyproject.toml b/pyproject.toml index ca0cc92e..165df606 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -90,7 +90,12 @@ qt_qapp_name = "testsuite" # List of plugins (as comma separated values of python module names) to load, # usually to register additional checkers. load-plugins = ["pylint.extensions.no_self_use"] -ignore = ["nowplaying/beam"] +ignore-paths = [ + "nowplaying/beam", + "nowplaying/qtrc.py", + "nowplaying/vendor", + "nowplaying/version.py" +] [tool.vendoring] destination = "nowplaying/vendor" @@ -116,3 +121,13 @@ __BUILD_DATE__ = '{build_date:%Y-%m-%dT%H:%M:%SZ}' __CURRENT_TAG__ = '{base_version}' # pylint: disable=trailing-newlines ''' + +[tool.yapf] +column_limit = 100 + +[tool.yapfignore] +ignore_patterns = [ + "nowplaying/version.py", + "nowplaying/vendor/**", + "nowplaying/qtrc.py", +] diff --git a/test_settingsui.py b/test_settingsui.py index 067b57af..88be54eb 100755 --- a/test_settingsui.py +++ b/test_settingsui.py @@ -11,15 +11,12 @@ from PySide6.QtUiTools import QUiLoader GENERAL = [ - 'about', 'general', 'filter', 'obsws', 'quirks', 'settings', 'source', - 'twitchbot', 'webserver' + 'about', 'general', 'filter', 'obsws', 'quirks', 'settings', 'source', 'twitchbot', 'webserver' ] INPUTS = ['inputs_m3u', 'inputs_mpris2', 'inputs_serato'] -ARTISTEXTRAS = [ - 'artistextras_discogs', 'artistextras_fanarttv', 'artistextras_theaudiodb' -] +ARTISTEXTRAS = ['artistextras_discogs', 'artistextras_fanarttv', 'artistextras_theaudiodb'] RECOG = ['recognition_acoustidmb'] @@ -59,19 +56,15 @@ def _load_ui(uipath, name): self.qtui.settings_stack.addWidget(self.widgets[basic]) self._load_list_item(f'{basic}', self.widgets[basic]) - self.qtui.settings_list.currentRowChanged.connect( - self._set_stacked_display) + self.qtui.settings_list.currentRowChanged.connect(self._set_stacked_display) def _connect_recognition_acoustidmb_widget(self, qobject): - qobject.acoustid_checkbox.clicked.connect( - self._acoustidmb_checkbox_hook) + qobject.acoustid_checkbox.clicked.connect(self._acoustidmb_checkbox_hook) @Slot() def _acoustidmb_checkbox_hook(self): - if self.widgets['recognition_acoustidmb'].acoustid_checkbox.isChecked( - ): - self.widgets[ - 'recognition_acoustidmb'].musicbrainz_checkbox.setChecked(True) + if self.widgets['recognition_acoustidmb'].acoustid_checkbox.isChecked(): + self.widgets['recognition_acoustidmb'].musicbrainz_checkbox.setChecked(True) @staticmethod def _connect_webserver_widget(qobject): @@ -94,8 +87,7 @@ def _connect_source_widget(self, qobject): def _connect_filter_widget(self, qobject): ''' connect regex filter to template picker''' - qobject.add_recommended_button.clicked.connect( - self.on_filter_add_recommended_button) + qobject.add_recommended_button.clicked.connect(self.on_filter_add_recommended_button) qobject.add_button.clicked.connect(self.on_filter_regex_add_button) qobject.del_button.clicked.connect(self.on_filter_regex_del_button) diff --git a/tests-qt/test_settingsui.py b/tests-qt/test_settingsui.py index 1f56a865..abdb0f22 100644 --- a/tests-qt/test_settingsui.py +++ b/tests-qt/test_settingsui.py @@ -59,8 +59,7 @@ def test_settingsui_save(bootstrap, qtbot): rect = settingsui.widgets['source'].sourcelist.visualItemRect(item) center = rect.center() - assert settingsui.widgets['source'].sourcelist.itemAt( - center).text() == item.text() + assert settingsui.widgets['source'].sourcelist.itemAt(center).text() == item.text() settingsui.widgets['webserver'].enable_checkbox.setChecked(False) diff --git a/tests/test_acoustidmb.py b/tests/test_acoustidmb.py index 144d0614..707af58a 100755 --- a/tests/test_acoustidmb.py +++ b/tests/test_acoustidmb.py @@ -8,8 +8,7 @@ import nowplaying.recognition.acoustidmb # pylint: disable=import-error if not os.environ.get('ACOUSTID_TEST_APIKEY'): - pytest.skip("skipping, ACOUSTID_TEST_APIKEY is not set", - allow_module_level=True) + pytest.skip("skipping, ACOUSTID_TEST_APIKEY is not set", allow_module_level=True) @pytest.fixture @@ -18,47 +17,34 @@ def getacoustidmbplugin(bootstrap): config = bootstrap config.cparser.setValue('acoustidmb/enabled', True) config.cparser.setValue('musicbrainz/enabled', True) - config.cparser.setValue('acoustidmb/acoustidapikey', - os.environ['ACOUSTID_TEST_APIKEY']) - config.cparser.setValue('acoustidmb/emailaddress', - 'aw+wnptest@effectivemachines.com') + config.cparser.setValue('acoustidmb/acoustidapikey', os.environ['ACOUSTID_TEST_APIKEY']) + config.cparser.setValue('acoustidmb/emailaddress', 'aw+wnptest@effectivemachines.com') yield nowplaying.recognition.acoustidmb.Plugin(config=config) def test_15ghosts2_orig(getacoustidmbplugin, getroot): # pylint: disable=redefined-outer-name ''' automated integration test ''' plugin = getacoustidmbplugin - metadata = plugin.recognize({ - 'filename': - os.path.join(getroot, 'tests', 'audio', '15_Ghosts_II_64kb_orig.mp3') - }) + metadata = plugin.recognize( + {'filename': os.path.join(getroot, 'tests', 'audio', '15_Ghosts_II_64kb_orig.mp3')}) assert metadata['album'] == 'Ghosts I–IV' assert metadata['artist'] == 'Nine Inch Nails' assert metadata['date'] == '2008-03-02' assert metadata['label'] == 'The Null Corporation' - assert metadata['musicbrainzartistid'] == [ - 'b7ffd2af-418f-4be2-bdd1-22f8b48613da' - ] - assert metadata[ - 'musicbrainzrecordingid'] == '2d7f08e1-be1c-4b86-b725-6e675b7b6de0' + assert metadata['musicbrainzartistid'] == ['b7ffd2af-418f-4be2-bdd1-22f8b48613da'] + assert metadata['musicbrainzrecordingid'] == '2d7f08e1-be1c-4b86-b725-6e675b7b6de0' assert metadata['title'] == '15 Ghosts II' def test_15ghosts2_fullytagged(getacoustidmbplugin, getroot): # pylint: disable=redefined-outer-name ''' automated integration test ''' plugin = getacoustidmbplugin - metadata = plugin.recognize({ - 'filename': - os.path.join(getroot, 'tests', 'audio', - '15_Ghosts_II_64kb_füllytâgged.mp3') - }) + metadata = plugin.recognize( + {'filename': os.path.join(getroot, 'tests', 'audio', '15_Ghosts_II_64kb_füllytâgged.mp3')}) assert metadata['album'] == 'Ghosts I–IV' assert metadata['artist'] == 'Nine Inch Nails' assert metadata['date'] == '2008-03-02' assert metadata['label'] == 'The Null Corporation' - assert metadata['musicbrainzartistid'] == [ - 'b7ffd2af-418f-4be2-bdd1-22f8b48613da' - ] - assert metadata[ - 'musicbrainzrecordingid'] == '2d7f08e1-be1c-4b86-b725-6e675b7b6de0' + assert metadata['musicbrainzartistid'] == ['b7ffd2af-418f-4be2-bdd1-22f8b48613da'] + assert metadata['musicbrainzrecordingid'] == '2d7f08e1-be1c-4b86-b725-6e675b7b6de0' assert metadata['title'] == '15 Ghosts II' diff --git a/tests/test_artistextras.py b/tests/test_artistextras.py index 64e1ca89..ea256fa5 100644 --- a/tests/test_artistextras.py +++ b/tests/test_artistextras.py @@ -16,8 +16,7 @@ PLUGINS.append('theaudiodb') if not PLUGINS: - pytest.skip("skipping, no API keys for artistextras are available", - allow_module_level=True) + pytest.skip("skipping, no API keys for artistextras are available", allow_module_level=True) class FakeImageCache: # pylint: disable=too-few-public-methods @@ -64,16 +63,13 @@ def getconfiguredplugin(bootstrap): config = bootstrap if 'discogs' in PLUGINS: configuresettings('discogs', config.cparser) - config.cparser.setValue('discogs/apikey', - os.environ['DISCOGS_API_KEY']) + config.cparser.setValue('discogs/apikey', os.environ['DISCOGS_API_KEY']) if 'fanarttv' in PLUGINS: configuresettings('fanarttv', config.cparser) - config.cparser.setValue('fanarttv/apikey', - os.environ['FANARTTV_API_KEY']) + config.cparser.setValue('fanarttv/apikey', os.environ['FANARTTV_API_KEY']) if 'theaudiodb' in PLUGINS: configuresettings('theaudiodb', config.cparser) - config.cparser.setValue('theaudiodb/apikey', - os.environ['THEAUDIODB_API_KEY']) + config.cparser.setValue('theaudiodb/apikey', os.environ['THEAUDIODB_API_KEY']) yield configureplugins(config) @@ -128,8 +124,7 @@ def test_noimagecache(getconfiguredplugin): # pylint: disable=redefined-outer-n { 'album': 'The Downward Spiral', 'artist': 'Nine Inch Nails' - }, - imagecache=None) + }, imagecache=None) if pluginname in ['discogs', 'theaudiodb']: assert data['artistwebsites'] assert data['artistlongbio'] @@ -143,8 +138,7 @@ def test_missingallartistdata(getconfiguredplugin): # pylint: disable=redefined for pluginname in PLUGINS: logging.debug('Testing %s', pluginname) - data = plugins[pluginname].download({'title': 'title'}, - imagecache=imagecaches[pluginname]) + data = plugins[pluginname].download({'title': 'title'}, imagecache=imagecaches[pluginname]) assert not data assert not imagecaches[pluginname].urls @@ -161,12 +155,9 @@ def test_missingmbid(getconfiguredplugin): # pylint: disable=redefined-outer-na assert data['artistfanarturls'] assert data['artistlongbio'] assert data['artistwebsites'] - assert imagecaches[pluginname].urls['Nine Inch Nails'][ - 'artistbanner'] - assert imagecaches[pluginname].urls['Nine Inch Nails'][ - 'artistlogo'] - assert imagecaches[pluginname].urls['Nine Inch Nails'][ - 'artistthumb'] + assert imagecaches[pluginname].urls['Nine Inch Nails']['artistbanner'] + assert imagecaches[pluginname].urls['Nine Inch Nails']['artistlogo'] + assert imagecaches[pluginname].urls['Nine Inch Nails']['artistthumb'] else: assert not data assert not imagecaches[pluginname].urls @@ -188,12 +179,9 @@ def test_badmbid(getconfiguredplugin): # pylint: disable=redefined-outer-name assert data['artistfanarturls'] assert data['artistlongbio'] assert data['artistwebsites'] - assert imagecaches[pluginname].urls['Nine Inch Nails'][ - 'artistbanner'] - assert imagecaches[pluginname].urls['Nine Inch Nails'][ - 'artistlogo'] - assert imagecaches[pluginname].urls['Nine Inch Nails'][ - 'artistthumb'] + assert imagecaches[pluginname].urls['Nine Inch Nails']['artistbanner'] + assert imagecaches[pluginname].urls['Nine Inch Nails']['artistlogo'] + assert imagecaches[pluginname].urls['Nine Inch Nails']['artistthumb'] else: assert not data assert not imagecaches[pluginname].urls @@ -207,8 +195,7 @@ def test_onlymbid(getconfiguredplugin): # pylint: disable=redefined-outer-name data = plugins[pluginname].download( { - 'musicbrainzartistid': - ['b7ffd2af-418f-4be2-bdd1-22f8b48613da'], + 'musicbrainzartistid': ['b7ffd2af-418f-4be2-bdd1-22f8b48613da'], }, imagecache=imagecaches[pluginname]) assert not data @@ -224,8 +211,7 @@ def test_artist_and_mbid(getconfiguredplugin): # pylint: disable=redefined-oute data = plugins[pluginname].download( { 'artist': 'Nine Inch Nails', - 'musicbrainzartistid': - ['b7ffd2af-418f-4be2-bdd1-22f8b48613da'], + 'musicbrainzartistid': ['b7ffd2af-418f-4be2-bdd1-22f8b48613da'], }, imagecache=imagecaches[pluginname]) if pluginname == 'theaudiodb': @@ -233,12 +219,9 @@ def test_artist_and_mbid(getconfiguredplugin): # pylint: disable=redefined-oute assert data['artistwebsites'] if pluginname in ['fanarttv', 'theaudiodb']: assert data['artistfanarturls'] - assert imagecaches[pluginname].urls['Nine Inch Nails'][ - 'artistbanner'] - assert imagecaches[pluginname].urls['Nine Inch Nails'][ - 'artistlogo'] - assert imagecaches[pluginname].urls['Nine Inch Nails'][ - 'artistthumb'] + assert imagecaches[pluginname].urls['Nine Inch Nails']['artistbanner'] + assert imagecaches[pluginname].urls['Nine Inch Nails']['artistlogo'] + assert imagecaches[pluginname].urls['Nine Inch Nails']['artistthumb'] else: assert not data assert not imagecaches[pluginname].urls @@ -254,18 +237,15 @@ def test_all(getconfiguredplugin): # pylint: disable=redefined-outer-name { 'artist': 'Nine Inch Nails', 'album': 'The Downward Spiral', - 'musicbrainzartistid': - ['b7ffd2af-418f-4be2-bdd1-22f8b48613da'], + 'musicbrainzartistid': ['b7ffd2af-418f-4be2-bdd1-22f8b48613da'], }, imagecache=imagecaches[pluginname]) if pluginname in ['discogs', 'theaudiodb']: assert data['artistlongbio'] assert data['artistwebsites'] if pluginname in ['fanarttv', 'theaudiodb']: - assert imagecaches[pluginname].urls['Nine Inch Nails'][ - 'artistbanner'] - assert imagecaches[pluginname].urls['Nine Inch Nails'][ - 'artistlogo'] + assert imagecaches[pluginname].urls['Nine Inch Nails']['artistbanner'] + assert imagecaches[pluginname].urls['Nine Inch Nails']['artistlogo'] assert data['artistfanarturls'] @@ -280,8 +260,7 @@ def test_theall(getconfiguredplugin): # pylint: disable=redefined-outer-name { 'artist': 'The Nine Inch Nails', 'album': 'The Downward Spiral', - 'musicbrainzartistid': - ['b7ffd2af-418f-4be2-bdd1-22f8b48613da'], + 'musicbrainzartistid': ['b7ffd2af-418f-4be2-bdd1-22f8b48613da'], }, imagecache=imagecaches[pluginname]) logging.debug(imagecaches['theaudiodb'].urls) @@ -289,13 +268,10 @@ def test_theall(getconfiguredplugin): # pylint: disable=redefined-outer-name assert data['artistlongbio'] assert data['artistwebsites'] if pluginname in ['fanarttv', 'theaudiodb']: - assert imagecaches[pluginname].urls['The Nine Inch Nails'][ - 'artistbanner'] - assert imagecaches[pluginname].urls['The Nine Inch Nails'][ - 'artistlogo'] + assert imagecaches[pluginname].urls['The Nine Inch Nails']['artistbanner'] + assert imagecaches[pluginname].urls['The Nine Inch Nails']['artistlogo'] assert data['artistfanarturls'] - assert imagecaches[pluginname].urls['The Nine Inch Nails'][ - 'artistthumb'] + assert imagecaches[pluginname].urls['The Nine Inch Nails']['artistthumb'] def test_notfound(getconfiguredplugin): # pylint: disable=redefined-outer-name diff --git a/tests/test_config.py b/tests/test_config.py index b54d56bf..f9eb67dd 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -28,9 +28,7 @@ def test_reset2(getroot): config.cparser.sync() assert config.cparser.value('fake/setting') del config - config = nowplaying.config.ConfigFile(bundledir=bundledir, - reset=True, - testmode=True) + config = nowplaying.config.ConfigFile(bundledir=bundledir, reset=True, testmode=True) assert not config.cparser.value('fake/setting') @@ -61,10 +59,8 @@ def test_get1(bootstrap): assert not config.notif assert config.txttemplate == str( pathlib.Path( - QStandardPaths.standardLocations( - QStandardPaths.DocumentsLocation)[0], - QCoreApplication.applicationName()).joinpath( - 'templates', 'basic-plain.txt')) + QStandardPaths.standardLocations(QStandardPaths.DocumentsLocation)[0], + QCoreApplication.applicationName()).joinpath('templates', 'basic-plain.txt')) config.cparser.setValue('settings/initialized', True) config.cparser.setValue('settings/loglevel', 'invalid1') diff --git a/tests/test_db.py b/tests/test_db.py index 854f9886..ae178f05 100755 --- a/tests/test_db.py +++ b/tests/test_db.py @@ -15,8 +15,7 @@ def getmetadb(bootstrap): ''' create a temporary directory ''' config = bootstrap # pylint: disable=unused-variable with tempfile.TemporaryDirectory() as newpath: - yield nowplaying.db.MetadataDB(databasefile=os.path.join( - newpath, 'test.db'), + yield nowplaying.db.MetadataDB(databasefile=os.path.join(newpath, 'test.db'), initialize=True) @@ -26,8 +25,7 @@ def config_and_getmetadb(bootstrap): config = bootstrap # pylint: disable=unused-variable with tempfile.TemporaryDirectory() as newpath: config.setlistdir = os.path.join(newpath, 'sl') - yield config, nowplaying.db.MetadataDB(databasefile=os.path.join( - newpath, 'test.db'), + yield config, nowplaying.db.MetadataDB(databasefile=os.path.join(newpath, 'test.db'), initialize=True) @@ -143,8 +141,7 @@ async def test_data_db2(getmetadb): # pylint: disable=redefined-outer-name 'coverimageraw': "Grr! I'm an image!", 'date': '1997', 'deck': 1, - 'filename': - "/Users/aw/Music/songs/LĪVE/Secret Samadhi/02 Lakini's Juice.mp3", + 'filename': "/Users/aw/Music/songs/LĪVE/Secret Samadhi/02 Lakini's Juice.mp3", 'genre': 'Rock', 'key': 'C#m', 'label': 'Radioactive Records', @@ -177,8 +174,7 @@ async def test_data_db2(getmetadb): # pylint: disable=redefined-outer-name 'discsubtitle': None, 'duration': None, 'duration_hhmmss': None, - 'filename': - "/Users/aw/Music/songs/LĪVE/Secret Samadhi/02 Lakini's Juice.mp3", + 'filename': "/Users/aw/Music/songs/LĪVE/Secret Samadhi/02 Lakini's Juice.mp3", 'fpcalcduration': None, 'fpcalcfingerprint': None, 'genre': 'Rock', @@ -238,10 +234,7 @@ async def test_data_previoustrack(getmetadb): # pylint: disable=redefined-outer metadb = getmetadb for counter in range(4): - await metadb.write_to_metadb(metadata={ - 'artist': f'a{counter}', - 'title': f't{counter}' - }) + await metadb.write_to_metadb(metadata={'artist': f'a{counter}', 'title': f't{counter}'}) readdata = metadb.read_last_meta() diff --git a/tests/test_imagecache.py b/tests/test_imagecache.py index 7206995e..26753cff 100755 --- a/tests/test_imagecache.py +++ b/tests/test_imagecache.py @@ -31,8 +31,7 @@ def get_imagecache(bootstrap): logging.debug(newpathdir) logpath = newpathdir.joinpath('debug.log') stopevent = multiprocessing.Event() - imagecache = nowplaying.imagecache.ImageCache(cachedir=newpathdir, - stopevent=stopevent) + imagecache = nowplaying.imagecache.ImageCache(cachedir=newpathdir, stopevent=stopevent) icprocess = multiprocessing.Process(target=imagecache.queue_process, name='ICProcess', args=( @@ -51,14 +50,8 @@ def test_imagecache(get_imagecache): # pylint: disable=redefined-outer-name ''' testing queue filling ''' config, imagecache = get_imagecache - imagecache.fill_queue(config=config, - artist='Gary Numan', - imagetype='fanart', - urllist=TEST_URLS) - imagecache.fill_queue(config=config, - artist='Gary Numan', - imagetype='fanart', - urllist=TEST_URLS) + imagecache.fill_queue(config=config, artist='Gary Numan', imagetype='fanart', urllist=TEST_URLS) + imagecache.fill_queue(config=config, artist='Gary Numan', imagetype='fanart', urllist=TEST_URLS) time.sleep(5) page = requests.get(TEST_URLS[2], timeout=10) @@ -72,17 +65,12 @@ def test_imagecache(get_imagecache): # pylint: disable=redefined-outer-name logging.debug('Found it at %s', cachekey) -@pytest.mark.xfail(sys.platform == "win32", - reason="Windows cannot close fast enough") +@pytest.mark.xfail(sys.platform == "win32", reason="Windows cannot close fast enough") def test_randomimage(get_imagecache): # pylint: disable=redefined-outer-name ''' get a 'random' image' ''' config, imagecache = get_imagecache # pylint: disable=unused-variable - imagedict = { - 'url': TEST_URLS[0], - 'artist': 'Gary Numan', - 'imagetype': 'fanart' - } + imagedict = {'url': TEST_URLS[0], 'artist': 'Gary Numan', 'imagetype': 'fanart'} imagecache.image_dl(imagedict) @@ -90,8 +78,7 @@ def test_randomimage(get_imagecache): # pylint: disable=redefined-outer-name assert data_find['artist'] == 'garynuman' assert data_find['imagetype'] == 'fanart' - data_random = imagecache.random_fetch(artist='Gary Numan', - imagetype='fanart') + data_random = imagecache.random_fetch(artist='Gary Numan', imagetype='fanart') assert data_random['artist'] == 'garynuman' assert data_random['cachekey'] assert data_random['url'] == TEST_URLS[0] @@ -99,8 +86,7 @@ def test_randomimage(get_imagecache): # pylint: disable=redefined-outer-name data_findkey = imagecache.find_cachekey(data_random['cachekey']) assert data_findkey - image = imagecache.random_image_fetch(artist='Gary Numan', - imagetype='fanart') + image = imagecache.random_image_fetch(artist='Gary Numan', imagetype='fanart') cachedimage = imagecache.cache[data_random['cachekey']] assert image == cachedimage @@ -116,10 +102,8 @@ def test_randomfailure(get_imagecache): # pylint: disable=redefined-outer-name assert imagecache.databasefile.exists() imagecache.databasefile.unlink() - image = imagecache.random_image_fetch(artist='Gary Numan', - imagetype='fanart') + image = imagecache.random_image_fetch(artist='Gary Numan', imagetype='fanart') assert not image - image = imagecache.random_image_fetch(artist='Gary Numan', - imagetype='fanart') + image = imagecache.random_image_fetch(artist='Gary Numan', imagetype='fanart') assert not image diff --git a/tests/test_m3u.py b/tests/test_m3u.py index 6c3d4535..e6f5a3d6 100755 --- a/tests/test_m3u.py +++ b/tests/test_m3u.py @@ -53,39 +53,23 @@ def write_m3u8(m3u, filename): def write_extvdj_remix(m3u): ''' create m3u file with VDJ ''' with open(m3u, 'w', encoding='utf-8') as m3ufn: - m3ufn.write( - '#EXTVDJ:1674884385' - ) - m3ufn.write( - 'j. periodBuddy [Remix]feat. De La Soul' - ) - m3ufn.write( - f', Jungle Brothers, Q-Tip & Queen Latifah{os.linesep}') + m3ufn.write('#EXTVDJ:1674884385') + m3ufn.write('j. periodBuddy [Remix]feat. De La Soul') + m3ufn.write(f', Jungle Brothers, Q-Tip & Queen Latifah{os.linesep}') m3ufn.write(f'netsearch://dz715352532{os.linesep}') def write_extvdj_m3u8(m3u): ''' create m3u file with VDJ ''' with open(m3u, 'w', encoding='utf-8') as m3ufn: - m3ufn.write( - '#EXTVDJ:1674884385' - ) - m3ufn.write( - 'j. periodBuddy [Remix]feat. De La Soul' - ) - m3ufn.write( - f', Jungle Brothers, Q-Tip & Queen Latifah{os.linesep}') + m3ufn.write('#EXTVDJ:1674884385') + m3ufn.write('j. periodBuddy [Remix]feat. De La Soul') + m3ufn.write(f', Jungle Brothers, Q-Tip & Queen Latifah{os.linesep}') m3ufn.write(f'netsearch://dz715352532{os.linesep}') - m3ufn.write( - '#EXTVDJ:1674884510' - ) - m3ufn.write( - f'Kid \'N PlayCan You Dig That{os.linesep}' - ) + m3ufn.write('#EXTVDJ:1674884510') + m3ufn.write(f'Kid \'N PlayCan You Dig That{os.linesep}') m3ufn.write(f'netsearch://dz85144450{os.linesep}') - m3ufn.write( - '#EXTVDJ:1674884707' - ) + m3ufn.write('#EXTVDJ:1674884707') m3ufn.write('Lords Of The Underground') m3ufn.write(f'Chief Rocka{os.linesep}') m3ufn.write(f'netsearch://dz3130706{os.linesep}') @@ -94,9 +78,7 @@ def write_extvdj_m3u8(m3u): def write_extvdj_ampersand(m3u): ''' create m3u file with VDJ ''' with open(m3u, 'w', encoding='utf-8') as m3ufn: - m3ufn.write( - '#EXTVDJ:1675701805' - ) + m3ufn.write('#EXTVDJ:1675701805') m3ufn.write('Nick Cave & The Bad Seeds') m3ufn.write(f'Hollywood{os.linesep}') m3ufn.write(f'netsearch://dz1873796677{os.linesep}') @@ -174,8 +156,7 @@ async def test_no2newm3u(m3u_bootstrap, getroot): # pylint: disable=redefined-o assert not metadata.get('title') assert not metadata.get('filename') - testmp3 = os.path.join(getroot, 'tests', 'audio', - '15_Ghosts_II_64kb_orig.mp3') + testmp3 = os.path.join(getroot, 'tests', 'audio', '15_Ghosts_II_64kb_orig.mp3') m3ufile = os.path.join(mym3udir, 'test.m3u') write_m3u(m3ufile, testmp3) await asyncio.sleep(1) @@ -200,15 +181,12 @@ async def test_no2newm3upolltest(m3u_bootstrap, getroot): # pylint: disable=red assert not metadata.get('artist') assert not metadata.get('title') assert not metadata.get('filename') - assert isinstance(plugin.observer, - watchdog.observers.polling.PollingObserver) + assert isinstance(plugin.observer, watchdog.observers.polling.PollingObserver) - testmp3 = os.path.join(getroot, 'tests', 'audio', - '15_Ghosts_II_64kb_orig.mp3') + testmp3 = os.path.join(getroot, 'tests', 'audio', '15_Ghosts_II_64kb_orig.mp3') m3ufile = os.path.join(mym3udir, 'test.m3u') write_m3u(m3ufile, testmp3) - await asyncio.sleep( - 10) # needs to be long enough that the poller finds the update! + await asyncio.sleep(10) # needs to be long enough that the poller finds the update! metadata = await plugin.getplayingtrack() assert not metadata.get('artist') assert not metadata.get('title') @@ -227,8 +205,7 @@ async def test_noencodingm3u8(m3u_bootstrap, getroot): # pylint: disable=redefi await asyncio.sleep(5) metadata = await plugin.getplayingtrack() - testmp3 = os.path.join(getroot, 'tests', 'audio', - '15_Ghosts_II_64kb_orig.mp3') + testmp3 = os.path.join(getroot, 'tests', 'audio', '15_Ghosts_II_64kb_orig.mp3') m3ufile = os.path.join(mym3udir, 'test.m3u') write_m3u8(m3ufile, testmp3) await asyncio.sleep(1) @@ -248,8 +225,7 @@ async def test_encodingm3u(m3u_bootstrap, getroot): # pylint: disable=redefined plugin = nowplaying.inputs.m3u.Plugin(config=config, m3udir=mym3udir) await plugin.start() await asyncio.sleep(5) - testmp3 = os.path.join(getroot, 'tests', 'audio', - '15_Ghosts_II_64kb_füllytâgged.mp3') + testmp3 = os.path.join(getroot, 'tests', 'audio', '15_Ghosts_II_64kb_füllytâgged.mp3') m3ufile = os.path.join(mym3udir, 'test.m3u') write_m3u(m3ufile, testmp3) await asyncio.sleep(1) @@ -296,8 +272,7 @@ async def test_vdjm3u_remix(m3u_bootstrap): # pylint: disable=redefined-outer-n metadata = await plugin.getplayingtrack() assert metadata.get('artist') == 'j. period' assert metadata.get( - 'title' - ) == 'Buddy [Remix] (feat. De La Soul, Jungle Brothers, Q-Tip & Queen Latifah)' + 'title') == 'Buddy [Remix] (feat. De La Soul, Jungle Brothers, Q-Tip & Queen Latifah)' assert not metadata.get('filename') await plugin.stop() await asyncio.sleep(5) @@ -356,8 +331,7 @@ async def test_no2newm3u8(m3u_bootstrap, getroot): # pylint: disable=redefined- assert not metadata.get('title') assert not metadata.get('filename') - testmp3 = os.path.join(getroot, 'tests', 'audio', - '15_Ghosts_II_64kb_füllytâgged.mp3') + testmp3 = os.path.join(getroot, 'tests', 'audio', '15_Ghosts_II_64kb_füllytâgged.mp3') m3ufile = os.path.join(mym3udir, 'test.m3u8') write_m3u8(m3ufile, testmp3) await asyncio.sleep(1) @@ -408,8 +382,7 @@ async def test_m3urelativesubst(m3u_bootstrap, getroot): # pylint: disable=rede if sys.platform == 'darwin': mym3udir = mym3udir.resolve() config.cparser.setValue('quirks/filesubst', True) - config.cparser.setValue('quirks/filesubstin', - str(mym3udir.joinpath('fakedir'))) + config.cparser.setValue('quirks/filesubstin', str(mym3udir.joinpath('fakedir'))) config.cparser.setValue('quirks/filesubstout', str(audiodir)) plugin = nowplaying.inputs.m3u.Plugin(config=config, m3udir=str(mym3udir)) await plugin.start() @@ -419,16 +392,14 @@ async def test_m3urelativesubst(m3u_bootstrap, getroot): # pylint: disable=rede assert not metadata.get('title') assert not metadata.get('filename') - testmp3 = str( - pathlib.Path('fakedir').joinpath('15_Ghosts_II_64kb_orig.mp3')) + testmp3 = str(pathlib.Path('fakedir').joinpath('15_Ghosts_II_64kb_orig.mp3')) mym3udir.joinpath('fakedir').mkdir(parents=True, exist_ok=True) mym3udir.joinpath(testmp3).touch() m3ufile = str(mym3udir.joinpath('test.m3u8')) write_m3u(m3ufile, testmp3) await asyncio.sleep(5) metadata = await plugin.getplayingtrack() - assert metadata['filename'] == str( - audiodir.joinpath('15_Ghosts_II_64kb_orig.mp3')) + assert metadata['filename'] == str(audiodir.joinpath('15_Ghosts_II_64kb_orig.mp3')) await plugin.stop() await asyncio.sleep(5) diff --git a/tests/test_metadata.py b/tests/test_metadata.py index a01a1974..bbbb070c 100755 --- a/tests/test_metadata.py +++ b/tests/test_metadata.py @@ -17,12 +17,10 @@ async def test_15ghosts2_mp3_orig(bootstrap, getroot): config = bootstrap config.cparser.setValue('acoustidmb/enabled', False) config.cparser.setValue('musicbrainz/enabled', False) - metadatain = { - 'filename': - os.path.join(getroot, 'tests', 'audio', '15_Ghosts_II_64kb_orig.mp3') - } - metadataout = await nowplaying.metadata.MetadataProcessors( - config=config).getmoremetadata(metadata=metadatain) + metadatain = {'filename': os.path.join(getroot, 'tests', 'audio', '15_Ghosts_II_64kb_orig.mp3')} + metadataout = await nowplaying.metadata.MetadataProcessors(config=config + ).getmoremetadata(metadata=metadatain + ) assert metadataout['album'] == 'Ghosts I - IV' assert metadataout['artist'] == 'Nine Inch Nails' assert metadataout['bitrate'] == 64000 @@ -38,12 +36,11 @@ async def test_15ghosts2_mp3_fullytagged(bootstrap, getroot): config.cparser.setValue('acoustidmb/enabled', False) config.cparser.setValue('musicbrainz/enabled', False) metadatain = { - 'filename': - os.path.join(getroot, 'tests', 'audio', - '15_Ghosts_II_64kb_füllytâgged.mp3') + 'filename': os.path.join(getroot, 'tests', 'audio', '15_Ghosts_II_64kb_füllytâgged.mp3') } - metadataout = await nowplaying.metadata.MetadataProcessors( - config=config).getmoremetadata(metadata=metadatain) + metadataout = await nowplaying.metadata.MetadataProcessors(config=config + ).getmoremetadata(metadata=metadatain + ) assert metadataout['acoustidid'] == '02d23182-de8b-493e-a6e1-e011bfdacbcf' assert metadataout['album'] == 'Ghosts I-IV' assert metadataout['albumartist'] == 'Nine Inch Nails' @@ -54,13 +51,9 @@ async def test_15ghosts2_mp3_fullytagged(bootstrap, getroot): assert metadataout['date'] == '2008' assert metadataout['isrc'] == ['USTC40852243'] assert metadataout['label'] == 'The Null Corporation' - assert metadataout[ - 'musicbrainzalbumid'] == '3af7ec8c-3bf4-4e6d-9bb3-1885d22b2b6a' - assert metadataout['musicbrainzartistid'] == [ - 'b7ffd2af-418f-4be2-bdd1-22f8b48613da' - ] - assert metadataout[ - 'musicbrainzrecordingid'] == '2d7f08e1-be1c-4b86-b725-6e675b7b6de0' + assert metadataout['musicbrainzalbumid'] == '3af7ec8c-3bf4-4e6d-9bb3-1885d22b2b6a' + assert metadataout['musicbrainzartistid'] == ['b7ffd2af-418f-4be2-bdd1-22f8b48613da'] + assert metadataout['musicbrainzrecordingid'] == '2d7f08e1-be1c-4b86-b725-6e675b7b6de0' assert metadataout['title'] == '15 Ghosts II' assert metadataout['duration'] == 110 @@ -72,11 +65,11 @@ async def test_15ghosts2_flac_orig(bootstrap, getroot): config.cparser.setValue('acoustidmb/enabled', False) config.cparser.setValue('musicbrainz/enabled', False) metadatain = { - 'filename': - os.path.join(getroot, 'tests', 'audio', '15_Ghosts_II_64kb_orig.flac') + 'filename': os.path.join(getroot, 'tests', 'audio', '15_Ghosts_II_64kb_orig.flac') } - metadataout = await nowplaying.metadata.MetadataProcessors( - config=config).getmoremetadata(metadata=metadatain) + metadataout = await nowplaying.metadata.MetadataProcessors(config=config + ).getmoremetadata(metadata=metadatain + ) assert metadataout['album'] == 'Ghosts I - IV' assert metadataout['artist'] == 'Nine Inch Nails' assert metadataout['track'] == '15' @@ -90,12 +83,10 @@ async def test_15ghosts2_m4a_orig(bootstrap, getroot): config = bootstrap config.cparser.setValue('acoustidmb/enabled', False) config.cparser.setValue('musicbrainz/enabled', False) - metadatain = { - 'filename': - os.path.join(getroot, 'tests', 'audio', '15_Ghosts_II_64kb_orig.m4a') - } - metadataout = await nowplaying.metadata.MetadataProcessors( - config=config).getmoremetadata(metadata=metadatain) + metadatain = {'filename': os.path.join(getroot, 'tests', 'audio', '15_Ghosts_II_64kb_orig.m4a')} + metadataout = await nowplaying.metadata.MetadataProcessors(config=config + ).getmoremetadata(metadata=metadatain + ) assert metadataout['album'] == 'Ghosts I - IV' assert metadataout['artist'] == 'Nine Inch Nails' assert metadataout['bitrate'] == 705600 @@ -111,11 +102,11 @@ async def test_15ghosts2_aiff_orig(bootstrap, getroot): config.cparser.setValue('acoustidmb/enabled', False) config.cparser.setValue('musicbrainz/enabled', False) metadatain = { - 'filename': - os.path.join(getroot, 'tests', 'audio', '15_Ghosts_II_64kb_orig.aiff') + 'filename': os.path.join(getroot, 'tests', 'audio', '15_Ghosts_II_64kb_orig.aiff') } - metadataout = await nowplaying.metadata.MetadataProcessors( - config=config).getmoremetadata(metadata=metadatain) + metadataout = await nowplaying.metadata.MetadataProcessors(config=config + ).getmoremetadata(metadata=metadatain + ) assert metadataout['album'] == 'Ghosts I - IV' assert metadataout['artist'] == 'Nine Inch Nails' assert metadataout['track'] == '15' @@ -130,12 +121,11 @@ async def test_15ghosts2_flac_fullytagged(bootstrap, getroot): config.cparser.setValue('acoustidmb/enabled', False) config.cparser.setValue('musicbrainz/enabled', False) metadatain = { - 'filename': - os.path.join(getroot, 'tests', 'audio', - '15_Ghosts_II_64kb_füllytâgged.flac') + 'filename': os.path.join(getroot, 'tests', 'audio', '15_Ghosts_II_64kb_füllytâgged.flac') } - metadataout = await nowplaying.metadata.MetadataProcessors( - config=config).getmoremetadata(metadata=metadatain) + metadataout = await nowplaying.metadata.MetadataProcessors(config=config + ).getmoremetadata(metadata=metadatain + ) assert metadataout['acoustidid'] == '02d23182-de8b-493e-a6e1-e011bfdacbcf' assert metadataout['album'] == 'Ghosts I-IV' @@ -147,13 +137,9 @@ async def test_15ghosts2_flac_fullytagged(bootstrap, getroot): assert metadataout['date'] == '2008-03-02' assert metadataout['isrc'] == ['USTC40852243'] assert metadataout['label'] == 'The Null Corporation' - assert metadataout[ - 'musicbrainzalbumid'] == '3af7ec8c-3bf4-4e6d-9bb3-1885d22b2b6a' - assert metadataout['musicbrainzartistid'] == [ - 'b7ffd2af-418f-4be2-bdd1-22f8b48613da' - ] - assert metadataout[ - 'musicbrainzrecordingid'] == '2d7f08e1-be1c-4b86-b725-6e675b7b6de0' + assert metadataout['musicbrainzalbumid'] == '3af7ec8c-3bf4-4e6d-9bb3-1885d22b2b6a' + assert metadataout['musicbrainzartistid'] == ['b7ffd2af-418f-4be2-bdd1-22f8b48613da'] + assert metadataout['musicbrainzrecordingid'] == '2d7f08e1-be1c-4b86-b725-6e675b7b6de0' assert metadataout['title'] == '15 Ghosts II' assert metadataout['duration'] == 113 @@ -165,12 +151,11 @@ async def test_15ghosts2_m4a_fullytagged(bootstrap, getroot): config.cparser.setValue('acoustidmb/enabled', False) config.cparser.setValue('musicbrainz/enabled', False) metadatain = { - 'filename': - os.path.join(getroot, 'tests', 'audio', - '15_Ghosts_II_64kb_füllytâgged.m4a') + 'filename': os.path.join(getroot, 'tests', 'audio', '15_Ghosts_II_64kb_füllytâgged.m4a') } - metadataout = await nowplaying.metadata.MetadataProcessors( - config=config).getmoremetadata(metadata=metadatain) + metadataout = await nowplaying.metadata.MetadataProcessors(config=config + ).getmoremetadata(metadata=metadatain + ) assert metadataout['acoustidid'] == '02d23182-de8b-493e-a6e1-e011bfdacbcf' assert metadataout['album'] == 'Ghosts I-IV' @@ -182,13 +167,9 @@ async def test_15ghosts2_m4a_fullytagged(bootstrap, getroot): assert metadataout['date'] == '2008-03-02' assert metadataout['isrc'] == ['USTC40852243'] assert metadataout['label'] == 'The Null Corporation' - assert metadataout[ - 'musicbrainzalbumid'] == '3af7ec8c-3bf4-4e6d-9bb3-1885d22b2b6a' - assert metadataout['musicbrainzartistid'] == [ - 'b7ffd2af-418f-4be2-bdd1-22f8b48613da' - ] - assert metadataout[ - 'musicbrainzrecordingid'] == '2d7f08e1-be1c-4b86-b725-6e675b7b6de0' + assert metadataout['musicbrainzalbumid'] == '3af7ec8c-3bf4-4e6d-9bb3-1885d22b2b6a' + assert metadataout['musicbrainzartistid'] == ['b7ffd2af-418f-4be2-bdd1-22f8b48613da'] + assert metadataout['musicbrainzrecordingid'] == '2d7f08e1-be1c-4b86-b725-6e675b7b6de0' assert metadataout['title'] == '15 Ghosts II' assert metadataout['duration'] == 113 @@ -200,12 +181,11 @@ async def test_15ghosts2_aiff_fullytagged(bootstrap, getroot): config.cparser.setValue('acoustidmb/enabled', False) config.cparser.setValue('musicbrainz/enabled', False) metadatain = { - 'filename': - os.path.join(getroot, 'tests', 'audio', - '15_Ghosts_II_64kb_füllytâgged.aiff') + 'filename': os.path.join(getroot, 'tests', 'audio', '15_Ghosts_II_64kb_füllytâgged.aiff') } - metadataout = await nowplaying.metadata.MetadataProcessors( - config=config).getmoremetadata(metadata=metadatain) + metadataout = await nowplaying.metadata.MetadataProcessors(config=config + ).getmoremetadata(metadata=metadatain + ) assert metadataout['album'] == 'Ghosts I-IV' assert metadataout['albumartist'] == 'Nine Inch Nails' @@ -251,8 +231,9 @@ async def test_artistshortio(bootstrap, getroot): ' songwriter, instrumentalist, and sole member of Nine Inch Nails for 28 years. This changed' \ ' in December 2016 when Atticus Ross officially became the second member of the band.' - metadataout = await nowplaying.metadata.MetadataProcessors( - config=config).getmoremetadata(metadata=metadatain) + metadataout = await nowplaying.metadata.MetadataProcessors(config=config + ).getmoremetadata(metadata=metadatain + ) logging.debug(metadataout['artistshortbio']) assert metadataout['artistshortbio'] == shortbio assert metadataout['album'] == 'Ghosts I - IV' @@ -271,8 +252,9 @@ async def test_stripre_cleandash(bootstrap): config.cparser.setValue('settings/stripextras', True) nowplaying.upgrade.upgrade_filters(config.cparser) metadatain = {'title': 'Test - Clean'} - metadataout = await nowplaying.metadata.MetadataProcessors( - config=config).getmoremetadata(metadata=metadatain) + metadataout = await nowplaying.metadata.MetadataProcessors(config=config + ).getmoremetadata(metadata=metadatain + ) assert metadataout['title'] == 'Test' @@ -285,8 +267,9 @@ async def test_stripre_nocleandash(bootstrap): config.cparser.setValue('settings/stripextras', False) nowplaying.upgrade.upgrade_filters(config.cparser) metadatain = {'title': 'Test - Clean'} - metadataout = await nowplaying.metadata.MetadataProcessors( - config=config).getmoremetadata(metadata=metadatain) + metadataout = await nowplaying.metadata.MetadataProcessors(config=config + ).getmoremetadata(metadata=metadatain + ) assert metadataout['title'] == 'Test - Clean' @@ -299,8 +282,9 @@ async def test_stripre_cleanparens(bootstrap): config.cparser.setValue('settings/stripextras', True) nowplaying.upgrade.upgrade_filters(config.cparser) metadatain = {'title': 'Test (Clean)'} - metadataout = await nowplaying.metadata.MetadataProcessors( - config=config).getmoremetadata(metadata=metadatain) + metadataout = await nowplaying.metadata.MetadataProcessors(config=config + ).getmoremetadata(metadata=metadatain + ) assert metadataout['title'] == 'Test' @@ -313,8 +297,9 @@ async def test_stripre_cleanextraparens(bootstrap): config.cparser.setValue('settings/stripextras', True) nowplaying.upgrade.upgrade_filters(config.cparser) metadatain = {'title': 'Test (Clean) (Single Mix)'} - metadataout = await nowplaying.metadata.MetadataProcessors( - config=config).getmoremetadata(metadata=metadatain) + metadataout = await nowplaying.metadata.MetadataProcessors(config=config + ).getmoremetadata(metadata=metadatain + ) assert metadataout['title'] == 'Test (Single Mix)' @@ -327,8 +312,9 @@ async def test_publisher_not_label(bootstrap): config.cparser.setValue('settings/stripextras', False) nowplaying.upgrade.upgrade_filters(config.cparser) metadatain = {'publisher': 'Cool Music Publishing'} - metadataout = await nowplaying.metadata.MetadataProcessors( - config=config).getmoremetadata(metadata=metadatain) + metadataout = await nowplaying.metadata.MetadataProcessors(config=config + ).getmoremetadata(metadata=metadatain + ) assert metadataout['label'] == 'Cool Music Publishing' assert not metadataout.get('publisher') @@ -341,8 +327,9 @@ async def test_year_not_date(bootstrap): config.cparser.setValue('musicbrainz/enabled', False) config.cparser.setValue('settings/stripextras', False) metadatain = {'year': '1999'} - metadataout = await nowplaying.metadata.MetadataProcessors( - config=config).getmoremetadata(metadata=metadatain) + metadataout = await nowplaying.metadata.MetadataProcessors(config=config + ).getmoremetadata(metadata=metadatain + ) assert metadataout['date'] == '1999' assert not metadataout.get('year') @@ -354,11 +341,10 @@ async def test_url_dedupe1(bootstrap): config.cparser.setValue('acoustidmb/enabled', False) config.cparser.setValue('musicbrainz/enabled', False) config.cparser.setValue('settings/stripextras', False) - metadatain = { - 'artistwebsites': ['http://example.com', 'http://example.com/'] - } - metadataout = await nowplaying.metadata.MetadataProcessors( - config=config).getmoremetadata(metadata=metadatain) + metadatain = {'artistwebsites': ['http://example.com', 'http://example.com/']} + metadataout = await nowplaying.metadata.MetadataProcessors(config=config + ).getmoremetadata(metadata=metadatain + ) assert metadataout['artistwebsites'] == ['http://example.com/'] @@ -369,11 +355,10 @@ async def test_url_dedupe2(bootstrap): config.cparser.setValue('acoustidmb/enabled', False) config.cparser.setValue('musicbrainz/enabled', False) config.cparser.setValue('settings/stripextras', False) - metadatain = { - 'artistwebsites': ['http://example.com', 'https://example.com/'] - } - metadataout = await nowplaying.metadata.MetadataProcessors( - config=config).getmoremetadata(metadata=metadatain) + metadatain = {'artistwebsites': ['http://example.com', 'https://example.com/']} + metadataout = await nowplaying.metadata.MetadataProcessors(config=config + ).getmoremetadata(metadata=metadatain + ) assert metadataout['artistwebsites'] == ['https://example.com/'] @@ -384,11 +369,10 @@ async def test_url_dedupe3(bootstrap): config.cparser.setValue('acoustidmb/enabled', False) config.cparser.setValue('musicbrainz/enabled', False) config.cparser.setValue('settings/stripextras', False) - metadatain = { - 'artistwebsites': ['https://example.com', 'http://example.com/'] - } - metadataout = await nowplaying.metadata.MetadataProcessors( - config=config).getmoremetadata(metadata=metadatain) + metadatain = {'artistwebsites': ['https://example.com', 'http://example.com/']} + metadataout = await nowplaying.metadata.MetadataProcessors(config=config + ).getmoremetadata(metadata=metadatain + ) assert metadataout['artistwebsites'] == ['https://example.com/'] @@ -400,13 +384,12 @@ async def test_url_dedupe4(bootstrap): config.cparser.setValue('musicbrainz/enabled', False) config.cparser.setValue('settings/stripextras', False) metadatain = { - 'artistwebsites': [ - 'https://example.com', 'https://whatsnowplaying.github.io', - 'http://example.com/' - ] + 'artistwebsites': + ['https://example.com', 'https://whatsnowplaying.github.io', 'http://example.com/'] } - metadataout = await nowplaying.metadata.MetadataProcessors( - config=config).getmoremetadata(metadata=metadatain) + metadataout = await nowplaying.metadata.MetadataProcessors(config=config + ).getmoremetadata(metadata=metadatain + ) assert metadataout['artistwebsites'] == [ 'https://example.com/', 'https://whatsnowplaying.github.io/' ] @@ -420,8 +403,9 @@ async def test_broken_duration(bootstrap): config.cparser.setValue('musicbrainz/enabled', False) config.cparser.setValue('settings/stripextras', False) metadatain = {'duration': '1 hour 10 minutes'} - metadataout = await nowplaying.metadata.MetadataProcessors( - config=config).getmoremetadata(metadata=metadatain) + metadataout = await nowplaying.metadata.MetadataProcessors(config=config + ).getmoremetadata(metadata=metadatain + ) assert not metadataout.get('duration') @@ -433,6 +417,7 @@ async def test_str_duration(bootstrap): config.cparser.setValue('musicbrainz/enabled', False) config.cparser.setValue('settings/stripextras', False) metadatain = {'duration': '1'} - metadataout = await nowplaying.metadata.MetadataProcessors( - config=config).getmoremetadata(metadata=metadatain) + metadataout = await nowplaying.metadata.MetadataProcessors(config=config + ).getmoremetadata(metadata=metadatain + ) assert metadataout['duration'] == 1 diff --git a/tests/test_musicbrainz.py b/tests/test_musicbrainz.py index e231fc51..6904c3d7 100755 --- a/tests/test_musicbrainz.py +++ b/tests/test_musicbrainz.py @@ -13,8 +13,7 @@ def getmusicbrainz(bootstrap): config = bootstrap config.cparser.setValue('acoustidmb/enabled', False) config.cparser.setValue('musicbrainz/enabled', True) - config.cparser.setValue('acoustidmb/emailaddress', - 'aw+wnptest@effectivemachines.com') + config.cparser.setValue('acoustidmb/emailaddress', 'aw+wnptest@effectivemachines.com') return nowplaying.musicbrainz.MusicBrainzHelper(config=config) @@ -26,11 +25,8 @@ def test_15ghosts2_orig(getmusicbrainz): # pylint: disable=redefined-outer-name assert metadata['artist'] == 'Nine Inch Nails' assert metadata['date'] == '2008-03-02' assert metadata['label'] == 'The Null Corporation' - assert metadata['musicbrainzartistid'] == [ - 'b7ffd2af-418f-4be2-bdd1-22f8b48613da' - ] - assert metadata[ - 'musicbrainzrecordingid'] == '2d7f08e1-be1c-4b86-b725-6e675b7b6de0' + assert metadata['musicbrainzartistid'] == ['b7ffd2af-418f-4be2-bdd1-22f8b48613da'] + assert metadata['musicbrainzrecordingid'] == '2d7f08e1-be1c-4b86-b725-6e675b7b6de0' assert metadata['title'] == '15 Ghosts II' @@ -42,11 +38,8 @@ def test_15ghosts2_fullytagged(getmusicbrainz): # pylint: disable=redefined-out assert metadata['artist'] == 'Nine Inch Nails' assert metadata['date'] == '2008-03-02' assert metadata['label'] == 'The Null Corporation' - assert metadata['musicbrainzartistid'] == [ - 'b7ffd2af-418f-4be2-bdd1-22f8b48613da' - ] - assert metadata[ - 'musicbrainzrecordingid'] == '2d7f08e1-be1c-4b86-b725-6e675b7b6de0' + assert metadata['musicbrainzartistid'] == ['b7ffd2af-418f-4be2-bdd1-22f8b48613da'] + assert metadata['musicbrainzrecordingid'] == '2d7f08e1-be1c-4b86-b725-6e675b7b6de0' assert metadata['title'] == '15 Ghosts II' @@ -57,9 +50,7 @@ def test_fallback1(getmusicbrainz): # pylint: disable=redefined-outer-name newdata = mbhelper.lastditcheffort(metadata) assert newdata['artist'] == 'Nine Inch Nails' assert newdata['title'] == '15 Ghosts II' - assert newdata['musicbrainzartistid'] == [ - 'b7ffd2af-418f-4be2-bdd1-22f8b48613da' - ] + assert newdata['musicbrainzartistid'] == ['b7ffd2af-418f-4be2-bdd1-22f8b48613da'] assert newdata['album'] == 'Ghosts I–IV' @@ -68,9 +59,7 @@ def test_fallback2(getmusicbrainz): # pylint: disable=redefined-outer-name mbhelper = getmusicbrainz metadata = {'artist': 'Danse Society', 'title': 'Somewhere'} newdata = mbhelper.lastditcheffort(metadata) - assert newdata['musicbrainzartistid'] == [ - '75ede374-68bb-4429-85fb-4b3b1421dbd1' - ] + assert newdata['musicbrainzartistid'] == ['75ede374-68bb-4429-85fb-4b3b1421dbd1'] assert newdata['album'] == 'Somewhere' @@ -86,9 +75,7 @@ def test_fallback3(getmusicbrainz): # pylint: disable=redefined-outer-name if newdata.get('coverimageraw'): del newdata['coverimageraw'] logging.debug(newdata) - assert newdata['musicbrainzartistid'] == [ - '070d193a-845c-479f-980e-bef15710653e' - ] + assert newdata['musicbrainzartistid'] == ['070d193a-845c-479f-980e-bef15710653e'] def test_fallback3a(getmusicbrainz): # pylint: disable=redefined-outer-name @@ -97,28 +84,20 @@ def test_fallback3a(getmusicbrainz): # pylint: disable=redefined-outer-name # # Now if the album is there, hopefully that helps... # - metadata = { - 'artist': 'Prince', - 'title': 'Computer Blue', - 'album': 'Purple Rain' - } + metadata = {'artist': 'Prince', 'title': 'Computer Blue', 'album': 'Purple Rain'} newdata = mbhelper.lastditcheffort(metadata) if newdata.get('coverimageraw'): del newdata['coverimageraw'] logging.debug(newdata) assert newdata['musicbrainzartistid'] == [ - '070d193a-845c-479f-980e-bef15710653e', - '4c8ead39-b9df-4c56-a27c-51bc049cfd48' + '070d193a-845c-479f-980e-bef15710653e', '4c8ead39-b9df-4c56-a27c-51bc049cfd48' ] def test_fallback4(getmusicbrainz): # pylint: disable=redefined-outer-name ''' automated integration test ''' mbhelper = getmusicbrainz - metadata = { - 'artist': 'Snap! vs. Martin Eyerer', - 'title': 'Green Grass Grows' - } + metadata = {'artist': 'Snap! vs. Martin Eyerer', 'title': 'Green Grass Grows'} newdata = mbhelper.lastditcheffort(metadata) # @@ -129,9 +108,7 @@ def test_fallback4(getmusicbrainz): # pylint: disable=redefined-outer-name if newdata.get('coverimageraw'): del newdata['coverimageraw'] logging.debug(newdata) - assert newdata['musicbrainzartistid'] == [ - 'cd23732d-ffd2-444e-8884-53475d7ac7d9' - ] + assert newdata['musicbrainzartistid'] == ['cd23732d-ffd2-444e-8884-53475d7ac7d9'] assert newdata['album'] == 'Welcome to Tomorrow' @@ -149,8 +126,7 @@ def test_fallback5(getmusicbrainz): # pylint: disable=redefined-outer-name # version. Could be worse? # assert newdata['musicbrainzartistid'] == [ - '733a2394-e003-43cb-88a6-02f3b57e345b', - 'db4624cf-0e44-481e-a9dc-2142b833ec2f' + '733a2394-e003-43cb-88a6-02f3b57e345b', 'db4624cf-0e44-481e-a9dc-2142b833ec2f' ] assert newdata['album'] == 'Close My Eyes' @@ -168,8 +144,7 @@ def test_fallback6(getmusicbrainz): # pylint: disable=redefined-outer-name # Not the best choice, but passable # assert newdata['musicbrainzartistid'] == [ - '8092b8b7-235e-4844-9f72-95a9d5a73dbf', - '709af0d0-dcb6-4858-b76d-05a13fc9a0a6' + '8092b8b7-235e-4844-9f72-95a9d5a73dbf', '709af0d0-dcb6-4858-b76d-05a13fc9a0a6' ] assert newdata['album'] == 'Solid State Logik 1' @@ -177,15 +152,10 @@ def test_fallback6(getmusicbrainz): # pylint: disable=redefined-outer-name def test_fallback7(getmusicbrainz): # pylint: disable=redefined-outer-name ''' automated integration test ''' mbhelper = getmusicbrainz - metadata = { - 'artist': 'Mareux', - 'title': 'The Perfect Girl (Live at Coachella 2023)' - } + metadata = {'artist': 'Mareux', 'title': 'The Perfect Girl (Live at Coachella 2023)'} newdata = mbhelper.lastditcheffort(metadata) # # Not the best choice, but passable # - assert newdata['musicbrainzartistid'] == [ - '09095919-c549-4f33-9555-70df9dd941e1' - ] + assert newdata['musicbrainzartistid'] == ['09095919-c549-4f33-9555-70df9dd941e1'] assert newdata['album'] == 'The Perfect Girl' diff --git a/tests/test_serato.py b/tests/test_serato.py index a58dbe9f..700ec8da 100755 --- a/tests/test_serato.py +++ b/tests/test_serato.py @@ -53,12 +53,10 @@ async def getseratoplugin(serato_bootstrap, getroot, request): # pylint: disabl else: datadir = mark.kwargs['datadir'] config.cparser.setValue('serato/local', True) - config.cparser.setValue('serato/libpath', - os.path.join(getroot, 'tests', datadir)) + config.cparser.setValue('serato/libpath', os.path.join(getroot, 'tests', datadir)) if 'mixmode' in mark.kwargs: config.cparser.setValue('serato/mixmode', mark.kwargs['mixmode']) - touchdir(os.path.join(getroot, 'tests', datadir, 'History', - 'Sessions')) + touchdir(os.path.join(getroot, 'tests', datadir, 'History', 'Sessions')) config.cparser.sync() plugin = nowplaying.inputs.serato.Plugin(config=config) await plugin.start(testmode=True) @@ -80,14 +78,11 @@ def results(expected, metadata): async def test_serato_remote2(getseratoplugin, getroot, httpserver): # pylint: disable=redefined-outer-name ''' test serato remote ''' plugin = getseratoplugin - with open(os.path.join(getroot, 'tests', 'seratolive', - '2021_08_25_pong.html'), + with open(os.path.join(getroot, 'tests', 'seratolive', '2021_08_25_pong.html'), encoding='utf8') as inputfh: content = inputfh.readlines() - httpserver.expect_request('/index.html').respond_with_data( - ''.join(content)) - plugin.config.cparser.setValue('serato/url', - httpserver.url_for('/index.html')) + httpserver.expect_request('/index.html').respond_with_data(''.join(content)) + plugin.config.cparser.setValue('serato/url', httpserver.url_for('/index.html')) plugin.config.cparser.sync() metadata = await plugin.getplayingtrack() @@ -108,8 +103,7 @@ async def test_serato24_mac_oldest(getseratoplugin): # pylint: disable=redefine 'bpm': 109, 'date': '1991', 'deck': 2, - 'filename': - '/Users/aw/Music/songs/LĪVE/Mental Jewelry/08 Take My Anthem.mp3', + 'filename': '/Users/aw/Music/songs/LĪVE/Mental Jewelry/08 Take My Anthem.mp3', 'genre': 'Rock', 'key': 'G#m', 'label': 'Radioactive Records', @@ -130,8 +124,7 @@ async def test_serato24_mac_newest(getseratoplugin): # pylint: disable=redefine 'bpm': 91, 'date': '1997', 'deck': 1, - 'filename': - "/Users/aw/Music/songs/LĪVE/Secret Samadhi/02 Lakini's Juice.mp3", + 'filename': "/Users/aw/Music/songs/LĪVE/Secret Samadhi/02 Lakini's Juice.mp3", 'genre': 'Rock', 'key': 'C#m', 'label': 'Radioactive Records', diff --git a/tests/test_templatehandler.py b/tests/test_templatehandler.py index a92d2eba..e4d5ab59 100755 --- a/tests/test_templatehandler.py +++ b/tests/test_templatehandler.py @@ -16,8 +16,7 @@ def gettemplatehandler(getroot, bootstrap, request): config = bootstrap # pylint: disable=unused-variable mark = request.node.get_closest_marker("templatesettings") if mark and 'template' in mark.kwargs: - template = os.path.join(getroot, 'tests', 'templates', - mark.kwargs['template']) + template = os.path.join(getroot, 'tests', 'templates', mark.kwargs['template']) else: template = None return nowplaying.utils.TemplateHandler(filename=template) diff --git a/tests/test_trackpoll.py b/tests/test_trackpoll.py index 8fcfb621..c18cfa4b 100644 --- a/tests/test_trackpoll.py +++ b/tests/test_trackpoll.py @@ -32,9 +32,7 @@ async def trackpollbootstrap(bootstrap, getroot, tmp_path): # pylint: disable=r logging.debug('output = %s', txtfile) config.cparser.sync() trackpoll = nowplaying.processes.trackpoll.TrackPoll( # pylint: disable=unused-variable - stopevent=stopevent, - config=config, - testmode=True) + stopevent=stopevent, config=config, testmode=True) yield config stopevent.set() await asyncio.sleep(2) @@ -82,11 +80,7 @@ async def test_trackpoll_basic(trackpollbootstrap): # pylint: disable=redefined text = filein.readlines() assert text[0].strip() == 'NIN' - await write_json_metadata(config=config, - metadata={ - 'artist': 'NIN', - 'title': 'Ghosts' - }) + await write_json_metadata(config=config, metadata={'artist': 'NIN', 'title': 'Ghosts'}) with open(txtoutput, encoding='utf-8') as filein: text = filein.readlines() assert text[0].strip() == 'NIN' @@ -102,10 +96,7 @@ async def test_trackpoll_metadata(trackpollbootstrap, getroot): # pylint: disab config.cparser.setValue('textoutput/txttemplate', str(template)) config.cparser.setValue('control/paused', False) config.cparser.sync() - metadata = { - 'filename': - str(getroot.joinpath('tests', 'audio', '15_Ghosts_II_64kb_orig.mp3')) - } + metadata = {'filename': str(getroot.joinpath('tests', 'audio', '15_Ghosts_II_64kb_orig.mp3'))} txtoutput = config.cparser.value('textoutput/file') await write_json_metadata(config=config, metadata=metadata) @@ -146,8 +137,7 @@ async def test_trackpoll_titleisfile(trackpollbootstrap, getroot): # pylint: di config.cparser.setValue('textoutput/txttemplate', str(template)) config.cparser.setValue('control/paused', False) config.cparser.sync() - title = str( - getroot.joinpath('tests', 'audio', '15_Ghosts_II_64kb_orig.mp3')) + title = str(getroot.joinpath('tests', 'audio', '15_Ghosts_II_64kb_orig.mp3')) await write_json_metadata(config=config, metadata={'title': title}) with open(txtoutput, encoding='utf-8') as filein: text = filein.readlines() @@ -189,11 +179,7 @@ async def test_trackpoll_badfile(trackpollbootstrap, getroot): # pylint: disabl config.cparser.setValue('control/paused', False) config.cparser.sync() - metadata = { - 'title': 'title', - 'artist': 'artist', - 'filename': 'completejunk' - } + metadata = {'title': 'title', 'artist': 'artist', 'filename': 'completejunk'} await write_json_metadata(config=config, metadata=metadata) with open(txtoutput, encoding='utf-8') as filein: text = filein.readlines() diff --git a/tests/test_trackrequests.py b/tests/test_trackrequests.py index c8a58c48..5c1e04eb 100644 --- a/tests/test_trackrequests.py +++ b/tests/test_trackrequests.py @@ -18,14 +18,11 @@ async def trackrequestbootstrap(bootstrap, getroot): # pylint: disable=redefine stopevent = asyncio.Event() config = bootstrap config.cparser.setValue('settings/input', 'jsonreader') - playlistpath = pathlib.Path(getroot).joinpath('tests', 'playlists', 'json', - 'test.json') + playlistpath = pathlib.Path(getroot).joinpath('tests', 'playlists', 'json', 'test.json') config.pluginobjs['inputs']['nowplaying.inputs.jsonreader'].load_playlists( getroot, playlistpath) config.cparser.sync() - yield nowplaying.trackrequests.Requests(stopevent=stopevent, - config=config, - testmode=True) + yield nowplaying.trackrequests.Requests(stopevent=stopevent, config=config, testmode=True) stopevent.set() await asyncio.sleep(2) @@ -36,8 +33,7 @@ async def test_trackrequest_artisttitlenoquote(trackrequestbootstrap): # pylint trackrequest = trackrequestbootstrap - data = await trackrequest.user_track_request({'displayname': 'test'}, - 'user', 'artist - title') + data = await trackrequest.user_track_request({'displayname': 'test'}, 'user', 'artist - title') assert data['artist'] == 'artist' assert data['title'] == 'title' assert data['requester'] == 'user' @@ -50,8 +46,8 @@ async def test_trackrequest_artisttitlenoquotespaces(trackrequestbootstrap): # trackrequest = trackrequestbootstrap - data = await trackrequest.user_track_request( - {'displayname': 'test'}, 'user', ' artist - title ') + data = await trackrequest.user_track_request({'displayname': 'test'}, 'user', + ' artist - title ') assert data['artist'] == 'artist' assert data['title'] == 'title' assert data['requester'] == 'user' @@ -79,8 +75,8 @@ async def test_trackrequest_artisttitlequotes(trackrequestbootstrap): # pylint: trackrequest = trackrequestbootstrap - data = await trackrequest.user_track_request({'displayname': 'test'}, - 'user', 'artist - "title"') + data = await trackrequest.user_track_request({'displayname': 'test'}, 'user', + 'artist - "title"') assert data['artist'] == 'artist' assert data['title'] == 'title' assert data['requester'] == 'user' @@ -93,8 +89,8 @@ async def test_trackrequest_artisttitlequotesspaces(trackrequestbootstrap): # p trackrequest = trackrequestbootstrap - data = await trackrequest.user_track_request( - {'displayname': 'test'}, 'user', ' artist - "title" ') + data = await trackrequest.user_track_request({'displayname': 'test'}, 'user', + ' artist - "title" ') assert data['artist'] == 'artist' assert data['title'] == 'title' assert data['requester'] == 'user' @@ -107,8 +103,8 @@ async def test_trackrequest_titlequotesartist(trackrequestbootstrap): # pylint: trackrequest = trackrequestbootstrap - data = await trackrequest.user_track_request({'displayname': 'test'}, - 'user', '"title" - artist') + data = await trackrequest.user_track_request({'displayname': 'test'}, 'user', + '"title" - artist') assert data['artist'] == 'artist' assert data['title'] == 'title' assert data['requester'] == 'user' @@ -121,8 +117,8 @@ async def test_trackrequest_titlequotesbyartist(trackrequestbootstrap): # pylin trackrequest = trackrequestbootstrap - data = await trackrequest.user_track_request({'displayname': 'test'}, - 'user', '"title" by artist') + data = await trackrequest.user_track_request({'displayname': 'test'}, 'user', + '"title" by artist') assert data['artist'] == 'artist' assert data['title'] == 'title' assert data['requester'] == 'user' @@ -135,9 +131,8 @@ async def test_trackrequest_quotedweirdal(trackrequestbootstrap): # pylint: dis trackrequest = trackrequestbootstrap - data = await trackrequest.user_track_request( - {'displayname': 'test'}, 'user', - '"Weird Al" Yankovic - This Is The Life.') + data = await trackrequest.user_track_request({'displayname': 'test'}, 'user', + '"Weird Al" Yankovic - This Is The Life.') assert data['artist'] == '"Weird Al" Yankovic' assert data['title'] == 'This Is The Life.' assert data['requester'] == 'user' @@ -150,9 +145,8 @@ async def test_trackrequest_quotedchampagne(trackrequestbootstrap): # pylint: d trackrequest = trackrequestbootstrap - data = await trackrequest.user_track_request( - {'displayname': 'test'}, 'user', - 'Evelyn "Champagne" King - "I\'m In Love"') + data = await trackrequest.user_track_request({'displayname': 'test'}, 'user', + 'Evelyn "Champagne" King - "I\'m In Love"') assert data['artist'] == 'Evelyn "Champagne" King' assert data['title'] == 'I\'m In Love' assert data['requester'] == 'user' @@ -165,8 +159,8 @@ async def test_trackrequest_xtcfornigel(trackrequestbootstrap): # pylint: disab trackrequest = trackrequestbootstrap - data = await trackrequest.user_track_request( - {'displayname': 'test'}, 'user', 'xtc - making plans for nigel') + data = await trackrequest.user_track_request({'displayname': 'test'}, 'user', + 'xtc - making plans for nigel') assert data['artist'] == 'xtc' assert data['title'] == 'making plans for nigel' assert data['requester'] == 'user' @@ -179,8 +173,8 @@ async def test_trackrequest_xtcforatnigel(trackrequestbootstrap): # pylint: dis trackrequest = trackrequestbootstrap - data = await trackrequest.user_track_request( - {'displayname': 'test'}, 'user', 'xtc - making plans for @nigel') + data = await trackrequest.user_track_request({'displayname': 'test'}, 'user', + 'xtc - making plans for @nigel') assert data['artist'] == 'xtc' assert data['title'] == 'making plans' assert data['requester'] == 'user' @@ -193,8 +187,7 @@ async def test_trackrequest_nospace(trackrequestbootstrap): # pylint: disable=r trackrequest = trackrequestbootstrap - data = await trackrequest.user_track_request({'displayname': 'test'}, - 'user', 'artist-title') + data = await trackrequest.user_track_request({'displayname': 'test'}, 'user', 'artist-title') assert data['artist'] == 'artist' assert data['title'] == 'title' assert data['requester'] == 'user' @@ -211,18 +204,14 @@ async def test_trackrequest_rouletterequest(trackrequestbootstrap): # pylint: d trackrequest.config.cparser.setValue('settings/requests', True) trackrequest.config.cparser.sync() - data = await trackrequest.user_roulette_request( - { - 'displayname': 'test', - 'playlist': 'testlist' - }, 'user', 'artist-title') + data = await trackrequest.user_roulette_request({ + 'displayname': 'test', + 'playlist': 'testlist' + }, 'user', 'artist-title') assert data['requester'] == 'user' assert data['requestdisplayname'] == 'test' - data = await trackrequest.get_request({ - 'artist': 'Nine Inch Nails', - 'title': '15 Ghosts II' - }) + data = await trackrequest.get_request({'artist': 'Nine Inch Nails', 'title': '15 Ghosts II'}) assert data['requester'] == 'user' assert data['requestdisplayname'] == 'test' assert data['requesterimageraw'] @@ -238,18 +227,14 @@ async def test_trackrequest_rouletterequest_normalized(trackrequestbootstrap): trackrequest.config.cparser.setValue('settings/requests', True) trackrequest.config.cparser.sync() - data = await trackrequest.user_roulette_request( - { - 'displayname': 'test', - 'playlist': 'testlist' - }, 'user', 'artist-title') + data = await trackrequest.user_roulette_request({ + 'displayname': 'test', + 'playlist': 'testlist' + }, 'user', 'artist-title') assert data['requester'] == 'user' assert data['requestdisplayname'] == 'test' - data = await trackrequest.get_request({ - 'artist': 'Níne Ínch Näíls', - 'title': '15 Ghosts II' - }) + data = await trackrequest.get_request({'artist': 'Níne Ínch Näíls', 'title': '15 Ghosts II'}) assert data['requester'] == 'user' assert data['requestdisplayname'] == 'test' assert data['requesterimageraw'] @@ -266,16 +251,12 @@ async def test_trackrequest_getrequest_artist(trackrequestbootstrap): # pylint: trackrequest.config.cparser.sync() trackrequest = trackrequestbootstrap - data = await trackrequest.user_track_request({'displayname': 'test'}, - 'user', 'Nine Inch Nails') + data = await trackrequest.user_track_request({'displayname': 'test'}, 'user', 'Nine Inch Nails') logging.debug(data) assert data['requestartist'] == 'Nine Inch Nails' assert not data['requesttitle'] - data = await trackrequest.get_request({ - 'artist': 'Níne Ínch Näíls', - 'title': '15 Ghosts II' - }) + data = await trackrequest.get_request({'artist': 'Níne Ínch Näíls', 'title': '15 Ghosts II'}) assert data['requester'] == 'user' assert data['requestdisplayname'] == 'test' assert data['requesterimageraw'] @@ -292,16 +273,12 @@ async def test_trackrequest_getrequest_title(trackrequestbootstrap): # pylint: trackrequest.config.cparser.sync() trackrequest = trackrequestbootstrap - data = await trackrequest.user_track_request({'displayname': 'test'}, - 'user', '"15 Ghosts II"') + data = await trackrequest.user_track_request({'displayname': 'test'}, 'user', '"15 Ghosts II"') logging.debug(data) assert not data['requestartist'] assert data['requesttitle'] == '15 Ghosts II' - data = await trackrequest.get_request({ - 'artist': 'Níne Ínch Näíls', - 'title': '15 Ghosts II' - }) + data = await trackrequest.get_request({'artist': 'Níne Ínch Näíls', 'title': '15 Ghosts II'}) assert data['requester'] == 'user' assert data['requestdisplayname'] == 'test' assert data['requesterimageraw'] @@ -313,8 +290,7 @@ async def test_twofer(bootstrap, getroot): # pylint: disable=redefined-outer-na stopevent = asyncio.Event() config = bootstrap config.cparser.setValue('settings/input', 'json') - playlistpath = pathlib.Path(getroot).joinpath('tests', 'playlists', 'json', - 'test.json') + playlistpath = pathlib.Path(getroot).joinpath('tests', 'playlists', 'json', 'test.json') config.pluginobjs['inputs']['nowplaying.inputs.jsonreader'].load_playlists( getroot, playlistpath) config.cparser.sync() diff --git a/tests/test_upgradetemplates.py b/tests/test_upgradetemplates.py index 2fd4bd85..89e0fac4 100755 --- a/tests/test_upgradetemplates.py +++ b/tests/test_upgradetemplates.py @@ -21,8 +21,7 @@ def upgrade_bootstrap(getroot): bundledir = os.path.join(getroot, 'nowplaying') logging.basicConfig(level=logging.DEBUG) nowplaying.bootstrap.set_qt_names(appname='testsuite') - config = nowplaying.config.ConfigFile(bundledir=bundledir, - testmode=True) + config = nowplaying.config.ConfigFile(bundledir=bundledir, testmode=True) config.cparser.sync() old_cwd = os.getcwd() os.chdir(newpath) @@ -107,9 +106,8 @@ def test_upgrade_old(upgrade_bootstrap, getroot): # pylint: disable=redefined-o srcdir = os.path.join(bundledir, 'templates') destdir = os.path.join(testpath, 'testsuite', 'templates') pathlib.Path(destdir).mkdir(parents=True, exist_ok=True) - shutil.copyfile( - os.path.join(getroot, 'tests', 'templates', 'songquotes.txt'), - os.path.join(destdir, 'songquotes.new')) + shutil.copyfile(os.path.join(getroot, 'tests', 'templates', 'songquotes.txt'), + os.path.join(destdir, 'songquotes.new')) touchfile = os.path.join(destdir, 'songquotes.txt') pathlib.Path(touchfile).touch() nowplaying.upgrade.UpgradeTemplates(bundledir=bundledir, testdir=testpath) diff --git a/tests/test_upgradeutils.py b/tests/test_upgradeutils.py index 0328924d..4dd75532 100644 --- a/tests/test_upgradeutils.py +++ b/tests/test_upgradeutils.py @@ -12,8 +12,7 @@ @pytest.fixture def getreleasedata(getroot): ''' automated integration test ''' - releasedata = pathlib.Path(getroot).joinpath('tests', 'upgrade', - 'releasedata.json') + releasedata = pathlib.Path(getroot).joinpath('tests', 'upgrade', 'releasedata.json') with open(releasedata, 'r', encoding='utf-8') as fhin: data = json.load(fhin) return data diff --git a/tests/test_utils.py b/tests/test_utils.py index 025b3c3a..2da739a1 100755 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -37,8 +37,7 @@ def test_songsubst2backward(bootstrap): config = bootstrap config.cparser.setValue('quirks/filesubst', True) config.cparser.setValue('quirks/slashmode', 'toforward') - location = nowplaying.utils.songpathsubst(config, - '\\songs\\myband\\mysong') + location = nowplaying.utils.songpathsubst(config, '\\songs\\myband\\mysong') assert location == '/songs/myband/mysong' diff --git a/tests/test_virtualdj.py b/tests/test_virtualdj.py index e7a3cd14..dfa2a34c 100755 --- a/tests/test_virtualdj.py +++ b/tests/test_virtualdj.py @@ -53,39 +53,26 @@ def write_virtualdj8(virtualdj, filename): def write_extvdj_remix(virtualdj): ''' create virtualdj file with VDJ ''' with open(virtualdj, 'w', encoding='utf-8') as virtualdjfn: + virtualdjfn.write('#EXTVDJ:1674884385') virtualdjfn.write( - '#EXTVDJ:1674884385' - ) - virtualdjfn.write( - 'j. periodBuddy [Remix]feat. De La Soul' - ) - virtualdjfn.write( - f', Jungle Brothers, Q-Tip & Queen Latifah{os.linesep}') + 'j. periodBuddy [Remix]feat. De La Soul') + virtualdjfn.write(f', Jungle Brothers, Q-Tip & Queen Latifah{os.linesep}') virtualdjfn.write(f'netsearch://dz715352532{os.linesep}') def write_extvdj_virtualdj8(virtualdj): ''' create virtualdj file with VDJ ''' with open(virtualdj, 'w', encoding='utf-8') as virtualdjfn: + virtualdjfn.write('#EXTVDJ:1674884385') virtualdjfn.write( - '#EXTVDJ:1674884385' - ) - virtualdjfn.write( - 'j. periodBuddy [Remix]feat. De La Soul' - ) - virtualdjfn.write( - f', Jungle Brothers, Q-Tip & Queen Latifah{os.linesep}') + 'j. periodBuddy [Remix]feat. De La Soul') + virtualdjfn.write(f', Jungle Brothers, Q-Tip & Queen Latifah{os.linesep}') virtualdjfn.write(f'netsearch://dz715352532{os.linesep}') + virtualdjfn.write('#EXTVDJ:1674884510') virtualdjfn.write( - '#EXTVDJ:1674884510' - ) - virtualdjfn.write( - f'Kid \'N PlayCan You Dig That{os.linesep}' - ) + f'Kid \'N PlayCan You Dig That{os.linesep}') virtualdjfn.write(f'netsearch://dz85144450{os.linesep}') - virtualdjfn.write( - '#EXTVDJ:1674884707' - ) + virtualdjfn.write('#EXTVDJ:1674884707') virtualdjfn.write('Lords Of The Underground') virtualdjfn.write(f'Chief Rocka{os.linesep}') virtualdjfn.write(f'netsearch://dz3130706{os.linesep}') @@ -94,9 +81,7 @@ def write_extvdj_virtualdj8(virtualdj): def write_extvdj_ampersand(virtualdj): ''' create virtualdj file with VDJ ''' with open(virtualdj, 'w', encoding='utf-8') as virtualdjfn: - virtualdjfn.write( - '#EXTVDJ:1675701805' - ) + virtualdjfn.write('#EXTVDJ:1675701805') virtualdjfn.write('Nick Cave & The Bad Seeds') virtualdjfn.write(f'Hollywood{os.linesep}') virtualdjfn.write(f'netsearch://dz1873796677{os.linesep}') @@ -165,8 +150,7 @@ async def test_no2newvirtualdj(virtualdj_bootstrap, getroot): # pylint: disable ''' automated integration test ''' config = virtualdj_bootstrap myvirtualdjdir = config.cparser.value('virtualdj/history') - plugin = nowplaying.inputs.virtualdj.Plugin(config=config, - m3udir=myvirtualdjdir) + plugin = nowplaying.inputs.virtualdj.Plugin(config=config, m3udir=myvirtualdjdir) metadata = await plugin.getplayingtrack() await plugin.start() await asyncio.sleep(5) @@ -175,8 +159,7 @@ async def test_no2newvirtualdj(virtualdj_bootstrap, getroot): # pylint: disable assert not metadata.get('title') assert not metadata.get('filename') - testmp3 = os.path.join(getroot, 'tests', 'audio', - '15_Ghosts_II_64kb_orig.mp3') + testmp3 = os.path.join(getroot, 'tests', 'audio', '15_Ghosts_II_64kb_orig.mp3') virtualdjfile = os.path.join(myvirtualdjdir, 'test.m3u') write_virtualdj(virtualdjfile, testmp3) await asyncio.sleep(1) @@ -194,23 +177,19 @@ async def test_no2newvirtualdjpolltest(virtualdj_bootstrap, getroot): # pylint: config = virtualdj_bootstrap myvirtualdjdir = config.cparser.value('virtualdj/history') config.cparser.setValue('quirks/pollingobserver', True) - plugin = nowplaying.inputs.virtualdj.Plugin(config=config, - m3udir=myvirtualdjdir) + plugin = nowplaying.inputs.virtualdj.Plugin(config=config, m3udir=myvirtualdjdir) metadata = await plugin.getplayingtrack() await plugin.start() await asyncio.sleep(5) assert not metadata.get('artist') assert not metadata.get('title') assert not metadata.get('filename') - assert isinstance(plugin.observer, - watchdog.observers.polling.PollingObserver) + assert isinstance(plugin.observer, watchdog.observers.polling.PollingObserver) - testmp3 = os.path.join(getroot, 'tests', 'audio', - '15_Ghosts_II_64kb_orig.mp3') + testmp3 = os.path.join(getroot, 'tests', 'audio', '15_Ghosts_II_64kb_orig.mp3') virtualdjfile = os.path.join(myvirtualdjdir, 'test.m3u') write_virtualdj(virtualdjfile, testmp3) - await asyncio.sleep( - 10) # needs to be long enough that the poller finds the update! + await asyncio.sleep(10) # needs to be long enough that the poller finds the update! metadata = await plugin.getplayingtrack() assert not metadata.get('artist') assert not metadata.get('title') @@ -224,14 +203,12 @@ async def test_noencodingvirtualdj8(virtualdj_bootstrap, getroot): # pylint: di ''' automated integration test ''' config = virtualdj_bootstrap myvirtualdjdir = config.cparser.value('virtualdj/history') - plugin = nowplaying.inputs.virtualdj.Plugin(config=config, - m3udir=myvirtualdjdir) + plugin = nowplaying.inputs.virtualdj.Plugin(config=config, m3udir=myvirtualdjdir) await plugin.start() await asyncio.sleep(5) metadata = await plugin.getplayingtrack() - testmp3 = os.path.join(getroot, 'tests', 'audio', - '15_Ghosts_II_64kb_orig.mp3') + testmp3 = os.path.join(getroot, 'tests', 'audio', '15_Ghosts_II_64kb_orig.mp3') virtualdjfile = os.path.join(myvirtualdjdir, 'test.m3u') write_virtualdj8(virtualdjfile, testmp3) await asyncio.sleep(1) @@ -248,12 +225,10 @@ async def test_encodingvirtualdj(virtualdj_bootstrap, getroot): # pylint: disab ''' automated integration test ''' config = virtualdj_bootstrap myvirtualdjdir = config.cparser.value('virtualdj/history') - plugin = nowplaying.inputs.virtualdj.Plugin(config=config, - m3udir=myvirtualdjdir) + plugin = nowplaying.inputs.virtualdj.Plugin(config=config, m3udir=myvirtualdjdir) await plugin.start() await asyncio.sleep(5) - testmp3 = os.path.join(getroot, 'tests', 'audio', - '15_Ghosts_II_64kb_füllytâgged.mp3') + testmp3 = os.path.join(getroot, 'tests', 'audio', '15_Ghosts_II_64kb_füllytâgged.mp3') virtualdjfile = os.path.join(myvirtualdjdir, 'test.m3u') write_virtualdj(virtualdjfile, testmp3) await asyncio.sleep(1) @@ -270,8 +245,7 @@ async def test_vdjvirtualdj_normal(virtualdj_bootstrap): # pylint: disable=rede ''' automated integration test ''' config = virtualdj_bootstrap myvirtualdjdir = config.cparser.value('virtualdj/history') - plugin = nowplaying.inputs.virtualdj.Plugin(config=config, - m3udir=myvirtualdjdir) + plugin = nowplaying.inputs.virtualdj.Plugin(config=config, m3udir=myvirtualdjdir) await plugin.start() await asyncio.sleep(5) virtualdjfile = os.path.join(myvirtualdjdir, 'test.m3u') @@ -292,8 +266,7 @@ async def test_vdjvirtualdj_remix(virtualdj_bootstrap): # pylint: disable=redef myvirtualdjdir = config.cparser.value('virtualdj/history') config.cparser.setValue('virtualdj/useremix', True) config.cparser.sync() - plugin = nowplaying.inputs.virtualdj.Plugin(config=config, - m3udir=myvirtualdjdir) + plugin = nowplaying.inputs.virtualdj.Plugin(config=config, m3udir=myvirtualdjdir) await plugin.start() await asyncio.sleep(5) virtualdjfile = os.path.join(myvirtualdjdir, 'test.m3u') @@ -302,8 +275,7 @@ async def test_vdjvirtualdj_remix(virtualdj_bootstrap): # pylint: disable=redef metadata = await plugin.getplayingtrack() assert metadata.get('artist') == 'j. period' assert metadata.get( - 'title' - ) == 'Buddy [Remix] (feat. De La Soul, Jungle Brothers, Q-Tip & Queen Latifah)' + 'title') == 'Buddy [Remix] (feat. De La Soul, Jungle Brothers, Q-Tip & Queen Latifah)' assert not metadata.get('filename') await plugin.stop() await asyncio.sleep(5) @@ -316,8 +288,7 @@ async def test_vdjvirtualdj_noremix(virtualdj_bootstrap): # pylint: disable=red myvirtualdjdir = config.cparser.value('virtualdj/history') config.cparser.setValue('virtualdj/useremix', False) config.cparser.sync() - plugin = nowplaying.inputs.virtualdj.Plugin(config=config, - m3udir=myvirtualdjdir) + plugin = nowplaying.inputs.virtualdj.Plugin(config=config, m3udir=myvirtualdjdir) await plugin.start() await asyncio.sleep(5) virtualdjfile = os.path.join(myvirtualdjdir, 'test.m3u') @@ -336,8 +307,7 @@ async def test_vdjvirtualdj_ampersand(virtualdj_bootstrap): # pylint: disable=r ''' automated integration test ''' config = virtualdj_bootstrap myvirtualdjdir = config.cparser.value('virtualdj/history') - plugin = nowplaying.inputs.virtualdj.Plugin(config=config, - m3udir=myvirtualdjdir) + plugin = nowplaying.inputs.virtualdj.Plugin(config=config, m3udir=myvirtualdjdir) await plugin.start() await asyncio.sleep(5) virtualdjfile = os.path.join(myvirtualdjdir, 'test.m3u') @@ -356,8 +326,7 @@ async def test_no2newvirtualdj8(virtualdj_bootstrap, getroot): # pylint: disabl ''' automated integration test ''' config = virtualdj_bootstrap myvirtualdjdir = config.cparser.value('virtualdj/history') - plugin = nowplaying.inputs.virtualdj.Plugin(config=config, - m3udir=myvirtualdjdir) + plugin = nowplaying.inputs.virtualdj.Plugin(config=config, m3udir=myvirtualdjdir) await plugin.start() await asyncio.sleep(5) metadata = await plugin.getplayingtrack() @@ -365,8 +334,7 @@ async def test_no2newvirtualdj8(virtualdj_bootstrap, getroot): # pylint: disabl assert not metadata.get('title') assert not metadata.get('filename') - testmp3 = os.path.join(getroot, 'tests', 'audio', - '15_Ghosts_II_64kb_füllytâgged.mp3') + testmp3 = os.path.join(getroot, 'tests', 'audio', '15_Ghosts_II_64kb_füllytâgged.mp3') virtualdjfile = os.path.join(myvirtualdjdir, 'test.m3u') write_virtualdj8(virtualdjfile, testmp3) await asyncio.sleep(1) @@ -384,8 +352,7 @@ async def test_virtualdjrelative(virtualdj_bootstrap): # pylint: disable=redefi config = virtualdj_bootstrap myvirtualdjdir = config.cparser.value('virtualdj/history') myvirtualdjpath = pathlib.Path(myvirtualdjdir) - plugin = nowplaying.inputs.virtualdj.Plugin(config=config, - m3udir=myvirtualdjdir) + plugin = nowplaying.inputs.virtualdj.Plugin(config=config, m3udir=myvirtualdjdir) await plugin.start() await asyncio.sleep(5) metadata = await plugin.getplayingtrack() @@ -398,8 +365,7 @@ async def test_virtualdjrelative(virtualdj_bootstrap): # pylint: disable=redefi myvirtualdjpath.joinpath(testmp3).touch() virtualdjfile = myvirtualdjpath.joinpath('test.m3u') write_virtualdj(virtualdjfile, testmp3) - fullpath = myvirtualdjpath.joinpath('fakedir', - '15_Ghosts_II_64kb_orig.mp3') + fullpath = myvirtualdjpath.joinpath('fakedir', '15_Ghosts_II_64kb_orig.mp3') await asyncio.sleep(1) metadata = await plugin.getplayingtrack() assert not metadata.get('artist') @@ -419,11 +385,9 @@ async def test_virtualdjrelativesubst(virtualdj_bootstrap, getroot): # pylint: if sys.platform == 'darwin': myvirtualdjdir = myvirtualdjdir.resolve() config.cparser.setValue('quirks/filesubst', True) - config.cparser.setValue('quirks/filesubstin', - str(myvirtualdjdir.joinpath('fakedir'))) + config.cparser.setValue('quirks/filesubstin', str(myvirtualdjdir.joinpath('fakedir'))) config.cparser.setValue('quirks/filesubstout', str(audiodir)) - plugin = nowplaying.inputs.virtualdj.Plugin(config=config, - m3udir=str(myvirtualdjdir)) + plugin = nowplaying.inputs.virtualdj.Plugin(config=config, m3udir=str(myvirtualdjdir)) await plugin.start() await asyncio.sleep(5) metadata = await plugin.getplayingtrack() @@ -431,16 +395,14 @@ async def test_virtualdjrelativesubst(virtualdj_bootstrap, getroot): # pylint: assert not metadata.get('title') assert not metadata.get('filename') - testmp3 = str( - pathlib.Path('fakedir').joinpath('15_Ghosts_II_64kb_orig.mp3')) + testmp3 = str(pathlib.Path('fakedir').joinpath('15_Ghosts_II_64kb_orig.mp3')) myvirtualdjdir.joinpath('fakedir').mkdir(parents=True, exist_ok=True) myvirtualdjdir.joinpath(testmp3).touch() virtualdjfile = str(myvirtualdjdir.joinpath('test.m3u')) write_virtualdj(virtualdjfile, testmp3) await asyncio.sleep(5) metadata = await plugin.getplayingtrack() - assert metadata['filename'] == str( - audiodir.joinpath('15_Ghosts_II_64kb_orig.mp3')) + assert metadata['filename'] == str(audiodir.joinpath('15_Ghosts_II_64kb_orig.mp3')) await plugin.stop() await asyncio.sleep(5) @@ -450,8 +412,7 @@ async def test_virtualdjstream(virtualdj_bootstrap): # pylint: disable=redefine ''' automated integration test ''' config = virtualdj_bootstrap myvirtualdjdir = config.cparser.value('virtualdj/history') - plugin = nowplaying.inputs.virtualdj.Plugin(config=config, - m3udir=myvirtualdjdir) + plugin = nowplaying.inputs.virtualdj.Plugin(config=config, m3udir=myvirtualdjdir) await plugin.start() await asyncio.sleep(5) metadata = await plugin.getplayingtrack() @@ -495,8 +456,7 @@ async def test_playlist_read(virtualdj_bootstrap, getroot): # pylint: disable=r playlistdir = getroot.joinpath('tests', 'playlists', 'virtualdj') myvirtualdjdir = config.cparser.value('virtualdj/history') config.cparser.setValue('virtualdj/playlists', playlistdir) - plugin = nowplaying.inputs.virtualdj.Plugin(config=config, - m3udir=myvirtualdjdir) + plugin = nowplaying.inputs.virtualdj.Plugin(config=config, m3udir=myvirtualdjdir) plugin.initdb() filename = await plugin.getrandomtrack('videos') assert filename diff --git a/tests/test_webserver.py b/tests/test_webserver.py index 507706a9..5c914f84 100644 --- a/tests/test_webserver.py +++ b/tests/test_webserver.py @@ -32,8 +32,7 @@ def getwebserver(bootstrap): logging.debug('%s is in use; waiting', port) time.sleep(2) - manager = nowplaying.subprocesses.SubprocessManager(config=config, - testmode=True) + manager = nowplaying.subprocesses.SubprocessManager(config=config, testmode=True) manager.start_webserver() time.sleep(5) yield config, metadb @@ -52,9 +51,8 @@ def test_startstopwebserver(getwebserver): # pylint: disable=redefined-outer-na async def test_webserver_htmtest(getwebserver): # pylint: disable=redefined-outer-name ''' start webserver, read existing data, add new data, then read that ''' config, metadb = getwebserver - config.cparser.setValue( - 'weboutput/htmltemplate', - config.getbundledir().joinpath('templates', 'basic-plain.txt')) + config.cparser.setValue('weboutput/htmltemplate', + config.getbundledir().joinpath('templates', 'basic-plain.txt')) config.cparser.setValue('weboutput/once', True) config.cparser.sync() time.sleep(10) @@ -68,10 +66,7 @@ async def test_webserver_htmtest(getwebserver): # pylint: disable=redefined-out # handle first write - await metadb.write_to_metadb(metadata={ - 'title': 'testhtmtitle', - 'artist': 'testhtmartist' - }) + await metadb.write_to_metadb(metadata={'title': 'testhtmtitle', 'artist': 'testhtmartist'}) time.sleep(1) req = requests.get('http://localhost:8899/index.html', timeout=5) assert req.status_code == 200 @@ -111,12 +106,10 @@ async def test_webserver_txttest(getwebserver): # pylint: disable=redefined-out ''' start webserver, read existing data, add new data, then read that ''' config, metadb = getwebserver config.cparser.setValue('weboutput/httpenabled', 'true') - config.cparser.setValue( - 'weboutput/htmltemplate', - config.getbundledir().joinpath('templates', 'basic-plain.txt')) - config.cparser.setValue( - 'textoutput/txttemplate', - config.getbundledir().joinpath('templates', 'basic-plain.txt')) + config.cparser.setValue('weboutput/htmltemplate', + config.getbundledir().joinpath('templates', 'basic-plain.txt')) + config.cparser.setValue('textoutput/txttemplate', + config.getbundledir().joinpath('templates', 'basic-plain.txt')) config.cparser.setValue('weboutput/once', True) config.cparser.sync() time.sleep(10) @@ -133,10 +126,7 @@ async def test_webserver_txttest(getwebserver): # pylint: disable=redefined-out assert req.json() == {} # handle first write - await metadb.write_to_metadb(metadata={ - 'title': 'testtxttitle', - 'artist': 'testtxtartist' - }) + await metadb.write_to_metadb(metadata={'title': 'testtxttitle', 'artist': 'testtxtartist'}) time.sleep(1) req = requests.get('http://localhost:8899/index.txt', timeout=5) assert req.status_code == 200 diff --git a/tests/upgrade/test_300.py b/tests/upgrade/test_300.py index f2bdced1..fef4c7ae 100644 --- a/tests/upgrade/test_300.py +++ b/tests/upgrade/test_300.py @@ -69,8 +69,7 @@ def test_version_300rc1_to_current(): # pylint: disable=redefined-outer-name qsettingsformat = QSettings.IniFormat else: qsettingsformat = QSettings.NativeFormat - teststr = ''.join( - random.choice(string.ascii_lowercase) for _ in range(5)) + teststr = ''.join(random.choice(string.ascii_lowercase) for _ in range(5)) oldfilename = make_fake_300_config(teststr) oldchecksum = checksum(oldfilename) backupdir = os.path.join(newpath, 'testsuite', 'configbackup') @@ -79,8 +78,7 @@ def test_version_300rc1_to_current(): # pylint: disable=redefined-outer-name nowplaying.bootstrap.set_qt_names(appname='testsuite') upgrade = nowplaying.upgrade.UpgradeConfig(testdir=newpath) #pylint: disable=unused-variable config = QSettings(qsettingsformat, QSettings.UserScope, - QCoreApplication.organizationName(), - QCoreApplication.applicationName()) + QCoreApplication.organizationName(), QCoreApplication.applicationName()) newfilename = config.fileName() config.sync() fakevalue = config.value('settings/notdefault') diff --git a/tests/upgrade/test_noconfig.py b/tests/upgrade/test_noconfig.py index 6e2e0338..827eece3 100644 --- a/tests/upgrade/test_noconfig.py +++ b/tests/upgrade/test_noconfig.py @@ -39,8 +39,8 @@ def test_noconfigfile(): # pylint: disable=redefined-outer-name backupdir = os.path.join(newpath, 'testsuite', 'configbackup') nowplaying.bootstrap.set_qt_names(appname='testsuite') upgrade = nowplaying.upgrade.UpgradeConfig(testdir=newpath) #pylint: disable=unused-variable - config = QSettings(qsettingsformat, QSettings.UserScope, - 'com.github.whatsnowplaying', 'testsuite') + config = QSettings(qsettingsformat, QSettings.UserScope, 'com.github.whatsnowplaying', + 'testsuite') config.clear() config.setValue('fakevalue', 'force') config.sync() diff --git a/updateshas.py b/updateshas.py index 3cb951c9..20d563e9 100755 --- a/updateshas.py +++ b/updateshas.py @@ -30,8 +30,7 @@ def main(): for version in sys.argv[2:]: subprocess.check_call(['git', 'checkout', '--force', version]) - for apppath in pathlib.Path(os.path.join('nowplaying', - 'templates')).iterdir(): + for apppath in pathlib.Path(os.path.join('nowplaying', 'templates')).iterdir(): filename = os.path.basename(apppath) if filename not in oldshas: oldshas[filename] = {}