Source code for lyricsfandom.meta

"""
Base classes. They are optional and can be removed for simplicity.
However, they provides a better API and sperates Artist / Album / Song in a better way.
"""

from abc import ABC, abstractmethod

from .connect import connect
import lyricsfandom.scrape as F
from .utils import name_to_wiki_id, name_to_wiki


[docs]class LyricWikiMeta(ABC): """ The ``LyricWikiMeta`` is an abstract class that all object pointing to `Lyric Wiki` web site should inherits. It provide basic set-up to connect and access to `Lyric Wiki` website. """ def __init__(self): self.base = f'https://lyrics.fandom.com' self.href = '/' @property def url(self): if self.href: return self.base + self.href return None @url.setter def url(self, value): raise AttributeError('Cannot modify an URL directly. Please modify it through `base` and `href` attributes.') def connect(self): return connect(self.url)
[docs]class ArtistMeta(LyricWikiMeta): """Defines an Abstract Artist / Band from ``https://lyrics.fandom.com/wiki/``. * :attr:`artist_name`: name of the artist. * :attr:`artist_id`: id of the artist. * :attr:`base`: base page of the artist. * :attr:`href`: href page of the artist. * :attr:`url`: url page of the artist. """ def __init__(self, artist_name): super().__init__() self.artist_name = name_to_wiki(artist_name) self.href = f'/wiki/{name_to_wiki_id(self.artist_name)}' if self.artist_name else None self._links = None self._items = []
[docs] @classmethod @abstractmethod def from_url(cls, url): """Construct an Artist from an url. Args: url (string): url of the artist page. """ raise NotImplementedError
[docs] def items(self): """Basic Set-up to iterate through items (albums, songs...). Returns: Album or Song """ for item in self._items: yield item
[docs] @abstractmethod def to_json(self, encode=None): """Retrieve the full discography from an artist; in a JSON format. Returns: dict """ raise NotImplementedError
def __repr__(self): return f"Artist: {self.artist_name}"
[docs]class AlbumMeta(ArtistMeta): """Defines an Abstract Album from ``https://lyrics.fandom.com/wiki/``. * :attr:`album_name`: album of the artist. * :attr:`album_type`: type of album. * :attr:`album_year`: released of the album. """ def __init__(self, artist_name, album_name, album_year=None, album_type=None): super().__init__(artist_name) self.album_name = name_to_wiki(album_name) if album_name else '' # self.album_id = name_to_wiki_id(self.album_name) self.album_year = album_year self.album_type = album_type href = None if self.artist_name and self.album_name and self.album_year: href = f'/wiki/{name_to_wiki_id(self.artist_name)}:{name_to_wiki_id(self.album_name)}_({self.album_year})' self.href = href self._artist = None
[docs] def get_artist(self): """Retrieve the artist class linked to the album (if it exists). It is usually called when an album has been searched from an ``Artist`` class. Then, using this function will point to the same ``Artist`` object. Returns: Artist """ return self._artist
[docs] def register_artist(self, artist): """Manually set the pointer to an ``Artist``. Args: artist (Artist): artist related to the album. """ self._artist = artist
[docs] def unregister(self): """Unlink the album to its artist.""" self._artist = None
[docs] @classmethod @abstractmethod def from_url(cls, url): """Construct an Album from an url. Args: url (string): url of the album page. """ raise NotImplementedError
[docs] @classmethod @abstractmethod def from_artist(cls, artist, album_name): """Construct an Artist from an url. Args: artist (Artist): artist to extract the album from. album_name (string): album name. """ raise NotImplementedError
[docs] @abstractmethod def to_json(self, encode=None): """Retrieve the full playlist from an album; in a JSON format. Returns: dict """ raise NotImplementedError
def __repr__(self): rep_type = f' {self.album_type}' if self.album_type else '' rep_year = f' ({self.album_year})' if self.album_year else '' rep_songs = f', Songs: {len(self._items)}' if len(self._items) > 0 else '' rep = f'{self.artist_name}:{rep_type} "{self.album_name}"{rep_year}' \ f'{rep_songs}' return rep
[docs]class SongMeta(AlbumMeta): """Defines an Abstract Song from ``https://lyrics.fandom.com/``. * :attr:`song_name`: name of the song. * :attr:`song_id`: id of the song. * :attr:`lyrics`: lyrics of the song. """ def __init__(self, artist_name, song_name, album_name=None, album_year=None, album_type=None): super().__init__(artist_name, album_name, album_year=album_year, album_type=album_type) self.song_name = name_to_wiki(song_name) # self.song_id = name_to_wiki_id(song_name) href = None if name_to_wiki_id(self.artist_name) and self.song_name: href = f"/wiki/{name_to_wiki_id(self.artist_name)}:{name_to_wiki_id(self.song_name)}" self.href = href self._album = None self._lyrics = None
[docs] def set_lyrics(self, value): """Manually set the lyrics of the current song. Args: value (string): new lyrics. """ self._lyrics = value
[docs] def get_album(self): """Get the parent album pointing to the song, if it exists. Returns: Album """ return self._album
[docs] def register_album(self, album): """Link the song to a parent album. Args: album (Album): album to link to the song. """ self._album = album
[docs] def unregister(self): """Unlink the song to both artist and album.""" self._artist = None self._album = None
[docs] @classmethod @abstractmethod def from_url(cls, url): """Construct a Song from an url. Args: url (string): url of the lyrics song page. """ raise NotImplementedError
[docs] @classmethod @abstractmethod def from_album(cls, album, song_name): """Construct a Song from an url. Args: album (Album): album to extract the song from. song_name (string): song name. """ raise NotImplementedError
[docs] @classmethod @abstractmethod def from_artist(cls, artist, song_name): """Construct an Artist from an url. Args: artist (Artist): artist to extract the album from. song_name (string): song name. """ raise NotImplementedError
[docs] @abstractmethod def to_json(self, encode=None): """Retrieve the full information / lyrics from a song; in a JSON format. Returns: dict """ raise NotImplementedError
def __repr__(self): rep_year = f' ({self.album_year})' if self.album_year else '' rep_type = f' {self.album_type}' if self.album_type else '' rep_album = f', from{rep_type} "{self.album_name}"' if self.album_name else '' return f'{self.artist_name}: "{self.song_name}"{rep_album}{rep_year}'