From b19c3c91b3a8139c289bdfc553115fb76d903d56 Mon Sep 17 00:00:00 2001 From: Nicolas Hug Date: Mon, 20 Feb 2023 11:10:29 +0000 Subject: [PATCH 1/6] Add warnings checks for v2 namespaces --- test/common_utils.py | 21 ++++++++++++++++++ test/test_transforms_v2.py | 45 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/test/common_utils.py b/test/common_utils.py index 670115c6ec0..e4213f12026 100644 --- a/test/common_utils.py +++ b/test/common_utils.py @@ -8,8 +8,10 @@ import pathlib import random import shutil +import sys import tempfile from collections import defaultdict +from subprocess import CalledProcessError, check_output, STDOUT from typing import Callable, Sequence, Tuple, Union import numpy as np @@ -838,3 +840,22 @@ def get_closeness_kwargs(self, test_id, *, dtype, device): if isinstance(device, torch.device): device = device.type return self.closeness_kwargs.get((test_id, dtype, device), dict()) + + +def assert_run_python_script(source_code): + """Utility to check assertions in an independent Python subprocess. + The script provided in the source code should return 0 and not print + anything on stderr or stdout. Taken from scikit-learn test utils. + source_code (str): The Python source code to execute. + """ + with tempfile.NamedTemporaryFile(mode="wb") as f: + f.write(source_code.encode()) + f.flush() + + cmd = [sys.executable, f.name] + try: + out = check_output(cmd, stderr=STDOUT) + except CalledProcessError as e: + raise RuntimeError("script errored with output:\n%s" % e.output.decode()) + if out != b"": + raise AssertionError(out.decode()) diff --git a/test/test_transforms_v2.py b/test/test_transforms_v2.py index 733939b53d9..87e8b80c326 100644 --- a/test/test_transforms_v2.py +++ b/test/test_transforms_v2.py @@ -2,6 +2,7 @@ import pathlib import random import re +import textwrap import warnings from collections import defaultdict @@ -14,6 +15,7 @@ from common_utils import ( assert_equal, + assert_run_python_script, cpu_and_gpu, make_bounding_box, make_bounding_boxes, @@ -2045,3 +2047,46 @@ def test_sanitize_bounding_boxes_errors(): ) different_sizes = {"bbox": bad_bbox, "labels": torch.arange(bad_bbox.shape[0])} transforms.SanitizeBoundingBoxes()(different_sizes) + + +@pytest.mark.parametrize( + "import_statement", + ( + "from torchvision.transforms import v2", + "import torchvision.transforms.v2", + "from torchvision.transforms.v2 import Resize", + "import torchvision.transforms.v2.functional", + "from torchvision.transforms.v2.functional import resize", + "from torchvision import datapoints", + "from torchvision.datapoints import Image", + ), +) +@pytest.mark.parametrize("call_disable_warning", (True, False)) +def test_warnings(import_statement, call_disable_warning): + if call_disable_warning: + prelude = """ + import warnings + import torchvision + torchvision.disable_beta_transforms_warning() + with warnings.catch_warnings(): + """ + else: + prelude = """ + import pytest + with pytest.warns(UserWarning, match="v2 namespaces are still Beta"): + """ + source = prelude + " " * 4 + import_statement + assert_run_python_script(textwrap.dedent(source)) + + # TODO: Also do these below + the depreacted functional_pil.py and functional_ tensor.py + dataset wrapper + # source = """ + # import warnings + # with warnings.catch_warnings(): + # warnings.simplefilter("error") + # import torchvision.transforms + # from torchvision import transforms + # import torchvision.transforms.functional + # from torchvision.transforms import Resize + # from torchvision.transforms.functional import resize + # """ + # assert_run_python_script(textwrap.dedent(source)) From 24d3ff730ad6aab93269b9940caeb15eaa95c811 Mon Sep 17 00:00:00 2001 From: Nicolas Hug Date: Mon, 20 Feb 2023 12:21:42 +0000 Subject: [PATCH 2/6] Some more --- test/conftest.py | 3 ++- test/test_transforms.py | 48 +++++++++++++++++++++++++++++++++++++- test/test_transforms_v2.py | 32 ++++++++++++++----------- 3 files changed, 68 insertions(+), 15 deletions(-) diff --git a/test/conftest.py b/test/conftest.py index b3ab70af650..a9e8f1cda52 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -4,11 +4,12 @@ import pytest import torch import torchvision -from common_utils import CUDA_NOT_AVAILABLE_MSG, IN_FBCODE, IN_OSS_CI, IN_RE_WORKER, OSS_CI_GPU_NO_CUDA_MSG torchvision.disable_beta_transforms_warning() +from common_utils import CUDA_NOT_AVAILABLE_MSG, IN_FBCODE, IN_OSS_CI, IN_RE_WORKER, OSS_CI_GPU_NO_CUDA_MSG + def pytest_configure(config): # register an additional marker (see pytest_collection_modifyitems) diff --git a/test/test_transforms.py b/test/test_transforms.py index cec69c0cbe9..b886f110db6 100644 --- a/test/test_transforms.py +++ b/test/test_transforms.py @@ -2,6 +2,7 @@ import os import random import re +import textwrap import warnings from functools import partial @@ -24,7 +25,7 @@ except ImportError: stats = None -from common_utils import assert_equal, cycle_over, float_dtypes, int_dtypes +from common_utils import assert_equal, assert_run_python_script, cycle_over, float_dtypes, int_dtypes GRACE_HOPPER = get_file_path_2( @@ -2266,5 +2267,50 @@ def test_random_grayscale_with_grayscale_input(): torch.testing.assert_close(F.pil_to_tensor(output_pil), image_tensor) +def test_no_warnings_v1_namespace(): + source = """ + import warnings + with warnings.catch_warnings(): + warnings.simplefilter("error") + import torchvision.transforms + from torchvision import transforms + import torchvision.transforms.functional + from torchvision.transforms import Resize + from torchvision.transforms.functional import resize + """ + assert_run_python_script(textwrap.dedent(source)) + + +# TODO: remove in 0.17 when we can delete functional_pil.py and functional_tensor.py +@pytest.mark.parametrize( + "import_statement", + ( + "from torchvision.transforms import functional_pil", + "from torchvision.transforms import functional_tensor", + "from torchvision.transforms.functional_tensor import resize", + "from torchvision.transforms.functional_pil import resize", + ), +) +@pytest.mark.parametrize("from_private", (True, False)) +def test_functional_deprecation_warning(import_statement, from_private): + if from_private: + import_statement = import_statement.replace("functional", "_functional") + prelude = """ + import warnings + import torchvision + + with warnings.catch_warnings(): + warnings.simplefilter("error") + """ + else: + prelude = """ + import pytest + with pytest.warns(UserWarning, match="removed in 0.17"): + """ + + source = prelude + " " * 4 + import_statement + assert_run_python_script(textwrap.dedent(source)) + + if __name__ == "__main__": pytest.main([__file__]) diff --git a/test/test_transforms_v2.py b/test/test_transforms_v2.py index 87e8b80c326..01bedd7a3fb 100644 --- a/test/test_transforms_v2.py +++ b/test/test_transforms_v2.py @@ -2059,16 +2059,19 @@ def test_sanitize_bounding_boxes_errors(): "from torchvision.transforms.v2.functional import resize", "from torchvision import datapoints", "from torchvision.datapoints import Image", + "from torchvision.datasets import wrap_dataset_for_transforms_v2", ), ) @pytest.mark.parametrize("call_disable_warning", (True, False)) -def test_warnings(import_statement, call_disable_warning): +def test_warnings_v2_namespaces(import_statement, call_disable_warning): if call_disable_warning: prelude = """ import warnings import torchvision torchvision.disable_beta_transforms_warning() with warnings.catch_warnings(): + warnings.simplefilter("error") + """ else: prelude = """ @@ -2078,15 +2081,18 @@ def test_warnings(import_statement, call_disable_warning): source = prelude + " " * 4 + import_statement assert_run_python_script(textwrap.dedent(source)) - # TODO: Also do these below + the depreacted functional_pil.py and functional_ tensor.py + dataset wrapper - # source = """ - # import warnings - # with warnings.catch_warnings(): - # warnings.simplefilter("error") - # import torchvision.transforms - # from torchvision import transforms - # import torchvision.transforms.functional - # from torchvision.transforms import Resize - # from torchvision.transforms.functional import resize - # """ - # assert_run_python_script(textwrap.dedent(source)) + +def test_no_warnings_v1_namespace(): + source = """ + import warnings + with warnings.catch_warnings(): + warnings.simplefilter("error") + import torchvision.transforms + from torchvision import transforms + import torchvision.transforms.functional + from torchvision.transforms import Resize + from torchvision.transforms.functional import resize + from torchvision import datasets + from torchvision.datasets import ImageNet + """ + assert_run_python_script(textwrap.dedent(source)) From 584f6370e7425ef431e298b975b67929de8819ad Mon Sep 17 00:00:00 2001 From: Nicolas Hug Date: Mon, 20 Feb 2023 12:28:08 +0000 Subject: [PATCH 3/6] nit --- test/test_transforms.py | 1 - 1 file changed, 1 deletion(-) diff --git a/test/test_transforms.py b/test/test_transforms.py index b886f110db6..2efd1ae0dd2 100644 --- a/test/test_transforms.py +++ b/test/test_transforms.py @@ -2297,7 +2297,6 @@ def test_functional_deprecation_warning(import_statement, from_private): import_statement = import_statement.replace("functional", "_functional") prelude = """ import warnings - import torchvision with warnings.catch_warnings(): warnings.simplefilter("error") From 4972fb39e55164706b13fd6439dc6a60c1bfab3b Mon Sep 17 00:00:00 2001 From: Nicolas Hug Date: Mon, 20 Feb 2023 13:26:23 +0000 Subject: [PATCH 4/6] Update test/common_utils.py Co-authored-by: Philip Meier --- test/common_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/common_utils.py b/test/common_utils.py index e4213f12026..2f74f3686c3 100644 --- a/test/common_utils.py +++ b/test/common_utils.py @@ -856,6 +856,6 @@ def assert_run_python_script(source_code): try: out = check_output(cmd, stderr=STDOUT) except CalledProcessError as e: - raise RuntimeError("script errored with output:\n%s" % e.output.decode()) + raise RuntimeError(f"script errored with output:\n{e.output.decode()}") if out != b"": raise AssertionError(out.decode()) From 020e823ec22a11aeb062e358880a6d4628c220c4 Mon Sep 17 00:00:00 2001 From: Nicolas Hug Date: Mon, 20 Feb 2023 13:27:31 +0000 Subject: [PATCH 5/6] remove duplicated --- test/test_transforms.py | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/test/test_transforms.py b/test/test_transforms.py index 2efd1ae0dd2..aadd8ea1031 100644 --- a/test/test_transforms.py +++ b/test/test_transforms.py @@ -2267,20 +2267,6 @@ def test_random_grayscale_with_grayscale_input(): torch.testing.assert_close(F.pil_to_tensor(output_pil), image_tensor) -def test_no_warnings_v1_namespace(): - source = """ - import warnings - with warnings.catch_warnings(): - warnings.simplefilter("error") - import torchvision.transforms - from torchvision import transforms - import torchvision.transforms.functional - from torchvision.transforms import Resize - from torchvision.transforms.functional import resize - """ - assert_run_python_script(textwrap.dedent(source)) - - # TODO: remove in 0.17 when we can delete functional_pil.py and functional_tensor.py @pytest.mark.parametrize( "import_statement", From 7840082a248d40b3f4c4abf5820d921dce315832 Mon Sep 17 00:00:00 2001 From: Nicolas Hug Date: Mon, 20 Feb 2023 13:45:37 +0000 Subject: [PATCH 6/6] Use f-string to simplify source str construction --- test/test_transforms.py | 8 ++++---- test/test_transforms_v2.py | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/test/test_transforms.py b/test/test_transforms.py index aadd8ea1031..03b385e9edd 100644 --- a/test/test_transforms.py +++ b/test/test_transforms.py @@ -2281,19 +2281,19 @@ def test_random_grayscale_with_grayscale_input(): def test_functional_deprecation_warning(import_statement, from_private): if from_private: import_statement = import_statement.replace("functional", "_functional") - prelude = """ + source = f""" import warnings with warnings.catch_warnings(): warnings.simplefilter("error") + {import_statement} """ else: - prelude = """ + source = f""" import pytest with pytest.warns(UserWarning, match="removed in 0.17"): + {import_statement} """ - - source = prelude + " " * 4 + import_statement assert_run_python_script(textwrap.dedent(source)) diff --git a/test/test_transforms_v2.py b/test/test_transforms_v2.py index 01bedd7a3fb..2e43c86f91d 100644 --- a/test/test_transforms_v2.py +++ b/test/test_transforms_v2.py @@ -2065,20 +2065,20 @@ def test_sanitize_bounding_boxes_errors(): @pytest.mark.parametrize("call_disable_warning", (True, False)) def test_warnings_v2_namespaces(import_statement, call_disable_warning): if call_disable_warning: - prelude = """ + source = f""" import warnings import torchvision torchvision.disable_beta_transforms_warning() with warnings.catch_warnings(): warnings.simplefilter("error") - + {import_statement} """ else: - prelude = """ + source = f""" import pytest with pytest.warns(UserWarning, match="v2 namespaces are still Beta"): + {import_statement} """ - source = prelude + " " * 4 + import_statement assert_run_python_script(textwrap.dedent(source))