# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
import codecs
import distutils
import os
import re
import shutil
from os.path import join, exists, isdir

from setuptools import setup, find_packages

here = os.path.abspath(os.path.dirname(__file__))


def read(*parts):
    with codecs.open(os.path.join(here, *parts), "r") as fp:
        return fp.read()


def find_version(*file_paths):
    version_file = read(*file_paths)
    version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]", version_file, re.M)
    if version_match:
        return version_match.group(1)
    raise RuntimeError("Unable to find version string.")


class CleanCommand(distutils.cmd.Command):
    """
    Our custom command to clean out junk files.
    """

    description = "Cleans out junk files we don't want in the repo"
    user_options = []

    def initialize_options(self):
        pass

    def finalize_options(self):
        pass

    @staticmethod
    def find(root, includes, excludes=[]):
        res = []
        for parent, dirs, files in os.walk(root):
            for f in dirs + files:
                add = list()
                for include in includes:
                    if re.findall(include, f):
                        add.append(join(parent, f))
                res.extend(add)
        final_list = []
        # Exclude things that matches an exclude pattern
        for ex in excludes:
            for file in res:
                if not re.findall(ex, file):
                    final_list.append(file)
        return final_list

    def run(self):
        delete_patterns = [
            ".eggs",
            ".egg-info",
            ".pytest_cache",
            "build",
            "dist",
            "__pycache__",
            ".pyc",
        ]
        deletion_list = CleanCommand.find(
            ".", includes=delete_patterns, excludes=["\\.nox/.*"]
        )

        for f in deletion_list:
            if exists(f):
                if isdir(f):
                    shutil.rmtree(f, ignore_errors=True)
                else:
                    os.unlink(f)


with open("README.md", "r") as fh:
    LONG_DESC = fh.read()
    setup(
        cmdclass={"clean": CleanCommand},
        name="hydra-core",
        version=find_version("hydra", "__init__.py"),
        author="Omry Yadan",
        author_email="omry@fb.com",
        description="Hydra is a library for writing flexible command line applications",
        long_description=LONG_DESC,
        long_description_content_type="text/markdown",
        url="https://github.com/facebookresearch/hydra",
        keywords="command-line configuration yaml tab-completion",
        packages=find_packages(),
        include_package_data=True,
        classifiers=[
            "License :: OSI Approved :: MIT License",
            "Development Status :: 4 - Beta",
            "Programming Language :: Python :: 2.7",
            "Programming Language :: Python :: 3.6",
            "Programming Language :: Python :: 3.7",
            "Operating System :: POSIX :: Linux",
            "Operating System :: MacOS",
            "Operating System :: Microsoft :: Windows",
        ],
        install_requires=[
            "omegaconf>=1.4.0rc2",
            'pathlib2>=2.2.0;python_version<"3.0"',
        ],
        # Install development dependencies with
        # pip install -e .[dev]
        extras_require={
            "dev": [
                "black",
                "coverage",
                "flake8",
                "flake8-copyright",
                "nox",
                "pre-commit",
                "pytest",
                "setuptools",
                "towncrier",
                "twine",
            ]
        },
    )

setup.py
# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
import codecs
import distutils
import os
import re
import shutil
from os.path import join, exists, isdir

from setuptools import setup, find_packages

here = os.path.abspath(os.path.dirname(__file__))


def read(*parts):
    with codecs.open(os.path.join(here, *parts), "r") as fp:
        return fp.read()


def find_version(*file_paths):
    version_file = read(*file_paths)
    version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]", version_file, re.M)
    if version_match:
        return version_match.group(1)
    raise RuntimeError("Unable to find version string.")


