Repository: facebookresearch/hydra

Issue:
[Bug] MISSING for Object Conf cls argument
# 🐛 Bug

OmegaConf cls argument should not be a mandatory value if target is defined. Can we change this to be an optional value with None being the default?
 
** Stack trace/error message **
```
omegaconf.errors.MissingMandatoryValue: Missing mandatory value: scheduler.cls
        full_key: scheduler.cls
        reference_type=ObjectConf
        object_type=ObjectConf
```


## System information
- **Hydra Version** :  1.0.0rc2
- **Python version** : 3.7.7



Discussion:
Please create a minimal repro.
cc @shagunsodhani 
[struct.zip](https://github.com/facebookresearch/hydra/files/4940924/struct.zip)
Run: `python my_app.py +fn=NR +db=mysql`
I am using code from master.

Added the example as a gist: https://gist.github.com/shagunsodhani/cafab41a2ce43d3cb4604c652725aa02

In the current form, the bug is not happening because of `cls`/`target`. It is happening because `dict(cfg.fn)` is trying to resolve `cfg.fn` (which contains a key with missing value). Adding the config below for reference:

```
db:
  driver: mysql
  host: localhost
  port: 3306
fn:
  target: my_app.name_print
  params:
    name: ''
  cls: ???
```

I modified the script to use `hydra.utils.instantiate` (which I think was the intent of the user). In that case, the script works fine. The reference script (with one change): https://gist.github.com/shagunsodhani/f5bad29584e7cddee47526257237970e  and command to run it: `python my_app.py +fn=NR +db=mysql fn.params.name=hydra`. Output: 

```
hydra
db:
  driver: mysql
  host: localhost
  port: 3306
fn:
  target: my_app.name_print
  params:
    name: hydra
  cls: ???
```

On a side note, running the script does not throw any warning (despite `cls` key being present) because of the [additional check that `cls==???`](https://github.com/facebookresearch/hydra/blob/master/hydra/_internal/utils.py#L598). Had some value been set for `cls`, the script will throw a warning, but still work. For example, if the command is:  `python my_app.py +fn=NR +db=mysql fn.params.name=hydra fn.cls=any_random_cls`, output will be:

```
UserWarning: Config key 'fn.cls' is deprecated since Hydra 1.0 and will be removed in Hydra 1.1.
Use 'target' instead of 'cls'.
  warnings.warn(
hydra
db:
  driver: mysql
  host: localhost
  port: 3306
fn:
  target: my_app.name_print
  params:
    name: hydra
  cls: any_random_cls
```

In the above example, note that if both `cls` and `target` are present, `target` will be used.


So my reason for putting dict(cfg.fn) as this mirrors the use case in an issue I am having. I am using a library which tries to flatten the cfg.fn and log all its values. The problem is as we loop through all the config values, cls is missing which causes the above error. 
@shagunsodhani , please clean this up. dunno why I missed it:
```
@dataclass
# This extends Dict[str, Any] to allow for the deprecated "class" field.
# Once support for class field removed this can stop extending Dict.
class ObjectConf(Dict[str, Any]):
    # class, class method or function name
    target: str = MISSING

    # parameters to pass to cls when calling it
    params: Any = field(default_factory=dict)

    # cls is deprecated, use target, cls will be removed in Hydra 1.1
    cls: str = MISSING

    # class is deprecated, use target, class will be removed in Hydra 1.1
    # (class is Python keyword and is only supported through DictConfig)
    # class: str = MISSING
```

You can completely remove everytging after params.
just kill cls, this was introduced in Hydra 1.0 and it's not yet released. I don't mind breaking here.
Do we still allow using `cls` via config files or should I kill that as well? The current plan is to kill it in 1.1

Resolving patch:
diff --git a/hydra/types.py b/hydra/types.py
--- a/hydra/types.py
+++ b/hydra/types.py
@@ -18,13 +18,6 @@ class ObjectConf(Dict[str, Any]):
     # parameters to pass to cls when calling it
     params: Any = field(default_factory=dict)
 
-    # cls is deprecated, use target, cls will be removed in Hydra 1.1
-    cls: str = MISSING
-
-    # class is deprecated, use target, class will be removed in Hydra 1.1
-    # (class is Python keyword and is only supported through DictConfig)
-    # class: str = MISSING
-
 
 class RunMode(Enum):
     RUN = 1


Test patch:
diff --git a/tests/test_internal_utils.py b/tests/test_internal_utils.py
--- a/tests/test_internal_utils.py
+++ b/tests/test_internal_utils.py
@@ -92,13 +92,6 @@ def test_get_class_name(
 @pytest.mark.skipif(  # type: ignore
     sys.version_info < (3, 7), reason="requires python3.7"
 )
-def test_cls() -> None:
-    with pytest.warns(expected_warning=UserWarning):
-        assert utils._get_cls_name(ObjectConf(cls="foo")) == "foo"
-    with pytest.warns(expected_warning=UserWarning):
-        assert utils._get_cls_name(ObjectConf(cls="foo", target="bar")) == "bar"
-
-
 @pytest.mark.parametrize(  # type: ignore
     "name,expected",
     [