improved env loading
This commit is contained in:
parent
7c82226ff9
commit
41a21671ca
101
groove/cli.py
101
groove/cli.py
|
@ -1,21 +1,36 @@
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
import typer
|
import typer
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
from textwrap import dedent
|
||||||
|
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
|
from rich import print
|
||||||
from rich.logging import RichHandler
|
from rich.logging import RichHandler
|
||||||
|
|
||||||
|
import groove.path
|
||||||
|
|
||||||
from groove.shell import interactive_shell
|
from groove.shell import interactive_shell
|
||||||
from groove.db.manager import database_manager
|
from groove.db.manager import database_manager
|
||||||
from groove.webserver import webserver
|
from groove.webserver import webserver
|
||||||
|
from groove.exceptions import ConfigurationError
|
||||||
|
from groove.console import Console
|
||||||
|
|
||||||
app = typer.Typer()
|
app = typer.Typer()
|
||||||
|
|
||||||
|
|
||||||
def initialize():
|
@app.callback()
|
||||||
load_dotenv()
|
def main(
|
||||||
|
context: typer.Context,
|
||||||
|
env: Optional[Path] = typer.Option(
|
||||||
|
Path('~/.groove'),
|
||||||
|
help="Path to the Groove on Demand environment",
|
||||||
|
)
|
||||||
|
):
|
||||||
|
load_dotenv(env.expanduser())
|
||||||
debug = os.getenv('DEBUG', None)
|
debug = os.getenv('DEBUG', None)
|
||||||
logging.basicConfig(
|
logging.basicConfig(
|
||||||
format='%(message)s',
|
format='%(message)s',
|
||||||
|
@ -26,13 +41,76 @@ def initialize():
|
||||||
)
|
)
|
||||||
logging.getLogger('asyncio').setLevel(logging.ERROR)
|
logging.getLogger('asyncio').setLevel(logging.ERROR)
|
||||||
|
|
||||||
|
try:
|
||||||
|
groove.path.media_root()
|
||||||
|
groove.path.static_root()
|
||||||
|
groove.path.themes_root()
|
||||||
|
groove.path.database()
|
||||||
|
except ConfigurationError as e:
|
||||||
|
sys.stderr.write(f'{e}\n')
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
@app.command()
|
@app.command()
|
||||||
def list():
|
def setup(context: typer.Context):
|
||||||
"""
|
"""
|
||||||
List all Playlists
|
(Re)Initialize Groove on Demand.
|
||||||
|
"""
|
||||||
|
print(dedent(
|
||||||
|
"""
|
||||||
|
Interactive setup is not yet available. Sorry!
|
||||||
|
|
||||||
|
In the mean time, please make sure you set MEDIA_ROOT and SECRET_KEY
|
||||||
|
in your environment. By default, Groove on Demand will attempt to load
|
||||||
|
these variables from ~/.groove, which may contain the following
|
||||||
|
variables as well. See also the --env paramter.
|
||||||
|
|
||||||
|
# Set this one. The path containing your media files
|
||||||
|
MEDIA_ROOT=
|
||||||
|
|
||||||
|
# the kinds of files to import
|
||||||
|
# MEDIA_GLOB=*.mp3,*.flac,*.m4a
|
||||||
|
|
||||||
|
# where to store the groove_on_demand.db sqlite database.
|
||||||
|
# DATABASE_PATH=~
|
||||||
|
|
||||||
|
# Try 'groove themes' to see a list of available themes.
|
||||||
|
# DEFAULT_THEME=blue_train
|
||||||
|
|
||||||
|
# Web interface configuration
|
||||||
|
# HOST=127.0.0.1
|
||||||
|
# PORT=2323
|
||||||
|
|
||||||
|
# Set this to a suitably random string.
|
||||||
|
SECRET_KEY=much secret very private
|
||||||
|
|
||||||
|
# Console configuration
|
||||||
|
# EDITOR=
|
||||||
|
# CONSOLE_WIDTH=auto
|
||||||
|
"""
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
|
@app.command()
|
||||||
|
def themes(context: typer.Context):
|
||||||
|
"""
|
||||||
|
List the available themes.
|
||||||
|
"""
|
||||||
|
print("Available themes:")
|
||||||
|
themes = [theme for theme in groove.path.themes_root().iterdir()]
|
||||||
|
tags = ('artist', 'title', 'bold', 'dim', 'link', 'prompt', 'bright', 'text', 'help')
|
||||||
|
for theme in themes:
|
||||||
|
text = ''
|
||||||
|
for tag in tags:
|
||||||
|
text += f'[{tag}]◼◼◼◼◼◼'
|
||||||
|
Console(theme=theme.name).print(f' ▪ [title]{theme.name}[/title] {text}')
|
||||||
|
|
||||||
|
|
||||||
|
@app.command()
|
||||||
|
def playlists(context: typer.Context):
|
||||||
|
"""
|
||||||
|
List all playlists
|
||||||
"""
|
"""
|
||||||
initialize()
|
|
||||||
with database_manager() as manager:
|
with database_manager() as manager:
|
||||||
shell = interactive_shell.InteractiveShell(manager)
|
shell = interactive_shell.InteractiveShell(manager)
|
||||||
shell.list(None)
|
shell.list(None)
|
||||||
|
@ -40,6 +118,7 @@ def list():
|
||||||
|
|
||||||
@app.command()
|
@app.command()
|
||||||
def scan(
|
def scan(
|
||||||
|
context: typer.Context,
|
||||||
path: Optional[Path] = typer.Option(
|
path: Optional[Path] = typer.Option(
|
||||||
'',
|
'',
|
||||||
help="A path to scan, relative to your MEDIA_ROOT. "
|
help="A path to scan, relative to your MEDIA_ROOT. "
|
||||||
|
@ -49,7 +128,6 @@ def scan(
|
||||||
"""
|
"""
|
||||||
Scan the filesystem and create track entries in the database.
|
Scan the filesystem and create track entries in the database.
|
||||||
"""
|
"""
|
||||||
initialize()
|
|
||||||
with database_manager() as manager:
|
with database_manager() as manager:
|
||||||
shell = interactive_shell.InteractiveShell(manager)
|
shell = interactive_shell.InteractiveShell(manager)
|
||||||
shell.console.print("Starting the Groove on Demand scanner...")
|
shell.console.print("Starting the Groove on Demand scanner...")
|
||||||
|
@ -57,13 +135,17 @@ def scan(
|
||||||
|
|
||||||
|
|
||||||
@app.command()
|
@app.command()
|
||||||
def shell():
|
def shell(context: typer.Context):
|
||||||
initialize()
|
"""
|
||||||
interactive_shell.start()
|
Start the Groove on Demand interactive shell.
|
||||||
|
"""
|
||||||
|
with database_manager() as manager:
|
||||||
|
interactive_shell.InteractiveShell(manager).start()
|
||||||
|
|
||||||
|
|
||||||
@app.command()
|
@app.command()
|
||||||
def server(
|
def server(
|
||||||
|
context: typer.Context,
|
||||||
host: str = typer.Argument(
|
host: str = typer.Argument(
|
||||||
'0.0.0.0',
|
'0.0.0.0',
|
||||||
help="bind address",
|
help="bind address",
|
||||||
|
@ -80,7 +162,6 @@ def server(
|
||||||
"""
|
"""
|
||||||
Start the Groove on Demand playlsit server.
|
Start the Groove on Demand playlsit server.
|
||||||
"""
|
"""
|
||||||
initialize()
|
|
||||||
with database_manager() as manager:
|
with database_manager() as manager:
|
||||||
manager.import_from_filesystem()
|
manager.import_from_filesystem()
|
||||||
webserver.start(host=host, port=port, debug=debug)
|
webserver.start(host=host, port=port, debug=debug)
|
||||||
|
|
|
@ -26,7 +26,7 @@ BASE_STYLE = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def console_theme(theme_name: Union[str, None] = None) -> dict:
|
def console_theme(theme_name: Union[str, None] = 'blue_train') -> dict:
|
||||||
"""
|
"""
|
||||||
Return a console theme as a dictionary.
|
Return a console theme as a dictionary.
|
||||||
|
|
||||||
|
@ -36,8 +36,8 @@ def console_theme(theme_name: Union[str, None] = None) -> dict:
|
||||||
cfg = ConfigParser()
|
cfg = ConfigParser()
|
||||||
cfg.read_dict({'styles': BASE_STYLE})
|
cfg.read_dict({'styles': BASE_STYLE})
|
||||||
cfg.read(theme(
|
cfg.read(theme(
|
||||||
theme_name or os.environ['DEFAULT_THEME']) / Path('console.cfg')
|
Path(theme_name or os.environ['DEFAULT_THEME']) / Path('console.cfg')
|
||||||
)
|
))
|
||||||
return cfg['styles']
|
return cfg['styles']
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,7 @@ class MediaScanner:
|
||||||
console: Union[Console, None] = None,
|
console: Union[Console, None] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
self._db = db
|
self._db = db
|
||||||
self._glob = tuple((glob or os.environ.get('MEDIA_GLOB')).split(','))
|
self._glob = tuple((glob or os.environ.get('MEDIA_GLOB', '*.mp3,*.flac,*.m4a')).split(','))
|
||||||
self._root = groove.path.media_root()
|
self._root = groove.path.media_root()
|
||||||
self._console = console or Console()
|
self._console = console or Console()
|
||||||
self._scanned = 0
|
self._scanned = 0
|
||||||
|
|
|
@ -4,14 +4,14 @@ import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from groove.exceptions import ConfigurationError, ThemeMissingException, ThemeConfigurationError
|
from groove.exceptions import ConfigurationError, ThemeMissingException, ThemeConfigurationError
|
||||||
|
|
||||||
_setup_hint = "You may be able to solve this error by running 'groove setup'."
|
_setup_hint = "You may be able to solve this error by running 'groove setup' or specifying the --env parameter."
|
||||||
_reinstall_hint = "You might need to reinstall Groove On Demand to fix this error."
|
_reinstall_hint = "You might need to reinstall Groove On Demand to fix this error."
|
||||||
|
|
||||||
|
|
||||||
def root():
|
def root():
|
||||||
path = os.environ.get('GROOVE_ON_DEMAND_ROOT', None)
|
path = os.environ.get('GROOVE_ON_DEMAND_ROOT', None)
|
||||||
if not path:
|
if not path:
|
||||||
raise ConfigurationError(f"GROOVE_ON_DEMAND_ROOT is not defined in your environment.\n\n{_setup_hint}")
|
raise ConfigurationError(f"GROOVE_ON_DEMAND_ROOT is not defined in your environment.\n{_setup_hint}")
|
||||||
path = Path(path).expanduser()
|
path = Path(path).expanduser()
|
||||||
if not path.exists() or not path.is_dir():
|
if not path.exists() or not path.is_dir():
|
||||||
raise ConfigurationError(
|
raise ConfigurationError(
|
||||||
|
@ -83,7 +83,7 @@ def themes_root():
|
||||||
|
|
||||||
def theme(name):
|
def theme(name):
|
||||||
path = themes_root() / Path(name)
|
path = themes_root() / Path(name)
|
||||||
if not path.exists() or not path.is_dir():
|
if not path.exists():
|
||||||
available = ','.join(available_themes())
|
available = ','.join(available_themes())
|
||||||
raise ThemeMissingException(
|
raise ThemeMissingException(
|
||||||
f"A theme directory named {name} does not exist or isn't a directory. "
|
f"A theme directory named {name} does not exist or isn't a directory. "
|
||||||
|
@ -102,13 +102,9 @@ def available_themes():
|
||||||
|
|
||||||
|
|
||||||
def database():
|
def database():
|
||||||
path = os.environ.get('DATABASE_PATH', None)
|
path = Path(os.environ.get('DATABASE_PATH', '~')).expanduser()
|
||||||
if not path:
|
if not path.exists() or not path.is_dir():
|
||||||
path = root()
|
raise ConfigurationError(
|
||||||
else: # pragma: no cover
|
"DATABASE_PATH doesn't exist or isn't a directory.\n\n{_setup_hint}"
|
||||||
path = Path(path).expanduser()
|
)
|
||||||
if not path.exists() or not path.is_dir():
|
|
||||||
raise ConfigurationError(
|
|
||||||
"DATABASE_PATH doesn't exist or isn't a directory.\n\n{_setup_hint}"
|
|
||||||
)
|
|
||||||
return path / Path('groove_on_demand.db')
|
return path / Path('groove_on_demand.db')
|
||||||
|
|
|
@ -16,7 +16,7 @@ from groove.webserver import requests, themes
|
||||||
server = bottle.Bottle()
|
server = bottle.Bottle()
|
||||||
|
|
||||||
|
|
||||||
def start(host: str, port: int, debug: bool) -> None: # pragma: no cover
|
def start(host: str = '127.0.0.1', port: int = 2323, debug: bool = False) -> None: # pragma: no cover
|
||||||
"""
|
"""
|
||||||
Start the Bottle app.
|
Start the Bottle app.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -35,7 +35,7 @@ def test_theme_no_path():
|
||||||
|
|
||||||
|
|
||||||
def test_database_default(env):
|
def test_database_default(env):
|
||||||
assert path.database().relative_to(path.root())
|
assert path.database()
|
||||||
|
|
||||||
|
|
||||||
def test_database(env):
|
def test_database(env):
|
||||||
|
|
Loading…
Reference in New Issue
Block a user