Skip to content

Commit 4be5bbd

Browse files
committed
fixes with openml.config.[server|apikey] leakage
1 parent 2ee7fa3 commit 4be5bbd

12 files changed

Lines changed: 131 additions & 138 deletions

File tree

openml/_config.py

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,12 @@
5050
},
5151
"local": {
5252
APIVersion.V1: {
53-
"server": "http://localhost:8000/api/v1/xml/",
53+
"server": "http://localhost:8080/api/v1/xml/",
5454
"apikey": "normaluser",
5555
},
5656
APIVersion.V2: {
57-
"server": "http://localhost:8002/api/v1/xml/",
58-
"apikey": "normaluser",
57+
"server": "http://localhost:8082/",
58+
"apikey": "AD000000000000000000000000000000",
5959
},
6060
},
6161
}
@@ -137,15 +137,10 @@ def __init__(self) -> None:
137137
self.console_handler: logging.StreamHandler | None = None
138138
self.file_handler: logging.handlers.RotatingFileHandler | None = None
139139

140-
server_test_v1_apikey = self.get_servers("test")[APIVersion.V1]["apikey"]
141-
server_test_v1_server = self.get_servers("test")[APIVersion.V1]["server"]
142-
143140
self.OPENML_CACHE_DIR_ENV_VAR = "OPENML_CACHE_DIR"
144141
self.OPENML_SKIP_PARQUET_ENV_VAR = "OPENML_SKIP_PARQUET"
145-
self._TEST_SERVER_NORMAL_USER_KEY = server_test_v1_apikey
146-
self._HEADERS: dict[str, str] = {"user-agent": f"openml-python/{__version__}"}
147142
self.OPENML_TEST_SERVER_ADMIN_KEY_ENV_VAR = "OPENML_TEST_SERVER_ADMIN_KEY"
148-
self.TEST_SERVER_URL = cast("str", server_test_v1_server).split("/api/v1/xml")[0]
143+
self._HEADERS: dict[str, str] = {"user-agent": f"openml-python/{__version__}"}
149144

150145
self._config: OpenMLConfig = OpenMLConfig()
151146
# for legacy test `test_non_writable_home`
@@ -178,7 +173,6 @@ def __setattr__(self, name: str, value: Any) -> None:
178173
"_examples",
179174
"OPENML_CACHE_DIR_ENV_VAR",
180175
"OPENML_SKIP_PARQUET_ENV_VAR",
181-
"_TEST_SERVER_NORMAL_USER_KEY",
182176
"_HEADERS",
183177
}:
184178
return object.__setattr__(self, name, value)

openml/cli.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@
88
from collections.abc import Callable
99
from dataclasses import fields
1010
from pathlib import Path
11+
from typing import cast
1112
from urllib.parse import urlparse
1213

1314
import openml
1415
from openml.__version__ import __version__
16+
from openml.enums import APIVersion
1517

1618

1719
def is_hex(string_: str) -> bool:
@@ -110,9 +112,9 @@ def check_server(server: str) -> str:
110112

111113
def replace_shorthand(server: str) -> str:
112114
if server == "test":
113-
return f"{openml.config.TEST_SERVER_URL}/api/v1/xml"
115+
return cast("str", openml.config.get_servers("test")[APIVersion.V1]["server"])
114116
if server == "production_server":
115-
return "https://www.openml.org/api/v1/xml"
117+
return cast("str", openml.config.get_servers("production")[APIVersion.V1]["server"])
116118
return server
117119

118120
configure_field(

openml/testing.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,7 @@ class TestBase(unittest.TestCase):
4949
"user": [],
5050
}
5151
flow_name_tracker: ClassVar[list[str]] = []
52-
test_server = f"{openml.config.TEST_SERVER_URL}/api/v1/xml/"
5352
admin_key = os.environ.get(openml.config.OPENML_TEST_SERVER_ADMIN_KEY_ENV_VAR)
54-
user_key = openml.config._TEST_SERVER_NORMAL_USER_KEY
5553

5654
# creating logger for tracking files uploaded to test server
5755
logger = logging.getLogger("unit_tests_published_entities")
@@ -106,8 +104,6 @@ def setUp(self, n_levels: int = 1, tmpdir_suffix: str = "") -> None:
106104
os.chdir(self.workdir)
107105

108106
self.cached = True
109-
openml.config.apikey = TestBase.user_key
110-
self.production_server = "https://www.openml.org/api/v1/xml"
111107
openml.config.set_root_cache_directory(str(self.workdir))
112108

