1*cda5da8dSAndroid Build Coastguard Worker#!/usr/bin/env python3 2*cda5da8dSAndroid Build Coastguard Worker"""Generate Python documentation in HTML or text for interactive use. 3*cda5da8dSAndroid Build Coastguard Worker 4*cda5da8dSAndroid Build Coastguard WorkerAt the Python interactive prompt, calling help(thing) on a Python object 5*cda5da8dSAndroid Build Coastguard Workerdocuments the object, and calling help() starts up an interactive 6*cda5da8dSAndroid Build Coastguard Workerhelp session. 7*cda5da8dSAndroid Build Coastguard Worker 8*cda5da8dSAndroid Build Coastguard WorkerOr, at the shell command line outside of Python: 9*cda5da8dSAndroid Build Coastguard Worker 10*cda5da8dSAndroid Build Coastguard WorkerRun "pydoc <name>" to show documentation on something. <name> may be 11*cda5da8dSAndroid Build Coastguard Workerthe name of a function, module, package, or a dotted reference to a 12*cda5da8dSAndroid Build Coastguard Workerclass or function within a module or module in a package. If the 13*cda5da8dSAndroid Build Coastguard Workerargument contains a path segment delimiter (e.g. slash on Unix, 14*cda5da8dSAndroid Build Coastguard Workerbackslash on Windows) it is treated as the path to a Python source file. 15*cda5da8dSAndroid Build Coastguard Worker 16*cda5da8dSAndroid Build Coastguard WorkerRun "pydoc -k <keyword>" to search for a keyword in the synopsis lines 17*cda5da8dSAndroid Build Coastguard Workerof all available modules. 18*cda5da8dSAndroid Build Coastguard Worker 19*cda5da8dSAndroid Build Coastguard WorkerRun "pydoc -n <hostname>" to start an HTTP server with the given 20*cda5da8dSAndroid Build Coastguard Workerhostname (default: localhost) on the local machine. 21*cda5da8dSAndroid Build Coastguard Worker 22*cda5da8dSAndroid Build Coastguard WorkerRun "pydoc -p <port>" to start an HTTP server on the given port on the 23*cda5da8dSAndroid Build Coastguard Workerlocal machine. Port number 0 can be used to get an arbitrary unused port. 24*cda5da8dSAndroid Build Coastguard Worker 25*cda5da8dSAndroid Build Coastguard WorkerRun "pydoc -b" to start an HTTP server on an arbitrary unused port and 26*cda5da8dSAndroid Build Coastguard Workeropen a web browser to interactively browse documentation. Combine with 27*cda5da8dSAndroid Build Coastguard Workerthe -n and -p options to control the hostname and port used. 28*cda5da8dSAndroid Build Coastguard Worker 29*cda5da8dSAndroid Build Coastguard WorkerRun "pydoc -w <name>" to write out the HTML documentation for a module 30*cda5da8dSAndroid Build Coastguard Workerto a file named "<name>.html". 31*cda5da8dSAndroid Build Coastguard Worker 32*cda5da8dSAndroid Build Coastguard WorkerModule docs for core modules are assumed to be in 33*cda5da8dSAndroid Build Coastguard Worker 34*cda5da8dSAndroid Build Coastguard Worker https://docs.python.org/X.Y/library/ 35*cda5da8dSAndroid Build Coastguard Worker 36*cda5da8dSAndroid Build Coastguard WorkerThis can be overridden by setting the PYTHONDOCS environment variable 37*cda5da8dSAndroid Build Coastguard Workerto a different URL or to a local directory containing the Library 38*cda5da8dSAndroid Build Coastguard WorkerReference Manual pages. 39*cda5da8dSAndroid Build Coastguard Worker""" 40*cda5da8dSAndroid Build Coastguard Worker__all__ = ['help'] 41*cda5da8dSAndroid Build Coastguard Worker__author__ = "Ka-Ping Yee <[email protected]>" 42*cda5da8dSAndroid Build Coastguard Worker__date__ = "26 February 2001" 43*cda5da8dSAndroid Build Coastguard Worker 44*cda5da8dSAndroid Build Coastguard Worker__credits__ = """Guido van Rossum, for an excellent programming language. 45*cda5da8dSAndroid Build Coastguard WorkerTommy Burnette, the original creator of manpy. 46*cda5da8dSAndroid Build Coastguard WorkerPaul Prescod, for all his work on onlinehelp. 47*cda5da8dSAndroid Build Coastguard WorkerRichard Chamberlain, for the first implementation of textdoc. 48*cda5da8dSAndroid Build Coastguard Worker""" 49*cda5da8dSAndroid Build Coastguard Worker 50*cda5da8dSAndroid Build Coastguard Worker# Known bugs that can't be fixed here: 51*cda5da8dSAndroid Build Coastguard Worker# - synopsis() cannot be prevented from clobbering existing 52*cda5da8dSAndroid Build Coastguard Worker# loaded modules. 53*cda5da8dSAndroid Build Coastguard Worker# - If the __file__ attribute on a module is a relative path and 54*cda5da8dSAndroid Build Coastguard Worker# the current directory is changed with os.chdir(), an incorrect 55*cda5da8dSAndroid Build Coastguard Worker# path will be displayed. 56*cda5da8dSAndroid Build Coastguard Worker 57*cda5da8dSAndroid Build Coastguard Workerimport __future__ 58*cda5da8dSAndroid Build Coastguard Workerimport builtins 59*cda5da8dSAndroid Build Coastguard Workerimport importlib._bootstrap 60*cda5da8dSAndroid Build Coastguard Workerimport importlib._bootstrap_external 61*cda5da8dSAndroid Build Coastguard Workerimport importlib.machinery 62*cda5da8dSAndroid Build Coastguard Workerimport importlib.util 63*cda5da8dSAndroid Build Coastguard Workerimport inspect 64*cda5da8dSAndroid Build Coastguard Workerimport io 65*cda5da8dSAndroid Build Coastguard Workerimport os 66*cda5da8dSAndroid Build Coastguard Workerimport pkgutil 67*cda5da8dSAndroid Build Coastguard Workerimport platform 68*cda5da8dSAndroid Build Coastguard Workerimport re 69*cda5da8dSAndroid Build Coastguard Workerimport sys 70*cda5da8dSAndroid Build Coastguard Workerimport sysconfig 71*cda5da8dSAndroid Build Coastguard Workerimport time 72*cda5da8dSAndroid Build Coastguard Workerimport tokenize 73*cda5da8dSAndroid Build Coastguard Workerimport urllib.parse 74*cda5da8dSAndroid Build Coastguard Workerimport warnings 75*cda5da8dSAndroid Build Coastguard Workerfrom collections import deque 76*cda5da8dSAndroid Build Coastguard Workerfrom reprlib import Repr 77*cda5da8dSAndroid Build Coastguard Workerfrom traceback import format_exception_only 78*cda5da8dSAndroid Build Coastguard Worker 79*cda5da8dSAndroid Build Coastguard Worker 80*cda5da8dSAndroid Build Coastguard Worker# --------------------------------------------------------- common routines 81*cda5da8dSAndroid Build Coastguard Worker 82*cda5da8dSAndroid Build Coastguard Workerdef pathdirs(): 83*cda5da8dSAndroid Build Coastguard Worker """Convert sys.path into a list of absolute, existing, unique paths.""" 84*cda5da8dSAndroid Build Coastguard Worker dirs = [] 85*cda5da8dSAndroid Build Coastguard Worker normdirs = [] 86*cda5da8dSAndroid Build Coastguard Worker for dir in sys.path: 87*cda5da8dSAndroid Build Coastguard Worker dir = os.path.abspath(dir or '.') 88*cda5da8dSAndroid Build Coastguard Worker normdir = os.path.normcase(dir) 89*cda5da8dSAndroid Build Coastguard Worker if normdir not in normdirs and os.path.isdir(dir): 90*cda5da8dSAndroid Build Coastguard Worker dirs.append(dir) 91*cda5da8dSAndroid Build Coastguard Worker normdirs.append(normdir) 92*cda5da8dSAndroid Build Coastguard Worker return dirs 93*cda5da8dSAndroid Build Coastguard Worker 94*cda5da8dSAndroid Build Coastguard Workerdef _findclass(func): 95*cda5da8dSAndroid Build Coastguard Worker cls = sys.modules.get(func.__module__) 96*cda5da8dSAndroid Build Coastguard Worker if cls is None: 97*cda5da8dSAndroid Build Coastguard Worker return None 98*cda5da8dSAndroid Build Coastguard Worker for name in func.__qualname__.split('.')[:-1]: 99*cda5da8dSAndroid Build Coastguard Worker cls = getattr(cls, name) 100*cda5da8dSAndroid Build Coastguard Worker if not inspect.isclass(cls): 101*cda5da8dSAndroid Build Coastguard Worker return None 102*cda5da8dSAndroid Build Coastguard Worker return cls 103*cda5da8dSAndroid Build Coastguard Worker 104*cda5da8dSAndroid Build Coastguard Workerdef _finddoc(obj): 105*cda5da8dSAndroid Build Coastguard Worker if inspect.ismethod(obj): 106*cda5da8dSAndroid Build Coastguard Worker name = obj.__func__.__name__ 107*cda5da8dSAndroid Build Coastguard Worker self = obj.__self__ 108*cda5da8dSAndroid Build Coastguard Worker if (inspect.isclass(self) and 109*cda5da8dSAndroid Build Coastguard Worker getattr(getattr(self, name, None), '__func__') is obj.__func__): 110*cda5da8dSAndroid Build Coastguard Worker # classmethod 111*cda5da8dSAndroid Build Coastguard Worker cls = self 112*cda5da8dSAndroid Build Coastguard Worker else: 113*cda5da8dSAndroid Build Coastguard Worker cls = self.__class__ 114*cda5da8dSAndroid Build Coastguard Worker elif inspect.isfunction(obj): 115*cda5da8dSAndroid Build Coastguard Worker name = obj.__name__ 116*cda5da8dSAndroid Build Coastguard Worker cls = _findclass(obj) 117*cda5da8dSAndroid Build Coastguard Worker if cls is None or getattr(cls, name) is not obj: 118*cda5da8dSAndroid Build Coastguard Worker return None 119*cda5da8dSAndroid Build Coastguard Worker elif inspect.isbuiltin(obj): 120*cda5da8dSAndroid Build Coastguard Worker name = obj.__name__ 121*cda5da8dSAndroid Build Coastguard Worker self = obj.__self__ 122*cda5da8dSAndroid Build Coastguard Worker if (inspect.isclass(self) and 123*cda5da8dSAndroid Build Coastguard Worker self.__qualname__ + '.' + name == obj.__qualname__): 124*cda5da8dSAndroid Build Coastguard Worker # classmethod 125*cda5da8dSAndroid Build Coastguard Worker cls = self 126*cda5da8dSAndroid Build Coastguard Worker else: 127*cda5da8dSAndroid Build Coastguard Worker cls = self.__class__ 128*cda5da8dSAndroid Build Coastguard Worker # Should be tested before isdatadescriptor(). 129*cda5da8dSAndroid Build Coastguard Worker elif isinstance(obj, property): 130*cda5da8dSAndroid Build Coastguard Worker func = obj.fget 131*cda5da8dSAndroid Build Coastguard Worker name = func.__name__ 132*cda5da8dSAndroid Build Coastguard Worker cls = _findclass(func) 133*cda5da8dSAndroid Build Coastguard Worker if cls is None or getattr(cls, name) is not obj: 134*cda5da8dSAndroid Build Coastguard Worker return None 135*cda5da8dSAndroid Build Coastguard Worker elif inspect.ismethoddescriptor(obj) or inspect.isdatadescriptor(obj): 136*cda5da8dSAndroid Build Coastguard Worker name = obj.__name__ 137*cda5da8dSAndroid Build Coastguard Worker cls = obj.__objclass__ 138*cda5da8dSAndroid Build Coastguard Worker if getattr(cls, name) is not obj: 139*cda5da8dSAndroid Build Coastguard Worker return None 140*cda5da8dSAndroid Build Coastguard Worker if inspect.ismemberdescriptor(obj): 141*cda5da8dSAndroid Build Coastguard Worker slots = getattr(cls, '__slots__', None) 142*cda5da8dSAndroid Build Coastguard Worker if isinstance(slots, dict) and name in slots: 143*cda5da8dSAndroid Build Coastguard Worker return slots[name] 144*cda5da8dSAndroid Build Coastguard Worker else: 145*cda5da8dSAndroid Build Coastguard Worker return None 146*cda5da8dSAndroid Build Coastguard Worker for base in cls.__mro__: 147*cda5da8dSAndroid Build Coastguard Worker try: 148*cda5da8dSAndroid Build Coastguard Worker doc = _getowndoc(getattr(base, name)) 149*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 150*cda5da8dSAndroid Build Coastguard Worker continue 151*cda5da8dSAndroid Build Coastguard Worker if doc is not None: 152*cda5da8dSAndroid Build Coastguard Worker return doc 153*cda5da8dSAndroid Build Coastguard Worker return None 154*cda5da8dSAndroid Build Coastguard Worker 155*cda5da8dSAndroid Build Coastguard Workerdef _getowndoc(obj): 156*cda5da8dSAndroid Build Coastguard Worker """Get the documentation string for an object if it is not 157*cda5da8dSAndroid Build Coastguard Worker inherited from its class.""" 158*cda5da8dSAndroid Build Coastguard Worker try: 159*cda5da8dSAndroid Build Coastguard Worker doc = object.__getattribute__(obj, '__doc__') 160*cda5da8dSAndroid Build Coastguard Worker if doc is None: 161*cda5da8dSAndroid Build Coastguard Worker return None 162*cda5da8dSAndroid Build Coastguard Worker if obj is not type: 163*cda5da8dSAndroid Build Coastguard Worker typedoc = type(obj).__doc__ 164*cda5da8dSAndroid Build Coastguard Worker if isinstance(typedoc, str) and typedoc == doc: 165*cda5da8dSAndroid Build Coastguard Worker return None 166*cda5da8dSAndroid Build Coastguard Worker return doc 167*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 168*cda5da8dSAndroid Build Coastguard Worker return None 169*cda5da8dSAndroid Build Coastguard Worker 170*cda5da8dSAndroid Build Coastguard Workerdef _getdoc(object): 171*cda5da8dSAndroid Build Coastguard Worker """Get the documentation string for an object. 172*cda5da8dSAndroid Build Coastguard Worker 173*cda5da8dSAndroid Build Coastguard Worker All tabs are expanded to spaces. To clean up docstrings that are 174*cda5da8dSAndroid Build Coastguard Worker indented to line up with blocks of code, any whitespace than can be 175*cda5da8dSAndroid Build Coastguard Worker uniformly removed from the second line onwards is removed.""" 176*cda5da8dSAndroid Build Coastguard Worker doc = _getowndoc(object) 177*cda5da8dSAndroid Build Coastguard Worker if doc is None: 178*cda5da8dSAndroid Build Coastguard Worker try: 179*cda5da8dSAndroid Build Coastguard Worker doc = _finddoc(object) 180*cda5da8dSAndroid Build Coastguard Worker except (AttributeError, TypeError): 181*cda5da8dSAndroid Build Coastguard Worker return None 182*cda5da8dSAndroid Build Coastguard Worker if not isinstance(doc, str): 183*cda5da8dSAndroid Build Coastguard Worker return None 184*cda5da8dSAndroid Build Coastguard Worker return inspect.cleandoc(doc) 185*cda5da8dSAndroid Build Coastguard Worker 186*cda5da8dSAndroid Build Coastguard Workerdef getdoc(object): 187*cda5da8dSAndroid Build Coastguard Worker """Get the doc string or comments for an object.""" 188*cda5da8dSAndroid Build Coastguard Worker result = _getdoc(object) or inspect.getcomments(object) 189*cda5da8dSAndroid Build Coastguard Worker return result and re.sub('^ *\n', '', result.rstrip()) or '' 190*cda5da8dSAndroid Build Coastguard Worker 191*cda5da8dSAndroid Build Coastguard Workerdef splitdoc(doc): 192*cda5da8dSAndroid Build Coastguard Worker """Split a doc string into a synopsis line (if any) and the rest.""" 193*cda5da8dSAndroid Build Coastguard Worker lines = doc.strip().split('\n') 194*cda5da8dSAndroid Build Coastguard Worker if len(lines) == 1: 195*cda5da8dSAndroid Build Coastguard Worker return lines[0], '' 196*cda5da8dSAndroid Build Coastguard Worker elif len(lines) >= 2 and not lines[1].rstrip(): 197*cda5da8dSAndroid Build Coastguard Worker return lines[0], '\n'.join(lines[2:]) 198*cda5da8dSAndroid Build Coastguard Worker return '', '\n'.join(lines) 199*cda5da8dSAndroid Build Coastguard Worker 200*cda5da8dSAndroid Build Coastguard Workerdef classname(object, modname): 201*cda5da8dSAndroid Build Coastguard Worker """Get a class name and qualify it with a module name if necessary.""" 202*cda5da8dSAndroid Build Coastguard Worker name = object.__name__ 203*cda5da8dSAndroid Build Coastguard Worker if object.__module__ != modname: 204*cda5da8dSAndroid Build Coastguard Worker name = object.__module__ + '.' + name 205*cda5da8dSAndroid Build Coastguard Worker return name 206*cda5da8dSAndroid Build Coastguard Worker 207*cda5da8dSAndroid Build Coastguard Workerdef isdata(object): 208*cda5da8dSAndroid Build Coastguard Worker """Check if an object is of a type that probably means it's data.""" 209*cda5da8dSAndroid Build Coastguard Worker return not (inspect.ismodule(object) or inspect.isclass(object) or 210*cda5da8dSAndroid Build Coastguard Worker inspect.isroutine(object) or inspect.isframe(object) or 211*cda5da8dSAndroid Build Coastguard Worker inspect.istraceback(object) or inspect.iscode(object)) 212*cda5da8dSAndroid Build Coastguard Worker 213*cda5da8dSAndroid Build Coastguard Workerdef replace(text, *pairs): 214*cda5da8dSAndroid Build Coastguard Worker """Do a series of global replacements on a string.""" 215*cda5da8dSAndroid Build Coastguard Worker while pairs: 216*cda5da8dSAndroid Build Coastguard Worker text = pairs[1].join(text.split(pairs[0])) 217*cda5da8dSAndroid Build Coastguard Worker pairs = pairs[2:] 218*cda5da8dSAndroid Build Coastguard Worker return text 219*cda5da8dSAndroid Build Coastguard Worker 220*cda5da8dSAndroid Build Coastguard Workerdef cram(text, maxlen): 221*cda5da8dSAndroid Build Coastguard Worker """Omit part of a string if needed to make it fit in a maximum length.""" 222*cda5da8dSAndroid Build Coastguard Worker if len(text) > maxlen: 223*cda5da8dSAndroid Build Coastguard Worker pre = max(0, (maxlen-3)//2) 224*cda5da8dSAndroid Build Coastguard Worker post = max(0, maxlen-3-pre) 225*cda5da8dSAndroid Build Coastguard Worker return text[:pre] + '...' + text[len(text)-post:] 226*cda5da8dSAndroid Build Coastguard Worker return text 227*cda5da8dSAndroid Build Coastguard Worker 228*cda5da8dSAndroid Build Coastguard Worker_re_stripid = re.compile(r' at 0x[0-9a-f]{6,16}(>+)$', re.IGNORECASE) 229*cda5da8dSAndroid Build Coastguard Workerdef stripid(text): 230*cda5da8dSAndroid Build Coastguard Worker """Remove the hexadecimal id from a Python object representation.""" 231*cda5da8dSAndroid Build Coastguard Worker # The behaviour of %p is implementation-dependent in terms of case. 232*cda5da8dSAndroid Build Coastguard Worker return _re_stripid.sub(r'\1', text) 233*cda5da8dSAndroid Build Coastguard Worker 234*cda5da8dSAndroid Build Coastguard Workerdef _is_bound_method(fn): 235*cda5da8dSAndroid Build Coastguard Worker """ 236*cda5da8dSAndroid Build Coastguard Worker Returns True if fn is a bound method, regardless of whether 237*cda5da8dSAndroid Build Coastguard Worker fn was implemented in Python or in C. 238*cda5da8dSAndroid Build Coastguard Worker """ 239*cda5da8dSAndroid Build Coastguard Worker if inspect.ismethod(fn): 240*cda5da8dSAndroid Build Coastguard Worker return True 241*cda5da8dSAndroid Build Coastguard Worker if inspect.isbuiltin(fn): 242*cda5da8dSAndroid Build Coastguard Worker self = getattr(fn, '__self__', None) 243*cda5da8dSAndroid Build Coastguard Worker return not (inspect.ismodule(self) or (self is None)) 244*cda5da8dSAndroid Build Coastguard Worker return False 245*cda5da8dSAndroid Build Coastguard Worker 246*cda5da8dSAndroid Build Coastguard Worker 247*cda5da8dSAndroid Build Coastguard Workerdef allmethods(cl): 248*cda5da8dSAndroid Build Coastguard Worker methods = {} 249*cda5da8dSAndroid Build Coastguard Worker for key, value in inspect.getmembers(cl, inspect.isroutine): 250*cda5da8dSAndroid Build Coastguard Worker methods[key] = 1 251*cda5da8dSAndroid Build Coastguard Worker for base in cl.__bases__: 252*cda5da8dSAndroid Build Coastguard Worker methods.update(allmethods(base)) # all your base are belong to us 253*cda5da8dSAndroid Build Coastguard Worker for key in methods.keys(): 254*cda5da8dSAndroid Build Coastguard Worker methods[key] = getattr(cl, key) 255*cda5da8dSAndroid Build Coastguard Worker return methods 256*cda5da8dSAndroid Build Coastguard Worker 257*cda5da8dSAndroid Build Coastguard Workerdef _split_list(s, predicate): 258*cda5da8dSAndroid Build Coastguard Worker """Split sequence s via predicate, and return pair ([true], [false]). 259*cda5da8dSAndroid Build Coastguard Worker 260*cda5da8dSAndroid Build Coastguard Worker The return value is a 2-tuple of lists, 261*cda5da8dSAndroid Build Coastguard Worker ([x for x in s if predicate(x)], 262*cda5da8dSAndroid Build Coastguard Worker [x for x in s if not predicate(x)]) 263*cda5da8dSAndroid Build Coastguard Worker """ 264*cda5da8dSAndroid Build Coastguard Worker 265*cda5da8dSAndroid Build Coastguard Worker yes = [] 266*cda5da8dSAndroid Build Coastguard Worker no = [] 267*cda5da8dSAndroid Build Coastguard Worker for x in s: 268*cda5da8dSAndroid Build Coastguard Worker if predicate(x): 269*cda5da8dSAndroid Build Coastguard Worker yes.append(x) 270*cda5da8dSAndroid Build Coastguard Worker else: 271*cda5da8dSAndroid Build Coastguard Worker no.append(x) 272*cda5da8dSAndroid Build Coastguard Worker return yes, no 273*cda5da8dSAndroid Build Coastguard Worker 274*cda5da8dSAndroid Build Coastguard Worker_future_feature_names = set(__future__.all_feature_names) 275*cda5da8dSAndroid Build Coastguard Worker 276*cda5da8dSAndroid Build Coastguard Workerdef visiblename(name, all=None, obj=None): 277*cda5da8dSAndroid Build Coastguard Worker """Decide whether to show documentation on a variable.""" 278*cda5da8dSAndroid Build Coastguard Worker # Certain special names are redundant or internal. 279*cda5da8dSAndroid Build Coastguard Worker # XXX Remove __initializing__? 280*cda5da8dSAndroid Build Coastguard Worker if name in {'__author__', '__builtins__', '__cached__', '__credits__', 281*cda5da8dSAndroid Build Coastguard Worker '__date__', '__doc__', '__file__', '__spec__', 282*cda5da8dSAndroid Build Coastguard Worker '__loader__', '__module__', '__name__', '__package__', 283*cda5da8dSAndroid Build Coastguard Worker '__path__', '__qualname__', '__slots__', '__version__'}: 284*cda5da8dSAndroid Build Coastguard Worker return 0 285*cda5da8dSAndroid Build Coastguard Worker # Private names are hidden, but special names are displayed. 286*cda5da8dSAndroid Build Coastguard Worker if name.startswith('__') and name.endswith('__'): return 1 287*cda5da8dSAndroid Build Coastguard Worker # Namedtuples have public fields and methods with a single leading underscore 288*cda5da8dSAndroid Build Coastguard Worker if name.startswith('_') and hasattr(obj, '_fields'): 289*cda5da8dSAndroid Build Coastguard Worker return True 290*cda5da8dSAndroid Build Coastguard Worker # Ignore __future__ imports. 291*cda5da8dSAndroid Build Coastguard Worker if obj is not __future__ and name in _future_feature_names: 292*cda5da8dSAndroid Build Coastguard Worker if isinstance(getattr(obj, name, None), __future__._Feature): 293*cda5da8dSAndroid Build Coastguard Worker return False 294*cda5da8dSAndroid Build Coastguard Worker if all is not None: 295*cda5da8dSAndroid Build Coastguard Worker # only document that which the programmer exported in __all__ 296*cda5da8dSAndroid Build Coastguard Worker return name in all 297*cda5da8dSAndroid Build Coastguard Worker else: 298*cda5da8dSAndroid Build Coastguard Worker return not name.startswith('_') 299*cda5da8dSAndroid Build Coastguard Worker 300*cda5da8dSAndroid Build Coastguard Workerdef classify_class_attrs(object): 301*cda5da8dSAndroid Build Coastguard Worker """Wrap inspect.classify_class_attrs, with fixup for data descriptors.""" 302*cda5da8dSAndroid Build Coastguard Worker results = [] 303*cda5da8dSAndroid Build Coastguard Worker for (name, kind, cls, value) in inspect.classify_class_attrs(object): 304*cda5da8dSAndroid Build Coastguard Worker if inspect.isdatadescriptor(value): 305*cda5da8dSAndroid Build Coastguard Worker kind = 'data descriptor' 306*cda5da8dSAndroid Build Coastguard Worker if isinstance(value, property) and value.fset is None: 307*cda5da8dSAndroid Build Coastguard Worker kind = 'readonly property' 308*cda5da8dSAndroid Build Coastguard Worker results.append((name, kind, cls, value)) 309*cda5da8dSAndroid Build Coastguard Worker return results 310*cda5da8dSAndroid Build Coastguard Worker 311*cda5da8dSAndroid Build Coastguard Workerdef sort_attributes(attrs, object): 312*cda5da8dSAndroid Build Coastguard Worker 'Sort the attrs list in-place by _fields and then alphabetically by name' 313*cda5da8dSAndroid Build Coastguard Worker # This allows data descriptors to be ordered according 314*cda5da8dSAndroid Build Coastguard Worker # to a _fields attribute if present. 315*cda5da8dSAndroid Build Coastguard Worker fields = getattr(object, '_fields', []) 316*cda5da8dSAndroid Build Coastguard Worker try: 317*cda5da8dSAndroid Build Coastguard Worker field_order = {name : i-len(fields) for (i, name) in enumerate(fields)} 318*cda5da8dSAndroid Build Coastguard Worker except TypeError: 319*cda5da8dSAndroid Build Coastguard Worker field_order = {} 320*cda5da8dSAndroid Build Coastguard Worker keyfunc = lambda attr: (field_order.get(attr[0], 0), attr[0]) 321*cda5da8dSAndroid Build Coastguard Worker attrs.sort(key=keyfunc) 322*cda5da8dSAndroid Build Coastguard Worker 323*cda5da8dSAndroid Build Coastguard Worker# ----------------------------------------------------- module manipulation 324*cda5da8dSAndroid Build Coastguard Worker 325*cda5da8dSAndroid Build Coastguard Workerdef ispackage(path): 326*cda5da8dSAndroid Build Coastguard Worker """Guess whether a path refers to a package directory.""" 327*cda5da8dSAndroid Build Coastguard Worker if os.path.isdir(path): 328*cda5da8dSAndroid Build Coastguard Worker for ext in ('.py', '.pyc'): 329*cda5da8dSAndroid Build Coastguard Worker if os.path.isfile(os.path.join(path, '__init__' + ext)): 330*cda5da8dSAndroid Build Coastguard Worker return True 331*cda5da8dSAndroid Build Coastguard Worker return False 332*cda5da8dSAndroid Build Coastguard Worker 333*cda5da8dSAndroid Build Coastguard Workerdef source_synopsis(file): 334*cda5da8dSAndroid Build Coastguard Worker line = file.readline() 335*cda5da8dSAndroid Build Coastguard Worker while line[:1] == '#' or not line.strip(): 336*cda5da8dSAndroid Build Coastguard Worker line = file.readline() 337*cda5da8dSAndroid Build Coastguard Worker if not line: break 338*cda5da8dSAndroid Build Coastguard Worker line = line.strip() 339*cda5da8dSAndroid Build Coastguard Worker if line[:4] == 'r"""': line = line[1:] 340*cda5da8dSAndroid Build Coastguard Worker if line[:3] == '"""': 341*cda5da8dSAndroid Build Coastguard Worker line = line[3:] 342*cda5da8dSAndroid Build Coastguard Worker if line[-1:] == '\\': line = line[:-1] 343*cda5da8dSAndroid Build Coastguard Worker while not line.strip(): 344*cda5da8dSAndroid Build Coastguard Worker line = file.readline() 345*cda5da8dSAndroid Build Coastguard Worker if not line: break 346*cda5da8dSAndroid Build Coastguard Worker result = line.split('"""')[0].strip() 347*cda5da8dSAndroid Build Coastguard Worker else: result = None 348*cda5da8dSAndroid Build Coastguard Worker return result 349*cda5da8dSAndroid Build Coastguard Worker 350*cda5da8dSAndroid Build Coastguard Workerdef synopsis(filename, cache={}): 351*cda5da8dSAndroid Build Coastguard Worker """Get the one-line summary out of a module file.""" 352*cda5da8dSAndroid Build Coastguard Worker mtime = os.stat(filename).st_mtime 353*cda5da8dSAndroid Build Coastguard Worker lastupdate, result = cache.get(filename, (None, None)) 354*cda5da8dSAndroid Build Coastguard Worker if lastupdate is None or lastupdate < mtime: 355*cda5da8dSAndroid Build Coastguard Worker # Look for binary suffixes first, falling back to source. 356*cda5da8dSAndroid Build Coastguard Worker if filename.endswith(tuple(importlib.machinery.BYTECODE_SUFFIXES)): 357*cda5da8dSAndroid Build Coastguard Worker loader_cls = importlib.machinery.SourcelessFileLoader 358*cda5da8dSAndroid Build Coastguard Worker elif filename.endswith(tuple(importlib.machinery.EXTENSION_SUFFIXES)): 359*cda5da8dSAndroid Build Coastguard Worker loader_cls = importlib.machinery.ExtensionFileLoader 360*cda5da8dSAndroid Build Coastguard Worker else: 361*cda5da8dSAndroid Build Coastguard Worker loader_cls = None 362*cda5da8dSAndroid Build Coastguard Worker # Now handle the choice. 363*cda5da8dSAndroid Build Coastguard Worker if loader_cls is None: 364*cda5da8dSAndroid Build Coastguard Worker # Must be a source file. 365*cda5da8dSAndroid Build Coastguard Worker try: 366*cda5da8dSAndroid Build Coastguard Worker file = tokenize.open(filename) 367*cda5da8dSAndroid Build Coastguard Worker except OSError: 368*cda5da8dSAndroid Build Coastguard Worker # module can't be opened, so skip it 369*cda5da8dSAndroid Build Coastguard Worker return None 370*cda5da8dSAndroid Build Coastguard Worker # text modules can be directly examined 371*cda5da8dSAndroid Build Coastguard Worker with file: 372*cda5da8dSAndroid Build Coastguard Worker result = source_synopsis(file) 373*cda5da8dSAndroid Build Coastguard Worker else: 374*cda5da8dSAndroid Build Coastguard Worker # Must be a binary module, which has to be imported. 375*cda5da8dSAndroid Build Coastguard Worker loader = loader_cls('__temp__', filename) 376*cda5da8dSAndroid Build Coastguard Worker # XXX We probably don't need to pass in the loader here. 377*cda5da8dSAndroid Build Coastguard Worker spec = importlib.util.spec_from_file_location('__temp__', filename, 378*cda5da8dSAndroid Build Coastguard Worker loader=loader) 379*cda5da8dSAndroid Build Coastguard Worker try: 380*cda5da8dSAndroid Build Coastguard Worker module = importlib._bootstrap._load(spec) 381*cda5da8dSAndroid Build Coastguard Worker except: 382*cda5da8dSAndroid Build Coastguard Worker return None 383*cda5da8dSAndroid Build Coastguard Worker del sys.modules['__temp__'] 384*cda5da8dSAndroid Build Coastguard Worker result = module.__doc__.splitlines()[0] if module.__doc__ else None 385*cda5da8dSAndroid Build Coastguard Worker # Cache the result. 386*cda5da8dSAndroid Build Coastguard Worker cache[filename] = (mtime, result) 387*cda5da8dSAndroid Build Coastguard Worker return result 388*cda5da8dSAndroid Build Coastguard Worker 389*cda5da8dSAndroid Build Coastguard Workerclass ErrorDuringImport(Exception): 390*cda5da8dSAndroid Build Coastguard Worker """Errors that occurred while trying to import something to document it.""" 391*cda5da8dSAndroid Build Coastguard Worker def __init__(self, filename, exc_info): 392*cda5da8dSAndroid Build Coastguard Worker self.filename = filename 393*cda5da8dSAndroid Build Coastguard Worker self.exc, self.value, self.tb = exc_info 394*cda5da8dSAndroid Build Coastguard Worker 395*cda5da8dSAndroid Build Coastguard Worker def __str__(self): 396*cda5da8dSAndroid Build Coastguard Worker exc = self.exc.__name__ 397*cda5da8dSAndroid Build Coastguard Worker return 'problem in %s - %s: %s' % (self.filename, exc, self.value) 398*cda5da8dSAndroid Build Coastguard Worker 399*cda5da8dSAndroid Build Coastguard Workerdef importfile(path): 400*cda5da8dSAndroid Build Coastguard Worker """Import a Python source file or compiled file given its path.""" 401*cda5da8dSAndroid Build Coastguard Worker magic = importlib.util.MAGIC_NUMBER 402*cda5da8dSAndroid Build Coastguard Worker with open(path, 'rb') as file: 403*cda5da8dSAndroid Build Coastguard Worker is_bytecode = magic == file.read(len(magic)) 404*cda5da8dSAndroid Build Coastguard Worker filename = os.path.basename(path) 405*cda5da8dSAndroid Build Coastguard Worker name, ext = os.path.splitext(filename) 406*cda5da8dSAndroid Build Coastguard Worker if is_bytecode: 407*cda5da8dSAndroid Build Coastguard Worker loader = importlib._bootstrap_external.SourcelessFileLoader(name, path) 408*cda5da8dSAndroid Build Coastguard Worker else: 409*cda5da8dSAndroid Build Coastguard Worker loader = importlib._bootstrap_external.SourceFileLoader(name, path) 410*cda5da8dSAndroid Build Coastguard Worker # XXX We probably don't need to pass in the loader here. 411*cda5da8dSAndroid Build Coastguard Worker spec = importlib.util.spec_from_file_location(name, path, loader=loader) 412*cda5da8dSAndroid Build Coastguard Worker try: 413*cda5da8dSAndroid Build Coastguard Worker return importlib._bootstrap._load(spec) 414*cda5da8dSAndroid Build Coastguard Worker except: 415*cda5da8dSAndroid Build Coastguard Worker raise ErrorDuringImport(path, sys.exc_info()) 416*cda5da8dSAndroid Build Coastguard Worker 417*cda5da8dSAndroid Build Coastguard Workerdef safeimport(path, forceload=0, cache={}): 418*cda5da8dSAndroid Build Coastguard Worker """Import a module; handle errors; return None if the module isn't found. 419*cda5da8dSAndroid Build Coastguard Worker 420*cda5da8dSAndroid Build Coastguard Worker If the module *is* found but an exception occurs, it's wrapped in an 421*cda5da8dSAndroid Build Coastguard Worker ErrorDuringImport exception and reraised. Unlike __import__, if a 422*cda5da8dSAndroid Build Coastguard Worker package path is specified, the module at the end of the path is returned, 423*cda5da8dSAndroid Build Coastguard Worker not the package at the beginning. If the optional 'forceload' argument 424*cda5da8dSAndroid Build Coastguard Worker is 1, we reload the module from disk (unless it's a dynamic extension).""" 425*cda5da8dSAndroid Build Coastguard Worker try: 426*cda5da8dSAndroid Build Coastguard Worker # If forceload is 1 and the module has been previously loaded from 427*cda5da8dSAndroid Build Coastguard Worker # disk, we always have to reload the module. Checking the file's 428*cda5da8dSAndroid Build Coastguard Worker # mtime isn't good enough (e.g. the module could contain a class 429*cda5da8dSAndroid Build Coastguard Worker # that inherits from another module that has changed). 430*cda5da8dSAndroid Build Coastguard Worker if forceload and path in sys.modules: 431*cda5da8dSAndroid Build Coastguard Worker if path not in sys.builtin_module_names: 432*cda5da8dSAndroid Build Coastguard Worker # Remove the module from sys.modules and re-import to try 433*cda5da8dSAndroid Build Coastguard Worker # and avoid problems with partially loaded modules. 434*cda5da8dSAndroid Build Coastguard Worker # Also remove any submodules because they won't appear 435*cda5da8dSAndroid Build Coastguard Worker # in the newly loaded module's namespace if they're already 436*cda5da8dSAndroid Build Coastguard Worker # in sys.modules. 437*cda5da8dSAndroid Build Coastguard Worker subs = [m for m in sys.modules if m.startswith(path + '.')] 438*cda5da8dSAndroid Build Coastguard Worker for key in [path] + subs: 439*cda5da8dSAndroid Build Coastguard Worker # Prevent garbage collection. 440*cda5da8dSAndroid Build Coastguard Worker cache[key] = sys.modules[key] 441*cda5da8dSAndroid Build Coastguard Worker del sys.modules[key] 442*cda5da8dSAndroid Build Coastguard Worker module = __import__(path) 443*cda5da8dSAndroid Build Coastguard Worker except: 444*cda5da8dSAndroid Build Coastguard Worker # Did the error occur before or after the module was found? 445*cda5da8dSAndroid Build Coastguard Worker (exc, value, tb) = info = sys.exc_info() 446*cda5da8dSAndroid Build Coastguard Worker if path in sys.modules: 447*cda5da8dSAndroid Build Coastguard Worker # An error occurred while executing the imported module. 448*cda5da8dSAndroid Build Coastguard Worker raise ErrorDuringImport(sys.modules[path].__file__, info) 449*cda5da8dSAndroid Build Coastguard Worker elif exc is SyntaxError: 450*cda5da8dSAndroid Build Coastguard Worker # A SyntaxError occurred before we could execute the module. 451*cda5da8dSAndroid Build Coastguard Worker raise ErrorDuringImport(value.filename, info) 452*cda5da8dSAndroid Build Coastguard Worker elif issubclass(exc, ImportError) and value.name == path: 453*cda5da8dSAndroid Build Coastguard Worker # No such module in the path. 454*cda5da8dSAndroid Build Coastguard Worker return None 455*cda5da8dSAndroid Build Coastguard Worker else: 456*cda5da8dSAndroid Build Coastguard Worker # Some other error occurred during the importing process. 457*cda5da8dSAndroid Build Coastguard Worker raise ErrorDuringImport(path, sys.exc_info()) 458*cda5da8dSAndroid Build Coastguard Worker for part in path.split('.')[1:]: 459*cda5da8dSAndroid Build Coastguard Worker try: module = getattr(module, part) 460*cda5da8dSAndroid Build Coastguard Worker except AttributeError: return None 461*cda5da8dSAndroid Build Coastguard Worker return module 462*cda5da8dSAndroid Build Coastguard Worker 463*cda5da8dSAndroid Build Coastguard Worker# ---------------------------------------------------- formatter base class 464*cda5da8dSAndroid Build Coastguard Worker 465*cda5da8dSAndroid Build Coastguard Workerclass Doc: 466*cda5da8dSAndroid Build Coastguard Worker 467*cda5da8dSAndroid Build Coastguard Worker PYTHONDOCS = os.environ.get("PYTHONDOCS", 468*cda5da8dSAndroid Build Coastguard Worker "https://docs.python.org/%d.%d/library" 469*cda5da8dSAndroid Build Coastguard Worker % sys.version_info[:2]) 470*cda5da8dSAndroid Build Coastguard Worker 471*cda5da8dSAndroid Build Coastguard Worker def document(self, object, name=None, *args): 472*cda5da8dSAndroid Build Coastguard Worker """Generate documentation for an object.""" 473*cda5da8dSAndroid Build Coastguard Worker args = (object, name) + args 474*cda5da8dSAndroid Build Coastguard Worker # 'try' clause is to attempt to handle the possibility that inspect 475*cda5da8dSAndroid Build Coastguard Worker # identifies something in a way that pydoc itself has issues handling; 476*cda5da8dSAndroid Build Coastguard Worker # think 'super' and how it is a descriptor (which raises the exception 477*cda5da8dSAndroid Build Coastguard Worker # by lacking a __name__ attribute) and an instance. 478*cda5da8dSAndroid Build Coastguard Worker try: 479*cda5da8dSAndroid Build Coastguard Worker if inspect.ismodule(object): return self.docmodule(*args) 480*cda5da8dSAndroid Build Coastguard Worker if inspect.isclass(object): return self.docclass(*args) 481*cda5da8dSAndroid Build Coastguard Worker if inspect.isroutine(object): return self.docroutine(*args) 482*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 483*cda5da8dSAndroid Build Coastguard Worker pass 484*cda5da8dSAndroid Build Coastguard Worker if inspect.isdatadescriptor(object): return self.docdata(*args) 485*cda5da8dSAndroid Build Coastguard Worker return self.docother(*args) 486*cda5da8dSAndroid Build Coastguard Worker 487*cda5da8dSAndroid Build Coastguard Worker def fail(self, object, name=None, *args): 488*cda5da8dSAndroid Build Coastguard Worker """Raise an exception for unimplemented types.""" 489*cda5da8dSAndroid Build Coastguard Worker message = "don't know how to document object%s of type %s" % ( 490*cda5da8dSAndroid Build Coastguard Worker name and ' ' + repr(name), type(object).__name__) 491*cda5da8dSAndroid Build Coastguard Worker raise TypeError(message) 492*cda5da8dSAndroid Build Coastguard Worker 493*cda5da8dSAndroid Build Coastguard Worker docmodule = docclass = docroutine = docother = docproperty = docdata = fail 494*cda5da8dSAndroid Build Coastguard Worker 495*cda5da8dSAndroid Build Coastguard Worker def getdocloc(self, object, basedir=sysconfig.get_path('stdlib')): 496*cda5da8dSAndroid Build Coastguard Worker """Return the location of module docs or None""" 497*cda5da8dSAndroid Build Coastguard Worker 498*cda5da8dSAndroid Build Coastguard Worker try: 499*cda5da8dSAndroid Build Coastguard Worker file = inspect.getabsfile(object) 500*cda5da8dSAndroid Build Coastguard Worker except TypeError: 501*cda5da8dSAndroid Build Coastguard Worker file = '(built-in)' 502*cda5da8dSAndroid Build Coastguard Worker 503*cda5da8dSAndroid Build Coastguard Worker docloc = os.environ.get("PYTHONDOCS", self.PYTHONDOCS) 504*cda5da8dSAndroid Build Coastguard Worker 505*cda5da8dSAndroid Build Coastguard Worker basedir = os.path.normcase(basedir) 506*cda5da8dSAndroid Build Coastguard Worker if (isinstance(object, type(os)) and 507*cda5da8dSAndroid Build Coastguard Worker (object.__name__ in ('errno', 'exceptions', 'gc', 'imp', 508*cda5da8dSAndroid Build Coastguard Worker 'marshal', 'posix', 'signal', 'sys', 509*cda5da8dSAndroid Build Coastguard Worker '_thread', 'zipimport') or 510*cda5da8dSAndroid Build Coastguard Worker (file.startswith(basedir) and 511*cda5da8dSAndroid Build Coastguard Worker not file.startswith(os.path.join(basedir, 'site-packages')))) and 512*cda5da8dSAndroid Build Coastguard Worker object.__name__ not in ('xml.etree', 'test.pydoc_mod')): 513*cda5da8dSAndroid Build Coastguard Worker if docloc.startswith(("http://", "https://")): 514*cda5da8dSAndroid Build Coastguard Worker docloc = "{}/{}.html".format(docloc.rstrip("/"), object.__name__.lower()) 515*cda5da8dSAndroid Build Coastguard Worker else: 516*cda5da8dSAndroid Build Coastguard Worker docloc = os.path.join(docloc, object.__name__.lower() + ".html") 517*cda5da8dSAndroid Build Coastguard Worker else: 518*cda5da8dSAndroid Build Coastguard Worker docloc = None 519*cda5da8dSAndroid Build Coastguard Worker return docloc 520*cda5da8dSAndroid Build Coastguard Worker 521*cda5da8dSAndroid Build Coastguard Worker# -------------------------------------------- HTML documentation generator 522*cda5da8dSAndroid Build Coastguard Worker 523*cda5da8dSAndroid Build Coastguard Workerclass HTMLRepr(Repr): 524*cda5da8dSAndroid Build Coastguard Worker """Class for safely making an HTML representation of a Python object.""" 525*cda5da8dSAndroid Build Coastguard Worker def __init__(self): 526*cda5da8dSAndroid Build Coastguard Worker Repr.__init__(self) 527*cda5da8dSAndroid Build Coastguard Worker self.maxlist = self.maxtuple = 20 528*cda5da8dSAndroid Build Coastguard Worker self.maxdict = 10 529*cda5da8dSAndroid Build Coastguard Worker self.maxstring = self.maxother = 100 530*cda5da8dSAndroid Build Coastguard Worker 531*cda5da8dSAndroid Build Coastguard Worker def escape(self, text): 532*cda5da8dSAndroid Build Coastguard Worker return replace(text, '&', '&', '<', '<', '>', '>') 533*cda5da8dSAndroid Build Coastguard Worker 534*cda5da8dSAndroid Build Coastguard Worker def repr(self, object): 535*cda5da8dSAndroid Build Coastguard Worker return Repr.repr(self, object) 536*cda5da8dSAndroid Build Coastguard Worker 537*cda5da8dSAndroid Build Coastguard Worker def repr1(self, x, level): 538*cda5da8dSAndroid Build Coastguard Worker if hasattr(type(x), '__name__'): 539*cda5da8dSAndroid Build Coastguard Worker methodname = 'repr_' + '_'.join(type(x).__name__.split()) 540*cda5da8dSAndroid Build Coastguard Worker if hasattr(self, methodname): 541*cda5da8dSAndroid Build Coastguard Worker return getattr(self, methodname)(x, level) 542*cda5da8dSAndroid Build Coastguard Worker return self.escape(cram(stripid(repr(x)), self.maxother)) 543*cda5da8dSAndroid Build Coastguard Worker 544*cda5da8dSAndroid Build Coastguard Worker def repr_string(self, x, level): 545*cda5da8dSAndroid Build Coastguard Worker test = cram(x, self.maxstring) 546*cda5da8dSAndroid Build Coastguard Worker testrepr = repr(test) 547*cda5da8dSAndroid Build Coastguard Worker if '\\' in test and '\\' not in replace(testrepr, r'\\', ''): 548*cda5da8dSAndroid Build Coastguard Worker # Backslashes are only literal in the string and are never 549*cda5da8dSAndroid Build Coastguard Worker # needed to make any special characters, so show a raw string. 550*cda5da8dSAndroid Build Coastguard Worker return 'r' + testrepr[0] + self.escape(test) + testrepr[0] 551*cda5da8dSAndroid Build Coastguard Worker return re.sub(r'((\\[\\abfnrtv\'"]|\\[0-9]..|\\x..|\\u....)+)', 552*cda5da8dSAndroid Build Coastguard Worker r'<span class="repr">\1</span>', 553*cda5da8dSAndroid Build Coastguard Worker self.escape(testrepr)) 554*cda5da8dSAndroid Build Coastguard Worker 555*cda5da8dSAndroid Build Coastguard Worker repr_str = repr_string 556*cda5da8dSAndroid Build Coastguard Worker 557*cda5da8dSAndroid Build Coastguard Worker def repr_instance(self, x, level): 558*cda5da8dSAndroid Build Coastguard Worker try: 559*cda5da8dSAndroid Build Coastguard Worker return self.escape(cram(stripid(repr(x)), self.maxstring)) 560*cda5da8dSAndroid Build Coastguard Worker except: 561*cda5da8dSAndroid Build Coastguard Worker return self.escape('<%s instance>' % x.__class__.__name__) 562*cda5da8dSAndroid Build Coastguard Worker 563*cda5da8dSAndroid Build Coastguard Worker repr_unicode = repr_string 564*cda5da8dSAndroid Build Coastguard Worker 565*cda5da8dSAndroid Build Coastguard Workerclass HTMLDoc(Doc): 566*cda5da8dSAndroid Build Coastguard Worker """Formatter class for HTML documentation.""" 567*cda5da8dSAndroid Build Coastguard Worker 568*cda5da8dSAndroid Build Coastguard Worker # ------------------------------------------- HTML formatting utilities 569*cda5da8dSAndroid Build Coastguard Worker 570*cda5da8dSAndroid Build Coastguard Worker _repr_instance = HTMLRepr() 571*cda5da8dSAndroid Build Coastguard Worker repr = _repr_instance.repr 572*cda5da8dSAndroid Build Coastguard Worker escape = _repr_instance.escape 573*cda5da8dSAndroid Build Coastguard Worker 574*cda5da8dSAndroid Build Coastguard Worker def page(self, title, contents): 575*cda5da8dSAndroid Build Coastguard Worker """Format an HTML page.""" 576*cda5da8dSAndroid Build Coastguard Worker return '''\ 577*cda5da8dSAndroid Build Coastguard Worker<!DOCTYPE html> 578*cda5da8dSAndroid Build Coastguard Worker<html lang="en"> 579*cda5da8dSAndroid Build Coastguard Worker<head> 580*cda5da8dSAndroid Build Coastguard Worker<meta charset="utf-8"> 581*cda5da8dSAndroid Build Coastguard Worker<title>Python: %s</title> 582*cda5da8dSAndroid Build Coastguard Worker</head><body> 583*cda5da8dSAndroid Build Coastguard Worker%s 584*cda5da8dSAndroid Build Coastguard Worker</body></html>''' % (title, contents) 585*cda5da8dSAndroid Build Coastguard Worker 586*cda5da8dSAndroid Build Coastguard Worker def heading(self, title, extras=''): 587*cda5da8dSAndroid Build Coastguard Worker """Format a page heading.""" 588*cda5da8dSAndroid Build Coastguard Worker return ''' 589*cda5da8dSAndroid Build Coastguard Worker<table class="heading"> 590*cda5da8dSAndroid Build Coastguard Worker<tr class="heading-text decor"> 591*cda5da8dSAndroid Build Coastguard Worker<td class="title"> <br>%s</td> 592*cda5da8dSAndroid Build Coastguard Worker<td class="extra">%s</td></tr></table> 593*cda5da8dSAndroid Build Coastguard Worker ''' % (title, extras or ' ') 594*cda5da8dSAndroid Build Coastguard Worker 595*cda5da8dSAndroid Build Coastguard Worker def section(self, title, cls, contents, width=6, 596*cda5da8dSAndroid Build Coastguard Worker prelude='', marginalia=None, gap=' '): 597*cda5da8dSAndroid Build Coastguard Worker """Format a section with a heading.""" 598*cda5da8dSAndroid Build Coastguard Worker if marginalia is None: 599*cda5da8dSAndroid Build Coastguard Worker marginalia = '<span class="code">' + ' ' * width + '</span>' 600*cda5da8dSAndroid Build Coastguard Worker result = '''<p> 601*cda5da8dSAndroid Build Coastguard Worker<table class="section"> 602*cda5da8dSAndroid Build Coastguard Worker<tr class="decor %s-decor heading-text"> 603*cda5da8dSAndroid Build Coastguard Worker<td class="section-title" colspan=3> <br>%s</td></tr> 604*cda5da8dSAndroid Build Coastguard Worker ''' % (cls, title) 605*cda5da8dSAndroid Build Coastguard Worker if prelude: 606*cda5da8dSAndroid Build Coastguard Worker result = result + ''' 607*cda5da8dSAndroid Build Coastguard Worker<tr><td class="decor %s-decor" rowspan=2>%s</td> 608*cda5da8dSAndroid Build Coastguard Worker<td class="decor %s-decor" colspan=2>%s</td></tr> 609*cda5da8dSAndroid Build Coastguard Worker<tr><td>%s</td>''' % (cls, marginalia, cls, prelude, gap) 610*cda5da8dSAndroid Build Coastguard Worker else: 611*cda5da8dSAndroid Build Coastguard Worker result = result + ''' 612*cda5da8dSAndroid Build Coastguard Worker<tr><td class="decor %s-decor">%s</td><td>%s</td>''' % (cls, marginalia, gap) 613*cda5da8dSAndroid Build Coastguard Worker 614*cda5da8dSAndroid Build Coastguard Worker return result + '\n<td class="singlecolumn">%s</td></tr></table>' % contents 615*cda5da8dSAndroid Build Coastguard Worker 616*cda5da8dSAndroid Build Coastguard Worker def bigsection(self, title, *args): 617*cda5da8dSAndroid Build Coastguard Worker """Format a section with a big heading.""" 618*cda5da8dSAndroid Build Coastguard Worker title = '<strong class="bigsection">%s</strong>' % title 619*cda5da8dSAndroid Build Coastguard Worker return self.section(title, *args) 620*cda5da8dSAndroid Build Coastguard Worker 621*cda5da8dSAndroid Build Coastguard Worker def preformat(self, text): 622*cda5da8dSAndroid Build Coastguard Worker """Format literal preformatted text.""" 623*cda5da8dSAndroid Build Coastguard Worker text = self.escape(text.expandtabs()) 624*cda5da8dSAndroid Build Coastguard Worker return replace(text, '\n\n', '\n \n', '\n\n', '\n \n', 625*cda5da8dSAndroid Build Coastguard Worker ' ', ' ', '\n', '<br>\n') 626*cda5da8dSAndroid Build Coastguard Worker 627*cda5da8dSAndroid Build Coastguard Worker def multicolumn(self, list, format): 628*cda5da8dSAndroid Build Coastguard Worker """Format a list of items into a multi-column list.""" 629*cda5da8dSAndroid Build Coastguard Worker result = '' 630*cda5da8dSAndroid Build Coastguard Worker rows = (len(list) + 3) // 4 631*cda5da8dSAndroid Build Coastguard Worker for col in range(4): 632*cda5da8dSAndroid Build Coastguard Worker result = result + '<td class="multicolumn">' 633*cda5da8dSAndroid Build Coastguard Worker for i in range(rows*col, rows*col+rows): 634*cda5da8dSAndroid Build Coastguard Worker if i < len(list): 635*cda5da8dSAndroid Build Coastguard Worker result = result + format(list[i]) + '<br>\n' 636*cda5da8dSAndroid Build Coastguard Worker result = result + '</td>' 637*cda5da8dSAndroid Build Coastguard Worker return '<table><tr>%s</tr></table>' % result 638*cda5da8dSAndroid Build Coastguard Worker 639*cda5da8dSAndroid Build Coastguard Worker def grey(self, text): return '<span class="grey">%s</span>' % text 640*cda5da8dSAndroid Build Coastguard Worker 641*cda5da8dSAndroid Build Coastguard Worker def namelink(self, name, *dicts): 642*cda5da8dSAndroid Build Coastguard Worker """Make a link for an identifier, given name-to-URL mappings.""" 643*cda5da8dSAndroid Build Coastguard Worker for dict in dicts: 644*cda5da8dSAndroid Build Coastguard Worker if name in dict: 645*cda5da8dSAndroid Build Coastguard Worker return '<a href="%s">%s</a>' % (dict[name], name) 646*cda5da8dSAndroid Build Coastguard Worker return name 647*cda5da8dSAndroid Build Coastguard Worker 648*cda5da8dSAndroid Build Coastguard Worker def classlink(self, object, modname): 649*cda5da8dSAndroid Build Coastguard Worker """Make a link for a class.""" 650*cda5da8dSAndroid Build Coastguard Worker name, module = object.__name__, sys.modules.get(object.__module__) 651*cda5da8dSAndroid Build Coastguard Worker if hasattr(module, name) and getattr(module, name) is object: 652*cda5da8dSAndroid Build Coastguard Worker return '<a href="%s.html#%s">%s</a>' % ( 653*cda5da8dSAndroid Build Coastguard Worker module.__name__, name, classname(object, modname)) 654*cda5da8dSAndroid Build Coastguard Worker return classname(object, modname) 655*cda5da8dSAndroid Build Coastguard Worker 656*cda5da8dSAndroid Build Coastguard Worker def modulelink(self, object): 657*cda5da8dSAndroid Build Coastguard Worker """Make a link for a module.""" 658*cda5da8dSAndroid Build Coastguard Worker return '<a href="%s.html">%s</a>' % (object.__name__, object.__name__) 659*cda5da8dSAndroid Build Coastguard Worker 660*cda5da8dSAndroid Build Coastguard Worker def modpkglink(self, modpkginfo): 661*cda5da8dSAndroid Build Coastguard Worker """Make a link for a module or package to display in an index.""" 662*cda5da8dSAndroid Build Coastguard Worker name, path, ispackage, shadowed = modpkginfo 663*cda5da8dSAndroid Build Coastguard Worker if shadowed: 664*cda5da8dSAndroid Build Coastguard Worker return self.grey(name) 665*cda5da8dSAndroid Build Coastguard Worker if path: 666*cda5da8dSAndroid Build Coastguard Worker url = '%s.%s.html' % (path, name) 667*cda5da8dSAndroid Build Coastguard Worker else: 668*cda5da8dSAndroid Build Coastguard Worker url = '%s.html' % name 669*cda5da8dSAndroid Build Coastguard Worker if ispackage: 670*cda5da8dSAndroid Build Coastguard Worker text = '<strong>%s</strong> (package)' % name 671*cda5da8dSAndroid Build Coastguard Worker else: 672*cda5da8dSAndroid Build Coastguard Worker text = name 673*cda5da8dSAndroid Build Coastguard Worker return '<a href="%s">%s</a>' % (url, text) 674*cda5da8dSAndroid Build Coastguard Worker 675*cda5da8dSAndroid Build Coastguard Worker def filelink(self, url, path): 676*cda5da8dSAndroid Build Coastguard Worker """Make a link to source file.""" 677*cda5da8dSAndroid Build Coastguard Worker return '<a href="file:%s">%s</a>' % (url, path) 678*cda5da8dSAndroid Build Coastguard Worker 679*cda5da8dSAndroid Build Coastguard Worker def markup(self, text, escape=None, funcs={}, classes={}, methods={}): 680*cda5da8dSAndroid Build Coastguard Worker """Mark up some plain text, given a context of symbols to look for. 681*cda5da8dSAndroid Build Coastguard Worker Each context dictionary maps object names to anchor names.""" 682*cda5da8dSAndroid Build Coastguard Worker escape = escape or self.escape 683*cda5da8dSAndroid Build Coastguard Worker results = [] 684*cda5da8dSAndroid Build Coastguard Worker here = 0 685*cda5da8dSAndroid Build Coastguard Worker pattern = re.compile(r'\b((http|https|ftp)://\S+[\w/]|' 686*cda5da8dSAndroid Build Coastguard Worker r'RFC[- ]?(\d+)|' 687*cda5da8dSAndroid Build Coastguard Worker r'PEP[- ]?(\d+)|' 688*cda5da8dSAndroid Build Coastguard Worker r'(self\.)?(\w+))') 689*cda5da8dSAndroid Build Coastguard Worker while True: 690*cda5da8dSAndroid Build Coastguard Worker match = pattern.search(text, here) 691*cda5da8dSAndroid Build Coastguard Worker if not match: break 692*cda5da8dSAndroid Build Coastguard Worker start, end = match.span() 693*cda5da8dSAndroid Build Coastguard Worker results.append(escape(text[here:start])) 694*cda5da8dSAndroid Build Coastguard Worker 695*cda5da8dSAndroid Build Coastguard Worker all, scheme, rfc, pep, selfdot, name = match.groups() 696*cda5da8dSAndroid Build Coastguard Worker if scheme: 697*cda5da8dSAndroid Build Coastguard Worker url = escape(all).replace('"', '"') 698*cda5da8dSAndroid Build Coastguard Worker results.append('<a href="%s">%s</a>' % (url, url)) 699*cda5da8dSAndroid Build Coastguard Worker elif rfc: 700*cda5da8dSAndroid Build Coastguard Worker url = 'https://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc) 701*cda5da8dSAndroid Build Coastguard Worker results.append('<a href="%s">%s</a>' % (url, escape(all))) 702*cda5da8dSAndroid Build Coastguard Worker elif pep: 703*cda5da8dSAndroid Build Coastguard Worker url = 'https://peps.python.org/pep-%04d/' % int(pep) 704*cda5da8dSAndroid Build Coastguard Worker results.append('<a href="%s">%s</a>' % (url, escape(all))) 705*cda5da8dSAndroid Build Coastguard Worker elif selfdot: 706*cda5da8dSAndroid Build Coastguard Worker # Create a link for methods like 'self.method(...)' 707*cda5da8dSAndroid Build Coastguard Worker # and use <strong> for attributes like 'self.attr' 708*cda5da8dSAndroid Build Coastguard Worker if text[end:end+1] == '(': 709*cda5da8dSAndroid Build Coastguard Worker results.append('self.' + self.namelink(name, methods)) 710*cda5da8dSAndroid Build Coastguard Worker else: 711*cda5da8dSAndroid Build Coastguard Worker results.append('self.<strong>%s</strong>' % name) 712*cda5da8dSAndroid Build Coastguard Worker elif text[end:end+1] == '(': 713*cda5da8dSAndroid Build Coastguard Worker results.append(self.namelink(name, methods, funcs, classes)) 714*cda5da8dSAndroid Build Coastguard Worker else: 715*cda5da8dSAndroid Build Coastguard Worker results.append(self.namelink(name, classes)) 716*cda5da8dSAndroid Build Coastguard Worker here = end 717*cda5da8dSAndroid Build Coastguard Worker results.append(escape(text[here:])) 718*cda5da8dSAndroid Build Coastguard Worker return ''.join(results) 719*cda5da8dSAndroid Build Coastguard Worker 720*cda5da8dSAndroid Build Coastguard Worker # ---------------------------------------------- type-specific routines 721*cda5da8dSAndroid Build Coastguard Worker 722*cda5da8dSAndroid Build Coastguard Worker def formattree(self, tree, modname, parent=None): 723*cda5da8dSAndroid Build Coastguard Worker """Produce HTML for a class tree as given by inspect.getclasstree().""" 724*cda5da8dSAndroid Build Coastguard Worker result = '' 725*cda5da8dSAndroid Build Coastguard Worker for entry in tree: 726*cda5da8dSAndroid Build Coastguard Worker if type(entry) is type(()): 727*cda5da8dSAndroid Build Coastguard Worker c, bases = entry 728*cda5da8dSAndroid Build Coastguard Worker result = result + '<dt class="heading-text">' 729*cda5da8dSAndroid Build Coastguard Worker result = result + self.classlink(c, modname) 730*cda5da8dSAndroid Build Coastguard Worker if bases and bases != (parent,): 731*cda5da8dSAndroid Build Coastguard Worker parents = [] 732*cda5da8dSAndroid Build Coastguard Worker for base in bases: 733*cda5da8dSAndroid Build Coastguard Worker parents.append(self.classlink(base, modname)) 734*cda5da8dSAndroid Build Coastguard Worker result = result + '(' + ', '.join(parents) + ')' 735*cda5da8dSAndroid Build Coastguard Worker result = result + '\n</dt>' 736*cda5da8dSAndroid Build Coastguard Worker elif type(entry) is type([]): 737*cda5da8dSAndroid Build Coastguard Worker result = result + '<dd>\n%s</dd>\n' % self.formattree( 738*cda5da8dSAndroid Build Coastguard Worker entry, modname, c) 739*cda5da8dSAndroid Build Coastguard Worker return '<dl>\n%s</dl>\n' % result 740*cda5da8dSAndroid Build Coastguard Worker 741*cda5da8dSAndroid Build Coastguard Worker def docmodule(self, object, name=None, mod=None, *ignored): 742*cda5da8dSAndroid Build Coastguard Worker """Produce HTML documentation for a module object.""" 743*cda5da8dSAndroid Build Coastguard Worker name = object.__name__ # ignore the passed-in name 744*cda5da8dSAndroid Build Coastguard Worker try: 745*cda5da8dSAndroid Build Coastguard Worker all = object.__all__ 746*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 747*cda5da8dSAndroid Build Coastguard Worker all = None 748*cda5da8dSAndroid Build Coastguard Worker parts = name.split('.') 749*cda5da8dSAndroid Build Coastguard Worker links = [] 750*cda5da8dSAndroid Build Coastguard Worker for i in range(len(parts)-1): 751*cda5da8dSAndroid Build Coastguard Worker links.append( 752*cda5da8dSAndroid Build Coastguard Worker '<a href="%s.html" class="white">%s</a>' % 753*cda5da8dSAndroid Build Coastguard Worker ('.'.join(parts[:i+1]), parts[i])) 754*cda5da8dSAndroid Build Coastguard Worker linkedname = '.'.join(links + parts[-1:]) 755*cda5da8dSAndroid Build Coastguard Worker head = '<strong class="title">%s</strong>' % linkedname 756*cda5da8dSAndroid Build Coastguard Worker try: 757*cda5da8dSAndroid Build Coastguard Worker path = inspect.getabsfile(object) 758*cda5da8dSAndroid Build Coastguard Worker url = urllib.parse.quote(path) 759*cda5da8dSAndroid Build Coastguard Worker filelink = self.filelink(url, path) 760*cda5da8dSAndroid Build Coastguard Worker except TypeError: 761*cda5da8dSAndroid Build Coastguard Worker filelink = '(built-in)' 762*cda5da8dSAndroid Build Coastguard Worker info = [] 763*cda5da8dSAndroid Build Coastguard Worker if hasattr(object, '__version__'): 764*cda5da8dSAndroid Build Coastguard Worker version = str(object.__version__) 765*cda5da8dSAndroid Build Coastguard Worker if version[:11] == '$' + 'Revision: ' and version[-1:] == '$': 766*cda5da8dSAndroid Build Coastguard Worker version = version[11:-1].strip() 767*cda5da8dSAndroid Build Coastguard Worker info.append('version %s' % self.escape(version)) 768*cda5da8dSAndroid Build Coastguard Worker if hasattr(object, '__date__'): 769*cda5da8dSAndroid Build Coastguard Worker info.append(self.escape(str(object.__date__))) 770*cda5da8dSAndroid Build Coastguard Worker if info: 771*cda5da8dSAndroid Build Coastguard Worker head = head + ' (%s)' % ', '.join(info) 772*cda5da8dSAndroid Build Coastguard Worker docloc = self.getdocloc(object) 773*cda5da8dSAndroid Build Coastguard Worker if docloc is not None: 774*cda5da8dSAndroid Build Coastguard Worker docloc = '<br><a href="%(docloc)s">Module Reference</a>' % locals() 775*cda5da8dSAndroid Build Coastguard Worker else: 776*cda5da8dSAndroid Build Coastguard Worker docloc = '' 777*cda5da8dSAndroid Build Coastguard Worker result = self.heading(head, '<a href=".">index</a><br>' + filelink + docloc) 778*cda5da8dSAndroid Build Coastguard Worker 779*cda5da8dSAndroid Build Coastguard Worker modules = inspect.getmembers(object, inspect.ismodule) 780*cda5da8dSAndroid Build Coastguard Worker 781*cda5da8dSAndroid Build Coastguard Worker classes, cdict = [], {} 782*cda5da8dSAndroid Build Coastguard Worker for key, value in inspect.getmembers(object, inspect.isclass): 783*cda5da8dSAndroid Build Coastguard Worker # if __all__ exists, believe it. Otherwise use old heuristic. 784*cda5da8dSAndroid Build Coastguard Worker if (all is not None or 785*cda5da8dSAndroid Build Coastguard Worker (inspect.getmodule(value) or object) is object): 786*cda5da8dSAndroid Build Coastguard Worker if visiblename(key, all, object): 787*cda5da8dSAndroid Build Coastguard Worker classes.append((key, value)) 788*cda5da8dSAndroid Build Coastguard Worker cdict[key] = cdict[value] = '#' + key 789*cda5da8dSAndroid Build Coastguard Worker for key, value in classes: 790*cda5da8dSAndroid Build Coastguard Worker for base in value.__bases__: 791*cda5da8dSAndroid Build Coastguard Worker key, modname = base.__name__, base.__module__ 792*cda5da8dSAndroid Build Coastguard Worker module = sys.modules.get(modname) 793*cda5da8dSAndroid Build Coastguard Worker if modname != name and module and hasattr(module, key): 794*cda5da8dSAndroid Build Coastguard Worker if getattr(module, key) is base: 795*cda5da8dSAndroid Build Coastguard Worker if not key in cdict: 796*cda5da8dSAndroid Build Coastguard Worker cdict[key] = cdict[base] = modname + '.html#' + key 797*cda5da8dSAndroid Build Coastguard Worker funcs, fdict = [], {} 798*cda5da8dSAndroid Build Coastguard Worker for key, value in inspect.getmembers(object, inspect.isroutine): 799*cda5da8dSAndroid Build Coastguard Worker # if __all__ exists, believe it. Otherwise use old heuristic. 800*cda5da8dSAndroid Build Coastguard Worker if (all is not None or 801*cda5da8dSAndroid Build Coastguard Worker inspect.isbuiltin(value) or inspect.getmodule(value) is object): 802*cda5da8dSAndroid Build Coastguard Worker if visiblename(key, all, object): 803*cda5da8dSAndroid Build Coastguard Worker funcs.append((key, value)) 804*cda5da8dSAndroid Build Coastguard Worker fdict[key] = '#-' + key 805*cda5da8dSAndroid Build Coastguard Worker if inspect.isfunction(value): fdict[value] = fdict[key] 806*cda5da8dSAndroid Build Coastguard Worker data = [] 807*cda5da8dSAndroid Build Coastguard Worker for key, value in inspect.getmembers(object, isdata): 808*cda5da8dSAndroid Build Coastguard Worker if visiblename(key, all, object): 809*cda5da8dSAndroid Build Coastguard Worker data.append((key, value)) 810*cda5da8dSAndroid Build Coastguard Worker 811*cda5da8dSAndroid Build Coastguard Worker doc = self.markup(getdoc(object), self.preformat, fdict, cdict) 812*cda5da8dSAndroid Build Coastguard Worker doc = doc and '<span class="code">%s</span>' % doc 813*cda5da8dSAndroid Build Coastguard Worker result = result + '<p>%s</p>\n' % doc 814*cda5da8dSAndroid Build Coastguard Worker 815*cda5da8dSAndroid Build Coastguard Worker if hasattr(object, '__path__'): 816*cda5da8dSAndroid Build Coastguard Worker modpkgs = [] 817*cda5da8dSAndroid Build Coastguard Worker for importer, modname, ispkg in pkgutil.iter_modules(object.__path__): 818*cda5da8dSAndroid Build Coastguard Worker modpkgs.append((modname, name, ispkg, 0)) 819*cda5da8dSAndroid Build Coastguard Worker modpkgs.sort() 820*cda5da8dSAndroid Build Coastguard Worker contents = self.multicolumn(modpkgs, self.modpkglink) 821*cda5da8dSAndroid Build Coastguard Worker result = result + self.bigsection( 822*cda5da8dSAndroid Build Coastguard Worker 'Package Contents', 'pkg-content', contents) 823*cda5da8dSAndroid Build Coastguard Worker elif modules: 824*cda5da8dSAndroid Build Coastguard Worker contents = self.multicolumn( 825*cda5da8dSAndroid Build Coastguard Worker modules, lambda t: self.modulelink(t[1])) 826*cda5da8dSAndroid Build Coastguard Worker result = result + self.bigsection( 827*cda5da8dSAndroid Build Coastguard Worker 'Modules', 'pkg-content', contents) 828*cda5da8dSAndroid Build Coastguard Worker 829*cda5da8dSAndroid Build Coastguard Worker if classes: 830*cda5da8dSAndroid Build Coastguard Worker classlist = [value for (key, value) in classes] 831*cda5da8dSAndroid Build Coastguard Worker contents = [ 832*cda5da8dSAndroid Build Coastguard Worker self.formattree(inspect.getclasstree(classlist, 1), name)] 833*cda5da8dSAndroid Build Coastguard Worker for key, value in classes: 834*cda5da8dSAndroid Build Coastguard Worker contents.append(self.document(value, key, name, fdict, cdict)) 835*cda5da8dSAndroid Build Coastguard Worker result = result + self.bigsection( 836*cda5da8dSAndroid Build Coastguard Worker 'Classes', 'index', ' '.join(contents)) 837*cda5da8dSAndroid Build Coastguard Worker if funcs: 838*cda5da8dSAndroid Build Coastguard Worker contents = [] 839*cda5da8dSAndroid Build Coastguard Worker for key, value in funcs: 840*cda5da8dSAndroid Build Coastguard Worker contents.append(self.document(value, key, name, fdict, cdict)) 841*cda5da8dSAndroid Build Coastguard Worker result = result + self.bigsection( 842*cda5da8dSAndroid Build Coastguard Worker 'Functions', 'functions', ' '.join(contents)) 843*cda5da8dSAndroid Build Coastguard Worker if data: 844*cda5da8dSAndroid Build Coastguard Worker contents = [] 845*cda5da8dSAndroid Build Coastguard Worker for key, value in data: 846*cda5da8dSAndroid Build Coastguard Worker contents.append(self.document(value, key)) 847*cda5da8dSAndroid Build Coastguard Worker result = result + self.bigsection( 848*cda5da8dSAndroid Build Coastguard Worker 'Data', 'data', '<br>\n'.join(contents)) 849*cda5da8dSAndroid Build Coastguard Worker if hasattr(object, '__author__'): 850*cda5da8dSAndroid Build Coastguard Worker contents = self.markup(str(object.__author__), self.preformat) 851*cda5da8dSAndroid Build Coastguard Worker result = result + self.bigsection('Author', 'author', contents) 852*cda5da8dSAndroid Build Coastguard Worker if hasattr(object, '__credits__'): 853*cda5da8dSAndroid Build Coastguard Worker contents = self.markup(str(object.__credits__), self.preformat) 854*cda5da8dSAndroid Build Coastguard Worker result = result + self.bigsection('Credits', 'credits', contents) 855*cda5da8dSAndroid Build Coastguard Worker 856*cda5da8dSAndroid Build Coastguard Worker return result 857*cda5da8dSAndroid Build Coastguard Worker 858*cda5da8dSAndroid Build Coastguard Worker def docclass(self, object, name=None, mod=None, funcs={}, classes={}, 859*cda5da8dSAndroid Build Coastguard Worker *ignored): 860*cda5da8dSAndroid Build Coastguard Worker """Produce HTML documentation for a class object.""" 861*cda5da8dSAndroid Build Coastguard Worker realname = object.__name__ 862*cda5da8dSAndroid Build Coastguard Worker name = name or realname 863*cda5da8dSAndroid Build Coastguard Worker bases = object.__bases__ 864*cda5da8dSAndroid Build Coastguard Worker 865*cda5da8dSAndroid Build Coastguard Worker contents = [] 866*cda5da8dSAndroid Build Coastguard Worker push = contents.append 867*cda5da8dSAndroid Build Coastguard Worker 868*cda5da8dSAndroid Build Coastguard Worker # Cute little class to pump out a horizontal rule between sections. 869*cda5da8dSAndroid Build Coastguard Worker class HorizontalRule: 870*cda5da8dSAndroid Build Coastguard Worker def __init__(self): 871*cda5da8dSAndroid Build Coastguard Worker self.needone = 0 872*cda5da8dSAndroid Build Coastguard Worker def maybe(self): 873*cda5da8dSAndroid Build Coastguard Worker if self.needone: 874*cda5da8dSAndroid Build Coastguard Worker push('<hr>\n') 875*cda5da8dSAndroid Build Coastguard Worker self.needone = 1 876*cda5da8dSAndroid Build Coastguard Worker hr = HorizontalRule() 877*cda5da8dSAndroid Build Coastguard Worker 878*cda5da8dSAndroid Build Coastguard Worker # List the mro, if non-trivial. 879*cda5da8dSAndroid Build Coastguard Worker mro = deque(inspect.getmro(object)) 880*cda5da8dSAndroid Build Coastguard Worker if len(mro) > 2: 881*cda5da8dSAndroid Build Coastguard Worker hr.maybe() 882*cda5da8dSAndroid Build Coastguard Worker push('<dl><dt>Method resolution order:</dt>\n') 883*cda5da8dSAndroid Build Coastguard Worker for base in mro: 884*cda5da8dSAndroid Build Coastguard Worker push('<dd>%s</dd>\n' % self.classlink(base, 885*cda5da8dSAndroid Build Coastguard Worker object.__module__)) 886*cda5da8dSAndroid Build Coastguard Worker push('</dl>\n') 887*cda5da8dSAndroid Build Coastguard Worker 888*cda5da8dSAndroid Build Coastguard Worker def spill(msg, attrs, predicate): 889*cda5da8dSAndroid Build Coastguard Worker ok, attrs = _split_list(attrs, predicate) 890*cda5da8dSAndroid Build Coastguard Worker if ok: 891*cda5da8dSAndroid Build Coastguard Worker hr.maybe() 892*cda5da8dSAndroid Build Coastguard Worker push(msg) 893*cda5da8dSAndroid Build Coastguard Worker for name, kind, homecls, value in ok: 894*cda5da8dSAndroid Build Coastguard Worker try: 895*cda5da8dSAndroid Build Coastguard Worker value = getattr(object, name) 896*cda5da8dSAndroid Build Coastguard Worker except Exception: 897*cda5da8dSAndroid Build Coastguard Worker # Some descriptors may meet a failure in their __get__. 898*cda5da8dSAndroid Build Coastguard Worker # (bug #1785) 899*cda5da8dSAndroid Build Coastguard Worker push(self.docdata(value, name, mod)) 900*cda5da8dSAndroid Build Coastguard Worker else: 901*cda5da8dSAndroid Build Coastguard Worker push(self.document(value, name, mod, 902*cda5da8dSAndroid Build Coastguard Worker funcs, classes, mdict, object)) 903*cda5da8dSAndroid Build Coastguard Worker push('\n') 904*cda5da8dSAndroid Build Coastguard Worker return attrs 905*cda5da8dSAndroid Build Coastguard Worker 906*cda5da8dSAndroid Build Coastguard Worker def spilldescriptors(msg, attrs, predicate): 907*cda5da8dSAndroid Build Coastguard Worker ok, attrs = _split_list(attrs, predicate) 908*cda5da8dSAndroid Build Coastguard Worker if ok: 909*cda5da8dSAndroid Build Coastguard Worker hr.maybe() 910*cda5da8dSAndroid Build Coastguard Worker push(msg) 911*cda5da8dSAndroid Build Coastguard Worker for name, kind, homecls, value in ok: 912*cda5da8dSAndroid Build Coastguard Worker push(self.docdata(value, name, mod)) 913*cda5da8dSAndroid Build Coastguard Worker return attrs 914*cda5da8dSAndroid Build Coastguard Worker 915*cda5da8dSAndroid Build Coastguard Worker def spilldata(msg, attrs, predicate): 916*cda5da8dSAndroid Build Coastguard Worker ok, attrs = _split_list(attrs, predicate) 917*cda5da8dSAndroid Build Coastguard Worker if ok: 918*cda5da8dSAndroid Build Coastguard Worker hr.maybe() 919*cda5da8dSAndroid Build Coastguard Worker push(msg) 920*cda5da8dSAndroid Build Coastguard Worker for name, kind, homecls, value in ok: 921*cda5da8dSAndroid Build Coastguard Worker base = self.docother(getattr(object, name), name, mod) 922*cda5da8dSAndroid Build Coastguard Worker doc = getdoc(value) 923*cda5da8dSAndroid Build Coastguard Worker if not doc: 924*cda5da8dSAndroid Build Coastguard Worker push('<dl><dt>%s</dl>\n' % base) 925*cda5da8dSAndroid Build Coastguard Worker else: 926*cda5da8dSAndroid Build Coastguard Worker doc = self.markup(getdoc(value), self.preformat, 927*cda5da8dSAndroid Build Coastguard Worker funcs, classes, mdict) 928*cda5da8dSAndroid Build Coastguard Worker doc = '<dd><span class="code">%s</span>' % doc 929*cda5da8dSAndroid Build Coastguard Worker push('<dl><dt>%s%s</dl>\n' % (base, doc)) 930*cda5da8dSAndroid Build Coastguard Worker push('\n') 931*cda5da8dSAndroid Build Coastguard Worker return attrs 932*cda5da8dSAndroid Build Coastguard Worker 933*cda5da8dSAndroid Build Coastguard Worker attrs = [(name, kind, cls, value) 934*cda5da8dSAndroid Build Coastguard Worker for name, kind, cls, value in classify_class_attrs(object) 935*cda5da8dSAndroid Build Coastguard Worker if visiblename(name, obj=object)] 936*cda5da8dSAndroid Build Coastguard Worker 937*cda5da8dSAndroid Build Coastguard Worker mdict = {} 938*cda5da8dSAndroid Build Coastguard Worker for key, kind, homecls, value in attrs: 939*cda5da8dSAndroid Build Coastguard Worker mdict[key] = anchor = '#' + name + '-' + key 940*cda5da8dSAndroid Build Coastguard Worker try: 941*cda5da8dSAndroid Build Coastguard Worker value = getattr(object, name) 942*cda5da8dSAndroid Build Coastguard Worker except Exception: 943*cda5da8dSAndroid Build Coastguard Worker # Some descriptors may meet a failure in their __get__. 944*cda5da8dSAndroid Build Coastguard Worker # (bug #1785) 945*cda5da8dSAndroid Build Coastguard Worker pass 946*cda5da8dSAndroid Build Coastguard Worker try: 947*cda5da8dSAndroid Build Coastguard Worker # The value may not be hashable (e.g., a data attr with 948*cda5da8dSAndroid Build Coastguard Worker # a dict or list value). 949*cda5da8dSAndroid Build Coastguard Worker mdict[value] = anchor 950*cda5da8dSAndroid Build Coastguard Worker except TypeError: 951*cda5da8dSAndroid Build Coastguard Worker pass 952*cda5da8dSAndroid Build Coastguard Worker 953*cda5da8dSAndroid Build Coastguard Worker while attrs: 954*cda5da8dSAndroid Build Coastguard Worker if mro: 955*cda5da8dSAndroid Build Coastguard Worker thisclass = mro.popleft() 956*cda5da8dSAndroid Build Coastguard Worker else: 957*cda5da8dSAndroid Build Coastguard Worker thisclass = attrs[0][2] 958*cda5da8dSAndroid Build Coastguard Worker attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass) 959*cda5da8dSAndroid Build Coastguard Worker 960*cda5da8dSAndroid Build Coastguard Worker if object is not builtins.object and thisclass is builtins.object: 961*cda5da8dSAndroid Build Coastguard Worker attrs = inherited 962*cda5da8dSAndroid Build Coastguard Worker continue 963*cda5da8dSAndroid Build Coastguard Worker elif thisclass is object: 964*cda5da8dSAndroid Build Coastguard Worker tag = 'defined here' 965*cda5da8dSAndroid Build Coastguard Worker else: 966*cda5da8dSAndroid Build Coastguard Worker tag = 'inherited from %s' % self.classlink(thisclass, 967*cda5da8dSAndroid Build Coastguard Worker object.__module__) 968*cda5da8dSAndroid Build Coastguard Worker tag += ':<br>\n' 969*cda5da8dSAndroid Build Coastguard Worker 970*cda5da8dSAndroid Build Coastguard Worker sort_attributes(attrs, object) 971*cda5da8dSAndroid Build Coastguard Worker 972*cda5da8dSAndroid Build Coastguard Worker # Pump out the attrs, segregated by kind. 973*cda5da8dSAndroid Build Coastguard Worker attrs = spill('Methods %s' % tag, attrs, 974*cda5da8dSAndroid Build Coastguard Worker lambda t: t[1] == 'method') 975*cda5da8dSAndroid Build Coastguard Worker attrs = spill('Class methods %s' % tag, attrs, 976*cda5da8dSAndroid Build Coastguard Worker lambda t: t[1] == 'class method') 977*cda5da8dSAndroid Build Coastguard Worker attrs = spill('Static methods %s' % tag, attrs, 978*cda5da8dSAndroid Build Coastguard Worker lambda t: t[1] == 'static method') 979*cda5da8dSAndroid Build Coastguard Worker attrs = spilldescriptors("Readonly properties %s" % tag, attrs, 980*cda5da8dSAndroid Build Coastguard Worker lambda t: t[1] == 'readonly property') 981*cda5da8dSAndroid Build Coastguard Worker attrs = spilldescriptors('Data descriptors %s' % tag, attrs, 982*cda5da8dSAndroid Build Coastguard Worker lambda t: t[1] == 'data descriptor') 983*cda5da8dSAndroid Build Coastguard Worker attrs = spilldata('Data and other attributes %s' % tag, attrs, 984*cda5da8dSAndroid Build Coastguard Worker lambda t: t[1] == 'data') 985*cda5da8dSAndroid Build Coastguard Worker assert attrs == [] 986*cda5da8dSAndroid Build Coastguard Worker attrs = inherited 987*cda5da8dSAndroid Build Coastguard Worker 988*cda5da8dSAndroid Build Coastguard Worker contents = ''.join(contents) 989*cda5da8dSAndroid Build Coastguard Worker 990*cda5da8dSAndroid Build Coastguard Worker if name == realname: 991*cda5da8dSAndroid Build Coastguard Worker title = '<a name="%s">class <strong>%s</strong></a>' % ( 992*cda5da8dSAndroid Build Coastguard Worker name, realname) 993*cda5da8dSAndroid Build Coastguard Worker else: 994*cda5da8dSAndroid Build Coastguard Worker title = '<strong>%s</strong> = <a name="%s">class %s</a>' % ( 995*cda5da8dSAndroid Build Coastguard Worker name, name, realname) 996*cda5da8dSAndroid Build Coastguard Worker if bases: 997*cda5da8dSAndroid Build Coastguard Worker parents = [] 998*cda5da8dSAndroid Build Coastguard Worker for base in bases: 999*cda5da8dSAndroid Build Coastguard Worker parents.append(self.classlink(base, object.__module__)) 1000*cda5da8dSAndroid Build Coastguard Worker title = title + '(%s)' % ', '.join(parents) 1001*cda5da8dSAndroid Build Coastguard Worker 1002*cda5da8dSAndroid Build Coastguard Worker decl = '' 1003*cda5da8dSAndroid Build Coastguard Worker try: 1004*cda5da8dSAndroid Build Coastguard Worker signature = inspect.signature(object) 1005*cda5da8dSAndroid Build Coastguard Worker except (ValueError, TypeError): 1006*cda5da8dSAndroid Build Coastguard Worker signature = None 1007*cda5da8dSAndroid Build Coastguard Worker if signature: 1008*cda5da8dSAndroid Build Coastguard Worker argspec = str(signature) 1009*cda5da8dSAndroid Build Coastguard Worker if argspec and argspec != '()': 1010*cda5da8dSAndroid Build Coastguard Worker decl = name + self.escape(argspec) + '\n\n' 1011*cda5da8dSAndroid Build Coastguard Worker 1012*cda5da8dSAndroid Build Coastguard Worker doc = getdoc(object) 1013*cda5da8dSAndroid Build Coastguard Worker if decl: 1014*cda5da8dSAndroid Build Coastguard Worker doc = decl + (doc or '') 1015*cda5da8dSAndroid Build Coastguard Worker doc = self.markup(doc, self.preformat, funcs, classes, mdict) 1016*cda5da8dSAndroid Build Coastguard Worker doc = doc and '<span class="code">%s<br> </span>' % doc 1017*cda5da8dSAndroid Build Coastguard Worker 1018*cda5da8dSAndroid Build Coastguard Worker return self.section(title, 'title', contents, 3, doc) 1019*cda5da8dSAndroid Build Coastguard Worker 1020*cda5da8dSAndroid Build Coastguard Worker def formatvalue(self, object): 1021*cda5da8dSAndroid Build Coastguard Worker """Format an argument default value as text.""" 1022*cda5da8dSAndroid Build Coastguard Worker return self.grey('=' + self.repr(object)) 1023*cda5da8dSAndroid Build Coastguard Worker 1024*cda5da8dSAndroid Build Coastguard Worker def docroutine(self, object, name=None, mod=None, 1025*cda5da8dSAndroid Build Coastguard Worker funcs={}, classes={}, methods={}, cl=None): 1026*cda5da8dSAndroid Build Coastguard Worker """Produce HTML documentation for a function or method object.""" 1027*cda5da8dSAndroid Build Coastguard Worker realname = object.__name__ 1028*cda5da8dSAndroid Build Coastguard Worker name = name or realname 1029*cda5da8dSAndroid Build Coastguard Worker anchor = (cl and cl.__name__ or '') + '-' + name 1030*cda5da8dSAndroid Build Coastguard Worker note = '' 1031*cda5da8dSAndroid Build Coastguard Worker skipdocs = 0 1032*cda5da8dSAndroid Build Coastguard Worker if _is_bound_method(object): 1033*cda5da8dSAndroid Build Coastguard Worker imclass = object.__self__.__class__ 1034*cda5da8dSAndroid Build Coastguard Worker if cl: 1035*cda5da8dSAndroid Build Coastguard Worker if imclass is not cl: 1036*cda5da8dSAndroid Build Coastguard Worker note = ' from ' + self.classlink(imclass, mod) 1037*cda5da8dSAndroid Build Coastguard Worker else: 1038*cda5da8dSAndroid Build Coastguard Worker if object.__self__ is not None: 1039*cda5da8dSAndroid Build Coastguard Worker note = ' method of %s instance' % self.classlink( 1040*cda5da8dSAndroid Build Coastguard Worker object.__self__.__class__, mod) 1041*cda5da8dSAndroid Build Coastguard Worker else: 1042*cda5da8dSAndroid Build Coastguard Worker note = ' unbound %s method' % self.classlink(imclass,mod) 1043*cda5da8dSAndroid Build Coastguard Worker 1044*cda5da8dSAndroid Build Coastguard Worker if (inspect.iscoroutinefunction(object) or 1045*cda5da8dSAndroid Build Coastguard Worker inspect.isasyncgenfunction(object)): 1046*cda5da8dSAndroid Build Coastguard Worker asyncqualifier = 'async ' 1047*cda5da8dSAndroid Build Coastguard Worker else: 1048*cda5da8dSAndroid Build Coastguard Worker asyncqualifier = '' 1049*cda5da8dSAndroid Build Coastguard Worker 1050*cda5da8dSAndroid Build Coastguard Worker if name == realname: 1051*cda5da8dSAndroid Build Coastguard Worker title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname) 1052*cda5da8dSAndroid Build Coastguard Worker else: 1053*cda5da8dSAndroid Build Coastguard Worker if cl and inspect.getattr_static(cl, realname, []) is object: 1054*cda5da8dSAndroid Build Coastguard Worker reallink = '<a href="#%s">%s</a>' % ( 1055*cda5da8dSAndroid Build Coastguard Worker cl.__name__ + '-' + realname, realname) 1056*cda5da8dSAndroid Build Coastguard Worker skipdocs = 1 1057*cda5da8dSAndroid Build Coastguard Worker else: 1058*cda5da8dSAndroid Build Coastguard Worker reallink = realname 1059*cda5da8dSAndroid Build Coastguard Worker title = '<a name="%s"><strong>%s</strong></a> = %s' % ( 1060*cda5da8dSAndroid Build Coastguard Worker anchor, name, reallink) 1061*cda5da8dSAndroid Build Coastguard Worker argspec = None 1062*cda5da8dSAndroid Build Coastguard Worker if inspect.isroutine(object): 1063*cda5da8dSAndroid Build Coastguard Worker try: 1064*cda5da8dSAndroid Build Coastguard Worker signature = inspect.signature(object) 1065*cda5da8dSAndroid Build Coastguard Worker except (ValueError, TypeError): 1066*cda5da8dSAndroid Build Coastguard Worker signature = None 1067*cda5da8dSAndroid Build Coastguard Worker if signature: 1068*cda5da8dSAndroid Build Coastguard Worker argspec = str(signature) 1069*cda5da8dSAndroid Build Coastguard Worker if realname == '<lambda>': 1070*cda5da8dSAndroid Build Coastguard Worker title = '<strong>%s</strong> <em>lambda</em> ' % name 1071*cda5da8dSAndroid Build Coastguard Worker # XXX lambda's won't usually have func_annotations['return'] 1072*cda5da8dSAndroid Build Coastguard Worker # since the syntax doesn't support but it is possible. 1073*cda5da8dSAndroid Build Coastguard Worker # So removing parentheses isn't truly safe. 1074*cda5da8dSAndroid Build Coastguard Worker argspec = argspec[1:-1] # remove parentheses 1075*cda5da8dSAndroid Build Coastguard Worker if not argspec: 1076*cda5da8dSAndroid Build Coastguard Worker argspec = '(...)' 1077*cda5da8dSAndroid Build Coastguard Worker 1078*cda5da8dSAndroid Build Coastguard Worker decl = asyncqualifier + title + self.escape(argspec) + (note and 1079*cda5da8dSAndroid Build Coastguard Worker self.grey('<span class="heading-text">%s</span>' % note)) 1080*cda5da8dSAndroid Build Coastguard Worker 1081*cda5da8dSAndroid Build Coastguard Worker if skipdocs: 1082*cda5da8dSAndroid Build Coastguard Worker return '<dl><dt>%s</dt></dl>\n' % decl 1083*cda5da8dSAndroid Build Coastguard Worker else: 1084*cda5da8dSAndroid Build Coastguard Worker doc = self.markup( 1085*cda5da8dSAndroid Build Coastguard Worker getdoc(object), self.preformat, funcs, classes, methods) 1086*cda5da8dSAndroid Build Coastguard Worker doc = doc and '<dd><span class="code">%s</span></dd>' % doc 1087*cda5da8dSAndroid Build Coastguard Worker return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc) 1088*cda5da8dSAndroid Build Coastguard Worker 1089*cda5da8dSAndroid Build Coastguard Worker def docdata(self, object, name=None, mod=None, cl=None): 1090*cda5da8dSAndroid Build Coastguard Worker """Produce html documentation for a data descriptor.""" 1091*cda5da8dSAndroid Build Coastguard Worker results = [] 1092*cda5da8dSAndroid Build Coastguard Worker push = results.append 1093*cda5da8dSAndroid Build Coastguard Worker 1094*cda5da8dSAndroid Build Coastguard Worker if name: 1095*cda5da8dSAndroid Build Coastguard Worker push('<dl><dt><strong>%s</strong></dt>\n' % name) 1096*cda5da8dSAndroid Build Coastguard Worker doc = self.markup(getdoc(object), self.preformat) 1097*cda5da8dSAndroid Build Coastguard Worker if doc: 1098*cda5da8dSAndroid Build Coastguard Worker push('<dd><span class="code">%s</span></dd>\n' % doc) 1099*cda5da8dSAndroid Build Coastguard Worker push('</dl>\n') 1100*cda5da8dSAndroid Build Coastguard Worker 1101*cda5da8dSAndroid Build Coastguard Worker return ''.join(results) 1102*cda5da8dSAndroid Build Coastguard Worker 1103*cda5da8dSAndroid Build Coastguard Worker docproperty = docdata 1104*cda5da8dSAndroid Build Coastguard Worker 1105*cda5da8dSAndroid Build Coastguard Worker def docother(self, object, name=None, mod=None, *ignored): 1106*cda5da8dSAndroid Build Coastguard Worker """Produce HTML documentation for a data object.""" 1107*cda5da8dSAndroid Build Coastguard Worker lhs = name and '<strong>%s</strong> = ' % name or '' 1108*cda5da8dSAndroid Build Coastguard Worker return lhs + self.repr(object) 1109*cda5da8dSAndroid Build Coastguard Worker 1110*cda5da8dSAndroid Build Coastguard Worker def index(self, dir, shadowed=None): 1111*cda5da8dSAndroid Build Coastguard Worker """Generate an HTML index for a directory of modules.""" 1112*cda5da8dSAndroid Build Coastguard Worker modpkgs = [] 1113*cda5da8dSAndroid Build Coastguard Worker if shadowed is None: shadowed = {} 1114*cda5da8dSAndroid Build Coastguard Worker for importer, name, ispkg in pkgutil.iter_modules([dir]): 1115*cda5da8dSAndroid Build Coastguard Worker if any((0xD800 <= ord(ch) <= 0xDFFF) for ch in name): 1116*cda5da8dSAndroid Build Coastguard Worker # ignore a module if its name contains a surrogate character 1117*cda5da8dSAndroid Build Coastguard Worker continue 1118*cda5da8dSAndroid Build Coastguard Worker modpkgs.append((name, '', ispkg, name in shadowed)) 1119*cda5da8dSAndroid Build Coastguard Worker shadowed[name] = 1 1120*cda5da8dSAndroid Build Coastguard Worker 1121*cda5da8dSAndroid Build Coastguard Worker modpkgs.sort() 1122*cda5da8dSAndroid Build Coastguard Worker contents = self.multicolumn(modpkgs, self.modpkglink) 1123*cda5da8dSAndroid Build Coastguard Worker return self.bigsection(dir, 'index', contents) 1124*cda5da8dSAndroid Build Coastguard Worker 1125*cda5da8dSAndroid Build Coastguard Worker# -------------------------------------------- text documentation generator 1126*cda5da8dSAndroid Build Coastguard Worker 1127*cda5da8dSAndroid Build Coastguard Workerclass TextRepr(Repr): 1128*cda5da8dSAndroid Build Coastguard Worker """Class for safely making a text representation of a Python object.""" 1129*cda5da8dSAndroid Build Coastguard Worker def __init__(self): 1130*cda5da8dSAndroid Build Coastguard Worker Repr.__init__(self) 1131*cda5da8dSAndroid Build Coastguard Worker self.maxlist = self.maxtuple = 20 1132*cda5da8dSAndroid Build Coastguard Worker self.maxdict = 10 1133*cda5da8dSAndroid Build Coastguard Worker self.maxstring = self.maxother = 100 1134*cda5da8dSAndroid Build Coastguard Worker 1135*cda5da8dSAndroid Build Coastguard Worker def repr1(self, x, level): 1136*cda5da8dSAndroid Build Coastguard Worker if hasattr(type(x), '__name__'): 1137*cda5da8dSAndroid Build Coastguard Worker methodname = 'repr_' + '_'.join(type(x).__name__.split()) 1138*cda5da8dSAndroid Build Coastguard Worker if hasattr(self, methodname): 1139*cda5da8dSAndroid Build Coastguard Worker return getattr(self, methodname)(x, level) 1140*cda5da8dSAndroid Build Coastguard Worker return cram(stripid(repr(x)), self.maxother) 1141*cda5da8dSAndroid Build Coastguard Worker 1142*cda5da8dSAndroid Build Coastguard Worker def repr_string(self, x, level): 1143*cda5da8dSAndroid Build Coastguard Worker test = cram(x, self.maxstring) 1144*cda5da8dSAndroid Build Coastguard Worker testrepr = repr(test) 1145*cda5da8dSAndroid Build Coastguard Worker if '\\' in test and '\\' not in replace(testrepr, r'\\', ''): 1146*cda5da8dSAndroid Build Coastguard Worker # Backslashes are only literal in the string and are never 1147*cda5da8dSAndroid Build Coastguard Worker # needed to make any special characters, so show a raw string. 1148*cda5da8dSAndroid Build Coastguard Worker return 'r' + testrepr[0] + test + testrepr[0] 1149*cda5da8dSAndroid Build Coastguard Worker return testrepr 1150*cda5da8dSAndroid Build Coastguard Worker 1151*cda5da8dSAndroid Build Coastguard Worker repr_str = repr_string 1152*cda5da8dSAndroid Build Coastguard Worker 1153*cda5da8dSAndroid Build Coastguard Worker def repr_instance(self, x, level): 1154*cda5da8dSAndroid Build Coastguard Worker try: 1155*cda5da8dSAndroid Build Coastguard Worker return cram(stripid(repr(x)), self.maxstring) 1156*cda5da8dSAndroid Build Coastguard Worker except: 1157*cda5da8dSAndroid Build Coastguard Worker return '<%s instance>' % x.__class__.__name__ 1158*cda5da8dSAndroid Build Coastguard Worker 1159*cda5da8dSAndroid Build Coastguard Workerclass TextDoc(Doc): 1160*cda5da8dSAndroid Build Coastguard Worker """Formatter class for text documentation.""" 1161*cda5da8dSAndroid Build Coastguard Worker 1162*cda5da8dSAndroid Build Coastguard Worker # ------------------------------------------- text formatting utilities 1163*cda5da8dSAndroid Build Coastguard Worker 1164*cda5da8dSAndroid Build Coastguard Worker _repr_instance = TextRepr() 1165*cda5da8dSAndroid Build Coastguard Worker repr = _repr_instance.repr 1166*cda5da8dSAndroid Build Coastguard Worker 1167*cda5da8dSAndroid Build Coastguard Worker def bold(self, text): 1168*cda5da8dSAndroid Build Coastguard Worker """Format a string in bold by overstriking.""" 1169*cda5da8dSAndroid Build Coastguard Worker return ''.join(ch + '\b' + ch for ch in text) 1170*cda5da8dSAndroid Build Coastguard Worker 1171*cda5da8dSAndroid Build Coastguard Worker def indent(self, text, prefix=' '): 1172*cda5da8dSAndroid Build Coastguard Worker """Indent text by prepending a given prefix to each line.""" 1173*cda5da8dSAndroid Build Coastguard Worker if not text: return '' 1174*cda5da8dSAndroid Build Coastguard Worker lines = [prefix + line for line in text.split('\n')] 1175*cda5da8dSAndroid Build Coastguard Worker if lines: lines[-1] = lines[-1].rstrip() 1176*cda5da8dSAndroid Build Coastguard Worker return '\n'.join(lines) 1177*cda5da8dSAndroid Build Coastguard Worker 1178*cda5da8dSAndroid Build Coastguard Worker def section(self, title, contents): 1179*cda5da8dSAndroid Build Coastguard Worker """Format a section with a given heading.""" 1180*cda5da8dSAndroid Build Coastguard Worker clean_contents = self.indent(contents).rstrip() 1181*cda5da8dSAndroid Build Coastguard Worker return self.bold(title) + '\n' + clean_contents + '\n\n' 1182*cda5da8dSAndroid Build Coastguard Worker 1183*cda5da8dSAndroid Build Coastguard Worker # ---------------------------------------------- type-specific routines 1184*cda5da8dSAndroid Build Coastguard Worker 1185*cda5da8dSAndroid Build Coastguard Worker def formattree(self, tree, modname, parent=None, prefix=''): 1186*cda5da8dSAndroid Build Coastguard Worker """Render in text a class tree as returned by inspect.getclasstree().""" 1187*cda5da8dSAndroid Build Coastguard Worker result = '' 1188*cda5da8dSAndroid Build Coastguard Worker for entry in tree: 1189*cda5da8dSAndroid Build Coastguard Worker if type(entry) is type(()): 1190*cda5da8dSAndroid Build Coastguard Worker c, bases = entry 1191*cda5da8dSAndroid Build Coastguard Worker result = result + prefix + classname(c, modname) 1192*cda5da8dSAndroid Build Coastguard Worker if bases and bases != (parent,): 1193*cda5da8dSAndroid Build Coastguard Worker parents = (classname(c, modname) for c in bases) 1194*cda5da8dSAndroid Build Coastguard Worker result = result + '(%s)' % ', '.join(parents) 1195*cda5da8dSAndroid Build Coastguard Worker result = result + '\n' 1196*cda5da8dSAndroid Build Coastguard Worker elif type(entry) is type([]): 1197*cda5da8dSAndroid Build Coastguard Worker result = result + self.formattree( 1198*cda5da8dSAndroid Build Coastguard Worker entry, modname, c, prefix + ' ') 1199*cda5da8dSAndroid Build Coastguard Worker return result 1200*cda5da8dSAndroid Build Coastguard Worker 1201*cda5da8dSAndroid Build Coastguard Worker def docmodule(self, object, name=None, mod=None): 1202*cda5da8dSAndroid Build Coastguard Worker """Produce text documentation for a given module object.""" 1203*cda5da8dSAndroid Build Coastguard Worker name = object.__name__ # ignore the passed-in name 1204*cda5da8dSAndroid Build Coastguard Worker synop, desc = splitdoc(getdoc(object)) 1205*cda5da8dSAndroid Build Coastguard Worker result = self.section('NAME', name + (synop and ' - ' + synop)) 1206*cda5da8dSAndroid Build Coastguard Worker all = getattr(object, '__all__', None) 1207*cda5da8dSAndroid Build Coastguard Worker docloc = self.getdocloc(object) 1208*cda5da8dSAndroid Build Coastguard Worker if docloc is not None: 1209*cda5da8dSAndroid Build Coastguard Worker result = result + self.section('MODULE REFERENCE', docloc + """ 1210*cda5da8dSAndroid Build Coastguard Worker 1211*cda5da8dSAndroid Build Coastguard WorkerThe following documentation is automatically generated from the Python 1212*cda5da8dSAndroid Build Coastguard Workersource files. It may be incomplete, incorrect or include features that 1213*cda5da8dSAndroid Build Coastguard Workerare considered implementation detail and may vary between Python 1214*cda5da8dSAndroid Build Coastguard Workerimplementations. When in doubt, consult the module reference at the 1215*cda5da8dSAndroid Build Coastguard Workerlocation listed above. 1216*cda5da8dSAndroid Build Coastguard Worker""") 1217*cda5da8dSAndroid Build Coastguard Worker 1218*cda5da8dSAndroid Build Coastguard Worker if desc: 1219*cda5da8dSAndroid Build Coastguard Worker result = result + self.section('DESCRIPTION', desc) 1220*cda5da8dSAndroid Build Coastguard Worker 1221*cda5da8dSAndroid Build Coastguard Worker classes = [] 1222*cda5da8dSAndroid Build Coastguard Worker for key, value in inspect.getmembers(object, inspect.isclass): 1223*cda5da8dSAndroid Build Coastguard Worker # if __all__ exists, believe it. Otherwise use old heuristic. 1224*cda5da8dSAndroid Build Coastguard Worker if (all is not None 1225*cda5da8dSAndroid Build Coastguard Worker or (inspect.getmodule(value) or object) is object): 1226*cda5da8dSAndroid Build Coastguard Worker if visiblename(key, all, object): 1227*cda5da8dSAndroid Build Coastguard Worker classes.append((key, value)) 1228*cda5da8dSAndroid Build Coastguard Worker funcs = [] 1229*cda5da8dSAndroid Build Coastguard Worker for key, value in inspect.getmembers(object, inspect.isroutine): 1230*cda5da8dSAndroid Build Coastguard Worker # if __all__ exists, believe it. Otherwise use old heuristic. 1231*cda5da8dSAndroid Build Coastguard Worker if (all is not None or 1232*cda5da8dSAndroid Build Coastguard Worker inspect.isbuiltin(value) or inspect.getmodule(value) is object): 1233*cda5da8dSAndroid Build Coastguard Worker if visiblename(key, all, object): 1234*cda5da8dSAndroid Build Coastguard Worker funcs.append((key, value)) 1235*cda5da8dSAndroid Build Coastguard Worker data = [] 1236*cda5da8dSAndroid Build Coastguard Worker for key, value in inspect.getmembers(object, isdata): 1237*cda5da8dSAndroid Build Coastguard Worker if visiblename(key, all, object): 1238*cda5da8dSAndroid Build Coastguard Worker data.append((key, value)) 1239*cda5da8dSAndroid Build Coastguard Worker 1240*cda5da8dSAndroid Build Coastguard Worker modpkgs = [] 1241*cda5da8dSAndroid Build Coastguard Worker modpkgs_names = set() 1242*cda5da8dSAndroid Build Coastguard Worker if hasattr(object, '__path__'): 1243*cda5da8dSAndroid Build Coastguard Worker for importer, modname, ispkg in pkgutil.iter_modules(object.__path__): 1244*cda5da8dSAndroid Build Coastguard Worker modpkgs_names.add(modname) 1245*cda5da8dSAndroid Build Coastguard Worker if ispkg: 1246*cda5da8dSAndroid Build Coastguard Worker modpkgs.append(modname + ' (package)') 1247*cda5da8dSAndroid Build Coastguard Worker else: 1248*cda5da8dSAndroid Build Coastguard Worker modpkgs.append(modname) 1249*cda5da8dSAndroid Build Coastguard Worker 1250*cda5da8dSAndroid Build Coastguard Worker modpkgs.sort() 1251*cda5da8dSAndroid Build Coastguard Worker result = result + self.section( 1252*cda5da8dSAndroid Build Coastguard Worker 'PACKAGE CONTENTS', '\n'.join(modpkgs)) 1253*cda5da8dSAndroid Build Coastguard Worker 1254*cda5da8dSAndroid Build Coastguard Worker # Detect submodules as sometimes created by C extensions 1255*cda5da8dSAndroid Build Coastguard Worker submodules = [] 1256*cda5da8dSAndroid Build Coastguard Worker for key, value in inspect.getmembers(object, inspect.ismodule): 1257*cda5da8dSAndroid Build Coastguard Worker if value.__name__.startswith(name + '.') and key not in modpkgs_names: 1258*cda5da8dSAndroid Build Coastguard Worker submodules.append(key) 1259*cda5da8dSAndroid Build Coastguard Worker if submodules: 1260*cda5da8dSAndroid Build Coastguard Worker submodules.sort() 1261*cda5da8dSAndroid Build Coastguard Worker result = result + self.section( 1262*cda5da8dSAndroid Build Coastguard Worker 'SUBMODULES', '\n'.join(submodules)) 1263*cda5da8dSAndroid Build Coastguard Worker 1264*cda5da8dSAndroid Build Coastguard Worker if classes: 1265*cda5da8dSAndroid Build Coastguard Worker classlist = [value for key, value in classes] 1266*cda5da8dSAndroid Build Coastguard Worker contents = [self.formattree( 1267*cda5da8dSAndroid Build Coastguard Worker inspect.getclasstree(classlist, 1), name)] 1268*cda5da8dSAndroid Build Coastguard Worker for key, value in classes: 1269*cda5da8dSAndroid Build Coastguard Worker contents.append(self.document(value, key, name)) 1270*cda5da8dSAndroid Build Coastguard Worker result = result + self.section('CLASSES', '\n'.join(contents)) 1271*cda5da8dSAndroid Build Coastguard Worker 1272*cda5da8dSAndroid Build Coastguard Worker if funcs: 1273*cda5da8dSAndroid Build Coastguard Worker contents = [] 1274*cda5da8dSAndroid Build Coastguard Worker for key, value in funcs: 1275*cda5da8dSAndroid Build Coastguard Worker contents.append(self.document(value, key, name)) 1276*cda5da8dSAndroid Build Coastguard Worker result = result + self.section('FUNCTIONS', '\n'.join(contents)) 1277*cda5da8dSAndroid Build Coastguard Worker 1278*cda5da8dSAndroid Build Coastguard Worker if data: 1279*cda5da8dSAndroid Build Coastguard Worker contents = [] 1280*cda5da8dSAndroid Build Coastguard Worker for key, value in data: 1281*cda5da8dSAndroid Build Coastguard Worker contents.append(self.docother(value, key, name, maxlen=70)) 1282*cda5da8dSAndroid Build Coastguard Worker result = result + self.section('DATA', '\n'.join(contents)) 1283*cda5da8dSAndroid Build Coastguard Worker 1284*cda5da8dSAndroid Build Coastguard Worker if hasattr(object, '__version__'): 1285*cda5da8dSAndroid Build Coastguard Worker version = str(object.__version__) 1286*cda5da8dSAndroid Build Coastguard Worker if version[:11] == '$' + 'Revision: ' and version[-1:] == '$': 1287*cda5da8dSAndroid Build Coastguard Worker version = version[11:-1].strip() 1288*cda5da8dSAndroid Build Coastguard Worker result = result + self.section('VERSION', version) 1289*cda5da8dSAndroid Build Coastguard Worker if hasattr(object, '__date__'): 1290*cda5da8dSAndroid Build Coastguard Worker result = result + self.section('DATE', str(object.__date__)) 1291*cda5da8dSAndroid Build Coastguard Worker if hasattr(object, '__author__'): 1292*cda5da8dSAndroid Build Coastguard Worker result = result + self.section('AUTHOR', str(object.__author__)) 1293*cda5da8dSAndroid Build Coastguard Worker if hasattr(object, '__credits__'): 1294*cda5da8dSAndroid Build Coastguard Worker result = result + self.section('CREDITS', str(object.__credits__)) 1295*cda5da8dSAndroid Build Coastguard Worker try: 1296*cda5da8dSAndroid Build Coastguard Worker file = inspect.getabsfile(object) 1297*cda5da8dSAndroid Build Coastguard Worker except TypeError: 1298*cda5da8dSAndroid Build Coastguard Worker file = '(built-in)' 1299*cda5da8dSAndroid Build Coastguard Worker result = result + self.section('FILE', file) 1300*cda5da8dSAndroid Build Coastguard Worker return result 1301*cda5da8dSAndroid Build Coastguard Worker 1302*cda5da8dSAndroid Build Coastguard Worker def docclass(self, object, name=None, mod=None, *ignored): 1303*cda5da8dSAndroid Build Coastguard Worker """Produce text documentation for a given class object.""" 1304*cda5da8dSAndroid Build Coastguard Worker realname = object.__name__ 1305*cda5da8dSAndroid Build Coastguard Worker name = name or realname 1306*cda5da8dSAndroid Build Coastguard Worker bases = object.__bases__ 1307*cda5da8dSAndroid Build Coastguard Worker 1308*cda5da8dSAndroid Build Coastguard Worker def makename(c, m=object.__module__): 1309*cda5da8dSAndroid Build Coastguard Worker return classname(c, m) 1310*cda5da8dSAndroid Build Coastguard Worker 1311*cda5da8dSAndroid Build Coastguard Worker if name == realname: 1312*cda5da8dSAndroid Build Coastguard Worker title = 'class ' + self.bold(realname) 1313*cda5da8dSAndroid Build Coastguard Worker else: 1314*cda5da8dSAndroid Build Coastguard Worker title = self.bold(name) + ' = class ' + realname 1315*cda5da8dSAndroid Build Coastguard Worker if bases: 1316*cda5da8dSAndroid Build Coastguard Worker parents = map(makename, bases) 1317*cda5da8dSAndroid Build Coastguard Worker title = title + '(%s)' % ', '.join(parents) 1318*cda5da8dSAndroid Build Coastguard Worker 1319*cda5da8dSAndroid Build Coastguard Worker contents = [] 1320*cda5da8dSAndroid Build Coastguard Worker push = contents.append 1321*cda5da8dSAndroid Build Coastguard Worker 1322*cda5da8dSAndroid Build Coastguard Worker try: 1323*cda5da8dSAndroid Build Coastguard Worker signature = inspect.signature(object) 1324*cda5da8dSAndroid Build Coastguard Worker except (ValueError, TypeError): 1325*cda5da8dSAndroid Build Coastguard Worker signature = None 1326*cda5da8dSAndroid Build Coastguard Worker if signature: 1327*cda5da8dSAndroid Build Coastguard Worker argspec = str(signature) 1328*cda5da8dSAndroid Build Coastguard Worker if argspec and argspec != '()': 1329*cda5da8dSAndroid Build Coastguard Worker push(name + argspec + '\n') 1330*cda5da8dSAndroid Build Coastguard Worker 1331*cda5da8dSAndroid Build Coastguard Worker doc = getdoc(object) 1332*cda5da8dSAndroid Build Coastguard Worker if doc: 1333*cda5da8dSAndroid Build Coastguard Worker push(doc + '\n') 1334*cda5da8dSAndroid Build Coastguard Worker 1335*cda5da8dSAndroid Build Coastguard Worker # List the mro, if non-trivial. 1336*cda5da8dSAndroid Build Coastguard Worker mro = deque(inspect.getmro(object)) 1337*cda5da8dSAndroid Build Coastguard Worker if len(mro) > 2: 1338*cda5da8dSAndroid Build Coastguard Worker push("Method resolution order:") 1339*cda5da8dSAndroid Build Coastguard Worker for base in mro: 1340*cda5da8dSAndroid Build Coastguard Worker push(' ' + makename(base)) 1341*cda5da8dSAndroid Build Coastguard Worker push('') 1342*cda5da8dSAndroid Build Coastguard Worker 1343*cda5da8dSAndroid Build Coastguard Worker # List the built-in subclasses, if any: 1344*cda5da8dSAndroid Build Coastguard Worker subclasses = sorted( 1345*cda5da8dSAndroid Build Coastguard Worker (str(cls.__name__) for cls in type.__subclasses__(object) 1346*cda5da8dSAndroid Build Coastguard Worker if not cls.__name__.startswith("_") and cls.__module__ == "builtins"), 1347*cda5da8dSAndroid Build Coastguard Worker key=str.lower 1348*cda5da8dSAndroid Build Coastguard Worker ) 1349*cda5da8dSAndroid Build Coastguard Worker no_of_subclasses = len(subclasses) 1350*cda5da8dSAndroid Build Coastguard Worker MAX_SUBCLASSES_TO_DISPLAY = 4 1351*cda5da8dSAndroid Build Coastguard Worker if subclasses: 1352*cda5da8dSAndroid Build Coastguard Worker push("Built-in subclasses:") 1353*cda5da8dSAndroid Build Coastguard Worker for subclassname in subclasses[:MAX_SUBCLASSES_TO_DISPLAY]: 1354*cda5da8dSAndroid Build Coastguard Worker push(' ' + subclassname) 1355*cda5da8dSAndroid Build Coastguard Worker if no_of_subclasses > MAX_SUBCLASSES_TO_DISPLAY: 1356*cda5da8dSAndroid Build Coastguard Worker push(' ... and ' + 1357*cda5da8dSAndroid Build Coastguard Worker str(no_of_subclasses - MAX_SUBCLASSES_TO_DISPLAY) + 1358*cda5da8dSAndroid Build Coastguard Worker ' other subclasses') 1359*cda5da8dSAndroid Build Coastguard Worker push('') 1360*cda5da8dSAndroid Build Coastguard Worker 1361*cda5da8dSAndroid Build Coastguard Worker # Cute little class to pump out a horizontal rule between sections. 1362*cda5da8dSAndroid Build Coastguard Worker class HorizontalRule: 1363*cda5da8dSAndroid Build Coastguard Worker def __init__(self): 1364*cda5da8dSAndroid Build Coastguard Worker self.needone = 0 1365*cda5da8dSAndroid Build Coastguard Worker def maybe(self): 1366*cda5da8dSAndroid Build Coastguard Worker if self.needone: 1367*cda5da8dSAndroid Build Coastguard Worker push('-' * 70) 1368*cda5da8dSAndroid Build Coastguard Worker self.needone = 1 1369*cda5da8dSAndroid Build Coastguard Worker hr = HorizontalRule() 1370*cda5da8dSAndroid Build Coastguard Worker 1371*cda5da8dSAndroid Build Coastguard Worker def spill(msg, attrs, predicate): 1372*cda5da8dSAndroid Build Coastguard Worker ok, attrs = _split_list(attrs, predicate) 1373*cda5da8dSAndroid Build Coastguard Worker if ok: 1374*cda5da8dSAndroid Build Coastguard Worker hr.maybe() 1375*cda5da8dSAndroid Build Coastguard Worker push(msg) 1376*cda5da8dSAndroid Build Coastguard Worker for name, kind, homecls, value in ok: 1377*cda5da8dSAndroid Build Coastguard Worker try: 1378*cda5da8dSAndroid Build Coastguard Worker value = getattr(object, name) 1379*cda5da8dSAndroid Build Coastguard Worker except Exception: 1380*cda5da8dSAndroid Build Coastguard Worker # Some descriptors may meet a failure in their __get__. 1381*cda5da8dSAndroid Build Coastguard Worker # (bug #1785) 1382*cda5da8dSAndroid Build Coastguard Worker push(self.docdata(value, name, mod)) 1383*cda5da8dSAndroid Build Coastguard Worker else: 1384*cda5da8dSAndroid Build Coastguard Worker push(self.document(value, 1385*cda5da8dSAndroid Build Coastguard Worker name, mod, object)) 1386*cda5da8dSAndroid Build Coastguard Worker return attrs 1387*cda5da8dSAndroid Build Coastguard Worker 1388*cda5da8dSAndroid Build Coastguard Worker def spilldescriptors(msg, attrs, predicate): 1389*cda5da8dSAndroid Build Coastguard Worker ok, attrs = _split_list(attrs, predicate) 1390*cda5da8dSAndroid Build Coastguard Worker if ok: 1391*cda5da8dSAndroid Build Coastguard Worker hr.maybe() 1392*cda5da8dSAndroid Build Coastguard Worker push(msg) 1393*cda5da8dSAndroid Build Coastguard Worker for name, kind, homecls, value in ok: 1394*cda5da8dSAndroid Build Coastguard Worker push(self.docdata(value, name, mod)) 1395*cda5da8dSAndroid Build Coastguard Worker return attrs 1396*cda5da8dSAndroid Build Coastguard Worker 1397*cda5da8dSAndroid Build Coastguard Worker def spilldata(msg, attrs, predicate): 1398*cda5da8dSAndroid Build Coastguard Worker ok, attrs = _split_list(attrs, predicate) 1399*cda5da8dSAndroid Build Coastguard Worker if ok: 1400*cda5da8dSAndroid Build Coastguard Worker hr.maybe() 1401*cda5da8dSAndroid Build Coastguard Worker push(msg) 1402*cda5da8dSAndroid Build Coastguard Worker for name, kind, homecls, value in ok: 1403*cda5da8dSAndroid Build Coastguard Worker doc = getdoc(value) 1404*cda5da8dSAndroid Build Coastguard Worker try: 1405*cda5da8dSAndroid Build Coastguard Worker obj = getattr(object, name) 1406*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 1407*cda5da8dSAndroid Build Coastguard Worker obj = homecls.__dict__[name] 1408*cda5da8dSAndroid Build Coastguard Worker push(self.docother(obj, name, mod, maxlen=70, doc=doc) + 1409*cda5da8dSAndroid Build Coastguard Worker '\n') 1410*cda5da8dSAndroid Build Coastguard Worker return attrs 1411*cda5da8dSAndroid Build Coastguard Worker 1412*cda5da8dSAndroid Build Coastguard Worker attrs = [(name, kind, cls, value) 1413*cda5da8dSAndroid Build Coastguard Worker for name, kind, cls, value in classify_class_attrs(object) 1414*cda5da8dSAndroid Build Coastguard Worker if visiblename(name, obj=object)] 1415*cda5da8dSAndroid Build Coastguard Worker 1416*cda5da8dSAndroid Build Coastguard Worker while attrs: 1417*cda5da8dSAndroid Build Coastguard Worker if mro: 1418*cda5da8dSAndroid Build Coastguard Worker thisclass = mro.popleft() 1419*cda5da8dSAndroid Build Coastguard Worker else: 1420*cda5da8dSAndroid Build Coastguard Worker thisclass = attrs[0][2] 1421*cda5da8dSAndroid Build Coastguard Worker attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass) 1422*cda5da8dSAndroid Build Coastguard Worker 1423*cda5da8dSAndroid Build Coastguard Worker if object is not builtins.object and thisclass is builtins.object: 1424*cda5da8dSAndroid Build Coastguard Worker attrs = inherited 1425*cda5da8dSAndroid Build Coastguard Worker continue 1426*cda5da8dSAndroid Build Coastguard Worker elif thisclass is object: 1427*cda5da8dSAndroid Build Coastguard Worker tag = "defined here" 1428*cda5da8dSAndroid Build Coastguard Worker else: 1429*cda5da8dSAndroid Build Coastguard Worker tag = "inherited from %s" % classname(thisclass, 1430*cda5da8dSAndroid Build Coastguard Worker object.__module__) 1431*cda5da8dSAndroid Build Coastguard Worker 1432*cda5da8dSAndroid Build Coastguard Worker sort_attributes(attrs, object) 1433*cda5da8dSAndroid Build Coastguard Worker 1434*cda5da8dSAndroid Build Coastguard Worker # Pump out the attrs, segregated by kind. 1435*cda5da8dSAndroid Build Coastguard Worker attrs = spill("Methods %s:\n" % tag, attrs, 1436*cda5da8dSAndroid Build Coastguard Worker lambda t: t[1] == 'method') 1437*cda5da8dSAndroid Build Coastguard Worker attrs = spill("Class methods %s:\n" % tag, attrs, 1438*cda5da8dSAndroid Build Coastguard Worker lambda t: t[1] == 'class method') 1439*cda5da8dSAndroid Build Coastguard Worker attrs = spill("Static methods %s:\n" % tag, attrs, 1440*cda5da8dSAndroid Build Coastguard Worker lambda t: t[1] == 'static method') 1441*cda5da8dSAndroid Build Coastguard Worker attrs = spilldescriptors("Readonly properties %s:\n" % tag, attrs, 1442*cda5da8dSAndroid Build Coastguard Worker lambda t: t[1] == 'readonly property') 1443*cda5da8dSAndroid Build Coastguard Worker attrs = spilldescriptors("Data descriptors %s:\n" % tag, attrs, 1444*cda5da8dSAndroid Build Coastguard Worker lambda t: t[1] == 'data descriptor') 1445*cda5da8dSAndroid Build Coastguard Worker attrs = spilldata("Data and other attributes %s:\n" % tag, attrs, 1446*cda5da8dSAndroid Build Coastguard Worker lambda t: t[1] == 'data') 1447*cda5da8dSAndroid Build Coastguard Worker 1448*cda5da8dSAndroid Build Coastguard Worker assert attrs == [] 1449*cda5da8dSAndroid Build Coastguard Worker attrs = inherited 1450*cda5da8dSAndroid Build Coastguard Worker 1451*cda5da8dSAndroid Build Coastguard Worker contents = '\n'.join(contents) 1452*cda5da8dSAndroid Build Coastguard Worker if not contents: 1453*cda5da8dSAndroid Build Coastguard Worker return title + '\n' 1454*cda5da8dSAndroid Build Coastguard Worker return title + '\n' + self.indent(contents.rstrip(), ' | ') + '\n' 1455*cda5da8dSAndroid Build Coastguard Worker 1456*cda5da8dSAndroid Build Coastguard Worker def formatvalue(self, object): 1457*cda5da8dSAndroid Build Coastguard Worker """Format an argument default value as text.""" 1458*cda5da8dSAndroid Build Coastguard Worker return '=' + self.repr(object) 1459*cda5da8dSAndroid Build Coastguard Worker 1460*cda5da8dSAndroid Build Coastguard Worker def docroutine(self, object, name=None, mod=None, cl=None): 1461*cda5da8dSAndroid Build Coastguard Worker """Produce text documentation for a function or method object.""" 1462*cda5da8dSAndroid Build Coastguard Worker realname = object.__name__ 1463*cda5da8dSAndroid Build Coastguard Worker name = name or realname 1464*cda5da8dSAndroid Build Coastguard Worker note = '' 1465*cda5da8dSAndroid Build Coastguard Worker skipdocs = 0 1466*cda5da8dSAndroid Build Coastguard Worker if _is_bound_method(object): 1467*cda5da8dSAndroid Build Coastguard Worker imclass = object.__self__.__class__ 1468*cda5da8dSAndroid Build Coastguard Worker if cl: 1469*cda5da8dSAndroid Build Coastguard Worker if imclass is not cl: 1470*cda5da8dSAndroid Build Coastguard Worker note = ' from ' + classname(imclass, mod) 1471*cda5da8dSAndroid Build Coastguard Worker else: 1472*cda5da8dSAndroid Build Coastguard Worker if object.__self__ is not None: 1473*cda5da8dSAndroid Build Coastguard Worker note = ' method of %s instance' % classname( 1474*cda5da8dSAndroid Build Coastguard Worker object.__self__.__class__, mod) 1475*cda5da8dSAndroid Build Coastguard Worker else: 1476*cda5da8dSAndroid Build Coastguard Worker note = ' unbound %s method' % classname(imclass,mod) 1477*cda5da8dSAndroid Build Coastguard Worker 1478*cda5da8dSAndroid Build Coastguard Worker if (inspect.iscoroutinefunction(object) or 1479*cda5da8dSAndroid Build Coastguard Worker inspect.isasyncgenfunction(object)): 1480*cda5da8dSAndroid Build Coastguard Worker asyncqualifier = 'async ' 1481*cda5da8dSAndroid Build Coastguard Worker else: 1482*cda5da8dSAndroid Build Coastguard Worker asyncqualifier = '' 1483*cda5da8dSAndroid Build Coastguard Worker 1484*cda5da8dSAndroid Build Coastguard Worker if name == realname: 1485*cda5da8dSAndroid Build Coastguard Worker title = self.bold(realname) 1486*cda5da8dSAndroid Build Coastguard Worker else: 1487*cda5da8dSAndroid Build Coastguard Worker if cl and inspect.getattr_static(cl, realname, []) is object: 1488*cda5da8dSAndroid Build Coastguard Worker skipdocs = 1 1489*cda5da8dSAndroid Build Coastguard Worker title = self.bold(name) + ' = ' + realname 1490*cda5da8dSAndroid Build Coastguard Worker argspec = None 1491*cda5da8dSAndroid Build Coastguard Worker 1492*cda5da8dSAndroid Build Coastguard Worker if inspect.isroutine(object): 1493*cda5da8dSAndroid Build Coastguard Worker try: 1494*cda5da8dSAndroid Build Coastguard Worker signature = inspect.signature(object) 1495*cda5da8dSAndroid Build Coastguard Worker except (ValueError, TypeError): 1496*cda5da8dSAndroid Build Coastguard Worker signature = None 1497*cda5da8dSAndroid Build Coastguard Worker if signature: 1498*cda5da8dSAndroid Build Coastguard Worker argspec = str(signature) 1499*cda5da8dSAndroid Build Coastguard Worker if realname == '<lambda>': 1500*cda5da8dSAndroid Build Coastguard Worker title = self.bold(name) + ' lambda ' 1501*cda5da8dSAndroid Build Coastguard Worker # XXX lambda's won't usually have func_annotations['return'] 1502*cda5da8dSAndroid Build Coastguard Worker # since the syntax doesn't support but it is possible. 1503*cda5da8dSAndroid Build Coastguard Worker # So removing parentheses isn't truly safe. 1504*cda5da8dSAndroid Build Coastguard Worker argspec = argspec[1:-1] # remove parentheses 1505*cda5da8dSAndroid Build Coastguard Worker if not argspec: 1506*cda5da8dSAndroid Build Coastguard Worker argspec = '(...)' 1507*cda5da8dSAndroid Build Coastguard Worker decl = asyncqualifier + title + argspec + note 1508*cda5da8dSAndroid Build Coastguard Worker 1509*cda5da8dSAndroid Build Coastguard Worker if skipdocs: 1510*cda5da8dSAndroid Build Coastguard Worker return decl + '\n' 1511*cda5da8dSAndroid Build Coastguard Worker else: 1512*cda5da8dSAndroid Build Coastguard Worker doc = getdoc(object) or '' 1513*cda5da8dSAndroid Build Coastguard Worker return decl + '\n' + (doc and self.indent(doc).rstrip() + '\n') 1514*cda5da8dSAndroid Build Coastguard Worker 1515*cda5da8dSAndroid Build Coastguard Worker def docdata(self, object, name=None, mod=None, cl=None): 1516*cda5da8dSAndroid Build Coastguard Worker """Produce text documentation for a data descriptor.""" 1517*cda5da8dSAndroid Build Coastguard Worker results = [] 1518*cda5da8dSAndroid Build Coastguard Worker push = results.append 1519*cda5da8dSAndroid Build Coastguard Worker 1520*cda5da8dSAndroid Build Coastguard Worker if name: 1521*cda5da8dSAndroid Build Coastguard Worker push(self.bold(name)) 1522*cda5da8dSAndroid Build Coastguard Worker push('\n') 1523*cda5da8dSAndroid Build Coastguard Worker doc = getdoc(object) or '' 1524*cda5da8dSAndroid Build Coastguard Worker if doc: 1525*cda5da8dSAndroid Build Coastguard Worker push(self.indent(doc)) 1526*cda5da8dSAndroid Build Coastguard Worker push('\n') 1527*cda5da8dSAndroid Build Coastguard Worker return ''.join(results) 1528*cda5da8dSAndroid Build Coastguard Worker 1529*cda5da8dSAndroid Build Coastguard Worker docproperty = docdata 1530*cda5da8dSAndroid Build Coastguard Worker 1531*cda5da8dSAndroid Build Coastguard Worker def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=None): 1532*cda5da8dSAndroid Build Coastguard Worker """Produce text documentation for a data object.""" 1533*cda5da8dSAndroid Build Coastguard Worker repr = self.repr(object) 1534*cda5da8dSAndroid Build Coastguard Worker if maxlen: 1535*cda5da8dSAndroid Build Coastguard Worker line = (name and name + ' = ' or '') + repr 1536*cda5da8dSAndroid Build Coastguard Worker chop = maxlen - len(line) 1537*cda5da8dSAndroid Build Coastguard Worker if chop < 0: repr = repr[:chop] + '...' 1538*cda5da8dSAndroid Build Coastguard Worker line = (name and self.bold(name) + ' = ' or '') + repr 1539*cda5da8dSAndroid Build Coastguard Worker if not doc: 1540*cda5da8dSAndroid Build Coastguard Worker doc = getdoc(object) 1541*cda5da8dSAndroid Build Coastguard Worker if doc: 1542*cda5da8dSAndroid Build Coastguard Worker line += '\n' + self.indent(str(doc)) + '\n' 1543*cda5da8dSAndroid Build Coastguard Worker return line 1544*cda5da8dSAndroid Build Coastguard Worker 1545*cda5da8dSAndroid Build Coastguard Workerclass _PlainTextDoc(TextDoc): 1546*cda5da8dSAndroid Build Coastguard Worker """Subclass of TextDoc which overrides string styling""" 1547*cda5da8dSAndroid Build Coastguard Worker def bold(self, text): 1548*cda5da8dSAndroid Build Coastguard Worker return text 1549*cda5da8dSAndroid Build Coastguard Worker 1550*cda5da8dSAndroid Build Coastguard Worker# --------------------------------------------------------- user interfaces 1551*cda5da8dSAndroid Build Coastguard Worker 1552*cda5da8dSAndroid Build Coastguard Workerdef pager(text): 1553*cda5da8dSAndroid Build Coastguard Worker """The first time this is called, determine what kind of pager to use.""" 1554*cda5da8dSAndroid Build Coastguard Worker global pager 1555*cda5da8dSAndroid Build Coastguard Worker pager = getpager() 1556*cda5da8dSAndroid Build Coastguard Worker pager(text) 1557*cda5da8dSAndroid Build Coastguard Worker 1558*cda5da8dSAndroid Build Coastguard Workerdef getpager(): 1559*cda5da8dSAndroid Build Coastguard Worker """Decide what method to use for paging through text.""" 1560*cda5da8dSAndroid Build Coastguard Worker if not hasattr(sys.stdin, "isatty"): 1561*cda5da8dSAndroid Build Coastguard Worker return plainpager 1562*cda5da8dSAndroid Build Coastguard Worker if not hasattr(sys.stdout, "isatty"): 1563*cda5da8dSAndroid Build Coastguard Worker return plainpager 1564*cda5da8dSAndroid Build Coastguard Worker if not sys.stdin.isatty() or not sys.stdout.isatty(): 1565*cda5da8dSAndroid Build Coastguard Worker return plainpager 1566*cda5da8dSAndroid Build Coastguard Worker if sys.platform == "emscripten": 1567*cda5da8dSAndroid Build Coastguard Worker return plainpager 1568*cda5da8dSAndroid Build Coastguard Worker use_pager = os.environ.get('MANPAGER') or os.environ.get('PAGER') 1569*cda5da8dSAndroid Build Coastguard Worker if use_pager: 1570*cda5da8dSAndroid Build Coastguard Worker if sys.platform == 'win32': # pipes completely broken in Windows 1571*cda5da8dSAndroid Build Coastguard Worker return lambda text: tempfilepager(plain(text), use_pager) 1572*cda5da8dSAndroid Build Coastguard Worker elif os.environ.get('TERM') in ('dumb', 'emacs'): 1573*cda5da8dSAndroid Build Coastguard Worker return lambda text: pipepager(plain(text), use_pager) 1574*cda5da8dSAndroid Build Coastguard Worker else: 1575*cda5da8dSAndroid Build Coastguard Worker return lambda text: pipepager(text, use_pager) 1576*cda5da8dSAndroid Build Coastguard Worker if os.environ.get('TERM') in ('dumb', 'emacs'): 1577*cda5da8dSAndroid Build Coastguard Worker return plainpager 1578*cda5da8dSAndroid Build Coastguard Worker if sys.platform == 'win32': 1579*cda5da8dSAndroid Build Coastguard Worker return lambda text: tempfilepager(plain(text), 'more <') 1580*cda5da8dSAndroid Build Coastguard Worker if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0: 1581*cda5da8dSAndroid Build Coastguard Worker return lambda text: pipepager(text, 'less') 1582*cda5da8dSAndroid Build Coastguard Worker 1583*cda5da8dSAndroid Build Coastguard Worker import tempfile 1584*cda5da8dSAndroid Build Coastguard Worker (fd, filename) = tempfile.mkstemp() 1585*cda5da8dSAndroid Build Coastguard Worker os.close(fd) 1586*cda5da8dSAndroid Build Coastguard Worker try: 1587*cda5da8dSAndroid Build Coastguard Worker if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0: 1588*cda5da8dSAndroid Build Coastguard Worker return lambda text: pipepager(text, 'more') 1589*cda5da8dSAndroid Build Coastguard Worker else: 1590*cda5da8dSAndroid Build Coastguard Worker return ttypager 1591*cda5da8dSAndroid Build Coastguard Worker finally: 1592*cda5da8dSAndroid Build Coastguard Worker os.unlink(filename) 1593*cda5da8dSAndroid Build Coastguard Worker 1594*cda5da8dSAndroid Build Coastguard Workerdef plain(text): 1595*cda5da8dSAndroid Build Coastguard Worker """Remove boldface formatting from text.""" 1596*cda5da8dSAndroid Build Coastguard Worker return re.sub('.\b', '', text) 1597*cda5da8dSAndroid Build Coastguard Worker 1598*cda5da8dSAndroid Build Coastguard Workerdef pipepager(text, cmd): 1599*cda5da8dSAndroid Build Coastguard Worker """Page through text by feeding it to another program.""" 1600*cda5da8dSAndroid Build Coastguard Worker import subprocess 1601*cda5da8dSAndroid Build Coastguard Worker proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, 1602*cda5da8dSAndroid Build Coastguard Worker errors='backslashreplace') 1603*cda5da8dSAndroid Build Coastguard Worker try: 1604*cda5da8dSAndroid Build Coastguard Worker with proc.stdin as pipe: 1605*cda5da8dSAndroid Build Coastguard Worker try: 1606*cda5da8dSAndroid Build Coastguard Worker pipe.write(text) 1607*cda5da8dSAndroid Build Coastguard Worker except KeyboardInterrupt: 1608*cda5da8dSAndroid Build Coastguard Worker # We've hereby abandoned whatever text hasn't been written, 1609*cda5da8dSAndroid Build Coastguard Worker # but the pager is still in control of the terminal. 1610*cda5da8dSAndroid Build Coastguard Worker pass 1611*cda5da8dSAndroid Build Coastguard Worker except OSError: 1612*cda5da8dSAndroid Build Coastguard Worker pass # Ignore broken pipes caused by quitting the pager program. 1613*cda5da8dSAndroid Build Coastguard Worker while True: 1614*cda5da8dSAndroid Build Coastguard Worker try: 1615*cda5da8dSAndroid Build Coastguard Worker proc.wait() 1616*cda5da8dSAndroid Build Coastguard Worker break 1617*cda5da8dSAndroid Build Coastguard Worker except KeyboardInterrupt: 1618*cda5da8dSAndroid Build Coastguard Worker # Ignore ctl-c like the pager itself does. Otherwise the pager is 1619*cda5da8dSAndroid Build Coastguard Worker # left running and the terminal is in raw mode and unusable. 1620*cda5da8dSAndroid Build Coastguard Worker pass 1621*cda5da8dSAndroid Build Coastguard Worker 1622*cda5da8dSAndroid Build Coastguard Workerdef tempfilepager(text, cmd): 1623*cda5da8dSAndroid Build Coastguard Worker """Page through text by invoking a program on a temporary file.""" 1624*cda5da8dSAndroid Build Coastguard Worker import tempfile 1625*cda5da8dSAndroid Build Coastguard Worker with tempfile.TemporaryDirectory() as tempdir: 1626*cda5da8dSAndroid Build Coastguard Worker filename = os.path.join(tempdir, 'pydoc.out') 1627*cda5da8dSAndroid Build Coastguard Worker with open(filename, 'w', errors='backslashreplace', 1628*cda5da8dSAndroid Build Coastguard Worker encoding=os.device_encoding(0) if 1629*cda5da8dSAndroid Build Coastguard Worker sys.platform == 'win32' else None 1630*cda5da8dSAndroid Build Coastguard Worker ) as file: 1631*cda5da8dSAndroid Build Coastguard Worker file.write(text) 1632*cda5da8dSAndroid Build Coastguard Worker os.system(cmd + ' "' + filename + '"') 1633*cda5da8dSAndroid Build Coastguard Worker 1634*cda5da8dSAndroid Build Coastguard Workerdef _escape_stdout(text): 1635*cda5da8dSAndroid Build Coastguard Worker # Escape non-encodable characters to avoid encoding errors later 1636*cda5da8dSAndroid Build Coastguard Worker encoding = getattr(sys.stdout, 'encoding', None) or 'utf-8' 1637*cda5da8dSAndroid Build Coastguard Worker return text.encode(encoding, 'backslashreplace').decode(encoding) 1638*cda5da8dSAndroid Build Coastguard Worker 1639*cda5da8dSAndroid Build Coastguard Workerdef ttypager(text): 1640*cda5da8dSAndroid Build Coastguard Worker """Page through text on a text terminal.""" 1641*cda5da8dSAndroid Build Coastguard Worker lines = plain(_escape_stdout(text)).split('\n') 1642*cda5da8dSAndroid Build Coastguard Worker try: 1643*cda5da8dSAndroid Build Coastguard Worker import tty 1644*cda5da8dSAndroid Build Coastguard Worker fd = sys.stdin.fileno() 1645*cda5da8dSAndroid Build Coastguard Worker old = tty.tcgetattr(fd) 1646*cda5da8dSAndroid Build Coastguard Worker tty.setcbreak(fd) 1647*cda5da8dSAndroid Build Coastguard Worker getchar = lambda: sys.stdin.read(1) 1648*cda5da8dSAndroid Build Coastguard Worker except (ImportError, AttributeError, io.UnsupportedOperation): 1649*cda5da8dSAndroid Build Coastguard Worker tty = None 1650*cda5da8dSAndroid Build Coastguard Worker getchar = lambda: sys.stdin.readline()[:-1][:1] 1651*cda5da8dSAndroid Build Coastguard Worker 1652*cda5da8dSAndroid Build Coastguard Worker try: 1653*cda5da8dSAndroid Build Coastguard Worker try: 1654*cda5da8dSAndroid Build Coastguard Worker h = int(os.environ.get('LINES', 0)) 1655*cda5da8dSAndroid Build Coastguard Worker except ValueError: 1656*cda5da8dSAndroid Build Coastguard Worker h = 0 1657*cda5da8dSAndroid Build Coastguard Worker if h <= 1: 1658*cda5da8dSAndroid Build Coastguard Worker h = 25 1659*cda5da8dSAndroid Build Coastguard Worker r = inc = h - 1 1660*cda5da8dSAndroid Build Coastguard Worker sys.stdout.write('\n'.join(lines[:inc]) + '\n') 1661*cda5da8dSAndroid Build Coastguard Worker while lines[r:]: 1662*cda5da8dSAndroid Build Coastguard Worker sys.stdout.write('-- more --') 1663*cda5da8dSAndroid Build Coastguard Worker sys.stdout.flush() 1664*cda5da8dSAndroid Build Coastguard Worker c = getchar() 1665*cda5da8dSAndroid Build Coastguard Worker 1666*cda5da8dSAndroid Build Coastguard Worker if c in ('q', 'Q'): 1667*cda5da8dSAndroid Build Coastguard Worker sys.stdout.write('\r \r') 1668*cda5da8dSAndroid Build Coastguard Worker break 1669*cda5da8dSAndroid Build Coastguard Worker elif c in ('\r', '\n'): 1670*cda5da8dSAndroid Build Coastguard Worker sys.stdout.write('\r \r' + lines[r] + '\n') 1671*cda5da8dSAndroid Build Coastguard Worker r = r + 1 1672*cda5da8dSAndroid Build Coastguard Worker continue 1673*cda5da8dSAndroid Build Coastguard Worker if c in ('b', 'B', '\x1b'): 1674*cda5da8dSAndroid Build Coastguard Worker r = r - inc - inc 1675*cda5da8dSAndroid Build Coastguard Worker if r < 0: r = 0 1676*cda5da8dSAndroid Build Coastguard Worker sys.stdout.write('\n' + '\n'.join(lines[r:r+inc]) + '\n') 1677*cda5da8dSAndroid Build Coastguard Worker r = r + inc 1678*cda5da8dSAndroid Build Coastguard Worker 1679*cda5da8dSAndroid Build Coastguard Worker finally: 1680*cda5da8dSAndroid Build Coastguard Worker if tty: 1681*cda5da8dSAndroid Build Coastguard Worker tty.tcsetattr(fd, tty.TCSAFLUSH, old) 1682*cda5da8dSAndroid Build Coastguard Worker 1683*cda5da8dSAndroid Build Coastguard Workerdef plainpager(text): 1684*cda5da8dSAndroid Build Coastguard Worker """Simply print unformatted text. This is the ultimate fallback.""" 1685*cda5da8dSAndroid Build Coastguard Worker sys.stdout.write(plain(_escape_stdout(text))) 1686*cda5da8dSAndroid Build Coastguard Worker 1687*cda5da8dSAndroid Build Coastguard Workerdef describe(thing): 1688*cda5da8dSAndroid Build Coastguard Worker """Produce a short description of the given thing.""" 1689*cda5da8dSAndroid Build Coastguard Worker if inspect.ismodule(thing): 1690*cda5da8dSAndroid Build Coastguard Worker if thing.__name__ in sys.builtin_module_names: 1691*cda5da8dSAndroid Build Coastguard Worker return 'built-in module ' + thing.__name__ 1692*cda5da8dSAndroid Build Coastguard Worker if hasattr(thing, '__path__'): 1693*cda5da8dSAndroid Build Coastguard Worker return 'package ' + thing.__name__ 1694*cda5da8dSAndroid Build Coastguard Worker else: 1695*cda5da8dSAndroid Build Coastguard Worker return 'module ' + thing.__name__ 1696*cda5da8dSAndroid Build Coastguard Worker if inspect.isbuiltin(thing): 1697*cda5da8dSAndroid Build Coastguard Worker return 'built-in function ' + thing.__name__ 1698*cda5da8dSAndroid Build Coastguard Worker if inspect.isgetsetdescriptor(thing): 1699*cda5da8dSAndroid Build Coastguard Worker return 'getset descriptor %s.%s.%s' % ( 1700*cda5da8dSAndroid Build Coastguard Worker thing.__objclass__.__module__, thing.__objclass__.__name__, 1701*cda5da8dSAndroid Build Coastguard Worker thing.__name__) 1702*cda5da8dSAndroid Build Coastguard Worker if inspect.ismemberdescriptor(thing): 1703*cda5da8dSAndroid Build Coastguard Worker return 'member descriptor %s.%s.%s' % ( 1704*cda5da8dSAndroid Build Coastguard Worker thing.__objclass__.__module__, thing.__objclass__.__name__, 1705*cda5da8dSAndroid Build Coastguard Worker thing.__name__) 1706*cda5da8dSAndroid Build Coastguard Worker if inspect.isclass(thing): 1707*cda5da8dSAndroid Build Coastguard Worker return 'class ' + thing.__name__ 1708*cda5da8dSAndroid Build Coastguard Worker if inspect.isfunction(thing): 1709*cda5da8dSAndroid Build Coastguard Worker return 'function ' + thing.__name__ 1710*cda5da8dSAndroid Build Coastguard Worker if inspect.ismethod(thing): 1711*cda5da8dSAndroid Build Coastguard Worker return 'method ' + thing.__name__ 1712*cda5da8dSAndroid Build Coastguard Worker return type(thing).__name__ 1713*cda5da8dSAndroid Build Coastguard Worker 1714*cda5da8dSAndroid Build Coastguard Workerdef locate(path, forceload=0): 1715*cda5da8dSAndroid Build Coastguard Worker """Locate an object by name or dotted path, importing as necessary.""" 1716*cda5da8dSAndroid Build Coastguard Worker parts = [part for part in path.split('.') if part] 1717*cda5da8dSAndroid Build Coastguard Worker module, n = None, 0 1718*cda5da8dSAndroid Build Coastguard Worker while n < len(parts): 1719*cda5da8dSAndroid Build Coastguard Worker nextmodule = safeimport('.'.join(parts[:n+1]), forceload) 1720*cda5da8dSAndroid Build Coastguard Worker if nextmodule: module, n = nextmodule, n + 1 1721*cda5da8dSAndroid Build Coastguard Worker else: break 1722*cda5da8dSAndroid Build Coastguard Worker if module: 1723*cda5da8dSAndroid Build Coastguard Worker object = module 1724*cda5da8dSAndroid Build Coastguard Worker else: 1725*cda5da8dSAndroid Build Coastguard Worker object = builtins 1726*cda5da8dSAndroid Build Coastguard Worker for part in parts[n:]: 1727*cda5da8dSAndroid Build Coastguard Worker try: 1728*cda5da8dSAndroid Build Coastguard Worker object = getattr(object, part) 1729*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 1730*cda5da8dSAndroid Build Coastguard Worker return None 1731*cda5da8dSAndroid Build Coastguard Worker return object 1732*cda5da8dSAndroid Build Coastguard Worker 1733*cda5da8dSAndroid Build Coastguard Worker# --------------------------------------- interactive interpreter interface 1734*cda5da8dSAndroid Build Coastguard Worker 1735*cda5da8dSAndroid Build Coastguard Workertext = TextDoc() 1736*cda5da8dSAndroid Build Coastguard Workerplaintext = _PlainTextDoc() 1737*cda5da8dSAndroid Build Coastguard Workerhtml = HTMLDoc() 1738*cda5da8dSAndroid Build Coastguard Worker 1739*cda5da8dSAndroid Build Coastguard Workerdef resolve(thing, forceload=0): 1740*cda5da8dSAndroid Build Coastguard Worker """Given an object or a path to an object, get the object and its name.""" 1741*cda5da8dSAndroid Build Coastguard Worker if isinstance(thing, str): 1742*cda5da8dSAndroid Build Coastguard Worker object = locate(thing, forceload) 1743*cda5da8dSAndroid Build Coastguard Worker if object is None: 1744*cda5da8dSAndroid Build Coastguard Worker raise ImportError('''\ 1745*cda5da8dSAndroid Build Coastguard WorkerNo Python documentation found for %r. 1746*cda5da8dSAndroid Build Coastguard WorkerUse help() to get the interactive help utility. 1747*cda5da8dSAndroid Build Coastguard WorkerUse help(str) for help on the str class.''' % thing) 1748*cda5da8dSAndroid Build Coastguard Worker return object, thing 1749*cda5da8dSAndroid Build Coastguard Worker else: 1750*cda5da8dSAndroid Build Coastguard Worker name = getattr(thing, '__name__', None) 1751*cda5da8dSAndroid Build Coastguard Worker return thing, name if isinstance(name, str) else None 1752*cda5da8dSAndroid Build Coastguard Worker 1753*cda5da8dSAndroid Build Coastguard Workerdef render_doc(thing, title='Python Library Documentation: %s', forceload=0, 1754*cda5da8dSAndroid Build Coastguard Worker renderer=None): 1755*cda5da8dSAndroid Build Coastguard Worker """Render text documentation, given an object or a path to an object.""" 1756*cda5da8dSAndroid Build Coastguard Worker if renderer is None: 1757*cda5da8dSAndroid Build Coastguard Worker renderer = text 1758*cda5da8dSAndroid Build Coastguard Worker object, name = resolve(thing, forceload) 1759*cda5da8dSAndroid Build Coastguard Worker desc = describe(object) 1760*cda5da8dSAndroid Build Coastguard Worker module = inspect.getmodule(object) 1761*cda5da8dSAndroid Build Coastguard Worker if name and '.' in name: 1762*cda5da8dSAndroid Build Coastguard Worker desc += ' in ' + name[:name.rfind('.')] 1763*cda5da8dSAndroid Build Coastguard Worker elif module and module is not object: 1764*cda5da8dSAndroid Build Coastguard Worker desc += ' in module ' + module.__name__ 1765*cda5da8dSAndroid Build Coastguard Worker 1766*cda5da8dSAndroid Build Coastguard Worker if not (inspect.ismodule(object) or 1767*cda5da8dSAndroid Build Coastguard Worker inspect.isclass(object) or 1768*cda5da8dSAndroid Build Coastguard Worker inspect.isroutine(object) or 1769*cda5da8dSAndroid Build Coastguard Worker inspect.isdatadescriptor(object) or 1770*cda5da8dSAndroid Build Coastguard Worker _getdoc(object)): 1771*cda5da8dSAndroid Build Coastguard Worker # If the passed object is a piece of data or an instance, 1772*cda5da8dSAndroid Build Coastguard Worker # document its available methods instead of its value. 1773*cda5da8dSAndroid Build Coastguard Worker if hasattr(object, '__origin__'): 1774*cda5da8dSAndroid Build Coastguard Worker object = object.__origin__ 1775*cda5da8dSAndroid Build Coastguard Worker else: 1776*cda5da8dSAndroid Build Coastguard Worker object = type(object) 1777*cda5da8dSAndroid Build Coastguard Worker desc += ' object' 1778*cda5da8dSAndroid Build Coastguard Worker return title % desc + '\n\n' + renderer.document(object, name) 1779*cda5da8dSAndroid Build Coastguard Worker 1780*cda5da8dSAndroid Build Coastguard Workerdef doc(thing, title='Python Library Documentation: %s', forceload=0, 1781*cda5da8dSAndroid Build Coastguard Worker output=None): 1782*cda5da8dSAndroid Build Coastguard Worker """Display text documentation, given an object or a path to an object.""" 1783*cda5da8dSAndroid Build Coastguard Worker if output is None: 1784*cda5da8dSAndroid Build Coastguard Worker pager(render_doc(thing, title, forceload)) 1785*cda5da8dSAndroid Build Coastguard Worker else: 1786*cda5da8dSAndroid Build Coastguard Worker output.write(render_doc(thing, title, forceload, plaintext)) 1787*cda5da8dSAndroid Build Coastguard Worker 1788*cda5da8dSAndroid Build Coastguard Workerdef writedoc(thing, forceload=0): 1789*cda5da8dSAndroid Build Coastguard Worker """Write HTML documentation to a file in the current directory.""" 1790*cda5da8dSAndroid Build Coastguard Worker object, name = resolve(thing, forceload) 1791*cda5da8dSAndroid Build Coastguard Worker page = html.page(describe(object), html.document(object, name)) 1792*cda5da8dSAndroid Build Coastguard Worker with open(name + '.html', 'w', encoding='utf-8') as file: 1793*cda5da8dSAndroid Build Coastguard Worker file.write(page) 1794*cda5da8dSAndroid Build Coastguard Worker print('wrote', name + '.html') 1795*cda5da8dSAndroid Build Coastguard Worker 1796*cda5da8dSAndroid Build Coastguard Workerdef writedocs(dir, pkgpath='', done=None): 1797*cda5da8dSAndroid Build Coastguard Worker """Write out HTML documentation for all modules in a directory tree.""" 1798*cda5da8dSAndroid Build Coastguard Worker if done is None: done = {} 1799*cda5da8dSAndroid Build Coastguard Worker for importer, modname, ispkg in pkgutil.walk_packages([dir], pkgpath): 1800*cda5da8dSAndroid Build Coastguard Worker writedoc(modname) 1801*cda5da8dSAndroid Build Coastguard Worker return 1802*cda5da8dSAndroid Build Coastguard Worker 1803*cda5da8dSAndroid Build Coastguard Workerclass Helper: 1804*cda5da8dSAndroid Build Coastguard Worker 1805*cda5da8dSAndroid Build Coastguard Worker # These dictionaries map a topic name to either an alias, or a tuple 1806*cda5da8dSAndroid Build Coastguard Worker # (label, seealso-items). The "label" is the label of the corresponding 1807*cda5da8dSAndroid Build Coastguard Worker # section in the .rst file under Doc/ and an index into the dictionary 1808*cda5da8dSAndroid Build Coastguard Worker # in pydoc_data/topics.py. 1809*cda5da8dSAndroid Build Coastguard Worker # 1810*cda5da8dSAndroid Build Coastguard Worker # CAUTION: if you change one of these dictionaries, be sure to adapt the 1811*cda5da8dSAndroid Build Coastguard Worker # list of needed labels in Doc/tools/extensions/pyspecific.py and 1812*cda5da8dSAndroid Build Coastguard Worker # regenerate the pydoc_data/topics.py file by running 1813*cda5da8dSAndroid Build Coastguard Worker # make pydoc-topics 1814*cda5da8dSAndroid Build Coastguard Worker # in Doc/ and copying the output file into the Lib/ directory. 1815*cda5da8dSAndroid Build Coastguard Worker 1816*cda5da8dSAndroid Build Coastguard Worker keywords = { 1817*cda5da8dSAndroid Build Coastguard Worker 'False': '', 1818*cda5da8dSAndroid Build Coastguard Worker 'None': '', 1819*cda5da8dSAndroid Build Coastguard Worker 'True': '', 1820*cda5da8dSAndroid Build Coastguard Worker 'and': 'BOOLEAN', 1821*cda5da8dSAndroid Build Coastguard Worker 'as': 'with', 1822*cda5da8dSAndroid Build Coastguard Worker 'assert': ('assert', ''), 1823*cda5da8dSAndroid Build Coastguard Worker 'async': ('async', ''), 1824*cda5da8dSAndroid Build Coastguard Worker 'await': ('await', ''), 1825*cda5da8dSAndroid Build Coastguard Worker 'break': ('break', 'while for'), 1826*cda5da8dSAndroid Build Coastguard Worker 'class': ('class', 'CLASSES SPECIALMETHODS'), 1827*cda5da8dSAndroid Build Coastguard Worker 'continue': ('continue', 'while for'), 1828*cda5da8dSAndroid Build Coastguard Worker 'def': ('function', ''), 1829*cda5da8dSAndroid Build Coastguard Worker 'del': ('del', 'BASICMETHODS'), 1830*cda5da8dSAndroid Build Coastguard Worker 'elif': 'if', 1831*cda5da8dSAndroid Build Coastguard Worker 'else': ('else', 'while for'), 1832*cda5da8dSAndroid Build Coastguard Worker 'except': 'try', 1833*cda5da8dSAndroid Build Coastguard Worker 'finally': 'try', 1834*cda5da8dSAndroid Build Coastguard Worker 'for': ('for', 'break continue while'), 1835*cda5da8dSAndroid Build Coastguard Worker 'from': 'import', 1836*cda5da8dSAndroid Build Coastguard Worker 'global': ('global', 'nonlocal NAMESPACES'), 1837*cda5da8dSAndroid Build Coastguard Worker 'if': ('if', 'TRUTHVALUE'), 1838*cda5da8dSAndroid Build Coastguard Worker 'import': ('import', 'MODULES'), 1839*cda5da8dSAndroid Build Coastguard Worker 'in': ('in', 'SEQUENCEMETHODS'), 1840*cda5da8dSAndroid Build Coastguard Worker 'is': 'COMPARISON', 1841*cda5da8dSAndroid Build Coastguard Worker 'lambda': ('lambda', 'FUNCTIONS'), 1842*cda5da8dSAndroid Build Coastguard Worker 'nonlocal': ('nonlocal', 'global NAMESPACES'), 1843*cda5da8dSAndroid Build Coastguard Worker 'not': 'BOOLEAN', 1844*cda5da8dSAndroid Build Coastguard Worker 'or': 'BOOLEAN', 1845*cda5da8dSAndroid Build Coastguard Worker 'pass': ('pass', ''), 1846*cda5da8dSAndroid Build Coastguard Worker 'raise': ('raise', 'EXCEPTIONS'), 1847*cda5da8dSAndroid Build Coastguard Worker 'return': ('return', 'FUNCTIONS'), 1848*cda5da8dSAndroid Build Coastguard Worker 'try': ('try', 'EXCEPTIONS'), 1849*cda5da8dSAndroid Build Coastguard Worker 'while': ('while', 'break continue if TRUTHVALUE'), 1850*cda5da8dSAndroid Build Coastguard Worker 'with': ('with', 'CONTEXTMANAGERS EXCEPTIONS yield'), 1851*cda5da8dSAndroid Build Coastguard Worker 'yield': ('yield', ''), 1852*cda5da8dSAndroid Build Coastguard Worker } 1853*cda5da8dSAndroid Build Coastguard Worker # Either add symbols to this dictionary or to the symbols dictionary 1854*cda5da8dSAndroid Build Coastguard Worker # directly: Whichever is easier. They are merged later. 1855*cda5da8dSAndroid Build Coastguard Worker _strprefixes = [p + q for p in ('b', 'f', 'r', 'u') for q in ("'", '"')] 1856*cda5da8dSAndroid Build Coastguard Worker _symbols_inverse = { 1857*cda5da8dSAndroid Build Coastguard Worker 'STRINGS' : ("'", "'''", '"', '"""', *_strprefixes), 1858*cda5da8dSAndroid Build Coastguard Worker 'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&', 1859*cda5da8dSAndroid Build Coastguard Worker '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'), 1860*cda5da8dSAndroid Build Coastguard Worker 'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'), 1861*cda5da8dSAndroid Build Coastguard Worker 'UNARY' : ('-', '~'), 1862*cda5da8dSAndroid Build Coastguard Worker 'AUGMENTEDASSIGNMENT' : ('+=', '-=', '*=', '/=', '%=', '&=', '|=', 1863*cda5da8dSAndroid Build Coastguard Worker '^=', '<<=', '>>=', '**=', '//='), 1864*cda5da8dSAndroid Build Coastguard Worker 'BITWISE' : ('<<', '>>', '&', '|', '^', '~'), 1865*cda5da8dSAndroid Build Coastguard Worker 'COMPLEX' : ('j', 'J') 1866*cda5da8dSAndroid Build Coastguard Worker } 1867*cda5da8dSAndroid Build Coastguard Worker symbols = { 1868*cda5da8dSAndroid Build Coastguard Worker '%': 'OPERATORS FORMATTING', 1869*cda5da8dSAndroid Build Coastguard Worker '**': 'POWER', 1870*cda5da8dSAndroid Build Coastguard Worker ',': 'TUPLES LISTS FUNCTIONS', 1871*cda5da8dSAndroid Build Coastguard Worker '.': 'ATTRIBUTES FLOAT MODULES OBJECTS', 1872*cda5da8dSAndroid Build Coastguard Worker '...': 'ELLIPSIS', 1873*cda5da8dSAndroid Build Coastguard Worker ':': 'SLICINGS DICTIONARYLITERALS', 1874*cda5da8dSAndroid Build Coastguard Worker '@': 'def class', 1875*cda5da8dSAndroid Build Coastguard Worker '\\': 'STRINGS', 1876*cda5da8dSAndroid Build Coastguard Worker '_': 'PRIVATENAMES', 1877*cda5da8dSAndroid Build Coastguard Worker '__': 'PRIVATENAMES SPECIALMETHODS', 1878*cda5da8dSAndroid Build Coastguard Worker '`': 'BACKQUOTES', 1879*cda5da8dSAndroid Build Coastguard Worker '(': 'TUPLES FUNCTIONS CALLS', 1880*cda5da8dSAndroid Build Coastguard Worker ')': 'TUPLES FUNCTIONS CALLS', 1881*cda5da8dSAndroid Build Coastguard Worker '[': 'LISTS SUBSCRIPTS SLICINGS', 1882*cda5da8dSAndroid Build Coastguard Worker ']': 'LISTS SUBSCRIPTS SLICINGS' 1883*cda5da8dSAndroid Build Coastguard Worker } 1884*cda5da8dSAndroid Build Coastguard Worker for topic, symbols_ in _symbols_inverse.items(): 1885*cda5da8dSAndroid Build Coastguard Worker for symbol in symbols_: 1886*cda5da8dSAndroid Build Coastguard Worker topics = symbols.get(symbol, topic) 1887*cda5da8dSAndroid Build Coastguard Worker if topic not in topics: 1888*cda5da8dSAndroid Build Coastguard Worker topics = topics + ' ' + topic 1889*cda5da8dSAndroid Build Coastguard Worker symbols[symbol] = topics 1890*cda5da8dSAndroid Build Coastguard Worker del topic, symbols_, symbol, topics 1891*cda5da8dSAndroid Build Coastguard Worker 1892*cda5da8dSAndroid Build Coastguard Worker topics = { 1893*cda5da8dSAndroid Build Coastguard Worker 'TYPES': ('types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS ' 1894*cda5da8dSAndroid Build Coastguard Worker 'FUNCTIONS CLASSES MODULES FILES inspect'), 1895*cda5da8dSAndroid Build Coastguard Worker 'STRINGS': ('strings', 'str UNICODE SEQUENCES STRINGMETHODS ' 1896*cda5da8dSAndroid Build Coastguard Worker 'FORMATTING TYPES'), 1897*cda5da8dSAndroid Build Coastguard Worker 'STRINGMETHODS': ('string-methods', 'STRINGS FORMATTING'), 1898*cda5da8dSAndroid Build Coastguard Worker 'FORMATTING': ('formatstrings', 'OPERATORS'), 1899*cda5da8dSAndroid Build Coastguard Worker 'UNICODE': ('strings', 'encodings unicode SEQUENCES STRINGMETHODS ' 1900*cda5da8dSAndroid Build Coastguard Worker 'FORMATTING TYPES'), 1901*cda5da8dSAndroid Build Coastguard Worker 'NUMBERS': ('numbers', 'INTEGER FLOAT COMPLEX TYPES'), 1902*cda5da8dSAndroid Build Coastguard Worker 'INTEGER': ('integers', 'int range'), 1903*cda5da8dSAndroid Build Coastguard Worker 'FLOAT': ('floating', 'float math'), 1904*cda5da8dSAndroid Build Coastguard Worker 'COMPLEX': ('imaginary', 'complex cmath'), 1905*cda5da8dSAndroid Build Coastguard Worker 'SEQUENCES': ('typesseq', 'STRINGMETHODS FORMATTING range LISTS'), 1906*cda5da8dSAndroid Build Coastguard Worker 'MAPPINGS': 'DICTIONARIES', 1907*cda5da8dSAndroid Build Coastguard Worker 'FUNCTIONS': ('typesfunctions', 'def TYPES'), 1908*cda5da8dSAndroid Build Coastguard Worker 'METHODS': ('typesmethods', 'class def CLASSES TYPES'), 1909*cda5da8dSAndroid Build Coastguard Worker 'CODEOBJECTS': ('bltin-code-objects', 'compile FUNCTIONS TYPES'), 1910*cda5da8dSAndroid Build Coastguard Worker 'TYPEOBJECTS': ('bltin-type-objects', 'types TYPES'), 1911*cda5da8dSAndroid Build Coastguard Worker 'FRAMEOBJECTS': 'TYPES', 1912*cda5da8dSAndroid Build Coastguard Worker 'TRACEBACKS': 'TYPES', 1913*cda5da8dSAndroid Build Coastguard Worker 'NONE': ('bltin-null-object', ''), 1914*cda5da8dSAndroid Build Coastguard Worker 'ELLIPSIS': ('bltin-ellipsis-object', 'SLICINGS'), 1915*cda5da8dSAndroid Build Coastguard Worker 'SPECIALATTRIBUTES': ('specialattrs', ''), 1916*cda5da8dSAndroid Build Coastguard Worker 'CLASSES': ('types', 'class SPECIALMETHODS PRIVATENAMES'), 1917*cda5da8dSAndroid Build Coastguard Worker 'MODULES': ('typesmodules', 'import'), 1918*cda5da8dSAndroid Build Coastguard Worker 'PACKAGES': 'import', 1919*cda5da8dSAndroid Build Coastguard Worker 'EXPRESSIONS': ('operator-summary', 'lambda or and not in is BOOLEAN ' 1920*cda5da8dSAndroid Build Coastguard Worker 'COMPARISON BITWISE SHIFTING BINARY FORMATTING POWER ' 1921*cda5da8dSAndroid Build Coastguard Worker 'UNARY ATTRIBUTES SUBSCRIPTS SLICINGS CALLS TUPLES ' 1922*cda5da8dSAndroid Build Coastguard Worker 'LISTS DICTIONARIES'), 1923*cda5da8dSAndroid Build Coastguard Worker 'OPERATORS': 'EXPRESSIONS', 1924*cda5da8dSAndroid Build Coastguard Worker 'PRECEDENCE': 'EXPRESSIONS', 1925*cda5da8dSAndroid Build Coastguard Worker 'OBJECTS': ('objects', 'TYPES'), 1926*cda5da8dSAndroid Build Coastguard Worker 'SPECIALMETHODS': ('specialnames', 'BASICMETHODS ATTRIBUTEMETHODS ' 1927*cda5da8dSAndroid Build Coastguard Worker 'CALLABLEMETHODS SEQUENCEMETHODS MAPPINGMETHODS ' 1928*cda5da8dSAndroid Build Coastguard Worker 'NUMBERMETHODS CLASSES'), 1929*cda5da8dSAndroid Build Coastguard Worker 'BASICMETHODS': ('customization', 'hash repr str SPECIALMETHODS'), 1930*cda5da8dSAndroid Build Coastguard Worker 'ATTRIBUTEMETHODS': ('attribute-access', 'ATTRIBUTES SPECIALMETHODS'), 1931*cda5da8dSAndroid Build Coastguard Worker 'CALLABLEMETHODS': ('callable-types', 'CALLS SPECIALMETHODS'), 1932*cda5da8dSAndroid Build Coastguard Worker 'SEQUENCEMETHODS': ('sequence-types', 'SEQUENCES SEQUENCEMETHODS ' 1933*cda5da8dSAndroid Build Coastguard Worker 'SPECIALMETHODS'), 1934*cda5da8dSAndroid Build Coastguard Worker 'MAPPINGMETHODS': ('sequence-types', 'MAPPINGS SPECIALMETHODS'), 1935*cda5da8dSAndroid Build Coastguard Worker 'NUMBERMETHODS': ('numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT ' 1936*cda5da8dSAndroid Build Coastguard Worker 'SPECIALMETHODS'), 1937*cda5da8dSAndroid Build Coastguard Worker 'EXECUTION': ('execmodel', 'NAMESPACES DYNAMICFEATURES EXCEPTIONS'), 1938*cda5da8dSAndroid Build Coastguard Worker 'NAMESPACES': ('naming', 'global nonlocal ASSIGNMENT DELETION DYNAMICFEATURES'), 1939*cda5da8dSAndroid Build Coastguard Worker 'DYNAMICFEATURES': ('dynamic-features', ''), 1940*cda5da8dSAndroid Build Coastguard Worker 'SCOPING': 'NAMESPACES', 1941*cda5da8dSAndroid Build Coastguard Worker 'FRAMES': 'NAMESPACES', 1942*cda5da8dSAndroid Build Coastguard Worker 'EXCEPTIONS': ('exceptions', 'try except finally raise'), 1943*cda5da8dSAndroid Build Coastguard Worker 'CONVERSIONS': ('conversions', ''), 1944*cda5da8dSAndroid Build Coastguard Worker 'IDENTIFIERS': ('identifiers', 'keywords SPECIALIDENTIFIERS'), 1945*cda5da8dSAndroid Build Coastguard Worker 'SPECIALIDENTIFIERS': ('id-classes', ''), 1946*cda5da8dSAndroid Build Coastguard Worker 'PRIVATENAMES': ('atom-identifiers', ''), 1947*cda5da8dSAndroid Build Coastguard Worker 'LITERALS': ('atom-literals', 'STRINGS NUMBERS TUPLELITERALS ' 1948*cda5da8dSAndroid Build Coastguard Worker 'LISTLITERALS DICTIONARYLITERALS'), 1949*cda5da8dSAndroid Build Coastguard Worker 'TUPLES': 'SEQUENCES', 1950*cda5da8dSAndroid Build Coastguard Worker 'TUPLELITERALS': ('exprlists', 'TUPLES LITERALS'), 1951*cda5da8dSAndroid Build Coastguard Worker 'LISTS': ('typesseq-mutable', 'LISTLITERALS'), 1952*cda5da8dSAndroid Build Coastguard Worker 'LISTLITERALS': ('lists', 'LISTS LITERALS'), 1953*cda5da8dSAndroid Build Coastguard Worker 'DICTIONARIES': ('typesmapping', 'DICTIONARYLITERALS'), 1954*cda5da8dSAndroid Build Coastguard Worker 'DICTIONARYLITERALS': ('dict', 'DICTIONARIES LITERALS'), 1955*cda5da8dSAndroid Build Coastguard Worker 'ATTRIBUTES': ('attribute-references', 'getattr hasattr setattr ATTRIBUTEMETHODS'), 1956*cda5da8dSAndroid Build Coastguard Worker 'SUBSCRIPTS': ('subscriptions', 'SEQUENCEMETHODS'), 1957*cda5da8dSAndroid Build Coastguard Worker 'SLICINGS': ('slicings', 'SEQUENCEMETHODS'), 1958*cda5da8dSAndroid Build Coastguard Worker 'CALLS': ('calls', 'EXPRESSIONS'), 1959*cda5da8dSAndroid Build Coastguard Worker 'POWER': ('power', 'EXPRESSIONS'), 1960*cda5da8dSAndroid Build Coastguard Worker 'UNARY': ('unary', 'EXPRESSIONS'), 1961*cda5da8dSAndroid Build Coastguard Worker 'BINARY': ('binary', 'EXPRESSIONS'), 1962*cda5da8dSAndroid Build Coastguard Worker 'SHIFTING': ('shifting', 'EXPRESSIONS'), 1963*cda5da8dSAndroid Build Coastguard Worker 'BITWISE': ('bitwise', 'EXPRESSIONS'), 1964*cda5da8dSAndroid Build Coastguard Worker 'COMPARISON': ('comparisons', 'EXPRESSIONS BASICMETHODS'), 1965*cda5da8dSAndroid Build Coastguard Worker 'BOOLEAN': ('booleans', 'EXPRESSIONS TRUTHVALUE'), 1966*cda5da8dSAndroid Build Coastguard Worker 'ASSERTION': 'assert', 1967*cda5da8dSAndroid Build Coastguard Worker 'ASSIGNMENT': ('assignment', 'AUGMENTEDASSIGNMENT'), 1968*cda5da8dSAndroid Build Coastguard Worker 'AUGMENTEDASSIGNMENT': ('augassign', 'NUMBERMETHODS'), 1969*cda5da8dSAndroid Build Coastguard Worker 'DELETION': 'del', 1970*cda5da8dSAndroid Build Coastguard Worker 'RETURNING': 'return', 1971*cda5da8dSAndroid Build Coastguard Worker 'IMPORTING': 'import', 1972*cda5da8dSAndroid Build Coastguard Worker 'CONDITIONAL': 'if', 1973*cda5da8dSAndroid Build Coastguard Worker 'LOOPING': ('compound', 'for while break continue'), 1974*cda5da8dSAndroid Build Coastguard Worker 'TRUTHVALUE': ('truth', 'if while and or not BASICMETHODS'), 1975*cda5da8dSAndroid Build Coastguard Worker 'DEBUGGING': ('debugger', 'pdb'), 1976*cda5da8dSAndroid Build Coastguard Worker 'CONTEXTMANAGERS': ('context-managers', 'with'), 1977*cda5da8dSAndroid Build Coastguard Worker } 1978*cda5da8dSAndroid Build Coastguard Worker 1979*cda5da8dSAndroid Build Coastguard Worker def __init__(self, input=None, output=None): 1980*cda5da8dSAndroid Build Coastguard Worker self._input = input 1981*cda5da8dSAndroid Build Coastguard Worker self._output = output 1982*cda5da8dSAndroid Build Coastguard Worker 1983*cda5da8dSAndroid Build Coastguard Worker @property 1984*cda5da8dSAndroid Build Coastguard Worker def input(self): 1985*cda5da8dSAndroid Build Coastguard Worker return self._input or sys.stdin 1986*cda5da8dSAndroid Build Coastguard Worker 1987*cda5da8dSAndroid Build Coastguard Worker @property 1988*cda5da8dSAndroid Build Coastguard Worker def output(self): 1989*cda5da8dSAndroid Build Coastguard Worker return self._output or sys.stdout 1990*cda5da8dSAndroid Build Coastguard Worker 1991*cda5da8dSAndroid Build Coastguard Worker def __repr__(self): 1992*cda5da8dSAndroid Build Coastguard Worker if inspect.stack()[1][3] == '?': 1993*cda5da8dSAndroid Build Coastguard Worker self() 1994*cda5da8dSAndroid Build Coastguard Worker return '' 1995*cda5da8dSAndroid Build Coastguard Worker return '<%s.%s instance>' % (self.__class__.__module__, 1996*cda5da8dSAndroid Build Coastguard Worker self.__class__.__qualname__) 1997*cda5da8dSAndroid Build Coastguard Worker 1998*cda5da8dSAndroid Build Coastguard Worker _GoInteractive = object() 1999*cda5da8dSAndroid Build Coastguard Worker def __call__(self, request=_GoInteractive): 2000*cda5da8dSAndroid Build Coastguard Worker if request is not self._GoInteractive: 2001*cda5da8dSAndroid Build Coastguard Worker try: 2002*cda5da8dSAndroid Build Coastguard Worker self.help(request) 2003*cda5da8dSAndroid Build Coastguard Worker except ImportError as e: 2004*cda5da8dSAndroid Build Coastguard Worker self.output.write(f'{e}\n') 2005*cda5da8dSAndroid Build Coastguard Worker else: 2006*cda5da8dSAndroid Build Coastguard Worker self.intro() 2007*cda5da8dSAndroid Build Coastguard Worker self.interact() 2008*cda5da8dSAndroid Build Coastguard Worker self.output.write(''' 2009*cda5da8dSAndroid Build Coastguard WorkerYou are now leaving help and returning to the Python interpreter. 2010*cda5da8dSAndroid Build Coastguard WorkerIf you want to ask for help on a particular object directly from the 2011*cda5da8dSAndroid Build Coastguard Workerinterpreter, you can type "help(object)". Executing "help('string')" 2012*cda5da8dSAndroid Build Coastguard Workerhas the same effect as typing a particular string at the help> prompt. 2013*cda5da8dSAndroid Build Coastguard Worker''') 2014*cda5da8dSAndroid Build Coastguard Worker 2015*cda5da8dSAndroid Build Coastguard Worker def interact(self): 2016*cda5da8dSAndroid Build Coastguard Worker self.output.write('\n') 2017*cda5da8dSAndroid Build Coastguard Worker while True: 2018*cda5da8dSAndroid Build Coastguard Worker try: 2019*cda5da8dSAndroid Build Coastguard Worker request = self.getline('help> ') 2020*cda5da8dSAndroid Build Coastguard Worker if not request: break 2021*cda5da8dSAndroid Build Coastguard Worker except (KeyboardInterrupt, EOFError): 2022*cda5da8dSAndroid Build Coastguard Worker break 2023*cda5da8dSAndroid Build Coastguard Worker request = request.strip() 2024*cda5da8dSAndroid Build Coastguard Worker 2025*cda5da8dSAndroid Build Coastguard Worker # Make sure significant trailing quoting marks of literals don't 2026*cda5da8dSAndroid Build Coastguard Worker # get deleted while cleaning input 2027*cda5da8dSAndroid Build Coastguard Worker if (len(request) > 2 and request[0] == request[-1] in ("'", '"') 2028*cda5da8dSAndroid Build Coastguard Worker and request[0] not in request[1:-1]): 2029*cda5da8dSAndroid Build Coastguard Worker request = request[1:-1] 2030*cda5da8dSAndroid Build Coastguard Worker if request.lower() in ('q', 'quit'): break 2031*cda5da8dSAndroid Build Coastguard Worker if request == 'help': 2032*cda5da8dSAndroid Build Coastguard Worker self.intro() 2033*cda5da8dSAndroid Build Coastguard Worker else: 2034*cda5da8dSAndroid Build Coastguard Worker self.help(request) 2035*cda5da8dSAndroid Build Coastguard Worker 2036*cda5da8dSAndroid Build Coastguard Worker def getline(self, prompt): 2037*cda5da8dSAndroid Build Coastguard Worker """Read one line, using input() when appropriate.""" 2038*cda5da8dSAndroid Build Coastguard Worker if self.input is sys.stdin: 2039*cda5da8dSAndroid Build Coastguard Worker return input(prompt) 2040*cda5da8dSAndroid Build Coastguard Worker else: 2041*cda5da8dSAndroid Build Coastguard Worker self.output.write(prompt) 2042*cda5da8dSAndroid Build Coastguard Worker self.output.flush() 2043*cda5da8dSAndroid Build Coastguard Worker return self.input.readline() 2044*cda5da8dSAndroid Build Coastguard Worker 2045*cda5da8dSAndroid Build Coastguard Worker def help(self, request): 2046*cda5da8dSAndroid Build Coastguard Worker if type(request) is type(''): 2047*cda5da8dSAndroid Build Coastguard Worker request = request.strip() 2048*cda5da8dSAndroid Build Coastguard Worker if request == 'keywords': self.listkeywords() 2049*cda5da8dSAndroid Build Coastguard Worker elif request == 'symbols': self.listsymbols() 2050*cda5da8dSAndroid Build Coastguard Worker elif request == 'topics': self.listtopics() 2051*cda5da8dSAndroid Build Coastguard Worker elif request == 'modules': self.listmodules() 2052*cda5da8dSAndroid Build Coastguard Worker elif request[:8] == 'modules ': 2053*cda5da8dSAndroid Build Coastguard Worker self.listmodules(request.split()[1]) 2054*cda5da8dSAndroid Build Coastguard Worker elif request in self.symbols: self.showsymbol(request) 2055*cda5da8dSAndroid Build Coastguard Worker elif request in ['True', 'False', 'None']: 2056*cda5da8dSAndroid Build Coastguard Worker # special case these keywords since they are objects too 2057*cda5da8dSAndroid Build Coastguard Worker doc(eval(request), 'Help on %s:') 2058*cda5da8dSAndroid Build Coastguard Worker elif request in self.keywords: self.showtopic(request) 2059*cda5da8dSAndroid Build Coastguard Worker elif request in self.topics: self.showtopic(request) 2060*cda5da8dSAndroid Build Coastguard Worker elif request: doc(request, 'Help on %s:', output=self._output) 2061*cda5da8dSAndroid Build Coastguard Worker else: doc(str, 'Help on %s:', output=self._output) 2062*cda5da8dSAndroid Build Coastguard Worker elif isinstance(request, Helper): self() 2063*cda5da8dSAndroid Build Coastguard Worker else: doc(request, 'Help on %s:', output=self._output) 2064*cda5da8dSAndroid Build Coastguard Worker self.output.write('\n') 2065*cda5da8dSAndroid Build Coastguard Worker 2066*cda5da8dSAndroid Build Coastguard Worker def intro(self): 2067*cda5da8dSAndroid Build Coastguard Worker self.output.write(''' 2068*cda5da8dSAndroid Build Coastguard WorkerWelcome to Python {0}'s help utility! 2069*cda5da8dSAndroid Build Coastguard Worker 2070*cda5da8dSAndroid Build Coastguard WorkerIf this is your first time using Python, you should definitely check out 2071*cda5da8dSAndroid Build Coastguard Workerthe tutorial on the internet at https://docs.python.org/{0}/tutorial/. 2072*cda5da8dSAndroid Build Coastguard Worker 2073*cda5da8dSAndroid Build Coastguard WorkerEnter the name of any module, keyword, or topic to get help on writing 2074*cda5da8dSAndroid Build Coastguard WorkerPython programs and using Python modules. To quit this help utility and 2075*cda5da8dSAndroid Build Coastguard Workerreturn to the interpreter, just type "quit". 2076*cda5da8dSAndroid Build Coastguard Worker 2077*cda5da8dSAndroid Build Coastguard WorkerTo get a list of available modules, keywords, symbols, or topics, type 2078*cda5da8dSAndroid Build Coastguard Worker"modules", "keywords", "symbols", or "topics". Each module also comes 2079*cda5da8dSAndroid Build Coastguard Workerwith a one-line summary of what it does; to list the modules whose name 2080*cda5da8dSAndroid Build Coastguard Workeror summary contain a given string such as "spam", type "modules spam". 2081*cda5da8dSAndroid Build Coastguard Worker'''.format('%d.%d' % sys.version_info[:2])) 2082*cda5da8dSAndroid Build Coastguard Worker 2083*cda5da8dSAndroid Build Coastguard Worker def list(self, items, columns=4, width=80): 2084*cda5da8dSAndroid Build Coastguard Worker items = list(sorted(items)) 2085*cda5da8dSAndroid Build Coastguard Worker colw = width // columns 2086*cda5da8dSAndroid Build Coastguard Worker rows = (len(items) + columns - 1) // columns 2087*cda5da8dSAndroid Build Coastguard Worker for row in range(rows): 2088*cda5da8dSAndroid Build Coastguard Worker for col in range(columns): 2089*cda5da8dSAndroid Build Coastguard Worker i = col * rows + row 2090*cda5da8dSAndroid Build Coastguard Worker if i < len(items): 2091*cda5da8dSAndroid Build Coastguard Worker self.output.write(items[i]) 2092*cda5da8dSAndroid Build Coastguard Worker if col < columns - 1: 2093*cda5da8dSAndroid Build Coastguard Worker self.output.write(' ' + ' ' * (colw - 1 - len(items[i]))) 2094*cda5da8dSAndroid Build Coastguard Worker self.output.write('\n') 2095*cda5da8dSAndroid Build Coastguard Worker 2096*cda5da8dSAndroid Build Coastguard Worker def listkeywords(self): 2097*cda5da8dSAndroid Build Coastguard Worker self.output.write(''' 2098*cda5da8dSAndroid Build Coastguard WorkerHere is a list of the Python keywords. Enter any keyword to get more help. 2099*cda5da8dSAndroid Build Coastguard Worker 2100*cda5da8dSAndroid Build Coastguard Worker''') 2101*cda5da8dSAndroid Build Coastguard Worker self.list(self.keywords.keys()) 2102*cda5da8dSAndroid Build Coastguard Worker 2103*cda5da8dSAndroid Build Coastguard Worker def listsymbols(self): 2104*cda5da8dSAndroid Build Coastguard Worker self.output.write(''' 2105*cda5da8dSAndroid Build Coastguard WorkerHere is a list of the punctuation symbols which Python assigns special meaning 2106*cda5da8dSAndroid Build Coastguard Workerto. Enter any symbol to get more help. 2107*cda5da8dSAndroid Build Coastguard Worker 2108*cda5da8dSAndroid Build Coastguard Worker''') 2109*cda5da8dSAndroid Build Coastguard Worker self.list(self.symbols.keys()) 2110*cda5da8dSAndroid Build Coastguard Worker 2111*cda5da8dSAndroid Build Coastguard Worker def listtopics(self): 2112*cda5da8dSAndroid Build Coastguard Worker self.output.write(''' 2113*cda5da8dSAndroid Build Coastguard WorkerHere is a list of available topics. Enter any topic name to get more help. 2114*cda5da8dSAndroid Build Coastguard Worker 2115*cda5da8dSAndroid Build Coastguard Worker''') 2116*cda5da8dSAndroid Build Coastguard Worker self.list(self.topics.keys()) 2117*cda5da8dSAndroid Build Coastguard Worker 2118*cda5da8dSAndroid Build Coastguard Worker def showtopic(self, topic, more_xrefs=''): 2119*cda5da8dSAndroid Build Coastguard Worker try: 2120*cda5da8dSAndroid Build Coastguard Worker import pydoc_data.topics 2121*cda5da8dSAndroid Build Coastguard Worker except ImportError: 2122*cda5da8dSAndroid Build Coastguard Worker self.output.write(''' 2123*cda5da8dSAndroid Build Coastguard WorkerSorry, topic and keyword documentation is not available because the 2124*cda5da8dSAndroid Build Coastguard Workermodule "pydoc_data.topics" could not be found. 2125*cda5da8dSAndroid Build Coastguard Worker''') 2126*cda5da8dSAndroid Build Coastguard Worker return 2127*cda5da8dSAndroid Build Coastguard Worker target = self.topics.get(topic, self.keywords.get(topic)) 2128*cda5da8dSAndroid Build Coastguard Worker if not target: 2129*cda5da8dSAndroid Build Coastguard Worker self.output.write('no documentation found for %s\n' % repr(topic)) 2130*cda5da8dSAndroid Build Coastguard Worker return 2131*cda5da8dSAndroid Build Coastguard Worker if type(target) is type(''): 2132*cda5da8dSAndroid Build Coastguard Worker return self.showtopic(target, more_xrefs) 2133*cda5da8dSAndroid Build Coastguard Worker 2134*cda5da8dSAndroid Build Coastguard Worker label, xrefs = target 2135*cda5da8dSAndroid Build Coastguard Worker try: 2136*cda5da8dSAndroid Build Coastguard Worker doc = pydoc_data.topics.topics[label] 2137*cda5da8dSAndroid Build Coastguard Worker except KeyError: 2138*cda5da8dSAndroid Build Coastguard Worker self.output.write('no documentation found for %s\n' % repr(topic)) 2139*cda5da8dSAndroid Build Coastguard Worker return 2140*cda5da8dSAndroid Build Coastguard Worker doc = doc.strip() + '\n' 2141*cda5da8dSAndroid Build Coastguard Worker if more_xrefs: 2142*cda5da8dSAndroid Build Coastguard Worker xrefs = (xrefs or '') + ' ' + more_xrefs 2143*cda5da8dSAndroid Build Coastguard Worker if xrefs: 2144*cda5da8dSAndroid Build Coastguard Worker import textwrap 2145*cda5da8dSAndroid Build Coastguard Worker text = 'Related help topics: ' + ', '.join(xrefs.split()) + '\n' 2146*cda5da8dSAndroid Build Coastguard Worker wrapped_text = textwrap.wrap(text, 72) 2147*cda5da8dSAndroid Build Coastguard Worker doc += '\n%s\n' % '\n'.join(wrapped_text) 2148*cda5da8dSAndroid Build Coastguard Worker pager(doc) 2149*cda5da8dSAndroid Build Coastguard Worker 2150*cda5da8dSAndroid Build Coastguard Worker def _gettopic(self, topic, more_xrefs=''): 2151*cda5da8dSAndroid Build Coastguard Worker """Return unbuffered tuple of (topic, xrefs). 2152*cda5da8dSAndroid Build Coastguard Worker 2153*cda5da8dSAndroid Build Coastguard Worker If an error occurs here, the exception is caught and displayed by 2154*cda5da8dSAndroid Build Coastguard Worker the url handler. 2155*cda5da8dSAndroid Build Coastguard Worker 2156*cda5da8dSAndroid Build Coastguard Worker This function duplicates the showtopic method but returns its 2157*cda5da8dSAndroid Build Coastguard Worker result directly so it can be formatted for display in an html page. 2158*cda5da8dSAndroid Build Coastguard Worker """ 2159*cda5da8dSAndroid Build Coastguard Worker try: 2160*cda5da8dSAndroid Build Coastguard Worker import pydoc_data.topics 2161*cda5da8dSAndroid Build Coastguard Worker except ImportError: 2162*cda5da8dSAndroid Build Coastguard Worker return(''' 2163*cda5da8dSAndroid Build Coastguard WorkerSorry, topic and keyword documentation is not available because the 2164*cda5da8dSAndroid Build Coastguard Workermodule "pydoc_data.topics" could not be found. 2165*cda5da8dSAndroid Build Coastguard Worker''' , '') 2166*cda5da8dSAndroid Build Coastguard Worker target = self.topics.get(topic, self.keywords.get(topic)) 2167*cda5da8dSAndroid Build Coastguard Worker if not target: 2168*cda5da8dSAndroid Build Coastguard Worker raise ValueError('could not find topic') 2169*cda5da8dSAndroid Build Coastguard Worker if isinstance(target, str): 2170*cda5da8dSAndroid Build Coastguard Worker return self._gettopic(target, more_xrefs) 2171*cda5da8dSAndroid Build Coastguard Worker label, xrefs = target 2172*cda5da8dSAndroid Build Coastguard Worker doc = pydoc_data.topics.topics[label] 2173*cda5da8dSAndroid Build Coastguard Worker if more_xrefs: 2174*cda5da8dSAndroid Build Coastguard Worker xrefs = (xrefs or '') + ' ' + more_xrefs 2175*cda5da8dSAndroid Build Coastguard Worker return doc, xrefs 2176*cda5da8dSAndroid Build Coastguard Worker 2177*cda5da8dSAndroid Build Coastguard Worker def showsymbol(self, symbol): 2178*cda5da8dSAndroid Build Coastguard Worker target = self.symbols[symbol] 2179*cda5da8dSAndroid Build Coastguard Worker topic, _, xrefs = target.partition(' ') 2180*cda5da8dSAndroid Build Coastguard Worker self.showtopic(topic, xrefs) 2181*cda5da8dSAndroid Build Coastguard Worker 2182*cda5da8dSAndroid Build Coastguard Worker def listmodules(self, key=''): 2183*cda5da8dSAndroid Build Coastguard Worker if key: 2184*cda5da8dSAndroid Build Coastguard Worker self.output.write(''' 2185*cda5da8dSAndroid Build Coastguard WorkerHere is a list of modules whose name or summary contains '{}'. 2186*cda5da8dSAndroid Build Coastguard WorkerIf there are any, enter a module name to get more help. 2187*cda5da8dSAndroid Build Coastguard Worker 2188*cda5da8dSAndroid Build Coastguard Worker'''.format(key)) 2189*cda5da8dSAndroid Build Coastguard Worker apropos(key) 2190*cda5da8dSAndroid Build Coastguard Worker else: 2191*cda5da8dSAndroid Build Coastguard Worker self.output.write(''' 2192*cda5da8dSAndroid Build Coastguard WorkerPlease wait a moment while I gather a list of all available modules... 2193*cda5da8dSAndroid Build Coastguard Worker 2194*cda5da8dSAndroid Build Coastguard Worker''') 2195*cda5da8dSAndroid Build Coastguard Worker modules = {} 2196*cda5da8dSAndroid Build Coastguard Worker def callback(path, modname, desc, modules=modules): 2197*cda5da8dSAndroid Build Coastguard Worker if modname and modname[-9:] == '.__init__': 2198*cda5da8dSAndroid Build Coastguard Worker modname = modname[:-9] + ' (package)' 2199*cda5da8dSAndroid Build Coastguard Worker if modname.find('.') < 0: 2200*cda5da8dSAndroid Build Coastguard Worker modules[modname] = 1 2201*cda5da8dSAndroid Build Coastguard Worker def onerror(modname): 2202*cda5da8dSAndroid Build Coastguard Worker callback(None, modname, None) 2203*cda5da8dSAndroid Build Coastguard Worker ModuleScanner().run(callback, onerror=onerror) 2204*cda5da8dSAndroid Build Coastguard Worker self.list(modules.keys()) 2205*cda5da8dSAndroid Build Coastguard Worker self.output.write(''' 2206*cda5da8dSAndroid Build Coastguard WorkerEnter any module name to get more help. Or, type "modules spam" to search 2207*cda5da8dSAndroid Build Coastguard Workerfor modules whose name or summary contain the string "spam". 2208*cda5da8dSAndroid Build Coastguard Worker''') 2209*cda5da8dSAndroid Build Coastguard Worker 2210*cda5da8dSAndroid Build Coastguard Workerhelp = Helper() 2211*cda5da8dSAndroid Build Coastguard Worker 2212*cda5da8dSAndroid Build Coastguard Workerclass ModuleScanner: 2213*cda5da8dSAndroid Build Coastguard Worker """An interruptible scanner that searches module synopses.""" 2214*cda5da8dSAndroid Build Coastguard Worker 2215*cda5da8dSAndroid Build Coastguard Worker def run(self, callback, key=None, completer=None, onerror=None): 2216*cda5da8dSAndroid Build Coastguard Worker if key: key = key.lower() 2217*cda5da8dSAndroid Build Coastguard Worker self.quit = False 2218*cda5da8dSAndroid Build Coastguard Worker seen = {} 2219*cda5da8dSAndroid Build Coastguard Worker 2220*cda5da8dSAndroid Build Coastguard Worker for modname in sys.builtin_module_names: 2221*cda5da8dSAndroid Build Coastguard Worker if modname != '__main__': 2222*cda5da8dSAndroid Build Coastguard Worker seen[modname] = 1 2223*cda5da8dSAndroid Build Coastguard Worker if key is None: 2224*cda5da8dSAndroid Build Coastguard Worker callback(None, modname, '') 2225*cda5da8dSAndroid Build Coastguard Worker else: 2226*cda5da8dSAndroid Build Coastguard Worker name = __import__(modname).__doc__ or '' 2227*cda5da8dSAndroid Build Coastguard Worker desc = name.split('\n')[0] 2228*cda5da8dSAndroid Build Coastguard Worker name = modname + ' - ' + desc 2229*cda5da8dSAndroid Build Coastguard Worker if name.lower().find(key) >= 0: 2230*cda5da8dSAndroid Build Coastguard Worker callback(None, modname, desc) 2231*cda5da8dSAndroid Build Coastguard Worker 2232*cda5da8dSAndroid Build Coastguard Worker for importer, modname, ispkg in pkgutil.walk_packages(onerror=onerror): 2233*cda5da8dSAndroid Build Coastguard Worker if self.quit: 2234*cda5da8dSAndroid Build Coastguard Worker break 2235*cda5da8dSAndroid Build Coastguard Worker 2236*cda5da8dSAndroid Build Coastguard Worker if key is None: 2237*cda5da8dSAndroid Build Coastguard Worker callback(None, modname, '') 2238*cda5da8dSAndroid Build Coastguard Worker else: 2239*cda5da8dSAndroid Build Coastguard Worker try: 2240*cda5da8dSAndroid Build Coastguard Worker spec = pkgutil._get_spec(importer, modname) 2241*cda5da8dSAndroid Build Coastguard Worker except SyntaxError: 2242*cda5da8dSAndroid Build Coastguard Worker # raised by tests for bad coding cookies or BOM 2243*cda5da8dSAndroid Build Coastguard Worker continue 2244*cda5da8dSAndroid Build Coastguard Worker loader = spec.loader 2245*cda5da8dSAndroid Build Coastguard Worker if hasattr(loader, 'get_source'): 2246*cda5da8dSAndroid Build Coastguard Worker try: 2247*cda5da8dSAndroid Build Coastguard Worker source = loader.get_source(modname) 2248*cda5da8dSAndroid Build Coastguard Worker except Exception: 2249*cda5da8dSAndroid Build Coastguard Worker if onerror: 2250*cda5da8dSAndroid Build Coastguard Worker onerror(modname) 2251*cda5da8dSAndroid Build Coastguard Worker continue 2252*cda5da8dSAndroid Build Coastguard Worker desc = source_synopsis(io.StringIO(source)) or '' 2253*cda5da8dSAndroid Build Coastguard Worker if hasattr(loader, 'get_filename'): 2254*cda5da8dSAndroid Build Coastguard Worker path = loader.get_filename(modname) 2255*cda5da8dSAndroid Build Coastguard Worker else: 2256*cda5da8dSAndroid Build Coastguard Worker path = None 2257*cda5da8dSAndroid Build Coastguard Worker else: 2258*cda5da8dSAndroid Build Coastguard Worker try: 2259*cda5da8dSAndroid Build Coastguard Worker module = importlib._bootstrap._load(spec) 2260*cda5da8dSAndroid Build Coastguard Worker except ImportError: 2261*cda5da8dSAndroid Build Coastguard Worker if onerror: 2262*cda5da8dSAndroid Build Coastguard Worker onerror(modname) 2263*cda5da8dSAndroid Build Coastguard Worker continue 2264*cda5da8dSAndroid Build Coastguard Worker desc = module.__doc__.splitlines()[0] if module.__doc__ else '' 2265*cda5da8dSAndroid Build Coastguard Worker path = getattr(module,'__file__',None) 2266*cda5da8dSAndroid Build Coastguard Worker name = modname + ' - ' + desc 2267*cda5da8dSAndroid Build Coastguard Worker if name.lower().find(key) >= 0: 2268*cda5da8dSAndroid Build Coastguard Worker callback(path, modname, desc) 2269*cda5da8dSAndroid Build Coastguard Worker 2270*cda5da8dSAndroid Build Coastguard Worker if completer: 2271*cda5da8dSAndroid Build Coastguard Worker completer() 2272*cda5da8dSAndroid Build Coastguard Worker 2273*cda5da8dSAndroid Build Coastguard Workerdef apropos(key): 2274*cda5da8dSAndroid Build Coastguard Worker """Print all the one-line module summaries that contain a substring.""" 2275*cda5da8dSAndroid Build Coastguard Worker def callback(path, modname, desc): 2276*cda5da8dSAndroid Build Coastguard Worker if modname[-9:] == '.__init__': 2277*cda5da8dSAndroid Build Coastguard Worker modname = modname[:-9] + ' (package)' 2278*cda5da8dSAndroid Build Coastguard Worker print(modname, desc and '- ' + desc) 2279*cda5da8dSAndroid Build Coastguard Worker def onerror(modname): 2280*cda5da8dSAndroid Build Coastguard Worker pass 2281*cda5da8dSAndroid Build Coastguard Worker with warnings.catch_warnings(): 2282*cda5da8dSAndroid Build Coastguard Worker warnings.filterwarnings('ignore') # ignore problems during import 2283*cda5da8dSAndroid Build Coastguard Worker ModuleScanner().run(callback, key, onerror=onerror) 2284*cda5da8dSAndroid Build Coastguard Worker 2285*cda5da8dSAndroid Build Coastguard Worker# --------------------------------------- enhanced web browser interface 2286*cda5da8dSAndroid Build Coastguard Worker 2287*cda5da8dSAndroid Build Coastguard Workerdef _start_server(urlhandler, hostname, port): 2288*cda5da8dSAndroid Build Coastguard Worker """Start an HTTP server thread on a specific port. 2289*cda5da8dSAndroid Build Coastguard Worker 2290*cda5da8dSAndroid Build Coastguard Worker Start an HTML/text server thread, so HTML or text documents can be 2291*cda5da8dSAndroid Build Coastguard Worker browsed dynamically and interactively with a web browser. Example use: 2292*cda5da8dSAndroid Build Coastguard Worker 2293*cda5da8dSAndroid Build Coastguard Worker >>> import time 2294*cda5da8dSAndroid Build Coastguard Worker >>> import pydoc 2295*cda5da8dSAndroid Build Coastguard Worker 2296*cda5da8dSAndroid Build Coastguard Worker Define a URL handler. To determine what the client is asking 2297*cda5da8dSAndroid Build Coastguard Worker for, check the URL and content_type. 2298*cda5da8dSAndroid Build Coastguard Worker 2299*cda5da8dSAndroid Build Coastguard Worker Then get or generate some text or HTML code and return it. 2300*cda5da8dSAndroid Build Coastguard Worker 2301*cda5da8dSAndroid Build Coastguard Worker >>> def my_url_handler(url, content_type): 2302*cda5da8dSAndroid Build Coastguard Worker ... text = 'the URL sent was: (%s, %s)' % (url, content_type) 2303*cda5da8dSAndroid Build Coastguard Worker ... return text 2304*cda5da8dSAndroid Build Coastguard Worker 2305*cda5da8dSAndroid Build Coastguard Worker Start server thread on port 0. 2306*cda5da8dSAndroid Build Coastguard Worker If you use port 0, the server will pick a random port number. 2307*cda5da8dSAndroid Build Coastguard Worker You can then use serverthread.port to get the port number. 2308*cda5da8dSAndroid Build Coastguard Worker 2309*cda5da8dSAndroid Build Coastguard Worker >>> port = 0 2310*cda5da8dSAndroid Build Coastguard Worker >>> serverthread = pydoc._start_server(my_url_handler, port) 2311*cda5da8dSAndroid Build Coastguard Worker 2312*cda5da8dSAndroid Build Coastguard Worker Check that the server is really started. If it is, open browser 2313*cda5da8dSAndroid Build Coastguard Worker and get first page. Use serverthread.url as the starting page. 2314*cda5da8dSAndroid Build Coastguard Worker 2315*cda5da8dSAndroid Build Coastguard Worker >>> if serverthread.serving: 2316*cda5da8dSAndroid Build Coastguard Worker ... import webbrowser 2317*cda5da8dSAndroid Build Coastguard Worker 2318*cda5da8dSAndroid Build Coastguard Worker The next two lines are commented out so a browser doesn't open if 2319*cda5da8dSAndroid Build Coastguard Worker doctest is run on this module. 2320*cda5da8dSAndroid Build Coastguard Worker 2321*cda5da8dSAndroid Build Coastguard Worker #... webbrowser.open(serverthread.url) 2322*cda5da8dSAndroid Build Coastguard Worker #True 2323*cda5da8dSAndroid Build Coastguard Worker 2324*cda5da8dSAndroid Build Coastguard Worker Let the server do its thing. We just need to monitor its status. 2325*cda5da8dSAndroid Build Coastguard Worker Use time.sleep so the loop doesn't hog the CPU. 2326*cda5da8dSAndroid Build Coastguard Worker 2327*cda5da8dSAndroid Build Coastguard Worker >>> starttime = time.monotonic() 2328*cda5da8dSAndroid Build Coastguard Worker >>> timeout = 1 #seconds 2329*cda5da8dSAndroid Build Coastguard Worker 2330*cda5da8dSAndroid Build Coastguard Worker This is a short timeout for testing purposes. 2331*cda5da8dSAndroid Build Coastguard Worker 2332*cda5da8dSAndroid Build Coastguard Worker >>> while serverthread.serving: 2333*cda5da8dSAndroid Build Coastguard Worker ... time.sleep(.01) 2334*cda5da8dSAndroid Build Coastguard Worker ... if serverthread.serving and time.monotonic() - starttime > timeout: 2335*cda5da8dSAndroid Build Coastguard Worker ... serverthread.stop() 2336*cda5da8dSAndroid Build Coastguard Worker ... break 2337*cda5da8dSAndroid Build Coastguard Worker 2338*cda5da8dSAndroid Build Coastguard Worker Print any errors that may have occurred. 2339*cda5da8dSAndroid Build Coastguard Worker 2340*cda5da8dSAndroid Build Coastguard Worker >>> print(serverthread.error) 2341*cda5da8dSAndroid Build Coastguard Worker None 2342*cda5da8dSAndroid Build Coastguard Worker """ 2343*cda5da8dSAndroid Build Coastguard Worker import http.server 2344*cda5da8dSAndroid Build Coastguard Worker import email.message 2345*cda5da8dSAndroid Build Coastguard Worker import select 2346*cda5da8dSAndroid Build Coastguard Worker import threading 2347*cda5da8dSAndroid Build Coastguard Worker 2348*cda5da8dSAndroid Build Coastguard Worker class DocHandler(http.server.BaseHTTPRequestHandler): 2349*cda5da8dSAndroid Build Coastguard Worker 2350*cda5da8dSAndroid Build Coastguard Worker def do_GET(self): 2351*cda5da8dSAndroid Build Coastguard Worker """Process a request from an HTML browser. 2352*cda5da8dSAndroid Build Coastguard Worker 2353*cda5da8dSAndroid Build Coastguard Worker The URL received is in self.path. 2354*cda5da8dSAndroid Build Coastguard Worker Get an HTML page from self.urlhandler and send it. 2355*cda5da8dSAndroid Build Coastguard Worker """ 2356*cda5da8dSAndroid Build Coastguard Worker if self.path.endswith('.css'): 2357*cda5da8dSAndroid Build Coastguard Worker content_type = 'text/css' 2358*cda5da8dSAndroid Build Coastguard Worker else: 2359*cda5da8dSAndroid Build Coastguard Worker content_type = 'text/html' 2360*cda5da8dSAndroid Build Coastguard Worker self.send_response(200) 2361*cda5da8dSAndroid Build Coastguard Worker self.send_header('Content-Type', '%s; charset=UTF-8' % content_type) 2362*cda5da8dSAndroid Build Coastguard Worker self.end_headers() 2363*cda5da8dSAndroid Build Coastguard Worker self.wfile.write(self.urlhandler( 2364*cda5da8dSAndroid Build Coastguard Worker self.path, content_type).encode('utf-8')) 2365*cda5da8dSAndroid Build Coastguard Worker 2366*cda5da8dSAndroid Build Coastguard Worker def log_message(self, *args): 2367*cda5da8dSAndroid Build Coastguard Worker # Don't log messages. 2368*cda5da8dSAndroid Build Coastguard Worker pass 2369*cda5da8dSAndroid Build Coastguard Worker 2370*cda5da8dSAndroid Build Coastguard Worker class DocServer(http.server.HTTPServer): 2371*cda5da8dSAndroid Build Coastguard Worker 2372*cda5da8dSAndroid Build Coastguard Worker def __init__(self, host, port, callback): 2373*cda5da8dSAndroid Build Coastguard Worker self.host = host 2374*cda5da8dSAndroid Build Coastguard Worker self.address = (self.host, port) 2375*cda5da8dSAndroid Build Coastguard Worker self.callback = callback 2376*cda5da8dSAndroid Build Coastguard Worker self.base.__init__(self, self.address, self.handler) 2377*cda5da8dSAndroid Build Coastguard Worker self.quit = False 2378*cda5da8dSAndroid Build Coastguard Worker 2379*cda5da8dSAndroid Build Coastguard Worker def serve_until_quit(self): 2380*cda5da8dSAndroid Build Coastguard Worker while not self.quit: 2381*cda5da8dSAndroid Build Coastguard Worker rd, wr, ex = select.select([self.socket.fileno()], [], [], 1) 2382*cda5da8dSAndroid Build Coastguard Worker if rd: 2383*cda5da8dSAndroid Build Coastguard Worker self.handle_request() 2384*cda5da8dSAndroid Build Coastguard Worker self.server_close() 2385*cda5da8dSAndroid Build Coastguard Worker 2386*cda5da8dSAndroid Build Coastguard Worker def server_activate(self): 2387*cda5da8dSAndroid Build Coastguard Worker self.base.server_activate(self) 2388*cda5da8dSAndroid Build Coastguard Worker if self.callback: 2389*cda5da8dSAndroid Build Coastguard Worker self.callback(self) 2390*cda5da8dSAndroid Build Coastguard Worker 2391*cda5da8dSAndroid Build Coastguard Worker class ServerThread(threading.Thread): 2392*cda5da8dSAndroid Build Coastguard Worker 2393*cda5da8dSAndroid Build Coastguard Worker def __init__(self, urlhandler, host, port): 2394*cda5da8dSAndroid Build Coastguard Worker self.urlhandler = urlhandler 2395*cda5da8dSAndroid Build Coastguard Worker self.host = host 2396*cda5da8dSAndroid Build Coastguard Worker self.port = int(port) 2397*cda5da8dSAndroid Build Coastguard Worker threading.Thread.__init__(self) 2398*cda5da8dSAndroid Build Coastguard Worker self.serving = False 2399*cda5da8dSAndroid Build Coastguard Worker self.error = None 2400*cda5da8dSAndroid Build Coastguard Worker 2401*cda5da8dSAndroid Build Coastguard Worker def run(self): 2402*cda5da8dSAndroid Build Coastguard Worker """Start the server.""" 2403*cda5da8dSAndroid Build Coastguard Worker try: 2404*cda5da8dSAndroid Build Coastguard Worker DocServer.base = http.server.HTTPServer 2405*cda5da8dSAndroid Build Coastguard Worker DocServer.handler = DocHandler 2406*cda5da8dSAndroid Build Coastguard Worker DocHandler.MessageClass = email.message.Message 2407*cda5da8dSAndroid Build Coastguard Worker DocHandler.urlhandler = staticmethod(self.urlhandler) 2408*cda5da8dSAndroid Build Coastguard Worker docsvr = DocServer(self.host, self.port, self.ready) 2409*cda5da8dSAndroid Build Coastguard Worker self.docserver = docsvr 2410*cda5da8dSAndroid Build Coastguard Worker docsvr.serve_until_quit() 2411*cda5da8dSAndroid Build Coastguard Worker except Exception as e: 2412*cda5da8dSAndroid Build Coastguard Worker self.error = e 2413*cda5da8dSAndroid Build Coastguard Worker 2414*cda5da8dSAndroid Build Coastguard Worker def ready(self, server): 2415*cda5da8dSAndroid Build Coastguard Worker self.serving = True 2416*cda5da8dSAndroid Build Coastguard Worker self.host = server.host 2417*cda5da8dSAndroid Build Coastguard Worker self.port = server.server_port 2418*cda5da8dSAndroid Build Coastguard Worker self.url = 'http://%s:%d/' % (self.host, self.port) 2419*cda5da8dSAndroid Build Coastguard Worker 2420*cda5da8dSAndroid Build Coastguard Worker def stop(self): 2421*cda5da8dSAndroid Build Coastguard Worker """Stop the server and this thread nicely""" 2422*cda5da8dSAndroid Build Coastguard Worker self.docserver.quit = True 2423*cda5da8dSAndroid Build Coastguard Worker self.join() 2424*cda5da8dSAndroid Build Coastguard Worker # explicitly break a reference cycle: DocServer.callback 2425*cda5da8dSAndroid Build Coastguard Worker # has indirectly a reference to ServerThread. 2426*cda5da8dSAndroid Build Coastguard Worker self.docserver = None 2427*cda5da8dSAndroid Build Coastguard Worker self.serving = False 2428*cda5da8dSAndroid Build Coastguard Worker self.url = None 2429*cda5da8dSAndroid Build Coastguard Worker 2430*cda5da8dSAndroid Build Coastguard Worker thread = ServerThread(urlhandler, hostname, port) 2431*cda5da8dSAndroid Build Coastguard Worker thread.start() 2432*cda5da8dSAndroid Build Coastguard Worker # Wait until thread.serving is True to make sure we are 2433*cda5da8dSAndroid Build Coastguard Worker # really up before returning. 2434*cda5da8dSAndroid Build Coastguard Worker while not thread.error and not thread.serving: 2435*cda5da8dSAndroid Build Coastguard Worker time.sleep(.01) 2436*cda5da8dSAndroid Build Coastguard Worker return thread 2437*cda5da8dSAndroid Build Coastguard Worker 2438*cda5da8dSAndroid Build Coastguard Worker 2439*cda5da8dSAndroid Build Coastguard Workerdef _url_handler(url, content_type="text/html"): 2440*cda5da8dSAndroid Build Coastguard Worker """The pydoc url handler for use with the pydoc server. 2441*cda5da8dSAndroid Build Coastguard Worker 2442*cda5da8dSAndroid Build Coastguard Worker If the content_type is 'text/css', the _pydoc.css style 2443*cda5da8dSAndroid Build Coastguard Worker sheet is read and returned if it exits. 2444*cda5da8dSAndroid Build Coastguard Worker 2445*cda5da8dSAndroid Build Coastguard Worker If the content_type is 'text/html', then the result of 2446*cda5da8dSAndroid Build Coastguard Worker get_html_page(url) is returned. 2447*cda5da8dSAndroid Build Coastguard Worker """ 2448*cda5da8dSAndroid Build Coastguard Worker class _HTMLDoc(HTMLDoc): 2449*cda5da8dSAndroid Build Coastguard Worker 2450*cda5da8dSAndroid Build Coastguard Worker def page(self, title, contents): 2451*cda5da8dSAndroid Build Coastguard Worker """Format an HTML page.""" 2452*cda5da8dSAndroid Build Coastguard Worker css_path = "pydoc_data/_pydoc.css" 2453*cda5da8dSAndroid Build Coastguard Worker css_link = ( 2454*cda5da8dSAndroid Build Coastguard Worker '<link rel="stylesheet" type="text/css" href="%s">' % 2455*cda5da8dSAndroid Build Coastguard Worker css_path) 2456*cda5da8dSAndroid Build Coastguard Worker return '''\ 2457*cda5da8dSAndroid Build Coastguard Worker<!DOCTYPE> 2458*cda5da8dSAndroid Build Coastguard Worker<html lang="en"> 2459*cda5da8dSAndroid Build Coastguard Worker<head> 2460*cda5da8dSAndroid Build Coastguard Worker<meta charset="utf-8"> 2461*cda5da8dSAndroid Build Coastguard Worker<title>Pydoc: %s</title> 2462*cda5da8dSAndroid Build Coastguard Worker%s</head><body>%s<div style="clear:both;padding-top:.5em;">%s</div> 2463*cda5da8dSAndroid Build Coastguard Worker</body></html>''' % (title, css_link, html_navbar(), contents) 2464*cda5da8dSAndroid Build Coastguard Worker 2465*cda5da8dSAndroid Build Coastguard Worker 2466*cda5da8dSAndroid Build Coastguard Worker html = _HTMLDoc() 2467*cda5da8dSAndroid Build Coastguard Worker 2468*cda5da8dSAndroid Build Coastguard Worker def html_navbar(): 2469*cda5da8dSAndroid Build Coastguard Worker version = html.escape("%s [%s, %s]" % (platform.python_version(), 2470*cda5da8dSAndroid Build Coastguard Worker platform.python_build()[0], 2471*cda5da8dSAndroid Build Coastguard Worker platform.python_compiler())) 2472*cda5da8dSAndroid Build Coastguard Worker return """ 2473*cda5da8dSAndroid Build Coastguard Worker <div style='float:left'> 2474*cda5da8dSAndroid Build Coastguard Worker Python %s<br>%s 2475*cda5da8dSAndroid Build Coastguard Worker </div> 2476*cda5da8dSAndroid Build Coastguard Worker <div style='float:right'> 2477*cda5da8dSAndroid Build Coastguard Worker <div style='text-align:center'> 2478*cda5da8dSAndroid Build Coastguard Worker <a href="index.html">Module Index</a> 2479*cda5da8dSAndroid Build Coastguard Worker : <a href="topics.html">Topics</a> 2480*cda5da8dSAndroid Build Coastguard Worker : <a href="keywords.html">Keywords</a> 2481*cda5da8dSAndroid Build Coastguard Worker </div> 2482*cda5da8dSAndroid Build Coastguard Worker <div> 2483*cda5da8dSAndroid Build Coastguard Worker <form action="get" style='display:inline;'> 2484*cda5da8dSAndroid Build Coastguard Worker <input type=text name=key size=15> 2485*cda5da8dSAndroid Build Coastguard Worker <input type=submit value="Get"> 2486*cda5da8dSAndroid Build Coastguard Worker </form> 2487*cda5da8dSAndroid Build Coastguard Worker <form action="search" style='display:inline;'> 2488*cda5da8dSAndroid Build Coastguard Worker <input type=text name=key size=15> 2489*cda5da8dSAndroid Build Coastguard Worker <input type=submit value="Search"> 2490*cda5da8dSAndroid Build Coastguard Worker </form> 2491*cda5da8dSAndroid Build Coastguard Worker </div> 2492*cda5da8dSAndroid Build Coastguard Worker </div> 2493*cda5da8dSAndroid Build Coastguard Worker """ % (version, html.escape(platform.platform(terse=True))) 2494*cda5da8dSAndroid Build Coastguard Worker 2495*cda5da8dSAndroid Build Coastguard Worker def html_index(): 2496*cda5da8dSAndroid Build Coastguard Worker """Module Index page.""" 2497*cda5da8dSAndroid Build Coastguard Worker 2498*cda5da8dSAndroid Build Coastguard Worker def bltinlink(name): 2499*cda5da8dSAndroid Build Coastguard Worker return '<a href="%s.html">%s</a>' % (name, name) 2500*cda5da8dSAndroid Build Coastguard Worker 2501*cda5da8dSAndroid Build Coastguard Worker heading = html.heading( 2502*cda5da8dSAndroid Build Coastguard Worker '<strong class="title">Index of Modules</strong>' 2503*cda5da8dSAndroid Build Coastguard Worker ) 2504*cda5da8dSAndroid Build Coastguard Worker names = [name for name in sys.builtin_module_names 2505*cda5da8dSAndroid Build Coastguard Worker if name != '__main__'] 2506*cda5da8dSAndroid Build Coastguard Worker contents = html.multicolumn(names, bltinlink) 2507*cda5da8dSAndroid Build Coastguard Worker contents = [heading, '<p>' + html.bigsection( 2508*cda5da8dSAndroid Build Coastguard Worker 'Built-in Modules', 'index', contents)] 2509*cda5da8dSAndroid Build Coastguard Worker 2510*cda5da8dSAndroid Build Coastguard Worker seen = {} 2511*cda5da8dSAndroid Build Coastguard Worker for dir in sys.path: 2512*cda5da8dSAndroid Build Coastguard Worker contents.append(html.index(dir, seen)) 2513*cda5da8dSAndroid Build Coastguard Worker 2514*cda5da8dSAndroid Build Coastguard Worker contents.append( 2515*cda5da8dSAndroid Build Coastguard Worker '<p align=right class="heading-text grey"><strong>pydoc</strong> by Ka-Ping Yee' 2516*cda5da8dSAndroid Build Coastguard Worker '<[email protected]></p>') 2517*cda5da8dSAndroid Build Coastguard Worker return 'Index of Modules', ''.join(contents) 2518*cda5da8dSAndroid Build Coastguard Worker 2519*cda5da8dSAndroid Build Coastguard Worker def html_search(key): 2520*cda5da8dSAndroid Build Coastguard Worker """Search results page.""" 2521*cda5da8dSAndroid Build Coastguard Worker # scan for modules 2522*cda5da8dSAndroid Build Coastguard Worker search_result = [] 2523*cda5da8dSAndroid Build Coastguard Worker 2524*cda5da8dSAndroid Build Coastguard Worker def callback(path, modname, desc): 2525*cda5da8dSAndroid Build Coastguard Worker if modname[-9:] == '.__init__': 2526*cda5da8dSAndroid Build Coastguard Worker modname = modname[:-9] + ' (package)' 2527*cda5da8dSAndroid Build Coastguard Worker search_result.append((modname, desc and '- ' + desc)) 2528*cda5da8dSAndroid Build Coastguard Worker 2529*cda5da8dSAndroid Build Coastguard Worker with warnings.catch_warnings(): 2530*cda5da8dSAndroid Build Coastguard Worker warnings.filterwarnings('ignore') # ignore problems during import 2531*cda5da8dSAndroid Build Coastguard Worker def onerror(modname): 2532*cda5da8dSAndroid Build Coastguard Worker pass 2533*cda5da8dSAndroid Build Coastguard Worker ModuleScanner().run(callback, key, onerror=onerror) 2534*cda5da8dSAndroid Build Coastguard Worker 2535*cda5da8dSAndroid Build Coastguard Worker # format page 2536*cda5da8dSAndroid Build Coastguard Worker def bltinlink(name): 2537*cda5da8dSAndroid Build Coastguard Worker return '<a href="%s.html">%s</a>' % (name, name) 2538*cda5da8dSAndroid Build Coastguard Worker 2539*cda5da8dSAndroid Build Coastguard Worker results = [] 2540*cda5da8dSAndroid Build Coastguard Worker heading = html.heading( 2541*cda5da8dSAndroid Build Coastguard Worker '<strong class="title">Search Results</strong>', 2542*cda5da8dSAndroid Build Coastguard Worker ) 2543*cda5da8dSAndroid Build Coastguard Worker for name, desc in search_result: 2544*cda5da8dSAndroid Build Coastguard Worker results.append(bltinlink(name) + desc) 2545*cda5da8dSAndroid Build Coastguard Worker contents = heading + html.bigsection( 2546*cda5da8dSAndroid Build Coastguard Worker 'key = %s' % key, 'index', '<br>'.join(results)) 2547*cda5da8dSAndroid Build Coastguard Worker return 'Search Results', contents 2548*cda5da8dSAndroid Build Coastguard Worker 2549*cda5da8dSAndroid Build Coastguard Worker def html_topics(): 2550*cda5da8dSAndroid Build Coastguard Worker """Index of topic texts available.""" 2551*cda5da8dSAndroid Build Coastguard Worker 2552*cda5da8dSAndroid Build Coastguard Worker def bltinlink(name): 2553*cda5da8dSAndroid Build Coastguard Worker return '<a href="topic?key=%s">%s</a>' % (name, name) 2554*cda5da8dSAndroid Build Coastguard Worker 2555*cda5da8dSAndroid Build Coastguard Worker heading = html.heading( 2556*cda5da8dSAndroid Build Coastguard Worker '<strong class="title">INDEX</strong>', 2557*cda5da8dSAndroid Build Coastguard Worker ) 2558*cda5da8dSAndroid Build Coastguard Worker names = sorted(Helper.topics.keys()) 2559*cda5da8dSAndroid Build Coastguard Worker 2560*cda5da8dSAndroid Build Coastguard Worker contents = html.multicolumn(names, bltinlink) 2561*cda5da8dSAndroid Build Coastguard Worker contents = heading + html.bigsection( 2562*cda5da8dSAndroid Build Coastguard Worker 'Topics', 'index', contents) 2563*cda5da8dSAndroid Build Coastguard Worker return 'Topics', contents 2564*cda5da8dSAndroid Build Coastguard Worker 2565*cda5da8dSAndroid Build Coastguard Worker def html_keywords(): 2566*cda5da8dSAndroid Build Coastguard Worker """Index of keywords.""" 2567*cda5da8dSAndroid Build Coastguard Worker heading = html.heading( 2568*cda5da8dSAndroid Build Coastguard Worker '<strong class="title">INDEX</strong>', 2569*cda5da8dSAndroid Build Coastguard Worker ) 2570*cda5da8dSAndroid Build Coastguard Worker names = sorted(Helper.keywords.keys()) 2571*cda5da8dSAndroid Build Coastguard Worker 2572*cda5da8dSAndroid Build Coastguard Worker def bltinlink(name): 2573*cda5da8dSAndroid Build Coastguard Worker return '<a href="topic?key=%s">%s</a>' % (name, name) 2574*cda5da8dSAndroid Build Coastguard Worker 2575*cda5da8dSAndroid Build Coastguard Worker contents = html.multicolumn(names, bltinlink) 2576*cda5da8dSAndroid Build Coastguard Worker contents = heading + html.bigsection( 2577*cda5da8dSAndroid Build Coastguard Worker 'Keywords', 'index', contents) 2578*cda5da8dSAndroid Build Coastguard Worker return 'Keywords', contents 2579*cda5da8dSAndroid Build Coastguard Worker 2580*cda5da8dSAndroid Build Coastguard Worker def html_topicpage(topic): 2581*cda5da8dSAndroid Build Coastguard Worker """Topic or keyword help page.""" 2582*cda5da8dSAndroid Build Coastguard Worker buf = io.StringIO() 2583*cda5da8dSAndroid Build Coastguard Worker htmlhelp = Helper(buf, buf) 2584*cda5da8dSAndroid Build Coastguard Worker contents, xrefs = htmlhelp._gettopic(topic) 2585*cda5da8dSAndroid Build Coastguard Worker if topic in htmlhelp.keywords: 2586*cda5da8dSAndroid Build Coastguard Worker title = 'KEYWORD' 2587*cda5da8dSAndroid Build Coastguard Worker else: 2588*cda5da8dSAndroid Build Coastguard Worker title = 'TOPIC' 2589*cda5da8dSAndroid Build Coastguard Worker heading = html.heading( 2590*cda5da8dSAndroid Build Coastguard Worker '<strong class="title">%s</strong>' % title, 2591*cda5da8dSAndroid Build Coastguard Worker ) 2592*cda5da8dSAndroid Build Coastguard Worker contents = '<pre>%s</pre>' % html.markup(contents) 2593*cda5da8dSAndroid Build Coastguard Worker contents = html.bigsection(topic , 'index', contents) 2594*cda5da8dSAndroid Build Coastguard Worker if xrefs: 2595*cda5da8dSAndroid Build Coastguard Worker xrefs = sorted(xrefs.split()) 2596*cda5da8dSAndroid Build Coastguard Worker 2597*cda5da8dSAndroid Build Coastguard Worker def bltinlink(name): 2598*cda5da8dSAndroid Build Coastguard Worker return '<a href="topic?key=%s">%s</a>' % (name, name) 2599*cda5da8dSAndroid Build Coastguard Worker 2600*cda5da8dSAndroid Build Coastguard Worker xrefs = html.multicolumn(xrefs, bltinlink) 2601*cda5da8dSAndroid Build Coastguard Worker xrefs = html.section('Related help topics: ', 'index', xrefs) 2602*cda5da8dSAndroid Build Coastguard Worker return ('%s %s' % (title, topic), 2603*cda5da8dSAndroid Build Coastguard Worker ''.join((heading, contents, xrefs))) 2604*cda5da8dSAndroid Build Coastguard Worker 2605*cda5da8dSAndroid Build Coastguard Worker def html_getobj(url): 2606*cda5da8dSAndroid Build Coastguard Worker obj = locate(url, forceload=1) 2607*cda5da8dSAndroid Build Coastguard Worker if obj is None and url != 'None': 2608*cda5da8dSAndroid Build Coastguard Worker raise ValueError('could not find object') 2609*cda5da8dSAndroid Build Coastguard Worker title = describe(obj) 2610*cda5da8dSAndroid Build Coastguard Worker content = html.document(obj, url) 2611*cda5da8dSAndroid Build Coastguard Worker return title, content 2612*cda5da8dSAndroid Build Coastguard Worker 2613*cda5da8dSAndroid Build Coastguard Worker def html_error(url, exc): 2614*cda5da8dSAndroid Build Coastguard Worker heading = html.heading( 2615*cda5da8dSAndroid Build Coastguard Worker '<strong class="title">Error</strong>', 2616*cda5da8dSAndroid Build Coastguard Worker ) 2617*cda5da8dSAndroid Build Coastguard Worker contents = '<br>'.join(html.escape(line) for line in 2618*cda5da8dSAndroid Build Coastguard Worker format_exception_only(type(exc), exc)) 2619*cda5da8dSAndroid Build Coastguard Worker contents = heading + html.bigsection(url, 'error', contents) 2620*cda5da8dSAndroid Build Coastguard Worker return "Error - %s" % url, contents 2621*cda5da8dSAndroid Build Coastguard Worker 2622*cda5da8dSAndroid Build Coastguard Worker def get_html_page(url): 2623*cda5da8dSAndroid Build Coastguard Worker """Generate an HTML page for url.""" 2624*cda5da8dSAndroid Build Coastguard Worker complete_url = url 2625*cda5da8dSAndroid Build Coastguard Worker if url.endswith('.html'): 2626*cda5da8dSAndroid Build Coastguard Worker url = url[:-5] 2627*cda5da8dSAndroid Build Coastguard Worker try: 2628*cda5da8dSAndroid Build Coastguard Worker if url in ("", "index"): 2629*cda5da8dSAndroid Build Coastguard Worker title, content = html_index() 2630*cda5da8dSAndroid Build Coastguard Worker elif url == "topics": 2631*cda5da8dSAndroid Build Coastguard Worker title, content = html_topics() 2632*cda5da8dSAndroid Build Coastguard Worker elif url == "keywords": 2633*cda5da8dSAndroid Build Coastguard Worker title, content = html_keywords() 2634*cda5da8dSAndroid Build Coastguard Worker elif '=' in url: 2635*cda5da8dSAndroid Build Coastguard Worker op, _, url = url.partition('=') 2636*cda5da8dSAndroid Build Coastguard Worker if op == "search?key": 2637*cda5da8dSAndroid Build Coastguard Worker title, content = html_search(url) 2638*cda5da8dSAndroid Build Coastguard Worker elif op == "topic?key": 2639*cda5da8dSAndroid Build Coastguard Worker # try topics first, then objects. 2640*cda5da8dSAndroid Build Coastguard Worker try: 2641*cda5da8dSAndroid Build Coastguard Worker title, content = html_topicpage(url) 2642*cda5da8dSAndroid Build Coastguard Worker except ValueError: 2643*cda5da8dSAndroid Build Coastguard Worker title, content = html_getobj(url) 2644*cda5da8dSAndroid Build Coastguard Worker elif op == "get?key": 2645*cda5da8dSAndroid Build Coastguard Worker # try objects first, then topics. 2646*cda5da8dSAndroid Build Coastguard Worker if url in ("", "index"): 2647*cda5da8dSAndroid Build Coastguard Worker title, content = html_index() 2648*cda5da8dSAndroid Build Coastguard Worker else: 2649*cda5da8dSAndroid Build Coastguard Worker try: 2650*cda5da8dSAndroid Build Coastguard Worker title, content = html_getobj(url) 2651*cda5da8dSAndroid Build Coastguard Worker except ValueError: 2652*cda5da8dSAndroid Build Coastguard Worker title, content = html_topicpage(url) 2653*cda5da8dSAndroid Build Coastguard Worker else: 2654*cda5da8dSAndroid Build Coastguard Worker raise ValueError('bad pydoc url') 2655*cda5da8dSAndroid Build Coastguard Worker else: 2656*cda5da8dSAndroid Build Coastguard Worker title, content = html_getobj(url) 2657*cda5da8dSAndroid Build Coastguard Worker except Exception as exc: 2658*cda5da8dSAndroid Build Coastguard Worker # Catch any errors and display them in an error page. 2659*cda5da8dSAndroid Build Coastguard Worker title, content = html_error(complete_url, exc) 2660*cda5da8dSAndroid Build Coastguard Worker return html.page(title, content) 2661*cda5da8dSAndroid Build Coastguard Worker 2662*cda5da8dSAndroid Build Coastguard Worker if url.startswith('/'): 2663*cda5da8dSAndroid Build Coastguard Worker url = url[1:] 2664*cda5da8dSAndroid Build Coastguard Worker if content_type == 'text/css': 2665*cda5da8dSAndroid Build Coastguard Worker path_here = os.path.dirname(os.path.realpath(__file__)) 2666*cda5da8dSAndroid Build Coastguard Worker css_path = os.path.join(path_here, url) 2667*cda5da8dSAndroid Build Coastguard Worker with open(css_path) as fp: 2668*cda5da8dSAndroid Build Coastguard Worker return ''.join(fp.readlines()) 2669*cda5da8dSAndroid Build Coastguard Worker elif content_type == 'text/html': 2670*cda5da8dSAndroid Build Coastguard Worker return get_html_page(url) 2671*cda5da8dSAndroid Build Coastguard Worker # Errors outside the url handler are caught by the server. 2672*cda5da8dSAndroid Build Coastguard Worker raise TypeError('unknown content type %r for url %s' % (content_type, url)) 2673*cda5da8dSAndroid Build Coastguard Worker 2674*cda5da8dSAndroid Build Coastguard Worker 2675*cda5da8dSAndroid Build Coastguard Workerdef browse(port=0, *, open_browser=True, hostname='localhost'): 2676*cda5da8dSAndroid Build Coastguard Worker """Start the enhanced pydoc web server and open a web browser. 2677*cda5da8dSAndroid Build Coastguard Worker 2678*cda5da8dSAndroid Build Coastguard Worker Use port '0' to start the server on an arbitrary port. 2679*cda5da8dSAndroid Build Coastguard Worker Set open_browser to False to suppress opening a browser. 2680*cda5da8dSAndroid Build Coastguard Worker """ 2681*cda5da8dSAndroid Build Coastguard Worker import webbrowser 2682*cda5da8dSAndroid Build Coastguard Worker serverthread = _start_server(_url_handler, hostname, port) 2683*cda5da8dSAndroid Build Coastguard Worker if serverthread.error: 2684*cda5da8dSAndroid Build Coastguard Worker print(serverthread.error) 2685*cda5da8dSAndroid Build Coastguard Worker return 2686*cda5da8dSAndroid Build Coastguard Worker if serverthread.serving: 2687*cda5da8dSAndroid Build Coastguard Worker server_help_msg = 'Server commands: [b]rowser, [q]uit' 2688*cda5da8dSAndroid Build Coastguard Worker if open_browser: 2689*cda5da8dSAndroid Build Coastguard Worker webbrowser.open(serverthread.url) 2690*cda5da8dSAndroid Build Coastguard Worker try: 2691*cda5da8dSAndroid Build Coastguard Worker print('Server ready at', serverthread.url) 2692*cda5da8dSAndroid Build Coastguard Worker print(server_help_msg) 2693*cda5da8dSAndroid Build Coastguard Worker while serverthread.serving: 2694*cda5da8dSAndroid Build Coastguard Worker cmd = input('server> ') 2695*cda5da8dSAndroid Build Coastguard Worker cmd = cmd.lower() 2696*cda5da8dSAndroid Build Coastguard Worker if cmd == 'q': 2697*cda5da8dSAndroid Build Coastguard Worker break 2698*cda5da8dSAndroid Build Coastguard Worker elif cmd == 'b': 2699*cda5da8dSAndroid Build Coastguard Worker webbrowser.open(serverthread.url) 2700*cda5da8dSAndroid Build Coastguard Worker else: 2701*cda5da8dSAndroid Build Coastguard Worker print(server_help_msg) 2702*cda5da8dSAndroid Build Coastguard Worker except (KeyboardInterrupt, EOFError): 2703*cda5da8dSAndroid Build Coastguard Worker print() 2704*cda5da8dSAndroid Build Coastguard Worker finally: 2705*cda5da8dSAndroid Build Coastguard Worker if serverthread.serving: 2706*cda5da8dSAndroid Build Coastguard Worker serverthread.stop() 2707*cda5da8dSAndroid Build Coastguard Worker print('Server stopped') 2708*cda5da8dSAndroid Build Coastguard Worker 2709*cda5da8dSAndroid Build Coastguard Worker 2710*cda5da8dSAndroid Build Coastguard Worker# -------------------------------------------------- command-line interface 2711*cda5da8dSAndroid Build Coastguard Worker 2712*cda5da8dSAndroid Build Coastguard Workerdef ispath(x): 2713*cda5da8dSAndroid Build Coastguard Worker return isinstance(x, str) and x.find(os.sep) >= 0 2714*cda5da8dSAndroid Build Coastguard Worker 2715*cda5da8dSAndroid Build Coastguard Workerdef _get_revised_path(given_path, argv0): 2716*cda5da8dSAndroid Build Coastguard Worker """Ensures current directory is on returned path, and argv0 directory is not 2717*cda5da8dSAndroid Build Coastguard Worker 2718*cda5da8dSAndroid Build Coastguard Worker Exception: argv0 dir is left alone if it's also pydoc's directory. 2719*cda5da8dSAndroid Build Coastguard Worker 2720*cda5da8dSAndroid Build Coastguard Worker Returns a new path entry list, or None if no adjustment is needed. 2721*cda5da8dSAndroid Build Coastguard Worker """ 2722*cda5da8dSAndroid Build Coastguard Worker # Scripts may get the current directory in their path by default if they're 2723*cda5da8dSAndroid Build Coastguard Worker # run with the -m switch, or directly from the current directory. 2724*cda5da8dSAndroid Build Coastguard Worker # The interactive prompt also allows imports from the current directory. 2725*cda5da8dSAndroid Build Coastguard Worker 2726*cda5da8dSAndroid Build Coastguard Worker # Accordingly, if the current directory is already present, don't make 2727*cda5da8dSAndroid Build Coastguard Worker # any changes to the given_path 2728*cda5da8dSAndroid Build Coastguard Worker if '' in given_path or os.curdir in given_path or os.getcwd() in given_path: 2729*cda5da8dSAndroid Build Coastguard Worker return None 2730*cda5da8dSAndroid Build Coastguard Worker 2731*cda5da8dSAndroid Build Coastguard Worker # Otherwise, add the current directory to the given path, and remove the 2732*cda5da8dSAndroid Build Coastguard Worker # script directory (as long as the latter isn't also pydoc's directory. 2733*cda5da8dSAndroid Build Coastguard Worker stdlib_dir = os.path.dirname(__file__) 2734*cda5da8dSAndroid Build Coastguard Worker script_dir = os.path.dirname(argv0) 2735*cda5da8dSAndroid Build Coastguard Worker revised_path = given_path.copy() 2736*cda5da8dSAndroid Build Coastguard Worker if script_dir in given_path and not os.path.samefile(script_dir, stdlib_dir): 2737*cda5da8dSAndroid Build Coastguard Worker revised_path.remove(script_dir) 2738*cda5da8dSAndroid Build Coastguard Worker revised_path.insert(0, os.getcwd()) 2739*cda5da8dSAndroid Build Coastguard Worker return revised_path 2740*cda5da8dSAndroid Build Coastguard Worker 2741*cda5da8dSAndroid Build Coastguard Worker 2742*cda5da8dSAndroid Build Coastguard Worker# Note: the tests only cover _get_revised_path, not _adjust_cli_path itself 2743*cda5da8dSAndroid Build Coastguard Workerdef _adjust_cli_sys_path(): 2744*cda5da8dSAndroid Build Coastguard Worker """Ensures current directory is on sys.path, and __main__ directory is not. 2745*cda5da8dSAndroid Build Coastguard Worker 2746*cda5da8dSAndroid Build Coastguard Worker Exception: __main__ dir is left alone if it's also pydoc's directory. 2747*cda5da8dSAndroid Build Coastguard Worker """ 2748*cda5da8dSAndroid Build Coastguard Worker revised_path = _get_revised_path(sys.path, sys.argv[0]) 2749*cda5da8dSAndroid Build Coastguard Worker if revised_path is not None: 2750*cda5da8dSAndroid Build Coastguard Worker sys.path[:] = revised_path 2751*cda5da8dSAndroid Build Coastguard Worker 2752*cda5da8dSAndroid Build Coastguard Worker 2753*cda5da8dSAndroid Build Coastguard Workerdef cli(): 2754*cda5da8dSAndroid Build Coastguard Worker """Command-line interface (looks at sys.argv to decide what to do).""" 2755*cda5da8dSAndroid Build Coastguard Worker import getopt 2756*cda5da8dSAndroid Build Coastguard Worker class BadUsage(Exception): pass 2757*cda5da8dSAndroid Build Coastguard Worker 2758*cda5da8dSAndroid Build Coastguard Worker _adjust_cli_sys_path() 2759*cda5da8dSAndroid Build Coastguard Worker 2760*cda5da8dSAndroid Build Coastguard Worker try: 2761*cda5da8dSAndroid Build Coastguard Worker opts, args = getopt.getopt(sys.argv[1:], 'bk:n:p:w') 2762*cda5da8dSAndroid Build Coastguard Worker writing = False 2763*cda5da8dSAndroid Build Coastguard Worker start_server = False 2764*cda5da8dSAndroid Build Coastguard Worker open_browser = False 2765*cda5da8dSAndroid Build Coastguard Worker port = 0 2766*cda5da8dSAndroid Build Coastguard Worker hostname = 'localhost' 2767*cda5da8dSAndroid Build Coastguard Worker for opt, val in opts: 2768*cda5da8dSAndroid Build Coastguard Worker if opt == '-b': 2769*cda5da8dSAndroid Build Coastguard Worker start_server = True 2770*cda5da8dSAndroid Build Coastguard Worker open_browser = True 2771*cda5da8dSAndroid Build Coastguard Worker if opt == '-k': 2772*cda5da8dSAndroid Build Coastguard Worker apropos(val) 2773*cda5da8dSAndroid Build Coastguard Worker return 2774*cda5da8dSAndroid Build Coastguard Worker if opt == '-p': 2775*cda5da8dSAndroid Build Coastguard Worker start_server = True 2776*cda5da8dSAndroid Build Coastguard Worker port = val 2777*cda5da8dSAndroid Build Coastguard Worker if opt == '-w': 2778*cda5da8dSAndroid Build Coastguard Worker writing = True 2779*cda5da8dSAndroid Build Coastguard Worker if opt == '-n': 2780*cda5da8dSAndroid Build Coastguard Worker start_server = True 2781*cda5da8dSAndroid Build Coastguard Worker hostname = val 2782*cda5da8dSAndroid Build Coastguard Worker 2783*cda5da8dSAndroid Build Coastguard Worker if start_server: 2784*cda5da8dSAndroid Build Coastguard Worker browse(port, hostname=hostname, open_browser=open_browser) 2785*cda5da8dSAndroid Build Coastguard Worker return 2786*cda5da8dSAndroid Build Coastguard Worker 2787*cda5da8dSAndroid Build Coastguard Worker if not args: raise BadUsage 2788*cda5da8dSAndroid Build Coastguard Worker for arg in args: 2789*cda5da8dSAndroid Build Coastguard Worker if ispath(arg) and not os.path.exists(arg): 2790*cda5da8dSAndroid Build Coastguard Worker print('file %r does not exist' % arg) 2791*cda5da8dSAndroid Build Coastguard Worker sys.exit(1) 2792*cda5da8dSAndroid Build Coastguard Worker try: 2793*cda5da8dSAndroid Build Coastguard Worker if ispath(arg) and os.path.isfile(arg): 2794*cda5da8dSAndroid Build Coastguard Worker arg = importfile(arg) 2795*cda5da8dSAndroid Build Coastguard Worker if writing: 2796*cda5da8dSAndroid Build Coastguard Worker if ispath(arg) and os.path.isdir(arg): 2797*cda5da8dSAndroid Build Coastguard Worker writedocs(arg) 2798*cda5da8dSAndroid Build Coastguard Worker else: 2799*cda5da8dSAndroid Build Coastguard Worker writedoc(arg) 2800*cda5da8dSAndroid Build Coastguard Worker else: 2801*cda5da8dSAndroid Build Coastguard Worker help.help(arg) 2802*cda5da8dSAndroid Build Coastguard Worker except (ImportError, ErrorDuringImport) as value: 2803*cda5da8dSAndroid Build Coastguard Worker print(value) 2804*cda5da8dSAndroid Build Coastguard Worker sys.exit(1) 2805*cda5da8dSAndroid Build Coastguard Worker 2806*cda5da8dSAndroid Build Coastguard Worker except (getopt.error, BadUsage): 2807*cda5da8dSAndroid Build Coastguard Worker cmd = os.path.splitext(os.path.basename(sys.argv[0]))[0] 2808*cda5da8dSAndroid Build Coastguard Worker print("""pydoc - the Python documentation tool 2809*cda5da8dSAndroid Build Coastguard Worker 2810*cda5da8dSAndroid Build Coastguard Worker{cmd} <name> ... 2811*cda5da8dSAndroid Build Coastguard Worker Show text documentation on something. <name> may be the name of a 2812*cda5da8dSAndroid Build Coastguard Worker Python keyword, topic, function, module, or package, or a dotted 2813*cda5da8dSAndroid Build Coastguard Worker reference to a class or function within a module or module in a 2814*cda5da8dSAndroid Build Coastguard Worker package. If <name> contains a '{sep}', it is used as the path to a 2815*cda5da8dSAndroid Build Coastguard Worker Python source file to document. If name is 'keywords', 'topics', 2816*cda5da8dSAndroid Build Coastguard Worker or 'modules', a listing of these things is displayed. 2817*cda5da8dSAndroid Build Coastguard Worker 2818*cda5da8dSAndroid Build Coastguard Worker{cmd} -k <keyword> 2819*cda5da8dSAndroid Build Coastguard Worker Search for a keyword in the synopsis lines of all available modules. 2820*cda5da8dSAndroid Build Coastguard Worker 2821*cda5da8dSAndroid Build Coastguard Worker{cmd} -n <hostname> 2822*cda5da8dSAndroid Build Coastguard Worker Start an HTTP server with the given hostname (default: localhost). 2823*cda5da8dSAndroid Build Coastguard Worker 2824*cda5da8dSAndroid Build Coastguard Worker{cmd} -p <port> 2825*cda5da8dSAndroid Build Coastguard Worker Start an HTTP server on the given port on the local machine. Port 2826*cda5da8dSAndroid Build Coastguard Worker number 0 can be used to get an arbitrary unused port. 2827*cda5da8dSAndroid Build Coastguard Worker 2828*cda5da8dSAndroid Build Coastguard Worker{cmd} -b 2829*cda5da8dSAndroid Build Coastguard Worker Start an HTTP server on an arbitrary unused port and open a web browser 2830*cda5da8dSAndroid Build Coastguard Worker to interactively browse documentation. This option can be used in 2831*cda5da8dSAndroid Build Coastguard Worker combination with -n and/or -p. 2832*cda5da8dSAndroid Build Coastguard Worker 2833*cda5da8dSAndroid Build Coastguard Worker{cmd} -w <name> ... 2834*cda5da8dSAndroid Build Coastguard Worker Write out the HTML documentation for a module to a file in the current 2835*cda5da8dSAndroid Build Coastguard Worker directory. If <name> contains a '{sep}', it is treated as a filename; if 2836*cda5da8dSAndroid Build Coastguard Worker it names a directory, documentation is written for all the contents. 2837*cda5da8dSAndroid Build Coastguard Worker""".format(cmd=cmd, sep=os.sep)) 2838*cda5da8dSAndroid Build Coastguard Worker 2839*cda5da8dSAndroid Build Coastguard Workerif __name__ == '__main__': 2840*cda5da8dSAndroid Build Coastguard Worker cli() 2841