Merge branch 'develop'

This commit is contained in:
2020-03-09 01:31:16 +00:00
30 changed files with 337 additions and 15351 deletions

View File

@@ -1,10 +0,0 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.0.0] - 2020-03-07
### Added
- Initial version

21
CHANGELOG.rst Normal file
View File

@@ -0,0 +1,21 @@
Changelog
==========
All notable changes to this project will be documented in this file.
This format is based on `Keep a Changelog`_
.. _Keep a Changelog: https://keepachangelog.com/en/1.0.0/
and this project adheres to `Semantic Versioning`_
.. _Semantic Versioning: https://semver.org/spec/v2.0.0.html
[1.0.0] - 2020-03-07
------------------------
Added
######
- Initial version

View File

@@ -5,4 +5,4 @@ RUN mkdir /outputs && mkdir /inputs
COPY ./setup.py /inputs/setup.py COPY ./setup.py /inputs/setup.py
COPY ./src /inputs/src COPY ./src /inputs/src
RUN cd /inputs && python ./setup.py install && cd /outputs RUN cd /inputs && python ./setup.py install

View File

@@ -1,19 +1,128 @@
=============
Introduction
=============
.. image:: https://img.shields.io/readthedocs/panaetius?style=for-the-badge
.. image:: https://img.shields.io/github/v/tag/dtomlinson91/musicbrainzapi-cv-airelogic?style=for-the-badge
.. image:: https://img.shields.io/github/commit-activity/m/dtomlinson91/musicbrainzapi-cv-airelogic?style=for-the-badge
.. image:: https://img.shields.io/github/issues/dtomlinson91/musicbrainzapi-cv-airelogic?style=for-the-badge
.. image:: https://img.shields.io/github/license/dtomlinson91/musicbrainzapi-cv-airelogic?style=for-the-badge
.. image:: https://img.shields.io/github/languages/code-size/dtomlinson91/musicbrainzapi-cv-airelogic?style=for-the-badge
.. image:: https://img.shields.io/github/languages/top/dtomlinson91/musicbrainzapi-cv-airelogic?style=for-the-badge
.. image:: https://img.shields.io/requires/github/dtomlinson91/musicbrainzapi-cv-airelogic?style=for-the-badge
Summary
========
Musicbrainzapi is a Python module with a CLI that allows you to search for an artist and receive summary statistics on lyrics across all albums + tracks.
In addition to basic statistics the module further allows you to save details of an artist. You can save album information, the lyrics themselves and track lists.
The module (currently) provides a simple CLI with some underlying assumptions:
- We are interested in albums only - no singles.
- We are interested in any album where the artist is listed as a primary artist on a release. This could include compilations or joint albums with other artists.
- Where an album has been released multiple times, in different regions, we take the album with the longest track list.
These assumptions are not configurable in the current version - but this functionality could be added to the module if needed.
Further information, and a brief summary of decisions taken and current caveats can be found in the documentation which is linked below.
Documentation
=============
The documentation for the module can be found at https://musicbrainzapi-cv-airelogic.readthedocs.io/en/latest/
Installation
============
You will need ``python>=3.7``. Installation to a python virtual environment is recommended.
PIP
---
Download the latest release ``.whl`` file from the `releases`_ page
.. _releases: https://github.com/dtomlinson91/musicbrainzapi-cv-airelogic/releases
In a virtual environment run:
.. code-block:: bash
pip install -U musicbrainzapi.whl
Replacing ``musicbrainzapi.whl`` with the filename you downloaded.
setup.py
--------
Clone the repo:
.. code-block:: bash
git clone https://github.com/dtomlinson91/musicbrainzapi-cv-airelogic.git
In the root of the repo in a virtual environment run:
.. code-block:: bash
python ./setup.py install
Docker
------
.. note:: Using Docker will mean you cannot view a wordcloud, as the default behaviour is to show the plot interactively which the container cannot do.
If you don't have ``python>=3.7`` installed, or would rather use Docker, you can build a Docker image and run the module using Docker.
Clone the repo:
.. code-block:: bash
git clone https://github.com/dtomlinson91/musicbrainzapi-cv-airelogic.git
In the root of the repo build the Docker image:
.. code-block:: bash
docker build . -t musicbrainzapi
No entrypoint is provided in the ``Dockerfile`` - you will have to specify the command at runtime and run the container in interactive mode:
Using Docker run
^^^^^^^^^^^^^^^^
.. code-block:: bash
docker run --rm -it --volume=$(pwd):/outputs \
musicbrainzapi:latest musicbrainzapi --path /outputs \
lyrics -a "Savage Garden" -c gb --show-summary all --save-output
Usage
=====
Once installed you can access the command running:
.. code-block:: bash
musicbrainzapi musicbrainzapi
===============
.. image:: https://img.shields.io/readthedocs/panaetius?style=for-the-badge :target: https://panaetius.readthedocs.io/en/latest/?badge=latest To see all options available you can run:
:alt: Documentation Status
.. image:: https://img.shields.io/github/v/tag/dtomlinson91/musicbrainzapi-cv-airelogic?style=for-the-badge :alt: GitHub tag (latest by date) .. code-block:: bash
.. image:: https://img.shields.io/github/commit-activity/m/dtomlinson91/musicbrainzapi-cv-airelogic?style=for-the-badge :alt: GitHub commit activity musicbrainzapi --help
.. image:: https://img.shields.io/github/issues/dtomlinson91/musicbrainzapi-cv-airelogic?style=for-the-badge :alt: GitHub issues In the current release there is one command available ``lyrics``:
.. image:: https://img.shields.io/github/license/dtomlinson91/musicbrainzapi-cv-airelogic?style=for-the-badge :alt: GitHubtbc .. code-block:: bash
.. image:: https://img.shields.io/github/languages/code-size/dtomlinson91/musicbrainzapi-cv-airelogic?style=for-the-badge :alt: GitHub code size in bytes musicbrainzapi lyrics --help
.. image:: https://img.shields.io/github/languages/top/dtomlinson91/musicbrainzapi-cv-airelogic?style=for-the-badge :alt: GitHub top language License information
===================
.. image:: https://img.shields.io/requires/github/dtomlinson91/musicbrainzapi-cv-airelogic?style=for-the-badge :alt: Requires.io Released under the `MIT License`_
.. _MIT License: https://github.com/dtomlinson91/musicbrainzapi-cv-airelogic/blob/master/LICENSE