class CleanCommand(distutils.cmd.Command):
    """
    Our custom command to clean out junk files.
    """

    description = "Cleans out junk files we don't want in the repo"
    user_options = []

    def initialize_options(self):
        pass

    def finalize_options(self):
        pass

    @staticmethod
    def find(root, includes, excludes=[]):
        res = []
        for parent, dirs, files in os.walk(root):
            for f in dirs + files:
                add = list()
                for include in includes:
                    if re.findall(include, f):
                        add.append(join(parent, f))
                res.extend(add)
        final_list = []
        # Exclude things that matches an exclude pattern
        for ex in excludes:
            for file in res:
                if not re.findall(ex, file):
                    final_list.append(file)
        return final_list

    def run(self):
        delete_patterns = [
            ".eggs",
            ".egg-info",
            ".pytest_cache",
            "build",
            "dist",
            "__pycache__",
            ".pyc",
        ]
        deletion_list = CleanCommand.find(
            ".", includes=delete_patterns, excludes=["\\.nox/.*"]
        )

        for f in deletion_list:
            if exists(f):
                if isdir(f):
                    shutil.rmtree(f, ignore_errors=True)
                else:
                    os.unlink(f)


with open("README.md", "r") as fh:
    LONG_DESC = fh.read()
    setup(
        cmdclass={"clean": CleanCommand},
        name="hydra-core",
        version=find_version("hydra", "__init__.py"),
        author="Omry Yadan",
        author_email="omry@fb.com",
        description="Hydra is a library for writing flexible command line applications",
        long_description=LONG_DESC,
        long_description_content_type="text/markdown",
        url="https://github.com/facebookresearch/hydra",
        keywords="command-line configuration yaml tab-completion",
        packages=find_packages(),
        include_package_data=True,
        classifiers=[
            "License :: OSI Approved :: MIT License",
            "Development Status :: 4 - Beta",
            "Programming Language :: Python :: 2.7",
            "Programming Language :: Python :: 3.6",
            "Programming Language :: Python :: 3.7",
            "Operating System :: POSIX :: Linux",
            "Operating System :: MacOS",
            "Operating System :: Microsoft :: Windows",
        ],
        install_requires=[
            "omegaconf>=1.4.0rc3",
            'pathlib2>=2.2.0;python_version<"3.0"',
        ],
        # Install development dependencies with
        # pip install -e .[dev]
        extras_require={
            "dev": [
                "black",
                "coverage",
                "flake8",
                "flake8-copyright",
                "nox",
                "pre-commit",
                "pytest",
                "setuptools",
                "towncrier",
                "twine",
            ]
        },
    )

setup.py
diff --git a/hydra/test_utils/configs/db/mysql.yaml b/hydra/test_utils/configs/db/mysql.yaml
new file mode 100644
index 00000000000..dc462781224
--- /dev/null
+++ b/hydra/test_utils/configs/db/mysql.yaml
@@ -0,0 +1,4 @@
+db:
+  driver: mysql
+  user: omry
+  pass: secret
diff --git a/hydra/test_utils/configs/db/postgresql.yaml b/hydra/test_utils/configs/db/postgresql.yaml
new file mode 100644
index 00000000000..862073c5d81
--- /dev/null
+++ b/hydra/test_utils/configs/db/postgresql.yaml
@@ -0,0 +1,5 @@
+db:
+  driver: postgresql
+  user: postgre_user
+  pass: drowssap
+  timeout: 10
diff --git a/hydra/test_utils/configs/db_conf.yaml b/hydra/test_utils/configs/db_conf.yaml
new file mode 100644
index 00000000000..fcfafc5e576
--- /dev/null
+++ b/hydra/test_utils/configs/db_conf.yaml
@@ -0,0 +1,5 @@
+defaults:
+  - db: mysql
+
+db:
+  user: ???
\ No newline at end of file
diff --git a/hydra/test_utils/launcher_common_tests.py b/hydra/test_utils/launcher_common_tests.py
index 73f1b4c8605..b83138381d2 100644
--- a/hydra/test_utils/launcher_common_tests.py
+++ b/hydra/test_utils/launcher_common_tests.py
@@ -75,6 +75,58 @@ def test_sweep_over_unspecified_mandatory_default(
                 assert job_ret.cfg == expected_conf[i]
                 verify_dir_outputs(job_ret, job_ret.overrides)
 
+    def test_sweep_and_override(
+        self, sweep_runner, launcher_name, overrides
+    ):  # noqa: F811
+        """
+        This test validates the behavior that happens in issue #283.
+        While constructing the main config, Hydra is skipping the db config group overrides as they are a part of a
+        sweep and will be loaded later.
+        when merging in db.user, there is no such node and this causes an error in strict mode.
+        This is expected behavior, solving it automatically will require validating that we can apply db.user to
+        each of the sweep configs. This can be very expensive for large sweeps so it's not a viable solution.
+        Instead, the solution is for the user to create scaffolding for db.user in the main config, for example:
+        db:
+          user: ???
+
+        This makes sense because overriding db.user in a sweep essentially calls out db.user as
+        existing in all sweep variants.
+        """
+        base_overrides = [
+            "hydra/launcher=" + launcher_name,
+            "db=mysql,postgresql",
+            "db.user=someone",
+        ]
+        sweep = sweep_runner(
+            calling_file=None,
+            calling_module="hydra.test_utils.a_module",
+            config_path="configs/db_conf.yaml",
+            overrides=base_overrides + overrides,
+            strict=True,
+        )
+        expected_overrides = [
+            ["db=mysql", "db.user=someone"],
+            ["db=postgresql", "db.user=someone"],
+        ]
+        expected_conf = [
+            {"db": {"driver": "mysql", "pass": "secret", "user": "someone"}},
+            {
+                "db": {
+                    "user": "someone",
+                    "driver": "postgresql",
+                    "pass": "drowssap",
+                    "timeout": 10,
+                }
+            },
+        ]
+        with sweep:
+            assert len(sweep.returns[0]) == 2
+            for i in range(2):
+                job_ret = sweep.returns[0][i]
+                assert job_ret.overrides == expected_overrides[i]
+                assert job_ret.cfg == expected_conf[i]
+                verify_dir_outputs(job_ret, job_ret.overrides)
+
 
 def sweep_1_job(sweep_runner, overrides, strict=False):
     """
diff --git a/setup.py b/setup.py
index fb0dec15f11..91dc6681a49 100644
--- a/setup.py
+++ b/setup.py
@@ -104,7 +104,7 @@ def run(self):
             "Operating System :: Microsoft :: Windows",
         ],
         install_requires=[
-            "omegaconf>=1.4.0rc2",
+            "omegaconf>=1.4.0rc3",
             'pathlib2>=2.2.0;python_version<"3.0"',
         ],
         # Install development dependencies with
diff --git a/tests/test_basic_launcher.py b/tests/test_basic_launcher.py
index 47aaebd5c7c..8eefa51e1a8 100644
--- a/tests/test_basic_launcher.py
+++ b/tests/test_basic_launcher.py
@@ -24,7 +24,7 @@ class TestBasicLauncher(LauncherTestSuite):
                     {"hydra/launcher": "basic"},
                     {"hydra/hydra_logging": "hydra_debug"},
                     {"hydra/job_logging": "disabled"},
-                ],
+                ]
             },
             ["-m"],
             "hydra._internal.core_plugins.basic_launcher",
diff --git a/tests/test_conf_loader.py b/tests/test_conf_loader.py
index fc73d336e07..922fa51c93b 100644
--- a/tests/test_conf_loader.py
+++ b/tests/test_conf_loader.py
@@ -311,12 +311,8 @@ def test_list_groups():
         strict_cfg=False,
         config_file="overriding_output_dir.yaml",
     )
-    assert sorted(config_loader.list_groups("")) == [
-        "completion_test",
-        "group1",
-        "group2",
-        "hydra",
-    ]
+    groups = config_loader.list_groups("")
+    assert sorted(groups) == ["completion_test", "db", "group1", "group2", "hydra"]
 
     assert sorted(config_loader.list_groups("hydra")) == [
         "help",

[Bug] example of override fail in multirun
This fails

`python examples/tutorial/5_composition/my_app.py -m db=mysql,postgresql db.user=omry`
