adding builder for the artist search
This commit is contained in:
1
src/musicbrainzapi/api/command_builders/__init__.py
Normal file
1
src/musicbrainzapi/api/command_builders/__init__.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
from . import lyrics
|
||||||
226
src/musicbrainzapi/api/command_builders/lyrics.py
Normal file
226
src/musicbrainzapi/api/command_builders/lyrics.py
Normal file
@@ -0,0 +1,226 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
from abc import ABC, abstractmethod, abstractstaticmethod
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
# from pprint import pprint
|
||||||
|
|
||||||
|
import musicbrainzngs
|
||||||
|
import click
|
||||||
|
|
||||||
|
from musicbrainzapi.api import authenticate
|
||||||
|
|
||||||
|
|
||||||
|
class LyricsConcreteBuilder(ABC):
|
||||||
|
"""docstring for Lyrics"""
|
||||||
|
|
||||||
|
@abstractstaticmethod
|
||||||
|
def set_useragent():
|
||||||
|
authenticate.set_useragent()
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def product(self) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def artist(self) -> str:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@artist.setter
|
||||||
|
@abstractmethod
|
||||||
|
def artist(self, artist: str) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def artist_id(self) -> str:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@artist_id.setter
|
||||||
|
@abstractmethod
|
||||||
|
def artist_id(self, artist_id: str) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __init__(self) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def reset(self) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def do_search_artists(self) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def do_sort_names(self) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def get_accuracy_scores(self) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def get_top_five_results(self) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class LyricsBuilder(LyricsConcreteBuilder):
|
||||||
|
"""docstring for LyricsBuilder"""
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def set_useragent() -> None:
|
||||||
|
authenticate.set_useragent()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def product(self) -> Lyrics:
|
||||||
|
product = self._product
|
||||||
|
return product
|
||||||
|
|
||||||
|
@property
|
||||||
|
def artist(self) -> str:
|
||||||
|
return self._artist
|
||||||
|
|
||||||
|
@artist.setter
|
||||||
|
def artist(self, artist: str) -> None:
|
||||||
|
self._artist = artist
|
||||||
|
|
||||||
|
@property
|
||||||
|
def artist_id(self) -> str:
|
||||||
|
return self._artist_id
|
||||||
|
|
||||||
|
@artist_id.setter
|
||||||
|
def artist_id(self, artist_id: str) -> None:
|
||||||
|
self._artist_id = artist_id
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.reset()
|
||||||
|
|
||||||
|
def reset(self) -> None:
|
||||||
|
self._product = Lyrics
|
||||||
|
|
||||||
|
def do_search_artists(self) -> None:
|
||||||
|
self.musicbrainz_artists = musicbrainzngs.search_artists(
|
||||||
|
artist=self.artist
|
||||||
|
)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def do_sort_names(self) -> None:
|
||||||
|
self._sort_names = dict(
|
||||||
|
(i.get('id'), f'{i.get("sort-name")} | {i.get("disambiguation")}')
|
||||||
|
if i.get('disambiguation') is not None
|
||||||
|
else (i.get('id'), f'{i.get("sort-name")}')
|
||||||
|
for i in self.musicbrainz_artists['artist-list']
|
||||||
|
)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def get_accuracy_scores(self) -> None:
|
||||||
|
self._accuracy_scores = dict(
|
||||||
|
(i.get('id'), int(i.get('ext:score', '0')))
|
||||||
|
for i in self.musicbrainz_artists['artist-list']
|
||||||
|
)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def get_top_five_results(self) -> None:
|
||||||
|
self._top_five_results = dict(
|
||||||
|
(i, self._accuracy_scores.get(i))
|
||||||
|
for i in sorted(
|
||||||
|
self._accuracy_scores,
|
||||||
|
key=self._accuracy_scores.get,
|
||||||
|
reverse=True,
|
||||||
|
)[0:5]
|
||||||
|
)
|
||||||
|
return self
|
||||||
|
|
||||||
|
|
||||||
|
class LyricsClickDirector:
|
||||||
|
"""docstring for LyricsClickDirector"""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self._builder = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def builder(self) -> LyricsBuilder:
|
||||||
|
return self._builder
|
||||||
|
|
||||||
|
@builder.setter
|
||||||
|
def builder(self, builder: LyricsBuilder) -> None:
|
||||||
|
self._builder = builder
|
||||||
|
|
||||||
|
def _get_initial_artists(self, artist: str) -> None:
|
||||||
|
self.builder.artist = artist
|
||||||
|
self.builder.set_useragent()
|
||||||
|
self.builder.do_search_artists()
|
||||||
|
self.builder.do_sort_names()
|
||||||
|
self.builder.get_accuracy_scores()
|
||||||
|
self.builder.get_top_five_results()
|
||||||
|
|
||||||
|
def _confirm_final_artist(self) -> None:
|
||||||
|
artist_meta = None
|
||||||
|
for i, j in self.builder._top_five_results.items():
|
||||||
|
artist_meta = 'Multiple' if j <= 100 else None
|
||||||
|
|
||||||
|
if artist_meta == 'Multiple':
|
||||||
|
_position = []
|
||||||
|
click.echo(
|
||||||
|
f'Musicbrainz found several results for {self.builder.artist[0]}'
|
||||||
|
'. Which artist/group do you want?',
|
||||||
|
)
|
||||||
|
for i, j in zip(self.builder._top_five_results, range(1, 6)):
|
||||||
|
click.echo(
|
||||||
|
f'[{j}] {self.builder._sort_names.get(i)}'
|
||||||
|
f' ({self.builder._accuracy_scores.get(i)}% match)'
|
||||||
|
)
|
||||||
|
_position.append(i)
|
||||||
|
chosen = int(
|
||||||
|
click.prompt(
|
||||||
|
f'Enter number',
|
||||||
|
type=click.Choice(
|
||||||
|
[
|
||||||
|
str(i + 1)
|
||||||
|
for i in range(len(self.builder._top_five_results))
|
||||||
|
]
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
choice = _position[chosen - 1]
|
||||||
|
# click.echo(choice)
|
||||||
|
click.echo(f'You chose {self.builder._sort_names.get(choice)}')
|
||||||
|
self._artist = self.builder._sort_names.get(choice).split('|')[0]
|
||||||
|
self._artist_id = choice
|
||||||
|
|
||||||
|
elif artist_meta is None:
|
||||||
|
click.echo(
|
||||||
|
f'Musicbrainz did not find any results for '
|
||||||
|
f'{self.builder.artist[0]}. Check the spelling or consider '
|
||||||
|
'alternative names that the artist/group may go by.'
|
||||||
|
)
|
||||||
|
raise SystemExit()
|
||||||
|
|
||||||
|
def _set_artist_id_on_product(self) -> None:
|
||||||
|
self.builder._product.artist_id = self._artist_id
|
||||||
|
self.builder._product.artist = self._artist
|
||||||
|
print(self.builder._product.artist_id)
|
||||||
|
print(self.builder._product.artist)
|
||||||
|
print(self.builder._product.__slots__)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Lyrics:
|
||||||
|
"""docstring for Lyrics"""
|
||||||
|
__slots__ = ['artist_id', 'artist']
|
||||||
|
artist_id: str
|
||||||
|
artist: str
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
# director = LyricsClickDirector()
|
||||||
|
# builder = LyricsBuilder()
|
||||||
|
# director.builder = builder
|
||||||
|
# director._get_initial_artists('One Direction')
|
||||||
|
# director._confirm_final_artist()
|
||||||
|
# director._set_artist_id_on_product()
|
||||||
|
# director.builder._product
|
||||||
|
print(type(Lyrics))
|
||||||
@@ -19,6 +19,7 @@ cmd_folder = os.path.abspath(
|
|||||||
os.path.join(os.path.dirname(__file__), 'commands')
|
os.path.join(os.path.dirname(__file__), 'commands')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class ComplexCLI(click.MultiCommand):
|
class ComplexCLI(click.MultiCommand):
|
||||||
def list_commands(self, ctx):
|
def list_commands(self, ctx):
|
||||||
rv = []
|
rv = []
|
||||||
@@ -56,5 +57,6 @@ def cli(ctx, verbose, home):
|
|||||||
if home is not None:
|
if home is not None:
|
||||||
ctx.home = home
|
ctx.home = home
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
cli()
|
cli()
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
Python 3.8.0 (default, Nov 3 2019, 22:15:08)
|
|
||||||
[Clang 10.0.1 (clang-1001.0.46.4)] on darwin
|
|
||||||
Type "help", "copyright", "credits" or "license" for more information.
|
|
||||||
(InteractiveConsole)
|
|
||||||
>>> match_check := False
|
|
||||||
File "<console>", line 1
|
|
||||||
match_check := False
|
|
||||||
^
|
|
||||||
SyntaxError: invalid syntax
|
|
||||||
>>> if match_check := False:
|
|
||||||
... print('false')
|
|
||||||
File "<console>", line 2
|
|
||||||
print('false')
|
|
||||||
^
|
|
||||||
IndentationError: expected an indented block
|
|
||||||
>>> if match_check := False:
|
|
||||||
... print(False)
|
|
||||||
...
|
|
||||||
>>> if not match_check := False:
|
|
||||||
... print(False)
|
|
||||||
@@ -5,6 +5,7 @@ import musicbrainzngs
|
|||||||
|
|
||||||
from musicbrainzapi.cli.cli import pass_environment
|
from musicbrainzapi.cli.cli import pass_environment
|
||||||
from musicbrainzapi.api import authenticate
|
from musicbrainzapi.api import authenticate
|
||||||
|
from musicbrainzapi.api.command_builders import lyrics
|
||||||
|
|
||||||
|
|
||||||
class LyricsInfo:
|
class LyricsInfo:
|
||||||
@@ -17,7 +18,7 @@ class LyricsInfo:
|
|||||||
|
|
||||||
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)
|
||||||
pprint(self.artists['artist-list'])
|
# pprint(self.artists['artist-list'])
|
||||||
|
|
||||||
if self.artists.get('artist-count') == 0:
|
if self.artists.get('artist-count') == 0:
|
||||||
self.chosen_artist = 'Null'
|
self.chosen_artist = 'Null'
|
||||||
@@ -56,12 +57,8 @@ class LyricsInfo:
|
|||||||
# Check for 100% match
|
# Check for 100% match
|
||||||
self.chosen_artist = None
|
self.chosen_artist = None
|
||||||
for i, j in self.top_five_results.items():
|
for i, j in self.top_five_results.items():
|
||||||
if self.chosen_artist is None:
|
self.chosen_artist = 'Multiple' if j <= 100 else None
|
||||||
if j == 100:
|
|
||||||
self.chosen_artist = i
|
|
||||||
break
|
|
||||||
|
|
||||||
# pprint(self.sort_names.get(self.chosen_artist))
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
||||||
@@ -73,36 +70,20 @@ class CommandUtility:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@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.option('--artist', '-a', required=True, multiple=True, type=str)
|
@click.option('--artist', '-a', required=True, multiple=True, type=str)
|
||||||
@click.command(short_help='a test command')
|
@click.command()
|
||||||
@pass_environment
|
@pass_environment
|
||||||
def cli(ctx, artist, path: click.Path) -> None:
|
def cli(ctx, artist) -> None:
|
||||||
# print(artist)
|
director = lyrics.LyricsClickDirector()
|
||||||
artist_0 = LyricsInfo(artist)._search_artist()
|
builder = lyrics.LyricsBuilder()
|
||||||
print(f'artist_0 = {artist_0.chosen_artist}')
|
director.builder = builder
|
||||||
if artist_0.chosen_artist is None:
|
director._get_initial_artists(artist)
|
||||||
|
director._confirm_final_artist()
|
||||||
for i, j in zip(artist_0.top_five_results, range(1, 6)):
|
director._set_artist_id_on_product()
|
||||||
click.echo(
|
|
||||||
f'[{j}] {artist_0.sort_names.get(i)}'
|
|
||||||
f' ({artist_0._accuracy_scores.get(i)}% match)'
|
|
||||||
)
|
|
||||||
|
|
||||||
click.prompt(
|
|
||||||
f'We found several results for {artist[0]}, which artist/group do you want?'
|
|
||||||
)
|
|
||||||
# implement this
|
|
||||||
elif artist_0.chosen_artist == 'Null':
|
|
||||||
click.echo(f"We didn't find any results for {artist}")
|
|
||||||
else:
|
|
||||||
click.confirm(
|
|
||||||
f'Musicbrainz a perfect match for {artist[0]} with '
|
|
||||||
f'"{artist_0.sort_names.get(artist_0.chosen_artist)}" (100% match)'
|
|
||||||
'. Is this correct?'
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
LyricsInfo('Queenifie')._search_artist()
|
# LyricsInfo('Queenifie')._search_artist()
|
||||||
|
LyricsInfo('Que')._search_artist()
|
||||||
|
|||||||
Reference in New Issue
Block a user