48
docs/source/CLI.rst Normal file
View File

@@ -0,0 +1,48 @@
***
CLI
***
As the CLI is provided by `Click`_ , you can pass the ``--help`` option to the base command, or any subcommands, to see information on usage and all available options.
.. _Click: https://click.palletsprojects.com/en/7.x/
Full options of the CLI are provided on this page.
.. important:: The ``--path`` option should be provided to the base command. This is so the path provided can be used in all subcommands.
Quickstart
==========
If you want to see everything the module offers run the following:
.. code-block:: bash
musicbrainzapi --path . lyrics -a "savage garden" -c gb --show-summary all --wordcloud --save-output
This will search for all tracks across all albums for the artist Savage Garden.
``--show-summary all`` will show descriptive statistics for both albums and years for this artist.
``--wordcloud`` will generate a wordcloud showing the most popular words across all lyrics.
``--save-output`` will save the module's output to disk as ``.json`` files.
Outputs
=======
The following files will be saved to disk
- all_albums_lyrics_sum.json - Total number of words in a track for each album.
- year_statistics.json - Descriptive statistics by year.
- album_statistics.json - Descriptive statistics by album
- all_albums_with_tracks.json - Track titles for each album.
- all_albums_with_lyrics.json - Lyrics for each track for each album.
- all_albums_lyrics_count.json - Shows a frequency count of each word in every track.
CLI Documentation
=================
.. click:: musicbrainzapi.cli.cli:cli
:prog: musicbrainzapi
:show-nested:

View File

