Compare commits
8 Commits
documentat
...
develop
| Author | SHA1 | Date | |
|---|---|---|---|
| 511986a131 | |||
| 8dc88f6361 | |||
| 0a77fa34fd | |||
| 0034340d63 | |||
| 02cb79c4b2 | |||
| 26b346d359 | |||
| 78544673b4 | |||
| e8ce4b59f8 |
21
README.rst
21
README.rst
@@ -70,6 +70,27 @@ In the root of the repo in a virtual environment run:
|
|||||||
|
|
||||||
python ./setup.py install
|
python ./setup.py install
|
||||||
|
|
||||||
|
poetry
|
||||||
|
------
|
||||||
|
|
||||||
|
Clone the repo:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
git clone https://github.com/dtomlinson91/musicbrainzapi-cv-airelogic.git
|
||||||
|
|
||||||
|
In a virtual environment install poetry:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
pip install poetry
|
||||||
|
|
||||||
|
In the root of the repo in a virtual environment run:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
poetry install --no-dev
|
||||||
|
|
||||||
Docker
|
Docker
|
||||||
------
|
------
|
||||||
|
|
||||||
|
|||||||
@@ -115,3 +115,12 @@ Although inelegant, and not guaranteed to capture the specific behaviour we want
|
|||||||
|
|
||||||
Musicbrainz provides a schema for their api. If this were to be placed in a production environment then readdressing this should be a priority - we should be checking the values returned, using the schema as a guide, and replacing missing values accordingly. We should not rely on ``try except`` blocks to do this as it can be unreliable and is prone to raise other errors.
|
Musicbrainz provides a schema for their api. If this were to be placed in a production environment then readdressing this should be a priority - we should be checking the values returned, using the schema as a guide, and replacing missing values accordingly. We should not rely on ``try except`` blocks to do this as it can be unreliable and is prone to raise other errors.
|
||||||
|
|
||||||
|
Further statistical analysis
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
Standard descriptive statistics are provided. I did consider including a more deeper analysis but opted not to for several reasons:
|
||||||
|
|
||||||
|
- Without a specific problem or question to answer - explorative work can take a lot of time and may not yield satisfactory results. Questions I did consider are:
|
||||||
|
|
||||||
|
+ `For active artists, based on their previous lyrics count what is the predicition of their next album?` Although a sensible question I'm not sure how useful the predicition would be - I am sure for some artists they would follow a pattern over time, but I'm not convinced all artists would and I imagine the results would be mixed.
|
||||||
|
+ `Anomaly detection - for artists with large releases, what albums stood out as larger than usual and what feature (or track) caused this anomaly?` - This would be a good question to answer and we have many tools available. As we have numeric data - clustering could be a candidate (DBSCAN or even K-MEANS). I opted not to because of time and the fact it would bloat the requirements up. Feature flags are an option when handling extra packages, ``pip install musicbrainzapi[analysis]`` for example, but nonetheless this would be an interesting question to answer and I beleive one of the easier ones to implement if it was desired.
|
||||||
|
|||||||
@@ -6,55 +6,64 @@ import click
|
|||||||
from musicbrainzapi.__version__ import __version__
|
from musicbrainzapi.__version__ import __version__
|
||||||
from musicbrainzapi.__header__ import __header__
|
from musicbrainzapi.__header__ import __header__
|
||||||
|
|
||||||
CONTEXT_SETTINGS = dict(auto_envvar_prefix='COMPLEX')
|
# pylint:disable=invalid-name
|
||||||
|
|
||||||
|
CONTEXT_SETTINGS = dict(auto_envvar_prefix="COMPLEX")
|
||||||
|
|
||||||
|
|
||||||
class Environment(object):
|
class Environment:
|
||||||
|
"""Environment class to house shared parameters between all subcommands."""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.verbose = False
|
self.verbose = False
|
||||||
self.home = os.getcwd()
|
self.home = os.getcwd()
|
||||||
|
|
||||||
|
|
||||||
pass_environment = click.make_pass_decorator(Environment, ensure=True)
|
pass_environment = click.make_pass_decorator(
|
||||||
|
Environment, ensure=True
|
||||||
|
)
|
||||||
cmd_folder = os.path.abspath(
|
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):
|
||||||
|
"""Access and run subcommands."""
|
||||||
|
|
||||||
def list_commands(self, ctx):
|
def list_commands(self, ctx):
|
||||||
rv = []
|
"""List all subcommands."""
|
||||||
for filename in os.listdir(cmd_folder):
|
rv = [
|
||||||
if filename.endswith('.py') and filename.startswith('cmd_'):
|
filename[4:-3]
|
||||||
rv.append(filename[4:-3])
|
for filename in os.listdir(cmd_folder)
|
||||||
|
if filename.endswith(".py") and filename.startswith("cmd_")
|
||||||
|
]
|
||||||
rv.sort()
|
rv.sort()
|
||||||
return rv
|
return rv
|
||||||
|
|
||||||
def get_command(self, ctx, cmd_name):
|
def get_command(self, ctx, cmd_name):
|
||||||
mod = import_module(f'musicbrainzapi.cli.commands.cmd_{cmd_name}')
|
"""Get chosen subcummands."""
|
||||||
|
mod = import_module(f"musicbrainzapi.cli.commands.cmd_{cmd_name}")
|
||||||
return getattr(mod, cmd_name)
|
return getattr(mod, cmd_name)
|
||||||
|
|
||||||
|
|
||||||
@click.command(cls=ComplexCLI, context_settings=CONTEXT_SETTINGS)
|
@click.command(cls=ComplexCLI, context_settings=CONTEXT_SETTINGS)
|
||||||
@click.option(
|
@click.option(
|
||||||
'-p',
|
"-p",
|
||||||
'--path',
|
"--path",
|
||||||
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="Local path to save any output files.",
|
||||||
),
|
default=os.getcwd(),
|
||||||
help='Local path to save any output files.',
|
|
||||||
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.")
|
||||||
@click.version_option(
|
@click.version_option(
|
||||||
version=__version__,
|
version=__version__,
|
||||||
prog_name=__header__,
|
prog_name=__header__,
|
||||||
message=f'{__header__} version {__version__} 🎤',
|
message=f"{__header__} version {__version__} 🎤",
|
||||||
)
|
)
|
||||||
@pass_environment
|
@pass_environment
|
||||||
def cli(ctx, path):
|
def cli(ctx, verbose, path):
|
||||||
"""Base command for the musicbrainzapi program."""
|
"""Display 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)}")
|
||||||
ctx.path = os.path.expanduser(path)
|
ctx.path = os.path.expanduser(path)
|
||||||
|
|||||||
BIN
src/musicbrainzapi/wordcloud/resources/.DS_Store
vendored
BIN
src/musicbrainzapi/wordcloud/resources/.DS_Store
vendored
Binary file not shown.
Reference in New Issue
Block a user