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
11 changes: 11 additions & 0 deletions dvc/commands/experiments/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ def run(self):
tmp_dir=self.args.tmp_dir,
copy_paths=self.args.copy_paths,
message=self.args.message,
no_hydra=self.args.no_hydra,
**self._common_kwargs,
)

Expand Down Expand Up @@ -107,4 +108,14 @@ def _add_run_common(parser):
default=None,
help="Custom commit message to use when committing the experiment.",
)
parser.add_argument(
"--no-hydra",
action="store_true",
default=False,
help=(
"Disables automatically updating `params.yaml` with Hydra configuration. "
" You can still use `--set-param` to update individual params if needed."
" Default is False."
),
)
parser.add_argument("-M", dest="message", help=argparse.SUPPRESS) # obsolete
9 changes: 6 additions & 3 deletions dvc/repo/experiments/queue/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ def _stash_exp(
baseline_rev: Optional[str] = None,
branch: Optional[str] = None,
name: Optional[str] = None,
no_hydra: bool = False,
**kwargs,
) -> QueueEntry:
"""Stash changes from the workspace as an experiment.
Expand All @@ -302,6 +303,7 @@ def _stash_exp(
name: Optional experiment name. If specified this will be used as
the human-readable name in the experiment branch ref. Has no
effect of branch is specified.
no_hydra: Disable Hydra from automatically overwriting all params.

.. _Hydra Override:
https://hydra.cc/docs/next/advanced/override_grammar/basic/
Expand All @@ -318,7 +320,7 @@ def _stash_exp(

# update experiment params from command line
if params:
self._update_params(params)
self._update_params(params, no_hydra=no_hydra)

# DVC commit data deps to preserve state across workspace
# & tempdir runs
Expand Down Expand Up @@ -441,12 +443,13 @@ def _format_new_params_msg(new_params, config_path):
f"from '{config_path}': {param_list}"
)

def _update_params(self, params: dict[str, list[str]]):
def _update_params(self, params: dict[str, list[str]], no_hydra: bool = False):
"""Update param files with the provided `Hydra Override`_ patterns.

Args:
params: Dict mapping paths to `Hydra Override`_ patterns,
provided via `exp run --set-param`.
no_hydra: Disable Hydra from automatically overwriting all params.

.. _Hydra Override:
https://hydra.cc/docs/advanced/override_grammar/basic/
Expand All @@ -456,7 +459,7 @@ def _update_params(self, params: dict[str, list[str]]):
logger.debug("Using experiment params '%s'", params)

