Skip to content

Commit ec3ed63

Browse files
EmanAbdelhaleemfkiralysatvshrgeetu040pre-commit-ci[bot]
authored
[ENH] V1 → V2 API Migration - setups (#1619)
Fixes #1625 Depends on #1576 Related to #1575 Details This PR implements `Setups` resource, and refactor its existing functions --------- Co-authored-by: Franz Király <fkiraly@gcos.ai> Co-authored-by: Satvik Mishra <112589278+satvshr@users.noreply.github.com> Co-authored-by: geetu040 <raoarmaghanshakir040@gmail.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Simon Blanke <simon.blanke@yahoo.com> Co-authored-by: Matthias Feurer <lists@matthiasfeurer.de> Co-authored-by: Pieter Gijsbers <p.gijsbers@tue.nl>
1 parent fe58eb0 commit ec3ed63

9 files changed

Lines changed: 462 additions & 229 deletions

File tree

openml/_api/clients/http.py

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,26 @@ def _key_to_path(self, key: str) -> Path:
8989
"""
9090
return self.path.joinpath(key)
9191

92+
def _get_body_filename_from_response(self, response: Response) -> str:
93+
content_type = response.headers.get("Content-Type", "").lower()
94+
95+
if "application/json" in content_type:
96+
return "body.json"
97+
98+
if "text/xml" in content_type:
99+
return "body.xml"
100+
101+
return "body.txt"
102+
103+
def _get_body_filename_from_path(self, path: Path) -> str:
104+
if (path / "body.json").exists():
105+
return "body.json"
106+
107+
if (path / "body.xml").exists():
108+
return "body.xml"
109+
110+
return "body.txt"
111+
92112
def load(self, key: str) -> Response:
93113
"""
94114
Load a cached HTTP response from disk.
@@ -112,31 +132,26 @@ def load(self, key: str) -> Response:
112132
"""
113133
path = self._key_to_path(key)
114134

115-
if not path.exists():
116-
raise FileNotFoundError(f"Cache entry not found: {path}")
117-
118135
meta_path = path / "meta.json"
119-
headers_path = path / "headers.json"
120-
body_path = path / "body.bin"
136+
meta_raw = meta_path.read_bytes() if meta_path.exists() else "{}"
137+
meta = json.loads(meta_raw)
121138

122-
if not (meta_path.exists() and headers_path.exists() and body_path.exists()):
123-
raise FileNotFoundError(f"Incomplete cache at {path}")
124-
125-
with meta_path.open("r", encoding="utf-8") as f:
126-
meta = json.load(f)
127-
128-
with headers_path.open("r", encoding="utf-8") as f:
129-
headers = json.load(f)
139+
headers_path = path / "headers.json"
140+
headers_raw = headers_path.read_bytes() if headers_path.exists() else "{}"
141+
headers = json.loads(headers_raw)
130142

143+
body_path = path / self._get_body_filename_from_path(path)
144+
if not body_path.exists():
145+
raise FileNotFoundError(f"Incomplete cache at {body_path}")
131146
body = body_path.read_bytes()
132147

133148
response = Response()
134-
response.status_code = meta["status_code"]
135-
response.url = meta["url"]
136-
response.reason = meta["reason"]
137149
response.headers = headers
138150
response._content = body
139-
response.encoding = meta["encoding"]
151+
response.status_code = meta.get("status_code")
152+
response.url = meta.get("url")
153+
response.reason = meta.get("reason")
154+
response.encoding = meta.get("encoding")
140155

141156
return response
142157

@@ -160,7 +175,9 @@ def save(self, key: str, response: Response) -> None:
160175
path = self._key_to_path(key)
161176
path.mkdir(parents=True, exist_ok=True)
162177

163-
(path / "body.bin").write_bytes(response.content)
178+
body_filename = self._get_body_filename_from_response(response)
179+
with (path / body_filename).open("wb") as f:
180+
f.write(response.content)
164181

165182
with (path / "headers.json").open("w", encoding="utf-8") as f:
166183
json.dump(dict(response.headers), f)

openml/_api/resources/base/resources.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
from __future__ import annotations
22

3+
import builtins
34
from abc import abstractmethod
5+
from collections.abc import Iterable
46
from typing import TYPE_CHECKING, Any
57

68
from openml.enums import ResourceType
@@ -9,6 +11,8 @@
911

1012
if TYPE_CHECKING:
1113
from openml.evaluations import OpenMLEvaluation
14+
from openml.flows.flow import OpenMLFlow
15+
from openml.setups.setup import OpenMLSetup
1216

1317

1418
class DatasetAPI(ResourceAPI):
@@ -83,3 +87,24 @@ class SetupAPI(ResourceAPI):
8387
"""Abstract API interface for setup resources."""
8488

8589
resource_type: ResourceType = ResourceType.SETUP
90+
91+
@abstractmethod
92+
def list(
93+
self,
94+
limit: int,
95+
offset: int,
96+
*,
97+
setup: Iterable[int] | None = None,
98+
flow: int | None = None,
99+
tag: str | None = None,
100+
) -> list[OpenMLSetup]: ...
101+
102+
@abstractmethod
103+
def get(self, setup_id: int) -> OpenMLSetup: ...
104+
105+
@abstractmethod
106+
def exists(
107+
self,
108+
flow: OpenMLFlow,
109+
param_settings: builtins.list[dict[str, Any]],
110+
) -> int | bool: ...

0 commit comments

Comments
 (0)