nc-py-api 0.20.0__py3-none-any.whl → 0.20.2__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.
@@ -61,6 +61,21 @@ class _BasicAppCfgPref:
61
61
  if not not_fail:
62
62
  raise e from None
63
63
 
64
+ def set_value(self, key: str, value: str, sensitive: bool | None = None) -> None:
65
+ """Sets a value and if specified the sensitive flag for a key.
66
+
67
+ .. note:: A sensitive flag ensures key value are encrypted and truncated in Nextcloud logs.
68
+ Default for new records is ``False`` when sensitive is *unspecified*, if changes existing record and
69
+ sensitive is *unspecified* it will not change the existing `sensitive` flag.
70
+ """
71
+ if not key:
72
+ raise ValueError("`key` parameter can not be empty")
73
+ require_capabilities("app_api", self._session.capabilities)
74
+ params: dict = {"configKey": key, "configValue": value}
75
+ if sensitive is not None:
76
+ params["sensitive"] = sensitive
77
+ self._session.ocs("POST", f"{self._session.ae_url}/{self._url_suffix}", json=params)
78
+
64
79
 
65
80
  class _AsyncBasicAppCfgPref:
66
81
  _url_suffix: str
@@ -104,72 +119,41 @@ class _AsyncBasicAppCfgPref:
104
119
  if not not_fail:
105
120
  raise e from None
106
121
 
122
+ async def set_value(self, key: str, value: str, sensitive: bool | None = None) -> None:
123
+ """Sets a value and if specified the sensitive flag for a key.
124
+
125
+ .. note:: A sensitive flag ensures key value are encrypted and truncated in Nextcloud logs.
126
+ Default for new records is ``False`` when sensitive is *unspecified*, if changes existing record and
127
+ sensitive is *unspecified* it will not change the existing `sensitive` flag.
128
+ """
129
+ if not key:
130
+ raise ValueError("`key` parameter can not be empty")
131
+ require_capabilities("app_api", await self._session.capabilities)
132
+ params: dict = {"configKey": key, "configValue": value}
133
+ if sensitive is not None:
134
+ params["sensitive"] = sensitive
135
+ await self._session.ocs("POST", f"{self._session.ae_url}/{self._url_suffix}", json=params)
136
+
107
137
 
108
138
  class PreferencesExAPI(_BasicAppCfgPref):
109
- """User specific preferences API, avalaible as **nc.preferences_ex.<method>**."""
139
+ """User specific preferences API, available as **nc.preferences_ex.<method>**."""
110
140
 
111
141
  _url_suffix = "ex-app/preference"
112
142
 
113
- def set_value(self, key: str, value: str) -> None:
114
- """Sets a value for a key."""
115
- if not key:
116
- raise ValueError("`key` parameter can not be empty")
117
- require_capabilities("app_api", self._session.capabilities)
118
- params = {"configKey": key, "configValue": value}
119
- self._session.ocs("POST", f"{self._session.ae_url}/{self._url_suffix}", json=params)
120
-
121
143
 
122
144
  class AsyncPreferencesExAPI(_AsyncBasicAppCfgPref):
123
145
  """User specific preferences API."""
124
146
 
125
147
  _url_suffix = "ex-app/preference"
126
148
 
127
- async def set_value(self, key: str, value: str) -> None:
128
- """Sets a value for a key."""
129
- if not key:
130
- raise ValueError("`key` parameter can not be empty")
131
- require_capabilities("app_api", await self._session.capabilities)
132
- params = {"configKey": key, "configValue": value}
133
- await self._session.ocs("POST", f"{self._session.ae_url}/{self._url_suffix}", json=params)
134
-
135
149
 
136
150
  class AppConfigExAPI(_BasicAppCfgPref):
137
- """Non-user(App) specific preferences API, avalaible as **nc.appconfig_ex.<method>**."""
151
+ """Non-user(App) specific preferences API, available as **nc.appconfig_ex.<method>**."""
138
152
 
139
153
  _url_suffix = "ex-app/config"