hydra_config = self.repo.config.get("hydra", {})
hydra_enabled = hydra_config.get("enabled", False)
hydra_enabled = hydra_config.get("enabled", False) and not no_hydra
hydra_output_file = ParamsDependency.DEFAULT_PARAMS_FILE
for path, overrides in params.items():
if hydra_enabled and path == hydra_output_file:
Expand Down
5 changes: 4 additions & 1 deletion dvc/repo/experiments/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ def run( # noqa: C901, PLR0912
queue: bool = False,
copy_paths: Optional[Iterable[str]] = None,
message: Optional[str] = None,
no_hydra: bool = False,
**kwargs,
) -> dict[str, str]:
"""Reproduce the specified targets as an experiment.
Expand Down Expand Up @@ -67,7 +68,7 @@ def run( # noqa: C901, PLR0912
else:
path_overrides = {}

hydra_enabled = repo.config.get("hydra", {}).get("enabled", False)
hydra_enabled = repo.config.get("hydra", {}).get("enabled", False) and not no_hydra
hydra_output_file = ParamsDependency.DEFAULT_PARAMS_FILE
if hydra_enabled and hydra_output_file not in path_overrides:
# Force `_update_params` even if `--set-param` was not used
Expand All @@ -80,6 +81,7 @@ def run( # noqa: C901, PLR0912
tmp_dir=tmp_dir,
copy_paths=copy_paths,
message=message,
no_hydra=no_hydra,
**kwargs,
)

Expand All @@ -100,6 +102,7 @@ def run( # noqa: C901, PLR0912
params=sweep_overrides,
copy_paths=copy_paths,
message=message,
no_hydra=no_hydra,
**kwargs,
)
if sweep_overrides:
Expand Down
83 changes: 79 additions & 4 deletions tests/func/experiments/test_set_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ def test_modify_params(params_repo, dvc, changes, expected):
("conf", "bar"),
],
)
@pytest.mark.parametrize("no_hydra", [True, False])
def test_hydra_compose_and_dump(
tmp_dir, params_repo, dvc, hydra_enabled, config_dir, config_name
tmp_dir, params_repo, dvc, hydra_enabled, config_dir, config_name, no_hydra
):
hydra_setup(
tmp_dir,
Expand All @@ -50,14 +51,14 @@ def test_hydra_compose_and_dump(
if config_name is not None:
conf["hydra"]["config_name"] = config_name

dvc.experiments.run()
dvc.experiments.run(no_hydra=no_hydra)

if hydra_enabled:
if hydra_enabled and not no_hydra:
assert (tmp_dir / "params.yaml").parse() == {
"db": {"driver": "mysql", "user": "omry", "pass": "secret"},
}

dvc.experiments.run(params=["db=postgresql"])
dvc.experiments.run(params=["db=postgresql"], no_hydra=no_hydra)
assert (tmp_dir / "params.yaml").parse() == {
"db": {
"driver": "postgresql",
Expand Down Expand Up @@ -117,6 +118,7 @@ def test_hydra_sweep(
targets=None,
copy_paths=None,
message=None,
no_hydra=False,
)


Expand All @@ -137,3 +139,76 @@ def test_hydra_sweep_prefix_name(tmp_dir, params_repo, dvc):
exp_names = [entry.name for entry in dvc.experiments.celery_queue.iter_queued()]
for name, expected in zip(exp_names, expected_names):
assert name == expected


def test_mixing_no_hydra_and_params_flags(tmp_dir, params_repo, dvc):
# Passing no_hydra should not prevent user from
# using --set-param on unmodified params.yaml
hydra_setup(
tmp_dir,
config_dir="conf",
config_name="config",
)

with dvc.config.edit() as conf:
conf["hydra"]["enabled"] = True
conf["hydra"]["config_dir"] = "conf"
conf["hydra"]["config_name"] = "config"

dvc.experiments.run(no_hydra=True, params=["goo.bag=10.0"])

assert (tmp_dir / "params.yaml").parse() == {
"foo": [{"bar": 1}, {"baz": 2}],
"goo": {"bag": 10.0},
"lorem": False,
}


@pytest.mark.parametrize(
"hydra_enabled,overrides,expected",
[
(
True,
["db=mysql,postgresql"],
[
{"params.yaml": ["db=mysql"]},
{"params.yaml": ["db=postgresql"]},
],
),
(
False,
["foo=bar,baz"],
[{"params.yaml": ["foo=bar"]}, {"params.yaml": ["foo=baz"]}],
),
(
False,
[],
[{}],
),
],
)
@pytest.mark.parametrize("no_hydra", [True, False])
def test_mixing_no_hydra_and_sweeps(
tmp_dir, params_repo, dvc, mocker, hydra_enabled, overrides, expected, no_hydra
):
# Passing no_hydra should not prevent user from
# queuing sweeps with --set-param and --queue
patched = mocker.patch.object(dvc.experiments, "queue_one")
Comment on lines +190 to +196
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the point of using --no-hydra here?

Would this still hydrate yaml file using hydra? Or, is this only limited to sweeps?

Copy link
Author

@StaszekM StaszekM Sep 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

During first tests (dvc exp run) no-hydra flag worked fine, but I noticed later that this flag does not work if we pass --queue and related sweep params, then sweeps are created with configs hydrated with Hydra.

So I changed implementation in both exp scenarios (as one exp and as a sweep) to handle this new flag

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may also need to change this:

def _update_params(self, params: dict[str, list[str]]):


if hydra_enabled:
hydra_setup(tmp_dir, config_dir="conf", config_name="config")
with dvc.config.edit() as conf:
conf["hydra"]["enabled"] = True

dvc.experiments.run(params=overrides, queue=True, no_hydra=no_hydra)

assert patched.call_count == len(expected)
for e in expected:
patched.assert_any_call(
mocker.ANY,
params=e,
targets=None,
copy_paths=None,
message=None,
no_hydra=no_hydra,
)
2 changes: 2 additions & 0 deletions tests/unit/command/test_experiments.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ def test_experiments_run(dvc, scm, mocker):
"tmp_dir": False,
"copy_paths": [],
"message": None,
"no_hydra": False,
}
default_arguments.update(repro_arguments)

Expand All @@ -151,6 +152,7 @@ def test_experiments_run_message(dvc, scm, mocker, flag):
"tmp_dir": False,
"copy_paths": [],
"message": "mymessage",
"no_hydra": False,
}
default_arguments.update(repro_arguments)

Expand Down
Loading