Skip to content

Client

The two clients are twins — identical surface, the only difference is await.

SepalClient

pysepal_api.SepalClient

SepalClient(
    *,
    session_id: str | None = None,
    module_name: str | None = None,
    auth: Auth | None = None,
    auth_mode: AuthMode = "auto",
    base_url: str | None = None,
    timeout: float | Timeout = 30.0,
    verify: bool | None = None
)

Synchronous HTTP client for SEPAL services.

Source code in src/pysepal_api/client.py
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
def __init__(
    self,
    *,
    session_id: str | None = None,
    module_name: str | None = None,
    auth: httpx.Auth | None = None,
    auth_mode: AuthMode = "auto",
    base_url: str | None = None,
    timeout: float | httpx.Timeout = 30.0,
    verify: bool | None = None,
) -> None:
    base, resolved_auth, resolved_verify = _resolve_config(
        session_id, auth, auth_mode, base_url, verify
    )
    self.module_name = module_name
    self.base_url = base
    self.verify = resolved_verify
    self.results_path: PurePosixPath | None = (
        module_results_path(module_name) if module_name else None
    )
    self._http = httpx.Client(
        base_url=base,
        auth=resolved_auth,
        verify=resolved_verify,
        timeout=timeout,
        headers={"Accept": "application/json"},
    )
    self.files = UserFilesEndpoint(self._http)
    self.tasks = TasksEndpoint(self._http)
    self.recipes = RecipesEndpoint(self._http)

BASE_REMOTE_PATH class-attribute instance-attribute

BASE_REMOTE_PATH = BASE_REMOTE_PATH

module_name instance-attribute

module_name = module_name

base_url instance-attribute

base_url = base

verify instance-attribute

verify = resolved_verify

results_path instance-attribute

results_path: PurePosixPath | None = (
    module_results_path(module_name)
    if module_name
    else None
)

files instance-attribute

files = UserFilesEndpoint(self._http)

tasks instance-attribute

tasks = TasksEndpoint(self._http)

recipes instance-attribute

recipes = RecipesEndpoint(self._http)

create classmethod

create(
    *,
    session_id: str | None = None,
    module_name: str | None = None,
    auth: Auth | None = None,
    auth_mode: AuthMode = "auto",
    base_url: str | None = None,
    timeout: float | Timeout = 30.0,
    verify: bool | None = None
) -> SepalClient

Build a ready-to-use client. Pure.

results_path is derived arithmetically from module_name; call ensure_results_dir() off the UI render path to materialise it.

Source code in src/pysepal_api/client.py
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
@classmethod
def create(
    cls,
    *,
    session_id: str | None = None,
    module_name: str | None = None,
    auth: httpx.Auth | None = None,
    auth_mode: AuthMode = "auto",
    base_url: str | None = None,
    timeout: float | httpx.Timeout = 30.0,
    verify: bool | None = None,
) -> SepalClient:
    """Build a ready-to-use client. Pure.

    ``results_path`` is derived arithmetically from ``module_name``; call
    `ensure_results_dir()` off the UI render path to materialise it.
    """
    return cls(
        session_id=session_id,
        module_name=module_name,
        auth=auth,
        auth_mode=auth_mode,
        base_url=base_url,
        timeout=timeout,
        verify=verify,
    )

ensure_results_dir

ensure_results_dir() -> PurePosixPath | None

Create the module results directory on the server.

Network I/O — never call this on a UI render path, and call it once at startup rather than before every write: it re-issues the request each time. Returns the absolute results path, or None when the client has no module_name. Idempotent: files.mkdir swallows 409/403.

Source code in src/pysepal_api/client.py
152
153
154
155
156
157
158
159
160
161
162
def ensure_results_dir(self) -> PurePosixPath | None:
    """Create the module results directory on the server.

    Network I/O — never call this on a UI render path, and call it once at
    startup rather than before every write: it re-issues the request each
    time. Returns the absolute results path, or ``None`` when the client
    has no ``module_name``. Idempotent: `files.mkdir` swallows 409/403.
    """
    if not self.module_name:
        return None
    return self.files.module_dir(self.module_name)

request

request(
    method: str, url: str, **kwargs: Any
) -> httpx.Response

