Compare commits

..

No commits in common. "dc037a0a4b3d15b9e80384b2d843694c7b8aefef" and "fd7866ed14e9c59d69a959202b05906fc0e322ee" have entirely different histories.

13 changed files with 33 additions and 310 deletions

112
pdm.lock
View file

@ -5,7 +5,7 @@
groups = ["default", "all", "dev"] groups = ["default", "all", "dev"]
strategy = ["cross_platform"] strategy = ["cross_platform"]
lock_version = "4.4.1" lock_version = "4.4.1"
content_hash = "sha256:828f8051de2c2a04cede8130abf86764edb38f0428cd1d52dd797bff43452afe" content_hash = "sha256:2b4fba8ca6883f5a1de28a420870d566efa031d62f9057c59095a25a0e51d36e"
[[package]] [[package]]
name = "aiocache" name = "aiocache"
@ -54,22 +54,6 @@ files = [
{file = "aiomcache-0.8.2.tar.gz", hash = "sha256:43b220d7f499a32a71871c4f457116eb23460fa216e69c1d32b81e3209e51359"}, {file = "aiomcache-0.8.2.tar.gz", hash = "sha256:43b220d7f499a32a71871c4f457116eb23460fa216e69c1d32b81e3209e51359"},
] ]
[[package]]
name = "apischema"
version = "0.18.1"
requires_python = ">=3.7"
summary = "JSON (de)serialization, GraphQL and JSON schema generation using Python typing."
files = [
{file = "apischema-0.18.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:220aa56974f765dc100e875c66c688ff57bad3ae48d0aeaee4fb1ec90c5cd0fd"},
{file = "apischema-0.18.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:653492010d22acdcbe2240f0ceb3ca59de1b6d34640895e03fda15f944e216d8"},
{file = "apischema-0.18.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:56a8acc8da59cf7a1052b5aec71d2f8ed6137b54aa1492709acb2c47f0547107"},
{file = "apischema-0.18.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:d466ccc31cbc95b381037ed5b9e82e034f921eb28f8057263aefc2817678036f"},
{file = "apischema-0.18.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4b005d5a4baba32eccec5bb0fbd616f9fd26b6a5fb4f15e9a8bb53a948adade0"},
{file = "apischema-0.18.1-cp312-cp312-win32.whl", hash = "sha256:bd06fc6a52d461bd6540409cb25c1d51aae23b22fcd10b1fb002a3f7f1f15d0f"},
{file = "apischema-0.18.1-cp312-cp312-win_amd64.whl", hash = "sha256:429f13d9e35379bf8187c41a3c05562f8149358128382a90e415c63db528d6a2"},
{file = "apischema-0.18.1.tar.gz", hash = "sha256:355dc4dea7389f5b25f5326c26f06eebee8107efda7e82db8f09ee122cdf0c98"},
]
[[package]] [[package]]
name = "attrs" name = "attrs"
version = "23.2.0" version = "23.2.0"
@ -80,41 +64,6 @@ files = [
{file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"}, {file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"},
] ]
[[package]]
name = "idna"
version = "3.7"
requires_python = ">=3.5"
summary = "Internationalized Domain Names in Applications (IDNA)"
files = [
{file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"},
{file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"},
]
[[package]]
name = "multidict"
version = "6.0.5"
requires_python = ">=3.7"
summary = "multidict implementation"
files = [
{file = "multidict-6.0.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:51d035609b86722963404f711db441cf7134f1889107fb171a970c9701f92e1e"},
{file = "multidict-6.0.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cbebcd5bcaf1eaf302617c114aa67569dd3f090dd0ce8ba9e35e9985b41ac35b"},
{file = "multidict-6.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ffc42c922dbfddb4a4c3b438eb056828719f07608af27d163191cb3e3aa6cc5"},
{file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ceb3b7e6a0135e092de86110c5a74e46bda4bd4fbfeeb3a3bcec79c0f861e450"},
{file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79660376075cfd4b2c80f295528aa6beb2058fd289f4c9252f986751a4cd0496"},
{file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4428b29611e989719874670fd152b6625500ad6c686d464e99f5aaeeaca175a"},
{file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d84a5c3a5f7ce6db1f999fb9438f686bc2e09d38143f2d93d8406ed2dd6b9226"},
{file = "multidict-6.0.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76c0de87358b192de7ea9649beb392f107dcad9ad27276324c24c91774ca5271"},
{file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:79a6d2ba910adb2cbafc95dad936f8b9386e77c84c35bc0add315b856d7c3abb"},
{file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:92d16a3e275e38293623ebf639c471d3e03bb20b8ebb845237e0d3664914caef"},
{file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:fb616be3538599e797a2017cccca78e354c767165e8858ab5116813146041a24"},
{file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:14c2976aa9038c2629efa2c148022ed5eb4cb939e15ec7aace7ca932f48f9ba6"},
{file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:435a0984199d81ca178b9ae2c26ec3d49692d20ee29bc4c11a2a8d4514c67eda"},
{file = "multidict-6.0.5-cp312-cp312-win32.whl", hash = "sha256:9fe7b0653ba3d9d65cbe7698cca585bf0f8c83dbbcc710db9c90f478e175f2d5"},
{file = "multidict-6.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:01265f5e40f5a17f8241d52656ed27192be03bfa8764d88e8220141d1e4b3556"},
{file = "multidict-6.0.5-py3-none-any.whl", hash = "sha256:0d63c74e3d7ab26de115c49bffc92cc77ed23395303d496eae515d4204a625e7"},
{file = "multidict-6.0.5.tar.gz", hash = "sha256:f7e301075edaf50500f0b341543c41194d8df3ae5caf4702f2095f3ca73dd8da"},
]
[[package]] [[package]]
name = "mypy" name = "mypy"
version = "1.10.0" version = "1.10.0"
@ -266,26 +215,6 @@ files = [
{file = "python_mpd2-3.1.1-py2.py3-none-any.whl", hash = "sha256:86bf1100a0b135959d74a9a7a58cf0515bf30bb54eb25ae6fb8e175e50300fc3"}, {file = "python_mpd2-3.1.1-py2.py3-none-any.whl", hash = "sha256:86bf1100a0b135959d74a9a7a58cf0515bf30bb54eb25ae6fb8e175e50300fc3"},
] ]
[[package]]
name = "pytomlpp"
version = "1.0.13"
summary = "A python wrapper for toml++"
files = [
{file = "pytomlpp-1.0.13-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:4710c72456c10a90e58084174312abef8f9652b0f91c240c008903c1bd99814d"},
{file = "pytomlpp-1.0.13-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b59acc12339a992404289ab7294f28ba06c7df3c2562e81d316a0e744ab4103b"},
{file = "pytomlpp-1.0.13-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:252e31a5e013a74b898784f4ffb8aa8068e136b910ad11f2af1ee8a5700e6e1e"},
{file = "pytomlpp-1.0.13-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:09e716c0f462d15f2334cecc736957777dd30f8a5bfa5cf8150679da7577d2fd"},
{file = "pytomlpp-1.0.13-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:19dbded2995370e802105fa6dce54ed60f79e58b4eb35fee7ef33f1fb5958f6c"},
{file = "pytomlpp-1.0.13-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9f87f6c958309e4c2358b778902c80bd33611d1c392f1abe2c226e3a62909ca4"},
{file = "pytomlpp-1.0.13-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e285aca948b419301fdda1927723287ef28482752782c44c9ee8c57eae7a1dc8"},
{file = "pytomlpp-1.0.13-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:aad6ae19c056ea62a43fec82427ad4675b5c773dc255c4bdcf6da659cd7edff6"},
{file = "pytomlpp-1.0.13-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0e0b34b7a132856567714342e9a622f7be0b4c9bac561a6252f0f85626c1aa4b"},
{file = "pytomlpp-1.0.13-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ac06ca7683f5a2737b3888ea1e38d6968abb24fab703bc7ceccbe589d5420e0c"},
{file = "pytomlpp-1.0.13-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:35225c1d9d674df87b4682f04af97856049351c38822455b78258248d9309363"},
{file = "pytomlpp-1.0.13-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:dbc9208ac58ea2a9d5ebb77e69d54d146744007f4a704a3f4e56d9881d41ee1c"},
{file = "pytomlpp-1.0.13.tar.gz", hash = "sha256:a0bd639a8f624d1bdf5b3ea94363ca23dbfef38ab7b5b9348881a84afab434ad"},
]
[[package]] [[package]]
name = "redis" name = "redis"
version = "5.0.4" version = "5.0.4"
@ -330,42 +259,3 @@ files = [
{file = "typing_extensions-4.11.0-py3-none-any.whl", hash = "sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a"}, {file = "typing_extensions-4.11.0-py3-none-any.whl", hash = "sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a"},
{file = "typing_extensions-4.11.0.tar.gz", hash = "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0"}, {file = "typing_extensions-4.11.0.tar.gz", hash = "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0"},
] ]
[[package]]
name = "xdg-base-dirs"
version = "6.0.1"
requires_python = ">=3.10,<4.0"
summary = "Variables defined by the XDG Base Directory Specification"
files = [
{file = "xdg_base_dirs-6.0.1-py3-none-any.whl", hash = "sha256:63f6ebc1721ced2e86c340856e004ef829501a30a37e17079c52cfaf0e1741b9"},
{file = "xdg_base_dirs-6.0.1.tar.gz", hash = "sha256:b4c8f4ba72d1286018b25eea374ec6fbf4fddda3d4137edf50de95de53e195a6"},
]
[[package]]
name = "yarl"
version = "1.9.4"
requires_python = ">=3.7"
summary = "Yet another URL library"
dependencies = [
"idna>=2.0",
"multidict>=4.0",
]
files = [
{file = "yarl-1.9.4-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0d2454f0aef65ea81037759be5ca9947539667eecebca092733b2eb43c965a81"},
{file = "yarl-1.9.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:44d8ffbb9c06e5a7f529f38f53eda23e50d1ed33c6c869e01481d3fafa6b8142"},
{file = "yarl-1.9.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:aaaea1e536f98754a6e5c56091baa1b6ce2f2700cc4a00b0d49eca8dea471074"},
{file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3777ce5536d17989c91696db1d459574e9a9bd37660ea7ee4d3344579bb6f129"},
{file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fc5fc1eeb029757349ad26bbc5880557389a03fa6ada41703db5e068881e5f2"},
{file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea65804b5dc88dacd4a40279af0cdadcfe74b3e5b4c897aa0d81cf86927fee78"},
{file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa102d6d280a5455ad6a0f9e6d769989638718e938a6a0a2ff3f4a7ff8c62cc4"},
{file = "yarl-1.9.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09efe4615ada057ba2d30df871d2f668af661e971dfeedf0c159927d48bbeff0"},
{file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:008d3e808d03ef28542372d01057fd09168419cdc8f848efe2804f894ae03e51"},
{file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:6f5cb257bc2ec58f437da2b37a8cd48f666db96d47b8a3115c29f316313654ff"},
{file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:992f18e0ea248ee03b5a6e8b3b4738850ae7dbb172cc41c966462801cbf62cf7"},
{file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0e9d124c191d5b881060a9e5060627694c3bdd1fe24c5eecc8d5d7d0eb6faabc"},
{file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3986b6f41ad22988e53d5778f91855dc0399b043fc8946d4f2e68af22ee9ff10"},
{file = "yarl-1.9.4-cp312-cp312-win32.whl", hash = "sha256:4b21516d181cd77ebd06ce160ef8cc2a5e9ad35fb1c5930882baff5ac865eee7"},
{file = "yarl-1.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:a9bd00dc3bc395a662900f33f74feb3e757429e545d831eef5bb280252631984"},
{file = "yarl-1.9.4-py3-none-any.whl", hash = "sha256:928cecb0ef9d5a7946eb6ff58417ad2fe9375762382f1bf5c55e61645f2c43ad"},
{file = "yarl-1.9.4.tar.gz", hash = "sha256:566db86717cf8080b99b58b083b773a908ae40f06681e87e589a976faf8246bf"},
]

View file

@ -10,10 +10,6 @@ dependencies = [
"attrs>=23.1.0", "attrs>=23.1.0",
"pyobjc-framework-MediaPlayer>=10.0", "pyobjc-framework-MediaPlayer>=10.0",
"python-mpd2>=3.1.0", "python-mpd2>=3.1.0",
"xdg-base-dirs>=6.0.1",
"pytomlpp>=1.0.13",
"apischema>=0.18.1",
"yarl>=1.9.4",
] ]
readme = "README.md" readme = "README.md"
@ -52,8 +48,6 @@ check = {composite = ['lint', 'typecheck']}
[tool.pdm.version] [tool.pdm.version]
source = "scm" source = "scm"
write_to = 'mpd_now_playable/__version__.py'
write_template = "__version__ = '{}'"
[build-system] [build-system]
requires = ["pdm-backend"] requires = ["pdm-backend"]

View file

@ -1 +0,0 @@
__version__ = '0.0.1'

View file

@ -2,10 +2,10 @@ from __future__ import annotations
from contextlib import suppress from contextlib import suppress
from typing import Any, Optional, TypeVar from typing import Any, Optional, TypeVar
from urllib.parse import parse_qsl, urlparse
from aiocache import Cache from aiocache import Cache
from aiocache.serializers import BaseSerializer, PickleSerializer from aiocache.serializers import BaseSerializer, PickleSerializer
from yarl import URL
T = TypeVar("T") T = TypeVar("T")
@ -28,23 +28,24 @@ class OrmsgpackSerializer(BaseSerializer):
return ormsgpack.unpackb(value) return ormsgpack.unpackb(value)
def make_cache(url: URL, namespace: str = "") -> Cache[T]: def make_cache(url: str, namespace: str = "") -> Cache[T]:
backend = Cache.get_scheme_class(url.scheme) parsed_url = urlparse(url)
backend = Cache.get_scheme_class(parsed_url.scheme)
if backend == Cache.MEMORY: if backend == Cache.MEMORY:
return Cache(backend) return Cache(backend)
kwargs: dict[str, Any] = dict(url.query) kwargs: dict[str, Any] = dict(parse_qsl(parsed_url.query))
if url.path: if parsed_url.path:
kwargs.update(backend.parse_uri_path(url.path)) kwargs.update(backend.parse_uri_path(parsed_url.path))
if url.host: if parsed_url.hostname:
kwargs["endpoint"] = url.host kwargs["endpoint"] = parsed_url.hostname
if url.port: if parsed_url.port:
kwargs["port"] = url.port kwargs["port"] = parsed_url.port
if url.password: if parsed_url.password:
kwargs["password"] = url.password kwargs["password"] = parsed_url.password
namespace = ":".join(s for s in [kwargs.pop("namespace", ""), namespace] if s) namespace = ":".join(s for s in [kwargs.pop("namespace", ""), namespace] if s)

View file

@ -1,19 +1,23 @@
import asyncio import asyncio
from os import environ
from corefoundationasyncio import CoreFoundationEventLoop from corefoundationasyncio import CoreFoundationEventLoop
from .__version__ import __version__
from .cocoa.now_playing import CocoaNowPlaying from .cocoa.now_playing import CocoaNowPlaying
from .config.load import loadConfig
from .mpd.listener import MpdStateListener from .mpd.listener import MpdStateListener
async def listen() -> None: async def listen() -> None:
print(f"mpd-now-playable v{__version__}") port = int(environ.get("MPD_PORT", "6600"))
config = loadConfig() host = environ.get("MPD_HOST", "localhost")
listener = MpdStateListener(config.cache) password = environ.get("MPD_PASSWORD")
cache = environ.get("MPD_NOW_PLAYABLE_CACHE")
if password is None and "@" in host:
password, host = host.split("@", maxsplit=1)
listener = MpdStateListener(cache)
now_playing = CocoaNowPlaying(listener) now_playing = CocoaNowPlaying(listener)
await listener.start(config.mpd) await listener.start(host=host, port=port, password=password)
await listener.loop(now_playing) await listener.loop(now_playing)

View file

@ -1,44 +0,0 @@
{
"$id": "https://cdn.00dani.me/m/schemata/mpd-now-playable/config-v1.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false,
"definitions": {
"URL": {
"format": "uri",
"type": "string"
}
},
"properties": {
"$schema": {
"$ref": "#/definitions/URL"
},
"cache": {
"$ref": "#/definitions/URL"
},
"mpd": {
"additionalProperties": false,
"default": {
"host": "127.0.0.1",
"port": 6600
},
"properties": {
"host": {
"default": "127.0.0.1",
"format": "hostname",
"type": "string"
},
"password": {
"type": "string"
},
"port": {
"default": 6600,
"maximum": 65535,
"minimum": 1,
"type": "integer"
}
},
"type": "object"
}
},
"type": "object"
}

View file

@ -1,28 +0,0 @@
from dataclasses import field
from typing import NewType, Optional, TypeVar
from apischema import schema
from apischema.conversions import deserializer
from apischema.metadata import none_as_undefined
from yarl import URL
__all__ = ("Host", "Port", "optional")
T = TypeVar("T")
Host = NewType("Host", str)
schema(format="hostname")(Host)
Port = NewType("Port", int)
schema(min=1, max=65535)(Port)
schema(format="uri")(URL)
def optional() -> Optional[T]:
return field(default=None, metadata=none_as_undefined)
@deserializer
def from_yarl(url: str) -> URL:
return URL(url)

View file

@ -1,34 +0,0 @@
from os import environ
from apischema import deserialize
from pytomlpp import load
from xdg_base_dirs import xdg_config_home
from .model import Config
__all__ = "loadConfig"
def loadConfigFromFile() -> Config:
path = xdg_config_home() / "mpd-now-playable" / "config.toml"
data = load(path)
print(f"Loaded your configuration from {path}")
return deserialize(Config, data)
def loadConfigFromEnv() -> Config:
port = int(environ["MPD_PORT"]) if "MPD_PORT" in environ else None
host = environ.get("MPD_HOST")
password = environ.get("MPD_PASSWORD")
cache = environ.get("MPD_NOW_PLAYABLE_CACHE")
if password is None and host is not None and "@" in host:
password, host = host.split("@", maxsplit=1)
data = {"cache": cache, "mpd": {"port": port, "host": host, "password": password}}
return deserialize(Config, data)
def loadConfig() -> Config:
try:
return loadConfigFromFile()
except FileNotFoundError:
return loadConfigFromEnv()

View file

@ -1,26 +0,0 @@
from dataclasses import dataclass, field
from typing import Optional
from apischema import alias
from yarl import URL
from .fields import Host, Port, optional
__all__ = ("MpdConfig", "Config")
@dataclass(frozen=True)
class MpdConfig:
password: Optional[str] = optional()
host: Host = Host("127.0.0.1")
port: Port = Port(6600)
@dataclass(frozen=True)
class Config:
schema: URL = field(
default=URL("https://cdn.00dani.me/m/schemata/mpd-now-playable/config-v1.json"),
metadata=alias("$schema"),
)
cache: Optional[URL] = optional()
mpd: MpdConfig = field(default_factory=MpdConfig)

View file

@ -1,28 +0,0 @@
from json import dump
from pathlib import Path
from pprint import pp
from typing import Any, Mapping
from apischema.json_schema import JsonSchemaVersion, deserialization_schema
from .model import Config
def generate() -> Mapping[str, Any]:
return deserialization_schema(Config, version=JsonSchemaVersion.DRAFT_7)
def write() -> None:
schema = dict(generate())
schema["$id"] = Config.schema.human_repr()
schema_file = Path(__file__).parent / Config.schema.name
print(f"Writing this schema to {schema_file}")
pp(schema)
with open(schema_file, "w") as fp:
dump(schema, fp, indent="\t", sort_keys=True)
fp.write("\n")
if __name__ == "__main__":
write()

View file

@ -2,8 +2,6 @@ from __future__ import annotations
from typing import TypedDict from typing import TypedDict
from yarl import URL
from ..async_tools import run_background_task from ..async_tools import run_background_task
from ..cache import Cache, make_cache from ..cache import Cache, make_cache
from .types import CurrentSongResponse, MpdStateHandler from .types import CurrentSongResponse, MpdStateHandler
@ -25,15 +23,12 @@ def calc_track_key(song: CurrentSongResponse) -> str:
return song["file"] return song["file"]
MEMORY = URL("memory://")
class MpdArtworkCache: class MpdArtworkCache:
mpd: MpdStateHandler mpd: MpdStateHandler
album_cache: Cache[ArtCacheEntry] album_cache: Cache[ArtCacheEntry]
track_cache: Cache[ArtCacheEntry] track_cache: Cache[ArtCacheEntry]
def __init__(self, mpd: MpdStateHandler, cache_url: URL = MEMORY): def __init__(self, mpd: MpdStateHandler, cache_url: str = "memory://"):
self.mpd = mpd self.mpd = mpd
self.album_cache = make_cache(cache_url, "album") self.album_cache = make_cache(cache_url, "album")
self.track_cache = make_cache(cache_url, "track") self.track_cache = make_cache(cache_url, "track")

View file

@ -4,9 +4,7 @@ from uuid import UUID
from mpd.asyncio import MPDClient from mpd.asyncio import MPDClient
from mpd.base import CommandError from mpd.base import CommandError
from yarl import URL
from ..config.model import MpdConfig
from ..player import Player from ..player import Player
from ..song import PlaybackState, Song, SongListener from ..song import PlaybackState, Song, SongListener
from ..type_tools import convert_if_exists from ..type_tools import convert_if_exists
@ -46,18 +44,20 @@ class MpdStateListener(Player):
art_cache: MpdArtworkCache art_cache: MpdArtworkCache
idle_count = 0 idle_count = 0
def __init__(self, cache: URL | None = None) -> None: def __init__(self, cache: str | None = None) -> None:
self.client = MPDClient() self.client = MPDClient()
self.art_cache = ( self.art_cache = (
MpdArtworkCache(self, cache) if cache else MpdArtworkCache(self) MpdArtworkCache(self, cache) if cache else MpdArtworkCache(self)
) )
async def start(self, conf: MpdConfig) -> None: async def start(
print(f"Connecting to MPD server {conf.host}:{conf.port}...") self, host: str = "localhost", port: int = 6600, password: str | None = None
await self.client.connect(conf.host, conf.port) ) -> None:
if conf.password is not None: print(f"Connecting to MPD server {host}:{port}...")
await self.client.connect(host, port)
if password is not None:
print("Authorising to MPD with your password...") print("Authorising to MPD with your password...")
await self.client.password(conf.password) await self.client.password(password)
print(f"Connected to MPD v{self.client.mpd_version}") print(f"Connected to MPD v{self.client.mpd_version}")
async def refresh(self) -> None: async def refresh(self) -> None: