adding latest

This commit is contained in:
2020-03-04 16:19:41 +00:00
parent abe87ce90b
commit 2af554ffa3
4 changed files with 4190 additions and 19 deletions

3
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,3 @@
{
"python.pythonPath": "/Users/dtomlinson/.virtualenvs/musicbrainzapi/bin/python"
}

View File

@@ -1,6 +1,9 @@
from __future__ import annotations from __future__ import annotations
from abc import ABC, abstractmethod, abstractstaticmethod from abc import ABC, abstractmethod, abstractstaticmethod
from dataclasses import dataclass from dataclasses import dataclass
from pprint import pprint
from typing import Union
import contextlib
# from pprint import pprint # from pprint import pprint
@@ -32,6 +35,16 @@ class LyricsConcreteBuilder(ABC):
def artist(self, artist: str) -> None: def artist(self, artist: str) -> None:
pass pass
@property
@abstractmethod
def country(self) -> Union[str, None]:
pass
@country.setter
@abstractmethod
def country(self, country: Union[str, None]) -> None:
pass
@property @property
@abstractmethod @abstractmethod
def artist_id(self) -> str: def artist_id(self) -> str:
@@ -86,6 +99,16 @@ class LyricsBuilder(LyricsConcreteBuilder):
@artist.setter @artist.setter
def artist(self, artist: str) -> None: def artist(self, artist: str) -> None:
self._artist = artist self._artist = artist
self._product.artist = artist
@property
def country(self) -> Union[str, None]:
return self._country
@country.setter
def country(self, country: Union[str, None]) -> None:
self._country = country
self._product.country = country
@property @property
def artist_id(self) -> str: def artist_id(self) -> str:
@@ -94,6 +117,7 @@ class LyricsBuilder(LyricsConcreteBuilder):
@artist_id.setter @artist_id.setter
def artist_id(self, artist_id: str) -> None: def artist_id(self, artist_id: str) -> None:
self._artist_id = artist_id self._artist_id = artist_id
self._product.artist_id = artist_id
def __init__(self) -> None: def __init__(self) -> None:
self.reset() self.reset()
@@ -103,8 +127,9 @@ class LyricsBuilder(LyricsConcreteBuilder):
def do_search_artists(self) -> None: def do_search_artists(self) -> None:
self.musicbrainz_artists = musicbrainzngs.search_artists( self.musicbrainz_artists = musicbrainzngs.search_artists(
artist=self.artist artist=self.artist, country=self.country
) )
# pprint(self.musicbrainz_artists['artist-list'])
return self return self
def do_sort_names(self) -> None: def do_sort_names(self) -> None:
@@ -134,6 +159,97 @@ class LyricsBuilder(LyricsConcreteBuilder):
) )
return self return self
@staticmethod
def browse_releases(
artist_id: str,
limit: int,
release_type: list,
offset: Union[int, None] = None,
) -> dict:
releases = musicbrainzngs.browse_releases(
artist=artist_id,
limit=limit,
release_type=release_type,
offset=offset,
includes=['recordings'],
)
return releases
@staticmethod
def browse_recordings(
release: str, limit: int, offset: Union[int, None]
) -> dict:
recordings = musicbrainzngs.browse_recordings(
release=release, limit=limit, offset=offset
)
return recordings
def do_search_albumns(self) -> None:
limit = 100
offset = 0
page = 1
self.releases_list = list()
releases = self.browse_releases(self.artist_id, limit, ['album'])
total_releases_count = releases['release-count']
page_releases_list = releases['release-list']
self.releases_list += page_releases_list
with click.progressbar(
length=total_releases_count - limit,
label='Finding all albumns from Musicbrainz',
) as bar:
while len(self.releases_list) < total_releases_count:
offset += limit
page += 1
page_releases = self.browse_releases(
self.artist_id, limit, ['album'], offset
)
page_releases_list = page_releases['release-list']
self.releases_list += page_releases_list
bar.update(limit)
click.echo(f'Found {total_releases_count} albums for {self.artist}')
return self
def do_filter_albums_official(self) -> None:
# Get official albums only
_official_albums_list = list()
for i in self.releases_list:
with contextlib.suppress(KeyError):
if i['status'] == 'Official':
_official_albums_list.append(i)
self.official_albums = dict(
(i['id'], i['title']) for i in _official_albums_list
)
# pprint(self.official_albums)
return self
def do_search_album_tracks(self) -> None:
# No album is over 100 tracks so we don't need to iterate
limit = 100
offset = 0
recordings_list = list()
self.recordings = dict()
with click.progressbar(
length=len(self.official_albums),
label='Finding all tracks in albums from Musicbrainz',
) as bar:
for i in self.official_albums:
_recordings_result = self.browse_recordings(
i, limit=limit, offset=offset
)
album_recordings_list = _recordings_result['recording-list']
recordings_list.append(
dict((i['id'], i['title']) for i in album_recordings_list)
)
bar.update(1)
for i in recordings_list:
self.recordings = {**self.recordings, **i}
# pprint(self.recordings)
click.echo(
f'Found {len(self.recordings)} tracks from '
f'{len(self.official_albums)} albums for {self.artist}'
)
return self
class LyricsClickDirector: class LyricsClickDirector:
"""docstring for LyricsClickDirector""" """docstring for LyricsClickDirector"""
@@ -149,8 +265,9 @@ class LyricsClickDirector:
def builder(self, builder: LyricsBuilder) -> None: def builder(self, builder: LyricsBuilder) -> None:
self._builder = builder self._builder = builder
def _get_initial_artists(self, artist: str) -> None: def _get_initial_artists(self, artist: str, country: str) -> None:
self.builder.artist = artist self.builder.artist = artist
self.builder.country = country
self.builder.set_useragent() self.builder.set_useragent()
self.builder.do_search_artists() self.builder.do_search_artists()
self.builder.do_sort_names() self.builder.do_sort_names()
@@ -176,17 +293,14 @@ class LyricsClickDirector:
_position.append(i) _position.append(i)
chosen = int( chosen = int(
click.prompt( click.prompt(
f'Enter number', f'Enter choice, default is',
type=click.Choice( default=1,
[ type=click.IntRange(
str(i + 1) 1, len(self.builder._top_five_results)
for i in range(len(self.builder._top_five_results))
]
), ),
), ),
) )
choice = _position[chosen - 1] choice = _position[chosen - 1]
# click.echo(choice)
click.echo(f'You chose {self.builder._sort_names.get(choice)}') click.echo(f'You chose {self.builder._sort_names.get(choice)}')
self._artist = self.builder._sort_names.get(choice).split('|')[0] self._artist = self.builder._sort_names.get(choice).split('|')[0]
self._artist_id = choice self._artist_id = choice
@@ -200,16 +314,17 @@ class LyricsClickDirector:
raise SystemExit() raise SystemExit()
def _set_artist_id_on_product(self) -> None: def _set_artist_id_on_product(self) -> None:
self.builder._product.artist_id = self._artist_id self.builder.artist_id = self._artist_id
self.builder._product.artist = self._artist self.builder.artist = self._artist
print(self.builder._product.artist_id) # print(self.builder._product.artist_id)
print(self.builder._product.artist) # print(self.builder._product.artist)
print(self.builder._product.__slots__) # print(self.builder._product.__slots__)
@dataclass @dataclass
class Lyrics: class Lyrics:
"""docstring for Lyrics""" """docstring for Lyrics"""
__slots__ = ['artist_id', 'artist'] __slots__ = ['artist_id', 'artist']
artist_id: str artist_id: str
artist: str artist: str

