Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion openml/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@
tasks,
utils,
)
from .__version__ import __version__

__version__ = "0.16.0" # defined here directly, see issue #1642
from .datasets import OpenMLDataFeature, OpenMLDataset
from .evaluations import OpenMLEvaluation
from .flows import OpenMLFlow
Expand Down
8 changes: 0 additions & 8 deletions openml/__version__.py

This file was deleted.

157 changes: 99 additions & 58 deletions openml/setups/setup.py
Original file line number Diff line number Diff line change
@@ -1,84 +1,111 @@
# License: BSD 3-Clause
from __future__ import annotations

from dataclasses import asdict, dataclass
from typing import Any

import openml.config
import openml.flows
from openml.base import OpenMLBase


@dataclass
class OpenMLSetup:
class OpenMLSetup(OpenMLBase):
"""Setup object (a.k.a. Configuration).

An OpenML Setup corresponds to a flow with a specific parameter configuration.
It inherits :class:`~openml.base.OpenMLBase` to gain shared functionality
like tagging, URL access and ``__repr__``.

Parameters
----------
setup_id : int
The OpenML setup id
The OpenML setup id.
flow_id : int
The flow that it is build upon
parameters : dict
The setting of the parameters
The flow that it is built upon.
parameters : dict or None
The setting of the parameters, mapping parameter id to
:class:`OpenMLParameter`.
"""

setup_id: int
flow_id: int
parameters: dict[int, Any] | None

def __post_init__(self) -> None:
if not isinstance(self.setup_id, int):
def __init__(
self,
setup_id: int,
flow_id: int,
parameters: dict[int, Any] | None,
) -> None:
if not isinstance(setup_id, int):
raise ValueError("setup id should be int")

if not isinstance(self.flow_id, int):
if not isinstance(flow_id, int):
raise ValueError("flow id should be int")

if self.parameters is not None and not isinstance(self.parameters, dict):
if parameters is not None and not isinstance(parameters, dict):
raise ValueError("parameters should be dict")

self.setup_id = setup_id
self.flow_id = flow_id
self.parameters = parameters

@property
def id(self) -> int | None:
"""The setup id, unique among OpenML setups."""
return self.setup_id

@classmethod
def _entity_letter(cls) -> str:
"""Return the letter used in OpenML URLs for setups (``'s'``)."""
return "s"

def _get_repr_body_fields(
self,
) -> list[tuple[str, str | int | list[str] | None]]:
"""Return fields shown in :meth:`__repr__`."""
n_params: int | str = len(self.parameters) if self.parameters is not None else "nan"
return [
("Setup ID", self.setup_id),
("Flow ID", self.flow_id),
("Flow URL", openml.flows.OpenMLFlow.url_for_id(self.flow_id)),
("# of Parameters", n_params),
]

def _to_dict(self) -> dict[str, Any]:
"""Return a dictionary representation of this setup."""
return {
"setup_id": self.setup_id,
"flow_id": self.flow_id,
"parameters": {p.id: p._to_dict() for p in self.parameters.values()}
if self.parameters is not None
else None,
}

def __repr__(self) -> str:
header = "OpenML Setup"
header = f"{header}\n{'=' * len(header)}\n"

fields = {
"Setup ID": self.setup_id,
"Flow ID": self.flow_id,
"Flow URL": openml.flows.OpenMLFlow.url_for_id(self.flow_id),
"# of Parameters": (
len(self.parameters) if self.parameters is not None else float("nan")
"parameters": (
{p.id: p._to_dict() for p in self.parameters.values()}
if self.parameters is not None
else None
),
}

# determines the order in which the information will be printed
order = ["Setup ID", "Flow ID", "Flow URL", "# of Parameters"]
_fields = [(key, fields[key]) for key in order if key in fields]
def _parse_publish_response(self, xml_response: dict[str, str]) -> None:
"""Setups cannot be published; raises :class:`NotImplementedError`."""
raise NotImplementedError("OpenML Setups cannot be published.")

longest_field_name_length = max(len(name) for name, _ in _fields)
field_line_format = f"{{:.<{longest_field_name_length}}}: {{}}"
body = "\n".join(field_line_format.format(name, value) for name, value in _fields)
return header + body
def publish(self) -> OpenMLBase:
"""Setups cannot be published to the server.

Raises
------
TypeError
Always raised — OpenML Setups are created server-side and cannot be
uploaded by the client.
"""
raise TypeError(
"OpenML Setups are created automatically when a run is published "
"and cannot be uploaded directly."
)


@dataclass
class OpenMLParameter:
"""Parameter object (used in setup).

Parameters
----------
input_id : int
The input id from the openml database
flow id : int
flow_id : int
The flow to which this parameter is associated
flow name : str
flow_name : str
The name of the flow (no version number) to which this parameter
is associated
full_name : str
Expand All @@ -94,33 +121,47 @@ class OpenMLParameter:
If the parameter was set, the value that it was set to.
"""

input_id: int
flow_id: int
flow_name: str
full_name: str
parameter_name: str
data_type: str
default_value: str
value: str

def __post_init__(self) -> None:
def __init__( # noqa: PLR0913
self,
input_id: int,
flow_id: int,
flow_name: str,
full_name: str,
parameter_name: str,
data_type: str,
default_value: str,
value: str,
) -> None:
self.input_id = input_id
self.flow_id = flow_id
self.flow_name = flow_name
self.full_name = full_name
self.parameter_name = parameter_name
self.data_type = data_type
self.default_value = default_value
self.value = value
# Map input_id to id for backward compatibility
self.id = self.input_id

def _to_dict(self) -> dict[str, Any]:
result = asdict(self)
# Replaces input_id with id for backward compatibility
result["id"] = result.pop("input_id")
return result
return {
"id": self.input_id,
"flow_id": self.flow_id,
"flow_name": self.flow_name,
"full_name": self.full_name,
"parameter_name": self.parameter_name,
"data_type": self.data_type,
"default_value": self.default_value,
"value": self.value,
}

def __repr__(self) -> str:
header = "OpenML Parameter"
header = f"{header}\n{'=' * len(header)}\n"

fields = {
fields: dict[str, Any] = {
"ID": self.id,
"Flow ID": self.flow_id,
# "Flow Name": self.flow_name,
"Flow Name": self.full_name,
"Flow URL": openml.flows.OpenMLFlow.url_for_id(self.flow_id),
"Parameter Name": self.parameter_name,
Expand Down