@@ -1,87 +1,5 @@
@import url("css/theme.css"); @import url("css/theme.css");
.modname { .highlight {
font-size: 0.8em; background: white !important
opacity: 0.4;
}
.modname::before {
content: '- ';
}
.title {
font-weight: bold;
font-size: 1.2em;
background-color: #eee;
display: block;
padding: 1px 5px;
border-left: 2px solid #ddd;
}
/*colour of the text in the toc*/
.wy-menu-vertical header, .wy-menu-vertical p.caption{
color: #b26d46;;
}
/*colour of the top left header*/
.wy-side-nav-search{
background-color: #31465a;
}
/*colours of the class definitions*/
.rst-content dl:not(.docutils) dt{
background: #e2d7d1;
color: #0b2852;
border-top: solid 3px #31465a;
}
/*colour of the link in the class defintions*/
.rst-content .viewcode-link, .rst-content .viewcode-back{
color: #4b674a;
}
/*colour of the function definitions*/
.rst-content dl:not(.docutils) dl dt{
border-left: solid 3px #31465a;
background: #e2d7d1;
color: #0b2852;
}
/*colour of the link in the function definitions*/
.rst-content .viewcode-link, .rst-content .viewcode-back{
color: #4b674a;
}
/*edit the width of the body*/
.wy-nav-content{
max-width: 1200px;
}
/*code example blocks*/
.rst-content pre.literal-block, .rst-content div[class^="highlight"] pre, .rst-content .linenodiv pre{
background: #b4bec8;
color: black;
/*border-style: solid;*/
/*border-width: thin;*/
}
/*colour of inline code blocks using ``*/
.rst-content tt.literal, .rst-content tt.literal, .rst-content code.literal{
color: #b26d46;
}
/* Change code blocks font and bump up font size slightly (normally 12px)*/
.rst-content pre.literal-block, .rst-content div[class^="highlight"] pre, .rst-content .linenodiv pre {
font-family: 'Inconsolata', monospace !important;
font-size: 14px !important;
white-space: pre-wrap;
}
/* Change code descriptions and literal blocks (inline code via ``) to match the normal font size being used in the sphinx_RTD_theme text (normally 14px)*/
.rst-content dl:not(.docutils) tt.descname,.rst-content dl:not(.docutils) tt.descclassname,.rst-content dl:not(.docutils) tt.descname,.rst-content dl:not(.docutils) code.descname,.rst-content dl:not(.docutils) tt.descclassname,.rst-content dl:not(.docutils) code.descclassname, code.docutils {
font-family: 'Inconsolata', monospace !important;
font-size: 14px !important;
}
/*variables text*/
dl.class > dd > table.docutils.field-list tbody tr.field-odd.field th.field-name::before{
content: '(Class Attributes) ';
} }

View File

@@ -1,20 +1 @@
Changelog .. include:: ../../CHANGELOG.rst
==========
All notable changes to this project will be documented in this file.
The format is based on `Keep a Changelog`_
.. _https://keepachangelog.com/en/1.0.0/
and this project adheres to `Semantic Versioning`_
.. _https://semver.org/spec/v2.0.0.html
[1.0.0] - 2020-03-07
------------------------
Added
######
- Initial version

View File

@@ -39,6 +39,8 @@ extensions = [
'sphinx.ext.napoleon', 'sphinx.ext.napoleon',
'sphinx.ext.todo', 'sphinx.ext.todo',
'sphinx_click.ext', 'sphinx_click.ext',
'sphinx.ext.intersphinx',
'sphinx.ext.autosectionlabel'
] ]
# -- Napoleon Settings ----------------------------------------------------- # -- Napoleon Settings -----------------------------------------------------
@@ -60,7 +62,7 @@ autodoc_member_order = 'bysource'
templates_path = ['_templates'] templates_path = ['_templates']
# The master toctree document. # The master toctree document.
master_doc = 'introduction' master_doc = 'index'
# List of patterns, relative to source directory, that match files and # List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files. # directories to ignore when looking for source files.
@@ -82,11 +84,12 @@ html_theme = "sphinx_rtd_theme"
html_theme = "sphinx_rtd_theme" html_theme = "sphinx_rtd_theme"
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
html_static_path = ['_static'] html_static_path = ['_static']
# html_context = {'css_files': ['_static/custom.css']} html_context = {'css_files': ['_static/custom.css']}
html_theme_options = { html_theme_options = {
'collapse_navigation': True, 'collapse_navigation': True,
'display_version': True, 'display_version': True,
'prev_next_buttons_location': 'both', 'prev_next_buttons_location': 'both',
'navigation_depth': -1,
#'navigation_depth': 3, #'navigation_depth': 3,
} }

