adding builder for the artist search

This commit is contained in:
2020-03-04 01:09:23 +00:00
parent ddccce0d69
commit abe87ce90b
5 changed files with 244 additions and 54 deletions

View File

@@ -0,0 +1 @@
from . import lyrics

View 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))

View File

@@ -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()

View File

@@ -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)

View File

@@ -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()