misc
1import abc 2from ctypes import Structure 3from dataclasses import dataclass 4import functools 5from functools import cached_property 6from functools import lru_cache 7import sched 8from typing import Generic 9from typing import TypeVar 10from typing import Union 11 12# https://github.com/mitmproxy/pdoc/issues/226 13 14 15class Descriptor: 16 def __init__(self, func): 17 self.__doc__ = func.__doc__ 18 19 def __get__(self, instance, owner): 20 return self if instance is None else getattr(instance, "_x", 0) 21 22 def __set__(self, instance, value): 23 instance._x = value 24 25 26class Issue226: 27 @Descriptor 28 def size(self): 29 """This is the size""" 30 31 32# Testing function and object default values 33 34 35def default_func(): 36 pass 37 38 39default_obj = object() 40 41var_with_default_obj = default_obj 42"""this shouldn't render the object address""" 43var_with_default_func = default_func 44"""this just renders like a normal function""" 45 46 47def func_with_defaults(a=default_obj, b=default_func): 48 """this shouldn't render object or function addresses""" 49 pass 50 51 52# Testing classmethod links in code 53class ClassmethodLink: 54 """ 55 You can either do 56 57 >>> ClassmethodLink.bar() 58 42 59 60 or 61 62 ```python 63 ClassmethodLink.bar() 64 ``` 65 66 neither will be linked. 67 """ 68 69 @classmethod 70 def bar(cls): 71 return 42 72 73 74# Testing generic bases 75 76T = TypeVar("T") 77 78 79class GenericParent(Generic[T]): 80 """GenericParent""" 81 82 83class NonGenericChild(GenericParent[str]): 84 """NonGenericChild""" 85 86 87# Testing docstring inheritance 88 89 90class Base: 91 def __init__(self): 92 """init""" 93 super().__init__() 94 95 def foo(self): 96 """foo""" 97 pass 98 99 @classmethod 100 def bar(cls): 101 """bar""" 102 pass 103 104 @staticmethod 105 def baz(): 106 """baz""" 107 pass 108 109 @property 110 def qux(self): 111 """qux""" 112 return 113 114 @cached_property 115 def quux(self): 116 """quux""" 117 return 118 119 quuux: int = 42 120 """quuux""" 121 122 123class Child(Base): 124 def __init__(self): 125 super().__init__() 126 127 def foo(self): 128 pass 129 130 @classmethod 131 def bar(cls): 132 pass 133 134 @staticmethod 135 def baz(): 136 pass 137 138 @property 139 def qux(self): 140 return 141 142 @cached_property 143 def quux(self): 144 return 145 146 quuux: int = 42 147 148 149# Testing that an attribute that is only annotated does not trigger a "submodule not found" warning. 150 151only_annotated: int 152 153 154# Testing that a private class in __all__ is displayed 155 156 157class _Private: 158 """private class""" 159 160 pass 161 162 def _do(self): 163 """private method""" 164 165 166# Testing a class attribute that is a lambda (which generates quirky sources) 167 168 169class LambdaAttr: 170 # not really supported, but also shouldn't crash. 171 attr = lambda x: 42 # noqa 172 173 174# Testing different docstring annotations 175# fmt: off 176 177 178def foo(): 179 """no indents""" 180 181 182def bar(): 183 """no 184indents""" 185 186 187def baz(): 188 """one 189 indent""" 190 191 192def qux(): 193 """ 194 two 195 indents 196 """ 197 198 199class Indented: 200 def foo(self): 201 """no indents""" 202 203 def bar(self): 204 """no 205indents""" 206 207 def baz(self): 208 """one 209 indent""" 210 211 def qux(self): 212 """ 213 two 214 indents 215 """ 216 217 @lru_cache() 218 def foo_decorated(self): 219 """no indents""" 220 221 @lru_cache() 222 # comment 223 def foo_commented(self): 224 """no indents""" 225 226 @lru_cache() 227 def bar_decorated(self): 228 """no 229indents""" 230 231 @lru_cache() 232 def baz_decorated(self): 233 """one 234 indent""" 235 236 @lru_cache() 237 def qux_decorated(self): 238 """ 239 two 240 indents 241 """ 242 243 @lru_cache( 244 maxsize=42 245 ) 246 def quux_decorated(self): 247 """multi-line decorator, https://github.com/mitmproxy/pdoc/issues/246""" 248 249 250def _protected_decorator(f): 251 return f 252 253 254@_protected_decorator 255def fun_with_protected_decorator(): 256 """This function has a protected decorator (name starting with a single `_`).""" 257 258 259class UnhashableDataDescriptor: 260 def __get__(self): 261 pass 262 __hash__ = None # type: ignore 263 264 265unhashable = UnhashableDataDescriptor() 266 267 268class AbstractClass(metaclass=abc.ABCMeta): 269 """This class shouldn't show a constructor as it's abstract.""" 270 @abc.abstractmethod 271 def foo(self): 272 pass 273 274 275# Adapted from https://github.com/mitmproxy/pdoc/issues/320 276 277def make_adder(a: int): 278 def add_func(b: int) -> int: 279 """This function adds two numbers.""" 280 return a + b 281 return add_func 282 283 284add_four = make_adder(4) 285add_five = make_adder(5) 286"""This function adds five.""" 287add_six = make_adder(6) 288add_six.__doc__ = "This function adds six." 289 290 291# Adapted from https://github.com/mitmproxy/pdoc/issues/335 292def linkify_links(): 293 """ 294 This docstring contains links that are also identifiers: 295 296 - [`linkify_links`](https://example.com/) 297 - [misc.linkify_links](https://example.com/) 298 - [`linkify_links()`](https://example.com/) 299 - [misc.linkify_links()](https://example.com/) 300 - [link in target](https://example.com/misc.linkify_links) 301 - [explicit linking](#AbstractClass.foo) 302 """ 303 304 305class Issue352aMeta(type): 306 def __call__(cls, *args, **kwargs): 307 """Meta.__call__""" 308 309 310class Issue352a(metaclass=Issue352aMeta): 311 def __init__(self): 312 """Issue352.__init__ should be preferred over Meta.__call__.""" 313 314 315class Issue352bMeta(type): 316 def __call__(cls, *args, **kwargs): 317 pass 318 319 320class Issue352b(metaclass=Issue352bMeta): 321 """No docstrings for the constructor here.""" 322 323 324class CustomCallMeta(type): 325 def __call__(cls, *args, **kwargs): 326 """Custom docstring in metaclass.`__call__`""" 327 328 329class CustomCall(metaclass=CustomCallMeta): 330 """A class where the constructor is defined by its metaclass.""" 331 332 333class Headings: 334 """ 335 # Heading 1 336 337 Here is some text. 338 339 ## Heading 2 340 341 Here is some text. 342 343 ### Heading 3 344 345 Here is some text. 346 347 #### Heading 4 348 349 Here is some text. 350 351 ##### Heading 5 352 353 Here is some text. 354 355 ###### Heading 6 356 357 Here is some text. 358 359 """ 360 361 362class CustomRepr: 363 def __repr__(self): 364 return "°<script>alert(1)</script>" 365 366 367def repr_not_syntax_highlightable(x=CustomRepr()): 368 """The default value for x fails to highlight with pygments.""" 369 370 371class ClassDecorator: 372 """This is a class that wraps a function. It will be documented correctly.""" 373 def __init__(self, func): 374 self._func = func 375 376 377@ClassDecorator 378def another_decorated_function(arg: str) -> str: 379 """This is another decorated function. It will not be documented correctly.""" 380 raise NotImplementedError 381 382 383class SubclassRef: 384 class SubClass: 385 pass 386 387 def __init__(self, x: "SubClass"): 388 print(x) 389 390 391class ClassAsAttribute: 392 static_attr_to_class = ClassDecorator 393 """this is a static attribute that point to a Class (not an instance)""" 394 395 static_attr_to_instance = ClassDecorator(None) 396 """this is a static attribute that point to an instance""" 397 398 399class scheduler(sched.scheduler): 400 """Test for broken links for inherited methods, https://github.com/mitmproxy/pdoc/issues/490""" 401 402 403class __init__: 404 """https://github.com/mitmproxy/pdoc/issues/519""" 405 406 407def dynamically_modify_docstring1(): 408 """this should **not** be the docstring.""" 409 410 411def dynamically_modify_docstring2(): 412 pass 413 414 415dynamically_modify_docstring1.__doc__ = "https://github.com/mitmproxy/pdoc/issues/536" 416dynamically_modify_docstring2.__doc__ = "https://github.com/mitmproxy/pdoc/issues/536" 417 418 419def _docstring_modifier(fn): 420 fn.__doc__ = "https://github.com/mitmproxy/pdoc/issues/536" 421 return fn 422 423 424@_docstring_modifier 425def dynamically_modify_docstring3(): 426 """This should **not** be the docstring.""" 427 428 429@_docstring_modifier 430def dynamically_modify_docstring4(): 431 pass 432 433 434class DocstringFromNew: 435 def __new__(cls, *args, **kwargs): 436 """This is a class with a docstring inferred from `__new__`.""" 437 438 439 440 441 442 443class SingleDispatchMethodExample: 444 @functools.singledispatchmethod 445 def fancymethod(self, str_or_int: Union[str, int]): 446 """A fancy method which is capable of handling either `str` or `int`. 447 448 :param str_or_int: string or integer to handle 449 """ 450 raise NotImplementedError(f"{type(str_or_int)=} not implemented!") 451 452 @fancymethod.register 453 def fancymethod_handle_str(self, str_to_handle: str): 454 """Fancy method handles a string. 455 456 :param str_to_handle: string which will be handled 457 """ 458 print(f"{type(str_to_handle)} = '{str_to_handle}") 459 460 @fancymethod.register 461 def _fancymethod_handle_int(self, int_to_handle: int): 462 """Fancy method handles int (not shown in doc). 463 464 :param int_to_handle: int which will be handled 465 """ 466 print(f"{type(int_to_handle)} = '{int_to_handle:x}'") 467 468 469@dataclass(init=False) 470class DataclassStructure(Structure): 471 """DataclassStructure raises for `inspect.signature`.""" 472 473 474__all__ = [ 475 "Issue226", 476 "var_with_default_obj", 477 "var_with_default_func", 478 "func_with_defaults", 479 "ClassmethodLink", 480 "GenericParent", 481 "NonGenericChild", 482 "Child", 483 "only_annotated", 484 "_Private", 485 "LambdaAttr", 486 "foo", 487 "bar", 488 "baz", 489 "qux", 490 "Indented", 491 "fun_with_protected_decorator", 492 "unhashable", 493 "AbstractClass", 494 "add_four", 495 "add_five", 496 "add_six", 497 "linkify_links", 498 "Issue352a", 499 "Issue352b", 500 "CustomCall", 501 "Headings", 502 "repr_not_syntax_highlightable", 503 "ClassDecorator", 504 "another_decorated_function", 505 "SubclassRef", 506 "ClassAsAttribute", 507 "scheduler", 508 "__init__", 509 "dynamically_modify_docstring1", 510 "dynamically_modify_docstring2", 511 "dynamically_modify_docstring3", 512 "dynamically_modify_docstring4", 513 "DocstringFromNew", 514 "SingleDispatchMethodExample", 515 "DataclassStructure", 516]
this shouldn't render the object address
this just renders like a normal function
48def func_with_defaults(a=default_obj, b=default_func): 49 """this shouldn't render object or function addresses""" 50 pass
this shouldn't render object or function addresses
GenericParent
NonGenericChild
124class Child(Base): 125 def __init__(self): 126 super().__init__() 127 128 def foo(self): 129 pass 130 131 @classmethod 132 def bar(cls): 133 pass 134 135 @staticmethod 136 def baz(): 137 pass 138 139 @property 140 def qux(self): 141 return 142 143 @cached_property 144 def quux(self): 145 return 146 147 quuux: int = 42
158class _Private: 159 """private class""" 160 161 pass 162 163 def _do(self): 164 """private method"""
private class
no indents
no indents
one indent
two indents
200class Indented: 201 def foo(self): 202 """no indents""" 203 204 def bar(self): 205 """no 206indents""" 207 208 def baz(self): 209 """one 210 indent""" 211 212 def qux(self): 213 """ 214 two 215 indents 216 """ 217 218 @lru_cache() 219 def foo_decorated(self): 220 """no indents""" 221 222 @lru_cache() 223 # comment 224 def foo_commented(self): 225 """no indents""" 226 227 @lru_cache() 228 def bar_decorated(self): 229 """no 230indents""" 231 232 @lru_cache() 233 def baz_decorated(self): 234 """one 235 indent""" 236 237 @lru_cache() 238 def qux_decorated(self): 239 """ 240 two 241 indents 242 """ 243 244 @lru_cache( 245 maxsize=42 246 ) 247 def quux_decorated(self): 248 """multi-line decorator, https://github.com/mitmproxy/pdoc/issues/246"""
255@_protected_decorator 256def fun_with_protected_decorator(): 257 """This function has a protected decorator (name starting with a single `_`)."""
This function has a protected decorator (name starting with a single _
).
269class AbstractClass(metaclass=abc.ABCMeta): 270 """This class shouldn't show a constructor as it's abstract.""" 271 @abc.abstractmethod 272 def foo(self): 273 pass
This class shouldn't show a constructor as it's abstract.
This function adds two numbers.
This function adds five.
This function adds six.
293def linkify_links(): 294 """ 295 This docstring contains links that are also identifiers: 296 297 - [`linkify_links`](https://example.com/) 298 - [misc.linkify_links](https://example.com/) 299 - [`linkify_links()`](https://example.com/) 300 - [misc.linkify_links()](https://example.com/) 301 - [link in target](https://example.com/misc.linkify_links) 302 - [explicit linking](#AbstractClass.foo) 303 """
This docstring contains links that are also identifiers:
No docstrings for the constructor here.
330class CustomCall(metaclass=CustomCallMeta): 331 """A class where the constructor is defined by its metaclass."""
A class where the constructor is defined by its metaclass.
334class Headings: 335 """ 336 # Heading 1 337 338 Here is some text. 339 340 ## Heading 2 341 342 Here is some text. 343 344 ### Heading 3 345 346 Here is some text. 347 348 #### Heading 4 349 350 Here is some text. 351 352 ##### Heading 5 353 354 Here is some text. 355 356 ###### Heading 6 357 358 Here is some text. 359 360 """
Heading 1
Here is some text.
Heading 2
Here is some text.
Heading 3
Here is some text.
Heading 4
Here is some text.
Heading 5
Here is some text.
Heading 6
Here is some text.
368def repr_not_syntax_highlightable(x=CustomRepr()): 369 """The default value for x fails to highlight with pygments."""
The default value for x fails to highlight with pygments.
372class ClassDecorator: 373 """This is a class that wraps a function. It will be documented correctly.""" 374 def __init__(self, func): 375 self._func = func
This is a class that wraps a function. It will be documented correctly.
This is another decorated function. It will not be documented correctly.
392class ClassAsAttribute: 393 static_attr_to_class = ClassDecorator 394 """this is a static attribute that point to a Class (not an instance)""" 395 396 static_attr_to_instance = ClassDecorator(None) 397 """this is a static attribute that point to an instance"""
this is a static attribute that point to a Class (not an instance)
this is a static attribute that point to an instance
400class scheduler(sched.scheduler): 401 """Test for broken links for inherited methods, https://github.com/mitmproxy/pdoc/issues/490"""
Test for broken links for inherited methods, https://github.com/mitmproxy/pdoc/issues/490
444class SingleDispatchMethodExample: 445 @functools.singledispatchmethod 446 def fancymethod(self, str_or_int: Union[str, int]): 447 """A fancy method which is capable of handling either `str` or `int`. 448 449 :param str_or_int: string or integer to handle 450 """ 451 raise NotImplementedError(f"{type(str_or_int)=} not implemented!") 452 453 @fancymethod.register 454 def fancymethod_handle_str(self, str_to_handle: str): 455 """Fancy method handles a string. 456 457 :param str_to_handle: string which will be handled 458 """ 459 print(f"{type(str_to_handle)} = '{str_to_handle}") 460 461 @fancymethod.register 462 def _fancymethod_handle_int(self, int_to_handle: int): 463 """Fancy method handles int (not shown in doc). 464 465 :param int_to_handle: int which will be handled 466 """ 467 print(f"{type(int_to_handle)} = '{int_to_handle:x}'")
445 @functools.singledispatchmethod 446 def fancymethod(self, str_or_int: Union[str, int]): 447 """A fancy method which is capable of handling either `str` or `int`. 448 449 :param str_or_int: string or integer to handle 450 """ 451 raise NotImplementedError(f"{type(str_or_int)=} not implemented!")
A fancy method which is capable of handling either str
or int
.
Parameters
- str_or_int: string or integer to handle
453 @fancymethod.register 454 def fancymethod_handle_str(self, str_to_handle: str): 455 """Fancy method handles a string. 456 457 :param str_to_handle: string which will be handled 458 """ 459 print(f"{type(str_to_handle)} = '{str_to_handle}")
Fancy method handles a string.
Parameters
- str_to_handle: string which will be handled
470@dataclass(init=False) 471class DataclassStructure(Structure): 472 """DataclassStructure raises for `inspect.signature`."""
DataclassStructure raises for inspect.signature
.