55
55
# ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode,
56
56
# isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers,
57
57
# getdoc, getfile, getmodule, getsourcefile, getcomments, getsource,
58
- # getclasstree, getargvalues, formatargvalues,
59
- # currentframe, stack, trace, isdatadescriptor,
60
- # ismethodwrapper
58
+ # getclasstree, getargvalues, formatargvalues, currentframe,
59
+ # stack, trace, ismethoddescriptor, isdatadescriptor, ismethodwrapper
61
60
62
61
# NOTE: There are some additional tests relating to interaction with
63
62
# zipimport in the test_zipimport_support test module.
@@ -179,6 +178,7 @@ def test_excluding_predicates(self):
179
178
self .istest (inspect .ismethod , 'git.argue' )
180
179
self .istest (inspect .ismethod , 'mod.custom_method' )
181
180
self .istest (inspect .ismodule , 'mod' )
181
+ self .istest (inspect .ismethoddescriptor , 'int.__add__' )
182
182
self .istest (inspect .isdatadescriptor , 'collections.defaultdict.default_factory' )
183
183
self .istest (inspect .isgenerator , '(x for x in range(2))' )
184
184
self .istest (inspect .isgeneratorfunction , 'generator_function_example' )
@@ -1813,6 +1813,121 @@ def test_typing_replacement(self):
1813
1813
self .assertEqual (inspect .formatannotation (ann1 ), 'Union[List[testModule.typing.A], int]' )
1814
1814
1815
1815
1816
+ class TestIsMethodDescriptor (unittest .TestCase ):
1817
+
1818
+ def test_custom_descriptors (self ):
1819
+ class MethodDescriptor :
1820
+ def __get__ (self , * _ ): pass
1821
+ class MethodDescriptorSub (MethodDescriptor ):
1822
+ pass
1823
+ class DataDescriptorWithNoGet :
1824
+ def __set__ (self , * _ ): pass
1825
+ class DataDescriptorWithGetSet :
1826
+ def __get__ (self , * _ ): pass
1827
+ def __set__ (self , * _ ): pass
1828
+ class DataDescriptorWithGetDelete :
1829
+ def __get__ (self , * _ ): pass
1830
+ def __delete__ (self , * _ ): pass
1831
+ class DataDescriptorSub (DataDescriptorWithNoGet ,
1832
+ DataDescriptorWithGetDelete ):
1833
+ pass
1834
+
1835
+ # Custom method descriptors:
1836
+ self .assertTrue (
1837
+ inspect .ismethoddescriptor (MethodDescriptor ()),
1838
+ '__get__ and no __set__/__delete__ => method descriptor' )
1839
+ self .assertTrue (
1840
+ inspect .ismethoddescriptor (MethodDescriptorSub ()),
1841
+ '__get__ (inherited) and no __set__/__delete__'
1842
+ ' => method descriptor' )
1843
+
1844
+ # Custom data descriptors:
1845
+ self .assertFalse (
1846
+ inspect .ismethoddescriptor (DataDescriptorWithNoGet ()),
1847
+ '__set__ (and no __get__) => not a method descriptor' )
1848
+ self .assertFalse (
1849
+ inspect .ismethoddescriptor (DataDescriptorWithGetSet ()),
1850
+ '__get__ and __set__ => not a method descriptor' )
1851
+ self .assertFalse (
1852
+ inspect .ismethoddescriptor (DataDescriptorWithGetDelete ()),
1853
+ '__get__ and __delete__ => not a method descriptor' )
1854
+ self .assertFalse (
1855
+ inspect .ismethoddescriptor (DataDescriptorSub ()),
1856
+ '__get__, __set__ and __delete__ => not a method descriptor' )
1857
+
1858
+ # Classes of descriptors (are *not* descriptors themselves):
1859
+ self .assertFalse (inspect .ismethoddescriptor (MethodDescriptor ))
1860
+ self .assertFalse (inspect .ismethoddescriptor (MethodDescriptorSub ))
1861
+ self .assertFalse (inspect .ismethoddescriptor (DataDescriptorSub ))
1862
+
1863
+ def test_builtin_descriptors (self ):
1864
+ builtin_slot_wrapper = int .__add__ # This one is mentioned in docs.
1865
+ class Owner :
1866
+ def instance_method (self ): pass
1867
+ @classmethod
1868
+ def class_method (cls ): pass
1869
+ @staticmethod
1870
+ def static_method (): pass
1871
+ @property
1872
+ def a_property (self ): pass
1873
+ class Slotermeyer :
1874
+ __slots__ = 'a_slot' ,
1875
+ def function ():
1876
+ pass
1877
+ a_lambda = lambda : None
1878
+
1879
+ # Example builtin method descriptors:
1880
+ self .assertTrue (
1881
+ inspect .ismethoddescriptor (builtin_slot_wrapper ),
1882
+ 'a builtin slot wrapper is a method descriptor' )
1883
+ self .assertTrue (
1884
+ inspect .ismethoddescriptor (Owner .__dict__ ['class_method' ]),
1885
+ 'a classmethod object is a method descriptor' )
1886
+ self .assertTrue (
1887
+ inspect .ismethoddescriptor (Owner .__dict__ ['static_method' ]),
1888
+ 'a staticmethod object is a method descriptor' )
1889
+
1890
+ # Example builtin data descriptors:
1891
+ self .assertFalse (
1892
+ inspect .ismethoddescriptor (Owner .__dict__ ['a_property' ]),
1893
+ 'a property is not a method descriptor' )
1894
+ self .assertFalse (
1895
+ inspect .ismethoddescriptor (Slotermeyer .__dict__ ['a_slot' ]),
1896
+ 'a slot is not a method descriptor' )
1897
+
1898
+ # `types.MethodType`/`types.FunctionType` instances (they *are*
1899
+ # method descriptors, but `ismethoddescriptor()` explicitly
1900
+ # excludes them):
1901
+ self .assertFalse (inspect .ismethoddescriptor (Owner ().instance_method ))
1902
+ self .assertFalse (inspect .ismethoddescriptor (Owner ().class_method ))
1903
+ self .assertFalse (inspect .ismethoddescriptor (Owner ().static_method ))
1904
+ self .assertFalse (inspect .ismethoddescriptor (Owner .instance_method ))
1905
+ self .assertFalse (inspect .ismethoddescriptor (Owner .class_method ))
1906
+ self .assertFalse (inspect .ismethoddescriptor (Owner .static_method ))
1907
+ self .assertFalse (inspect .ismethoddescriptor (function ))
1908
+ self .assertFalse (inspect .ismethoddescriptor (a_lambda ))
1909
+
1910
+ def test_descriptor_being_a_class (self ):
1911
+ class MethodDescriptorMeta (type ):
1912
+ def __get__ (self , * _ ): pass
1913
+ class ClassBeingMethodDescriptor (metaclass = MethodDescriptorMeta ):
1914
+ pass
1915
+ # `ClassBeingMethodDescriptor` itself *is* a method descriptor,
1916
+ # but it is *also* a class, and `ismethoddescriptor()` explicitly
1917
+ # excludes classes.
1918
+ self .assertFalse (
1919
+ inspect .ismethoddescriptor (ClassBeingMethodDescriptor ),
1920
+ 'classes (instances of type) are explicitly excluded' )
1921
+
1922
+ def test_non_descriptors (self ):
1923
+ class Test :
1924
+ pass
1925
+ self .assertFalse (inspect .ismethoddescriptor (Test ()))
1926
+ self .assertFalse (inspect .ismethoddescriptor (Test ))
1927
+ self .assertFalse (inspect .ismethoddescriptor ([42 ]))
1928
+ self .assertFalse (inspect .ismethoddescriptor (42 ))
1929
+
1930
+
1816
1931
class TestIsDataDescriptor (unittest .TestCase ):
1817
1932
1818
1933
def test_custom_descriptors (self ):
0 commit comments