113109
# Increase the number of retries to avoid spurious server failures
@@ -128,8 +124,7 @@ def use_production_server(self) -> None:
128124
129125
Please use this sparingly - it is better to use the test server.
130126
"""
131-
openml.config.server = self.production_server
132-
openml.config.apikey = ""
127+
openml.config.set_servers("production")
133128

134129
def tearDown(self) -> None:
135130
"""Tear down the test"""

tests/conftest.py

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,7 @@ def delete_remote_files(tracker, flow_names) -> None:
9999
:param tracker: Dict
100100
:return: None
101101
"""
102-
openml.config.server = TestBase.test_server
103-
openml.config.apikey = TestBase.user_key
102+
openml.config.set_servers("test")
104103

105104
# reordering to delete sub flows at the end of flows
106105
# sub-flows have shorter names, hence, sorting by descending order of flow name length
@@ -252,8 +251,23 @@ def test_files_directory() -> Path:
252251

253252

254253
@pytest.fixture(scope="session")
255-
def test_api_key() -> str:
256-
return TestBase.user_key
254+
def test_server_v1() -> str:
255+
return openml.config.get_servers("test")[APIVersion.V1]["server"]
256+
257+
258+
@pytest.fixture(scope="session")
259+
def test_apikey_v1() -> str:
260+
return openml.config.get_servers("test")[APIVersion.V1]["apikey"]
261+
262+
263+
@pytest.fixture(scope="session")
264+
def test_server_v2() -> str:
265+
return openml.config.get_servers("test")[APIVersion.V2]["server"]
266+
267+
268+
@pytest.fixture(scope="session")
269+
def test_apikey_v2() -> str:
270+
return openml.config.get_servers("test")[APIVersion.V2]["apikey"]
257271

258272

259273
@pytest.fixture(autouse=True, scope="function")
@@ -275,12 +289,10 @@ def as_robot() -> Iterator[None]:
275289
@pytest.fixture(autouse=True)
276290
def with_server(request):
277291
if "production_server" in request.keywords:
278-
openml.config.server = "https://www.openml.org/api/v1/xml/"
279-
openml.config.apikey = None
292+
openml.config.set_servers("production")
280293
yield
281294
return
282-
openml.config.server = f"{openml.config.TEST_SERVER_URL}/api/v1/xml/"
283-
openml.config.apikey = TestBase.user_key
295+
openml.config.set_servers("test")
284296
yield
285297

286298

tests/test_api/test_http.py

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -26,28 +26,28 @@ def sample_path() -> str:
2626

2727

2828
@pytest.fixture
29-
def sample_url(sample_path) -> str:
30-
return urljoin(openml.config.server, sample_path)
29+
def sample_url_v1(sample_path, test_server_v1) -> str:
30+
return urljoin(test_server_v1, sample_path)
3131

3232

3333
@pytest.fixture
34-
def sample_download_url() -> str:
35-
server = openml.config.server.split("api/")[0]
34+
def sample_download_url_v1(test_server_v1) -> str:
35+
server = test_server_v1.split("api/")[0]
3636
endpoint = "data/v1/download/1/anneal.arff"
3737
url = server + endpoint
3838
return url
3939

4040

41-
def test_cache(cache, sample_url):
41+
def test_cache(cache, sample_url_v1):
4242
params = {"param1": "value1", "param2": "value2"}
4343

44-
parsed_url = urlparse(sample_url)
44+
parsed_url = urlparse(sample_url_v1)
4545
netloc_parts = parsed_url.netloc.split(".")[::-1]
4646
path_parts = parsed_url.path.strip("/").split("/")
4747
params_key = "&".join([f"{k}={v}" for k, v in params.items()])
4848

4949

50-
key = cache.get_key(sample_url, params)
50+
key = cache.get_key(sample_url_v1, params)
5151