View File

@@ -1,3 +1,29 @@
*****************
Table of Contents Table of Contents
================= *****************
.. include:: toc.rst
.. toctree::
:maxdepth: 2
:caption: Contents
introduction
CLI
changelog
.. toctree::
:caption: API
:maxdepth: 2
modules/modules
.. toctree::
:caption: Table of Contents
self
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

View File

@@ -1 +1 @@
.. include:: ../../toc.rst .. include:: ../../README.rst

View File

@@ -0,0 +1,7 @@
musicbrainzapi
--------------
.. toctree::
:maxdepth: 3
musicbrainzapi

View File

@@ -1,10 +0,0 @@
.. include:: ../global.rst
musicbrainzapi.api.authenticate :modname:`musicbrainzapi.api.authenticate module`
------------------------------------------------------------------------------------------
.. automodule:: musicbrainzapi.api.authenticate
:members:
:undoc-members:
:show-inheritance:
:private-members:

View File

@@ -1,10 +0,0 @@
.. include:: ../global.rst
musicbrainzapi.api.lyrics.builder :modname:`musicbrainzapi.api.lyrics.builder`
-------------------------------------------------------------------------------
.. automodule:: musicbrainzapi.api.lyrics.builder
:members:
:undoc-members:
:show-inheritance:
:private-members:

View File

@@ -1,10 +0,0 @@
.. include:: ../global.rst
musicbrainzapi.api.lyrics.concrete_builder :modname:`musicbrainzapi.api.lyrics.concrete_builder`
-------------------------------------------------------------------------------------------------
.. automodule:: musicbrainzapi.api.lyrics.concrete_builder
:members:
:undoc-members:
:show-inheritance:
:private-members:

View File

@@ -1,10 +0,0 @@
.. include:: ../global.rst
musicbrainzapi.api.lyrics.director :modname:`musicbrainzapi.api.lyrics.director`
----------------------------------------------------------------------------------
.. automodule:: musicbrainzapi.api.lyrics.director
:members:
:undoc-members:
:show-inheritance:
:private-members:

View File

@@ -1,7 +1,5 @@
.. include:: ../global.rst musicbrainzapi.api.lyrics package
=================================
musicbrainzapi.api.lyrics :modname:`musicbrainzapi.api.lyrics`
--------------------------------------------------------------------------
.. automodule:: musicbrainzapi.api.lyrics .. automodule:: musicbrainzapi.api.lyrics
:members: :members:
@@ -9,8 +7,32 @@ musicbrainzapi.api.lyrics :modname:`musicbrainzapi.api.lyrics`
:show-inheritance: :show-inheritance:
:private-members: :private-members:
.. toctree:: Submodules
----------
musicbrainzapi.api.lyrics.builder musicbrainzapi.api.lyrics.builder module
musicbrainzapi.api.lyrics.concrete_builder ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
musicbrainzapi.api.lyrics.director
.. automodule:: musicbrainzapi.api.lyrics.builder
:members:
:undoc-members:
:show-inheritance:
:private-members:
musicbrainzapi.api.lyrics.concrete_builder module
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. automodule:: musicbrainzapi.api.lyrics.concrete_builder
:members:
:undoc-members:
:show-inheritance:
:private-members:
musicbrainzapi.api.lyrics.director module
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. automodule:: musicbrainzapi.api.lyrics.director
:members:
:undoc-members:
:show-inheritance:
:private-members:

View File

@@ -1,7 +1,5 @@
.. include:: ../global.rst musicbrainzapi.api package
===========================
musicbrainzapi.api :modname:`musicbrainzapi.api`
--------------------------------------------------------------------------
.. automodule:: musicbrainzapi.api .. automodule:: musicbrainzapi.api
:members: :members:
@@ -9,11 +7,22 @@ musicbrainzapi.api :modname:`musicbrainzapi.api`
:show-inheritance: :show-inheritance:
:private-members: :private-members:
Subpackages
-----------
.. toctree:: .. toctree::
:maxdepth: 1
musicbrainzapi.api.lyrics musicbrainzapi.api.lyrics
.. toctree:: Submodules
----------
musicbrainzapi.api.authenticate musicbrainzapi.api.authenticate module
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. automodule:: musicbrainzapi.api.authenticate
:members:
:undoc-members:
:show-inheritance:
:private-members:

