Repository: mit-ll-responsible-ai/hydra-zen

Issue:
Add support for `_convert_='object'` for Hydra 1.3.0
See [FR](https://github.com/facebookresearch/hydra/issues/1719) and [merged PR](https://github.com/facebookresearch/hydra/pull/2451) in Hydra for additional details.

In short, starting with Hydra 1.3.0, hydra-zen's config-creation functions should support `hydra_convert='object'`. This signals to Hydra's instantiate that it is to convert resulting objects to instances of their backing dataclass

E.g.,

```python
from hydra_zen import instantiate, builds, make_config

Conf = make_config(a=builds(dict, b=1), hydra_convert="object")  # should raise if local Hydra version is < 1.3.0
assert isinstance(instantiate(Conf), Conf)
```

Discussion:

Patch:
diff --git a/.github/workflows/tox_run.yml b/.github/workflows/tox_run.yml
index bbd88cb4..2f93237c 100644
--- a/.github/workflows/tox_run.yml
+++ b/.github/workflows/tox_run.yml
@@ -139,21 +139,6 @@ jobs:
     - name: Test with tox
       run: tox -e pre-release
 
-  test-against-hydra-1_1_2dev:
-    runs-on: ubuntu-latest
-    steps:
-    - uses: actions/checkout@v3
-    - name: Set up Python 3.8
-      uses: actions/setup-python@v4
-      with:
-        python-version: 3.8
-    - name: Install dependencies
-      run: |
-        python -m pip install --upgrade pip
-        pip install tox tox-gh-actions
-    - name: Test with tox
-      run: tox -e hydra-1p1p2-pre-release
-
   test-against-omegaconf-2p2p2:
     runs-on: ubuntu-latest
     steps:
diff --git a/docs/source/changes.rst b/docs/source/changes.rst
index bfc41891..6e8e9c68 100644
--- a/docs/source/changes.rst
+++ b/docs/source/changes.rst
@@ -118,6 +118,7 @@ New Features
 - Adds the :func:`~hydra_zen.wrapper.Zen` decorator-class (see :pull:`310`)
 - Adds the :class:`~hydra_zen.ZenStore` class (see :pull:`331`)
 - Adds `hyda_zen.store`, which is a pre-initialized instance of :class:`~hydra_zen.ZenStore` (see :pull:`331`)
+- The option `hydra_convert='object'` is now supported by all of hydra-zen's config-creation functions. So that an instantiated structured config can be converted to an instance of its backing dataclass. This feature was added by `Hydra 1.3.0 <https://github.com/facebookresearch/hydra/issues/1719>`_.
 
 Improvements
 ------------
diff --git a/pyproject.toml b/pyproject.toml
index b1936708..69638cf2 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -156,15 +156,6 @@ deps = {[testenv]deps}
        cloudpickle
 basepython = python3.8
 
-[testenv:hydra-1p1p2-pre-release]  # test against pre-releases of dependencies
-pip_pre = true
-deps = hydra-core==1.1.2
-       {[testenv]deps}
-       pydantic
-       beartype
-       cloudpickle
-basepython = python3.8
-
 [testenv:omegaconf-2p2p2]  # guard against regressions for type sanitization
 pip_pre = true
 deps = omegaconf==2.2.2
diff --git a/src/hydra_zen/_compatibility.py b/src/hydra_zen/_compatibility.py
index d7519c1d..7c0b0c13 100644
--- a/src/hydra_zen/_compatibility.py
+++ b/src/hydra_zen/_compatibility.py
@@ -89,3 +89,5 @@ else:  # pragma: no cover
     ZEN_SUPPORTED_PRIMITIVES.update(_path_types)
 
 del _path_types
+
+HYDRA_SUPPORTS_OBJECT_CONVERT = HYDRA_VERSION >= Version(1, 3, 0)
diff --git a/src/hydra_zen/structured_configs/_implementations.py b/src/hydra_zen/structured_configs/_implementations.py
index 3f70b2eb..d824c9df 100644
--- a/src/hydra_zen/structured_configs/_implementations.py
+++ b/src/hydra_zen/structured_configs/_implementations.py
@@ -197,7 +197,7 @@ def hydrated_dataclass(
     zen_meta: Optional[Mapping[str, Any]] = None,
     populate_full_signature: bool = False,
     hydra_recursive: Optional[bool] = None,
-    hydra_convert: Optional[Literal["none", "partial", "all"]] = None,
+    hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = None,
     zen_convert: Optional[ZenConvert] = None,
     init: bool = True,
     repr: bool = True,
@@ -285,6 +285,19 @@ def hydrated_dataclass(
 
         If ``None``, the ``_convert_`` attribute is not set on the resulting config.
 
+    hydra_convert : Optional[Literal["none", "partial", "all", "object"]], optional (default="none")
+        Determines how Hydra treats the non-primitive, omegaconf-specific objects
+        during instantiateion [3]_.
+
+        - ``"none"``: No conversion occurs; omegaconf containers are passed through (Default)
+        - ``"partial"``: ``DictConfig`` and ``ListConfig`` objects converted to ``dict`` and
+          ``list``, respectively. Structured configs and their fields are passed without conversion.
+        - ``"all"``: All passed objects are converted to dicts, lists, and primitives, without
+          a trace of OmegaConf containers.
+        - ``"object"``: Passed objects are converted to dict and list. Structured Configs are converted to instances of the backing dataclass / attr class.
+
+        If ``None``, the ``_convert_`` attribute is not set on the resulting config.
+
     init : bool, optional (default=True)
         If true (the default), a __init__() method will be generated. If the class
         already defines __init__(), this parameter is ignored.
@@ -544,7 +557,7 @@ def sanitized_default_value(
     structured_conf_permitted: bool = True,
     convert_dataclass: bool,
     hydra_recursive: Optional[bool] = None,
-    hydra_convert: Optional[Literal["none", "partial", "all"]] = None,
+    hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = None,
     zen_dataclass: Optional[DataclassOptions] = None,
 ) -> Any:
     """Converts `value` to Hydra-supported type if necessary and possible. Otherwise
@@ -715,7 +728,7 @@ def sanitize_collection(
     *,
     convert_dataclass: bool,
     hydra_recursive: Optional[bool] = None,
-    hydra_convert: Optional[Literal["none", "partial", "all"]] = None,
+    hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = None,
 ) -> _T:
     """Pass contents of lists, tuples, or dicts through sanitized_default_values"""
     type_x = type(x)
@@ -791,7 +804,7 @@ def builds(
     zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
     zen_meta: Optional[Mapping[str, SupportedPrimitive]] = ...,
     hydra_recursive: Optional[bool] = ...,
-    hydra_convert: Optional[Literal["none", "partial", "all"]] = ...,
+    hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
     hydra_defaults: Optional[DefaultsList] = ...,
     dataclass_name: Optional[str] = ...,
     builds_bases: Tuple[()] = ...,
@@ -812,7 +825,7 @@ def builds(
     zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
     zen_meta: Optional[Mapping[str, SupportedPrimitive]] = ...,
     hydra_recursive: Optional[bool] = ...,
-    hydra_convert: Optional[Literal["none", "partial", "all"]] = ...,
+    hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
     hydra_defaults: Optional[DefaultsList] = ...,
     dataclass_name: Optional[str] = ...,
     builds_bases: Tuple[Type[DataClass_], ...] = ...,
@@ -834,7 +847,7 @@ def builds(
     zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
     zen_meta: Optional[Mapping[str, SupportedPrimitive]] = ...,
     hydra_recursive: Optional[bool] = ...,
-    hydra_convert: Optional[Literal["none", "partial", "all"]] = ...,
+    hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
     hydra_defaults: Optional[DefaultsList] = ...,
     dataclass_name: Optional[str] = ...,
     builds_bases: Tuple[Type[DataClass_], ...] = ...,
@@ -856,7 +869,7 @@ def builds(
     zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
     zen_meta: Optional[Mapping[str, SupportedPrimitive]] = ...,
     hydra_recursive: Optional[bool] = ...,
-    hydra_convert: Optional[Literal["none", "partial", "all"]] = ...,
+    hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
     hydra_defaults: Optional[DefaultsList] = ...,
     dataclass_name: Optional[str] = ...,
     builds_bases: Tuple[Type[DataClass_], ...] = ...,
@@ -878,7 +891,7 @@ def builds(
     zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
     zen_meta: Optional[Mapping[str, SupportedPrimitive]] = ...,
     hydra_recursive: Optional[bool] = ...,
-    hydra_convert: Optional[Literal["none", "partial", "all"]] = ...,
+    hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
     hydra_defaults: Optional[DefaultsList] = ...,
     dataclass_name: Optional[str] = ...,
     builds_bases: Tuple[Type[DataClass_], ...] = ...,
@@ -902,7 +915,7 @@ def builds(
     populate_full_signature: bool = False,
     zen_convert: Optional[ZenConvert] = None,
     hydra_recursive: Optional[bool] = None,
-    hydra_convert: Optional[Literal["none", "partial", "all"]] = None,
+    hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = None,
     hydra_defaults: Optional[DefaultsList] = None,
     builds_bases: Tuple[Type[DataClass_], ...] = (),
     zen_dataclass: Optional[DataclassOptions] = None,
@@ -998,7 +1011,7 @@ def builds(
 
         If ``None``, the ``_recursive_`` attribute is not set on the resulting config.
 
-    hydra_convert : Optional[Literal["none", "partial", "all"]], optional (default="none")
+    hydra_convert : Optional[Literal["none", "partial", "all", "object"]], optional (default="none")
         Determines how Hydra handles the non-primitive, omegaconf-specific objects passed to
         ``<hydra_target>`` [4]_.
 
@@ -1007,6 +1020,7 @@ def builds(
           ``list``, respectively. Structured configs and their fields are passed without conversion.
         - ``"all"``: All passed objects are converted to dicts, lists, and primitives, without
           a trace of OmegaConf containers.
+        - ``"object"``: Passed objects are converted to dict and list. Structured Configs are converted to instances of the backing dataclass / attr class.
 
         If ``None``, the ``_convert_`` attribute is not set on the resulting config.
 
diff --git a/src/hydra_zen/structured_configs/_just.py b/src/hydra_zen/structured_configs/_just.py
index a0296e9f..b010f272 100644
--- a/src/hydra_zen/structured_configs/_just.py
+++ b/src/hydra_zen/structured_configs/_just.py
@@ -33,7 +33,7 @@ def just(
     *,
     zen_convert: Optional[ZenConvert] = ...,
     hydra_recursive: Optional[bool] = ...,
-    hydra_convert: Optional[Literal["none", "partial", "all"]] = ...,
+    hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
     zen_dataclass: Optional[DataclassOptions] = ...,
 ) -> TP:
     ...
@@ -45,7 +45,7 @@ def just(
     *,
     zen_convert: Optional[ZenConvert] = ...,
     hydra_recursive: Optional[bool] = ...,
-    hydra_convert: Optional[Literal["none", "partial", "all"]] = ...,
+    hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
     zen_dataclass: Optional[DataclassOptions] = ...,
 ) -> ConfigComplex:
     ...
@@ -57,7 +57,7 @@ def just(
     *,
     zen_convert: Optional[ZenConvert] = ...,
     hydra_recursive: Optional[bool] = ...,
-    hydra_convert: Optional[Literal["none", "partial", "all"]] = ...,
+    hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
     zen_dataclass: Optional[DataclassOptions] = ...,
 ) -> Just[TC]:
     ...
@@ -69,7 +69,7 @@ def just(
     *,
     zen_convert: Optional[ZenConvert] = ...,
     hydra_recursive: Optional[bool] = ...,
-    hydra_convert: Optional[Literal["none", "partial", "all"]] = ...,
+    hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
     zen_dataclass: Optional[DataclassOptions] = ...,
 ) -> Builds[Type[TB]]:
     ...
@@ -81,7 +81,7 @@ def just(
     *,
     zen_convert: Literal[None] = ...,
     hydra_recursive: Optional[bool] = ...,
-    hydra_convert: Optional[Literal["none", "partial", "all"]] = ...,
+    hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
     zen_dataclass: Optional[DataclassOptions] = ...,
 ) -> Type[Builds[Type[TD]]]:
     ...
@@ -93,7 +93,7 @@ def just(
     *,
     zen_convert: ZenConvert,
     hydra_recursive: Optional[bool] = ...,
-    hydra_convert: Optional[Literal["none", "partial", "all"]] = ...,
+    hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
     zen_dataclass: Optional[DataclassOptions] = ...,
 ) -> Any:
     ...
@@ -105,7 +105,7 @@ def just(
     *,
     zen_convert: Optional[ZenConvert] = ...,
     hydra_recursive: Optional[bool] = ...,
-    hydra_convert: Optional[Literal["none", "partial", "all"]] = ...,
+    hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
     zen_dataclass: Optional[DataclassOptions] = ...,
 ) -> Any:
     ...
@@ -116,7 +116,7 @@ def just(
     *,
     zen_convert: Optional[ZenConvert] = None,
     hydra_recursive: Optional[bool] = None,
-    hydra_convert: Optional[Literal["none", "partial", "all"]] = None,
+    hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = None,
     zen_dataclass: Optional[DataclassOptions] = None,
 ) -> Any:
     """`just(obj)` returns a config that, when instantiated, just returns `obj`.
@@ -148,7 +148,7 @@ def just(
 
         If ``None``, the ``_recursive_`` attribute is not set on the resulting config.
 
-    hydra_convert : Optional[Literal["none", "partial", "all"]], optional (default="none")
+    hydra_convert : Optional[Literal["none", "partial", "all", "object"]], optional (default="none")
         Determines how Hydra treats the non-primitive, omegaconf-specific objects
         during instantiateion [3]_.
 
@@ -157,6 +157,7 @@ def just(
           ``list``, respectively. Structured configs and their fields are passed without conversion.
         - ``"all"``: All passed objects are converted to dicts, lists, and primitives, without
           a trace of OmegaConf containers.
+        - ``"object"``: Passed objects are converted to dict and list. Structured Configs are converted to instances of the backing dataclass / attr class.
 
         If ``None``, the ``_convert_`` attribute is not set on the resulting config.
 
diff --git a/src/hydra_zen/structured_configs/_make_config.py b/src/hydra_zen/structured_configs/_make_config.py
index 0ea6a3e2..05198177 100644
--- a/src/hydra_zen/structured_configs/_make_config.py
+++ b/src/hydra_zen/structured_configs/_make_config.py
@@ -142,7 +142,7 @@ _MAKE_CONFIG_SETTINGS = AllConvert(dataclass=False)
 def make_config(
     *fields_as_args: Union[str, ZenField],
     hydra_recursive: Optional[bool] = None,
-    hydra_convert: Optional[Literal["none", "partial", "all"]] = None,
+    hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = None,
     hydra_defaults: Optional[DefaultsList] = None,
     zen_dataclass: Optional[DataclassOptions] = None,
     bases: Tuple[Type[DataClass_], ...] = (),
@@ -189,16 +189,16 @@ def make_config(
 
         If ``None``, the ``_recursive_`` attribute is not set on the resulting config.
 
-    hydra_convert : Optional[Literal["none", "partial", "all"]], optional (default="none")
+    hydra_convert : Optional[Literal["none", "partial", "all", "object"]], optional (default="none")
         Determines how Hydra handles the non-primitive objects passed to configuration [3]_.
 
         - ``"none"``: Passed objects are DictConfig and ListConfig, default
         - ``"partial"``: Passed objects are converted to dict and list, with the exception of Structured Configs (and their fields).
         - ``"all"``: Passed objects are dicts, lists and primitives without a trace of OmegaConf containers
+        - ``"object"``: Passed objects are converted to dict and list. Structured Configs are converted to instances of the backing dataclass / attr class.
 
         If ``None``, the ``_convert_`` attribute is not set on the resulting config.
 
-
     hydra_defaults : None | list[str | dict[str, str | list[str] | None ]], optional (default = None)
         A list in an input config that instructs Hydra how to build the output config
         [7]_ [8]_. Each input config can have a Defaults List as a top level element. The
diff --git a/src/hydra_zen/structured_configs/_make_custom_builds.py b/src/hydra_zen/structured_configs/_make_custom_builds.py
index 3ad75480..bf39e193 100644
--- a/src/hydra_zen/structured_configs/_make_custom_builds.py
+++ b/src/hydra_zen/structured_configs/_make_custom_builds.py
@@ -40,7 +40,7 @@ def make_custom_builds_fn(
     zen_meta: Optional[Mapping[str, Any]] = ...,
     populate_full_signature: Literal[True],
     hydra_recursive: Optional[bool] = ...,
-    hydra_convert: Optional[Literal["none", "partial", "all"]] = ...,
+    hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
     zen_dataclass: Optional[DataclassOptions] = ...,
     frozen: bool = ...,
     zen_convert: Optional[ZenConvert] = ...,
@@ -57,7 +57,7 @@ def make_custom_builds_fn(
     zen_meta: Optional[Mapping[str, Any]] = ...,
     populate_full_signature: bool = ...,
     hydra_recursive: Optional[bool] = ...,
-    hydra_convert: Optional[Literal["none", "partial", "all"]] = ...,
+    hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
     zen_dataclass: Optional[DataclassOptions] = ...,
     frozen: bool = ...,
     zen_convert: Optional[ZenConvert] = ...,
@@ -74,7 +74,7 @@ def make_custom_builds_fn(
     zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
     zen_meta: Optional[Mapping[str, Any]] = ...,
     hydra_recursive: Optional[bool] = ...,
-    hydra_convert: Optional[Literal["none", "partial", "all"]] = ...,
+    hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
     zen_dataclass: Optional[DataclassOptions] = ...,
     frozen: bool = ...,
     zen_convert: Optional[ZenConvert] = ...,
@@ -91,7 +91,7 @@ def make_custom_builds_fn(
     zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
     zen_meta: Optional[Mapping[str, Any]] = ...,
     hydra_recursive: Optional[bool] = ...,
-    hydra_convert: Optional[Literal["none", "partial", "all"]] = ...,
+    hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
     zen_dataclass: Optional[DataclassOptions] = ...,
     frozen: bool = ...,
     zen_convert: Optional[ZenConvert] = ...,
@@ -108,7 +108,7 @@ def make_custom_builds_fn(
     zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
     zen_meta: Optional[Mapping[str, Any]] = ...,
     hydra_recursive: Optional[bool] = ...,
-    hydra_convert: Optional[Literal["none", "partial", "all"]] = ...,
+    hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
     zen_dataclass: Optional[DataclassOptions] = ...,
     frozen: bool = ...,
     zen_convert: Optional[ZenConvert] = ...,
@@ -125,7 +125,7 @@ def make_custom_builds_fn(
     zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
     zen_meta: Optional[Mapping[str, Any]] = ...,
     hydra_recursive: Optional[bool] = ...,
-    hydra_convert: Optional[Literal["none", "partial", "all"]] = ...,
+    hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
     zen_dataclass: Optional[DataclassOptions] = ...,
     frozen: bool = ...,
     zen_convert: Optional[ZenConvert] = ...,
@@ -140,7 +140,7 @@ def make_custom_builds_fn(
     zen_wrappers: ZenWrappers[Callable[..., Any]] = tuple(),
     zen_meta: Optional[Mapping[str, Any]] = None,
     hydra_recursive: Optional[bool] = None,
-    hydra_convert: Optional[Literal["none", "partial", "all"]] = None,
+    hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = None,
     zen_dataclass: Optional[DataclassOptions] = None,
     frozen: bool = False,
     zen_convert: Optional[ZenConvert] = None,
@@ -186,7 +186,7 @@ def make_custom_builds_fn(
     hydra_recursive : Optional[bool], optional (default=True)
         Specifies a new the default value for ``builds(..., hydra_recursive=<..>)``
 
-    hydra_convert : Optional[Literal["none", "partial", "all"]], optional (default="none")
+    hydra_convert : Optional[Literal["none", "partial", "all", "object"]], optional (default="none")
         Specifies a new the default value for ``builds(..., hydra_convert=<..>)``
 
     frozen : bool, optional (default=False)
diff --git a/src/hydra_zen/structured_configs/_utils.py b/src/hydra_zen/structured_configs/_utils.py
index 58ff25d4..0911fce0 100644
--- a/src/hydra_zen/structured_configs/_utils.py
+++ b/src/hydra_zen/structured_configs/_utils.py
@@ -41,6 +41,7 @@ from typing_extensions import (
 from hydra_zen._compatibility import (
     HYDRA_SUPPORTED_PRIMITIVE_TYPES,
     HYDRA_SUPPORTS_NESTED_CONTAINER_TYPES,
+    HYDRA_SUPPORTS_OBJECT_CONVERT,
     HYDRA_SUPPORTS_PARTIAL,
     OMEGACONF_VERSION,
     PATCH_OMEGACONF_830,
@@ -699,16 +700,25 @@ def parse_strict_dataclass_options(
     return options.keys() <= _STRICT_DATACLASS_OPTION_KEYS and StrictDataclassOptions.__required_keys__ <= options.keys()  # type: ignore
 
 
+_HYDRA_CONVERT_OPTIONS = (
+    {"none", "partial", "all", "object"}
+    if HYDRA_SUPPORTS_OBJECT_CONVERT
+    else {"none", "partial", "all"}
+)
+
+
 def validate_hydra_options(
     hydra_recursive: Optional[bool] = None,
-    hydra_convert: Optional[Literal["none", "partial", "all"]] = None,
+    hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = None,
 ) -> None:
     if hydra_recursive is not None and not isinstance(hydra_recursive, bool):
         raise TypeError(
             f"`hydra_recursive` must be a boolean type, got {hydra_recursive}"
         )
 
-    if hydra_convert is not None and hydra_convert not in {"none", "partial", "all"}:
+    if hydra_convert is not None and hydra_convert not in _HYDRA_CONVERT_OPTIONS:
         raise ValueError(
-            f"`hydra_convert` must be 'none', 'partial', or 'all', got: {hydra_convert}"
+            f"`hydra_convert` must be 'none', 'partial',"
+            f"{' object' if HYDRA_SUPPORTS_OBJECT_CONVERT else ''} or 'all', got: "
+            f"{hydra_convert}"
         )


Test patch:
diff --git a/tests/custom_strategies.py b/tests/custom_strategies.py
index 73f1fecd..f936b8de 100644
--- a/tests/custom_strategies.py
+++ b/tests/custom_strategies.py
@@ -18,6 +18,7 @@ from typing import (
 import hypothesis.strategies as st
 
 from hydra_zen import ZenStore, builds
+from hydra_zen._compatibility import HYDRA_SUPPORTS_OBJECT_CONVERT
 from hydra_zen.structured_configs._utils import get_obj_path
 from hydra_zen.typing import DataclassOptions
 from hydra_zen.typing._implementations import ZenConvert
@@ -79,7 +80,14 @@ _valid_builds_strats = dict(
     ),
     populate_full_signature=st.booleans(),
     hydra_recursive=st.booleans(),
-    hydra_convert=st.sampled_from(["none", "partial", "all"]),
+    hydra_convert=st.sampled_from(
+        [
+            "none",
+            "partial",
+            "all",
+            *(("object",) if HYDRA_SUPPORTS_OBJECT_CONVERT else ()),
+        ]
+    ),
     builds_bases=st.just(()),
     zen_convert=st.none() | st.from_type(ZenConvert),
     zen_dataclass=st.none() | st.from_type(DataclassOptions),
diff --git a/tests/test_hydra_behaviors.py b/tests/test_hydra_behaviors.py
index c43f2fdd..b57245d9 100644
--- a/tests/test_hydra_behaviors.py
+++ b/tests/test_hydra_behaviors.py
@@ -9,7 +9,14 @@ from hypothesis import given
 from omegaconf import DictConfig, ListConfig
 from omegaconf.errors import ValidationError
 
-from hydra_zen import builds, hydrated_dataclass, instantiate, mutable_value
+from hydra_zen import (
+    builds,
+    hydrated_dataclass,
+    instantiate,
+    make_config,
+    mutable_value,
+)
+from hydra_zen._compatibility import HYDRA_SUPPORTS_OBJECT_CONVERT
 from hydra_zen.structured_configs._utils import get_obj_path
 
 
@@ -128,6 +135,31 @@ def test_hydra_convert(
     assert type(out["a_struct_config"]["x"]) is expected_field_type
 
 
+@pytest.mark.xfail(
+    not HYDRA_SUPPORTS_OBJECT_CONVERT,
+    raises=ValueError,
+    reason="Hydra 1.3.0 required for _convert_ = 'object'",
+)
+def test_object_convert():
+    Conf = make_config(
+        a=builds(dict, b=1), hydra_convert="object"
+    )  # should raise if local Hydra version is < 1.3.0
+    assert isinstance(instantiate(Conf), Conf)
+
+
+@pytest.mark.xfail(
+    not HYDRA_SUPPORTS_OBJECT_CONVERT,
+    raises=ValueError,
+    reason="Hydra 1.3.0 required for _convert_ = 'object'",
+)
+def test_object_convert_hydrated():
+    @hydrated_dataclass(dict, hydra_convert="object")
+    class A:
+        ...
+
+    assert A._convert_ == "object"  # type: ignore
+
+
 def f_for_recursive(**kwargs):
     return kwargs