Repository: facebookresearch/hydra

Issue:
Make composition trace optional and off by default
#1170 added a composition trace to the Hydra output config which is very large and not generally helpful (outside of some special cases).
It should be off by default.


Discussion:

Resolving patch:
diff --git a/hydra/_internal/config_loader_impl.py b/hydra/_internal/config_loader_impl.py
--- a/hydra/_internal/config_loader_impl.py
+++ b/hydra/_internal/config_loader_impl.py
@@ -10,7 +10,7 @@
 from collections import defaultdict
 from dataclasses import dataclass
 from textwrap import dedent
-from typing import Any, Dict, List, Optional, Tuple
+from typing import Any, Dict, List, Optional
 
 from omegaconf import DictConfig, OmegaConf, open_dict
 from omegaconf.errors import (
@@ -26,7 +26,7 @@
     IConfigRepository,
 )
 from hydra._internal.defaults_list import DefaultsList, create_defaults_list
-from hydra.core.config_loader import ConfigLoader, LoadTrace
+from hydra.core.config_loader import ConfigLoader
 from hydra.core.config_search_path import ConfigSearchPath
 from hydra.core.default_element import ResultDefault
 from hydra.core.object_type import ObjectType
@@ -189,7 +189,7 @@ def _load_configuration_impl(
 
         config_overrides = defaults_list.config_overrides
 
-        cfg, composition_trace = self._compose_config_from_defaults_list(
+        cfg = self._compose_config_from_defaults_list(
             defaults=defaults_list.defaults, repo=caching_repo
         )
 
@@ -216,7 +216,6 @@ def _load_configuration_impl(
             cfg.hydra.runtime.version = __version__
             cfg.hydra.runtime.cwd = os.getcwd()
 
-            cfg.hydra.composition_trace = composition_trace
             if "name" not in cfg.hydra.job:
                 cfg.hydra.job.name = JobRuntime().get("name")
             cfg.hydra.job.override_dirname = get_overrides_dirname(
@@ -319,7 +318,7 @@ def _apply_overrides_to_config(overrides: List[Override], cfg: DictConfig) -> No
 
     def _load_single_config(
         self, default: ResultDefault, repo: IConfigRepository
-    ) -> Tuple[ConfigResult, LoadTrace]:
+    ) -> ConfigResult:
         config_path = default.config_path
 
         assert config_path is not None
@@ -385,18 +384,7 @@ def _load_single_config(
 
                 assert isinstance(merged, DictConfig)
 
-        trace = LoadTrace(
-            config_path=default.config_path,
-            package=default.package,
-            parent=default.parent,
-            is_self=default.is_self,
-            search_path=ret.path,
-            provider=ret.provider,
-        )
-
-        ret = self._embed_result_config(ret, default.package)
-
-        return ret, trace
+        return self._embed_result_config(ret, default.package)
 
     @staticmethod
     def _embed_result_config(
@@ -428,11 +416,10 @@ def _compose_config_from_defaults_list(
         self,
         defaults: List[ResultDefault],
         repo: IConfigRepository,
-    ) -> Tuple[DictConfig, List[LoadTrace]]:
-        composition_trace = []
+    ) -> DictConfig:
         cfg = OmegaConf.create()
         for default in defaults:
-            loaded, trace = self._load_single_config(default=default, repo=repo)
+            loaded = self._load_single_config(default=default, repo=repo)
             try:
                 merged = OmegaConf.merge(cfg, loaded.config)
             except ValidationError as e:
@@ -443,12 +430,11 @@ def _compose_config_from_defaults_list(
             assert isinstance(merged, DictConfig)
             cfg = merged
             assert cfg is not None
-            composition_trace.append(trace)
 
         # This is primarily cosmetic
         cfg._metadata.ref_type = cfg._metadata.object_type
 
-        return cfg, composition_trace
+        return cfg
 
     def get_sources(self) -> List[ConfigSource]:
         return self.repository.get_sources()
diff --git a/hydra/conf/__init__.py b/hydra/conf/__init__.py
--- a/hydra/conf/__init__.py
+++ b/hydra/conf/__init__.py
@@ -129,9 +129,6 @@ class HydraConf:
     # Those lists will contain runtime overrides
     overrides: OverridesConf = OverridesConf()
 
-    # the resulting defaults list
-    composition_trace: List[Any] = MISSING
-
     job: JobConf = JobConf()
 
     # populated at runtime
diff --git a/hydra/core/config_loader.py b/hydra/core/config_loader.py
--- a/hydra/core/config_loader.py
+++ b/hydra/core/config_loader.py
@@ -1,6 +1,5 @@
 # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
 from abc import ABC, abstractmethod
-from dataclasses import dataclass
 from typing import Any, List, Optional
 
 from omegaconf import DictConfig
@@ -11,16 +10,6 @@
 from hydra.types import RunMode
 
 
-@dataclass
-class LoadTrace:
-    config_path: Optional[str] = None
-    package: Optional[str] = None
-    parent: Optional[str] = None
-    is_self: bool = False
-    search_path: Optional[str] = None
-    provider: Optional[str] = None
-
-
 class ConfigLoader(ABC):
     """
     Config loader interface


Test patch:
diff --git a/hydra/test_utils/configs/custom_default_launcher.yaml b/hydra/test_utils/configs/custom_default_launcher.yaml
deleted file mode 100644
--- a/hydra/test_utils/configs/custom_default_launcher.yaml
+++ /dev/null
@@ -1,2 +0,0 @@
-defaults:
-  - override hydra/launcher: fancy_launcher
diff --git a/hydra/test_utils/configs/mixed_compose.yaml b/hydra/test_utils/configs/mixed_compose.yaml
deleted file mode 100644
--- a/hydra/test_utils/configs/mixed_compose.yaml
+++ /dev/null
@@ -1,4 +0,0 @@
-defaults:
-  - some_config
-  - group1: file1
-  - config
diff --git a/hydra/test_utils/configs/non_config_group_default.yaml b/hydra/test_utils/configs/non_config_group_default.yaml
deleted file mode 100644
--- a/hydra/test_utils/configs/non_config_group_default.yaml
+++ /dev/null
@@ -1,2 +0,0 @@
-defaults:
-  - some_config
diff --git a/hydra/test_utils/configs/overriding_logging_default.yaml b/hydra/test_utils/configs/overriding_logging_default.yaml
deleted file mode 100644
--- a/hydra/test_utils/configs/overriding_logging_default.yaml
+++ /dev/null
@@ -1,3 +0,0 @@
-defaults:
-  - override hydra/hydra_logging: hydra_debug
-  - override hydra/job_logging: disabled
diff --git a/hydra/test_utils/configs/removing-hydra-launcher-default.yaml b/hydra/test_utils/configs/removing-hydra-launcher-default.yaml
deleted file mode 100644
--- a/hydra/test_utils/configs/removing-hydra-launcher-default.yaml
+++ /dev/null
@@ -1,2 +0,0 @@
-defaults:
-  - override hydra/launcher: null
diff --git a/tests/test_config_loader.py b/tests/test_config_loader.py
--- a/tests/test_config_loader.py
+++ b/tests/test_config_loader.py
@@ -1,9 +1,7 @@
 # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
 import os
 import re
-from copy import deepcopy
 from dataclasses import dataclass
-from itertools import filterfalse
 from textwrap import dedent
 from typing import Any, List
 
@@ -12,7 +10,6 @@
 
 from hydra._internal.config_loader_impl import ConfigLoaderImpl
 from hydra._internal.utils import create_config_search_path
-from hydra.core.config_loader import LoadTrace
 from hydra.core.config_store import ConfigStore, ConfigStoreWithProvider
 from hydra.core.override_parser.overrides_parser import OverridesParser
 from hydra.core.utils import env_override, setup_globals
@@ -43,72 +40,6 @@ class TopLevelConfig:
     db: MySQLConfig = MySQLConfig()
 
 
-hydra_load_list: List[LoadTrace] = [
-    LoadTrace(
-        config_path="hydra/output/default",
-        package="hydra",
-        parent="hydra/config",
-        search_path="pkg://hydra.conf",
-        provider="hydra",
-    ),
-    LoadTrace(
-        config_path="hydra/launcher/basic",
-        package="hydra.launcher",
-        parent="hydra/config",
-        search_path="structured://",
-        provider="hydra",
-    ),
-    LoadTrace(
-        config_path="hydra/sweeper/basic",
-        package="hydra.sweeper",
-        parent="hydra/config",
-        search_path="structured://",
-        provider="hydra",
-    ),
-    LoadTrace(
-        config_path="hydra/help/default",
-        package="hydra.help",
-        parent="hydra/config",
-        search_path="pkg://hydra.conf",
-        provider="hydra",
-    ),
-    LoadTrace(
-        config_path="hydra/hydra_help/default",
-        package="hydra.hydra_help",
-        parent="hydra/config",
-        search_path="pkg://hydra.conf",
-        provider="hydra",
-    ),
-    LoadTrace(
-        config_path="hydra/hydra_logging/default",
-        package="hydra.hydra_logging",
-        parent="hydra/config",
-        search_path="pkg://hydra.conf",
-        provider="hydra",
-    ),
-    LoadTrace(
-        config_path="hydra/job_logging/default",
-        package="hydra.job_logging",
-        parent="hydra/config",
-        search_path="pkg://hydra.conf",
-        provider="hydra",
-    ),
-    LoadTrace(
-        config_path="hydra/config",
-        package="hydra",
-        parent="<root>",
-        is_self=True,
-        search_path="structured://",
-        provider="hydra",
-    ),
-]
-
-
-def assert_same_composition_trace(composition_trace: Any, expected: Any) -> None:
-    actual = [LoadTrace(**x) for x in composition_trace]
-    assert actual == expected
-
-
 @pytest.mark.parametrize(
     "path",
     [
@@ -267,52 +198,6 @@ def test_load_strict(self, path: str) -> None:
                 run_mode=RunMode.RUN,
             )
 
-    def test_load_history(self, path: str) -> None:
-        config_loader = ConfigLoaderImpl(
-            config_search_path=create_config_search_path(path)
-        )
-        cfg = config_loader.load_configuration(
-            config_name="missing-optional-default.yaml",
-            overrides=[],
-            run_mode=RunMode.RUN,
-        )
-        expected = deepcopy(hydra_load_list)
-        expected.append(
-            LoadTrace(
-                config_path="missing-optional-default.yaml",
-                package="",
-                parent="<root>",
-                is_self=True,
-                search_path=path,
-                provider="main",
-            )
-        )
-
-        assert_same_composition_trace(cfg.hydra.composition_trace, expected)
-
-    def test_load_history_with_basic_launcher(self, path: str) -> None:
-        config_loader = ConfigLoaderImpl(
-            config_search_path=create_config_search_path(path)
-        )
-        cfg = config_loader.load_configuration(
-            config_name="custom_default_launcher.yaml",
-            overrides=["hydra/launcher=basic"],
-            strict=False,
-            run_mode=RunMode.RUN,
-        )
-
-        expected = deepcopy(hydra_load_list)
-        expected.append(
-            LoadTrace(
-                config_path="custom_default_launcher.yaml",
-                package="",
-                parent="<root>",
-                search_path=path,
-                provider="main",
-            )
-        )
-        assert_same_composition_trace(cfg.hydra.composition_trace, expected)
-
     def test_load_yml_file(self, path: str) -> None:
         config_loader = ConfigLoaderImpl(
             config_search_path=create_config_search_path(path)
@@ -423,27 +308,6 @@ def test_load_config_file_with_schema_validation(
                 run_mode=RunMode.RUN,
             )
 
-        expected = deepcopy(hydra_load_list)
-        expected.extend(
-            [
-                LoadTrace(
-                    config_path="config",
-                    package="",
-                    parent="<root>",
-                    search_path=path,
-                    provider="main",
-                ),
-                LoadTrace(
-                    config_path="db/mysql",
-                    package="db",
-                    parent="<root>",
-                    search_path=path,
-                    provider="main",
-                ),
-            ]
-        )
-        assert_same_composition_trace(cfg.hydra.composition_trace, expected)
-
         with open_dict(cfg):
             del cfg["hydra"]
         assert cfg == {
@@ -503,51 +367,6 @@ def test_sweep_config_cache(
         assert sweep_cfg.home == os.getenv("HOME")
 
 
-@pytest.mark.parametrize(
-    "config_file, overrides",
-    [
-        # remove from config
-        pytest.param(
-            "removing-hydra-launcher-default.yaml", [], id="remove-from-config"
-        ),
-        # remove from override
-        pytest.param("config.yaml", ["~hydra/launcher"], id="override"),
-        # remove from both
-        pytest.param(
-            "removing-hydra-launcher-default.yaml", ["~hydra/launcher"], id="both"
-        ),
-        # second overrides removes
-        pytest.param(
-            "config.yaml",
-            ["hydra/launcher=submitit", "~hydra/launcher"],
-            id="second-override",
-        ),
-    ],
-)
-def test_default_removal(config_file: str, overrides: List[str]) -> None:
-    config_loader = ConfigLoaderImpl(
-        config_search_path=create_config_search_path("hydra/test_utils/configs")
-    )
-    cfg = config_loader.load_configuration(
-        config_name=config_file, overrides=overrides, strict=False, run_mode=RunMode.RUN
-    )
-
-    expected = deepcopy(hydra_load_list)
-    expected = list(
-        filterfalse(lambda x: x.config_path == "hydra/launcher/basic", expected)
-    )
-    expected.append(
-        LoadTrace(
-            config_path=config_file,
-            package="",
-            parent="<root>",
-            search_path="file://hydra/test_utils/configs",
-            provider="main",
-        )
-    )
-    assert_same_composition_trace(cfg.hydra.composition_trace, expected)
-
-
 def test_defaults_not_list_exception() -> None:
     config_loader = ConfigLoaderImpl(
         config_search_path=create_config_search_path("hydra/test_utils/configs")
@@ -575,87 +394,6 @@ def test_override_hydra_config_value_from_config_file() -> None:
     assert cfg.hydra.run.dir == "foo"
 
 
-def test_override_hydra_config_group_from_config_file() -> None:
-    config_loader = ConfigLoaderImpl(
-        config_search_path=create_config_search_path("hydra/test_utils/configs")
-    )
-
-    cfg = config_loader.load_configuration(
-        config_name="overriding_logging_default.yaml",
-        overrides=[],
-        strict=False,
-        run_mode=RunMode.RUN,
-    )
-    expected = [
-        LoadTrace(
-            config_path="hydra/output/default",
-            package="hydra",
-            parent="hydra/config",
-            search_path="pkg://hydra.conf",
-            provider="hydra",
-        ),
-        LoadTrace(
-            config_path="hydra/launcher/basic",
-            package="hydra.launcher",
-            parent="hydra/config",
-            search_path="structured://",
-            provider="hydra",
-        ),
-        LoadTrace(
-            config_path="hydra/sweeper/basic",
-            package="hydra.sweeper",
-            parent="hydra/config",
-            search_path="structured://",
-            provider="hydra",
-        ),
-        LoadTrace(
-            config_path="hydra/help/default",
-            package="hydra.help",
-            parent="hydra/config",
-            search_path="pkg://hydra.conf",
-            provider="hydra",
-        ),
-        LoadTrace(
-            config_path="hydra/hydra_help/default",
-            package="hydra.hydra_help",
-            parent="hydra/config",
-            search_path="pkg://hydra.conf",
-            provider="hydra",
-        ),
-        LoadTrace(
-            config_path="hydra/hydra_logging/hydra_debug",
-            package="hydra.hydra_logging",
-            parent="hydra/config",
-            search_path="pkg://hydra.conf",
-            provider="hydra",
-        ),
-        LoadTrace(
-            config_path="hydra/job_logging/disabled",
-            package="hydra.job_logging",
-            parent="hydra/config",
-            search_path="pkg://hydra.conf",
-            provider="hydra",
-        ),
-        LoadTrace(
-            config_path="hydra/config",
-            package="hydra",
-            parent="<root>",
-            is_self=True,
-            search_path="structured://",
-            provider="hydra",
-        ),
-        LoadTrace(
-            config_path="overriding_logging_default.yaml",
-            package="",
-            parent="<root>",
-            search_path="file://hydra/test_utils/configs",
-            provider="main",
-        ),
-    ]
-
-    assert_same_composition_trace(cfg.hydra.composition_trace, expected)
-
-
 def test_list_groups() -> None:
     config_loader = ConfigLoaderImpl(
         config_search_path=create_config_search_path(
@@ -682,94 +420,6 @@ def test_list_groups() -> None:
     ]
 
 
-def test_non_config_group_default() -> None:
-    config_loader = ConfigLoaderImpl(
-        config_search_path=create_config_search_path("hydra/test_utils/configs")
-    )
-    cfg = config_loader.load_configuration(
-        config_name="non_config_group_default.yaml",
-        overrides=[],
-        strict=False,
-        run_mode=RunMode.RUN,
-    )
-
-    expected = deepcopy(hydra_load_list)
-    expected.extend(
-        [
-            LoadTrace(
-                config_path="some_config",
-                package="",
-                parent="non_config_group_default.yaml",
-                search_path="file://hydra/test_utils/configs",
-                provider="main",
-            ),
-            LoadTrace(
-                config_path="non_config_group_default.yaml",
-                package="",
-                parent="<root>",
-                is_self=True,
-                search_path="file://hydra/test_utils/configs",
-                provider="main",
-            ),
-        ],
-    )
-
-    assert_same_composition_trace(cfg.hydra.composition_trace, expected)
-
-
-def test_mixed_composition_order() -> None:
-    """
-    Tests that the order of mixed composition (defaults contains both config group and non config group
-    items) is correct
-    """
-    config_loader = ConfigLoaderImpl(
-        config_search_path=create_config_search_path("hydra/test_utils/configs")
-    )
-    cfg = config_loader.load_configuration(
-        config_name="mixed_compose.yaml",
-        overrides=[],
-        strict=False,
-        run_mode=RunMode.RUN,
-    )
-
-    expected = deepcopy(hydra_load_list)
-    expected.extend(
-        [
-            LoadTrace(
-                config_path="some_config",
-                package="",
-                parent="mixed_compose.yaml",
-                search_path="file://hydra/test_utils/configs",
-                provider="main",
-            ),
-            LoadTrace(
-                config_path="group1/file1",
-                package="",
-                parent="mixed_compose.yaml",
-                search_path="file://hydra/test_utils/configs",
-                provider="main",
-            ),
-            LoadTrace(
-                config_path="config",
-                package="",
-                parent="mixed_compose.yaml",
-                search_path="file://hydra/test_utils/configs",
-                provider="main",
-            ),
-            LoadTrace(
-                config_path="mixed_compose.yaml",
-                package="",
-                parent="<root>",
-                is_self=True,
-                search_path="file://hydra/test_utils/configs",
-                provider="main",
-            ),
-        ]
-    )
-
-    assert_same_composition_trace(cfg.hydra.composition_trace, expected)
-
-
 def test_load_schema_as_config(hydra_restore_singletons: Any) -> None:
     """
     Load structured config as a configuration
@@ -787,18 +437,6 @@ def test_load_schema_as_config(hydra_restore_singletons: Any) -> None:
         config_name="config", overrides=[], run_mode=RunMode.RUN
     )
 
-    expected = deepcopy(hydra_load_list)
-    expected.append(
-        LoadTrace(
-            config_path="config",
-            package="",
-            parent="<root>",
-            search_path="structured://",
-            provider="this_test",
-        )
-    )
-    assert_same_composition_trace(cfg.hydra.composition_trace, expected)
-
     with open_dict(cfg):
         del cfg["hydra"]
     assert cfg == {