View File

@@ -1,10 +0,0 @@
.. include:: ../global.rst
musicbrainzapi.cli.cli :modname:`musicbrainzapi.cli.cli`
--------------------------------------------------------------------------
.. automodule:: musicbrainzapi.cli.cli
:members:
:undoc-members:
:show-inheritance:
:private-members:

View File

@@ -1,16 +0,0 @@
.. include:: ../global.rst
musicbrainzapi.cli.commands.cmd_lyrics :modname:`musicbrainzapi.cli.commands.cmd_lyrics`
------------------------------------------------------------------------------------------
.. automodule:: musicbrainzapi.cli.commands.cmd_lyrics
:members:
:undoc-members:
:show-inheritance:
:private-members:
lyrics subcommand. Use with...
.. click:: musicbrainzapi.cli.cli:cli
:prog: musicbrainzapi
:show-nested:

View File

@@ -1,14 +0,0 @@
.. include:: ../global.rst
musicbrainzapi.cli.commands :modname:`musicbrainzapi.cli.commands`
--------------------------------------------------------------------------
.. automodule:: musicbrainzapi.cli.commands
:members:
:undoc-members:
:show-inheritance:
:private-members:
.. toctree::
musicbrainzapi.cli.commands.cmd_lyrics

View File

@@ -1,18 +0,0 @@
.. include:: ../global.rst
musicbrainzapi.cli :modname:`musicbrainzapi.cli`
--------------------------------------------------------------------------
.. automodule:: musicbrainzapi.cli
:members:
:undoc-members:
:show-inheritance:
:private-members:
.. toctree::
musicbrainzapi.cli.commands
.. toctree::
musicbrainzapi.cli.cli

View File

@@ -1,7 +1,5 @@
.. include:: ../global.rst musicbrainzapi
===============
musicbrainzapi :modname:`musicbrainzapi`
-----------------------------------------
.. automodule:: musicbrainzapi .. automodule:: musicbrainzapi
:members: :members:
@@ -9,4 +7,13 @@ musicbrainzapi :modname:`musicbrainzapi`
:show-inheritance: :show-inheritance:
:private-members: :private-members:
Main module text
Subpackages
-----------
.. toctree::
:maxdepth: 1
musicbrainzapi.api
musicbrainzapi.wordcloud

View File

@@ -1,10 +0,0 @@
.. include:: ../global.rst
musicbrainzapi.wordcloud.resources :modname:`musicbrainzapi.wordcloud.resources`
---------------------------------------------------------------------------------
.. automodule:: musicbrainzapi.wordcloud.resources
:members:
:undoc-members:
:show-inheritance:
:private-members:

View File

@@ -1,14 +1,9 @@
.. include:: ../global.rst ********************************
musicbrainzapi.wordcloud package
musicbrainzapi.wordcloud :modname:`musicbrainzapi.wordcloud` ********************************
--------------------------------------------------------------------------
.. automodule:: musicbrainzapi.wordcloud .. automodule:: musicbrainzapi.wordcloud
:members: :members:
:undoc-members: :undoc-members:
:show-inheritance: :show-inheritance:
:private-members: :private-members:
.. toctree::
musicbrainzapi.wordcloud.resources

View File

@@ -1,23 +0,0 @@
.. toctree::
:maxdepth: 1
:caption: Overview
:titlesonly:
introduction
changelog
.. toctree::
:maxdepth: 4
:caption: Modules
:titlesonly:
modules/musicbrainzapi.rst
.. toctree::
:maxdepth: 4
:caption: Submodules
:titlesonly:
modules/musicbrainzapi.api.rst
modules/musicbrainzapi.cli.rst
modules/musicbrainzapi.wordcloud.rst

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,7 @@
"""
musicbrainzapi: A CLI lyrics searcher
=====================================
This module was written by dtomlinson <dtomlinson@panaetius.co.uk> for Aire Logic
"""

View File

