upgrade to sanic-ext

This commit is contained in:
Peder Bergebakken Sundt 2023-08-27 00:51:10 +02:00
parent eeaa845dbd
commit 34134cd81c
6 changed files with 511 additions and 495 deletions

View File

@ -6,7 +6,7 @@ Why "Grzegorz"? [Great taste in humor of course!](https://youtu.be/t-fcrn1Edik)
When `grzegorz` starts, it launches an instance of MPV and maintains it. It is designed to be used as an info screen or HTPC, and supports multiple users to push changes to the MPV instance. When `grzegorz` starts, it launches an instance of MPV and maintains it. It is designed to be used as an info screen or HTPC, and supports multiple users to push changes to the MPV instance.
The API is described and can be tested at `http:/localhost:8080/swagger` while the server is running. All API endpoints are available under `/api` The API is described and can be tested at `http:/localhost:8080/docs/swagger` while the server is running. All API endpoints are available under `/api`
## How install and run it ## How install and run it

View File

@ -22,14 +22,14 @@
in { in {
packages = forAllSystems ({ system, pkgs, ...}: rec { packages = forAllSystems ({ system, pkgs, ...}: rec {
sanic-openapi = with pkgs.python3.pkgs; buildPythonPackage rec { sanic-ext = with pkgs.python3.pkgs; buildPythonPackage rec {
pname = "sanic-openapi"; pname = "sanic-ext";
version = "21.12.0"; version = "23.6.0";
src = fetchPypi { src = fetchPypi {
inherit pname version; inherit pname version;
hash = "sha256-fNpiI00IyWX3OeqsawWejyRNhwYdlzNcVyh/1q4Wv1I="; hash = "sha256-gd0Ta2t7ef2otP7CRE2YIjlFVXecKYqJFVxnKHoYSQI=";
}; };
propagatedBuildInputs = [ sanic pyyaml ]; propagatedBuildInputs = [ pyyaml ];
doCheck = false; doCheck = false;
}; };
grzegorz = with pkgs.python3.pkgs; buildPythonPackage { grzegorz = with pkgs.python3.pkgs; buildPythonPackage {
@ -40,12 +40,12 @@
postInstall = '' postInstall = ''
''; '';
nativeBuildInputs = [ poetry-core ]; nativeBuildInputs = [ poetry-core ];
propagatedBuildInputs = [ sanic sanic-openapi youtube-dl mpv ]; propagatedBuildInputs = [ setuptools sanic sanic-ext youtube-dl mpv ];
doCheck = false; doCheck = false;
}; };
grzegorz-run = pkgs.writeShellApplication { grzegorz-run = pkgs.writeShellApplication {
name = "grzegorz-run"; name = "grzegorz-run";
runtimeInputs = [ grzegorz pkgs.mpv ]; runtimeInputs = [ (pkgs.python3.withPackages (ps: [ grzegorz ])) pkgs.mpv ];
text = '' text = ''
TOOMANYARGS=() TOOMANYARGS=()
if test -z "$*"; then if test -z "$*"; then

View File

@ -1,5 +1,4 @@
from sanic import Sanic from sanic import Sanic
from sanic_openapi import swagger_blueprint#, openapi2_blueprint
from pathlib import Path from pathlib import Path
import traceback import traceback
from . import mpv from . import mpv
@ -15,20 +14,11 @@ app = Sanic(module_name, env_prefix=module_name.upper() + '_')
app.blueprint(api.bp, url_prefix="/api") app.blueprint(api.bp, url_prefix="/api")
app.add_task(api.PLAYLIST_DATA_CACHE.run()) app.add_task(api.PLAYLIST_DATA_CACHE.run())
# openapi: # openapi:
app.config.API_VERSION = '1.0' app.ext.openapi.describe("Grzegorz API",
app.config.API_TITLE = 'Grzegorz API' version = "1.0.0.",
app.config.API_DESCRIPTION \ description = "The Grzegorz Brzeczyszczykiewicz API, used to control a running mpv instance",
= 'The Grzegorz Brzeczyszczykiewicz API, used to control a running mpv instance' )
#app.config.API_TERMS_OF_SERVICE = ''# Supposed to be a link
app.config.API_PRODUCES_CONTENT_TYPES = ['application/json']
app.config.API_CONTACT_EMAIL = 'drift@pvv.ntnu.no'
#app.config.API_LICENSE_NAME = 'MIT'
#app.config.API_LICENSE_URL = 'todo'
#app.blueprint(openapi2_blueprint)
app.blueprint(swagger_blueprint)
# mpv: # mpv:

View File

@ -1,5 +1,5 @@
from sanic import Request, Blueprint, response from sanic import Request, Blueprint, response
from sanic_openapi import doc from sanic_ext import openapi
from functools import wraps from functools import wraps
from .mpv import MPVControl from .mpv import MPVControl
from .playlist_data import PlaylistDataCache from .playlist_data import PlaylistDataCache
@ -44,15 +44,15 @@ PLAYLIST_DATA_CACHE = PlaylistDataCache(auto_fetch_data=True)
#routes: #routes:
@bp.get("") @bp.get("")
@doc.exclude(True) @openapi.exclude(True)
@response_text @response_text
async def root(request: Request): async def root(request: Request):
return "Hello friend, I hope you're having a lovely day" return "Hello friend, I hope you're having a lovely day"
@bp.post("/load") @bp.post("/load")
@doc.summary("Add item to playlist") @openapi.summary("Add item to playlist")
@doc.consumes({"path": doc.String("Link to the resource to enqueue")}, required=True) @openapi.parameter("path", openapi.String(description="Link to the resource to enqueue"), required=True)
@doc.consumes({"body":doc.Dictionary(description="Any data you want stored with the queued item")}, location="body") @openapi.parameter("body", openapi.Object(description="Any data you want stored with the queued item"), location="body")
@response_json @response_json
async def loadfile(request: Request, mpv_control: MPVControl): async def loadfile(request: Request, mpv_control: MPVControl):
if "path" not in request.args: if "path" not in request.args:
@ -63,15 +63,15 @@ async def loadfile(request: Request, mpv_control: MPVControl):
return locals() return locals()
@bp.get("/play") @bp.get("/play")
@doc.summary("Check whether the player is paused or playing") @openapi.summary("Check whether the player is paused or playing")
@response_json @response_json
async def play_get(request: Request, mpv_control: MPVControl): async def play_get(request: Request, mpv_control: MPVControl):
value = await mpv_control.pause_get() == False value = await mpv_control.pause_get() == False
return locals() return locals()
@bp.post("/play") @bp.post("/play")
@doc.summary("Set whether the player is paused or playing") @openapi.summary("Set whether the player is paused or playing")
@doc.consumes({"play": doc.Boolean("Whether to be playing or not")}) @openapi.parameter("play", openapi.Boolean(description="Whether to be playing or not"))
@response_json @response_json
async def play_set(request: Request, mpv_control: MPVControl): async def play_set(request: Request, mpv_control: MPVControl):
if "play" not in request.args: if "play" not in request.args:
@ -81,15 +81,15 @@ async def play_set(request: Request, mpv_control: MPVControl):
return locals() return locals()
@bp.get("/volume") @bp.get("/volume")
@doc.summary("Get the current player volume") @openapi.summary("Get the current player volume")
@response_json @response_json
async def volume_get(request: Request, mpv_control: MPVControl): async def volume_get(request: Request, mpv_control: MPVControl):
value = await mpv_control.volume_get() value = await mpv_control.volume_get()
return locals() return locals()
@bp.post("/volume") @bp.post("/volume")
@doc.summary("Set the player volume") @openapi.summary("Set the player volume")
@doc.consumes({"volume": doc.Integer("A number between 0 and 100")}) @openapi.parameter("volume", openapi.Integer(description="A number between 0 and 100"))
@response_json @response_json
async def volume_set(request: Request, mpv_control: MPVControl): async def volume_set(request: Request, mpv_control: MPVControl):
if "volume" not in request.args: if "volume" not in request.args:
@ -99,7 +99,7 @@ async def volume_set(request: Request, mpv_control: MPVControl):
return locals() return locals()
@bp.get("/time") @bp.get("/time")
@doc.summary("Get current playback position") @openapi.summary("Get current playback position")
@response_json @response_json
async def time_get(request: Request, mpv_control: MPVControl): async def time_get(request: Request, mpv_control: MPVControl):
value = { value = {
@ -110,8 +110,9 @@ async def time_get(request: Request, mpv_control: MPVControl):
return locals() return locals()
@bp.post("/time") @bp.post("/time")
@doc.summary("Set playback position") @openapi.summary("Set playback position")
@doc.consumes({"pos": doc.Float("Seconds to seek to"), "pos": doc.Integer("Percent to seek to")}) @openapi.parameter("pos", openapi.Float(description="Seconds to seek to"))
@openapi.parameter("percent", openapi.Integer(description="Percent to seek to"))
@response_json @response_json
async def time_set(request: Request, mpv_control: MPVControl): async def time_set(request: Request, mpv_control: MPVControl):
if "pos" in request.args: if "pos" in request.args:
@ -123,7 +124,7 @@ async def time_set(request: Request, mpv_control: MPVControl):
return locals() return locals()
@bp.get("/playlist") @bp.get("/playlist")
@doc.summary("Get the current playlist") @openapi.summary("Get the current playlist")
@response_json @response_json
async def playlist_get(request: Request, mpv_control: MPVControl): async def playlist_get(request: Request, mpv_control: MPVControl):
value = await mpv_control.playlist_get() value = await mpv_control.playlist_get()
@ -136,22 +137,22 @@ async def playlist_get(request: Request, mpv_control: MPVControl):
return locals() return locals()
@bp.post("/playlist/next") @bp.post("/playlist/next")
@doc.summary("Skip to the next item in the playlist") @openapi.summary("Skip to the next item in the playlist")
@response_json @response_json
async def playlist_next(request: Request, mpv_control: MPVControl): async def playlist_next(request: Request, mpv_control: MPVControl):
success = await mpv_control.playlist_next() success = await mpv_control.playlist_next()
return locals() return locals()
@bp.post("/playlist/previous") @bp.post("/playlist/previous")
@doc.summary("Go back to the previous item in the playlist") @openapi.summary("Go back to the previous item in the playlist")
@response_json @response_json
async def playlist_previous(request: Request, mpv_control: MPVControl): async def playlist_previous(request: Request, mpv_control: MPVControl):
success = await mpv_control.playlist_prev() success = await mpv_control.playlist_prev()
return locals() return locals()
@bp.post("/playlist/goto") @bp.post("/playlist/goto")
@doc.summary("Go chosen item in the playlist") @openapi.summary("Go chosen item in the playlist")
@doc.consumes({"index": doc.Integer("The 0 indexed playlist item to go to")}, required=True) @openapi.parameter("index", openapi.Integer(description="The 0 indexed playlist item to go to"), required=True)
@response_json @response_json
async def playlist_goto(request: Request, mpv_control: MPVControl): async def playlist_goto(request: Request, mpv_control: MPVControl):
if "index" not in request.args: if "index" not in request.args:
@ -161,8 +162,8 @@ async def playlist_goto(request: Request, mpv_control: MPVControl):
return locals() return locals()
@bp.delete("/playlist") @bp.delete("/playlist")
@doc.summary("Clears single item or whole playlist") @openapi.summary("Clears single item or whole playlist")
@doc.consumes({"index": doc.Integer("Index to item in playlist to remove. If unset, the whole playlist is cleared")}) @openapi.parameter("index", openapi.Integer(description="Index to item in playlist to remove. If unset, the whole playlist is cleared"))
@response_json @response_json
async def playlist_remove_or_clear(request: Request, mpv_control: MPVControl): async def playlist_remove_or_clear(request: Request, mpv_control: MPVControl):
if "index" in request.args: if "index" in request.args:
@ -174,15 +175,15 @@ async def playlist_remove_or_clear(request: Request, mpv_control: MPVControl):
return locals() return locals()
@bp.post("/playlist/move") @bp.post("/playlist/move")
@doc.summary("Move playlist item to new position") @openapi.summary("Move playlist item to new position")
@doc.description( @openapi.description(
"Move the playlist entry at index1, so that it takes the " "Move the playlist entry at index1, so that it takes the "
"place of the entry index2. (Paradoxically, the moved playlist " "place of the entry index2. (Paradoxically, the moved playlist "
"entry will not have the index value index2 after moving if index1 " "entry will not have the index value index2 after moving if index1 "
"was lower than index2, because index2 refers to the target entry, " "was lower than index2, because index2 refers to the target entry, "
"not the index the entry will have after moving.)") "not the index the entry will have after moving.)")
@doc.consumes({"index2": int}, required=True) @openapi.parameter("index2", int, required=True)
@doc.consumes({"index1": int}, required=True) @openapi.parameter("index1", int, required=True)
@response_json @response_json
async def playlist_move(request: Request, mpv_control: MPVControl): async def playlist_move(request: Request, mpv_control: MPVControl):
if "index1" not in request.args or "index2" not in request.args: if "index1" not in request.args or "index2" not in request.args:
@ -195,22 +196,22 @@ async def playlist_move(request: Request, mpv_control: MPVControl):
return locals() return locals()
@bp.post("/playlist/shuffle") @bp.post("/playlist/shuffle")
@doc.summary("Clears single item or whole playlist") @openapi.summary("Clears single item or whole playlist")
@response_json @response_json
async def playlist_shuffle(request: Request, mpv_control: MPVControl): async def playlist_shuffle(request: Request, mpv_control: MPVControl):
success = await mpv_control.playlist_shuffle() success = await mpv_control.playlist_shuffle()
return locals() return locals()
@bp.get("/playlist/loop") @bp.get("/playlist/loop")
@doc.summary("See whether it loops the playlist or not") @openapi.summary("See whether it loops the playlist or not")
@response_json @response_json
async def playlist_get_looping(request: Request, mpv_control: MPVControl): async def playlist_get_looping(request: Request, mpv_control: MPVControl):
value = await mpv_control.playlist_get_looping() value = await mpv_control.playlist_get_looping()
return locals() return locals()
@bp.post("/playlist/loop") @bp.post("/playlist/loop")
@doc.summary("Sets whether to loop the playlist or not") @openapi.summary("Sets whether to loop the playlist or not")
@doc.consumes({"loop": doc.Boolean("Whether to be looping or not")}, required=True) @openapi.parameter("loop", openapi.Boolean(description="Whether to be looping or not"), required=True)
@response_json @response_json
async def playlist_set_looping(request: Request, mpv_control: MPVControl): async def playlist_set_looping(request: Request, mpv_control: MPVControl):
if "loop" not in request.args: if "loop" not in request.args:

910
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -10,7 +10,8 @@ python = ">=3.7,<4.0"
mpv = ">=0.1" # TODO: do we use this? mpv = ">=0.1" # TODO: do we use this?
youtube_dl = "^2021.12.17" youtube_dl = "^2021.12.17"
sanic = ">=21.12.2" sanic = ">=21.12.2"
sanic-openapi = ">=21.6.1" sanic-ext = ">=23.6.0"
#sanic-openapi = ">=21.6.1"
[tool.poetry.dev-dependencies] [tool.poetry.dev-dependencies]
python-lsp-server = {extras = ["all"], version = "^1.3.3"} python-lsp-server = {extras = ["all"], version = "^1.3.3"}