merge track into develop
This commit is contained in:
25
poetry.lock
generated
25
poetry.lock
generated
@@ -1,3 +1,11 @@
|
|||||||
|
[[package]]
|
||||||
|
category = "main"
|
||||||
|
description = "Addict is a dictionary whose items can be set using both attribute and item syntax."
|
||||||
|
name = "addict"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
version = "2.2.1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
category = "dev"
|
category = "dev"
|
||||||
description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
|
description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
|
||||||
@@ -202,6 +210,14 @@ version = ">=0.12"
|
|||||||
[package.extras]
|
[package.extras]
|
||||||
dev = ["pre-commit", "tox"]
|
dev = ["pre-commit", "tox"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
category = "main"
|
||||||
|
description = "Easy to use progress bars"
|
||||||
|
name = "progress"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
version = "1.5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
category = "dev"
|
category = "dev"
|
||||||
description = "A full-screen, console-based Python debugger"
|
description = "A full-screen, console-based Python debugger"
|
||||||
@@ -477,10 +493,14 @@ docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"]
|
|||||||
testing = ["jaraco.itertools", "func-timeout"]
|
testing = ["jaraco.itertools", "func-timeout"]
|
||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
content-hash = "40cc154211436945480756e120f8b39bb419e373bc51da5c6bb4d1ab72db47c5"
|
content-hash = "50cff0758d9f4bfa77596b28f6f5f0c7f1db897b7c0d615071379c288b1d110d"
|
||||||
python-versions = "^3.7"
|
python-versions = "^3.7"
|
||||||
|
|
||||||
[metadata.files]
|
[metadata.files]
|
||||||
|
addict = [
|
||||||
|
{file = "addict-2.2.1-py3-none-any.whl", hash = "sha256:1948c2a5d93ba6026eb91aef2c971234aaf72488a9c07ab8a7950f82ae30eea7"},
|
||||||
|
{file = "addict-2.2.1.tar.gz", hash = "sha256:f22493f056032f50e4931a82444fcba8ef74c8fc994c5d06aa546a1433c2b8b0"},
|
||||||
|
]
|
||||||
appdirs = [
|
appdirs = [
|
||||||
{file = "appdirs-1.4.3-py2.py3-none-any.whl", hash = "sha256:d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e"},
|
{file = "appdirs-1.4.3-py2.py3-none-any.whl", hash = "sha256:d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e"},
|
||||||
{file = "appdirs-1.4.3.tar.gz", hash = "sha256:9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92"},
|
{file = "appdirs-1.4.3.tar.gz", hash = "sha256:9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92"},
|
||||||
@@ -556,6 +576,9 @@ pluggy = [
|
|||||||
{file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"},
|
{file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"},
|
||||||
{file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"},
|
{file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"},
|
||||||
]
|
]
|
||||||
|
progress = [
|
||||||
|
{file = "progress-1.5.tar.gz", hash = "sha256:69ecedd1d1bbe71bf6313d88d1e6c4d2957b7f1d4f71312c211257f7dae64372"},
|
||||||
|
]
|
||||||
pudb = [
|
pudb = [
|
||||||
{file = "pudb-2019.2.tar.gz", hash = "sha256:e8f0ea01b134d802872184b05bffc82af29a1eb2f9374a277434b932d68f58dc"},
|
{file = "pudb-2019.2.tar.gz", hash = "sha256:e8f0ea01b134d802872184b05bffc82af29a1eb2f9374a277434b932d68f58dc"},
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ authors = ["dtomlinson <dtomlinson@williamhill.co.uk>"]
|
|||||||
python = "^3.7"
|
python = "^3.7"
|
||||||
requests = "^2.23.0"
|
requests = "^2.23.0"
|
||||||
musicbrainzngs = "^0.7.1"
|
musicbrainzngs = "^0.7.1"
|
||||||
|
addict = "^2.2.1"
|
||||||
|
progress = "^1.5"
|
||||||
|
|
||||||
[tool.poetry.dev-dependencies]
|
[tool.poetry.dev-dependencies]
|
||||||
pytest = "^5.2"
|
pytest = "^5.2"
|
||||||
@@ -25,3 +27,6 @@ pyls-black = "^0.4.4"
|
|||||||
[build-system]
|
[build-system]
|
||||||
requires = ["poetry>=0.12"]
|
requires = ["poetry>=0.12"]
|
||||||
build-backend = "poetry.masonry.api"
|
build-backend = "poetry.masonry.api"
|
||||||
|
|
||||||
|
[tool.poetry.plugins."console_scripts"]
|
||||||
|
"musicbrainzapi" = "musicbrainzapi.cli.cli:cli"
|
||||||
|
|||||||
@@ -2,13 +2,16 @@ 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 pprint import pprint
|
||||||
from typing import Union
|
from typing import Union, List
|
||||||
import contextlib
|
import contextlib
|
||||||
|
import itertools
|
||||||
|
from progress.spinner import PieSpinner
|
||||||
|
|
||||||
# from pprint import pprint
|
# from pprint import pprint
|
||||||
|
|
||||||
import musicbrainzngs
|
import musicbrainzngs
|
||||||
import click
|
import click
|
||||||
|
import addict
|
||||||
|
|
||||||
from musicbrainzapi.api import authenticate
|
from musicbrainzapi.api import authenticate
|
||||||
|
|
||||||
@@ -16,10 +19,6 @@ from musicbrainzapi.api import authenticate
|
|||||||
class LyricsConcreteBuilder(ABC):
|
class LyricsConcreteBuilder(ABC):
|
||||||
"""docstring for Lyrics"""
|
"""docstring for Lyrics"""
|
||||||
|
|
||||||
@abstractstaticmethod
|
|
||||||
def set_useragent():
|
|
||||||
authenticate.set_useragent()
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def product(self) -> None:
|
def product(self) -> None:
|
||||||
@@ -55,6 +54,22 @@ class LyricsConcreteBuilder(ABC):
|
|||||||
def artist_id(self, artist_id: str) -> None:
|
def artist_id(self, artist_id: str) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@abstractstaticmethod
|
||||||
|
def set_useragent():
|
||||||
|
authenticate.set_useragent()
|
||||||
|
|
||||||
|
@abstractstaticmethod
|
||||||
|
def browse_releases(self) -> dict:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractstaticmethod
|
||||||
|
def get_album_info_list(self) -> list:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractstaticmethod
|
||||||
|
def paginate_results(self) -> list:
|
||||||
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
pass
|
pass
|
||||||
@@ -79,14 +94,14 @@ class LyricsConcreteBuilder(ABC):
|
|||||||
def get_top_five_results(self) -> None:
|
def get_top_five_results(self) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def do_search_albums(self) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class LyricsBuilder(LyricsConcreteBuilder):
|
class LyricsBuilder(LyricsConcreteBuilder):
|
||||||
"""docstring for LyricsBuilder"""
|
"""docstring for LyricsBuilder"""
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def set_useragent() -> None:
|
|
||||||
authenticate.set_useragent()
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def product(self) -> Lyrics:
|
def product(self) -> Lyrics:
|
||||||
product = self._product
|
product = self._product
|
||||||
@@ -119,6 +134,76 @@ class LyricsBuilder(LyricsConcreteBuilder):
|
|||||||
self._artist_id = artist_id
|
self._artist_id = artist_id
|
||||||
self._product.artist_id = artist_id
|
self._product.artist_id = artist_id
|
||||||
|
|
||||||
|
@property
|
||||||
|
def all_tracks(self) -> set:
|
||||||
|
return self._all_tracks
|
||||||
|
|
||||||
|
@all_tracks.setter
|
||||||
|
def all_tracks(self, all_tracks: set) -> None:
|
||||||
|
self._all_tracks = all_tracks
|
||||||
|
self._product.all_tracks = all_tracks
|
||||||
|
|
||||||
|
@property
|
||||||
|
def all_albums_with_tracks(self) -> list:
|
||||||
|
return self._all_albums_with_tracks
|
||||||
|
|
||||||
|
@all_albums_with_tracks.setter
|
||||||
|
def all_albums_with_tracks(self, all_albums_with_tracks: list) -> None:
|
||||||
|
self._all_albums_with_tracks = all_albums_with_tracks
|
||||||
|
self._product.all_albums_with_tracks = all_albums_with_tracks
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def set_useragent() -> None:
|
||||||
|
authenticate.set_useragent()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def browse_releases(
|
||||||
|
artist_id: str,
|
||||||
|
limit: int,
|
||||||
|
release_type: list,
|
||||||
|
offset: Union[int, None] = None,
|
||||||
|
includes: Union[List[str, None]] = list(),
|
||||||
|
) -> dict:
|
||||||
|
releases = musicbrainzngs.browse_releases(
|
||||||
|
artist=artist_id,
|
||||||
|
limit=limit,
|
||||||
|
release_type=release_type,
|
||||||
|
offset=offset,
|
||||||
|
includes=includes,
|
||||||
|
)
|
||||||
|
return releases
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_album_info_list(
|
||||||
|
album_info_list: list, album_tracker: set, releases: addict.Dict
|
||||||
|
) -> list:
|
||||||
|
for i in releases['release-list']:
|
||||||
|
_throwaway_dict = addict.Dict()
|
||||||
|
_throwaway_dict.album = i.title
|
||||||
|
_throwaway_dict.year = i.date.split('-')[0]
|
||||||
|
_throwaway_dict.tracks = [
|
||||||
|
j.recording.title for j in i['medium-list'][0]['track-list']
|
||||||
|
]
|
||||||
|
if i.title not in album_tracker:
|
||||||
|
album_tracker.add(i.title)
|
||||||
|
album_info_list.append(_throwaway_dict)
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
return album_info_list, album_tracker
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def paginate_results(
|
||||||
|
releases: addict.Dict, duplicated_tracks: list
|
||||||
|
) -> List:
|
||||||
|
tracks = [
|
||||||
|
j.recording.title
|
||||||
|
for i in releases['release-list']
|
||||||
|
for j in i['medium-list'][0]['track-list']
|
||||||
|
]
|
||||||
|
for i in itertools.chain(tracks):
|
||||||
|
duplicated_tracks.append(i)
|
||||||
|
return duplicated_tracks
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.reset()
|
self.reset()
|
||||||
|
|
||||||
@@ -159,95 +244,78 @@ class LyricsBuilder(LyricsConcreteBuilder):
|
|||||||
)
|
)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
@staticmethod
|
def do_search_albums(self) -> None:
|
||||||
def browse_releases(
|
album_info_list = list()
|
||||||
artist_id: str,
|
album_tracker = set()
|
||||||
limit: int,
|
duplicated_tracks = list()
|
||||||
release_type: list,
|
limit, offset, page = (100, 0, 1)
|
||||||
offset: Union[int, None] = None,
|
|
||||||
) -> dict:
|
raw_releases = self.browse_releases(
|
||||||
releases = musicbrainzngs.browse_releases(
|
artist_id=self.artist_id,
|
||||||
artist=artist_id,
|
|
||||||
limit=limit,
|
limit=limit,
|
||||||
release_type=release_type,
|
release_type=['album'],
|
||||||
offset=offset,
|
offset=offset,
|
||||||
includes=['recordings'],
|
includes=['recordings'],
|
||||||
)
|
)
|
||||||
return releases
|
|
||||||
|
|
||||||
@staticmethod
|
releases = addict.Dict(raw_releases)
|
||||||
def browse_recordings(
|
|
||||||
release: str, limit: int, offset: Union[int, None]
|
duplicated_tracks = self.paginate_results(releases, duplicated_tracks)
|
||||||
) -> dict:
|
|
||||||
recordings = musicbrainzngs.browse_recordings(
|
# Get album info list
|
||||||
release=release, limit=limit, offset=offset
|
album_info_list, album_tracker = self.get_album_info_list(
|
||||||
|
album_info_list, album_tracker, releases
|
||||||
)
|
)
|
||||||
return recordings
|
|
||||||
|
|
||||||
def do_search_albumns(self) -> None:
|
bar_count = len(releases['release-list'])
|
||||||
limit = 100
|
previous_bar_count = 0
|
||||||
offset = 0
|
|
||||||
page = 1
|
with PieSpinner(
|
||||||
self.releases_list = list()
|
f'Finding all tracks in all albums for {self.artist}'
|
||||||
releases = self.browse_releases(self.artist_id, limit, ['album'])
|
'from Musicbrainz '
|
||||||
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:
|
) as bar:
|
||||||
while len(self.releases_list) < total_releases_count:
|
while bar_count != previous_bar_count:
|
||||||
offset += limit
|
offset += limit
|
||||||
page += 1
|
page += 1
|
||||||
page_releases = self.browse_releases(
|
# Get next page
|
||||||
self.artist_id, limit, ['album'], offset
|
raw_page_releases = self.browse_releases(
|
||||||
|
artist_id=self.artist_id,
|
||||||
|
limit=limit,
|
||||||
|
release_type=['album'],
|
||||||
|
offset=offset,
|
||||||
|
includes=['recordings'],
|
||||||
)
|
)
|
||||||
page_releases_list = page_releases['release-list']
|
page_releases = addict.Dict(raw_page_releases)
|
||||||
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:
|
# Update list
|
||||||
# Get official albums only
|
duplicated_tracks = self.paginate_results(
|
||||||
_official_albums_list = list()
|
page_releases, duplicated_tracks
|
||||||
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:
|
# Update album info list
|
||||||
# No album is over 100 tracks so we don't need to iterate
|
(
|
||||||
limit = 100
|
album_info_list,
|
||||||
offset = 0
|
album_tracker,
|
||||||
recordings_list = list()
|
) = self.get_album_info_list(
|
||||||
self.recordings = dict()
|
album_info_list, album_tracker, releases
|
||||||
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(
|
previous_bar_count = bar_count
|
||||||
dict((i['id'], i['title']) for i in album_recordings_list)
|
bar_count += len(page_releases['release-list'])
|
||||||
)
|
bar.next()
|
||||||
bar.update(1)
|
total_releases_count = bar_count
|
||||||
for i in recordings_list:
|
|
||||||
self.recordings = {**self.recordings, **i}
|
tracks = set(duplicated_tracks)
|
||||||
# pprint(self.recordings)
|
|
||||||
click.echo(
|
click.echo(
|
||||||
f'Found {len(self.recordings)} tracks from '
|
f'Musicbrainz found {len(tracks)} unique tracks in '
|
||||||
f'{len(self.official_albums)} albums for {self.artist}'
|
f'{total_releases_count} releases for {self.artist}'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Set properties
|
||||||
|
self.all_tracks = tracks
|
||||||
|
self.all_albums_with_tracks = album_info_list
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
||||||
@@ -282,8 +350,8 @@ class LyricsClickDirector:
|
|||||||
if artist_meta == 'Multiple':
|
if artist_meta == 'Multiple':
|
||||||
_position = []
|
_position = []
|
||||||
click.echo(
|
click.echo(
|
||||||
f'Musicbrainz found several results for {self.builder.artist[0]}'
|
f'Musicbrainz found several results for '
|
||||||
'. Which artist/group do you want?',
|
f'{self.builder.artist[0]}. Which artist/group do you want?',
|
||||||
)
|
)
|
||||||
for i, j in zip(self.builder._top_five_results, range(1, 6)):
|
for i, j in zip(self.builder._top_five_results, range(1, 6)):
|
||||||
click.echo(
|
click.echo(
|
||||||
@@ -313,29 +381,29 @@ class LyricsClickDirector:
|
|||||||
)
|
)
|
||||||
raise SystemExit()
|
raise SystemExit()
|
||||||
|
|
||||||
|
def _search_for_all_tracks(self) -> None:
|
||||||
|
self.builder.do_search_albums()
|
||||||
|
pprint(self.builder._product.all_tracks)
|
||||||
|
# pprint(self.builder._product.all_albums_with_tracks)
|
||||||
|
|
||||||
def _set_artist_id_on_product(self) -> None:
|
def _set_artist_id_on_product(self) -> None:
|
||||||
self.builder.artist_id = self._artist_id
|
self.builder.artist_id = self._artist_id
|
||||||
self.builder.artist = self._artist
|
self.builder.artist = self._artist
|
||||||
# print(self.builder._product.artist_id)
|
|
||||||
# print(self.builder._product.artist)
|
|
||||||
# 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',
|
||||||
|
'country',
|
||||||
|
'all_tracks',
|
||||||
|
'all_albums_with_tracks',
|
||||||
|
]
|
||||||
artist_id: str
|
artist_id: str
|
||||||
artist: str
|
artist: str
|
||||||
|
country: Union[str, None]
|
||||||
|
all_tracks: set
|
||||||
if __name__ == '__main__':
|
all_albums_with_tracks: list
|
||||||
# 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))
|
|
||||||
|
|||||||
@@ -100,16 +100,16 @@ def cli(ctx, artist: str, country: Union[str, None]) -> None:
|
|||||||
"""
|
"""
|
||||||
Search for lyrics of an Artist/Group.
|
Search for lyrics of an Artist/Group.
|
||||||
"""
|
"""
|
||||||
print(artist)
|
# 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, country)
|
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()
|
director._search_for_all_tracks()
|
||||||
builder.do_filter_albums_official()
|
# builder.do_filter_albums_official()
|
||||||
builder.do_search_album_tracks()
|
# builder.do_search_album_tracks()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
Reference in New Issue
Block a user