@@ -9,12 +9,27 @@ from musicbrainzapi.api.lyrics import Lyrics
class LyricsClickDirector: class LyricsClickDirector:
"""Director for Lyrics builder. """Director for Lyrics builder."""
"""
def __init__(self) -> None: def __init__(self) -> None:
self._builder = None self._builder = None
@staticmethod
def _get_product(builder_inst: LyricsBuilder) -> Lyrics:
"""Returns the constructed Lyrics object
Parameters
----------
builder_inst : LyricsBuilder
Builder class for Lyrics object
Returns
-------
Lyrics
Lyrics object
"""
return builder_inst._product
@property @property
def builder(self) -> LyricsBuilder: def builder(self) -> LyricsBuilder:
return self._builder return self._builder
@@ -156,19 +171,3 @@ class LyricsClickDirector:
self.builder._product.show_summary() self.builder._product.show_summary()
self.builder._product.show_summary_statistics(group_by='year') self.builder._product.show_summary_statistics(group_by='year')
return self return self
@staticmethod
def _get_product(builder_inst: LyricsBuilder) -> Lyrics:
"""Returns the constructed Lyrics object
Parameters
----------
builder_inst : LyricsBuilder
Builder class for Lyrics object
Returns
-------
Lyrics
Lyrics object
"""
return builder_inst._product

View File

@@ -42,7 +42,7 @@ class ComplexCLI(click.MultiCommand):
type=click.Path( type=click.Path(
exists=True, file_okay=False, resolve_path=True, writable=True exists=True, file_okay=False, resolve_path=True, writable=True
), ),
help='Path to save results.', help='Local path to save any output files.',
default=os.getcwd() default=os.getcwd()
) )
# @click.option('-v', '--verbose', is_flag=True, help='Enables verbose mode.') # @click.option('-v', '--verbose', is_flag=True, help='Enables verbose mode.')
@@ -53,7 +53,7 @@ class ComplexCLI(click.MultiCommand):
) )
@pass_environment @pass_environment
def cli(ctx, path): def cli(ctx, path):
"""A complex command line interface.""" """Base command for the musicbrainzapi program."""
# ctx.verbose = verbose # ctx.verbose = verbose
if path is not None: if path is not None:
click.echo(f'Path set to {os.path.expanduser(path)}') click.echo(f'Path set to {os.path.expanduser(path)}')

View File

@@ -24,7 +24,7 @@ from musicbrainzapi.api.lyrics.director import LyricsClickDirector
@click.option( @click.option(
'--wordcloud', '--wordcloud',
required=False, required=False,
help='Generate a wordcloud from lyrics.', help='Generates a wordcloud from lyrics.',
is_flag=True, is_flag=True,
default=False, default=False,
) )
@@ -41,7 +41,7 @@ from musicbrainzapi.api.lyrics.director import LyricsClickDirector
required=False, required=False,
multiple=False, multiple=False,
type=str, type=str,
help='ISO A-2 Country code (https://en.wikipedia.org/wiki/ISO_3166-1_alpha' help='Filter artist by country. This is optional but can narrow down a search if many artists share the same or similar names. Country must be a ISO A-2 Country code (https://en.wikipedia.org/wiki/ISO_3166-1_alpha'
'-2) Example: GB', '-2) Example: GB',
) )
@click.option( @click.option(
@@ -63,7 +63,7 @@ def lyrics(
wordcloud: bool, wordcloud: bool,
save_output: bool, save_output: bool,
) -> None: ) -> None:
"""Search for lyrics statistics of an Artist/Group. """Search for lyrics statistics of an Artist/Group. Optionally save the results to disk, and show a wordcloud. Descriptive statistics can be shown in addition to the final average.
""" """
director = LyricsClickDirector() director = LyricsClickDirector()
builder = LyricsBuilder() builder = LyricsBuilder()
@@ -78,7 +78,6 @@ def lyrics(
director._query_for_data() director._query_for_data()
director._get_lyrics() director._get_lyrics()
director._calculate_basic_statistics() director._calculate_basic_statistics()
if show_summary is not None:
director._calculate_descriptive_statistics() director._calculate_descriptive_statistics()
# Get the Lyrics object # Get the Lyrics object