140
154
 
141
- def set_value(self, key: str, value: str, sensitive: bool | None = None) -> None:
142
- """Sets a value and if specified the sensitive flag for a key.
143
-
144
- .. note:: A sensitive flag ensures key values are truncated in Nextcloud logs.
145
- Default for new records is ``False`` when sensitive is *unspecified*, if changes existing record and
146
- sensitive is *unspecified* it will not change the existing `sensitive` flag.
147
- """
148
- if not key:
149
- raise ValueError("`key` parameter can not be empty")
150
- require_capabilities("app_api", self._session.capabilities)
151
- params: dict = {"configKey": key, "configValue": value}
152
- if sensitive is not None:
153
- params["sensitive"] = sensitive
154
- self._session.ocs("POST", f"{self._session.ae_url}/{self._url_suffix}", json=params)
155
-
156
155
 
157
156
  class AsyncAppConfigExAPI(_AsyncBasicAppCfgPref):
158
157
  """Non-user(App) specific preferences API."""
159
158
 
160
159
  _url_suffix = "ex-app/config"
161
-
162
- async def set_value(self, key: str, value: str, sensitive: bool | None = None) -> None:
163
- """Sets a value and if specified the sensitive flag for a key.
164
-
165
- .. note:: A sensitive flag ensures key values are truncated in Nextcloud logs.
166
- Default for new records is ``False`` when sensitive is *unspecified*, if changes existing record and
167
- sensitive is *unspecified* it will not change the existing `sensitive` flag.
168
- """
169
- if not key:
170
- raise ValueError("`key` parameter can not be empty")
171
- require_capabilities("app_api", await self._session.capabilities)
172
- params: dict = {"configKey": key, "configValue": value}
173
- if sensitive is not None:
174
- params["sensitive"] = sensitive
175
- await self._session.ocs("POST", f"{self._session.ae_url}/{self._url_suffix}", json=params)
nc_py_api/_version.py CHANGED
@@ -1,3 +1,3 @@
1
1
  """Version of nc_py_api."""
2
2
 
3
- __version__ = "0.20.0"
3
+ __version__ = "0.20.2"
@@ -247,7 +247,7 @@ class AppAPIAuthMiddleware:
247
247
 
248
248
  conn = HTTPConnection(scope)
249
249
  url_path = conn.url.path.lstrip("/")
250
- if not fnmatch.filter(self._disable_for, url_path):
250
+ if not any(fnmatch.fnmatch(url_path, i) for i in self._disable_for):
251
251
  try:
252
252
  scope["username"] = _request_sign_check(conn, AsyncNextcloudApp())
253
253
  except HTTPException as exc:
@@ -48,6 +48,7 @@ class SettingsField:
48
48
  description: str = ""
49
49
  placeholder: str = ""
50
50
  label: str = ""
51
+ sensitive: bool = False
51
52
  notify = False # to be supported in future
52
53
 
53
54
  @classmethod
@@ -74,6 +75,7 @@ class SettingsField:
74
75
  "placeholder": self.placeholder,
75
76
  "label": self.label,
76
77
  "notify": self.notify,
78
+ "sensitive": self.sensitive,
77
79
  }
78
80
 
79
81
 
nc_py_api/files/_files.py CHANGED
@@ -1,8 +1,10 @@
1
1
  """Helper functions for **FilesAPI** and **AsyncFilesAPI** classes."""
2
2
 
3
3
  import enum
4
+ from datetime import datetime, timezone
4
5
  from io import BytesIO
5
6
  from json import dumps, loads
7
+ from typing import Any
6
8
  from urllib.parse import unquote
7
9
  from xml.etree import ElementTree
8
10
 
@@ -69,6 +71,16 @@ def get_propfind_properties(capabilities: dict) -> list:
69
71
  return r
70
72
 
71
73
 
