diff --git a/test/dynamo/cpython/3_13/test_defaultdict.diff b/test/dynamo/cpython/3_13/test_defaultdict.diff new file mode 100644 index 000000000000..65a4cb892936 --- /dev/null +++ b/test/dynamo/cpython/3_13/test_defaultdict.diff @@ -0,0 +1,98 @@ +diff --git a/test/dynamo/cpython/3_13/test_defaultdict.py b/test/dynamo/cpython/3_13/test_defaultdict.py +index bdbe9b81e8f..d55f1dc54c6 100644 +--- a/test/dynamo/cpython/3_13/test_defaultdict.py ++++ b/test/dynamo/cpython/3_13/test_defaultdict.py +@@ -1,3 +1,60 @@ ++# ======= BEGIN Dynamo patch ======= ++# Owner(s): ["module: dynamo"] ++ ++# ruff: noqa ++# flake8: noqa ++ ++# Test copied from ++# https://raw.githubusercontent.com/python/cpython/refs/tags/v3.13.5/Lib/test/test_defaultdict.py ++ ++import sys ++import torch ++import torch._dynamo.test_case ++import unittest ++from torch._dynamo.test_case import CPythonTestCase ++from torch.testing._internal.common_utils import ( ++ run_tests, ++) ++ ++__TestCase = CPythonTestCase ++ ++ ++# redirect import statements ++import sys ++import importlib.abc ++ ++redirect_imports = ( ++ "test.mapping_tests", ++ "test.typinganndata", ++ "test.test_grammar", ++ "test.test_math", ++ "test.test_iter", ++ "test.typinganndata.ann_module", ++) ++ ++class RedirectImportFinder(importlib.abc.MetaPathFinder): ++ def find_spec(self, fullname, path, target=None): ++ # Check if the import is the problematic one ++ if fullname in redirect_imports: ++ try: ++ # Attempt to import the standalone module ++ name = fullname.removeprefix("test.") ++ r = importlib.import_module(name) ++ # Redirect the module in sys.modules ++ sys.modules[fullname] = r ++ # Return a module spec from the found module ++ return importlib.util.find_spec(name) ++ except ImportError: ++ return None ++ return None ++ ++# Add the custom finder to sys.meta_path ++sys.meta_path.insert(0, RedirectImportFinder()) ++ ++ ++# ======= END DYNAMO PATCH ======= ++ ++ + """Unit tests for collections.defaultdict.""" + + import copy +@@ -9,7 +66,7 @@ from collections import defaultdict + def foobar(): + return list + +-class TestDefaultDict(unittest.TestCase): ++class TestDefaultDict(__TestCase): + + def test_basic(self): + d1 = defaultdict() +@@ -127,11 +184,12 @@ class TestDefaultDict(unittest.TestCase): + + def test_recursive_repr(self): + # Issue2045: stack overflow when default_factory is a bound method +- class sub(defaultdict): +- def __init__(self): +- self.default_factory = self._factory +- def _factory(self): +- return [] ++ with torch._dynamo.set_fullgraph(fullgraph=False): ++ class sub(defaultdict): ++ def __init__(self): ++ self.default_factory = self._factory ++ def _factory(self): ++ return [] + d = sub() + self.assertRegex(repr(d), + r"sub\(, {12: 42})") + def foo(): return 43 + d3 = defaultdict(foo) + self.assertTrue(d3.default_factory is foo) + d3[13] + self.assertEqual(repr(d3), "defaultdict(%s, {13: 43})" % repr(foo)) + + def test_copy(self): + d1 = defaultdict() + d2 = d1.copy() + self.assertEqual(type(d2), defaultdict) + self.assertEqual(d2.default_factory, None) + self.assertEqual(d2, {}) + d1.default_factory = list + d3 = d1.copy() + self.assertEqual(type(d3), defaultdict) + self.assertEqual(d3.default_factory, list) + self.assertEqual(d3, {}) + d1[42] + d4 = d1.copy() + self.assertEqual(type(d4), defaultdict) + self.assertEqual(d4.default_factory, list) + self.assertEqual(d4, {42: []}) + d4[12] + self.assertEqual(d4, {42: [], 12: []}) + + # Issue 6637: Copy fails for empty default dict + d = defaultdict() + d['a'] = 42 + e = d.copy() + self.assertEqual(e['a'], 42) + + def test_shallow_copy(self): + d1 = defaultdict(foobar, {1: 1}) + d2 = copy.copy(d1) + self.assertEqual(d2.default_factory, foobar) + self.assertEqual(d2, d1) + d1.default_factory = list + d2 = copy.copy(d1) + self.assertEqual(d2.default_factory, list) + self.assertEqual(d2, d1) + + def test_deep_copy(self): + d1 = defaultdict(foobar, {1: [1]}) + d2 = copy.deepcopy(d1) + self.assertEqual(d2.default_factory, foobar) + self.assertEqual(d2, d1) + self.assertTrue(d1[1] is not d2[1]) + d1.default_factory = list + d2 = copy.deepcopy(d1) + self.assertEqual(d2.default_factory, list) + self.assertEqual(d2, d1) + + def test_keyerror_without_factory(self): + d1 = defaultdict() + try: + d1[(1,)] + except KeyError as err: + self.assertEqual(err.args[0], (1,)) + else: + self.fail("expected KeyError") + + def test_recursive_repr(self): + # Issue2045: stack overflow when default_factory is a bound method + with torch._dynamo.set_fullgraph(fullgraph=False): + class sub(defaultdict): + def __init__(self): + self.default_factory = self._factory + def _factory(self): + return [] + d = sub() + self.assertRegex(repr(d), + r"sub\(, \{\}\)") + + def test_callable_arg(self): + self.assertRaises(TypeError, defaultdict, {}) + + def test_pickling(self): + d = defaultdict(int) + d[1] + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + s = pickle.dumps(d, proto) + o = pickle.loads(s) + self.assertEqual(d, o) + + def test_union(self): + i = defaultdict(int, {1: 1, 2: 2}) + s = defaultdict(str, {0: "zero", 1: "one"}) + + i_s = i | s + self.assertIs(i_s.default_factory, int) + self.assertDictEqual(i_s, {1: "one", 2: 2, 0: "zero"}) + self.assertEqual(list(i_s), [1, 2, 0]) + + s_i = s | i + self.assertIs(s_i.default_factory, str) + self.assertDictEqual(s_i, {0: "zero", 1: 1, 2: 2}) + self.assertEqual(list(s_i), [0, 1, 2]) + + i_ds = i | dict(s) + self.assertIs(i_ds.default_factory, int) + self.assertDictEqual(i_ds, {1: "one", 2: 2, 0: "zero"}) + self.assertEqual(list(i_ds), [1, 2, 0]) + + ds_i = dict(s) | i + self.assertIs(ds_i.default_factory, int) + self.assertDictEqual(ds_i, {0: "zero", 1: 1, 2: 2}) + self.assertEqual(list(ds_i), [0, 1, 2]) + + with self.assertRaises(TypeError): + i | list(s.items()) + with self.assertRaises(TypeError): + list(s.items()) | i + + # We inherit a fine |= from dict, so just a few sanity checks here: + i |= list(s.items()) + self.assertIs(i.default_factory, int) + self.assertDictEqual(i, {1: "one", 2: 2, 0: "zero"}) + self.assertEqual(list(i), [1, 2, 0]) + + with self.assertRaises(TypeError): + i |= None + +if __name__ == "__main__": + run_tests() diff --git a/test/dynamo_expected_failures/CPython313-test_defaultdict-TestDefaultDict.test_basic b/test/dynamo_expected_failures/CPython313-test_defaultdict-TestDefaultDict.test_basic new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/dynamo_expected_failures/CPython313-test_defaultdict-TestDefaultDict.test_callable_arg b/test/dynamo_expected_failures/CPython313-test_defaultdict-TestDefaultDict.test_callable_arg new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/dynamo_expected_failures/CPython313-test_defaultdict-TestDefaultDict.test_copy b/test/dynamo_expected_failures/CPython313-test_defaultdict-TestDefaultDict.test_copy new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/dynamo_expected_failures/CPython313-test_defaultdict-TestDefaultDict.test_deep_copy b/test/dynamo_expected_failures/CPython313-test_defaultdict-TestDefaultDict.test_deep_copy new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/dynamo_expected_failures/CPython313-test_defaultdict-TestDefaultDict.test_keyerror_without_factory b/test/dynamo_expected_failures/CPython313-test_defaultdict-TestDefaultDict.test_keyerror_without_factory new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/dynamo_expected_failures/CPython313-test_defaultdict-TestDefaultDict.test_missing b/test/dynamo_expected_failures/CPython313-test_defaultdict-TestDefaultDict.test_missing new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/dynamo_expected_failures/CPython313-test_defaultdict-TestDefaultDict.test_pickling b/test/dynamo_expected_failures/CPython313-test_defaultdict-TestDefaultDict.test_pickling new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/dynamo_expected_failures/CPython313-test_defaultdict-TestDefaultDict.test_repr b/test/dynamo_expected_failures/CPython313-test_defaultdict-TestDefaultDict.test_repr new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/dynamo_expected_failures/CPython313-test_defaultdict-TestDefaultDict.test_shallow_copy b/test/dynamo_expected_failures/CPython313-test_defaultdict-TestDefaultDict.test_shallow_copy new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/dynamo_expected_failures/CPython313-test_defaultdict-TestDefaultDict.test_union b/test/dynamo_expected_failures/CPython313-test_defaultdict-TestDefaultDict.test_union new file mode 100644 index 000000000000..e69de29bb2d1