Skip to content

Commit 8a5532f

Browse files
satvshrfkiralygeetu040
authored
[ENH] Improve Global Config Architecture (#1577)
#### Metadata * Reference Issue: fixes #1564 * New Tests Added: No * Documentation Updated: No * Change Log Entry: Replaces global variables with an instance of a dataclass `OpenMLConfig`. #### Details * What does this PR implement/fix? Explain your changes. * Mainly Introduces an `OpenMLConfig` dataclass and an `OpenMLConfigManager` class to accumulate all config functions and varialbles into one class, and a single module-level instance `_config` in `openml.config`. * Reads/parses configuration defaults from `OpenMLConfig`. * Adds `__getattr__` so attribute reads on openml.config forward to the dataclass (preserving read compatibility). * Changes `openml/__init__.py` to route to the instance of `OpenMLConfigManager` when `openml.config` is called. * Moved `ConfigurationForExamples` inside `OpenMLConfigManager` to preserve API. * Why is this change necessary? What is the problem it solves? * consolidates defaults and runtime state into one place, * simplifies consistent parsing and writing of the config file, * removes the use of global variables. --------- Co-authored-by: Franz Király <fkiraly@gcos.ai> Co-authored-by: Armaghan Shakir <raoarmaghanshakir040@gmail.com>
1 parent 25ba6f8 commit 8a5532f

19 files changed

Lines changed: 516 additions & 581 deletions

File tree

openml/__init__.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@
1818
# License: BSD 3-Clause
1919
from __future__ import annotations
2020

21+
from typing import TYPE_CHECKING
22+
2123
from . import (
2224
_api_calls,
23-
config,
25+
_config as _config_module,
2426
datasets,
2527
evaluations,
2628
exceptions,
@@ -49,6 +51,11 @@
4951
OpenMLTask,
5052
)
5153

54+
if TYPE_CHECKING:
55+
from ._config import OpenMLConfigManager
56+
57+
config: OpenMLConfigManager = _config_module.__config
58+
5259

5360
def populate_cache(
5461
task_ids: list[int] | None = None,

openml/_api_calls.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,16 @@
1212
import xml
1313
import zipfile
1414
from pathlib import Path
15+
from typing import cast
1516

1617
import minio
1718
import requests
1819
import requests.utils
1920
import xmltodict
2021
from urllib3 import ProxyManager
2122

22-
from . import config
23+
import openml
24+
2325
from .__version__ import __version__
2426
from .exceptions import (
2527
OpenMLAuthenticationError,
@@ -70,7 +72,7 @@ def resolve_env_proxies(url: str) -> str | None:
7072

7173

7274
def _create_url_from_endpoint(endpoint: str) -> str:
73-
url = config.server
75+
url = cast("str", openml.config.server)
7476
if not url.endswith("/"):
7577
url += "/"
7678
url += endpoint
@@ -171,7 +173,7 @@ def _download_minio_file(
171173
bucket_name=bucket,
172174
object_name=object_name,
173175
file_path=str(destination),
174-
progress=ProgressBar() if config.show_progress else None,
176+
progress=ProgressBar() if openml.config.show_progress else None,
175177
request_headers=_HEADERS,
176178
)
177179
if destination.is_file() and destination.suffix == ".zip":
@@ -300,7 +302,8 @@ def _file_id_to_url(file_id: int, filename: str | None = None) -> str:
300302
Presents the URL how to download a given file id
301303
filename is optional
302304
"""
303-
openml_url = config.server.split("/api/")
305+
openml_server = cast("str", openml.config.server)
306+
openml_url = openml_server.split("/api/")
304307
url = openml_url[0] + f"/data/download/{file_id!s}"
305308
if filename is not None:
306309
url += "/" + filename
@@ -316,7 +319,7 @@ def _read_url_files(
316319
and sending file_elements as files
317320
"""
318321
data = {} if data is None else data
319-
data["api_key"] = config.apikey
322+
data["api_key"] = openml.config.apikey
320323
if file_elements is None:
321324
file_elements = {}
322325
# Using requests.post sets header 'Accept-encoding' automatically to
@@ -336,8 +339,8 @@ def __read_url(
336339
md5_checksum: str | None = None,
337340
) -> requests.Response:
338341
data = {} if data is None else data
339-
if config.apikey:
340-
data["api_key"] = config.apikey
342+
if openml.config.apikey:
343+
data["api_key"] = openml.config.apikey
341344
return _send_request(
342345
request_method=request_method,
343346
url=url,
@@ -362,10 +365,10 @@ def _send_request( # noqa: C901, PLR0912
362365
files: FILE_ELEMENTS_TYPE | None = None,
363366
md5_checksum: str | None = None,
364367
) -> requests.Response:
365-
n_retries = max(1, config.connection_n_retries)
368+
n_retries = max(1, openml.config.connection_n_retries)
366369

367370
response: requests.Response | None = None
368-
delay_method = _human_delay if config.retry_policy == "human" else _robot_delay
371+
delay_method = _human_delay if openml.config.retry_policy == "human" else _robot_delay
369372

370373
# Error to raise in case of retrying too often. Will be set to the last observed exception.
371374
retry_raise_e: Exception | None = None

0 commit comments

Comments
 (0)