diff options
| author | Eddy Pedroni <epedroni@pm.me> | 2025-07-16 07:10:50 +0200 | 
|---|---|---|
| committer | Eddy Pedroni <epedroni@pm.me> | 2025-07-16 07:10:50 +0200 | 
| commit | 1dcde6cc9cb322b743e0b0355c697af869c2934a (patch) | |
| tree | e4cae31881e3eb129bcdc998dee706f8cda2a590 | |
| parent | 1d42bfe5f7b3c671fc5b50e716c5e8aa68728fb3 (diff) | |
Session manager add song, interface, web UI tested
| -rw-r--r-- | solo-tool-project/src/solo_tool/session_manager.py | 31 | ||||
| -rw-r--r-- | solo-tool-project/test/session_manager_unittest.py | 10 | ||||
| -rw-r--r-- | web-project/src/solo_tool_web.py | 15 | 
3 files changed, 44 insertions, 12 deletions
| diff --git a/solo-tool-project/src/solo_tool/session_manager.py b/solo-tool-project/src/solo_tool/session_manager.py index 4fae19f..ece67d8 100644 --- a/solo-tool-project/src/solo_tool/session_manager.py +++ b/solo-tool-project/src/solo_tool/session_manager.py @@ -1,9 +1,28 @@ +from typing import BinaryIO, Protocol +from abc import abstractmethod  from glob import glob  import json  from pathlib import Path  from . import SoloTool -class FileSystemSessionManager: +class SessionManager(Protocol): +    @abstractmethod +    def getSessions(self) -> list[str]: +        raise NotImplementedError + +    @abstractmethod +    def loadSession(self, key: str, player=None) -> SoloTool: +        raise NotImplementedError + +    @abstractmethod +    def saveSession(self, soloTool: SoloTool, key: str) -> None: +        raise NotImplementedError + +    @abstractmethod +    def addSong(self, name: str, content: BinaryIO) -> None: +        raise NotImplementedError + +class _FileSystemSessionManager(SessionManager):      def __init__(self, songPool: str, sessionPath: str):          self._songPool = Path(songPool)          self._sessionPath = Path(sessionPath) @@ -39,5 +58,11 @@ class FileSystemSessionManager:          with open(self._sessionPath / f"{key}.json", "w") as f:              json.dump(session, f) -def getSessionManager(songPool: str, sessionPath: str) -> FileSystemSessionManager: -    return FileSystemSessionManager(songPool, sessionPath) +    def addSong(self, name: str, content: BinaryIO): +        from shutil import copyfileobj +        newSong = self._songPool / name +        with open(newSong, "wb") as f: +            copyfileobj(content, f) + +def getSessionManager(songPool: str, sessionPath: str) -> SessionManager: +    return _FileSystemSessionManager(songPool, sessionPath) diff --git a/solo-tool-project/test/session_manager_unittest.py b/solo-tool-project/test/session_manager_unittest.py index bd6fbb6..bef4e5d 100644 --- a/solo-tool-project/test/session_manager_unittest.py +++ b/solo-tool-project/test/session_manager_unittest.py @@ -64,3 +64,13 @@ def test_loadAndSaveEmptySession(sessionManager, sessionPath, soloTool, tmp_path      assert reloadedTool.songs == [] +def test_uploadSong(sessionManager, songPool, tmp_path): +    song = tmp_path / "song-to-be-uploaded.mp3" +    song.touch() +     +    expected = songPool / "song-to-be-uploaded.mp3" +    assert not expected.exists() + +    with open(song, "rb") as f: +        sessionManager.addSong("song-to-be-uploaded.mp3", f) +    assert expected.exists() diff --git a/web-project/src/solo_tool_web.py b/web-project/src/solo_tool_web.py index 5512408..7b36b75 100644 --- a/web-project/src/solo_tool_web.py +++ b/web-project/src/solo_tool_web.py @@ -2,7 +2,7 @@ import sys  from os import getenv  from os.path import basename, splitext  from functools import partial -from nicegui import ui +from nicegui import ui, events  from starlette.formparsers import MultiPartParser  import click @@ -45,13 +45,9 @@ def sessionPage(sessionName: str):      st = sessions[sessionName]      # Upload song dialog -    def handleFileUpload(e): -        if False: -            from shutil import copyfileobj -            newSong = f"{SONG_POOL}/{e.name}" -            with open(newSong, "wb") as f: -                copyfileobj(e.content, f) -            st.addSong(newSong) +    def handleFileUpload(e: events.UploadEventArguments): +        sessionManager.addSong(e.name, e.content) +        st.addSong(e.name)      with ui.dialog() as uploadSongDialog:          ui.upload(label="Upload songs", auto_upload=True, on_upload=handleFileUpload).classes('max-w-full') @@ -63,7 +59,7 @@ def sessionPage(sessionName: str):              ui.label().bind_text_from(st, 'song', lambda index: fileName(st.songs[index]) if index is not None else "Select a song").classes('text-lg')          with ui.row().classes('items-center justify-start'):              ui.button(icon='home', on_click=lambda: ui.navigate.to("/")).props('flat dense round color=white') -            def save(): sessionManager.saveSession(st, f"{sessionName}.json") +            def save(): sessionManager.saveSession(st, sessionName)              ui.button(icon='save', on_click=save).props('flat dense round color=white')              ui.button(icon='fullscreen', on_click=fullscreen.toggle).props('flat dense round color=white') @@ -121,6 +117,7 @@ def landingPage():          ui.button(name, on_click=partial(ui.navigate.to, f"/{name}"))  def start(port, refresh, reload, session_path, song_path): +    global sessionManager      sessionManager = getSessionManager(song_path, session_path)      for key in sessionManager.getSessions(): | 