Issue an arbitrary authenticated request to any SEPAL route.

The typed endpoints (files, tasks, recipes) cover the common cases; this is the escape hatch for routes the library doesn't model. Returns the raw httpx.Response with errors mapped to typed exceptions. kwargs are forwarded to httpx.Client.build_request (params, json, content, files, headers, …).

Source code in src/pysepal_api/client.py
164
165
166
167
168
169
170
171
172
173
def request(self, method: str, url: str, **kwargs: Any) -> httpx.Response:
    """Issue an arbitrary authenticated request to any SEPAL route.

    The typed endpoints (`files`, `tasks`, `recipes`) cover the common
    cases; this is the escape hatch for routes the library doesn't model.
    Returns the raw `httpx.Response` with errors mapped to typed exceptions.
    `kwargs` are forwarded to `httpx.Client.build_request` (`params`,
    `json`, `content`, `files`, `headers`, …).
    """
    return send_with_error_mapping(self._http, self._http.build_request(method, url, **kwargs))

get

get(url: str, **kwargs: Any) -> httpx.Response
Source code in src/pysepal_api/client.py
175
176
def get(self, url: str, **kwargs: Any) -> httpx.Response:
    return self.request("GET", url, **kwargs)

post

post(url: str, **kwargs: Any) -> httpx.Response
Source code in src/pysepal_api/client.py
178
179
def post(self, url: str, **kwargs: Any) -> httpx.Response:
    return self.request("POST", url, **kwargs)

put

put(url: str, **kwargs: Any) -> httpx.Response
Source code in src/pysepal_api/client.py
181
182
def put(self, url: str, **kwargs: Any) -> httpx.Response:
    return self.request("PUT", url, **kwargs)

delete

delete(url: str, **kwargs: Any) -> httpx.Response
Source code in src/pysepal_api/client.py
184
185
def delete(self, url: str, **kwargs: Any) -> httpx.Response:
    return self.request("DELETE", url, **kwargs)

close

close() -> None
Source code in src/pysepal_api/client.py
187
188
def close(self) -> None:
    self._http.close()

AsyncSepalClient

pysepal_api.AsyncSepalClient

AsyncSepalClient(
    *,
    session_id: str | None = None,
    module_name: str | None = None,
    auth: Auth | None = None,
    auth_mode: AuthMode = "auto",
    base_url: str | None = None,
    timeout: float | Timeout = 30.0,
    verify: bool | None = None
)

Asynchronous twin of SepalClient.

Source code in src/pysepal_api/client.py
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
def __init__(
    self,
    *,
    session_id: str | None = None,
    module_name: str | None = None,
    auth: httpx.Auth | None = None,
    auth_mode: AuthMode = "auto",
    base_url: str | None = None,
    timeout: float | httpx.Timeout = 30.0,
    verify: bool | None = None,
) -> None:
    base, resolved_auth, resolved_verify = _resolve_config(
        session_id, auth, auth_mode, base_url, verify
    )
    self.module_name = module_name
    self.base_url = base
    self.verify = resolved_verify
    self.results_path: PurePosixPath | None = (
        module_results_path(module_name) if module_name else None
    )
    self._http = httpx.AsyncClient(
        base_url=base,
        auth=resolved_auth,
        verify=resolved_verify,
        timeout=timeout,
        headers={"Accept": "application/json"},
    )
    self.files = AsyncUserFilesEndpoint(self._http)
    self.tasks = AsyncTasksEndpoint(self._http)
    self.recipes = AsyncRecipesEndpoint(self._http)

BASE_REMOTE_PATH class-attribute instance-attribute

BASE_REMOTE_PATH = BASE_REMOTE_PATH

module_name instance-attribute

module_name = module_name

base_url instance-attribute

base_url = base

verify instance-attribute

verify = resolved_verify

results_path instance-attribute

results_path: PurePosixPath | None = (
    module_results_path(module_name)
    if module_name
    else None
)

files instance-attribute

files = AsyncUserFilesEndpoint(self._http)

tasks instance-attribute

tasks = AsyncTasksEndpoint(self._http)

recipes instance-attribute

