adding latest
This commit is contained in:
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"python.pythonPath": "/Users/dtomlinson/.virtualenvs/musicbrainzapi/bin/python"
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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__':
|
||||||
|
|||||||
4025
src/musicbrainzapi/cli/test.json
Normal file
4025
src/musicbrainzapi/cli/test.json
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user