5252
expected_key = os.path.join(
5353
*netloc_parts,
@@ -58,10 +58,10 @@ def test_cache(cache, sample_url):
5858
assert key == expected_key
5959

6060
# mock response
61-
req = Request("GET", sample_url).prepare()
61+
req = Request("GET", sample_url_v1).prepare()
6262
response = Response()
6363
response.status_code = 200
64-
response.url = sample_url
64+
response.url = sample_url_v1
6565
response.reason = "OK"
6666
response._content = b"<xml>test</xml>"
6767
response.headers = {"Content-Type": "text/xml"}
@@ -73,7 +73,7 @@ def test_cache(cache, sample_url):
7373
cached = cache.load(key)
7474

7575
assert cached.status_code == 200
76-
assert cached.url == sample_url
76+
assert cached.url == sample_url_v1
7777
assert cached.content == b"<xml>test</xml>"
7878
assert cached.headers["Content-Type"] == "text/xml"
7979

@@ -87,13 +87,13 @@ def test_get(http_client):
8787

8888

8989
@pytest.mark.uses_test_server()
90-
def test_get_with_cache_creates_cache(http_client, cache, sample_url, sample_path):
90+
def test_get_with_cache_creates_cache(http_client, cache, sample_url_v1, sample_path):
9191
response = http_client.get(sample_path, enable_cache=True)
9292

9393
assert response.status_code == 200
9494
assert cache.path.exists()
9595

96-
cache_key = cache.get_key(sample_url, {})
96+
cache_key = cache.get_key(sample_url_v1, {})
9797
cache_path = cache._key_to_path(cache_key)
9898

9999
assert (cache_path / "meta.json").exists()
@@ -102,8 +102,8 @@ def test_get_with_cache_creates_cache(http_client, cache, sample_url, sample_pat
102102

103103

104104
@pytest.mark.uses_test_server()
105-
def test_get_uses_cached_response(http_client, cache, sample_url, sample_path):
106-
key = cache.get_key(sample_url, {})
105+
def test_get_uses_cached_response(http_client, cache, sample_url_v1, sample_path):
106+
key = cache.get_key(sample_url_v1, {})
107107
meta_path = cache._key_to_path(key) / "meta.json"
108108

109109
r1 = http_client.get(sample_path, enable_cache=True)
@@ -118,8 +118,8 @@ def test_get_uses_cached_response(http_client, cache, sample_url, sample_path):
118118

119119

120120
@pytest.mark.uses_test_server()
121-
def test_get_refresh_cache(http_client, cache, sample_url, sample_path):
122-
key = cache.get_key(sample_url, {})
121+
def test_get_refresh_cache(http_client, cache, sample_url_v1, sample_path):
122+
key = cache.get_key(sample_url_v1, {})
123123
meta_path = cache._key_to_path(key) / "meta.json"
124124

125125
r1 = http_client.get(sample_path, enable_cache=True)
@@ -148,9 +148,9 @@ def test_get_without_api_key_raises(http_client):
148148

149149

150150
@pytest.mark.uses_test_server()
151-
def test_download_creates_file(http_client, sample_download_url):
151+
def test_download_creates_file(http_client, sample_download_url_v1):
152152
path = http_client.download(
153-
url=sample_download_url,
153+
url=sample_download_url_v1,
154154
file_name="downloaded.bin",
155155
)
156156

@@ -160,15 +160,15 @@ def test_download_creates_file(http_client, sample_download_url):
160160

161161

162162
@pytest.mark.uses_test_server()
163-
def test_download_is_cached_on_disk(http_client, sample_download_url):
163+
def test_download_is_cached_on_disk(http_client, sample_download_url_v1):
164164
path1 = http_client.download(
165-
url=sample_download_url,
165+
url=sample_download_url_v1,
166166
file_name="cached.bin",
167167
)
168168
mtime1 = path1.stat().st_mtime
169169

170170
path2 = http_client.download(
171-
url=sample_download_url,
171+
url=sample_download_url_v1,
172172
file_name="cached.bin",
173173
)
174174
mtime2 = path2.stat().st_mtime
@@ -178,13 +178,13 @@ def test_download_is_cached_on_disk(http_client, sample_download_url):
178178

179179

180180
@pytest.mark.uses_test_server()
181-
def test_download_respects_custom_handler(http_client, sample_download_url):
181+
def test_download_respects_custom_handler(http_client, sample_download_url_v1):
182182
def handler(response, path: Path, encoding: str):
183183
path.write_text("HANDLED", encoding=encoding)
184184
return path
185185

186186
path = http_client.download(
187-
url=sample_download_url,
187+
url=sample_download_url_v1,
188188
file_name="handler.bin",
189189
handler=handler,
190190
)
@@ -193,7 +193,7 @@ def handler(response, path: Path, encoding: str):
193193
assert path.read_text() == "HANDLED"
194194

195195

196-
def test_post(http_client):
196+
def test_post(http_client, test_server_v1, test_apikey_v1):
197197
resource_name = "resource"
198198
resource_files = {"description": "Resource Description File"}
199199

@@ -205,15 +205,15 @@ def test_post(http_client):
205205

206206
mock_request.assert_called_once_with(
207207
method="POST",
208-
url=urljoin(openml.config.server, resource_name),
208+
url=urljoin(test_server_v1, resource_name),
209209
params={},
210-
data={"api_key": openml.config.apikey},
210+
data={"api_key": test_apikey_v1},
211211
headers=openml.config._HEADERS,
212212
files=resource_files,
213213
)
214214

215215

216-
def test_delete(http_client):
216+
def test_delete(http_client, test_server_v1, test_apikey_v1):
217217
resource_name = "resource"
218218
resource_id = 123
219219

@@ -226,12 +226,12 @@ def test_delete(http_client):
226226
mock_request.assert_called_once_with(
227227
method="DELETE",
228228
url=(
229-
openml.config.server
229+
test_server_v1
230230
+ resource_name
231231
+ "/"
232232
+ str(resource_id)
233233
),
234-
params={"api_key": openml.config.apikey},
234+
params={"api_key": test_apikey_v1},
235235
data={},
236236
headers=openml.config._HEADERS,
237237
files=None,

0 commit comments

Comments
 (0)