forked from ragadeeshu/mp3printer
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path_config.py
More file actions
91 lines (68 loc) · 2.54 KB
/
Copy path_config.py
File metadata and controls
91 lines (68 loc) · 2.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# pyright: strict
import os
import pathlib as pl
import tomllib as tl
from typing import Annotated, Any, Iterable, cast
import pydantic as pyd
# optional libs
try:
# Chromecast support
import pychromecast.discovery
except ModuleNotFoundError:
pychromecast = None
def _normalize_source(inp: Any) -> tuple[str, ...]:
if isinstance(inp, str):
return (inp,)
if isinstance(inp, Iterable):
return tuple(str(item) for item in cast(Iterable[Any], inp))
raise ValueError("source must be str or iterable of str")
class FallbackConfig(pyd.BaseModel):
name: str
source: Annotated[tuple[str, ...], pyd.BeforeValidator(_normalize_source)]
random: bool = False
model_config = {"extra": "forbid"}
def _normalize_persist_dir(inp: Any) -> pl.Path | None:
if inp:
path = pl.Path(inp)
os.makedirs(path, exist_ok=True)
return path
return None
def _handle_chromecast(inp: Any) -> tuple[str, int] | None:
if inp:
if not isinstance(inp, str):
raise ValueError(f"Expected str, got {type(inp).__name__}")
if pychromecast:
services, browser = pychromecast.discovery.discover_listed_chromecasts(
friendly_names=[inp]
)
pychromecast.discovery.stop_discovery(browser)
if len(services) < 1:
raise Exception(f'Could not find Chromecast (or group) "{inp}"')
elif len(services) > 1:
raise Exception(f'More than one Chromecast (or group) matched "{inp}"')
return (services[0].host, services[0].port)
else:
raise Exception("chromecast is set, but pychromecast is not installed.")
return None
def _normalize_fallback(inp: Any) -> tuple[Any, ...]:
if isinstance(inp, Iterable):
return tuple(cast(Iterable[Any], inp))
raise ValueError("fallback must be iterable")
class PrinterConfig(pyd.BaseModel):
bind: str | None = None
port: int = 80
proxied: bool = False
prio_dropoff: int = 3
persist_dir: Annotated[
pl.Path | None, pyd.BeforeValidator(_normalize_persist_dir)
] = None
chromecast: Annotated[
tuple[str, int] | None, pyd.BeforeValidator(_handle_chromecast)
] = None
fallback: Annotated[
tuple[FallbackConfig, ...], pyd.BeforeValidator(_normalize_fallback)
] = ()
model_config = {"extra": "forbid"}
def parse(config_file: str | os.PathLike[str]) -> PrinterConfig:
with open(config_file, "rb") as f:
return PrinterConfig.model_validate(tl.load(f))