Skip to content

Commit

Permalink
Feat/add docstrings (#43)
Browse files Browse the repository at this point in the history
* Add docstrings for exception handling

* Add docstrings for the bookmarks endpoints

* Add docstrings for the browsing endpoints

* Add chat, internet radio and jukebox endpoints docstrings

* Add lists endpoints docstrings

* Add media retrieval endpoints docstrings

* Add media annotation endpoints docstrings

* Add podcast endpoints docstrings

* Add searching and sharing endpoints docstrings

* Add system endpoints and Subsonic object docstrings

* Add user management endpoints docstrings

* Add docstrings for album models

* Add docstrings for artist, artist index, bookmark, chat message, contributor, over art and genre models

* Add docstrings for internet radio station, jukebox, lyrics, music directory and music folder models and the base model class

* Add docstrings for jukebox, now playing entry, play queue, playlist, podcast, replay gain, scan status, search result, share, song and starred contentmodels

* Add docstrings for jukebox, now playing entry, play queue, playlist, podcast, replay gain, scan status, search result, share, song and starred contentmodels

* Update TODO.md

---------

Co-authored-by: Kutu <[email protected]>
  • Loading branch information
kutu-dev and Kutu authored Jun 1, 2024
1 parent 59b418f commit 45783bb
Show file tree
Hide file tree
Showing 57 changed files with 2,589 additions and 1,492 deletions.
6 changes: 2 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
# Knuckles
> A [OpenSubsonic](https://opensubsonic.netlify.app/) API wrapper for Python.
> A [OpenSubsonic](https://opensubsonic.netlify.app/) API wrapper for Python 3.11.0+.
## Compatiblity
Knuckles **only** works with servers compatible with the REST API version 1.4.0 onwards (Subsonic 4.2+).
It follows strictly the [OpenSubsonic API Spec](https://opensubsonic.netlify.app/docs/opensubsonic-api/), being fully retro-compatible with the original [Subsonic API](https://subsonic.org/pages/api.jsp).
It follows strictly the [OpenSubsonic API Spec](https://opensubsonic.netlify.app/docs/opensubsonic-api/), it being fully retro-compatible with the original [Subsonic API](https://subsonic.org/pages/api.jsp).

### Quickstart
...

## Acknowledgements
Created with :heart: by [Jorge "Kutu" Dobón Blanco](https://dobon.dev).

::: knuckles.models._user
7 changes: 7 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# TODO

- [ ] Add `justfile`.
- [ ] Remove `pre-commit`.
- [ ] Custom git-hooks?
- [ ] Document in contributing why attributes are double typed.
- [ ] Add general documentation and tutorials.
12 changes: 6 additions & 6 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ tests = [
"responses>=0.23.1",
]
docs = [
"mkdocs==1.5.3",
"mkdocs-material==9.5.18",
"mkdocstrings[python]==0.24.3",
"mkdocs-gen-files==0.5.0",
"pymdown-extensions==10.8.0",
"mkdocs-literate-nav==0.6.1"
"mkdocs>=1.5.3",
"mkdocs-material>=9.5.18",
"mkdocstrings[python]>=0.24.3",
"mkdocs-gen-files>=0.5.0",
"pymdown-extensions>=10.8.0",
"mkdocs-literate-nav>=0.6.1"
]

[build-system]
Expand Down
4 changes: 2 additions & 2 deletions src/knuckles/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
from ._subsonic import Subsonic
from .models._album import Album, AlbumInfo, Disc, RecordLabel, ReleaseDate
from .models._artist import Artist, ArtistInfo
from .models._artist_index import ArtistIndex
from .models._bookmark import Bookmark
from .models._chat_message import ChatMessage
from .models._contributor import Contributor
from .models._cover_art import CoverArt
from .models._genre import Genre, ItemGenre
from .models._index import Index
from .models._internet_radio_station import InternetRadioStation
from .models._jukebox import Jukebox
from .models._lyrics import Lyrics
Expand Down Expand Up @@ -45,7 +45,7 @@
"CoverArt",
"ItemGenre",
"Genre",
"Index",
"ArtistIndex",
"InternetRadioStation",
"Jukebox",
"Lyrics",
Expand Down
4 changes: 2 additions & 2 deletions src/knuckles/_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from requests import Response
from requests.models import PreparedRequest

from .exceptions import CODE_ERROR_EXCEPTIONS, get_code_error_exception
from .exceptions import ERROR_CODE_EXCEPTION, get_error_code_exception


class RequestMethod(Enum):
Expand Down Expand Up @@ -182,7 +182,7 @@ def json_request(
json_response: dict[str, Any] = response.json()["subsonic-response"]

if json_response["status"] == "failed":
code_error: CODE_ERROR_EXCEPTIONS = get_code_error_exception(
code_error: ERROR_CODE_EXCEPTION = get_error_code_exception(
json_response["error"]["code"]
)

Expand Down
132 changes: 68 additions & 64 deletions src/knuckles/_bookmarks.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,103 +9,108 @@


class Bookmarks:
"""Class that contains all the methods needed to interact
with the browsing calls in the Subsonic API.
<https://opensubsonic.netlify.app/categories/bookmarks/>
"""Class that contains all the methods needed to interact with the
[bookmark endpoints](https://opensubsonic.netlify.app/
categories/bookmarks/) in the Subsonic API.
"""

def __init__(self, api: Api, subsonic: "Subsonic") -> None:
self.api = api
self.subsonic = subsonic

def get_bookmarks(self) -> list[Bookmark]:
"""Calls the "getBookmarks" endpoints of the API.
"""Get all the bookmarks created by the authenticated user.
:return: A list with all the bookmarks given by the server.
:rtype: list[Bookmark]
Returns:
A list containing all the bookmarks for the authenticated user.
"""

response = self.api.json_request("getBookmarks")["bookmarks"]["bookmark"]

return [Bookmark(self.subsonic, **bookmark) for bookmark in response]

def get_bookmark(self, id_: str) -> Bookmark | None:
"""Using the "getBookmarks" endpoint iterates over all the bookmarks
and find the one with the same ID.
def get_bookmark(self, bookmark_id: str) -> Bookmark | None:
"""Get all the info of a bookmark given its ID.
:param id_: The ID of the song of the bookmark to find.
:type id_: str
:return: The found bookmark or None if no one is found.
:rtype: Bookmark | None
Args:
bookmark_id: The id of the bookmark to get.
Returns:
A object that contains all the info of the requested bookmark.
"""

bookmarks = self.get_bookmarks()

for bookmark in bookmarks:
if bookmark.song.id == id_:
if bookmark.song.id == bookmark_id:
return bookmark

return None

def create_bookmark(
self, id_: str, position: int, comment: str | None = None
self, song_or_video_id: str, position: int, comment: str | None = None
) -> Bookmark:
"""Calls the "createBookmark" endpoint of the API.
:param id_: The ID of the song of the bookmark.
:type id_: str
:param position: The position in seconds of the bookmark.
:type position: int
:param comment: The comment of the bookmark, defaults to None.
:type comment: str | None, optional
:return: The new created share.
:rtype: Bookmark
"""Creates a new bookmark for the authenticated user.
Args:
song_or_video_id: The ID of the song or video to bookmark.
position: A position in milliseconds to be indicated with the song
or video.
comment: A comment to be attached with the song or video.
Returns:
An object that contains all the info of the new created
bookmark.
"""

self.api.json_request(
"createBookmark", {"id": id_, "position": position, "comment": comment}
"createBookmark",
{"id": song_or_video_id, "position": position, "comment": comment},
)

# Fake the song structure given by in the API.
return Bookmark(self.subsonic, {"id": id_}, position=position, comment=comment)
return Bookmark(
self.subsonic, {"id": song_or_video_id}, position=position, comment=comment
)

def update_bookmark(
self, id_: str, position: int, comment: str | None = None
self, song_or_video_id: str, position: int, comment: str | None = None
) -> Bookmark:
"""Method that internally calls the create_bookmark method
as creating and updating a bookmark uses the same endpoint. Useful for having
more self-descriptive code.
:param id_: The ID of the song of the bookmark.
:type id_: str
:param position: The position in seconds of the bookmark.
:type position: int
:param comment: The comment of the bookmark, defaults to None.
:type comment: str | None, optional
:return: A Bookmark object with all the updated info.
:rtype: Bookmark
"""Updates a bookmark for the authenticated user.
Args:
song_or_video_id: The ID of the song or video to update its
bookmark.
position: A position in milliseconds to be indicated with the song
or video.
comment: A comment to be attached with the song or video.
Returns:
An object that contains all the info of the new created
bookmark.
"""

return self.create_bookmark(id_, position, comment)
return self.create_bookmark(song_or_video_id, position, comment)

def delete_bookmark(self, id_: str) -> "Subsonic":
"""Calls the "deleteBookmark" endpoint of the API.
def delete_bookmark(self, song_or_video_id: str) -> "Subsonic":
"""Deletes a bookmark for the authenticated user.
:param id_: The ID of the song of the bookmark to delete.
:type id_: str
:return: The object itself to allow method chaining.
:rtype: Subsonic
Args:
song_or_video_id: The ID of the song or video to delete its
bookmark.
Returns:
The Subsonic object where this method was called to allow
method chaining.
"""

self.api.json_request("deleteBookmark", {"id": id_})
self.api.json_request("deleteBookmark", {"id": song_or_video_id})

return self.subsonic

def get_play_queue(self) -> PlayQueue:
"""Calls the "getPlayQueue" endpoint of the API.
"""Get the play queue of the authenticated user.
:return: The play queue of the authenticated user.
:rtype: PlayQueue
Returns:
An object that contains all the info of the
play queue of the user.
"""

response = self.api.json_request("getPlayQueue")["playQueue"]
Expand All @@ -118,18 +123,17 @@ def save_play_queue(
current_song_id: str | None = None,
position: int | None = None,
) -> PlayQueue:
"""Calls the "savePlayQueue" endpoint of the API.
:param song_ids: A list with all the IDs of the songs to add.
:type song_ids: list[str]
:param current_song_id: The ID of the current song in the queue,
defaults to None.
:type current_song_id: str | None, optional
:param position: The position in seconds of the current song,
defaults to None.
:type position: int | None, optional
:return: The new saved play queue.
:rtype: PlayQueue
"""Saves a new play queue for the authenticated user.
Args:
song_ids: A list with all the songs to add to the queue.
current_song_id: The ID of the current playing song.
position: A position in milliseconds of where the current song
playback it at.
Returns:
An object that contains all the info of the new
saved play queue.
"""

self.api.json_request(
Expand Down
Loading

0 comments on commit 45783bb

Please sign in to comment.