nc-py-api 0.17.0__tar.gz → 0.18.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/AUTHORS +1 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/CHANGELOG.md +21 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/PKG-INFO +3 -3
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/_session.py +2 -2
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/_version.py +1 -1
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/apps.py +0 -13
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/ex_app/__init__.py +1 -0
- nc_py_api-0.18.0/nc_py_api/ex_app/logging.py +46 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/files/__init__.py +8 -2
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/files/files.py +8 -3
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/files/files_async.py +8 -3
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/nextcloud.py +24 -12
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/users.py +2 -2
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/webhooks.py +15 -1
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/pyproject.toml +3 -2
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/.gitignore +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/LICENSE.txt +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/README.md +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/__init__.py +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/_deffered_error.py +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/_exceptions.py +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/_misc.py +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/_preferences.py +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/_preferences_ex.py +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/_talk_api.py +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/_theming.py +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/activity.py +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/calendar.py +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/ex_app/defs.py +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/ex_app/events_listener.py +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/ex_app/integration_fastapi.py +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/ex_app/misc.py +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/ex_app/occ_commands.py +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/ex_app/persist_transformers_cache.py +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/ex_app/providers/__init__.py +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/ex_app/providers/providers.py +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/ex_app/providers/task_processing.py +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/ex_app/ui/__init__.py +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/ex_app/ui/files_actions.py +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/ex_app/ui/resources.py +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/ex_app/ui/settings.py +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/ex_app/ui/top_menu.py +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/ex_app/ui/ui.py +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/ex_app/uvicorn_fastapi.py +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/files/_files.py +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/files/sharing.py +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/loginflow_v2.py +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/notes.py +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/notifications.py +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/options.py +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/talk.py +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/talk_bot.py +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/user_status.py +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/users_groups.py +0 -0
- {nc_py_api-0.17.0 → nc_py_api-0.18.0}/nc_py_api/weather_status.py +0 -0
|
@@ -6,6 +6,7 @@ answer newbie questions, and generally made NC-Py-API that much better:
|
|
|
6
6
|
Alexander Piskun <bigcat88@icloud.com>
|
|
7
7
|
CooperGerman <https://github.com/CooperGerman>
|
|
8
8
|
Tobias Tschech <Tobias@tschech-online.de>
|
|
9
|
+
Scott Williams <scottwilliams@ucsb.edu>
|
|
9
10
|
<Please alphabetize new entries>
|
|
10
11
|
|
|
11
12
|
A big THANK YOU goes to:
|
|
@@ -2,6 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.18.0 - 2024-10-09]
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- New `webhooks.unregister_all` method. #309
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- Files: `user` and `user_path` properties in `FSNode` when Nextcloud located in the sub-path. #297 Thanks to @vwbusguy
|
|
14
|
+
- `files.download_directory_as_zip` method now supports upcoming Nextcloud 31. #304
|
|
15
|
+
|
|
16
|
+
## [0.17.1 - 2024-09-06]
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
- NextcloudApp: `setup_nextcloud_logging` function to support transparently sending logs to Nextcloud. #294
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
|
|
24
|
+
- NextcloudApp: `nc.log` now suppresses all exceptions to safe call it anywhere(for example in exception handlers). #293
|
|
25
|
+
|
|
5
26
|
## [0.17.0 - 2024-09-05]
|
|
6
27
|
|
|
7
28
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: nc-py-api
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.18.0
|
|
4
4
|
Summary: Nextcloud Python Framework
|
|
5
5
|
Project-URL: Changelog, https://github.com/cloud-py-api/nc_py_api/blob/main/CHANGELOG.md
|
|
6
6
|
Project-URL: Documentation, https://cloud-py-api.github.io/nc_py_api/
|
|
@@ -70,8 +70,8 @@ Requires-Dist: caldav==1.3.6; extra == 'docs'
|
|
|
70
70
|
Requires-Dist: sphinx-copybutton; extra == 'docs'
|
|
71
71
|
Requires-Dist: sphinx-inline-tabs; extra == 'docs'
|
|
72
72
|
Requires-Dist: sphinx-issues>=3.0.1; extra == 'docs'
|
|
73
|
-
Requires-Dist: sphinx-rtd-theme
|
|
74
|
-
Requires-Dist: sphinx
|
|
73
|
+
Requires-Dist: sphinx-rtd-theme<3; extra == 'docs'
|
|
74
|
+
Requires-Dist: sphinx<8; extra == 'docs'
|
|
75
75
|
Requires-Dist: uvicorn[standard]>=0.23.2; extra == 'docs'
|
|
76
76
|
Description-Content-Type: text/markdown
|
|
77
77
|
|
|
@@ -301,7 +301,7 @@ class NcSessionBasic(NcSessionBase, ABC):
|
|
|
301
301
|
|
|
302
302
|
def download2fp(self, url_path: str, fp, dav: bool, params=None, **kwargs):
|
|
303
303
|
adapter = self.adapter_dav if dav else self.adapter
|
|
304
|
-
with adapter.stream("GET", url_path, params=params) as response:
|
|
304
|
+
with adapter.stream("GET", url_path, params=params, headers=kwargs.get("headers")) as response:
|
|
305
305
|
check_error(response)
|
|
306
306
|
for data_chunk in response.iter_raw(chunk_size=kwargs.get("chunk_size", 5 * 1024 * 1024)):
|
|
307
307
|
fp.write(data_chunk)
|
|
@@ -425,7 +425,7 @@ class AsyncNcSessionBasic(NcSessionBase, ABC):
|
|
|
425
425
|
|
|
426
426
|
async def download2fp(self, url_path: str, fp, dav: bool, params=None, **kwargs):
|
|
427
427
|
adapter = self.adapter_dav if dav else self.adapter
|
|
428
|
-
async with adapter.stream("GET", url_path, params=params) as response:
|
|
428
|
+
async with adapter.stream("GET", url_path, params=params, headers=kwargs.get("headers")) as response:
|
|
429
429
|
check_error(response)
|
|
430
430
|
async for data_chunk in response.aiter_raw(chunk_size=kwargs.get("chunk_size", 5 * 1024 * 1024)):
|
|
431
431
|
fp.write(data_chunk)
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"""Nextcloud API for working with applications."""
|
|
2
2
|
|
|
3
3
|
import dataclasses
|
|
4
|
-
import datetime
|
|
5
4
|
|
|
6
5
|
from ._misc import require_capabilities
|
|
7
6
|
from ._session import AsyncNcSessionBasic, NcSessionBasic
|
|
@@ -34,18 +33,6 @@ class ExAppInfo:
|
|
|
34
33
|
"""Flag indicating if the application enabled."""
|
|
35
34
|
return bool(self._raw_data["enabled"])
|
|
36
35
|
|
|
37
|
-
@property
|
|
38
|
-
def last_check_time(self) -> datetime.datetime:
|
|
39
|
-
"""Time of the last successful application check."""
|
|
40
|
-
return datetime.datetime.utcfromtimestamp(int(self._raw_data["last_check_time"])).replace(
|
|
41
|
-
tzinfo=datetime.timezone.utc
|
|
42
|
-
)
|
|
43
|
-
|
|
44
|
-
@property
|
|
45
|
-
def system(self) -> bool:
|
|
46
|
-
"""**DEPRECATED** Flag indicating if the application is a system application."""
|
|
47
|
-
return True
|
|
48
|
-
|
|
49
36
|
def __repr__(self):
|
|
50
37
|
return f"<{self.__class__.__name__} id={self.app_id}, ver={self.version}>"
|
|
51
38
|
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""Transparent logging support to store logs in the nextcloud.log."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
import threading
|
|
5
|
+
|
|
6
|
+
from ..nextcloud import NextcloudApp
|
|
7
|
+
from .defs import LogLvl
|
|
8
|
+
|
|
9
|
+
LOGLVL_MAP = {
|
|
10
|
+
logging.NOTSET: LogLvl.DEBUG,
|
|
11
|
+
logging.DEBUG: LogLvl.DEBUG,
|
|
12
|
+
logging.INFO: LogLvl.INFO,
|
|
13
|
+
logging.WARNING: LogLvl.WARNING,
|
|
14
|
+
logging.ERROR: LogLvl.ERROR,
|
|
15
|
+
logging.CRITICAL: LogLvl.FATAL,
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
THREAD_LOCAL = threading.local()
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class _NextcloudLogsHandler(logging.Handler):
|
|
22
|
+
def __init__(self):
|
|
23
|
+
super().__init__()
|
|
24
|
+
|
|
25
|
+
def emit(self, record):
|
|
26
|
+
if THREAD_LOCAL.__dict__.get("nc_py_api.loghandler", False):
|
|
27
|
+
return
|
|
28
|
+
|
|
29
|
+
try:
|
|
30
|
+
THREAD_LOCAL.__dict__["nc_py_api.loghandler"] = True
|
|
31
|
+
log_entry = self.format(record)
|
|
32
|
+
log_level = record.levelno
|
|
33
|
+
NextcloudApp().log(LOGLVL_MAP.get(log_level, LogLvl.FATAL), log_entry, fast_send=True)
|
|
34
|
+
except Exception: # noqa pylint: disable=broad-exception-caught
|
|
35
|
+
self.handleError(record)
|
|
36
|
+
finally:
|
|
37
|
+
THREAD_LOCAL.__dict__["nc_py_api.loghandler"] = False
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def setup_nextcloud_logging(logger_name: str | None = None, logging_level: int = logging.DEBUG):
|
|
41
|
+
"""Function to easily send all or selected log entries to Nextcloud."""
|
|
42
|
+
logger = logging.getLogger(logger_name)
|
|
43
|
+
nextcloud_handler = _NextcloudLogsHandler()
|
|
44
|
+
nextcloud_handler.setLevel(logging_level)
|
|
45
|
+
logger.addHandler(nextcloud_handler)
|
|
46
|
+
return nextcloud_handler
|
|
@@ -5,12 +5,18 @@ import datetime
|
|
|
5
5
|
import email.utils
|
|
6
6
|
import enum
|
|
7
7
|
import os
|
|
8
|
+
import re
|
|
8
9
|
import warnings
|
|
9
10
|
|
|
10
11
|
from pydantic import BaseModel
|
|
11
12
|
|
|
12
13
|
from .. import _misc
|
|
13
14
|
|
|
15
|
+
user_regex = re.compile(r"(?:files|trashbin|versions)/([^/]+)/")
|
|
16
|
+
"""Regex for evaluating user from full path string; instantiated once on import."""
|
|
17
|
+
user_path_regex = re.compile(r".*?(files|trashbin|versions)/([^/]+)/")
|
|
18
|
+
"""Regex for evaluating user path from full path string; instantiated once on import."""
|
|
19
|
+
|
|
14
20
|
|
|
15
21
|
class LockType(enum.IntEnum):
|
|
16
22
|
"""Nextcloud File Locks types."""
|
|
@@ -218,12 +224,12 @@ class FsNode:
|
|
|
218
224
|
@property
|
|
219
225
|
def user(self) -> str:
|
|
220
226
|
"""Returns user ID extracted from the `full_path`."""
|
|
221
|
-
return self.full_path
|
|
227
|
+
return user_regex.findall(self.full_path)[0]
|
|
222
228
|
|
|
223
229
|
@property
|
|
224
230
|
def user_path(self) -> str:
|
|
225
231
|
"""Returns path relative to the user's root directory."""
|
|
226
|
-
return
|
|
232
|
+
return user_path_regex.sub("", self.full_path, count=1)
|
|
227
233
|
|
|
228
234
|
@property
|
|
229
235
|
def is_shared(self) -> bool:
|
|
@@ -115,9 +115,14 @@ class FilesAPI:
|
|
|
115
115
|
path = path.user_path if isinstance(path, FsNode) else path
|
|
116
116
|
result_path = local_path if local_path else os.path.basename(path)
|
|
117
117
|
with open(result_path, "wb") as fp:
|
|
118
|
-
self._session.
|
|
119
|
-
|
|
120
|
-
|
|
118
|
+
if self._session.nc_version["major"] >= 31:
|
|
119
|
+
full_path = dav_get_obj_path(self._session.user, path)
|
|
120
|
+
accept_header = f"application/{kwargs.get('format', 'zip')}"
|
|
121
|
+
self._session.download2fp(quote(full_path), fp, dav=True, headers={"Accept": accept_header})
|
|
122
|
+
else:
|
|
123
|
+
self._session.download2fp(
|
|
124
|
+
"/index.php/apps/files/ajax/download.php", fp, dav=False, params={"dir": path}, **kwargs
|
|
125
|
+
)
|
|
121
126
|
return Path(result_path)
|
|
122
127
|
|
|
123
128
|
def upload(self, path: str | FsNode, content: bytes | str) -> FsNode:
|
|
@@ -119,9 +119,14 @@ class AsyncFilesAPI:
|
|
|
119
119
|
path = path.user_path if isinstance(path, FsNode) else path
|
|
120
120
|
result_path = local_path if local_path else os.path.basename(path)
|
|
121
121
|
with open(result_path, "wb") as fp:
|
|
122
|
-
await self._session.
|
|
123
|
-
|
|
124
|
-
|
|
122
|
+
if (await self._session.nc_version)["major"] >= 31:
|
|
123
|
+
full_path = dav_get_obj_path(await self._session.user, path)
|
|
124
|
+
accept_header = f"application/{kwargs.get('format', 'zip')}"
|
|
125
|
+
await self._session.download2fp(quote(full_path), fp, dav=True, headers={"Accept": accept_header})
|
|
126
|
+
else:
|
|
127
|
+
await self._session.download2fp(
|
|
128
|
+
"/index.php/apps/files/ajax/download.php", fp, dav=False, params={"dir": path}, **kwargs
|
|
129
|
+
)
|
|
125
130
|
return Path(result_path)
|
|
126
131
|
|
|
127
132
|
async def upload(self, path: str | FsNode, content: bytes | str) -> FsNode:
|
|
@@ -348,13 +348,18 @@ class NextcloudApp(_NextcloudBasic):
|
|
|
348
348
|
return bool(self._session.ocs("GET", "/ocs/v1.php/apps/app_api/ex-app/state"))
|
|
349
349
|
return False
|
|
350
350
|
|
|
351
|
-
def log(self, log_lvl: LogLvl, content: str) -> None:
|
|
351
|
+
def log(self, log_lvl: LogLvl, content: str, fast_send: bool = False) -> None:
|
|
352
352
|
"""Writes log to the Nextcloud log file."""
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
353
|
+
int_log_lvl = int(log_lvl)
|
|
354
|
+
if int_log_lvl < 0 or int_log_lvl > 4:
|
|
355
|
+
raise ValueError("Invalid `log_lvl` value")
|
|
356
|
+
if not fast_send:
|
|
357
|
+
if self.check_capabilities("app_api"):
|
|
358
|
+
return
|
|
359
|
+
if int_log_lvl < self.capabilities["app_api"].get("loglevel", 0):
|
|
360
|
+
return
|
|
361
|
+
with contextlib.suppress(Exception):
|
|
362
|
+
self._session.ocs("POST", f"{self._session.ae_url}/log", json={"level": int_log_lvl, "message": content})
|
|
358
363
|
|
|
359
364
|
def users_list(self) -> list[str]:
|
|
360
365
|
"""Returns list of users on the Nextcloud instance."""
|
|
@@ -478,13 +483,20 @@ class AsyncNextcloudApp(_AsyncNextcloudBasic):
|
|
|
478
483
|
return bool(await self._session.ocs("GET", "/ocs/v1.php/apps/app_api/ex-app/state"))
|
|
479
484
|
return False
|
|
480
485
|
|
|
481
|
-
async def log(self, log_lvl: LogLvl, content: str) -> None:
|
|
486
|
+
async def log(self, log_lvl: LogLvl, content: str, fast_send: bool = False) -> None:
|
|
482
487
|
"""Writes log to the Nextcloud log file."""
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
+
int_log_lvl = int(log_lvl)
|
|
489
|
+
if int_log_lvl < 0 or int_log_lvl > 4:
|
|
490
|
+
raise ValueError("Invalid `log_lvl` value")
|
|
491
|
+
if not fast_send:
|
|
492
|
+
if await self.check_capabilities("app_api"):
|
|
493
|
+
return
|
|
494
|
+
if int_log_lvl < (await self.capabilities)["app_api"].get("loglevel", 0):
|
|
495
|
+
return
|
|
496
|
+
with contextlib.suppress(Exception):
|
|
497
|
+
await self._session.ocs(
|
|
498
|
+
"POST", f"{self._session.ae_url}/log", json={"level": int_log_lvl, "message": content}
|
|
499
|
+
)
|
|
488
500
|
|
|
489
501
|
async def users_list(self) -> list[str]:
|
|
490
502
|
"""Returns list of users on the Nextcloud instance."""
|
|
@@ -369,8 +369,8 @@ class _AsyncUsersAPI:
|
|
|
369
369
|
|
|
370
370
|
|
|
371
371
|
def _create(user_id: str, display_name: str | None, **kwargs) -> dict[str, typing.Any]:
|
|
372
|
-
password = kwargs.get("password"
|
|
373
|
-
email = kwargs.get("email"
|
|
372
|
+
password = kwargs.get("password")
|
|
373
|
+
email = kwargs.get("email")
|
|
374
374
|
if not password and not email:
|
|
375
375
|
raise ValueError("Either password or email must be set")
|
|
376
376
|
data = {"userid": user_id}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import dataclasses
|
|
4
4
|
|
|
5
5
|
from ._misc import clear_from_params_empty # , require_capabilities
|
|
6
|
-
from ._session import AsyncNcSessionBasic, NcSessionBasic
|
|
6
|
+
from ._session import AppConfig, AsyncNcSessionBasic, NcSessionBasic
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
@dataclasses.dataclass
|
|
@@ -140,6 +140,13 @@ class _WebhooksAPI:
|
|
|
140
140
|
def unregister(self, webhook_id: int) -> bool:
|
|
141
141
|
return self._session.ocs("DELETE", f"{self._ep_base}/{webhook_id}")
|
|
142
142
|
|
|
143
|
+
def unregister_all(self, appid: str = "") -> int:
|
|
144
|
+
if not appid and isinstance(self._session.cfg, AppConfig):
|
|
145
|
+
appid = self._session.cfg.app_name
|
|
146
|
+
else:
|
|
147
|
+
raise ValueError("The `appid` parameter cannot be empty for non-ExApp use.")
|
|
148
|
+
return self._session.ocs("DELETE", f"{self._ep_base}/byappid/{appid}")
|
|
149
|
+
|
|
143
150
|
|
|
144
151
|
class _AsyncWebhooksAPI:
|
|
145
152
|
"""The class provides the async application management API on the Nextcloud server."""
|
|
@@ -208,3 +215,10 @@ class _AsyncWebhooksAPI:
|
|
|
208
215
|
|
|
209
216
|
async def unregister(self, webhook_id: int) -> bool:
|
|
210
217
|
return await self._session.ocs("DELETE", f"{self._ep_base}/{webhook_id}")
|
|
218
|
+
|
|
219
|
+
async def unregister_all(self, appid: str = "") -> int:
|
|
220
|
+
if not appid and isinstance(self._session.cfg, AppConfig):
|
|
221
|
+
appid = self._session.cfg.app_name
|
|
222
|
+
else:
|
|
223
|
+
raise ValueError("The `appid` parameter cannot be empty for non-ExApp use.")
|
|
224
|
+
return await self._session.ocs("DELETE", f"{self._ep_base}/byappid/{appid}")
|
|
@@ -77,11 +77,11 @@ optional-dependencies.dev-min = [
|
|
|
77
77
|
optional-dependencies.docs = [
|
|
78
78
|
"autodoc-pydantic>=2.0.1",
|
|
79
79
|
"nc-py-api[app,calendar]",
|
|
80
|
-
"sphinx
|
|
80
|
+
"sphinx<8",
|
|
81
81
|
"sphinx-copybutton",
|
|
82
82
|
"sphinx-inline-tabs",
|
|
83
83
|
"sphinx-issues>=3.0.1",
|
|
84
|
-
"sphinx-rtd-theme
|
|
84
|
+
"sphinx-rtd-theme<3",
|
|
85
85
|
]
|
|
86
86
|
urls.Changelog = "https://github.com/cloud-py-api/nc_py_api/blob/main/CHANGELOG.md"
|
|
87
87
|
urls.Documentation = "https://cloud-py-api.github.io/nc_py_api/"
|
|
@@ -207,6 +207,7 @@ messages_control.disable = [
|
|
|
207
207
|
"too-few-public-methods",
|
|
208
208
|
"too-many-public-methods",
|
|
209
209
|
"too-many-instance-attributes",
|
|
210
|
+
"too-many-positional-arguments",
|
|
210
211
|
]
|
|
211
212
|
|
|
212
213
|
[tool.pytest.ini_options]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|