nc-py-api 0.17.1__py3-none-any.whl → 0.18.0__py3-none-any.whl

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/_session.py CHANGED
@@ -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)
nc_py_api/_version.py CHANGED
@@ -1,3 +1,3 @@
1
1
  """Version of nc_py_api."""
2
2
 
3
- __version__ = "0.17.1"
3
+ __version__ = "0.18.0"
@@ -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.lstrip("/").split("/", maxsplit=2)[1]
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 self.full_path.lstrip("/").split("/", maxsplit=2)[-1]
232
+ return user_path_regex.sub("", self.full_path, count=1)
227
233
 
228
234
  @property
229
235
  def is_shared(self) -> bool:
nc_py_api/files/files.py CHANGED
@@ -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.download2fp(
119
- "/index.php/apps/files/ajax/download.php", fp, dav=False, params={"dir": path}, **kwargs
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.download2fp(
123
- "/index.php/apps/files/ajax/download.php", fp, dav=False, params={"dir": path}, **kwargs
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:
nc_py_api/users.py CHANGED
@@ -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", None)
373
- email = kwargs.get("email", None)
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}
nc_py_api/webhooks.py CHANGED
@@ -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}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: nc-py-api
3
- Version: 0.17.1
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>=1; extra == 'docs'
74
- Requires-Dist: sphinx>=6.2; extra == 'docs'
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
 
@@ -4,10 +4,10 @@ nc_py_api/_exceptions.py,sha256=7vbUECaLmD7RJBCU27t4fuP6NmQK6r4508u_gS4szhI,2298
4
4
  nc_py_api/_misc.py,sha256=dUzCP9VmyhtICTsn1aexlFAYUioBm40k6Zh-YE5WwCY,3333
5
5
  nc_py_api/_preferences.py,sha256=OtovFZuGHnHYKjdDjSnUappO795tW8Oxj7qVaejHWpQ,2479
6
6
  nc_py_api/_preferences_ex.py,sha256=tThj6U0ZZMaBZ-jUkjrbaI0xDnafWsBowQKsC6gjOQs,7179
7
- nc_py_api/_session.py,sha256=iFv8_xkPA_erhUNvSvjUJvhKL3yCnq2xHNkL8PHLbrA,20180
7
+ nc_py_api/_session.py,sha256=ZD0TKrL-tOpxYtV6AO0cwRrYzbnjBr_ylCEUirrykjU,20242
8
8
  nc_py_api/_talk_api.py,sha256=0Uo7OduYniuuX3UQPb468RyGJJ-PWBCgJ5HoPuz5Qa0,51068
9
9
  nc_py_api/_theming.py,sha256=hTr3nuOemSuRFZaPy9iXNmBM7rDgQHECH43tHMWGqEY,1870
10
- nc_py_api/_version.py,sha256=CSuVzDV5v1IVnCLmZ23tjFH9hOciQqyc4WRmAjRx8qw,52
10
+ nc_py_api/_version.py,sha256=t3qny54XTwpi3rVJqMS8yB4HNF5ZcqFIKiy_TGER6lQ,52
11
11
  nc_py_api/activity.py,sha256=t9VDSnnaXRNOvALqOSGCeXSQZ-426pCOMSfQ96JHys4,9574
12
12
  nc_py_api/apps.py,sha256=Us2y2lszdxXlD8t6kxwd5_Nrrmazc0EvZXIH9O-ol80,9315
13
13
  nc_py_api/calendar.py,sha256=-T6CJ8cRbJZTLtxSEDWuuYpD29DMJGCTfLONmtxZV9w,1445
@@ -19,10 +19,10 @@ nc_py_api/options.py,sha256=K5co-fIfFVbwF6r3sqWsJF3cKgAbS2CjLAXdyTOkP9s,1717
19
19
  nc_py_api/talk.py,sha256=OZFemYkDOaM6o4xAK3EvQbjMFiK75E5qnsCDyihIElg,29368
20
20
  nc_py_api/talk_bot.py,sha256=_RuImwb3jYvUKX3ywcX095ucOjECCxsuc59heIxNoTM,16725
21
21
  nc_py_api/user_status.py,sha256=I101nwYS8X1WvC8AnLa2f3qJUCPDPHrbq-ke0h1VT4E,13282
22
- nc_py_api/users.py,sha256=ixMHBFJtrlvqmZqJ73VdbOZ6CbRnppdsRpjIJnMUtYY,15488
22
+ nc_py_api/users.py,sha256=SQG8Agplaxy7XJgguK-rxV-azpc-QdktbDmLmQtJkXo,15476
23
23
  nc_py_api/users_groups.py,sha256=IPxw-Ks5NjCm6r8_HC9xmf3IYptH00ulITbp5iazhAo,6289