recipes = AsyncRecipesEndpoint(self._http)

create classmethod

create(
    *,
    session_id: str | None = None,
    module_name: str | None = None,
    auth: Auth | None = None,
    auth_mode: AuthMode = "auto",
    base_url: str | None = None,
    timeout: float | Timeout = 30.0,
    verify: bool | None = None
) -> _AwaitableClient

Build a ready-to-use client. Pure. The result can be awaited or used as an async context manager — both spellings work:

sepal = await AsyncSepalClient.create(...)      # long-lived
async with AsyncSepalClient.create(...) as sepal:   # scoped

results_path is derived arithmetically from module_name; call ensure_results_dir() off the UI render path to materialise it.

Source code in src/pysepal_api/client.py
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
@classmethod
def create(
    cls,
    *,
    session_id: str | None = None,
    module_name: str | None = None,
    auth: httpx.Auth | None = None,
    auth_mode: AuthMode = "auto",
    base_url: str | None = None,
    timeout: float | httpx.Timeout = 30.0,
    verify: bool | None = None,
) -> _AwaitableClient:
    """Build a ready-to-use client. Pure. The result can be awaited *or*
    used as an async context manager — both spellings work:

        sepal = await AsyncSepalClient.create(...)      # long-lived
        async with AsyncSepalClient.create(...) as sepal:   # scoped

    ``results_path`` is derived arithmetically from ``module_name``; call
    `ensure_results_dir()` off the UI render path to materialise it.
    """
    client = cls(
        session_id=session_id,
        module_name=module_name,
        auth=auth,
        auth_mode=auth_mode,
        base_url=base_url,
        timeout=timeout,
        verify=verify,
    )
    return _AwaitableClient(client)

ensure_results_dir async

ensure_results_dir() -> PurePosixPath | None

Create the module results directory on the server.

Network I/O — never call this on a UI render path, and call it once at startup rather than before every write: it re-issues the request each time. Returns the absolute results path, or None when the client has no module_name. Idempotent: files.mkdir swallows 409/403.

Source code in src/pysepal_api/client.py
268
269
270
271
272
273
274
275
276
277
278
async def ensure_results_dir(self) -> PurePosixPath | None:
    """Create the module results directory on the server.

    Network I/O — never call this on a UI render path, and call it once at
    startup rather than before every write: it re-issues the request each
    time. Returns the absolute results path, or ``None`` when the client
    has no ``module_name``. Idempotent: `files.mkdir` swallows 409/403.
    """
    if not self.module_name:
        return None
    return await self.files.module_dir(self.module_name)

request async

request(
    method: str, url: str, **kwargs: Any
) -> httpx.Response

Async twin of SepalClient.request. Escape hatch for unmodeled routes.

Source code in src/pysepal_api/client.py
280
281
282
283
284
async def request(self, method: str, url: str, **kwargs: Any) -> httpx.Response:
    """Async twin of `SepalClient.request`. Escape hatch for unmodeled routes."""
    return await send_with_error_mapping_async(
        self._http, self._http.build_request(method, url, **kwargs)
    )

get async

get(url: str, **kwargs: Any) -> httpx.Response
Source code in src/pysepal_api/client.py
286
287
async def get(self, url: str, **kwargs: Any) -> httpx.Response:
    return await self.request("GET", url, **kwargs)

post async

post(url: str, **kwargs: Any) -> httpx.Response
Source code in src/pysepal_api/client.py
289
290
async def post(self, url: str, **kwargs: Any) -> httpx.Response:
    return await self.request("POST", url, **kwargs)

put async

put(url: str, **kwargs: Any) -> httpx.Response
Source code in src/pysepal_api/client.py
292
293
async def put(self, url: str, **kwargs: Any) -> httpx.Response:
    return await self.request("PUT", url, **kwargs)

delete async

delete(url: str, **kwargs: Any) -> httpx.Response
Source code in src/pysepal_api/client.py
295
296
async def delete(self, url: str, **kwargs: Any) -> httpx.Response:
    return await self.request("DELETE", url, **kwargs)

aclose async

aclose() -> None
Source code in src/pysepal_api/client.py
298
299
async def aclose(self) -> None:
    await self._http.aclose()