Repository: facebookresearch/hydra

Issue:
[Bug] cant pass arg value that contains the char '=' 
# 🐛 Bug

when passing argument value that contains the char '=' an error is thrown:
ValueError: too many values to unpack (expected 2)

## To reproduce

python example.py input_path=s3://rawData/year=2019/month=10/day=29/data_raw_joined.parquet 


** Stack trace/error message **
```
  File "/anaconda3/lib/python3.6/site-packages/hydra/_internal/config_loader.py", line 136, in _apply_defaults_overrides
    key, value = override.split("=")```
**Optional video**
If applicable, record a short [video](https://asciinema.org) with to help explain your problem.
You can also 

## Expected Behavior
I expect way to pass an argument that contains '=' in some other way

## System information
- 0.10.0
- macOS




Discussion:
Hi Gilad,
Thanks for reporting.
This is a pretty simple bug to fix (I think). if you would like to try fixing it I can take a look at a PR.
(Please add tests as well if you do that).

I am traveling so it may take a few weeks before I can fix this).

Resolving patch:
diff --git a/hydra/_internal/config_loader.py b/hydra/_internal/config_loader.py
--- a/hydra/_internal/config_loader.py
+++ b/hydra/_internal/config_loader.py
@@ -124,6 +124,16 @@ def _find_config(self, filepath):
                 break
         return filepath, found_search_path
 
+    @staticmethod
+    def _split_key_val(s):
+        assert "=" in s, "'{}' not a valid override, expecting key=value format".format(
+            s
+        )
+
+        idx = s.find("=")
+        assert idx != -1
+        return s[0:idx], s[idx + 1 :]
+
     @staticmethod
     def _apply_defaults_overrides(overrides, defaults):
         consumed = []
@@ -133,10 +143,7 @@ def _apply_defaults_overrides(overrides, defaults):
                 key = next(iter(d.keys()))
                 key_to_idx[key] = idx
         for override in copy.deepcopy(overrides):
-            assert (
-                "=" in override
-            ), "'{}' not a valid override, expecting key=value format".format(override)
-            key, value = override.split("=")
+            key, value = ConfigLoader._split_key_val(override)
             if key in key_to_idx:
                 if "," in value:
                     # If this is a multirun config (comma separated list), flag the default to prevent it from being
@@ -155,7 +162,7 @@ def _apply_defaults_overrides(overrides, defaults):
     def _apply_free_defaults(self, defaults, overrides):
         consumed = []
         for override in overrides:
-            key, value = override.split("=")
+            key, value = ConfigLoader._split_key_val(override)
             if self.exists_in_search_path(key):
                 # Do not add multirun configs into defaults, those will be added to the defaults
                 # during the runs after list is broken into items
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -103,7 +103,10 @@ def run(self):
             "Operating System :: MacOS",
             "Operating System :: Microsoft :: Windows",
         ],
-        install_requires=["omegaconf>=1.3.0", 'pathlib2>=2.2.0;python_version<"3.0"'],
+        install_requires=[
+            "omegaconf>=1.4.0rc1",
+            'pathlib2>=2.2.0;python_version<"3.0"',
+        ],
         # Install development dependencies with
         # pip install -e .[dev]
         extras_require={


Test patch:
diff --git a/tests/test_completion.py b/tests/test_completion.py
--- a/tests/test_completion.py
+++ b/tests/test_completion.py
@@ -49,7 +49,7 @@ def create_config_loader():
         ("dict.", 3, ["dict.key1=", "dict.key2=", "dict.key3="]),
         ("dict.key", 2, ["dict.key1=", "dict.key2=", "dict.key3="]),
         ("dict.key1=", 2, ["dict.key1=val1"]),
-        ("dict.key3=", 2, ["dict.key3="]),
+        ("dict.key3=", 2, []),  # no matches because value is ??? (missing)
         ("list", 2, ["list.", "list_prefix="]),
         ("list.", 2, ["list.0=", "list.1=", "list.2="]),
         (
diff --git a/tests/test_conf_loader.py b/tests/test_conf_loader.py
--- a/tests/test_conf_loader.py
+++ b/tests/test_conf_loader.py
@@ -165,6 +165,16 @@ def test_load_yml_file(self, path):
         del cfg["hydra"]
         assert cfg == dict(yml_file_here=True)
 
+    def test_override_with_equals(self, path):
+        config_loader = ConfigLoader(
+            config_search_path=create_search_path([path]),
+            strict_cfg=False,
+            config_file="config.yaml",
+        )
+        cfg = config_loader.load_configuration(overrides=["abc='cde=12'"])
+        del cfg["hydra"]
+        assert cfg == OmegaConf.create({"normal_yaml_config": True, "abc": "cde=12"})
+
 
 @pytest.mark.parametrize(
     "primary,merged,result",