nc-py-api 0.18.1__tar.gz → 0.19.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.
Files changed (55) hide show
  1. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/CHANGELOG.md +18 -0
  2. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/PKG-INFO +4 -22
  3. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/README.md +2 -21
  4. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/_session.py +3 -1
  5. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/_version.py +1 -1
  6. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/ex_app/__init__.py +1 -1
  7. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/ex_app/integration_fastapi.py +1 -1
  8. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/files/__init__.py +17 -0
  9. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/files/_files.py +4 -0
  10. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/nextcloud.py +1 -1
  11. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/options.py +12 -1
  12. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/pyproject.toml +1 -0
  13. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/.gitignore +0 -0
  14. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/AUTHORS +0 -0
  15. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/LICENSE.txt +0 -0
  16. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/__init__.py +0 -0
  17. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/_deffered_error.py +0 -0
  18. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/_exceptions.py +0 -0
  19. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/_misc.py +0 -0
  20. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/_preferences.py +0 -0
  21. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/_preferences_ex.py +0 -0
  22. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/_talk_api.py +0 -0
  23. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/_theming.py +0 -0
  24. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/activity.py +0 -0
  25. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/apps.py +0 -0
  26. /nc_py_api-0.18.1/nc_py_api/calendar.py → /nc_py_api-0.19.0/nc_py_api/calendar_api.py +0 -0
  27. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/ex_app/defs.py +0 -0
  28. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/ex_app/events_listener.py +0 -0
  29. /nc_py_api-0.18.1/nc_py_api/ex_app/logging.py → /nc_py_api-0.19.0/nc_py_api/ex_app/logger.py +0 -0
  30. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/ex_app/misc.py +0 -0
  31. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/ex_app/occ_commands.py +0 -0
  32. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/ex_app/persist_transformers_cache.py +0 -0
  33. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/ex_app/providers/__init__.py +0 -0
  34. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/ex_app/providers/providers.py +0 -0
  35. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/ex_app/providers/task_processing.py +0 -0
  36. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/ex_app/ui/__init__.py +0 -0
  37. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/ex_app/ui/files_actions.py +0 -0
  38. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/ex_app/ui/resources.py +0 -0
  39. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/ex_app/ui/settings.py +0 -0
  40. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/ex_app/ui/top_menu.py +0 -0
  41. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/ex_app/ui/ui.py +0 -0
  42. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/ex_app/uvicorn_fastapi.py +0 -0
  43. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/files/files.py +0 -0
  44. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/files/files_async.py +0 -0
  45. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/files/sharing.py +0 -0
  46. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/loginflow_v2.py +0 -0
  47. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/notes.py +0 -0
  48. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/notifications.py +0 -0
  49. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/talk.py +0 -0
  50. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/talk_bot.py +0 -0
  51. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/user_status.py +0 -0
  52. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/users.py +0 -0
  53. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/users_groups.py +0 -0
  54. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/weather_status.py +0 -0
  55. {nc_py_api-0.18.1 → nc_py_api-0.19.0}/nc_py_api/webhooks.py +0 -0
@@ -2,6 +2,24 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [0.19.0 - 2025-02-15]
6
+
7
+ ### Added
8
+
9
+ - Files: `FSNode` now have `creation_date` property. #335 Thanks to @SunnyFarmDay
10
+
11
+ ### Changed
12
+
13
+ - ExApps: no longer require the `AA-VERSION` header. (Nextcloud 32+) #336
14
+ - ExApps: `AppAPIAuthMiddleware` now secures the `websocket` connection. (Nextcloud 32+) #338
15
+
16
+ ## [0.18.2 - 2025-01-19]
17
+
18
+ ### Changed
19
+
20
+ - Default "User-Agent" for ExApps now set to `ExApp/appid/version (httpx/version)`. #329
21
+ - `System Trust Store` from now are used by default. #328
22
+
5
23
  ## [0.18.1 - 2025-01-14]
6
24
 
7
25
  ### Fixed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nc-py-api
