Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
use flake
18 changes: 11 additions & 7 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,27 @@ jobs:
fail-fast: false

steps:
- uses: actions/checkout@v3
- name: Install Poetry
uses: abatilo/actions-poetry@v2
- name: Set up Python
uses: actions/setup-python@v4
- uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'poetry'
enable-cache: true
cache-suffix: ${{ matrix.python-version }}

- name: Install mopidy-tidal
run: |
poetry install
uv sync

- name: Lint
run: |
make lint

- name: Test
run: |
make test

- name: Upload coverage
if: ${{ matrix.python-version == '3.10' }}
uses: codecov/codecov-action@v3
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -174,3 +174,4 @@ poetry.toml
pyrightconfig.json

# End of https://www.toptal.com/developers/gitignore/api/python
/.direnv/
11 changes: 7 additions & 4 deletions DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,16 @@ something is supposed to work is probably to have a look at the tests.


### Code Style
Code should be formatted with `isort` and `black`:
Code should be formatted with `ruff`:

```bash
isort --profile=black mopidy_tidal tests
black mopidy_tidal tests
ruff format
```

Additionally, run `ruff check` and clean up or `#noqa` its suggestions. You may
want to use `ruff check --fix`, potentially after staging so you can see the
difference.

if you are on *nix you can run:

```bash
Expand Down Expand Up @@ -107,4 +110,4 @@ by design of entering the venv permanently from within the makefile.)


In either case, run `mopidy` inside the virtualenv to launch mopidy with your
development version of Mopidy-Tidal.
development version of Mopidy-Tidal.
61 changes: 61 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

63 changes: 63 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{
description = "gstreamer proxy";

inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
};

outputs = {
self,
nixpkgs,
flake-utils,
...
}:
flake-utils.lib.eachDefaultSystem
(
system: let
pkgs = import nixpkgs {
inherit system;
};
python = pkgs.python313;
# 'build time' deps
buildInputs =
(with pkgs; [
(python.withPackages (ps:
with ps; [
gst-python
pygobject3
# packages not specified in pyproject.toml: these will be available in the venv.
]))
uv
pre-commit
ruff
gobject-introspection
])
++ (with pkgs.gst_all_1; [
# glib-networking
gst-plugins-bad
gst-plugins-base
gst-plugins-good
gst-plugins-ugly
gst-plugins-rs
]);
env = {
LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath [
pkgs.stdenv.cc.cc # allow building c extensions
];
UV_PROJECT_ENVIRONMENT = ".direnv/venv";
};
in
with pkgs; {
devShells.default = mkShell {
inherit buildInputs;
inherit env;
shellHook = ''
# pre-commit install
[ ! -d $UV_PROJECT_ENVIRONMENT ] && uv venv $UV_PROJECT_ENVIRONMENT --python ${python}/bin/python
source $UV_PROJECT_ENVIRONMENT/bin/activate
'';
};
}
);
}
2 changes: 1 addition & 1 deletion integration_tests/test_login_hack.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,5 @@ def test_user_warned_if_lazy_set_implicitly(spawn, config_dir):
child.expect("Connecting to TIDAL... Quality = LOSSLESS")
child.expect("HACK login implies lazy connection")
child.expect("Starting GLib mainloop")
with spawn(f"mpc list artist") as mpc:
with spawn("mpc list artist") as mpc:
mpc.expect("Please visit .*link.tidal.com/.* to log in")
21 changes: 9 additions & 12 deletions makefile
Original file line number Diff line number Diff line change
@@ -1,32 +1,29 @@
.PHONY: lint test install format all system-venv integration-test
POETRY ?= poetry run
UV ?= uv run

help:
@printf "Chose one of install, format, lint or test.\n"

install:
rm -rf dist
poetry build
uv build --wheel
pip install dist/*.whl

format:
${POETRY} isort --profile=black mopidy_tidal tests
${POETRY} black mopidy_tidal tests
${UV} ruff format

lint:
${POETRY} isort --check --profile=black mopidy_tidal tests
${POETRY} black --check mopidy_tidal tests
${UV} ruff check
${UV} ruff format --check

system-venv:
python -m venv .venv --system-site-packages
bash -c "source .venv/bin/activate && poetry install"
bash -c "source .venv/bin/activate && uv install"
@printf "You now need to activate the venv by sourcing the right file, e.g. source .venv/bin/activate\n"


test:
${POETRY} pytest tests/ \
-k "not gt_$$(python3 --version | sed 's/Python \([0-9]\).\([0-9]*\)\..*/\1_\2/')" \
--cov=mopidy_tidal --cov-report=html --cov-report=xml --cov-report=term-missing --cov-branch
${UV} pytest tests/ \
-k "not gt_$$(python3 --version | sed 's/Python \([0-9]\).\([0-9]*\)\..*/\1_\2/')"

integration-test:
${POETRY} pytest integration_tests/
${UV} pytest integration_tests/
5 changes: 2 additions & 3 deletions mopidy_tidal/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@
from tidalapi import Config, Session
from tidalapi import __version__ as tidalapi_ver

from mopidy_tidal import Extension
from mopidy_tidal import Extension, context, library, playback, playlists
from mopidy_tidal import __version__ as mopidy_tidal_ver
from mopidy_tidal import context, library, playback, playlists
from mopidy_tidal.web_auth_server import WebAuthServer

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -191,7 +190,7 @@ def _web_auth_callback(self, url_redirect: str):
# Parse and set tokens.
self._active_session.process_auth_token(json, is_pkce_token=True)
self._logged_in = True
except:
except Exception:
raise ValueError("Response code is required for PKCE login!")
# Store session after auth completion
self._complete_login()
Expand Down
1 change: 0 additions & 1 deletion mopidy_tidal/library.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from mopidy.models import Image, Ref, SearchResult, Track
from requests.exceptions import HTTPError
from tidalapi.exceptions import ObjectNotFound, TooManyRequests
from tidalapi.workers import get_items

from mopidy_tidal import full_models_mappers, ref_models_mappers
from mopidy_tidal.login_hack import login_hack
Expand Down
2 changes: 0 additions & 2 deletions mopidy_tidal/login_hack.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import inspect
from abc import ABC
from contextlib import suppress
from functools import reduce, wraps
from itertools import chain
from logging import getLogger
from pathlib import Path
from types import FunctionType
from typing import TYPE_CHECKING, Optional, Union, get_args, get_origin
from urllib.parse import urlencode
Expand Down
2 changes: 1 addition & 1 deletion mopidy_tidal/lru_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def _get_from_storage(self, key):
except Exception as e:
# If the cache entry on the filesystem is corrupt, reset it
logger.warning(
"Could not deserialize cache file %s: " "refreshing the entry: %s",
"Could not deserialize cache file %s: refreshing the entry: %s",
cache_file,
e,
)
Expand Down
2 changes: 0 additions & 2 deletions mopidy_tidal/playlists.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
from mopidy.models import Ref
from requests import HTTPError
from tidalapi.playlist import Playlist as TidalPlaylist
from tidalapi.workers import get_items

from mopidy_tidal import full_models_mappers
from mopidy_tidal.full_models_mappers import create_mopidy_playlist
Expand Down Expand Up @@ -195,7 +194,6 @@ def refresh(self, *uris, include_items: bool = True) -> dict[str, MopidyPlaylist
else:
logger.info("Refreshing TIDAL playlists..")

session = self.backend.session
plists = self._current_tidal_playlists
mapped_playlists = {}
playlist_cache = self._playlists if include_items else self._playlists_metadata
Expand Down
2 changes: 1 addition & 1 deletion mopidy_tidal/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ class SearchFieldMeta:


def _get_flattened_query_and_field_meta(
query: Mapping[str, str]
query: Mapping[str, str],
) -> Tuple[str, SearchFieldMeta]:
q = " ".join(
query[field]
Expand Down
2 changes: 1 addition & 1 deletion mopidy_tidal/web_auth_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ def __init__(
callback: Callable[[str], None],
pkce_enabled: bool,
*args,
**kwargs
**kwargs,
):
self.login_url = login_url
self.callback_fn: Callable = callback
Expand Down
Loading
Loading