|
1 | 1 | from __future__ import annotations
|
2 | 2 |
|
| 3 | +import functools |
3 | 4 | from dataclasses import dataclass
|
4 | 5 | from typing import List, Optional, Union
|
5 | 6 |
|
6 | 7 | from openeo.internal.jupyter import render_component
|
7 | 8 | from openeo.rest.models.federation_extension import FederationExtension
|
| 9 | +from openeo.rest.models.logs import LogEntry, normalize_log_level |
8 | 10 |
|
9 | 11 |
|
10 | 12 | @dataclass(frozen=True)
|
@@ -34,12 +36,15 @@ class CollectionListingResponse(list):
|
34 | 36 | from a ``GET /collections`` request.
|
35 | 37 |
|
36 | 38 | .. note::
|
37 |
| - This object mimics a simple list of collection metadata dictionaries, |
| 39 | + This object mimics, for backward compatibility reasons, |
| 40 | + the interface of simple list of collection metadata dictionaries (``List[dict]``), |
38 | 41 | which was the original return API of
|
39 | 42 | :py:meth:`~openeo.rest.connection.Connection.list_collections()`,
|
40 | 43 | but now also provides methods/properties to access additional response data.
|
41 | 44 |
|
42 | 45 | :param response_data: response data from a ``GET /collections`` request
|
| 46 | + :param warn_on_federation_missing: whether to automatically warn |
| 47 | + about missing federation components. |
43 | 48 |
|
44 | 49 | .. seealso:: :py:meth:`openeo.rest.connection.Connection.list_collections()`
|
45 | 50 |
|
@@ -75,12 +80,14 @@ class ProcessListingResponse(list):
|
75 | 80 | from a ``GET /processes`` request.
|
76 | 81 |
|
77 | 82 | .. note::
|
78 |
| - This object mimics a simple list of collection metadata dictionaries, |
79 |
| - which was the original return API of |
| 83 | + This object mimics, for backward compatibility reasons, |
| 84 | + the interface of simple list of process metadata dictionaries (``List[dict]``), |
80 | 85 | :py:meth:`~openeo.rest.connection.Connection.list_processes()`,
|
81 | 86 | but now also provides methods/properties to access additional response data.
|
82 | 87 |
|
83 | 88 | :param response_data: response data from a ``GET /processes`` request
|
| 89 | + :param warn_on_federation_missing: whether to automatically warn |
| 90 | + about missing federation components. |
84 | 91 |
|
85 | 92 | .. seealso:: :py:meth:`openeo.rest.connection.Connection.list_processes()`
|
86 | 93 |
|
@@ -118,12 +125,15 @@ class JobListingResponse(list):
|
118 | 125 | from a ``GET /jobs`` request.
|
119 | 126 |
|
120 | 127 | .. note::
|
121 |
| - This object mimics a simple ``List[dict]`` with job metadata, |
| 128 | + This object mimics, for backward compatibility reasons, |
| 129 | + the interface of simple list of job metadata dictionaries (``List[dict]``), |
122 | 130 | which was the original return API of
|
123 | 131 | :py:meth:`~openeo.rest.connection.Connection.list_jobs()`,
|
124 | 132 | but now also provides methods/properties to access additional response data.
|
125 | 133 |
|
126 | 134 | :param response_data: response data from a ``GET /jobs`` request
|
| 135 | + :param warn_on_federation_missing: whether to automatically warn |
| 136 | + about missing federation components. |
127 | 137 |
|
128 | 138 | .. seealso:: :py:meth:`openeo.rest.connection.Connection.list_jobs()`
|
129 | 139 |
|
@@ -151,3 +161,76 @@ def links(self) -> List[Link]:
|
151 | 161 | def ext_federation(self) -> FederationExtension:
|
152 | 162 | """Accessor for federation extension data related to this resource."""
|
153 | 163 | return FederationExtension(self._data)
|
| 164 | + |
| 165 | + |
| 166 | +class LogsResponse(list): |
| 167 | + """ |
| 168 | + Container for job/service logs as received |
| 169 | + from a ``GET /jobs/{job_id}/logs`` or ``GET /services/{service_id}/logs`` request. |
| 170 | +
|
| 171 | + .. note:: |
| 172 | + This object mimics, for backward compatibility reasons, |
| 173 | + the interface of a simple list (``List[LogEntry]``) |
| 174 | + which was the original return API of |
| 175 | + :py:meth:`~openeo.rest.job.BatchJob.logs()` |
| 176 | + and :py:meth:`~openeo.rest.service.Service.logs()`, |
| 177 | + but now also provides methods/properties to access additional response data. |
| 178 | +
|
| 179 | + :param response_data: response data from a ``GET /jobs/{job_id}/logs`` |
| 180 | + or ``GET /services/{service_id}/logs`` request. |
| 181 | + :param warn_on_federation_missing: whether to automatically warn |
| 182 | + about missing federation components. |
| 183 | +
|
| 184 | + .. seealso:: :py:meth:`~openeo.rest.job.BatchJob.logs()` |
| 185 | + and :py:meth:`~openeo.rest.service.Service.logs()` |
| 186 | +
|
| 187 | + .. versionadded:: 0.38.0 |
| 188 | + """ |
| 189 | + |
| 190 | + __slots__ = ["_data"] |
| 191 | + |
| 192 | + def __init__( |
| 193 | + self, response_data: dict, *, log_level: Optional[str] = None, warn_on_federation_missing: bool = True |
| 194 | + ): |
| 195 | + self._data = response_data |
| 196 | + |
| 197 | + logs = response_data.get("logs", []) |
| 198 | + # Extra client-side level filtering (in case the back-end does not support that) |
| 199 | + if log_level: |
| 200 | + |
| 201 | + @functools.lru_cache |
| 202 | + def accept_level(level: str) -> bool: |
| 203 | + return normalize_log_level(level) >= normalize_log_level(log_level) |
| 204 | + |
| 205 | + if ( |
| 206 | + # Backend does not list effective lowest level |
| 207 | + "level" not in response_data |
| 208 | + # Or effective lowest level is still too low |
| 209 | + or not accept_level(response_data["level"]) |
| 210 | + ): |
| 211 | + logs = (log for log in logs if accept_level(log.get("level"))) |
| 212 | + logs = [LogEntry(log) for log in logs] |
| 213 | + |
| 214 | + # Mimic original list of process metadata dictionaries |
| 215 | + super().__init__(logs) |
| 216 | + |
| 217 | + if warn_on_federation_missing: |
| 218 | + self.ext_federation.warn_on_missing(resource_name="log listing") |
| 219 | + |
| 220 | + def _repr_html_(self): |
| 221 | + return render_component(component="logs", data=self) |
| 222 | + |
| 223 | + @property |
| 224 | + def logs(self) -> List[LogEntry]: |
| 225 | + """Get the log entries.""" |
| 226 | + return self |
| 227 | + |
| 228 | + @property |
| 229 | + def links(self) -> List[Link]: |
| 230 | + """Get links related to this resource.""" |
| 231 | + return [Link.from_dict(d) for d in self._data.get("links", [])] |
| 232 | + |
| 233 | + @property |
| 234 | + def ext_federation(self) -> FederationExtension: |
| 235 | + """Accessor for federation extension data related to this resource.""" |
| 236 | + return FederationExtension(self._data) |
0 commit comments