diff --git a/README.md b/README.md index 9e34b760..66a2f433 100644 --- a/README.md +++ b/README.md @@ -88,13 +88,9 @@ This function uses wsgiref module which is not intended for the production use. This function exposes WSGI interface for people who want to run on the production-class WSGI servers like Gunicorn or uWSGI. -**`save_study_note(study: Study, body: str) -> None`** +**`save_note(study_or_trial: Union[Study, Trial], body: str) -> None`** -Save the note (Markdown format) to the Study. - -**`save_trial_note(trial: Trial, body: str) -> None`** - -Save the note (Markdown format) to the Trial. +Save the note (Markdown format) to the Study or the Trial. **`set_objective_names(study: Study, names: list[str]) -> None`** diff --git a/optuna_dashboard/__init__.py b/optuna_dashboard/__init__.py index f59d98a5..a0de3a34 100644 --- a/optuna_dashboard/__init__.py +++ b/optuna_dashboard/__init__.py @@ -1,8 +1,7 @@ from ._app import run_server # noqa from ._app import wsgi # noqa from ._named_objectives import set_objective_names # noqa -from ._note import save_study_note # noqa -from ._note import save_trial_note # noqa +from ._note import save_note # noqa __version__ = "0.9.0b1" diff --git a/optuna_dashboard/_app.py b/optuna_dashboard/_app.py index 703c4345..2330cf78 100644 --- a/optuna_dashboard/_app.py +++ b/optuna_dashboard/_app.py @@ -407,7 +407,7 @@ def create_app(storage: BaseStorage, debug: bool = False) -> Bottle: "note": note.get_note_from_system_attrs(system_attrs, None), } - note.save_note(storage, study_id, None, req_note_ver, req_note_body) + note.save_note_with_version(storage, study_id, None, req_note_ver, req_note_body) response.status = 204 # No content return {} @@ -430,7 +430,7 @@ def create_app(storage: BaseStorage, debug: bool = False) -> Bottle: "note": note.get_note_from_system_attrs(system_attrs, trial_id), } - note.save_note(storage, study_id, trial_id, req_note_ver, req_note_body) + note.save_note_with_version(storage, study_id, trial_id, req_note_ver, req_note_body) response.status = 204 # No content return {} diff --git a/optuna_dashboard/_note.py b/optuna_dashboard/_note.py index 1ed807dd..3950c72e 100644 --- a/optuna_dashboard/_note.py +++ b/optuna_dashboard/_note.py @@ -1,7 +1,6 @@ from __future__ import annotations import math -from typing import Any from typing import TYPE_CHECKING import optuna @@ -9,8 +8,10 @@ from optuna.storages import BaseStorage if TYPE_CHECKING: + from typing import Any from typing import Optional from typing import TypedDict + from typing import Union NoteType = TypedDict( "NoteType", @@ -23,65 +24,50 @@ if TYPE_CHECKING: SYSTEM_ATTR_MAX_LENGTH = 2045 -def save_study_note(study: optuna.Study, body: str) -> None: - """Save the note (Markdown format) to the Study. +def save_note(study_or_trial: Union[optuna.Study, optuna.Trial], body: str) -> None: + """Save the note (Markdown format) to the Study or Trial. Example: .. code-block:: python import optuna - from optuna_dashboard import save_study_note + from optuna_dashboard import save_note + + + def objective(trial: optuna.Trial) -> float: + x1 = trial.suggest_float("x1", 0, 10) + + save_note(trial, textwrap.dedent(f'''\ + ## Trial {trial.number} + + You can *freely* take a **note** that is associated with the Trial. + ''')) + return (x1 - 2) ** 2 + study = optuna.create_study() - - note = textwrap.dedent('''\ - ## Hello + save_note(study, textwrap.dedent(f'''\ + ## {study.study_name} You can *freely* take a **note** that is associated with the study. - ''') - save_study_note(study, note) - + ''')) + study.optimize(objective, n_trials=10) """ - storage = study._storage - study_id = study._study_id - system_attrs = storage.get_study_system_attrs(study_id) - next_ver = system_attrs.get(note_ver_key(None), 0) + 1 - save_note(storage, study_id, None, next_ver, body) - - -def save_trial_note(trial: optuna.Trial, body: str) -> None: - """Save the note (Markdown format) to the Trial. - - Example: - - .. code-block:: python - - import optuna - import textwrap - from optuna_dashboard import save_trial_note - - def objective_single(trial: optuna.Trial) -> float: - x1 = trial.suggest_float("x1", 0, 10) - x2 = trial.suggest_float("x2", 0, 10) - - note = textwrap.dedent(f'''\ - ## Trial {trial._trial_id} - - $$ - y = (x1 - 2)^{{2}} + (x2 - 5)^{{2}} = ({x1} - 2)^{{2}} + ({x2} - 5)^{{2}} - $$ - ''') - save_trial_note(trial, note) - return (x1 - 2) ** 2 + (x2 - 5) ** 2 - """ - storage = trial.storage - trial_id = trial._trial_id - study_id = trial.study._study_id + storage: BaseStorage + study_id: int + trial_id: Optional[int] = None + if isinstance(study_or_trial, optuna.Study): + storage = study_or_trial._storage + study_id = study_or_trial._study_id + else: + storage = study_or_trial.storage + study_id = study_or_trial.study._study_id + trial_id = study_or_trial._trial_id system_attrs = storage.get_study_system_attrs(study_id) next_ver = system_attrs.get(note_ver_key(trial_id), 0) + 1 - save_note(storage, study_id, trial_id, next_ver, body) + save_note_with_version(storage, study_id, trial_id, next_ver, body) def note_ver_key(trial_id: Optional[int]) -> str: @@ -120,7 +106,7 @@ def version_is_incremented( return req_note_ver == db_note_ver + 1 -def save_note( +def save_note_with_version( storage: BaseStorage, study_id: int, trial_id: Optional[int], ver: int, body: str ) -> None: storage.set_study_system_attr(study_id, note_ver_key(trial_id), ver) diff --git a/python_tests/test_note.py b/python_tests/test_note.py index 5e3c39bb..a45e63d5 100644 --- a/python_tests/test_note.py +++ b/python_tests/test_note.py @@ -5,8 +5,7 @@ from unittest.mock import patch import optuna from optuna_dashboard import _note as note -from optuna_dashboard import save_study_note -from optuna_dashboard import save_trial_note +from optuna_dashboard import save_note class NoteTestCase(TestCase): @@ -28,7 +27,7 @@ class NoteTestCase(TestCase): for body, expected_ver in [("version 1", 1), ("version 2", 2)]: with self.subTest(body): - save_study_note(study, body) + save_note(study, body) system_attrs = study._storage.get_study_system_attrs(study._study_id) note_dict = note.get_note_from_system_attrs(system_attrs, None) assert note_dict["body"] == body @@ -40,7 +39,7 @@ class NoteTestCase(TestCase): for body, expected_ver in [("version 1", 1), ("version 2", 2)]: with self.subTest(body): - save_trial_note(trial, body) + save_note(trial, body) system_attrs = study._storage.get_study_system_attrs(study._study_id) note_dict = note.get_note_from_system_attrs(system_attrs, trial._trial_id) assert note_dict["body"] == body