From 086782e5fe0f98a0538d5f7762a9b9b42fb81bc8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 7 May 2026 07:04:23 +0000 Subject: [PATCH 1/4] Initial plan From 454d662b6728557fc11642ae47e3733f80485671 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 7 May 2026 07:10:35 +0000 Subject: [PATCH 2/4] fix: suppress export tracer warnings in export_pytorch Agent-Logs-Url: https://github.com/microsoft/WinML-ModelKit/sessions/208a704a-029f-4bb4-a2d2-c8d4a76a413a Co-authored-by: chinazhangchao <3822520+chinazhangchao@users.noreply.github.com> --- src/winml/modelkit/_warnings.py | 5 +- src/winml/modelkit/commands/build.py | 24 ++++----- src/winml/modelkit/export/pytorch.py | 19 ++++--- .../unit/test_pytorch_warning_suppression.py | 50 +++++++++++++++++++ 4 files changed, 72 insertions(+), 26 deletions(-) create mode 100644 tests/unit/test_pytorch_warning_suppression.py diff --git a/src/winml/modelkit/_warnings.py b/src/winml/modelkit/_warnings.py index 026594849..37381245e 100644 --- a/src/winml/modelkit/_warnings.py +++ b/src/winml/modelkit/_warnings.py @@ -81,10 +81,9 @@ def filter(self, record: logging.LogRecord) -> bool: # NOTE: TracerWarning (from torch.jit) is intentionally NOT filtered here. # Importing torch.jit at startup would pull all of torch (~1.7s) into # `winml --help` and violate the CLI import budget (tests/cli/test_import_time.py). - # During ONNX export, build.py already wraps the export call in + # During ONNX export, export_pytorch() wraps torch.onnx.export in # `warnings.catch_warnings()` + `filterwarnings("ignore")`, which is strictly - # broader than a TracerWarning-only filter. Direct callers of export_pytorch() - # that want the same suppression can apply it locally at the call site. + # broader than a TracerWarning-only filter. # Diffusers warnings.filterwarnings( diff --git a/src/winml/modelkit/commands/build.py b/src/winml/modelkit/commands/build.py index 3c1f14c23..f95f0dba6 100644 --- a/src/winml/modelkit/commands/build.py +++ b/src/winml/modelkit/commands/build.py @@ -1049,27 +1049,21 @@ def _name(base: str) -> str: current_path = export_path # ── Export stage ────────────────────────────────────────────── - import warnings - with StageLive("export", console) as sl: sl.set_status("Exporting to ONNX...") # Load + export (blocking) - # Suppress TracerWarning and other transformer warnings - # during export to keep Live display clean. pytorch_model = _load_model(config, model_id, trust_remote_code=False) t0 = time.monotonic() - with warnings.catch_warnings(): - warnings.filterwarnings("ignore") - export_onnx( - model=pytorch_model, - output_path=export_path, - export_config=config.export, - model_id=model_label, - task=config.loader.task, - verbose=False, - use_external_data=True, - ) + export_onnx( + model=pytorch_model, + output_path=export_path, + export_config=config.export, + model_id=model_label, + task=config.loader.task, + verbose=False, + use_external_data=True, + ) _export_elapsed = time.monotonic() - t0 sl.set_done(_export_elapsed) # Meta shown after export completes (avoids duplicate in Live frame) diff --git a/src/winml/modelkit/export/pytorch.py b/src/winml/modelkit/export/pytorch.py index 2476634a7..3d157ddba 100644 --- a/src/winml/modelkit/export/pytorch.py +++ b/src/winml/modelkit/export/pytorch.py @@ -24,6 +24,7 @@ from __future__ import annotations import logging +import warnings from pathlib import Path from typing import TYPE_CHECKING, Any @@ -83,11 +84,13 @@ def export_pytorch( enable_reporting=enable_reporting, embed_hierarchy_attributes=export_config.enable_hierarchy_tags, ) - return exporter.export( - model=model, - output_path=str(output_path), - export_config=export_config, - model_name_or_path=model_name_or_path, - task=task, - **kwargs, - ) + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + return exporter.export( + model=model, + output_path=str(output_path), + export_config=export_config, + model_name_or_path=model_name_or_path, + task=task, + **kwargs, + ) diff --git a/tests/unit/test_pytorch_warning_suppression.py b/tests/unit/test_pytorch_warning_suppression.py new file mode 100644 index 000000000..0e3ddd313 --- /dev/null +++ b/tests/unit/test_pytorch_warning_suppression.py @@ -0,0 +1,50 @@ +# ------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. +# -------------------------------------------------------------------------- +"""Tests warning suppression behavior in export_pytorch().""" + +from __future__ import annotations + +import sys +import types +from types import SimpleNamespace +from unittest.mock import MagicMock, patch + +from winml.modelkit.export.pytorch import export_pytorch + + +def test_export_pytorch_suppresses_warnings(tmp_path, monkeypatch) -> None: + """export_pytorch should suppress warnings around exporter invocation.""" + + class DummyModel: + pass + + model = DummyModel() + config = SimpleNamespace(enable_hierarchy_tags=True) + expected = {"onnx_nodes": 1} + exporter_cls = MagicMock() + exporter = exporter_cls.return_value + exporter.export.return_value = expected + + fake_htp_pkg = types.ModuleType("winml.modelkit.export.htp") + fake_htp_pkg.__path__ = [] # mark as package + fake_exporter_module = types.ModuleType("winml.modelkit.export.htp.exporter") + fake_exporter_module.HTPExporter = exporter_cls + + monkeypatch.setitem(sys.modules, "winml.modelkit.export.htp", fake_htp_pkg) + monkeypatch.setitem( + sys.modules, + "winml.modelkit.export.htp.exporter", + fake_exporter_module, + ) + + with ( + patch("winml.modelkit.export.pytorch.warnings.catch_warnings") as mock_catch_warnings, + patch("winml.modelkit.export.pytorch.warnings.filterwarnings") as mock_filterwarnings, + ): + result = export_pytorch(model, tmp_path / "model.onnx", config) + + assert result == expected + mock_catch_warnings.assert_called_once_with() + mock_filterwarnings.assert_called_once_with("ignore") From 4423ed40a947c2205cd9203b95f2178f20613f8c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 7 May 2026 07:13:47 +0000 Subject: [PATCH 3/4] test: cover export_pytorch warning suppression behavior Agent-Logs-Url: https://github.com/microsoft/WinML-ModelKit/sessions/208a704a-029f-4bb4-a2d2-c8d4a76a413a Co-authored-by: chinazhangchao <3822520+chinazhangchao@users.noreply.github.com> --- .../unit/test_pytorch_warning_suppression.py | 62 ++++++++++++++----- 1 file changed, 47 insertions(+), 15 deletions(-) diff --git a/tests/unit/test_pytorch_warning_suppression.py b/tests/unit/test_pytorch_warning_suppression.py index 0e3ddd313..a35603f8f 100644 --- a/tests/unit/test_pytorch_warning_suppression.py +++ b/tests/unit/test_pytorch_warning_suppression.py @@ -8,24 +8,28 @@ import sys import types +import warnings from types import SimpleNamespace from unittest.mock import MagicMock, patch from winml.modelkit.export.pytorch import export_pytorch -def test_export_pytorch_suppresses_warnings(tmp_path, monkeypatch) -> None: - """export_pytorch should suppress warnings around exporter invocation.""" - - class DummyModel: - pass - - model = DummyModel() - config = SimpleNamespace(enable_hierarchy_tags=True) - expected = {"onnx_nodes": 1} +def _install_fake_exporter( + monkeypatch, + export_return: dict[str, int], + *, + emit_warning: bool, +) -> None: exporter_cls = MagicMock() exporter = exporter_cls.return_value - exporter.export.return_value = expected + + def _export(*args, **kwargs): + if emit_warning: + warnings.warn("tracer warning noise", UserWarning, stacklevel=2) + return export_return + + exporter.export.side_effect = _export fake_htp_pkg = types.ModuleType("winml.modelkit.export.htp") fake_htp_pkg.__path__ = [] # mark as package @@ -33,11 +37,19 @@ class DummyModel: fake_exporter_module.HTPExporter = exporter_cls monkeypatch.setitem(sys.modules, "winml.modelkit.export.htp", fake_htp_pkg) - monkeypatch.setitem( - sys.modules, - "winml.modelkit.export.htp.exporter", - fake_exporter_module, - ) + monkeypatch.setitem(sys.modules, "winml.modelkit.export.htp.exporter", fake_exporter_module) + + +def test_export_pytorch_uses_warning_context(tmp_path, monkeypatch) -> None: + """export_pytorch should use warnings.catch_warnings() context manager.""" + + class DummyModel: + pass + + model = DummyModel() + config = SimpleNamespace(enable_hierarchy_tags=True) + expected = {"onnx_nodes": 1} + _install_fake_exporter(monkeypatch, expected, emit_warning=False) with ( patch("winml.modelkit.export.pytorch.warnings.catch_warnings") as mock_catch_warnings, @@ -47,4 +59,24 @@ class DummyModel: assert result == expected mock_catch_warnings.assert_called_once_with() + mock_catch_warnings.return_value.__enter__.assert_called_once_with() mock_filterwarnings.assert_called_once_with("ignore") + + +def test_export_pytorch_suppresses_export_warnings(tmp_path, monkeypatch) -> None: + """Warnings emitted during export should not leak to callers.""" + + class DummyModel: + pass + + model = DummyModel() + config = SimpleNamespace(enable_hierarchy_tags=True) + expected = {"onnx_nodes": 1} + _install_fake_exporter(monkeypatch, expected, emit_warning=True) + + with warnings.catch_warnings(record=True) as captured: + warnings.simplefilter("always") + result = export_pytorch(model, tmp_path / "model.onnx", config) + + assert result == expected + assert captured == [] From 11ee0cf23dc59b64e25cd7fa9a25b3741b87e498 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 7 May 2026 07:16:15 +0000 Subject: [PATCH 4/4] test: strengthen warning suppression assertions Agent-Logs-Url: https://github.com/microsoft/WinML-ModelKit/sessions/208a704a-029f-4bb4-a2d2-c8d4a76a413a Co-authored-by: chinazhangchao <3822520+chinazhangchao@users.noreply.github.com> --- tests/unit/test_pytorch_warning_suppression.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/unit/test_pytorch_warning_suppression.py b/tests/unit/test_pytorch_warning_suppression.py index a35603f8f..19eef48d2 100644 --- a/tests/unit/test_pytorch_warning_suppression.py +++ b/tests/unit/test_pytorch_warning_suppression.py @@ -20,7 +20,7 @@ def _install_fake_exporter( export_return: dict[str, int], *, emit_warning: bool, -) -> None: +) -> MagicMock: exporter_cls = MagicMock() exporter = exporter_cls.return_value @@ -38,6 +38,7 @@ def _export(*args, **kwargs): monkeypatch.setitem(sys.modules, "winml.modelkit.export.htp", fake_htp_pkg) monkeypatch.setitem(sys.modules, "winml.modelkit.export.htp.exporter", fake_exporter_module) + return exporter def test_export_pytorch_uses_warning_context(tmp_path, monkeypatch) -> None: @@ -49,7 +50,7 @@ class DummyModel: model = DummyModel() config = SimpleNamespace(enable_hierarchy_tags=True) expected = {"onnx_nodes": 1} - _install_fake_exporter(monkeypatch, expected, emit_warning=False) + exporter = _install_fake_exporter(monkeypatch, expected, emit_warning=False) with ( patch("winml.modelkit.export.pytorch.warnings.catch_warnings") as mock_catch_warnings, @@ -58,6 +59,7 @@ class DummyModel: result = export_pytorch(model, tmp_path / "model.onnx", config) assert result == expected + exporter.export.assert_called_once() mock_catch_warnings.assert_called_once_with() mock_catch_warnings.return_value.__enter__.assert_called_once_with() mock_filterwarnings.assert_called_once_with("ignore") @@ -72,11 +74,12 @@ class DummyModel: model = DummyModel() config = SimpleNamespace(enable_hierarchy_tags=True) expected = {"onnx_nodes": 1} - _install_fake_exporter(monkeypatch, expected, emit_warning=True) + exporter = _install_fake_exporter(monkeypatch, expected, emit_warning=True) with warnings.catch_warnings(record=True) as captured: warnings.simplefilter("always") result = export_pytorch(model, tmp_path / "model.onnx", config) assert result == expected + exporter.export.assert_called_once() assert captured == []