Skip to content

Commit 68cf369

Browse files
committed
WIP
1 parent fba5dde commit 68cf369

3 files changed

Lines changed: 92 additions & 0 deletions

File tree

Doc/conf.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
_OPTIONAL_EXTENSIONS = (
4545
'notfound.extension',
4646
'sphinxext.opengraph',
47+
'typeshed_types',
4748
)
4849
for optional_ext in _OPTIONAL_EXTENSIONS:
4950
try:

Doc/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,4 @@ sphinx-notfound-page~=1.0.0
1919
python-docs-theme>=2023.3.1,!=2023.7
2020

2121
-c constraints.txt
22+
typeshed_client
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
"""Override Python Domain types to pull signature information from typeshed."""
2+
from __future__ import annotations
3+
import ast
4+
from typing import TYPE_CHECKING
5+
import pathlib
6+
7+
import typeshed_client
8+
from sphinx.domains.python import (
9+
PyFunction,
10+
PyDecoratorFunction,
11+
PyClasslike,
12+
PyMethod,
13+
PyClassMethod,
14+
PyStaticMethod,
15+
PyDecoratorMethod,
16+
PyAttribute,
17+
PyProperty,
18+
PythonDomain,
19+
)
20+
21+
if TYPE_CHECKING:
22+
from sphinx.application import Sphinx
23+
from sphinx.util.typing import ExtensionMetadata
24+
from sphinx.addnodes import desc_signature
25+
26+
ignored_modules = (
27+
"test",
28+
)
29+
30+
search_context = typeshed_client.get_search_context(
31+
typeshed=pathlib.Path().home() / "typeshed" / "stdlib",
32+
version=(3, 14),
33+
platform="linux",
34+
)
35+
36+
def ast_from_resolved_name(resolved_name: typeshed_client.resolver.ResolvedName) -> ast.AST:
37+
if isinstance(resolved_name, typeshed_client.NameInfo):
38+
return resolved_name.ast
39+
elif isinstance(resolved_name, typeshed_client.ImportedInfo):
40+
return resolved_name.info.ast
41+
else:
42+
return None
43+
44+
class TypedPyFunction(PyFunction):
45+
46+
def handle_signature(self, sig: str, signode: desc_signature) -> tuple[str, str]:
47+
fullname, clsname = super().handle_signature(sig, signode)
48+
modname = self.options.get('module', self.env.ref_context.get('py:module'))
49+
resolver = typeshed_client.Resolver(search_context)
50+
if modname and not any((modname.startswith(name) for name in ignored_modules)):
51+
try:
52+
if modname is not None:
53+
qualname = f"{modname}.{fullname}"
54+
else:
55+
qualname = fullname
56+
resolved_name = resolver.get_fully_qualified_name(qualname)
57+
resolved_ast = ast_from_resolved_name(resolved_name)
58+
if resolved_ast:
59+
# update signode with the proper signature from resolved_ast
60+
pass
61+
except Exception:
62+
print(f"Exception with: {modname}.{fullname}")
63+
raise
64+
65+
return fullname, clsname
66+
67+
overriden_directives = {
68+
"function": TypedPyFunction,
69+
"class": PyClasslike,
70+
"method": PyMethod,
71+
"classmethod": PyClassMethod,
72+
"staticmethod": PyStaticMethod,
73+
"attribute": PyAttribute,
74+
"property": PyProperty,
75+
"decorator": PyDecoratorFunction,
76+
"decoratormethod": PyDecoratorMethod,
77+
}
78+
79+
80+
def setup(app: Sphinx) -> ExtensionMetadata:
81+
for name, type_ in overriden_directives.items():
82+
app.add_directive_to_domain("py", name, type_, override=True)
83+
PythonDomain.directives.update(**overriden_directives)
84+
app.add_domain(PythonDomain, override=True)
85+
return {
86+
"version": "0.1.0",
87+
"env_version": 4,
88+
"parallel_read_safe": True,
89+
"parallel_write_safe": True,
90+
}

0 commit comments

Comments
 (0)