3
- Version: 0.18.1
3
+ Version: 0.19.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/
@@ -34,6 +34,7 @@ Requires-Dist: fastapi>=0.109.2
34
34
  Requires-Dist: httpx>=0.25.2
35
35
  Requires-Dist: pydantic>=2.1.1
36
36
  Requires-Dist: python-dotenv>=1
37
+ Requires-Dist: truststore==0.10
37
38
  Requires-Dist: xmltodict>=0.13
38
39
  Provides-Extra: app
39
40
  Requires-Dist: uvicorn[standard]>=0.23.2; extra == 'app'
@@ -86,7 +87,7 @@ Description-Content-Type: text/markdown
86
87
  [![Docs](https://github.com/cloud-py-api/nc_py_api/actions/workflows/docs.yml/badge.svg)](https://cloud-py-api.github.io/nc_py_api/)
87
88
  [![codecov](https://codecov.io/github/cloud-py-api/nc_py_api/branch/main/graph/badge.svg?token=C91PL3FYDQ)](https://codecov.io/github/cloud-py-api/nc_py_api)
88
89
 
89
- ![NextcloudVersion](https://img.shields.io/badge/Nextcloud-27%20%7C%2028%20%7C%2029%20%7C%2030-blue)
90
+ ![NextcloudVersion](https://img.shields.io/badge/Nextcloud-%2028%20%7C%2029%20%7C%2030%20%7C%2031-blue)
90
91
  ![PythonVersion](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12-blue)
91
92
  ![impl](https://img.shields.io/pypi/implementation/nc_py_api)
92
93
  ![pypi](https://img.shields.io/pypi/v/nc_py_api.svg)
@@ -94,6 +95,7 @@ Description-Content-Type: text/markdown
94
95
  Python library that provides a robust and well-documented API that allows developers to interact with and extend Nextcloud's functionality.
95
96
 
96
97
  ### The key features are:
98
+
97
99
  * **Fast**: High performance, and as low-latency as possible.
98
100
  * **Intuitive**: Fast to code, easy to use.
99
101
  * **Reliable**: Minimum number of incompatible changes.
@@ -101,24 +103,6 @@ Python library that provides a robust and well-documented API that allows develo
101
103
  * **Easy**: Designed to be easy to use with excellent documentation.
102
104
  * **Sync + Async**: Provides both sync and async APIs.
103
105
 
104
- ### Capabilities
105
- | **_Capability_** | Nextcloud 27 | Nextcloud 28 | Nextcloud 29 | Nextcloud 30 |
106
- |------------------------------|:------------:|:------------:|:------------:|:------------:|
107
- | Calendar | ✅ | ✅ | ✅ | ✅ |
108
- | File System & Tags | ✅ | ✅ | ✅ | ✅ |
109
- | Nextcloud Talk | ✅ | ✅ | ✅ | ✅ |
110
- | Notifications | ✅ | ✅ | ✅ | ✅ |
111
- | Shares | ✅ | ✅ | ✅ | ✅ |
112
- | Users & Groups | ✅ | ✅ | ✅ | ✅ |
113
- | User & Weather status | ✅ | ✅ | ✅ | ✅ |
114
- | Other APIs** | ✅ | ✅ | ✅ | ✅ |
115
- | Talk Bot API* | ✅ | ✅ | ✅ | ✅ |
116
- | Settings UI API* | N/A | N/A | ✅ | ✅ |
117
- | TaskProcessing Provider API* | N/A | N/A | N/A | ✅ |
118
-
119
- &ast;_available only for **NextcloudApp**_<br>
120
- &ast;&ast;_Activity, Notes_
121
-
122
106
  ### Differences between the Nextcloud and NextcloudApp classes
123
107
 
124
108
  The **Nextcloud** class functions as a standard Nextcloud client,
@@ -135,8 +119,6 @@ but NextcloudApp has a broader selection since applications typically require ac
135
119
  Any code written for the Nextcloud class can easily be adapted for use with the NextcloudApp class,
136
120
  as long as it doesn't involve calls that require user password verification.
137
121
 
138
- **NextcloudApp** avalaible only from Nextcloud 27.1.2 and greater version with installed **AppAPI**.
139
-
140
122
  ### Nextcloud skeleton app in Python
141
123
 
142
124
  ```python3
@@ -8,7 +8,7 @@
8
8
  [![Docs](https://github.com/cloud-py-api/nc_py_api/actions/workflows/docs.yml/badge.svg)](https://cloud-py-api.github.io/nc_py_api/)
9
9
  [![codecov](https://codecov.io/github/cloud-py-api/nc_py_api/branch/main/graph/badge.svg?token=C91PL3FYDQ)](https://codecov.io/github/cloud-py-api/nc_py_api)
10
10
 
11
- ![NextcloudVersion](https://img.shields.io/badge/Nextcloud-27%20%7C%2028%20%7C%2029%20%7C%2030-blue)
11
+ ![NextcloudVersion](https://img.shields.io/badge/Nextcloud-%2028%20%7C%2029%20%7C%2030%20%7C%2031-blue)
12
12
  ![PythonVersion](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12-blue)
13
13
  ![impl](https://img.shields.io/pypi/implementation/nc_py_api)
14
14
  ![pypi](https://img.shields.io/pypi/v/nc_py_api.svg)
@@ -16,6 +16,7 @@
16
16
  Python library that provides a robust and well-documented API that allows developers to interact with and extend Nextcloud's functionality.
17
17
 
18
18
  ### The key features are:
19
+
19
20
  * **Fast**: High performance, and as low-latency as possible.
20
21
  * **Intuitive**: Fast to code, easy to use.
21
22
  * **Reliable**: Minimum number of incompatible changes.
@@ -23,24 +24,6 @@ Python library that provides a robust and well-documented API that allows develo
23
24
  * **Easy**: Designed to be easy to use with excellent documentation.
24
25
  * **Sync + Async**: Provides both sync and async APIs.
25
26
 
26
- ### Capabilities
27
- | **_Capability_** | Nextcloud 27 | Nextcloud 28 | Nextcloud 29 | Nextcloud 30 |
28
- |------------------------------|:------------:|:------------:|:------------:|:------------:|
29
- | Calendar | ✅ | ✅ | ✅ | ✅ |
30
- | File System & Tags | ✅ | ✅ | ✅ | ✅ |
31
- | Nextcloud Talk | ✅ | ✅ | ✅ | ✅ |
32
- | Notifications | ✅ | ✅ | ✅ | ✅ |
33
- | Shares | ✅ | ✅ | ✅ | ✅ |
34
- | Users & Groups | ✅ | ✅ | ✅ | ✅ |
35
- | User & Weather status | ✅ | ✅ | ✅ | ✅ |
36
- | Other APIs** | ✅ | ✅ | ✅ | ✅ |
37
- | Talk Bot API* | ✅ | ✅ | ✅ | ✅ |
38
- | Settings UI API* | N/A | N/A | ✅ | ✅ |
39
- | TaskProcessing Provider API* | N/A | N/A | N/A | ✅ |
40
-
41
- &ast;_available only for **NextcloudApp**_<br>
42
- &ast;&ast;_Activity, Notes_
43
-
44
27
  ### Differences between the Nextcloud and NextcloudApp classes
45
28
 
46
29
  The **Nextcloud** class functions as a standard Nextcloud client,
@@ -57,8 +40,6 @@ but NextcloudApp has a broader selection since applications typically require ac
57
40
  Any code written for the Nextcloud class can easily be adapted for use with the NextcloudApp class,
58
41
  as long as it doesn't involve calls that require user password verification.
59
42
 
60
- **NextcloudApp** avalaible only from Nextcloud 27.1.2 and greater version with installed **AppAPI**.
61
-
62
43
  ### Nextcloud skeleton app in Python
63
44
 
64
45
  ```python3
@@ -12,6 +12,7 @@ from json import loads
12
12
  from os import environ
13
13
 
14
14
  from httpx import AsyncClient, Client, Headers, Limits, ReadTimeout, Request, Response
15
+ from httpx import __version__ as httpx_version
15
16
  from starlette.requests import HTTPConnection
16
17
 
17
18
  from . import options
@@ -477,7 +478,6 @@ class NcSessionAppBasic(ABC):
477
478
 
478
479
  def sign_check(self, request: HTTPConnection) -> str:
479
480
  headers = {
480
- "AA-VERSION": request.headers.get("AA-VERSION", ""),
481
481
  "EX-APP-ID": request.headers.get("EX-APP-ID", ""),
482
482
  "EX-APP-VERSION": request.headers.get("EX-APP-VERSION", ""),
483
483
  "AUTHORIZATION-APP-API": request.headers.get("AUTHORIZATION-APP-API", ""),
@@ -511,6 +511,7 @@ class NcSessionApp(NcSessionAppBasic, NcSessionBasic):
511
511
  "AA-VERSION": self.cfg.aa_version,
512
512
  "EX-APP-ID": self.cfg.app_name,
513
513
  "EX-APP-VERSION": self.cfg.app_version,
514
+ "user-agent": f"ExApp/{self.cfg.app_name}/{self.cfg.app_version} (httpx/{httpx_version})",
514
515
  },
515
516
  )
516
517
 
@@ -535,6 +536,7 @@ class AsyncNcSessionApp(NcSessionAppBasic, AsyncNcSessionBasic):
535
536
  "AA-VERSION": self.cfg.aa_version,
536
537
  "EX-APP-ID": self.cfg.app_name,
537
538
  "EX-APP-VERSION": self.cfg.app_version,
539
+ "User-Agent": f"ExApp/{self.cfg.app_name}/{self.cfg.app_version} (httpx/{httpx_version})",
538
540
  },
539
541
  )
540
542
 
@@ -1,3 +1,3 @@
1
1
  """Version of nc_py_api."""
2
2
 
3
- __version__ = "0.18.1"
3
+ __version__ = "0.19.0"
@@ -10,7 +10,7 @@ from .integration_fastapi import (
10
10
  set_handlers,
11
11
  talk_bot_msg,
12
12
  )
13
- from .logging import setup_nextcloud_logging
13
+ from .logger import setup_nextcloud_logging
14
14
  from .misc import (
15
15
  get_computation_device,
16
16
  get_model_path,
@@ -241,7 +241,7 @@ class AppAPIAuthMiddleware:
241
241
 
242
242
  async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
243
243
  """Method that will be called by Starlette for each event."""
244
- if scope["type"] != "http":
244
+ if scope["type"] not in ("http", "websocket"):
245
245
  await self.app(scope, receive, send)
246
246
  return
247
247
 
@@ -86,6 +86,7 @@ class FsNodeInfo:
86
86
  is_version: bool
87
87
  """Flag indicating if the object is File Version representation"""
88
88
  _last_modified: datetime.datetime
89
+ _creation_date: datetime.datetime
89
90
  _trashbin: dict
90
91
 
91
92
  def __init__(self, **kwargs):
@@ -102,6 +103,10 @@ class FsNodeInfo:
102
103
  self.last_modified = kwargs.get("last_modified", datetime.datetime(1970, 1, 1))
103
104
  except (ValueError, TypeError):
104
105
  self.last_modified = datetime.datetime(1970, 1, 1)
106
+ try:
107
+ self.creation_date = kwargs.get("creation_date", datetime.datetime(1970, 1, 1))
108
+ except (ValueError, TypeError):
109
+ self.creation_date = datetime.datetime(1970, 1, 1)
105
110
  self._trashbin: dict[str, str | int] = {}
106
111
  for i in ("trashbin_filename", "trashbin_original_location", "trashbin_deletion_time"):
107
112
  if i in kwargs:
@@ -142,6 +147,18 @@ class FsNodeInfo:
142
147
  else:
143
148
  self._last_modified = value
144
149
 
150
+ @property
151
+ def creation_date(self) -> datetime.datetime:
152
+ """Time when the object was created."""
153
+ return self._creation_date
154
+
155
+ @creation_date.setter
156
+ def creation_date(self, value: str | datetime.datetime):
157
+ if isinstance(value, str):
158
+ self._creation_date = email.utils.parsedate_to_datetime(value)
159
+ else:
160
+ self._creation_date = value
161
+
145
162
  @property
146
163
  def in_trash(self) -> bool:
147
164
  """Returns ``True`` if the object is in trash."""
@@ -16,6 +16,7 @@ from . import FsNode, SystemTag
16
16
  PROPFIND_PROPERTIES = [
17
17
  "d:resourcetype",
18
18
  "d:getlastmodified",
19
+ "d:creationdate",
19
20
  "d:getcontentlength",
20
21
  "d:getcontenttype",
21
22
  "d:getetag",
@@ -45,6 +46,7 @@ SEARCH_PROPERTIES_MAP = {
45
46
  "name": "d:displayname", # like, eq
46
47
  "mime": "d:getcontenttype", # like, eq
47
48
  "last_modified": "d:getlastmodified", # gt, eq, lt
49
+ "creation_date": "d:creationdate", # gt, eq, lt
48
50
  "size": "oc:size", # gt, gte, eq, lt
49
51
  "favorite": "oc:favorite", # eq
50
52
  "fileid": "oc:fileid", # eq
@@ -286,6 +288,8 @@ def _parse_record(full_path: str, prop_stats: list[dict]) -> FsNode: # noqa pyl
286
288
  fs_node_args["etag"] = prop["d:getetag"]
287
289
  if "d:getlastmodified" in prop_keys:
288
290
  fs_node_args["last_modified"] = prop["d:getlastmodified"]
291
+ if "d:creationdate" in prop_keys:
292
+ fs_node_args["creation_date"] = prop["d:creationdate"]
289
293
  if "d:getcontenttype" in prop_keys:
290
294
  fs_node_args["mimetype"] = prop["d:getcontenttype"]
291
295
  if "oc:permissions" in prop_keys:
@@ -29,7 +29,7 @@ from ._talk_api import _AsyncTalkAPI, _TalkAPI
29
29
  from ._theming import ThemingInfo, get_parsed_theme
30
30
  from .activity import _ActivityAPI, _AsyncActivityAPI
31
31
  from .apps import _AppsAPI, _AsyncAppsAPI
32
- from .calendar import _CalendarAPI
32
+ from .calendar_api import _CalendarAPI
33
33
  from .ex_app.defs import LogLvl
34
34
  from .ex_app.events_listener import AsyncEventsListenerAPI, EventsListenerAPI
35
35
  from .ex_app.occ_commands import AsyncOccCommandsAPI, OccCommandsAPI
@@ -33,11 +33,22 @@ NPA_NC_CERT: bool | str
33
33
  SSL certificates (a.k.a CA bundle) used to verify the identity of requested hosts. Either **True** (default CA bundle),
34
34
  a path to an SSL certificate file, or **False** (which will disable verification)."""
35
35
  str_val = environ.get("NPA_NC_CERT", "True")
36
- NPA_NC_CERT = True
36
+ # https://github.com/encode/httpx/issues/302
37
+ # when "httpx" will switch to use "truststore" by default - uncomment next line
38
+ # NPA_NC_CERT = True
37
39
  if str_val.lower() in ("false", "0"):
38
40
  NPA_NC_CERT = False
39
41
  elif str_val.lower() not in ("true", "1"):
40
42
  NPA_NC_CERT = str_val
43
+ else:
44
+ # Temporary workaround, see comment above.
45
+ # Use system certificate stores
46
+
47
+ import ssl
48
+
49
+ import truststore
50
+
51
+ NPA_NC_CERT = truststore.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
41
52
 
42
53
  CHUNKED_UPLOAD_V2 = environ.get("CHUNKED_UPLOAD_V2", True)
43
54
  """Option to enable/disable **version 2** chunked upload(better Object Storages support).
@@ -49,6 +49,7 @@ dependencies = [
49
49
  "httpx>=0.25.2",
50
50
  "pydantic>=2.1.1",
51
51
  "python-dotenv>=1",
52
+ "truststore==0.10",
52
53
  "xmltodict>=0.13",
53
54
  ]
54
55
  optional-dependencies.app = [
File without changes
File without changes
File without changes
File without changes
File without changes