55import inspect
66import os
77import subprocess
8+ import types
89import typing
910from pathlib import Path
1011
12+ import docstring_parser
1113import docutils .nodes
1214import docutils .parsers .rst .states
1315import git
@@ -25,6 +27,18 @@ def get_build_root() -> Path:
2527 return root
2628
2729
30+ def is_attribute (module : types .ModuleType , parameter : str ) -> bool :
31+ """Returns true if `parameter` is an attribute of `module`."""
32+ docs = docstring_parser .parse (inspect .getdoc (module ), docstring_parser .DocstringStyle .GOOGLE )
33+ for param in docs .params :
34+ # The docstring_parser library can mis-parse arguments like `arg (:obj:`str`)` as `arg (`
35+ # which would create a false-negative below, so we just strip away the extra parenthesis.
36+ if param .args [0 ] == "attribute" and param .arg_name .rstrip (" (" ) == parameter :
37+ return True
38+
39+ return False
40+
41+
2842def linkcode_resolve (repo_link : str , domain : str , info : dict [str , str ]) -> typing .Optional [str ]:
2943 """
3044 Function called by linkcode to get the URL for a given resource.
@@ -59,7 +73,15 @@ def linkcode_resolve(repo_link: str, domain: str, info: dict[str, str]) -> typin
5973
6074 symbol = [module ]
6175 for name in symbol_name .split ("." ):
62- symbol .append (getattr (symbol [- 1 ], name ))
76+ try :
77+ symbol .append (getattr (symbol [- 1 ], name ))
78+ except AttributeError as e :
79+ # This could be caused by trying to link a class attribute
80+ if is_attribute (symbol [- 1 ], name ):
81+ break
82+ else :
83+ raise e
84+
6385 symbol_name = name
6486
6587 try :
@@ -138,9 +160,13 @@ def cleanup() -> None:
138160 content = file .read_text (encoding = "utf-8" ).splitlines (keepends = True )
139161
140162 # Rename the extension to be less wordy
141- # Example: pydis_core.exts -> pydis_core Exts
142- title = content [0 ].split ()[0 ].strip ().replace ("pydis_core." , "" ).replace ("." , " " ).title ()
143- title = f"{ title } \n { '=' * len (title )} \n \n "
163+ # Example: pydis_core.exts -> Exts
164+ title = content [0 ].split ()[0 ].strip ().replace ("\\ " , "" ).replace ("pydis_core." , "" ).replace ("." , " " )
165+ if "pydis_core" in title :
166+ # Root title: pydis_core -> pydis core
167+ title = title .replace ("_" , " " )
168+
169+ title = f"{ title .title ()} \n { '=' * len (title )} \n \n "
144170 content = title , * content [3 :]
145171
146172 file .write_text ("" .join (content ), encoding = "utf-8" )
0 commit comments