|
2 | 2 | # these are all functions _testcapi exports whose name begins with 'test_'. |
3 | 3 |
|
4 | 4 | from collections import OrderedDict |
5 | | -from contextlib import contextmanager, ExitStack |
6 | 5 | import _thread |
7 | 6 | import importlib.machinery |
8 | 7 | import importlib.util |
|
20 | 19 | import weakref |
21 | 20 | from test import support |
22 | 21 | from test.support import MISSING_C_DOCSTRINGS |
23 | | -from test.support import catch_unraisable_exception |
24 | 22 | from test.support import import_helper |
25 | 23 | from test.support import threading_helper |
26 | 24 | from test.support import warnings_helper |
@@ -1705,333 +1703,5 @@ def func2(x=None): |
1705 | 1703 | self.do_test(func2) |
1706 | 1704 |
|
1707 | 1705 |
|
1708 | | -class TestDictWatchers(unittest.TestCase): |
1709 | | - # types of watchers testcapimodule can add: |
1710 | | - EVENTS = 0 # appends dict events as strings to global event list |
1711 | | - ERROR = 1 # unconditionally sets and signals a RuntimeException |
1712 | | - SECOND = 2 # always appends "second" to global event list |
1713 | | - |
1714 | | - def add_watcher(self, kind=EVENTS): |
1715 | | - return _testcapi.add_dict_watcher(kind) |
1716 | | - |
1717 | | - def clear_watcher(self, watcher_id): |
1718 | | - _testcapi.clear_dict_watcher(watcher_id) |
1719 | | - |
1720 | | - @contextmanager |
1721 | | - def watcher(self, kind=EVENTS): |
1722 | | - wid = self.add_watcher(kind) |
1723 | | - try: |
1724 | | - yield wid |
1725 | | - finally: |
1726 | | - self.clear_watcher(wid) |
1727 | | - |
1728 | | - def assert_events(self, expected): |
1729 | | - actual = _testcapi.get_dict_watcher_events() |
1730 | | - self.assertEqual(actual, expected) |
1731 | | - |
1732 | | - def watch(self, wid, d): |
1733 | | - _testcapi.watch_dict(wid, d) |
1734 | | - |
1735 | | - def unwatch(self, wid, d): |
1736 | | - _testcapi.unwatch_dict(wid, d) |
1737 | | - |
1738 | | - def test_set_new_item(self): |
1739 | | - d = {} |
1740 | | - with self.watcher() as wid: |
1741 | | - self.watch(wid, d) |
1742 | | - d["foo"] = "bar" |
1743 | | - self.assert_events(["new:foo:bar"]) |
1744 | | - |
1745 | | - def test_set_existing_item(self): |
1746 | | - d = {"foo": "bar"} |
1747 | | - with self.watcher() as wid: |
1748 | | - self.watch(wid, d) |
1749 | | - d["foo"] = "baz" |
1750 | | - self.assert_events(["mod:foo:baz"]) |
1751 | | - |
1752 | | - def test_clone(self): |
1753 | | - d = {} |
1754 | | - d2 = {"foo": "bar"} |
1755 | | - with self.watcher() as wid: |
1756 | | - self.watch(wid, d) |
1757 | | - d.update(d2) |
1758 | | - self.assert_events(["clone"]) |
1759 | | - |
1760 | | - def test_no_event_if_not_watched(self): |
1761 | | - d = {} |
1762 | | - with self.watcher() as wid: |
1763 | | - d["foo"] = "bar" |
1764 | | - self.assert_events([]) |
1765 | | - |
1766 | | - def test_del(self): |
1767 | | - d = {"foo": "bar"} |
1768 | | - with self.watcher() as wid: |
1769 | | - self.watch(wid, d) |
1770 | | - del d["foo"] |
1771 | | - self.assert_events(["del:foo"]) |
1772 | | - |
1773 | | - def test_pop(self): |
1774 | | - d = {"foo": "bar"} |
1775 | | - with self.watcher() as wid: |
1776 | | - self.watch(wid, d) |
1777 | | - d.pop("foo") |
1778 | | - self.assert_events(["del:foo"]) |
1779 | | - |
1780 | | - def test_clear(self): |
1781 | | - d = {"foo": "bar"} |
1782 | | - with self.watcher() as wid: |
1783 | | - self.watch(wid, d) |
1784 | | - d.clear() |
1785 | | - self.assert_events(["clear"]) |
1786 | | - |
1787 | | - def test_dealloc(self): |
1788 | | - d = {"foo": "bar"} |
1789 | | - with self.watcher() as wid: |
1790 | | - self.watch(wid, d) |
1791 | | - del d |
1792 | | - self.assert_events(["dealloc"]) |
1793 | | - |
1794 | | - def test_unwatch(self): |
1795 | | - d = {} |
1796 | | - with self.watcher() as wid: |
1797 | | - self.watch(wid, d) |
1798 | | - d["foo"] = "bar" |
1799 | | - self.unwatch(wid, d) |
1800 | | - d["hmm"] = "baz" |
1801 | | - self.assert_events(["new:foo:bar"]) |
1802 | | - |
1803 | | - def test_error(self): |
1804 | | - d = {} |
1805 | | - with self.watcher(kind=self.ERROR) as wid: |
1806 | | - self.watch(wid, d) |
1807 | | - with catch_unraisable_exception() as cm: |
1808 | | - d["foo"] = "bar" |
1809 | | - self.assertIs(cm.unraisable.object, d) |
1810 | | - self.assertEqual(str(cm.unraisable.exc_value), "boom!") |
1811 | | - self.assert_events([]) |
1812 | | - |
1813 | | - def test_two_watchers(self): |
1814 | | - d1 = {} |
1815 | | - d2 = {} |
1816 | | - with self.watcher() as wid1: |
1817 | | - with self.watcher(kind=self.SECOND) as wid2: |
1818 | | - self.watch(wid1, d1) |
1819 | | - self.watch(wid2, d2) |
1820 | | - d1["foo"] = "bar" |
1821 | | - d2["hmm"] = "baz" |
1822 | | - self.assert_events(["new:foo:bar", "second"]) |
1823 | | - |
1824 | | - def test_watch_non_dict(self): |
1825 | | - with self.watcher() as wid: |
1826 | | - with self.assertRaisesRegex(ValueError, r"Cannot watch non-dictionary"): |
1827 | | - self.watch(wid, 1) |
1828 | | - |
1829 | | - def test_watch_out_of_range_watcher_id(self): |
1830 | | - d = {} |
1831 | | - with self.assertRaisesRegex(ValueError, r"Invalid dict watcher ID -1"): |
1832 | | - self.watch(-1, d) |
1833 | | - with self.assertRaisesRegex(ValueError, r"Invalid dict watcher ID 8"): |
1834 | | - self.watch(8, d) # DICT_MAX_WATCHERS = 8 |
1835 | | - |
1836 | | - def test_watch_unassigned_watcher_id(self): |
1837 | | - d = {} |
1838 | | - with self.assertRaisesRegex(ValueError, r"No dict watcher set for ID 1"): |
1839 | | - self.watch(1, d) |
1840 | | - |
1841 | | - def test_unwatch_non_dict(self): |
1842 | | - with self.watcher() as wid: |
1843 | | - with self.assertRaisesRegex(ValueError, r"Cannot watch non-dictionary"): |
1844 | | - self.unwatch(wid, 1) |
1845 | | - |
1846 | | - def test_unwatch_out_of_range_watcher_id(self): |
1847 | | - d = {} |
1848 | | - with self.assertRaisesRegex(ValueError, r"Invalid dict watcher ID -1"): |
1849 | | - self.unwatch(-1, d) |
1850 | | - with self.assertRaisesRegex(ValueError, r"Invalid dict watcher ID 8"): |
1851 | | - self.unwatch(8, d) # DICT_MAX_WATCHERS = 8 |
1852 | | - |
1853 | | - def test_unwatch_unassigned_watcher_id(self): |
1854 | | - d = {} |
1855 | | - with self.assertRaisesRegex(ValueError, r"No dict watcher set for ID 1"): |
1856 | | - self.unwatch(1, d) |
1857 | | - |
1858 | | - def test_clear_out_of_range_watcher_id(self): |
1859 | | - with self.assertRaisesRegex(ValueError, r"Invalid dict watcher ID -1"): |
1860 | | - self.clear_watcher(-1) |
1861 | | - with self.assertRaisesRegex(ValueError, r"Invalid dict watcher ID 8"): |
1862 | | - self.clear_watcher(8) # DICT_MAX_WATCHERS = 8 |
1863 | | - |
1864 | | - def test_clear_unassigned_watcher_id(self): |
1865 | | - with self.assertRaisesRegex(ValueError, r"No dict watcher set for ID 1"): |
1866 | | - self.clear_watcher(1) |
1867 | | - |
1868 | | - |
1869 | | -class TestTypeWatchers(unittest.TestCase): |
1870 | | - # types of watchers testcapimodule can add: |
1871 | | - TYPES = 0 # appends modified types to global event list |
1872 | | - ERROR = 1 # unconditionally sets and signals a RuntimeException |
1873 | | - WRAP = 2 # appends modified type wrapped in list to global event list |
1874 | | - |
1875 | | - # duplicating the C constant |
1876 | | - TYPE_MAX_WATCHERS = 8 |
1877 | | - |
1878 | | - def add_watcher(self, kind=TYPES): |
1879 | | - return _testcapi.add_type_watcher(kind) |
1880 | | - |
1881 | | - def clear_watcher(self, watcher_id): |
1882 | | - _testcapi.clear_type_watcher(watcher_id) |
1883 | | - |
1884 | | - @contextmanager |
1885 | | - def watcher(self, kind=TYPES): |
1886 | | - wid = self.add_watcher(kind) |
1887 | | - try: |
1888 | | - yield wid |
1889 | | - finally: |
1890 | | - self.clear_watcher(wid) |
1891 | | - |
1892 | | - def assert_events(self, expected): |
1893 | | - actual = _testcapi.get_type_modified_events() |
1894 | | - self.assertEqual(actual, expected) |
1895 | | - |
1896 | | - def watch(self, wid, t): |
1897 | | - _testcapi.watch_type(wid, t) |
1898 | | - |
1899 | | - def unwatch(self, wid, t): |
1900 | | - _testcapi.unwatch_type(wid, t) |
1901 | | - |
1902 | | - def test_watch_type(self): |
1903 | | - class C: pass |
1904 | | - with self.watcher() as wid: |
1905 | | - self.watch(wid, C) |
1906 | | - C.foo = "bar" |
1907 | | - self.assert_events([C]) |
1908 | | - |
1909 | | - def test_event_aggregation(self): |
1910 | | - class C: pass |
1911 | | - with self.watcher() as wid: |
1912 | | - self.watch(wid, C) |
1913 | | - C.foo = "bar" |
1914 | | - C.bar = "baz" |
1915 | | - # only one event registered for both modifications |
1916 | | - self.assert_events([C]) |
1917 | | - |
1918 | | - def test_lookup_resets_aggregation(self): |
1919 | | - class C: pass |
1920 | | - with self.watcher() as wid: |
1921 | | - self.watch(wid, C) |
1922 | | - C.foo = "bar" |
1923 | | - # lookup resets type version tag |
1924 | | - self.assertEqual(C.foo, "bar") |
1925 | | - C.bar = "baz" |
1926 | | - # both events registered |
1927 | | - self.assert_events([C, C]) |
1928 | | - |
1929 | | - def test_unwatch_type(self): |
1930 | | - class C: pass |
1931 | | - with self.watcher() as wid: |
1932 | | - self.watch(wid, C) |
1933 | | - C.foo = "bar" |
1934 | | - self.assertEqual(C.foo, "bar") |
1935 | | - self.assert_events([C]) |
1936 | | - self.unwatch(wid, C) |
1937 | | - C.bar = "baz" |
1938 | | - self.assert_events([C]) |
1939 | | - |
1940 | | - def test_clear_watcher(self): |
1941 | | - class C: pass |
1942 | | - # outer watcher is unused, it's just to keep events list alive |
1943 | | - with self.watcher() as _: |
1944 | | - with self.watcher() as wid: |
1945 | | - self.watch(wid, C) |
1946 | | - C.foo = "bar" |
1947 | | - self.assertEqual(C.foo, "bar") |
1948 | | - self.assert_events([C]) |
1949 | | - C.bar = "baz" |
1950 | | - # Watcher on C has been cleared, no new event |
1951 | | - self.assert_events([C]) |
1952 | | - |
1953 | | - def test_watch_type_subclass(self): |
1954 | | - class C: pass |
1955 | | - class D(C): pass |
1956 | | - with self.watcher() as wid: |
1957 | | - self.watch(wid, D) |
1958 | | - C.foo = "bar" |
1959 | | - self.assert_events([D]) |
1960 | | - |
1961 | | - def test_error(self): |
1962 | | - class C: pass |
1963 | | - with self.watcher(kind=self.ERROR) as wid: |
1964 | | - self.watch(wid, C) |
1965 | | - with catch_unraisable_exception() as cm: |
1966 | | - C.foo = "bar" |
1967 | | - self.assertIs(cm.unraisable.object, C) |
1968 | | - self.assertEqual(str(cm.unraisable.exc_value), "boom!") |
1969 | | - self.assert_events([]) |
1970 | | - |
1971 | | - def test_two_watchers(self): |
1972 | | - class C1: pass |
1973 | | - class C2: pass |
1974 | | - with self.watcher() as wid1: |
1975 | | - with self.watcher(kind=self.WRAP) as wid2: |
1976 | | - self.assertNotEqual(wid1, wid2) |
1977 | | - self.watch(wid1, C1) |
1978 | | - self.watch(wid2, C2) |
1979 | | - C1.foo = "bar" |
1980 | | - C2.hmm = "baz" |
1981 | | - self.assert_events([C1, [C2]]) |
1982 | | - |
1983 | | - def test_watch_non_type(self): |
1984 | | - with self.watcher() as wid: |
1985 | | - with self.assertRaisesRegex(ValueError, r"Cannot watch non-type"): |
1986 | | - self.watch(wid, 1) |
1987 | | - |
1988 | | - def test_watch_out_of_range_watcher_id(self): |
1989 | | - class C: pass |
1990 | | - with self.assertRaisesRegex(ValueError, r"Invalid type watcher ID -1"): |
1991 | | - self.watch(-1, C) |
1992 | | - with self.assertRaisesRegex(ValueError, r"Invalid type watcher ID 8"): |
1993 | | - self.watch(self.TYPE_MAX_WATCHERS, C) |
1994 | | - |
1995 | | - def test_watch_unassigned_watcher_id(self): |
1996 | | - class C: pass |
1997 | | - with self.assertRaisesRegex(ValueError, r"No type watcher set for ID 1"): |
1998 | | - self.watch(1, C) |
1999 | | - |
2000 | | - def test_unwatch_non_type(self): |
2001 | | - with self.watcher() as wid: |
2002 | | - with self.assertRaisesRegex(ValueError, r"Cannot watch non-type"): |
2003 | | - self.unwatch(wid, 1) |
2004 | | - |
2005 | | - def test_unwatch_out_of_range_watcher_id(self): |
2006 | | - class C: pass |
2007 | | - with self.assertRaisesRegex(ValueError, r"Invalid type watcher ID -1"): |
2008 | | - self.unwatch(-1, C) |
2009 | | - with self.assertRaisesRegex(ValueError, r"Invalid type watcher ID 8"): |
2010 | | - self.unwatch(self.TYPE_MAX_WATCHERS, C) |
2011 | | - |
2012 | | - def test_unwatch_unassigned_watcher_id(self): |
2013 | | - class C: pass |
2014 | | - with self.assertRaisesRegex(ValueError, r"No type watcher set for ID 1"): |
2015 | | - self.unwatch(1, C) |
2016 | | - |
2017 | | - def test_clear_out_of_range_watcher_id(self): |
2018 | | - with self.assertRaisesRegex(ValueError, r"Invalid type watcher ID -1"): |
2019 | | - self.clear_watcher(-1) |
2020 | | - with self.assertRaisesRegex(ValueError, r"Invalid type watcher ID 8"): |
2021 | | - self.clear_watcher(self.TYPE_MAX_WATCHERS) |
2022 | | - |
2023 | | - def test_clear_unassigned_watcher_id(self): |
2024 | | - with self.assertRaisesRegex(ValueError, r"No type watcher set for ID 1"): |
2025 | | - self.clear_watcher(1) |
2026 | | - |
2027 | | - def test_no_more_ids_available(self): |
2028 | | - contexts = [self.watcher() for i in range(self.TYPE_MAX_WATCHERS)] |
2029 | | - with ExitStack() as stack: |
2030 | | - for ctx in contexts: |
2031 | | - stack.enter_context(ctx) |
2032 | | - with self.assertRaisesRegex(RuntimeError, r"no more type watcher IDs"): |
2033 | | - self.add_watcher() |
2034 | | - |
2035 | | - |
2036 | 1706 | if __name__ == "__main__": |
2037 | 1707 | unittest.main() |
0 commit comments