Skip to content

Commit f260e1a

Browse files
authored
[wk-libs] increase network timeout to 30 mins, allow custom timeout (#577)
* increase default timeout to 2min, allow custom timeout * add changelog entry * Merge branch 'master' into custom-timeouts * bump timout to 30min, fallback to previous wk_url, allow ds download without org * formatting * docs * make timeout default a constant, fix test by specifying url explicitly
1 parent dade59d commit f260e1a

File tree

6 files changed

+51
-16
lines changed

6 files changed

+51
-16
lines changed

webknossos/Changelog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ For upgrade instructions, please check the respective *Breaking Changes* section
1212
### Breaking Changes
1313

1414
### Added
15+
- A custom network request timeout can be set using `webknossos_context(…, timeout=300)` or `export WK_TIMEOUT="300"`. [#577](https://github.com/scalableminds/webknossos-libs/pull/577)
1516

1617
### Changed
18+
- The default network request timeout changed from ½min to 30 min. [#577](https://github.com/scalableminds/webknossos-libs/pull/577)
1719

1820
### Fixed
1921

webknossos/tests/test_generated_client.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import pytest
22

3+
from webknossos.client._defaults import DEFAULT_WEBKNOSSOS_URL
34
from webknossos.client._generated.api.default import (
45
annotation_info,
56
build_info,
@@ -99,7 +100,7 @@ def test_user_list(auth_client: Client) -> None:
99100

100101
@pytest.mark.vcr()
101102
def test_dataset_info() -> None:
102-
with webknossos_context():
103+
with webknossos_context(url=DEFAULT_WEBKNOSSOS_URL):
103104
client = _get_generated_client()
104105
response = dataset_info.sync(
105106
organization_name="scalable_minds",
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
DEFAULT_WEBKNOSSOS_URL = "https://webknossos.org"
2+
DEFAULT_HTTP_TIMEOUT = 1800

webknossos/webknossos/client/_download_dataset.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,19 @@
2323

2424
def download_dataset(
2525
dataset_name: str,
26-
organization_name: str,
26+
organization_name: Optional[str] = None,
2727
bbox: Optional[BoundingBox] = None,
2828
layers: Optional[List[str]] = None,
2929
mags: Optional[List[Mag]] = None,
3030
path: Optional[Union[PathLike, str]] = None,
3131
exist_ok: bool = False,
3232
) -> Dataset:
3333
client = _get_generated_client()
34+
context = _get_context()
35+
36+
if organization_name is None:
37+
organization_name = context.organization
38+
3439
dataset_info_response = dataset_info.sync_detailed(
3540
organization_name=organization_name,
3641
data_set_name=dataset_name,
@@ -40,10 +45,8 @@ def download_dataset(
4045
parsed = dataset_info_response.parsed
4146
assert parsed is not None
4247

43-
datastore_client = _get_context().get_generated_datastore_client(
44-
parsed.data_store.url
45-
)
46-
optional_datastore_token = _get_context().datastore_token
48+
datastore_client = context.get_generated_datastore_client(parsed.data_store.url)
49+
optional_datastore_token = context.datastore_token
4750

4851
actual_path = Path(dataset_name) if path is None else Path(path)
4952
if actual_path.exists():

webknossos/webknossos/client/context.py

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
[https://webknossos.org/auth/token](https://webknossos.org/auth/token)
99
1010
Using the same methods, you can also specify the webknossos-server if you
11-
are not using the default [webknossos.org](https://webknossos.org) instance.
11+
are not using the default [webknossos.org](https://webknossos.org) instance,
12+
as well as a timeout for network requests (default is 30 minutes).
1213
1314
There are the following four options to specify which server context to use:
1415
@@ -36,6 +37,7 @@
3637
# content of .env
3738
WK_TOKEN="my_webknossos_token"
3839
WK_URL="…"
40+
WK_TIMEOUT="3600" # in seconds
3941
```
4042
4143
4. If nothing else is specified and authentication is needed,
@@ -54,7 +56,7 @@
5456
from dotenv import load_dotenv
5557
from rich.prompt import Prompt
5658

57-
from webknossos.client._defaults import DEFAULT_WEBKNOSSOS_URL
59+
from webknossos.client._defaults import DEFAULT_HTTP_TIMEOUT, DEFAULT_WEBKNOSSOS_URL
5860
from webknossos.client._generated import Client as GeneratedClient
5961

6062
load_dotenv()
@@ -101,13 +103,14 @@ def _cached_get_datastore_token(context: "_WebknossosContext") -> str:
101103
def _cached__get_generated_client(
102104
webknossos_url: str,
103105
token: Optional[str],
106+
timeout: int,
104107
) -> GeneratedClient:
105108
"""Generates a client which might contain an x-auth-token header."""
106109
if token is None:
107-
return GeneratedClient(base_url=webknossos_url, timeout=30)
110+
return GeneratedClient(base_url=webknossos_url, timeout=timeout)
108111
else:
109112
return GeneratedClient(
110-
base_url=webknossos_url, headers={"X-Auth-Token": token}, timeout=30
113+
base_url=webknossos_url, headers={"X-Auth-Token": token}, timeout=timeout
111114
)
112115

113116

@@ -122,6 +125,7 @@ def _clear_all_context_caches() -> None:
122125
class _WebknossosContext:
123126
url: str = os.environ.get("WK_URL", default=DEFAULT_WEBKNOSSOS_URL)
124127
token: Optional[str] = os.environ.get("WK_TOKEN", default=None)
128+
timeout: int = int(os.environ.get("WK_TIMEOUT", default=DEFAULT_HTTP_TIMEOUT))
125129

126130
# all properties are cached outside to allow re-usability
127131
# if same context is instantiated twice
@@ -149,14 +153,16 @@ def datastore_required_token(self) -> str:
149153

150154
@property
151155
def generated_client(self) -> GeneratedClient:
152-
return _cached__get_generated_client(self.url, self.token)
156+
return _cached__get_generated_client(self.url, self.token, self.timeout)
153157

154158
@property
155159
def generated_auth_client(self) -> GeneratedClient:
156-
return _cached__get_generated_client(self.url, self.required_token)
160+
return _cached__get_generated_client(
161+
self.url, self.required_token, self.timeout
162+
)
157163

158164
def get_generated_datastore_client(self, datastore_url: str) -> GeneratedClient:
159-
return GeneratedClient(base_url=datastore_url, timeout=120)
165+
return GeneratedClient(base_url=datastore_url, timeout=self.timeout)
160166

161167

162168
_webknossos_context_var: ContextVar[_WebknossosContext] = ContextVar(
@@ -166,10 +172,32 @@ def get_generated_datastore_client(self, datastore_url: str) -> GeneratedClient:
166172

167173
@contextmanager
168174
def webknossos_context(
169-
url: str = DEFAULT_WEBKNOSSOS_URL,
175+
url: Optional[str] = None,
170176
token: Optional[str] = None,
177+
timeout: Optional[int] = None,
171178
) -> Iterator[None]:
172-
context_var_token = _webknossos_context_var.set(_WebknossosContext(url, token))
179+
"""Returns a new webKnossos server contextmanager. Use with the `with` statement:
180+
```python
181+
with webknossos_context(token="my_webknossos_token"):
182+
# code that interacts with webknossos
183+
```
184+
185+
You can specify the following arguments:
186+
* `url`, by default [https://webknossos.org](https://www.webknossos.org),
187+
* `token`, as displayed on [https://webknossos.org/auth/token](https://webknossos.org/auth/token),
188+
* `timeout` to specify a custom network request timeout in seconds, `1800` (30min) by default.
189+
190+
`url` and `timeout` are taken from the previous context (e.g. environment variables) if not specified.
191+
`token` must be set explicitly, it is not available when not specified.
192+
"""
193+
194+
if url is None:
195+
url = _get_context().url
196+
if timeout is None:
197+
timeout = _get_context().timeout
198+
context_var_token = _webknossos_context_var.set(
199+
_WebknossosContext(url, token, timeout)
200+
)
173201
try:
174202
yield
175203
finally:

webknossos/webknossos/dataset/dataset.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ def open(cls, dataset_path: Union[str, PathLike]) -> "Dataset":
219219
def download(
220220
cls,
221221
dataset_name: str,
222-
organization_name: str,
222+
organization_name: Optional[str] = None,
223223
bbox: Optional[BoundingBox] = None,
224224
layers: Optional[List[str]] = None,
225225
mags: Optional[List[Mag]] = None,

0 commit comments

Comments
 (0)