Visitar URL original
update test for tensorflow routing · DeepLabCut/DeepLabCut@0aded65 · GitHub
Skip to content

Commit 0aded65

Browse files
committed
update test for tensorflow routing
- drop the read_config patches from the router tests - assert the config is forwarded to get_shuffle_engine untouched - Parametrize the forwarding test over str, Path, dict and ProjectConfig - fix renamed_parameter(since=...) -> deprecation_round=..
1 parent 5460840 commit 0aded65

2 files changed

Lines changed: 40 additions & 38 deletions

File tree

‎tests/api/test_pose_estimation.py‎

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -707,26 +707,23 @@ def test_visualize_paf_delegates_to_core_visualization():
707707
# Unlike the tests above (which patch ``_resolve_engine`` directly), these
708708
# exercise the real ``with_tensorflow_fallback`` router through a real public
709709
# API function, with the filesystem/metadata lookups mocked:
710-
# - ``read_config`` -> returns a canned config (no YAML on disk)
711-
# - ``get_shuffle_engine`` -> returns the engine (no project metadata)
710+
# - ``get_shuffle_engine`` -> returns the engine (no project metadata, no YAML on disk)
712711
# - the downstream PyTorch impl -> MagicMock (no model loaded)
713712
# This is NOT an end-to-end test: nothing touches disk, weights, or the network.
714713

715714

716715
@patch("deeplabcut.generate_training_dataset.metadata.get_shuffle_engine", return_value=_PYTORCH)
717-
@patch("deeplabcut.core.config.utils.read_config", return_value={"project_path": "/tmp"})
718716
@pytest.mark.tf_routing_integration
719-
def test_analyze_videos_resolves_engine_from_config(mock_read_config, mock_get_shuffle_engine):
720-
"""analyze_videos drives the real router: config -> read_config -> get_shuffle_engine -> PyTorch."""
717+
def test_analyze_videos_resolves_engine_from_config(mock_get_shuffle_engine):
718+
"""analyze_videos drives the real router: config -> get_shuffle_engine -> PyTorch."""
721719
mock_impl = MagicMock(return_value="scorer")
722720
with patch("deeplabcut.pose_estimation_pytorch.apis.analyze_videos", mock_impl):
723721
from deeplabcut.api.pose_estimation import analyze_videos
724722

725723
analyze_videos("cfg.yaml", ["video.mp4"], shuffle=2, save_as_csv=True)
726724

