From 045853c30dd248c850ae6ea9ea07b852a7bfbcb0 Mon Sep 17 00:00:00 2001 From: Ryan Soklaski Date: Wed, 26 Jan 2022 10:35:16 -0500 Subject: [PATCH] Deprecations introduced in v0.3.0 are now errors (#212) * deprecated uses of target-as-kwarg and hydra_partial are now errors * Deprecated used of hydra_partial in hydrated_dataclass is now error * Add changelog notes * remove deprecated hydra_run, hydra_multirun * remove docs fro hydra_run and hydra_multirun --- docs/source/api_reference.rst | 8 - docs/source/changes.rst | 12 +- .../hydra_zen.experimental.hydra_multirun.rst | 6 - .../hydra_zen.experimental.hydra_run.rst | 6 - src/hydra_zen/experimental.py | 152 ------------------ .../structured_configs/_implementations.py | 98 ++--------- tests/test_experimental.py | 24 --- tests/test_validation.py | 50 +----- 8 files changed, 27 insertions(+), 329 deletions(-) delete mode 100644 docs/source/generated/hydra_zen.experimental.hydra_multirun.rst delete mode 100644 docs/source/generated/hydra_zen.experimental.hydra_run.rst delete mode 100644 src/hydra_zen/experimental.py delete mode 100644 tests/test_experimental.py diff --git a/docs/source/api_reference.rst b/docs/source/api_reference.rst index f9f8870b..333d6303 100644 --- a/docs/source/api_reference.rst +++ b/docs/source/api_reference.rst @@ -26,14 +26,6 @@ Python function instead of from a commandline interface. launch -.. currentmodule:: hydra_zen.experimental - -.. autosummary:: - :toctree: generated/ - - hydra_run - hydra_multirun - ********************************* Creating and Working with Configs diff --git a/docs/source/changes.rst b/docs/source/changes.rst index 872a45b8..32ca8c7f 100644 --- a/docs/source/changes.rst +++ b/docs/source/changes.rst @@ -33,11 +33,16 @@ Improvements - :ref:`Type widening ` will now be applied to configured fields where an interpolated variable -- a string of form ``"${}"`` -- is specified. See :issue:`206` for rationale and examples. - Fixed incomplete annotations for ``builds(..., zen_wrappers=<..>)``. See :pull:`180` +Compatibility-Breaking Changes +------------------------------ + +The deprecations :ref:`introduced in v0.3.0 <0p3p0-deprecations>` are now errors. Refer to those notes for details and for solutions for fixing stale code. + + Notes ----- -There are no compatibility-breaking changes in this release. However, it should be -noted that the aforementioned improvements to :func:`~hydra_zen.builds` can change -the interface to your app. +It should be noted that the aforementioned improvements to :func:`~hydra_zen.builds` +can change the interface to your app. For instance, if you were configuring ``torch.utils.data.DataLoader``, note the following difference in behavior: @@ -192,6 +197,7 @@ New Features interpolation will be valid no matter where the configuration is utilized. See :pull:`112`. +.. _0p3p0-deprecations: Deprecations ------------ diff --git a/docs/source/generated/hydra_zen.experimental.hydra_multirun.rst b/docs/source/generated/hydra_zen.experimental.hydra_multirun.rst deleted file mode 100644 index 32384670..00000000 --- a/docs/source/generated/hydra_zen.experimental.hydra_multirun.rst +++ /dev/null @@ -1,6 +0,0 @@ -hydra_multirun -============== - -.. currentmodule:: hydra_zen.experimental - -.. autofunction:: hydra_multirun \ No newline at end of file diff --git a/docs/source/generated/hydra_zen.experimental.hydra_run.rst b/docs/source/generated/hydra_zen.experimental.hydra_run.rst deleted file mode 100644 index 93b0a8f9..00000000 --- a/docs/source/generated/hydra_zen.experimental.hydra_run.rst +++ /dev/null @@ -1,6 +0,0 @@ -hydra_run -========= - -.. currentmodule:: hydra_zen.experimental - -.. autofunction:: hydra_run \ No newline at end of file diff --git a/src/hydra_zen/experimental.py b/src/hydra_zen/experimental.py deleted file mode 100644 index 61838466..00000000 --- a/src/hydra_zen/experimental.py +++ /dev/null @@ -1,152 +0,0 @@ -# Copyright (c) 2022 Massachusetts Institute of Technology -# SPDX-License-Identifier: MIT - -import warnings -from pathlib import Path -from typing import Any, Callable, List, Mapping, Optional, Union - -from omegaconf.dictconfig import DictConfig - -from hydra_zen.errors import HydraZenDeprecationWarning -from hydra_zen.typing._implementations import DataClass - -from ._launch import launch - - -def hydra_run( - config: Union[DataClass, DictConfig, Mapping], - task_function: Callable[[DictConfig], Any], - overrides: Optional[List[str]] = None, - config_dir: Optional[Union[str, Path]] = None, - config_name: str = "hydra_run", - job_name: str = "hydra_run", - with_log_configuration: bool = True, -): - """(Deprecated) Launch a Hydra job defined by `task_function` using the configuration - provided in `config`. - - .. deprecated:: 0.3.0 - `hydra_run` will be removed in hydra-zen 1.0.0; it is replaced by - :func:`hydra_zen.launch`. - - Parameters - ---------- - config : Union[DataClass, DictConfig, Mapping] - A configuration as a dataclass, configuration object, or a dictionary. - - task_function : Callable[[DictConfig], Any] - The function Hydra will execute with the given configuration. - - overrides : Optional[List[str]] (default: None) - If provided, overrides default configurations, see [1]_ and [2]_. - - config_dir : Optional[Union[str, Path]] (default: None) - Add configuration directories if needed. - - config_name : str (default: "hydra_run") - Name of the stored configuration in Hydra's ConfigStore API. - - job_name : str (default: "hydra_run") - - with_log_configuration : bool (default: True) - Flag to configure logging subsystem from the loaded config - - Returns - ------- - result : JobReturn - - References - ---------- - .. [1] https://hydra.cc/docs/next/advanced/override_grammar/basic - .. [2] https://hydra.cc/docs/next/configure_hydra/intro - .. [3] https://hydra.cc/docs/tutorials/basic/running_your_app/multi-run - """ - warnings.warn( - HydraZenDeprecationWarning( - "hydra_zen.experimental.hydra_run is deprecated " - "as of 2021-10-27. Change `hydra_run(cfg, task_fn, overrides, ...)` to `launch(cfg, task_fn, overrides, ...)`." - "\n\nThis will be an error in hydra-zen 1.0.0, or by 2022-01-27 — whichever " - "comes first.\n\nNote: This deprecation does not impact yaml configs " - "produced by `builds`." - ), - stacklevel=2, - ) - return launch( - config, - task_function=task_function, - overrides=overrides, - config_dir=config_dir, - config_name=config_name, - job_name=job_name, - with_log_configuration=with_log_configuration, - ) - - -def hydra_multirun( - config: Union[DataClass, DictConfig, Mapping], - task_function: Callable[[DictConfig], Any], - overrides: Optional[List[str]] = None, - config_dir: Optional[Union[str, Path]] = None, - config_name: str = "hydra_run", - job_name: str = "hydra_run", - with_log_configuration: bool = True, -): - """(Deprecated) Launch multiple Hydra jobs defined by `task_function` using the configuration - provided in `config`. - - .. deprecated:: 0.3.0 - `hydra_multirun` will be removed in hydra-zen 1.0.0; it is replaced by - :func:`hydra_zen.launch`. - - Parameters - ---------- - config : Union[DataClass, DictConfig, Mapping] - A configuration as a dataclass, configuration object, or a dictionary. - - task_function : Callable[[DictConfig], Any] - The function Hydra will execute with the given configuration. - - overrides : Optional[List[str]] (default: None) - If provided, overrides default configurations, see [1]_ and [2]_. - - config_dir : Optional[Union[str, Path]] (default: None) - Add configuration directories if needed. - - config_name : str (default: "hydra_run") - Name of the stored configuration in Hydra's ConfigStore API. - - job_name : str (default: "hydra_run") - - with_log_configuration : bool (default: True) - Flag to configure logging subsystem from the loaded config - - Returns - ------- - result : Any - - References - ---------- - .. [1] https://hydra.cc/docs/next/advanced/override_grammar/basic - .. [2] https://hydra.cc/docs/next/configure_hydra/intro - .. [3] https://hydra.cc/docs/tutorials/basic/running_your_app/multi-run - """ - warnings.warn( - HydraZenDeprecationWarning( - "hydra_zen.experimental.hydra_multirun is deprecated " - "as of 2021-10-27. Change `hydra_multirun(cfg, task_fn, overrides, ...)` to `launch(cfg, task_fn, overrides, multirun=True, ...)`." - "\n\nThis will be an error in hydra-zen 1.0.0, or by 2022-01-27 — whichever " - "comes first.\n\nNote: This deprecation does not impact yaml configs " - "produced by `builds`." - ), - stacklevel=2, - ) - return launch( - config, - task_function=task_function, - overrides=overrides, - config_dir=config_dir, - config_name=config_name, - job_name=job_name, - with_log_configuration=with_log_configuration, - multirun=True, - ) diff --git a/src/hydra_zen/structured_configs/_implementations.py b/src/hydra_zen/structured_configs/_implementations.py index b3e52819..559dd71e 100644 --- a/src/hydra_zen/structured_configs/_implementations.py +++ b/src/hydra_zen/structured_configs/_implementations.py @@ -154,56 +154,6 @@ def _retain_type_info(type_: type, value: Any, hydra_recursive: Optional[bool]): return False -def _target_as_kwarg_deprecation(func: _T2) -> Callable[..., _T2]: - @wraps(func) - def wrapped(*args, **kwargs): - if not args and "target" in kwargs: - # builds(target=<>, ...) is deprecated - warnings.warn( - HydraZenDeprecationWarning( - "Specifying the target of `builds` as a keyword argument is deprecated " - "as of 2021-10-27. Change `builds(target=, ...)` to `builds(, ...)`." - "\n\nThis will be an error in hydra-zen 1.0.0, or by 2021-01-27 — whichever " - "comes first.\n\nNote: This deprecation does not impact yaml configs " - "produced by `builds`." - ), - stacklevel=2, - ) - target = kwargs.pop("target") - return func(target, *args, **kwargs) - return func(*args, **kwargs) - - return wrapped - - -def _hydra_partial_deprecation(func: _T2) -> Callable[..., _T2]: - @wraps(func) - def wrapped(*args, **kwargs): - if "hydra_partial" in kwargs: - if "zen_partial" in kwargs: - raise TypeError( - "Both `hydra_partial` and `zen_partial` are specified. " - "Specifying `hydra_partial` is deprecated, use `zen_partial` " - "instead." - ) - - # builds(..., hydra_partial=...) is deprecated - warnings.warn( - HydraZenDeprecationWarning( - "The argument `hydra_partial` is deprecated as of 2021-10-27.\n" - "Change `builds(..., hydra_partial=<..>)` to `builds(..., zen_partial=<..>)`." - "\n\nThis will be an error in hydra-zen 1.0.0, or by 2022-01-27 — whichever " - "comes first.\n\nNote: This deprecation does not impact yaml configs " - "produced by `builds`." - ), - stacklevel=2, - ) - kwargs["zen_partial"] = kwargs.pop("hydra_partial") - return func(*args, **kwargs) - - return wrapped - - def mutable_value(x: _T) -> _T: """Used to set a mutable object as a default value for a field in a dataclass. @@ -271,7 +221,6 @@ def hydrated_dataclass( hydra_recursive: Optional[bool] = None, hydra_convert: Optional[Literal["none", "partial", "all"]] = None, frozen: bool = False, - **_kw, # reserved to deprecate hydra_partial ) -> Callable[[Type[_T]], Type[_T]]: """A decorator that uses `builds` to create a dataclass with the appropriate Hydra-specific fields for specifying a targeted config [1]_. @@ -390,31 +339,6 @@ def hydrated_dataclass( For more detailed examples, refer to `builds`. """ - if "hydra_partial" in _kw: - if zen_partial is True: - raise TypeError( - "Both `hydra_partial` and `zen_partial` are specified. " - "Specifying `hydra_partial` is deprecated, use `zen_partial` " - "instead." - ) - - # builds(..., hydra_partial=...) is deprecated - warnings.warn( - HydraZenDeprecationWarning( - "The argument `hydra_partial` is deprecated as of 2021-10-27.\n" - "Change `builds(..., hydra_partial=<..>)` to `builds(..., zen_partial=<..>)`." - "\n\nThis will be an error in hydra-zen 1.0.0, or by 2022-01-27 — whichever " - "comes first.\n\nNote: This deprecation does not impact yaml configs " - "produced by `builds`." - ), - stacklevel=2, - ) - zen_partial = _kw.pop("hydra_partial") - if _kw: - raise TypeError( - f"hydrated_dataclass got an unexpected argument: {', '.join(_kw)}" - ) - def wrapper(decorated_obj: Any) -> Any: if not isinstance(decorated_obj, type): @@ -757,20 +681,18 @@ def builds( ... -@_hydra_partial_deprecation -@_target_as_kwarg_deprecation def builds( - *pos_args: Any, - zen_partial: bool = False, - zen_wrappers: ZenWrappers = tuple(), - zen_meta: Optional[Mapping[str, SupportedPrimitive]] = None, - populate_full_signature: bool = False, - hydra_recursive: Optional[bool] = None, - hydra_convert: Optional[Literal["none", "partial", "all"]] = None, + *pos_args, + zen_partial=False, + zen_wrappers=tuple(), + zen_meta=None, + populate_full_signature=False, + hydra_recursive=None, + hydra_convert=None, frozen: bool = False, - builds_bases: Tuple[Type[_DataClass], ...] = (), - dataclass_name: Optional[str] = None, - **kwargs_for_target: SupportedPrimitive, + builds_bases=(), + dataclass_name=None, + **kwargs_for_target, ) -> Union[Type[Builds[Importable]], Type[PartialBuilds[Importable]]]: """builds(hydra_target, /, *pos_args, zen_partial=False, zen_meta=None, hydra_recursive=None, populate_full_signature=False, hydra_convert=None, diff --git a/tests/test_experimental.py b/tests/test_experimental.py deleted file mode 100644 index 0e0014fc..00000000 --- a/tests/test_experimental.py +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (c) 2022 Massachusetts Institute of Technology -# SPDX-License-Identifier: MIT - -import pytest - -from hydra_zen import builds, instantiate -from hydra_zen.errors import HydraZenDeprecationWarning -from hydra_zen.experimental import hydra_multirun, hydra_run - - -@pytest.mark.usefixtures("cleandir") -def test_hydra_run_is_deprecated(): - cfg = builds(dict, a=1, b=1) - overrides = ["a=1"] - with pytest.warns(HydraZenDeprecationWarning): - hydra_run(cfg, instantiate, overrides) - - -@pytest.mark.usefixtures("cleandir") -def test_hydra_multirun_is_deprecated(): - cfg = builds(dict, a=1, b=1) - overrides = ["a=1,2"] - with pytest.warns(HydraZenDeprecationWarning): - hydra_multirun(cfg, instantiate, overrides) diff --git a/tests/test_validation.py b/tests/test_validation.py index 3126df33..94d79c07 100644 --- a/tests/test_validation.py +++ b/tests/test_validation.py @@ -31,63 +31,29 @@ def test_builds_no_positional_target_raises(): builds(hydra_target=dict) -@pytest.mark.filterwarnings("ignore:Specifying the target of") -def test_target_as_kwarg_is_deprecated(): - with pytest.warns(HydraZenDeprecationWarning): +def test_target_as_kwarg_is_an_error(): + with pytest.raises(TypeError): builds(target=int) # type: ignore -@pytest.mark.filterwarnings("ignore:Specifying the target of") -def test_builds_target_as_kwarg_is_still_correct(): - out = instantiate(builds(target=dict, a=2, b=3, zen_partial=True))() # type: ignore - assert out == {"a": 2, "b": 3} - - -@pytest.mark.filterwarnings("ignore:The argument `hydra_partial` is deprecated") -def test_hydra_partial_is_deprecated(): - with pytest.warns(HydraZenDeprecationWarning): +def test_hydra_partial_is_error(): + with pytest.raises(ValueError): builds(int, hydra_partial=True) -@pytest.mark.filterwarnings("ignore:The argument `hydra_partial` is deprecated") -@given(st.booleans()) -def test_hydra_partial_is_still_works(as_partial): - out = instantiate(builds(int, hydra_partial=as_partial)) - - if as_partial: - assert out() == 0 # type: ignore - else: - assert out == 0 - - -@pytest.mark.filterwarnings("ignore:The argument `hydra_partial` is deprecated") -def test_hydra_partial_via_hydrated_dataclass_is_deprecated(): - with pytest.warns(HydraZenDeprecationWarning): +def test_hydra_partial_via_hydrated_dataclass_is_error(): + with pytest.raises(TypeError): - @hydrated_dataclass(int, hydra_partial=True) + @hydrated_dataclass(int, hydra_partial=True) # type: ignore class A: pass -@pytest.mark.filterwarnings("ignore:The argument `hydra_partial` is deprecated") -@given(st.booleans()) -def test_hydra_partial_via_hydrated_dataclass_still_works(as_partial): - @hydrated_dataclass(int, hydra_partial=as_partial) - class A: - pass - - out = instantiate(A) - if as_partial: - assert out() == 0 - else: - assert out == 0 - - @given(hydra_partial=st.booleans(), zen_partial=st.booleans()) def test_specifying_hydra_partial_and_zen_partial_raises( hydra_partial: bool, zen_partial: bool ): - with pytest.raises(TypeError): + with pytest.raises(ValueError): builds(int, hydra_partial=hydra_partial, zen_partial=zen_partial)