Skip to content

Commit fb02407

Browse files
authored
options rework (#64)
Allows to specify `options` throw environment variables or `.env` file. Also `options` now are independent in each `Nextcloud` or `NextcloudApp` class, and this allows to specify them with `kwargs` --------- Signed-off-by: Alexander Piskun <bigcat88@icloud.com>
1 parent 32650c4 commit fb02407

File tree

6 files changed

+75
-42
lines changed

6 files changed

+75
-42
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22

33
All notable changes to this project will be documented in this file.
44

5-
## [0.0.27 - 2023-08-03]
5+
## [0.0.27 - 2023-08-05]
66

77
### Added
88

99
- `Notifications API`
10+
- `options` now independent in each `Nextcloud` class. They can be specified in kwargs, environment or `.env` files.
1011

1112
### Changed
1213

docs/Options.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@ Options
66
-------
77

88
.. autodata:: nc_py_api.options.XDEBUG_SESSION
9-
.. autodata:: nc_py_api.options.TIMEOUT
10-
.. autodata:: nc_py_api.options.TIMEOUT_DAV
11-
.. autodata:: nc_py_api.options.VERIFY_NC_CERTIFICATE
9+
.. autodata:: nc_py_api.options.NPA_TIMEOUT
10+
.. autodata:: nc_py_api.options.NPA_TIMEOUT_DAV
11+
.. autodata:: nc_py_api.options.NPA_NC_CERT

nc_py_api/_session.py

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -43,29 +43,51 @@ class ServerVersion(TypedDict):
4343
"""Indicates if the subscription has extended support"""
4444

4545

46+
@dataclass
47+
class RuntimeOptions:
48+
xdebug_session: str
49+
timeout: Optional[int]
50+
timeout_dav: Optional[int]
51+
_nc_cert: Union[str, bool]
52+
53+
def __init__(self, **kwargs):
54+
self.xdebug_session = kwargs.get("xdebug_session", options.XDEBUG_SESSION)
55+
self.timeout = kwargs.get("npa_timeout", options.NPA_TIMEOUT)
56+
self.timeout_dav = kwargs.get("npa_timeout_dav", options.NPA_TIMEOUT_DAV)
57+
self._nc_cert = kwargs.get("npa_nc_cert", options.NPA_NC_CERT)
58+
59+
@property
60+
def nc_cert(self) -> Union[str, bool]:
61+
return self._nc_cert
62+
63+
4664
@dataclass
4765
class BasicConfig:
4866
endpoint: str
4967
dav_endpoint: str
5068
dav_url_suffix: str
69+
options: RuntimeOptions
5170

5271
def __init__(self, **kwargs):
53-
full_nc_url = self._get_value("nextcloud_url", **kwargs)
72+
full_nc_url = self._get_config_value("nextcloud_url", **kwargs)
5473
self.endpoint = full_nc_url.removesuffix("/index.php").removesuffix("/")
55-
self.dav_url_suffix = self._get_value("dav_url_suffix", raise_not_found=False, **kwargs)
74+
self.dav_url_suffix = self._get_config_value("dav_url_suffix", raise_not_found=False, **kwargs)
5675
if not self.dav_url_suffix:
5776
self.dav_url_suffix = "remote.php/dav"
5877
self.dav_url_suffix = "/" + self.dav_url_suffix.strip("/")
5978
self.dav_endpoint = self.endpoint + self.dav_url_suffix
79+
self.options = RuntimeOptions(**kwargs)
6080

6181
@staticmethod
62-
def _get_value(value_name: str, raise_not_found=True, **kwargs):
63-
value = kwargs.get(value_name, None)
64-
if not value:
65-
value = environ.get(value_name.upper(), None)
66-
if not value and raise_not_found:
82+
def _get_config_value(value_name: str, raise_not_found=True, **kwargs):
83+
if value_name in kwargs:
84+
return kwargs[value_name]
85+
value_name_upper = value_name.upper()
86+
if value_name_upper in environ:
87+
return environ[value_name_upper]
88+
if raise_not_found:
6789
raise ValueError(f"`{value_name}` is not found.")
68-
return value
90+
return None
6991

7092

7193
@dataclass
@@ -74,7 +96,7 @@ class Config(BasicConfig):
7496

7597
def __init__(self, **kwargs):
7698
super().__init__(**kwargs)
77-
self.auth = (self._get_value("nc_auth_user", **kwargs), self._get_value("nc_auth_pass", **kwargs))
99+
self.auth = (self._get_config_value("nc_auth_user", **kwargs), self._get_config_value("nc_auth_pass", **kwargs))
78100

79101

80102
@dataclass
@@ -92,12 +114,12 @@ class AppConfig(BasicConfig):
92114

93115
def __init__(self, **kwargs):
94116
super().__init__(**kwargs)
95-
self.ae_version = self._get_value("ae_version", raise_not_found=False, **kwargs)
117+
self.ae_version = self._get_config_value("ae_version", raise_not_found=False, **kwargs)
96118
if not self.ae_version:
97119
self.ae_version = "1.0.0"
98-
self.app_name = self._get_value("app_id", **kwargs)
99-
self.app_version = self._get_value("app_version", **kwargs)
100-
self.app_secret = self._get_value("app_secret", **kwargs).encode("UTF-8")
120+
self.app_name = self._get_config_value("app_id", **kwargs)
121+
self.app_version = self._get_config_value("app_version", **kwargs)
122+
self.app_secret = self._get_config_value("app_secret", **kwargs).encode("UTF-8")
101123

102124

103125
class NcSessionBasic(ABC):
@@ -147,7 +169,7 @@ def _ocs(self, method: str, path_params: str, headers: dict, data: Optional[byte
147169
info = f"request: method={method}, url={url_params}"
148170
nested_req = kwargs.pop("nested_req", False)
149171
try:
150-
timeout = kwargs.pop("timeout", options.TIMEOUT)
172+
timeout = kwargs.pop("timeout", self.cfg.options.timeout)
151173
if method == "GET":
152174
response = self.adapter.get(url_params, headers=headers, timeout=timeout, **kwargs)
153175
else:
@@ -190,14 +212,15 @@ def dav_stream(
190212

191213
def _dav(self, method: str, path: str, headers: dict, data: Optional[bytes], **kwargs) -> Response:
192214
self.init_adapter()
193-
timeout = kwargs.pop("timeout", options.TIMEOUT_DAV)
215+
# self.cfg.
216+
timeout = kwargs.pop("timeout", self.cfg.options.timeout_dav)
194217
return self.adapter.request(
195218
method, self.cfg.endpoint + path, headers=headers, content=data, timeout=timeout, **kwargs
196219
)
197220

198221
def _dav_stream(self, method: str, path: str, headers: dict, data: Optional[bytes], **kwargs) -> Iterator[Response]:
199222
self.init_adapter()
200-
timeout = kwargs.pop("timeout", options.TIMEOUT_DAV)
223+
timeout = kwargs.pop("timeout", self.cfg.options.timeout_dav)
201224
return self.adapter.stream(
202225
method, self.cfg.endpoint + path, headers=headers, content=data, timeout=timeout, **kwargs
203226
)
@@ -249,9 +272,7 @@ def __init__(self, **kwargs):
249272
super().__init__(user=self.cfg.auth[0])
250273

251274
def _create_adapter(self) -> Client:
252-
return Client(
253-
auth=self.cfg.auth, follow_redirects=True, limits=self.limits, verify=options.VERIFY_NC_CERTIFICATE
254-
)
275+
return Client(auth=self.cfg.auth, follow_redirects=True, limits=self.limits, verify=self.cfg.options.nc_cert)
255276

256277

257278
class NcSessionApp(NcSessionBasic):
@@ -274,7 +295,7 @@ def _dav_stream(self, method: str, path: str, headers: dict, data: Optional[byte
274295
return super()._dav_stream(method, path, headers, data, **kwargs)
275296

276297
def _create_adapter(self) -> Client:
277-
adapter = Client(follow_redirects=True, limits=self.limits, verify=options.VERIFY_NC_CERTIFICATE)
298+
adapter = Client(follow_redirects=True, limits=self.limits, verify=self.cfg.options.nc_cert)
278299
adapter.headers.update(
279300
{
280301
"AE-VERSION": self.cfg.ae_version,

nc_py_api/options.py

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,25 @@
1-
"""Options to change nc_py_api's runtime behaviour."""
1+
"""Options to change nc_py_api's runtime behavior.
22
3-
XDEBUG_SESSION = "PHPSTORM"
4-
"""Dev option, for debugging PHP code"""
3+
Each setting only affects newly created instances of the Nextcloud or NextcloudApp class, unless otherwise specified.
4+
Refer to the documentation for information in which different ways it can be useful.
5+
"""
6+
from os import environ
57

6-
TIMEOUT = 50
8+
from dotenv import load_dotenv
9+
10+
load_dotenv()
11+
12+
XDEBUG_SESSION = environ.get("XDEBUG_SESSION", "")
13+
"""Dev option, for debugging PHP code."""
14+
15+
NPA_TIMEOUT = environ.get("NPA_TIMEOUT", 50)
716
"""Default timeout for OCS API calls. Set to "None" to disable timeouts for development."""
817

9-
TIMEOUT_DAV = TIMEOUT * 3 if TIMEOUT else None
18+
NPA_TIMEOUT_DAV = environ.get("NPA_TIMEOUT_DAV", NPA_TIMEOUT * 3 if isinstance(NPA_TIMEOUT, int) else None)
1019
"""File operations timeout, usually it is OCS timeout multiplied by 3."""
1120

12-
VERIFY_NC_CERTIFICATE = True
13-
"""Option to enable/disable Nextcloud certificate verification
21+
NPA_NC_CERT = environ.get("NPA_NC_CERT", True)
22+
"""Option to enable/disable Nextcloud certificate verification.
1423
15-
In the case of self-signed certificates, you can disable verification."""
24+
SSL certificates (a.k.a CA bundle) used to verify the identity of requested hosts. Either `True` (default CA bundle),
25+
a path to an SSL certificate file, or `False` (which will disable verification)."""

pyproject.toml

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,17 @@ dynamic = [
4343
"version",
4444
]
4545
dependencies = [
46-
"fastapi==0.101",
47-
"httpx==0.24.1",
48-
"pydantic==2.1.1",
49-
"requests==2.31",
50-
"xmltodict==0.13",
46+
"fastapi>=0.101",
47+
"httpx>=0.24.1",
48+
"pydantic>=2.1.1",
49+
"python-dotenv>=1",
50+
"requests>=2.31",
51+
"xmltodict>=0.13",
5152
]
5253
[project.optional-dependencies]
5354
app = [
54-
"uvicorn[standard]==0.23.2",
55-
"xxhash==3.3",
55+
"uvicorn[standard]>=0.23.2",
56+
"xxhash>=3.3",
5657
]
5758
bench = [
5859
"matplotlib",

tests/misc_test.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@ def test_require_capabilities():
3939

4040

4141
def test_config_get_value():
42-
BasicConfig()._get_value("non_exist_value", raise_not_found=False)
42+
BasicConfig()._get_config_value("non_exist_value", raise_not_found=False)
4343
with pytest.raises(ValueError):
44-
BasicConfig()._get_value("non_exist_value")
45-
assert BasicConfig()._get_value("non_exist_value", non_exist_value=123) == 123
44+
BasicConfig()._get_config_value("non_exist_value")
45+
assert BasicConfig()._get_config_value("non_exist_value", non_exist_value=123) == 123
4646

4747

4848
def test_deffered_error():

0 commit comments

Comments
 (0)