727-
mock_read_config.assert_called_once_with("cfg.yaml")
728725
mock_get_shuffle_engine.assert_called_once_with(
729-
{"project_path": "/tmp"},
726+
"cfg.yaml",
730727
trainingsetindex=0,
731728
shuffle=2,
732729
modelprefix="",
@@ -737,9 +734,8 @@ def test_analyze_videos_resolves_engine_from_config(mock_read_config, mock_get_s
737734

738735

739736
@patch("deeplabcut.generate_training_dataset.metadata.get_shuffle_engine", return_value=_PYTORCH)
740-
@patch("deeplabcut.core.config.utils.read_config", return_value={"project_path": "/tmp"})
741737
@pytest.mark.tf_routing_integration
742-
def test_export_model_cfg_path_alias_reaches_engine_resolution(mock_read_config, mock_get_shuffle_engine):
738+
def test_export_model_cfg_path_alias_reaches_engine_resolution(mock_get_shuffle_engine):
743739
"""Legacy ``cfg_path`` is renamed to ``config`` *before* engine resolution, so the
744740
router can read the config (would KeyError without the rename)."""
745741
mock_impl = MagicMock(return_value=None)
@@ -751,8 +747,12 @@ def test_export_model_cfg_path_alias_reaches_engine_resolution(mock_read_config,
751747

752748
export_model(cfg_path="cfg.yaml", shuffle=2, overwrite=True)
753749

754-
mock_read_config.assert_called_once_with("cfg.yaml")
755-
mock_get_shuffle_engine.assert_called_once()
750+
mock_get_shuffle_engine.assert_called_once_with(
751+
"cfg.yaml",
752+
trainingsetindex=0,
753+
shuffle=2,
754+
modelprefix="",
755+
)
756756
mock_impl.assert_called_once()
757757
assert mock_impl.call_args.kwargs["config"] == "cfg.yaml"
758758
assert "cfg_path" not in mock_impl.call_args.kwargs

‎tests/api/test_tf_routing.py‎

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@
1313
from __future__ import annotations
1414

1515
import inspect
16+
from pathlib import Path
1617
from unittest.mock import MagicMock, patch
1718

1819
import pytest
1920

2021
from deeplabcut.api import _tf_routing as tf_routing
22+
from deeplabcut.core.config import ProjectConfig
2123
from deeplabcut.core.deprecation import DLCDeprecationWarning
2224
from deeplabcut.core.engine import Engine
2325

@@ -203,14 +205,17 @@ def test_resolve_legacy_kwargs_does_not_mutate_renamed_params():
203205
# ---------------------------------------------------------------------------
204206

205207

206-
def test_resolve_engine_uses_explicit_engine():
208+
@patch("deeplabcut.generate_training_dataset.metadata.get_shuffle_engine", return_value=Engine.TF)
209+
def test_resolve_engine_uses_explicit_engine_without_metadata_lookup(mock_get_shuffle_engine):
210+
"""An explicit engine short-circuits resolution, so the config is never read."""
207211
engine = tf_routing._resolve_engine({"config": "cfg.yaml", "engine": Engine.PYTORCH})
212+
208213
assert engine == Engine.PYTORCH
214+
mock_get_shuffle_engine.assert_not_called()
209215

210216

211217
@patch("deeplabcut.generate_training_dataset.metadata.get_shuffle_engine", return_value=Engine.PYTORCH)
212-
@patch("deeplabcut.core.config.utils.read_config", return_value={"project_path": "/tmp"})
213-
def test_resolve_engine_from_shuffle_metadata(mock_read_config, mock_get_shuffle_engine):
218+
def test_resolve_engine_from_shuffle_metadata(mock_get_shuffle_engine):
214219
engine = tf_routing._resolve_engine(
215220
{
216221
"config": "cfg.yaml",
@@ -221,32 +226,37 @@ def test_resolve_engine_from_shuffle_metadata(mock_read_config, mock_get_shuffle
221226
)
222227

223228
assert engine == Engine.PYTORCH
224-
mock_read_config.assert_called_once_with("cfg.yaml")
225229
mock_get_shuffle_engine.assert_called_once_with(
226-
{"project_path": "/tmp"},
230+
"cfg.yaml",
227231
trainingsetindex=1,
228232
shuffle=2,
229233
modelprefix="prefix",
230234
)
231235

232236

237+
@pytest.mark.parametrize(
238+
"config",
239+
["cfg.yaml", Path("cfg.yaml"), {"project_path": "/tmp"}, ProjectConfig(project_path="/tmp")],
240+
ids=["str", "path", "dict", "project_config"],
241+
)
233242
@patch("deeplabcut.generate_training_dataset.metadata.get_shuffle_engine", return_value=Engine.PYTORCH)
234-
@patch("deeplabcut.core.config.utils.read_config", return_value={"project_path": "/tmp"})
235-
def test_resolve_engine_defaults_to_shuffle_one(mock_read_config, mock_get_shuffle_engine):
236-
engine = tf_routing._resolve_engine({"config": "cfg.yaml"})
243+
def test_resolve_engine_forwards_config_as_is_and_defaults_to_shuffle_one(mock_get_shuffle_engine, config):
244+
"""Config is forwarded untouched, and shuffle defaults to 1 when none is given.
245+
``get_shuffle_engine`` accepts ProjectConfig | dict | Path | str
246+
"""
247+
engine = tf_routing._resolve_engine({"config": config})
237248

238249
assert engine == Engine.PYTORCH
239250
mock_get_shuffle_engine.assert_called_once_with(
240-
{"project_path": "/tmp"},
251+
config,
241252
trainingsetindex=0,
242253
shuffle=1,
243254
modelprefix="",
244255
)
245256

246257

247258
@patch("deeplabcut.generate_training_dataset.metadata.get_shuffle_engine")
248-
@patch("deeplabcut.core.config.utils.read_config", return_value={"project_path": "/tmp"})
249-
def test_resolve_engine_from_shuffles_list(mock_read_config, mock_get_shuffle_engine):
259+
def test_resolve_engine_from_shuffles_list(mock_get_shuffle_engine):
250260
mock_get_shuffle_engine.side_effect = [Engine.PYTORCH, Engine.PYTORCH]
251261

252262
engine = tf_routing._resolve_engine({"config": "cfg.yaml", "shuffles": [1, 2]})
@@ -256,20 +266,19 @@ def test_resolve_engine_from_shuffles_list(mock_read_config, mock_get_shuffle_en
256266

257267

258268
@patch("deeplabcut.generate_training_dataset.metadata.get_shuffle_engine", return_value=Engine.TF)
259-
@patch("deeplabcut.core.config.utils.read_config", return_value={"project_path": "/tmp"})
260-
def test_resolve_engine_accepts_legacy_shuffles_kwarg(mock_read_config, mock_get_shuffle_engine):
269+
def test_resolve_engine_accepts_legacy_shuffles_kwarg(mock_get_shuffle_engine):
261270
engine = tf_routing._resolve_engine({"config": "cfg.yaml", "Shuffles": [2, 3]})
262271

263272
assert engine == Engine.TF
264273
assert mock_get_shuffle_engine.call_count == 2
265274
mock_get_shuffle_engine.assert_any_call(
266-
{"project_path": "/tmp"},
275+
"cfg.yaml",
267276
trainingsetindex=0,
268277
shuffle=2,
269278
modelprefix="",
270279
)
271280
mock_get_shuffle_engine.assert_any_call(
272-
{"project_path": "/tmp"},
281+
"cfg.yaml",
273282
trainingsetindex=0,
274283
shuffle=3,
275284
modelprefix="",
@@ -288,22 +297,13 @@ def test_resolve_engine_raises_on_emplty_shuffles(shuffles):
288297

289298

290299
@patch("deeplabcut.generate_training_dataset.metadata.get_shuffle_engine")
291-
@patch("deeplabcut.core.config.utils.read_config", return_value={"project_path": "/tmp"})
292-
def test_resolve_engine_raises_when_shuffles_have_different_engines(mock_read_config, mock_get_shuffle_engine):
300+
def test_resolve_engine_raises_when_shuffles_have_different_engines(mock_get_shuffle_engine):
293301
mock_get_shuffle_engine.side_effect = [Engine.PYTORCH, Engine.TF]
294302

295303
with pytest.raises(ValueError, match="All shuffles must have the same engine"):
296304
tf_routing._resolve_engine({"config": "cfg.yaml", "shuffles": [1, 2]})
297305

298306

299-
@patch("deeplabcut.core.config.utils.read_config", return_value={"project_path": "/tmp"})
300-
def test_resolve_engine_reads_config_from_kwargs(mock_read_config):
301-
with patch("deeplabcut.generate_training_dataset.metadata.get_shuffle_engine", return_value=Engine.PYTORCH):
302-
tf_routing._resolve_engine({"config": "other.yaml", "engine": Engine.PYTORCH})
303-
304-
mock_read_config.assert_not_called()
305-
306-
307307
# ---------------------------------------------------------------------------
308308
# warn_deprecated_tensorflow
309309
# ---------------------------------------------------------------------------
@@ -598,12 +598,14 @@ def canonical_fn(path: str, model_name: str, **kwargs):
598598

599599
def test_with_tensorflow_fallback_forwards_legacy_alias_to_renamed_parameter():
600600
"""Router must not swallow legacy alias before inner @renamed_parameter."""
601-
from deeplabcut.core.deprecation import renamed_parameter
601+
from deeplabcut.core.deprecation import DeprecationRound, renamed_parameter
602602

603603
pytorch_fn = MagicMock(return_value="pytorch")
604604

605605
@tf_routing.with_tensorflow_fallback
606-
@renamed_parameter(old="displayiters", new="display_iters", since="3.0.0")
606+
@renamed_parameter(
607+
old="displayiters", new="display_iters", deprecation_round=DeprecationRound.INIT_PARAMETER_ALIASING
608+
)
607609
def canonical_fn(config: str, display_iters: int | None = None):
608610
return pytorch_fn(config, display_iters=display_iters)
609611

0 commit comments

Comments
 (0)