74
+ def _dav_literal(val: Any) -> str:
75
+ """Return a string suitable for <d:literal>."""
76
+ if isinstance(val, datetime):
77
+ # make timezone-aware, force UTC, second precision
78
+ dt = val if val.tzinfo else val.replace(tzinfo=timezone.utc)
79
+ dt = dt.astimezone(timezone.utc).replace(microsecond=0)
80
+ return dt.isoformat().replace("+00:00", "Z") # 2025-03-10T12:34:56Z
81
+ return str(val)
82
+
83
+
72
84
  def build_find_request(req: list, path: str | FsNode, user: str, capabilities: dict) -> ElementTree.Element:
73
85
  path = path.user_path if isinstance(path, FsNode) else path
74
86
  root = ElementTree.Element(
@@ -126,7 +138,7 @@ def build_search_req(xml_element_where, req: list) -> None:
126
138
  ElementTree.SubElement(_, SEARCH_PROPERTIES_MAP[req.pop(0)])
127
139
  _ = ElementTree.SubElement(_root, "d:literal")
128
140
  value = req.pop(0)
129
- _.text = value if isinstance(value, str) else str(value)
141
+ _.text = _dav_literal(value)
130
142
 
131
143
  while len(req):
132
144
  where_part = req.pop(0)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nc-py-api
3
- Version: 0.20.0
3
+ Version: 0.20.2
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/
@@ -3,11 +3,11 @@ nc_py_api/_deffered_error.py,sha256=BpEe_tBqflwfj2Zolb67nhW-K16XX-WbcY2IH_6u8fo,
3
3
  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
- nc_py_api/_preferences_ex.py,sha256=tThj6U0ZZMaBZ-jUkjrbaI0xDnafWsBowQKsC6gjOQs,7179
6
+ nc_py_api/_preferences_ex.py,sha256=Y6sDBrFJc7lk8BoDUfjC_iwOfjSbPPNPpcSxsL1fyIM,6391
7
7
  nc_py_api/_session.py,sha256=8CjrT0ZDTg8cugRkukxUHGA_O7UsiwleawZ_KyEI6n0,20664
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=ffWaRZShROhs5-fFhItPP3NQvF3fj57SDMn-qKh0UEo,52
10
+ nc_py_api/_version.py,sha256=rf1wT5GKIXVuBGABQqd82PICMV7siLu9r7a1l9gHq4E,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_api.py,sha256=-T6CJ8cRbJZTLtxSEDWuuYpD29DMJGCTfLONmtxZV9w,1445
@@ -25,7 +25,7 @@ nc_py_api/weather_status.py,sha256=wAkjuJPjxc0Rxe4za0BzfwB0XeUmkCXoisJtTH3-qdQ,7
25
25
  nc_py_api/webhooks.py,sha256=BGHRtankgbUkcqBRJTFShjRLpaVoFNcjLsrVitoNziM,8083
26
26
  nc_py_api/ex_app/__init__.py,sha256=6Lwid4bBXOSrZf_ocf5m8qkkO1OgYxG0GTs4q6Nw72o,691
27
27
  nc_py_api/ex_app/defs.py,sha256=FaQInH3jLugKxDUqpwrXdkMT-lBxmoqWmXJXc11fa6A,727
28
- nc_py_api/ex_app/integration_fastapi.py,sha256=a3mhbBFrv_IaRqaYfKa26duiufZL-hSDFqcPDr59Vts,11041
28
+ nc_py_api/ex_app/integration_fastapi.py,sha256=848ugedpEsQ-0vGPLfF5VlgQxETPMQl_aQN-erJf4CE,11058
29
29
  nc_py_api/ex_app/logger.py,sha256=nAHLObuPvl3UBLrlqZulgoxxVaAJ661iP4F6bTW-V-Y,1475
30
30
  nc_py_api/ex_app/misc.py,sha256=c7B0uE8isaIi4SQbxURGUuWjZaaXiLg3Ov6cqvRYplE,2298
31
31
  nc_py_api/ex_app/occ_commands.py,sha256=hb2BJuvFKIigvLycSCyAe9v6hedq4Gfu2junQZTaK_M,5219
@@ -37,16 +37,16 @@ nc_py_api/ex_app/providers/task_processing.py,sha256=h-H3fGK30c9M-VUpk7I9WGc730t
37
37
  nc_py_api/ex_app/ui/__init__.py,sha256=jUMU7_miFF-Q8BQNT90KZYQiLy_a3OvEyK6y8eRMKRk,38
38
38
  nc_py_api/ex_app/ui/files_actions.py,sha256=pKe0VSSy5Zl0NwPe8rwdL_NL374n-0_XBf6M5HmKoIU,7384
39
39
  nc_py_api/ex_app/ui/resources.py,sha256=Vwx69oZ93Ouh6HJtGUqaKFUr4Reo74H4vT1YCpb-7j0,12492
40
- nc_py_api/ex_app/ui/settings.py,sha256=f0R17lGhBfo2JQULVw_hFxhpfoPw_CW7vBu0Rb1ABJw,6623
40
+ nc_py_api/ex_app/ui/settings.py,sha256=VyGly-rCYMw9Zw7cTYRYilXXKe7f6tesTAW83X5gHGM,6692
41
41
  nc_py_api/ex_app/ui/top_menu.py,sha256=oCgGtIoMYbp-5iN5aXEbT7Q88HtccR7hg6IBFgbbyX4,5118
42
42
  nc_py_api/ex_app/ui/ui.py,sha256=OqFHKn6oIZli8T1wnv6YtQ4glNfeNb90WwGCvtWI1Z4,1632
43
43
  nc_py_api/files/__init__.py,sha256=aN6Lhc0km5eAIGFA8YoG-xXDOzIJILV2izCzHeC-a78,17949
44
- nc_py_api/files/_files.py,sha256=l1oGcXIKmuhlNthXkwL8qbINQgiMJ9wmFega9IP-wNk,13850
44
+ nc_py_api/files/_files.py,sha256=0jJ1yoq_wZUiB6pXrEG4iUhImcANEO5gXoqmUrJF_ws,14297
45
45
  nc_py_api/files/files.py,sha256=7x4hfnVa2y1R5bxK9f8cdggi1gPnpUYnsBj0e4p-4qc,24926
46
46
  nc_py_api/files/files_async.py,sha256=nyDeWiGx_8CHuVrNThSgfZy0l-WlC4El-TzJONo0TsM,25773
47
47
  nc_py_api/files/sharing.py,sha256=VRZCl-TYK6dbu9rUHPs3_jcVozu1EO8bLGZwoRpiLsU,14439
48
- nc_py_api-0.20.0.dist-info/METADATA,sha256=80t-MmU4I6iXrIIpzf4ruf4PXZwns2WY7hCfpB6yy80,8055
49
- nc_py_api-0.20.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
50
- nc_py_api-0.20.0.dist-info/licenses/AUTHORS,sha256=B2Q9q9XH3PAxJp0V3GiKQc1l0z7vtGDpDHqda-ISWKM,616
51
- nc_py_api-0.20.0.dist-info/licenses/LICENSE.txt,sha256=OLEMh401fAumGHfRSna365MLIfnjdTcdOHZ6QOzMjkg,1551
52
- nc_py_api-0.20.0.dist-info/RECORD,,
48
+ nc_py_api-0.20.2.dist-info/METADATA,sha256=ehwNyvLLh9FU2Mq5ykO1hKgiE6dHmDgpQ3agBA6CdxY,8055
49
+ nc_py_api-0.20.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
50
+ nc_py_api-0.20.2.dist-info/licenses/AUTHORS,sha256=B2Q9q9XH3PAxJp0V3GiKQc1l0z7vtGDpDHqda-ISWKM,616
51
+ nc_py_api-0.20.2.dist-info/licenses/LICENSE.txt,sha256=OLEMh401fAumGHfRSna365MLIfnjdTcdOHZ6QOzMjkg,1551
52
+ nc_py_api-0.20.2.dist-info/RECORD,,