@@ -546,6 +546,7 @@ impl<'source> Lexer<'source> {
546
546
}
547
547
// Form feed
548
548
'\x0C' => {
549
+ self . cursor . bump ( ) ;
549
550
indentation = Indentation :: root ( ) ;
550
551
}
551
552
_ => break ,
@@ -1786,4 +1787,380 @@ mod tests {
1786
1787
fn triple_quoted_macos_eol ( ) {
1787
1788
assert_triple_quoted ( MAC_EOL ) ;
1788
1789
}
1790
+
1791
+ #[ test]
1792
+ fn regression ( ) {
1793
+ for token in lex (
1794
+ r#"# Tests some corner cases with isinstance() and issubclass(). While these
1795
+ # tests use new style classes and properties, they actually do whitebox
1796
+ # testing of error conditions uncovered when using extension types.
1797
+
1798
+ import unittest
1799
+ import sys
1800
+ import typing
1801
+ from test import support
1802
+
1803
+
1804
+
1805
+
1806
+ class TestIsInstanceExceptions(unittest.TestCase):
1807
+ # Test to make sure that an AttributeError when accessing the instance's
1808
+ # class's bases is masked. This was actually a bug in Python 2.2 and
1809
+ # 2.2.1 where the exception wasn't caught but it also wasn't being cleared
1810
+ # (leading to an "undetected error" in the debug build). Set up is,
1811
+ # isinstance(inst, cls) where:
1812
+ #
1813
+ # - cls isn't a type, or a tuple
1814
+ # - cls has a __bases__ attribute
1815
+ # - inst has a __class__ attribute
1816
+ # - inst.__class__ as no __bases__ attribute
1817
+ #
1818
+ # Sounds complicated, I know, but this mimics a situation where an
1819
+ # extension type raises an AttributeError when its __bases__ attribute is
1820
+ # gotten. In that case, isinstance() should return False.
1821
+ def test_class_has_no_bases(self):
1822
+ class I(object):
1823
+ def getclass(self):
1824
+ # This must return an object that has no __bases__ attribute
1825
+ return None
1826
+ __class__ = property(getclass)
1827
+
1828
+ class C(object):
1829
+ def getbases(self):
1830
+ return ()
1831
+ __bases__ = property(getbases)
1832
+
1833
+ self.assertEqual(False, isinstance(I(), C()))
1834
+
1835
+ # Like above except that inst.__class__.__bases__ raises an exception
1836
+ # other than AttributeError
1837
+ def test_bases_raises_other_than_attribute_error(self):
1838
+ class E(object):
1839
+ def getbases(self):
1840
+ raise RuntimeError
1841
+ __bases__ = property(getbases)
1842
+
1843
+ class I(object):
1844
+ def getclass(self):
1845
+ return E()
1846
+ __class__ = property(getclass)
1847
+
1848
+ class C(object):
1849
+ def getbases(self):
1850
+ return ()
1851
+ __bases__ = property(getbases)
1852
+
1853
+ self.assertRaises(RuntimeError, isinstance, I(), C())
1854
+
1855
+ # Here's a situation where getattr(cls, '__bases__') raises an exception.
1856
+ # If that exception is not AttributeError, it should not get masked
1857
+ def test_dont_mask_non_attribute_error(self):
1858
+ class I: pass
1859
+
1860
+ class C(object):
1861
+ def getbases(self):
1862
+ raise RuntimeError
1863
+ __bases__ = property(getbases)
1864
+
1865
+ self.assertRaises(RuntimeError, isinstance, I(), C())
1866
+
1867
+ # Like above, except that getattr(cls, '__bases__') raises an
1868
+ # AttributeError, which /should/ get masked as a TypeError
1869
+ def test_mask_attribute_error(self):
1870
+ class I: pass
1871
+
1872
+ class C(object):
1873
+ def getbases(self):
1874
+ raise AttributeError
1875
+ __bases__ = property(getbases)
1876
+
1877
+ self.assertRaises(TypeError, isinstance, I(), C())
1878
+
1879
+ # check that we don't mask non AttributeErrors
1880
+ # see: http://bugs.python.org/issue1574217
1881
+ def test_isinstance_dont_mask_non_attribute_error(self):
1882
+ class C(object):
1883
+ def getclass(self):
1884
+ raise RuntimeError
1885
+ __class__ = property(getclass)
1886
+
1887
+ c = C()
1888
+ self.assertRaises(RuntimeError, isinstance, c, bool)
1889
+
1890
+ # test another code path
1891
+ class D: pass
1892
+ self.assertRaises(RuntimeError, isinstance, c, D)
1893
+
1894
+
1895
+
1896
+ # These tests are similar to above, but tickle certain code paths in
1897
+ # issubclass() instead of isinstance() -- really PyObject_IsSubclass()
1898
+ # vs. PyObject_IsInstance().
1899
+ class TestIsSubclassExceptions(unittest.TestCase):
1900
+ def test_dont_mask_non_attribute_error(self):
1901
+ class C(object):
1902
+ def getbases(self):
1903
+ raise RuntimeError
1904
+ __bases__ = property(getbases)
1905
+
1906
+ class S(C): pass
1907
+
1908
+ self.assertRaises(RuntimeError, issubclass, C(), S())
1909
+
1910
+ def test_mask_attribute_error(self):
1911
+ class C(object):
1912
+ def getbases(self):
1913
+ raise AttributeError
1914
+ __bases__ = property(getbases)
1915
+
1916
+ class S(C): pass
1917
+
1918
+ self.assertRaises(TypeError, issubclass, C(), S())
1919
+
1920
+ # Like above, but test the second branch, where the __bases__ of the
1921
+ # second arg (the cls arg) is tested. This means the first arg must
1922
+ # return a valid __bases__, and it's okay for it to be a normal --
1923
+ # unrelated by inheritance -- class.
1924
+ def test_dont_mask_non_attribute_error_in_cls_arg(self):
1925
+ class B: pass
1926
+
1927
+ class C(object):
1928
+ def getbases(self):
1929
+ raise RuntimeError
1930
+ __bases__ = property(getbases)
1931
+
1932
+ self.assertRaises(RuntimeError, issubclass, B, C())
1933
+
1934
+ def test_mask_attribute_error_in_cls_arg(self):
1935
+ class B: pass
1936
+
1937
+ class C(object):
1938
+ def getbases(self):
1939
+ raise AttributeError
1940
+ __bases__ = property(getbases)
1941
+
1942
+ self.assertRaises(TypeError, issubclass, B, C())
1943
+
1944
+
1945
+
1946
+
1947
+ # meta classes for creating abstract classes and instances
1948
+ class AbstractClass(object):
1949
+ def __init__(self, bases):
1950
+ self.bases = bases
1951
+
1952
+ def getbases(self):
1953
+ return self.bases
1954
+ __bases__ = property(getbases)
1955
+
1956
+ def __call__(self):
1957
+ return AbstractInstance(self)
1958
+
1959
+ class AbstractInstance(object):
1960
+ def __init__(self, klass):
1961
+ self.klass = klass
1962
+
1963
+ def getclass(self):
1964
+ return self.klass
1965
+ __class__ = property(getclass)
1966
+
1967
+ # abstract classes
1968
+ AbstractSuper = AbstractClass(bases=())
1969
+
1970
+ AbstractChild = AbstractClass(bases=(AbstractSuper,))
1971
+
1972
+ # normal classes
1973
+ class Super:
1974
+ pass
1975
+
1976
+ class Child(Super):
1977
+ pass
1978
+
1979
+
1980
+ class TestIsInstanceIsSubclass(unittest.TestCase):
1981
+ # Tests to ensure that isinstance and issubclass work on abstract
1982
+ # classes and instances. Before the 2.2 release, TypeErrors were
1983
+ # raised when boolean values should have been returned. The bug was
1984
+ # triggered by mixing 'normal' classes and instances were with
1985
+ # 'abstract' classes and instances. This case tries to test all
1986
+ # combinations.
1987
+
1988
+ def test_isinstance_normal(self):
1989
+ # normal instances
1990
+ self.assertEqual(True, isinstance(Super(), Super))
1991
+ self.assertEqual(False, isinstance(Super(), Child))
1992
+ self.assertEqual(False, isinstance(Super(), AbstractSuper))
1993
+ self.assertEqual(False, isinstance(Super(), AbstractChild))
1994
+
1995
+ self.assertEqual(True, isinstance(Child(), Super))
1996
+ self.assertEqual(False, isinstance(Child(), AbstractSuper))
1997
+
1998
+ def test_isinstance_abstract(self):
1999
+ # abstract instances
2000
+ self.assertEqual(True, isinstance(AbstractSuper(), AbstractSuper))
2001
+ self.assertEqual(False, isinstance(AbstractSuper(), AbstractChild))
2002
+ self.assertEqual(False, isinstance(AbstractSuper(), Super))
2003
+ self.assertEqual(False, isinstance(AbstractSuper(), Child))
2004
+
2005
+ self.assertEqual(True, isinstance(AbstractChild(), AbstractChild))
2006
+ self.assertEqual(True, isinstance(AbstractChild(), AbstractSuper))
2007
+ self.assertEqual(False, isinstance(AbstractChild(), Super))
2008
+ self.assertEqual(False, isinstance(AbstractChild(), Child))
2009
+
2010
+ def test_isinstance_with_or_union(self):
2011
+ self.assertTrue(isinstance(Super(), Super | int))
2012
+ self.assertFalse(isinstance(None, str | int))
2013
+ self.assertTrue(isinstance(3, str | int))
2014
+ self.assertTrue(isinstance("", str | int))
2015
+ self.assertTrue(isinstance([], typing.List | typing.Tuple))
2016
+ self.assertTrue(isinstance(2, typing.List | int))
2017
+ self.assertFalse(isinstance(2, typing.List | typing.Tuple))
2018
+ self.assertTrue(isinstance(None, int | None))
2019
+ self.assertFalse(isinstance(3.14, int | str))
2020
+ with self.assertRaises(TypeError):
2021
+ isinstance(2, list[int])
2022
+ with self.assertRaises(TypeError):
2023
+ isinstance(2, list[int] | int)
2024
+ with self.assertRaises(TypeError):
2025
+ isinstance(2, int | str | list[int] | float)
2026
+
2027
+
2028
+
2029
+ def test_subclass_normal(self):
2030
+ # normal classes
2031
+ self.assertEqual(True, issubclass(Super, Super))
2032
+ self.assertEqual(False, issubclass(Super, AbstractSuper))
2033
+ self.assertEqual(False, issubclass(Super, Child))
2034
+
2035
+ self.assertEqual(True, issubclass(Child, Child))
2036
+ self.assertEqual(True, issubclass(Child, Super))
2037
+ self.assertEqual(False, issubclass(Child, AbstractSuper))
2038
+ self.assertTrue(issubclass(typing.List, typing.List|typing.Tuple))
2039
+ self.assertFalse(issubclass(int, typing.List|typing.Tuple))
2040
+
2041
+ def test_subclass_abstract(self):
2042
+ # abstract classes
2043
+ self.assertEqual(True, issubclass(AbstractSuper, AbstractSuper))
2044
+ self.assertEqual(False, issubclass(AbstractSuper, AbstractChild))
2045
+ self.assertEqual(False, issubclass(AbstractSuper, Child))
2046
+
2047
+ self.assertEqual(True, issubclass(AbstractChild, AbstractChild))
2048
+ self.assertEqual(True, issubclass(AbstractChild, AbstractSuper))
2049
+ self.assertEqual(False, issubclass(AbstractChild, Super))
2050
+ self.assertEqual(False, issubclass(AbstractChild, Child))
2051
+
2052
+ def test_subclass_tuple(self):
2053
+ # test with a tuple as the second argument classes
2054
+ self.assertEqual(True, issubclass(Child, (Child,)))
2055
+ self.assertEqual(True, issubclass(Child, (Super,)))
2056
+ self.assertEqual(False, issubclass(Super, (Child,)))
2057
+ self.assertEqual(True, issubclass(Super, (Child, Super)))
2058
+ self.assertEqual(False, issubclass(Child, ()))
2059
+ self.assertEqual(True, issubclass(Super, (Child, (Super,))))
2060
+
2061
+ self.assertEqual(True, issubclass(int, (int, (float, int))))
2062
+ self.assertEqual(True, issubclass(str, (str, (Child, str))))
2063
+
2064
+ def test_subclass_recursion_limit(self):
2065
+ # make sure that issubclass raises RecursionError before the C stack is
2066
+ # blown
2067
+ with support.infinite_recursion():
2068
+ self.assertRaises(RecursionError, blowstack, issubclass, str, str)
2069
+
2070
+ def test_isinstance_recursion_limit(self):
2071
+ # make sure that issubclass raises RecursionError before the C stack is
2072
+ # blown
2073
+ with support.infinite_recursion():
2074
+ self.assertRaises(RecursionError, blowstack, isinstance, '', str)
2075
+
2076
+ def test_subclass_with_union(self):
2077
+ self.assertTrue(issubclass(int, int | float | int))
2078
+ self.assertTrue(issubclass(str, str | Child | str))
2079
+ self.assertFalse(issubclass(dict, float|str))
2080
+ self.assertFalse(issubclass(object, float|str))
2081
+ with self.assertRaises(TypeError):
2082
+ issubclass(2, Child | Super)
2083
+ with self.assertRaises(TypeError):
2084
+ issubclass(int, list[int] | Child)
2085
+
2086
+ def test_issubclass_refcount_handling(self):
2087
+ # bpo-39382: abstract_issubclass() didn't hold item reference while
2088
+ # peeking in the bases tuple, in the single inheritance case.
2089
+ class A:
2090
+ @property
2091
+ def __bases__(self):
2092
+ return (int, )
2093
+
2094
+ class B:
2095
+ def __init__(self):
2096
+ # setting this here increases the chances of exhibiting the bug,
2097
+ # probably due to memory layout changes.
2098
+ self.x = 1
2099
+
2100
+ @property
2101
+ def __bases__(self):
2102
+ return (A(), )
2103
+
2104
+ self.assertEqual(True, issubclass(B(), int))
2105
+
2106
+ def test_infinite_recursion_in_bases(self):
2107
+ class X:
2108
+ @property
2109
+ def __bases__(self):
2110
+ return self.__bases__
2111
+ with support.infinite_recursion():
2112
+ self.assertRaises(RecursionError, issubclass, X(), int)
2113
+ self.assertRaises(RecursionError, issubclass, int, X())
2114
+ self.assertRaises(RecursionError, isinstance, 1, X())
2115
+
2116
+ def test_infinite_recursion_via_bases_tuple(self):
2117
+ """Regression test for bpo-30570."""
2118
+ class Failure(object):
2119
+ def __getattr__(self, attr):
2120
+ return (self, None)
2121
+ with support.infinite_recursion():
2122
+ with self.assertRaises(RecursionError):
2123
+ issubclass(Failure(), int)
2124
+
2125
+ def test_infinite_cycle_in_bases(self):
2126
+ """Regression test for bpo-30570."""
2127
+ class X:
2128
+ @property
2129
+ def __bases__(self):
2130
+ return (self, self, self)
2131
+ with support.infinite_recursion():
2132
+ self.assertRaises(RecursionError, issubclass, X(), int)
2133
+
2134
+ def test_infinitely_many_bases(self):
2135
+ """Regression test for bpo-30570."""
2136
+ class X:
2137
+ def __getattr__(self, attr):
2138
+ self.assertEqual(attr, "__bases__")
2139
+ class A:
2140
+ pass
2141
+ class B:
2142
+ pass
2143
+ A.__getattr__ = B.__getattr__ = X.__getattr__
2144
+ return (A(), B())
2145
+ with support.infinite_recursion():
2146
+ self.assertRaises(RecursionError, issubclass, X(), int)
2147
+
2148
+
2149
+ def blowstack(fxn, arg, compare_to):
2150
+ # Make sure that calling isinstance with a deeply nested tuple for its
2151
+ # argument will raise RecursionError eventually.
2152
+ tuple_arg = (compare_to,)
2153
+ for cnt in range(sys.getrecursionlimit()+5):
2154
+ tuple_arg = (tuple_arg,)
2155
+ fxn(arg, tuple_arg)
2156
+
2157
+
2158
+
2159
+ if __name__ == '__main__':
2160
+ unittest.main()"# ,
2161
+ Mode :: Module ,
2162
+ ) {
2163
+ dbg ! ( token) ;
2164
+ }
2165
+ }
1789
2166
}
0 commit comments