View File

@@ -1,4 +1,5 @@
from pprint import pprint from pprint import pprint
from typing import Union
import click import click
import musicbrainzngs import musicbrainzngs
@@ -11,13 +12,16 @@ from musicbrainzapi.api.command_builders import lyrics
class LyricsInfo: class LyricsInfo:
"""docstring for LyricsInfo""" """docstring for LyricsInfo"""
def __init__(self, artist: str) -> None: def __init__(self, artist: str, country: str = None) -> None:
authenticate.set_useragent() authenticate.set_useragent()
self.artist = artist self.artist = artist
self.country = country
super().__init__() super().__init__()
def _search_artist(self) -> None: def _search_artist(self) -> None:
self.artists = musicbrainzngs.search_artists(artist=self.artist) self.artists = musicbrainzngs.search_artists(
artist=self.artist, country=self.country
)
# pprint(self.artists['artist-list']) # pprint(self.artists['artist-list'])
if self.artists.get('artist-count') == 0: if self.artists.get('artist-count') == 0:
@@ -72,16 +76,40 @@ class CommandUtility:
# @click.argument('path', required=False, type=click.Path(resolve_path=True)) # @click.argument('path', required=False, type=click.Path(resolve_path=True))
# @click.command(short_help='a test command') # @click.command(short_help='a test command')
@click.option('--artist', '-a', required=True, multiple=True, type=str) @click.option(
'--country',
'-c',
default=None,
required=False,
multiple=False,
type=str,
help='ISO A-2 Country code (https://en.wikipedia.org/wiki/ISO_3166-1_alpha'
'-2) Example: GB',
)
@click.option(
'--artist',
'-a',
required=True,
multiple=True,
type=str,
help='Artist/Group to search lyrics for.',
)
@click.command() @click.command()
@pass_environment @pass_environment
def cli(ctx, artist) -> None: def cli(ctx, artist: str, country: Union[str, None]) -> None:
"""
Search for lyrics of an Artist/Group.
"""
print(artist)
director = lyrics.LyricsClickDirector() director = lyrics.LyricsClickDirector()
builder = lyrics.LyricsBuilder() builder = lyrics.LyricsBuilder()
director.builder = builder director.builder = builder
director._get_initial_artists(artist) director._get_initial_artists(artist, country)
director._confirm_final_artist() director._confirm_final_artist()
director._set_artist_id_on_product() director._set_artist_id_on_product()
builder.do_search_albumns()
builder.do_filter_albums_official()
builder.do_search_album_tracks()
if __name__ == '__main__': if __name__ == '__main__':

File diff suppressed because it is too large Load Diff