Skip to content
10 changes: 3 additions & 7 deletions openml/_api_calls.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
from . import config
from .__version__ import __version__
from .exceptions import (
OpenMLAuthenticationError,
OpenMLHashException,
OpenMLNotAuthorizedError,
OpenMLServerError,
OpenMLServerException,
OpenMLServerNoResult,
Expand Down Expand Up @@ -515,11 +515,7 @@ def __parse_server_exception(
400, # run/42 delete
460, # task/42 delete
]:
msg = (
f"The API call {url} requires authentication via an API key.\nPlease configure "
"OpenML-Python to use your API as described in this example:"
"\nhttps://openml.github.io/openml-python/latest/examples/Basics/introduction_tutorial/#authentication"
)
return OpenMLNotAuthorizedError(message=msg)
msg = f"The API call {url} requires authentication via an API key."
return OpenMLAuthenticationError(message=msg)

return OpenMLServerException(code=code, message=full_message, url=url)
23 changes: 23 additions & 0 deletions openml/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,28 @@ class OpenMLNotAuthorizedError(OpenMLServerError):
"""Indicates an authenticated user is not authorized to execute the requested action."""


class OpenMLAuthenticationError(OpenMLServerError):
"""Exception raised when API authentication fails.

This typically occurs when:
- No API key is configured
- The API key is invalid or expired
- The API key format is incorrect

This is different from authorization (OpenMLNotAuthorizedError), which occurs
when a valid API key lacks permissions for the requested operation.
"""

def __init__(self, message: str):
help_text = (
"\n\nTo fix this:\n"
"1. Get your API key from https://www.openml.org/\n"
" (you'll need to register for a free account if you don't have one)\n"
"2. Configure your API key by following the authentication guide:\n"
" https://openml.github.io/openml-python/latest/examples/Basics/introduction_tutorial/#authentication"
)
super().__init__(message + help_text)


class ObjectNotPublishedError(PyOpenMLError):
"""Indicates an object has not been published yet."""
2 changes: 1 addition & 1 deletion tests/test_openml/test_api_calls.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,5 +124,5 @@ def test_authentication_endpoints_requiring_api_key_show_relevant_help_link(
) -> None:
# We need to temporarily disable the API key to test the error message
with openml.config.overwrite_config_context({"apikey": None}):
with pytest.raises(openml.exceptions.OpenMLNotAuthorizedError, match=API_TOKEN_HELP_LINK):
with pytest.raises(openml.exceptions.OpenMLAuthenticationError, match=API_TOKEN_HELP_LINK):
openml._api_calls._perform_api_call(call=endpoint, request_method=method, data=None)