@@ -1739,10 +1739,14 @@ def resolve(thing, forceload=0):
17391739 if isinstance (thing , str ):
17401740 object = locate (thing , forceload )
17411741 if object is None :
1742+ if re .match (r'^__\w+__$' , thing ):
1743+ special = "Use help('specialnames') for a list of special names for which help is available.\n "
1744+ else :
1745+ special = ""
17421746 raise ImportError ('''\
17431747 No Python documentation found for %r.
1744- Use help() to get the interactive help utility.
1745- Use help(str) for help on the str class.''' % thing )
1748+ %sUse help() to get the interactive help utility.
1749+ Use help(str) for help on the str class.''' % ( thing , special ) )
17461750 return object , thing
17471751 else :
17481752 name = getattr (thing , '__name__' , None )
@@ -1845,6 +1849,87 @@ def _introdoc():
18451849 enter "q", "quit" or "exit".
18461850 ''' )
18471851
1852+ def collect_dunders (symbols ):
1853+ dunders = {
1854+ '__main__' : ('__main__' , '' ),
1855+ '__call__' : ('callable-types' , 'SPECIALMETHODS' ),
1856+ }
1857+
1858+ basic_dunders = [
1859+ '__new__' , '__init__' , '__del__' , '__repr__' , '__str__' , '__bytes__' ,
1860+ '__format__' , '__hash__' , '__bool__' ,
1861+ ]
1862+ for bd in basic_dunders :
1863+ dunders [bd ] = ('customization' , 'SPECIALNAMES' )
1864+
1865+ attribute_dunders = [
1866+ '__getattr__' , '__getattribute__' , '__setattr__' , '__delattr__' ,
1867+ '__dir__' , '__get__' , '__set__' , '__delete__' , '__objclass__' ,
1868+ ]
1869+ for ad in attribute_dunders :
1870+ dunders [ad ] = ('attribute-access' , 'SPECIALNAMES' )
1871+
1872+ class_dunders = [
1873+ '__init_subclass__' , '__set_names__' , '__mro_entries__' ,
1874+ ]
1875+ for cd in class_dunders :
1876+ dunders [cd ] = ('class-customization' , 'SPECIALNAMES' )
1877+
1878+ instance_dunders = [
1879+ '__instancecheck__' , '__subclasscheck__'
1880+ ]
1881+ for d in instance_dunders :
1882+ dunders [d ] = ('custom-instance-subclass' , 'SPECIALNAMES' )
1883+
1884+ sequence_dunders = [
1885+ '__len__' , '__length_hint__' , '__getitem__' , '__setitem__' ,
1886+ '__delitem__' , '__missing__' , '__iter__' , '__reversed__' ,
1887+ '__contains__' ,
1888+ ]
1889+ for sd in sequence_dunders :
1890+ dunders [sd ] = ('SEQUENCEMETHODS' , 'SPECIALMETHODS' )
1891+
1892+ comparison_dunders = {
1893+ '__lt__' : '<' ,
1894+ '__le__' : '<=' ,
1895+ '__eq__' : '==' ,
1896+ '__ne__' : '!=' ,
1897+ '__gt__' : '>' ,
1898+ '__ge__' : '>=' ,
1899+ }
1900+ for dunder , symbol in comparison_dunders .items ():
1901+ dunders [dunder ] = ('customization' , f'{ symbol } SPECIALMETHODS' )
1902+ if symbol in symbols :
1903+ symbols [symbol ] += f' { dunder } '
1904+
1905+ arithmetic_dunders = {
1906+ '__add__' : '+' ,
1907+ '__sub__' : '-' ,
1908+ '__mul__' : '*' ,
1909+ '__matmul__' : '@' ,
1910+ '__truediv__' : '/' ,
1911+ '__floordiv__' : '//' ,
1912+ '__mod__' : '%' ,
1913+ '__pow__' : '**' ,
1914+ '__lshift__' : '<<' ,
1915+ '__rshift__' : '>>' ,
1916+ '__and__' : '&' ,
1917+ '__or__' : '|' ,
1918+ '__xor__' : '^' ,
1919+ }
1920+ for dunder , symbol in arithmetic_dunders .items ():
1921+ rname = "__r" + dunder [2 :]
1922+ iname = "__i" + dunder [2 :]
1923+ dunders [dunder ] = ('numeric-types' , f'{ symbol } { rname } { iname } SPECIALMETHODS' )
1924+ dunders [rname ] = ('numeric-types' , f'{ symbol } { dunder } SPECIALMETHODS' )
1925+ dunders [iname ] = ('numeric-types' , f'{ symbol } { dunder } SPECIALMETHODS' )
1926+ if symbol in symbols :
1927+ symbols [symbol ] += f' { dunder } '
1928+
1929+ dunders ['__divmod__' ] = ('numeric-types' , 'divmod' )
1930+
1931+ return dunders
1932+
18481933class Helper :
18491934
18501935 # These dictionaries map a topic name to either an alias, or a tuple
@@ -1925,7 +2010,8 @@ class Helper:
19252010 '(' : 'TUPLES FUNCTIONS CALLS' ,
19262011 ')' : 'TUPLES FUNCTIONS CALLS' ,
19272012 '[' : 'LISTS SUBSCRIPTS SLICINGS' ,
1928- ']' : 'LISTS SUBSCRIPTS SLICINGS'
2013+ ']' : 'LISTS SUBSCRIPTS SLICINGS' ,
2014+
19292015 }
19302016 for topic , symbols_ in _symbols_inverse .items ():
19312017 for symbol in symbols_ :
@@ -2023,9 +2109,13 @@ class Helper:
20232109 'CONTEXTMANAGERS' : ('context-managers' , 'with' ),
20242110 'DUNDERMETHODS' : 'SPECIALMETHODS' ,
20252111 'MAINMODULE' : '__main__' ,
2026- '__main__' : ('__main__' , '' ),
20272112 }
20282113
2114+ # add dunder methods
2115+ dunders = collect_dunders (symbols )
2116+ topics |= dunders
2117+
2118+
20292119 def __init__ (self , input = None , output = None ):
20302120 self ._input = input
20312121 self ._output = output
@@ -2100,6 +2190,8 @@ def help(self, request, is_cli=False):
21002190 elif request == 'keywords' : self .listkeywords ()
21012191 elif request == 'symbols' : self .listsymbols ()
21022192 elif request == 'topics' : self .listtopics ()
2193+ elif request in {'specialnames' , 'dunders' }:
2194+ self .listdunders ()
21032195 elif request == 'modules' : self .listmodules ()
21042196 elif request [:8 ] == 'modules ' :
21052197 self .listmodules (request .split ()[1 ])
@@ -2174,7 +2266,14 @@ def listtopics(self):
21742266Here is a list of available topics. Enter any topic name to get more help.
21752267
21762268''' )
2177- self .list ([k for k in self .topics .keys () if k .isupper ()], columns = 3 )
2269+ self .list ([k for k in self .topics if k not in self .dunders ], columns = 3 )
2270+
2271+ def listdunders (self ):
2272+ self .output .write ('''
2273+ Here is a list of special names for which help is available. Enter any one to get more help.
2274+
2275+ ''' )
2276+ self .list (self .dunders .keys (), columns = 3 )
21782277
21792278 def showtopic (self , topic , more_xrefs = '' ):
21802279 try :
0 commit comments