def check_clone_preserves_params(estimator) -> None:
"""Check ``clone()`` preserves shallow params and freshens nested estimators.
Family-agnostic generalization of ``check_clone_preserves_forecaster_params``:
the clone reproduces every ``get_params(deep=False)`` value, and nested
sub-estimators (including ``(name, estimator)`` tuple lists) become fresh
instances of the same type.
Parameters
----------
estimator : BaseEstimator
Estimator instance to clone.
Raises
------
AssertionError
If the clone has different parameter keys or values.
"""
name = type(estimator).__name__
estimator_clone = clone(estimator)
original = estimator.get_params(deep=False)
cloned = estimator_clone.get_params(deep=False)
assert set(original.keys()) == set(cloned.keys()), (
f"{name}: clone() changed parameter keys: {set(cloned.keys())} vs {set(original.keys())}"
)
for key, orig_val in original.items():
cloned_val = cloned[key]
if orig_val is None:
assert cloned_val is None, f"{name}: parameter {key!r} expected None, got {cloned_val!r}"
elif isinstance(orig_val, list) and orig_val and isinstance(orig_val[0], tuple):
# List of (name, estimator[, ...]) tuples (compositors).
assert isinstance(cloned_val, list), f"{name}: parameter {key!r} expected list, got {type(cloned_val)}"
assert len(cloned_val) == len(orig_val), f"{name}: parameter {key!r} changed length under clone()"
for orig_item, cloned_item in zip(orig_val, cloned_val, strict=True):
if not (isinstance(orig_item, tuple) and isinstance(cloned_item, tuple)):
continue
assert orig_item[0] == cloned_item[0], f"{name}: component name changed under clone()"
orig_est, cloned_est = orig_item[1], cloned_item[1]
if isinstance(orig_est, BaseEstimator):
assert type(orig_est) is type(cloned_est), (
f"{name}: component {orig_item[0]!r} changed type under clone()"
)
elif isinstance(orig_val, BaseEstimator):
assert type(orig_val) is type(cloned_val), f"{name}: parameter {key!r} changed type under clone()"
elif not _safe_equal(orig_val, cloned_val):
raise AssertionError(f"{name}: parameter {key!r} expected {orig_val!r}, got {cloned_val!r}")