24
24
  nc_py_api/weather_status.py,sha256=wAkjuJPjxc0Rxe4za0BzfwB0XeUmkCXoisJtTH3-qdQ,7582
25
- nc_py_api/webhooks.py,sha256=-cRqpgQFhjlGV0c7k0vLp2JtVw_UeYElecag650kD64,7044
25
+ nc_py_api/webhooks.py,sha256=14nAMy-tnOvmRnJbo42zUHyjX-z6kc9OMDUVKzNmplY,7769
26
26
  nc_py_api/ex_app/__init__.py,sha256=hFbu6wTXs-wmjs1tavm_HYLwiqgrp7_qJe-stzCiqfI,692
27
27
  nc_py_api/ex_app/defs.py,sha256=FaQInH3jLugKxDUqpwrXdkMT-lBxmoqWmXJXc11fa6A,727
28
28
  nc_py_api/ex_app/events_listener.py,sha256=pgQ4hSQV39NuP9F9IDWxo0Qle6oG15-Ol2FlItnIBGY,4682
@@ -41,13 +41,13 @@ nc_py_api/ex_app/ui/resources.py,sha256=Vwx69oZ93Ouh6HJtGUqaKFUr4Reo74H4vT1YCpb-
41
41
  nc_py_api/ex_app/ui/settings.py,sha256=f0R17lGhBfo2JQULVw_hFxhpfoPw_CW7vBu0Rb1ABJw,6623
42
42
  nc_py_api/ex_app/ui/top_menu.py,sha256=oCgGtIoMYbp-5iN5aXEbT7Q88HtccR7hg6IBFgbbyX4,5118
43
43
  nc_py_api/ex_app/ui/ui.py,sha256=OqFHKn6oIZli8T1wnv6YtQ4glNfeNb90WwGCvtWI1Z4,1632
44
- nc_py_api/files/__init__.py,sha256=p1RecBNkZCuu8_mf-y_mkbotj9fGsCDSFRl7hGkI1CA,17003
44
+ nc_py_api/files/__init__.py,sha256=uSjqZyYAq9x3xOb_yz15KNNAcPo1PhbpPLtPz_ej-Eo,17303
45
45
  nc_py_api/files/_files.py,sha256=_s_f8xbzQPEH2F2LNwomI9CxscYHryus1pMZ_vW00C4,13666
46
- nc_py_api/files/files.py,sha256=DuAMkfmRGtNJntMIo-yEYhZ-a3KhhhnwKATcGqpxJL4,24569
47
- nc_py_api/files/files_async.py,sha256=rEIT6P1Pb7TeTub1dAB5IKpR4LDqHWc5LclAEzpiHEQ,25410
46
+ nc_py_api/files/files.py,sha256=6G4zONjnI7oSCUf4C79xrFV4QUYquxZDCLlpkGvME0M,24912
47
+ nc_py_api/files/files_async.py,sha256=nyDeWiGx_8CHuVrNThSgfZy0l-WlC4El-TzJONo0TsM,25773
48
48
  nc_py_api/files/sharing.py,sha256=VRZCl-TYK6dbu9rUHPs3_jcVozu1EO8bLGZwoRpiLsU,14439
49
- nc_py_api-0.17.1.dist-info/METADATA,sha256=xSjepRylRZB3RNOy4uynbbMa-BmYI1owibOt2ggvDqI,9455
50
- nc_py_api-0.17.1.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
51
- nc_py_api-0.17.1.dist-info/licenses/AUTHORS,sha256=Y1omFHyI8ned9k4jJXs2ATgmgi1GmQ7EZ6S1gxqnX2k,572
52
- nc_py_api-0.17.1.dist-info/licenses/LICENSE.txt,sha256=OLEMh401fAumGHfRSna365MLIfnjdTcdOHZ6QOzMjkg,1551
53
- nc_py_api-0.17.1.dist-info/RECORD,,
49
+ nc_py_api-0.18.0.dist-info/METADATA,sha256=_cUiEBjdiSBuqx6RM9HyIMR_pjr62TanPtBpb9DFmlw,9451
50
+ nc_py_api-0.18.0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
51
+ nc_py_api-0.18.0.dist-info/licenses/AUTHORS,sha256=B2Q9q9XH3PAxJp0V3GiKQc1l0z7vtGDpDHqda-ISWKM,616
52
+ nc_py_api-0.18.0.dist-info/licenses/LICENSE.txt,sha256=OLEMh401fAumGHfRSna365MLIfnjdTcdOHZ6QOzMjkg,1551
53
+ nc_py_api-0.18.0.dist-info/RECORD,,
@@ -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: