Implement check for updates feature (#558)

* Implement check for updates

* Fix tests

* Bump version
This commit is contained in:
Nathan Thomas 2024-01-13 22:49:23 -08:00 committed by GitHub
parent 8bc87a4b74
commit fa65929c97
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 52 additions and 20 deletions

View file

@ -1,6 +1,6 @@
[tool.poetry] [tool.poetry]
name = "streamrip" name = "streamrip"
version = "2.0.2" version = "2.0.3"
description = "A fast, all-in-one music ripper for Qobuz, Deezer, Tidal, and SoundCloud" description = "A fast, all-in-one music ripper for Qobuz, Deezer, Tidal, and SoundCloud"
authors = ["nathom <nathanthomas707@gmail.com>"] authors = ["nathom <nathanthomas707@gmail.com>"]
license = "GPL-3.0-only" license = "GPL-3.0-only"

View file

@ -2,4 +2,4 @@ from . import converter, db, exceptions, media, metadata
from .config import Config from .config import Config
__all__ = ["Config", "media", "metadata", "converter", "db", "exceptions"] __all__ = ["Config", "media", "metadata", "converter", "db", "exceptions"]
__version__ = "2.0.2" __version__ = "2.0.3"

View file

@ -15,7 +15,7 @@ logger = logging.getLogger("streamrip")
APP_DIR = click.get_app_dir("streamrip") APP_DIR = click.get_app_dir("streamrip")
os.makedirs(APP_DIR, exist_ok=True) os.makedirs(APP_DIR, exist_ok=True)
DEFAULT_CONFIG_PATH = os.path.join(APP_DIR, "config.toml") DEFAULT_CONFIG_PATH = os.path.join(APP_DIR, "config.toml")
CURRENT_CONFIG_VERSION = "2.0" CURRENT_CONFIG_VERSION = "2.0.3"
@dataclass(slots=True) @dataclass(slots=True)
@ -214,6 +214,7 @@ class CliConfig:
@dataclass(slots=True) @dataclass(slots=True)
class MiscConfig: class MiscConfig:
version: str version: str
check_for_updates: bool
HOME = Path.home() HOME = Path.home()

View file

@ -186,4 +186,6 @@ max_search_results = 100
[misc] [misc]
# Metadata to identify this config file. Do not change. # Metadata to identify this config file. Do not change.
version = "2.0" version = "2.0.3"
# Print a message if a new version of streamrip is available
check_for_updates = true

View file

@ -8,13 +8,15 @@ from functools import wraps
from typing import Any from typing import Any
import aiofiles import aiofiles
import aiohttp
import click import click
from click_help_colors import HelpColorsGroup # type: ignore from click_help_colors import HelpColorsGroup # type: ignore
from rich.logging import RichHandler from rich.logging import RichHandler
from rich.markdown import Markdown
from rich.prompt import Confirm from rich.prompt import Confirm
from rich.traceback import install from rich.traceback import install
from .. import db from .. import __version__, db
from ..config import DEFAULT_CONFIG_PATH, Config, set_user_defaults from ..config import DEFAULT_CONFIG_PATH, Config, set_user_defaults
from ..console import console from ..console import console
from .main import Main from .main import Main
@ -33,7 +35,7 @@ def coro(f):
help_headers_color="yellow", help_headers_color="yellow",
help_options_color="green", help_options_color="green",
) )
@click.version_option(version="2.0.2") @click.version_option(version=__version__)
@click.option( @click.option(
"--config-path", "--config-path",
default=DEFAULT_CONFIG_PATH, default=DEFAULT_CONFIG_PATH,
@ -152,11 +154,30 @@ def rip(ctx, config_path, folder, no_db, quality, codec, no_progress, verbose):
async def url(ctx, urls): async def url(ctx, urls):
"""Download content from URLs.""" """Download content from URLs."""
with ctx.obj["config"] as cfg: with ctx.obj["config"] as cfg:
cfg: Config
updates = cfg.session.misc.check_for_updates
if updates:
# Run in background
version_coro = asyncio.create_task(latest_streamrip_version())
else:
version_coro = None
async with Main(cfg) as main: async with Main(cfg) as main:
await main.add_all(urls) await main.add_all(urls)
await main.resolve() await main.resolve()
await main.rip() await main.rip()
if version_coro is not None:
latest_version, notes = await version_coro
if latest_version != __version__:
console.print(
f"\n[green]A new version of streamrip [cyan]v{latest_version}[/cyan]"
" is available! Run [white][bold]pip3 install streamrip --upgrade[/bold][/white]"
" to update.[/green]\n"
)
console.print(Markdown(notes))
@rip.command() @rip.command()
@click.argument( @click.argument(
@ -390,5 +411,22 @@ async def id(ctx, source, media_type, id):
await main.rip() await main.rip()
async def latest_streamrip_version() -> tuple[str, str | None]:
async with aiohttp.ClientSession() as s:
async with s.get("https://pypi.org/pypi/streamrip/json") as resp:
data = await resp.json()
version = data["info"]["version"]
if version == __version__:
return version, None
async with s.get(
"https://api.github.com/repos/nathom/streamrip/releases/latest"
) as resp:
json = await resp.json()
notes = json["body"]
return version, notes
if __name__ == "__main__": if __name__ == "__main__":
rip() rip()

Binary file not shown.

View file

@ -127,7 +127,7 @@ def test_sample_config_data_fields(sample_config_data):
bit_depth=24, bit_depth=24,
lossy_bitrate=320, lossy_bitrate=320,
), ),
misc=MiscConfig(version="2.0"), misc=MiscConfig(version="2.0", check_for_updates=True),
_modified=False, _modified=False,
) )
assert sample_config_data.downloads == test_config.downloads assert sample_config_data.downloads == test_config.downloads

View file

@ -185,4 +185,5 @@ max_search_results = 100
[misc] [misc]
# Metadata to identify this config file. Do not change. # Metadata to identify this config file. Do not change.
version = "2.0" version = "2.0.3"
check_for_updates = true

View file

@ -24,19 +24,9 @@ def config_version() -> str | None:
return m.group(1) return m.group(1)
@pytest.fixture
def click_version() -> str | None:
r = re.compile(r'\@click\.version_option\(version="([\d\.]+)"\)')
with open("streamrip/rip/cli.py") as f:
m = r.search(f.read())
assert m is not None
return m.group(1)
def test_config_versions_match(config_version): def test_config_versions_match(config_version):
assert config_version == CURRENT_CONFIG_VERSION assert config_version == CURRENT_CONFIG_VERSION
def test_streamrip_versions_match(pyproject_version, click_version): def test_streamrip_versions_match(pyproject_version):
assert pyproject_version == click_version assert pyproject_version == init_version
assert click_version == init_version