fix: synology_api/photos.py update docstrings to comply with Numpydoc standards

This commit is contained in:
Luboš Zíma
2025-07-12 11:53:40 +07:00
parent 5229ead500
commit 76bbc6f1bc

View File

@ -1,3 +1,9 @@
"""
Photos API wrapper for Synology DSM.
This module provides a class to interact with the Synology Photos API.
"""
from __future__ import annotations
from typing import Optional, Any
from . import base_api
@ -5,6 +11,37 @@ import json
class Photos(base_api.BaseApi):
"""
Interface for Synology Photos API.
Provides methods to interact with Photos features such as retrieving user info,
folders, albums, sharing, and items.
Parameters
----------
ip_address : str
The IP address or hostname of the Synology NAS.
port : str
The port number to connect to.
username : str
The username for authentication.
password : str
The password for authentication.
secure : bool, optional
Whether to use HTTPS. Default is False.
cert_verify : bool, optional
Whether to verify SSL certificates. Default is False.
dsm_version : int, optional
DSM version. Default is 7.
debug : bool, optional
Enable debug output. Default is True.
otp_code : str, optional
One-time password for 2FA, if required.
device_id : str, optional
Device ID for the session.
device_name : str, optional
Device name for the session.
"""
def __init__(self,
ip_address: str,
@ -19,6 +56,34 @@ class Photos(base_api.BaseApi):
device_id: Optional[str] = None,
device_name: Optional[str] = None
) -> None:
"""
Initialize the Photos API interface.
Parameters
----------
ip_address : str
The IP address or hostname of the Synology NAS.
port : str
The port number to connect to.
username : str
The username for authentication.
password : str
The password for authentication.
secure : bool, optional
Whether to use HTTPS. Default is False.
cert_verify : bool, optional
Whether to verify SSL certificates. Default is False.
dsm_version : int, optional
DSM version. Default is 7.
debug : bool, optional
Enable debug output. Default is True.
otp_code : str, optional
One-time password for 2FA, if required.
device_id : str, optional
Device ID for the session.
device_name : str, optional
Device name for the session.
"""
super(Photos, self).__init__(ip_address, port, username, password, secure, cert_verify,
dsm_version, debug, otp_code, device_id, device_name, 'FotoStation')
@ -32,6 +97,14 @@ class Photos(base_api.BaseApi):
self._userinfo: Any = None
def get_userinfo(self) -> Any:
"""
Retrieve user information for the current session.
Returns
-------
Any
The user information data.
"""
if self._userinfo is not None:
return self._userinfo
@ -44,6 +117,19 @@ class Photos(base_api.BaseApi):
return self._userinfo
def get_folder(self, folder_id: int = 0) -> dict[str, object] | str:
"""
Retrieve information about a specific folder.
Parameters
----------
folder_id : int, optional
The ID of the folder. Default is 0.
Returns
-------
dict[str, object] or str
The folder information or an error message.
"""
api_name = 'SYNO.Foto.Browse.Folder'
info = self.photos_list[api_name]
api_path = info['path']
@ -58,6 +144,25 @@ class Photos(base_api.BaseApi):
offset: int = 0,
additional: str | list[str] = None
) -> dict[str, object] | str:
"""
List folders in Personal Space.
Parameters
----------
folder_id : int, optional
The parent folder ID. Default is 0.
limit : int, optional
Maximum number of folders to return. Default is 1000.
offset : int, optional
Number of folders to skip. Default is 0.
additional : str or list of str, optional
Additional fields to include.
Returns
-------
dict[str, object] or str
The list of folders or an error message.
"""
return self._list_folders(folder_id, limit, offset, additional, 'SYNO.Foto.Browse.Folder')
def list_teams_folders(self,
@ -66,10 +171,50 @@ class Photos(base_api.BaseApi):
offset: int = 0,
additional: Optional[str | list[str]] = None
) -> dict[str, object] | str:
"""
List folders in Team Space.
Parameters
----------
folder_id : int, optional
The parent folder ID. Default is 0.
limit : int, optional
Maximum number of folders to return. Default is 2000.
offset : int, optional
Number of folders to skip. Default is 0.
additional : str or list of str, optional
Additional fields to include.
Returns
-------
dict[str, object] or str
The list of team folders or an error message.
"""
return self._list_folders(folder_id, limit, offset, additional, 'SYNO.FotoTeam.Browse.Folder')
def _list_folders(self, folder_id: int, limit: int, offset: int, additional: Optional[str | list[str]],
api_name: str) -> Any:
"""
Internal method to list folders.
Parameters
----------
folder_id : int
The parent folder ID.
limit : int
Maximum number of folders to return.
offset : int
Number of folders to skip.
additional : str or list of str, optional
Additional fields to include.
api_name : str
API name to use.
Returns
-------
Any
The API response.
"""
if additional is None:
additional = []
info = self.photos_list[api_name]
@ -80,12 +225,53 @@ class Photos(base_api.BaseApi):
return self.request_data(api_name, api_path, req_param)
def count_folders(self, folder_id: int = 0) -> dict[str, object] | str:
"""
Count folders in Personal Space.
Parameters
----------
folder_id : int, optional
The parent folder ID. Default is 0.
Returns
-------
dict[str, object] or str
The count of folders or an error message.
"""
return self._count_folders(folder_id, 'SYNO.Foto.Browse.Folder')
def count_team_folders(self, folder_id: int = 0) -> dict[str, object] | str:
"""
Count folders in Team Space.
Parameters
----------
folder_id : int, optional
The parent folder ID. Default is 0.
Returns
-------
dict[str, object] or str
The count of team folders or an error message.
"""
return self._count_folders(folder_id, 'SYNO.FotoTeam.Browse.Folder')
def _count_folders(self, folder_id: int, api_name: str) -> Any:
"""
Internal method to count folders.
Parameters
----------
folder_id : int
The parent folder ID.
api_name : str
API name to use.
Returns
-------
Any
The API response.
"""
info = self.photos_list[api_name]
api_path = info['path']
req_param = {'version': info['maxVersion'],
@ -94,12 +280,55 @@ class Photos(base_api.BaseApi):
return self.request_data(api_name, api_path, req_param)
def lookup_folder(self, path: str) -> dict[str, object] | str:
"""
Lookup a folder by path in Personal Space.
Parameters
----------
path : str
The folder path.
Returns
-------
dict[str, object] or str
The folder information or None if not found.
"""
return self._lookup_folder(path, 'SYNO.FotoBrowse.Folder', 'SYNO.Foto.Browse.Folder')
def lookup_team_folder(self, path: str) -> dict[str, object] | str:
"""
Lookup a folder by path in Team Space.
Parameters
----------
path : str
The folder path.
Returns
-------
dict[str, object] or str
The folder information or None if not found.
"""
return self._lookup_folder(path, 'SYNO.FotoTeam.Browse.Folder', 'SYNO.FotoTeam.Browse.Folder')
def _lookup_folder(self, path: str, api_name_count: str, api_name_list: str) -> Optional[dict[str, object]]:
"""
Internal method to lookup a folder by path.
Parameters
----------
path : str
The folder path.
api_name_count : str
API name for counting folders.
api_name_list : str
API name for listing folders.
Returns
-------
dict[str, object] or None
The folder information or None if not found.
"""
parent = 0
found_path = ''
folder = ''
@ -124,6 +353,21 @@ class Photos(base_api.BaseApi):
return folder
def get_album(self, album_id: str, additional: Optional[str | list[str]] = None) -> dict[str, object] | str:
"""
Retrieve information about a specific album.
Parameters
----------
album_id : str
The album ID.
additional : str or list of str, optional
Additional fields to include.
Returns
-------
dict[str, object] or str
The album information or an error message.
"""
if not isinstance(album_id, list):
album_id = [album_id]
if additional is None:
@ -137,6 +381,21 @@ class Photos(base_api.BaseApi):
return self.request_data(api_name, api_path, req_param)
def list_albums(self, offset: int = 0, limit: int = 100) -> dict[str, object] | str:
"""
List albums.
Parameters
----------
offset : int, optional
Number of albums to skip. Default is 0.
limit : int, optional
Maximum number of albums to return. Default is 100.
Returns
-------
dict[str, object] or str
The list of albums or an error message.
"""
api_name = 'SYNO.Foto.Browse.Album'
info = self.photos_list[api_name]
api_path = info['path']
@ -150,6 +409,23 @@ class Photos(base_api.BaseApi):
condition: Optional[list[str]] = None,
user_id: Optional[str] = None
) -> dict[str, object] | str:
"""
Suggest album conditions based on a keyword.
Parameters
----------
keyword : str
The keyword to suggest conditions for.
condition : list of str, optional
List of conditions to use. Default is ['general_tag'].
user_id : str, optional
User ID to use. If None, uses the current user.
Returns
-------
dict[str, object] or str
The suggested conditions or an error message.
"""
if condition is None:
condition = ['general_tag']
if user_id is None:
@ -164,6 +440,21 @@ class Photos(base_api.BaseApi):
return self.request_data(api_name, api_path, req_param)
def create_album(self, name: str, condition: list[str]) -> dict[str, object] | str:
"""
Create a new album with the specified condition.
Parameters
----------
name : str
The name of the album.
condition : list of str
The condition for the album.
Returns
-------
dict[str, object] or str
The API response for album creation.
"""
api_name = 'SYNO.Foto.Browse.ConditionAlbum'
info = self.photos_list[api_name]
api_path = info['path']
@ -173,6 +464,19 @@ class Photos(base_api.BaseApi):
return self.request_data(api_name, api_path, req_param)
def delete_album(self, album_id: str) -> dict[str, object] | str:
"""
Delete an album by ID.
Parameters
----------
album_id : str
The album ID.
Returns
-------
dict[str, object] or str
The API response for album deletion.
"""
if not isinstance(album_id, list):
album_id = [album_id]
api_name = 'SYNO.Foto.Browse.Album'
@ -184,6 +488,21 @@ class Photos(base_api.BaseApi):
return self.request_data(api_name, api_path, req_param)
def set_album_condition(self, folder_id: int, condition: list[str]) -> dict[str, object] | str:
"""
Set the condition for an album.
Parameters
----------
folder_id : int
The folder ID.
condition : list of str
The condition to set.
Returns
-------
dict[str, object] or str
The API response for setting the condition.
"""
api_name = 'SYNO.Foto.Browse.ConditionAlbum'
info = self.photos_list[api_name]
api_path = info['path']
@ -198,6 +517,25 @@ class Photos(base_api.BaseApi):
enabled: bool = True,
expiration: int | str = 0
) -> Any:
"""
Share an album with specified permissions.
Parameters
----------
album_id : str
The album ID.
permission : str or list of str, optional
Permissions to set.
enabled : bool, optional
Whether sharing is enabled. Default is True.
expiration : int or str, optional
Expiration time for the share. Default is 0.
Returns
-------
Any
The API response for sharing the album.
"""
self._share('SYNO.Foto.Sharing.Passphrase', policy='album', permission=permission, album_id=album_id,
enabled=enabled, expiration=expiration)
@ -207,6 +545,25 @@ class Photos(base_api.BaseApi):
enabled: bool = True,
expiration: int | str = 0
) -> Any:
"""
Share a team folder with specified permissions.
Parameters
----------
folder_id : int
The folder ID.
permission : str, optional
Permissions to set.
enabled : bool, optional
Whether sharing is enabled. Default is True.
expiration : int or str, optional
Expiration time for the share. Default is 0.
Returns
-------
Any
The API response for sharing the team folder.
"""
self._share('SYNO.FotoTeam.Sharing.Passphrase', policy='folder', permission=permission, folder_id=folder_id,
enabled=enabled, expiration=expiration)
@ -217,6 +574,27 @@ class Photos(base_api.BaseApi):
expiration: int | str,
**kwargs
) -> dict[str, object] | Any:
"""
Internal method to share an album or folder.
Parameters
----------
api_name : str
API name to use.
policy : str
Sharing policy.
permission : str
Permissions to set.
expiration : int or str
Expiration time for the share.
**kwargs
Additional keyword arguments.
Returns
-------
dict[str, object] or Any
The API response for sharing.
"""
info = self.photos_list[api_name]
api_path = info['path']
req_param = {'version': info['maxVersion'],
@ -236,6 +614,19 @@ class Photos(base_api.BaseApi):
return self.request_data(api_name, api_path, req_param)
def list_shareable_users_and_groups(self, team_space_sharable_list: bool = False) -> dict[str, object] | str:
"""
List users and groups that can be shared with.
Parameters
----------
team_space_sharable_list : bool, optional
Whether to include team space sharable list. Default is False.
Returns
-------
dict[str, object] or str
The list of users and groups or an error message.
"""
api_name = 'SYNO.Foto.Sharing.Misc'
info = self.photos_list[api_name]
api_path = info['path']
@ -247,44 +638,35 @@ class Photos(base_api.BaseApi):
def list_item_in_folders(self, offset: int = 0, limit: int = 0, folder_id: int = 0, sort_by: str = 'filename',
sort_direction: str = 'desc', type: str = None, passphrase: str = None,
additional: list = None) -> dict[str, object] | str:
"""List all items in all folders in Personal Space
Parameters
----------
offset : int
Specify how many shared folders are skipped before beginning to return listed shared folders.
limit : int
Number of shared folders requested. Set to `0` to list all shared folders.
folder_id : int
ID of folder
sort_by : str, optional
Possible values:
- `filename`
- `filesize`
- `takentime`
- `item_type`
sort_direction : str, optional
Possible values: `asc` or `desc`. Defaults to: `desc`
passphrase : str, optional
Passphrase for a shared album
additional : list[str]
Possible values:
`["thumbnail","resolution", "orientation", "video_convert", "video_meta", "provider_user_id", "exif", "tag", "description", "gps", "geocoding_id", "address", "person"]`
type : str
Possible values:
- `photo`: Photo
- `video`: Video
- `live`: iPhone live photos'
"""
List all items in all folders in Personal Space.
Parameters
----------
offset : int
Specify how many shared folders are skipped before beginning to return listed shared folders.
limit : int
Number of shared folders requested. Set to `0` to list all shared folders.
folder_id : int
ID of folder.
sort_by : str, optional
Possible values: 'filename', 'filesize', 'takentime', 'item_type'.
sort_direction : str, optional
Possible values: 'asc' or 'desc'. Defaults to: 'desc'.
type : str, optional
Possible values: 'photo', 'video', 'live'.
passphrase : str, optional
Passphrase for a shared album.
additional : list, optional
Additional fields to include.
Possible values:
`["thumbnail","resolution", "orientation", "video_convert", "video_meta", "provider_user_id", "exif", "tag", "description", "gps", "geocoding_id", "address", "person"]`.
Returns
-------
dict[str, object] or str
The list of items or an error message.
"""
api_name = 'SYNO.Foto.Browse.Item'
info = self.photos_list[api_name]
api_path = info['path']
@ -301,6 +683,14 @@ class Photos(base_api.BaseApi):
return self.request_data(api_name, api_path, req_param)
def list_search_filters(self) -> dict[str, object] | str:
"""
List available search filters.
Returns
-------
dict[str, object] or str
The list of search filters or an error message.
"""
api_name = 'SYNO.Foto.Search.Filter'
info = self.photos_list[api_name]
api_path = info['path']
@ -309,6 +699,14 @@ class Photos(base_api.BaseApi):
return self.request_data(api_name, api_path, req_param)
def get_guest_settings(self) -> dict[str, object] | str:
"""
Retrieve guest settings for Photos.
Returns
-------
dict[str, object] or str
The guest settings or an error message.
"""
api_name = 'SYNO.Foto.Setting.Guest'
info = self.photos_list[api_name]
api_path = info['path']