Skip to content

Commit a7ffdc5

Browse files
committed
Merge branch 'master' into up-master
2 parents f8a9e3f + e5e3bfc commit a7ffdc5

8 files changed

Lines changed: 166 additions & 50 deletions

File tree

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"Sphinx>=4.1.0",
2121
"markupsafe==3.0.2",
2222
"attrs",
23-
"cattrs",
23+
"cattrs<25.1",
2424
],
2525
python_requires=">=3.10",
2626
classifiers=[

sphinx_js/js/cli.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ async function makeApp(args: string[]): Promise<Application> {
5353
throw new ExitError(ExitCodes.Ok);
5454
}
5555
app.extraData = {};
56-
app.options.getValue("modifierTags").push("@hidetype");
57-
app.options.getValue("blockTags").push("@destructure");
56+
app.options.getValue("modifierTags").push("@hidetype", "@omitFromAutoModule");
57+
app.options.getValue("blockTags").push("@destructure", "@summaryLink");
5858
return app;
5959
}
6060

sphinx_js/renderers.py

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -710,7 +710,11 @@ def get_object(self) -> Module: # type:ignore[override]
710710
return analyzer._modules_by_path.get(self._partial_path)
711711

712712
def rst_for_group(self, objects: Iterable[TopLevel]) -> list[str]:
713-
return [self.rst_for(obj) for obj in objects]
713+
return [
714+
self.rst_for(obj)
715+
for obj in objects
716+
if "@omitFromAutoModule" not in obj.modifier_tags
717+
]
714718

715719
def rst( # type:ignore[override]
716720
self,
@@ -722,7 +726,7 @@ def rst( # type:ignore[override]
722726
rst.append([f".. js:module:: {''.join(partial_path)}"])
723727
for group_name in _SECTION_ORDER:
724728
rst.append(self.rst_for_group(getattr(obj, group_name)))
725-
return "\n\n".join(["\n\n".join(r) for r in rst])
729+
return "\n\n".join(["\n\n".join(r) for r in rst if r])
726730

727731

728732
class AutoSummaryRenderer(Renderer):
@@ -787,26 +791,27 @@ def get_sig(self, obj: TopLevel) -> str:
787791
else:
788792
return ""
789793

790-
def get_summary_row(
791-
self, pkgname: str, obj: TopLevel
792-
) -> tuple[str, str, str, str, str, str]:
794+
def get_summary_row(self, pkgname: str, obj: TopLevel) -> tuple[str, str, str]:
793795
"""Get the summary table row for obj.
794796
795797
The output is designed to be input to format_table. The link name
796798
needs to be set up so that :any:`link_name` makes a link to the
797799
actual API docs for this object.
798800
"""
799-
sig = self.get_sig(obj)
800801
display_name = obj.name
801802
prefix = "**async** " if getattr(obj, "is_async", False) else ""
802803
qualifier = "any"
803-
summary = self.extract_summary(render_description(obj.description))
804804
link_name = pkgname + "." + display_name
805-
return (prefix, qualifier, display_name, sig, summary, link_name)
805+
main = f"{prefix}:{qualifier}:`{display_name} <{link_name}>`"
806+
if slink := obj.block_tags.get("summaryLink"):
807+
main = render_description(slink[0])
808+
sig = self.get_sig(obj)
809+
summary = self.extract_summary(render_description(obj.description))
810+
return (main, sig, summary)
806811

807812
def get_summary_table(
808813
self, pkgname: str, group: Iterable[TopLevel]
809-
) -> list[tuple[str, str, str, str, str, str]]:
814+
) -> list[tuple[str, str, str]]:
810815
"""Get the data for a summary tget_summary_tableable. Return value
811816
is set up to be an argument of format_table.
812817
"""
@@ -818,9 +823,7 @@ def get_summary_table(
818823
# We have to change the value of one string: qualifier = 'obj ==>
819824
# qualifier = 'any'
820825
# https://github.com/sphinx-doc/sphinx/blob/6.0.x/sphinx/ext/autosummary/__init__.py#L375
821-
def format_table(
822-
self, items: list[tuple[str, str, str, str, str, str]]
823-
) -> list[Node]:
826+
def format_table(self, items: list[tuple[str, str, str]]) -> list[Node]:
824827
"""Generate a proper list of table nodes for autosummary:: directive.
825828
826829
*items* is a list produced by :meth:`get_items`.
@@ -857,16 +860,13 @@ def append_row(column_texts: list[tuple[str, str]]) -> None:
857860
row.append(entry)
858861
body.append(row)
859862

860-
for prefix, qualifier, name, sig, summary, real_name in items:
863+
for name, sig, summary in items:
861864
# The body of this loop is changed from copied code.
862-
sig = rst.escape(sig)
863-
if sig:
864-
sig = f"**{sig}**"
865865
if "nosignatures" not in self._options:
866-
col1 = rf"{prefix}:{qualifier}:`{name} <{real_name}>`\ {sig}"
867-
else:
868-
col1 = f"{prefix}:{qualifier}:`{name} <{real_name}>`"
869-
col2 = summary
870-
append_row([(col1, "name"), (col2, "summary")])
866+
sig = rst.escape(sig)
867+
if sig:
868+
sig = f"**{sig}**"
869+
name = rf"{name}\ {sig}"
870+
append_row([(name, "name"), (summary, "summary")])
871871

872872
return [table_spec, table]

tests/test_build_ts/source/module.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,20 @@ export let interfaceInstance: I = {};
6363
*/
6464
export type TestTypeAlias<T extends A> = { a: T };
6565
export type TestTypeAlias2 = { a: number };
66+
/**
67+
* Omit from automodule and send summary link somewhere else
68+
* @omitFromAutoModule
69+
* @summaryLink :js:typealias:`TestTypeAlias3 <module.TestTypeAlias>`
70+
*/
71+
export type TestTypeAlias3 = { a: number };
6672

6773
export let t: TestTypeAlias<A>;
6874
export let t2: TestTypeAlias2;
6975

7076
/**
7177
* A function with a type parameter!
7278
*
73-
* We'll refer to ourselves: :js:func:`functionWithTypeParam`
79+
* We'll refer to ourselves: :js:func:`~module.functionWithTypeParam`
7480
*
7581
* @typeParam T The type parameter
7682
* @typeParam S Another type param

tests/test_build_ts/test_build_ts.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -490,12 +490,20 @@ def test_autosummary(self):
490490
classes = soup.find(class_="classes")
491491
assert classes.find(class_="summary").get_text() == "This is a summary."
492492

493-
classes = soup.find(class_="interfaces")
493+
interfaces = soup.find(class_="interfaces")
494494
assert (
495-
classes.find(class_="summary").get_text()
495+
interfaces.find(class_="summary").get_text()
496496
== "Documentation for the interface I"
497497
)
498498

499-
classes = soup.find(class_="type_aliases")
500-
assert classes
501-
assert classes.find(class_="summary").get_text() == "A super special type alias"
499+
type_aliases = soup.find(class_="type_aliases")
500+
assert type_aliases
501+
assert (
502+
type_aliases.find(class_="summary").get_text()
503+
== "A super special type alias"
504+
)
505+
rows = list(type_aliases.find_all("tr"))
506+
assert len(rows) == 3
507+
href = rows[2].find("a")
508+
assert href.get_text() == "TestTypeAlias3"
509+
assert href["href"] == "automodule.html#module.TestTypeAlias"

tests/test_renderers.py

Lines changed: 104 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
Exc,
1313
Function,
1414
Interface,
15+
Module,
1516
Param,
1617
Return,
1718
TypeAlias,
@@ -22,6 +23,7 @@
2223
from sphinx_js.renderers import (
2324
AutoAttributeRenderer,
2425
AutoFunctionRenderer,
26+
AutoModuleRenderer,
2527
render_description,
2628
)
2729

@@ -68,42 +70,47 @@ def ts_xref_formatter(config, xref):
6870
return xref.name
6971

7072

71-
@pytest.fixture()
72-
def function_renderer():
73-
class _config:
74-
pass
75-
73+
def make_renderer(cls):
7674
class _app:
77-
config = _config
78-
79-
def lookup_object(self, partial_path: list[str]):
80-
return self.objects[partial_path[-1]]
75+
class config:
76+
ts_type_xref_formatter = ts_xref_formatter
8177

82-
renderer = AutoFunctionRenderer.__new__(AutoFunctionRenderer)
78+
renderer = cls.__new__(cls)
8379
renderer._app = _app
8480
renderer._explicit_formal_params = None
8581
renderer._content = []
8682
renderer._set_type_xref_formatter(ts_xref_formatter)
8783
renderer._add_span = False
84+
return renderer
85+
86+
87+
@pytest.fixture()
88+
def function_renderer():
89+
def lookup_object(self, partial_path: list[str]):
90+
return self.objects[partial_path[-1]]
91+
92+
renderer = make_renderer(AutoFunctionRenderer)
8893
renderer.lookup_object = lookup_object.__get__(renderer)
8994
renderer.objects = {}
9095
return renderer
9196

9297

9398
@pytest.fixture()
9499
def attribute_renderer():
95-
class _config:
96-
pass
100+
return make_renderer(AutoAttributeRenderer)
97101

98-
class _app:
99-
config = _config
100102

101-
renderer = AutoAttributeRenderer.__new__(AutoAttributeRenderer)
102-
renderer._app = _app
103-
renderer._explicit_formal_params = None
104-
renderer._content = []
105-
renderer._set_type_xref_formatter(ts_xref_formatter)
106-
renderer._add_span = False
103+
@pytest.fixture()
104+
def auto_module_renderer():
105+
renderer = make_renderer(AutoModuleRenderer)
106+
107+
class directive:
108+
class state:
109+
class document:
110+
class settings:
111+
pass
112+
113+
renderer._directive = directive
107114
return renderer
108115

109116

@@ -146,6 +153,18 @@ def type_alias_render(partial_path=None, use_short_name=False, **args):
146153
return type_alias_render
147154

148155

156+
@pytest.fixture()
157+
def auto_module_render(auto_module_renderer) -> Any:
158+
def auto_module_render(partial_path=None, use_short_name=False, **args):
159+
if not partial_path:
160+
partial_path = ["blah"]
161+
return auto_module_renderer.rst(
162+
partial_path, make_module(**args), use_short_name
163+
)
164+
165+
return auto_module_render
166+
167+
149168
top_level_dict = dict(
150169
name="",
151170
path=[],
@@ -187,6 +206,17 @@ def type_alias_render(partial_path=None, use_short_name=False, **args):
187206
)
188207
attribute_dict = top_level_dict | member_dict | dict(type="")
189208
type_alias_dict = top_level_dict | dict(type="", type_params=[])
209+
module_dict = dict(
210+
filename="",
211+
deppath=None,
212+
path=[],
213+
line=0,
214+
attributes=[],
215+
functions=[],
216+
classes=[],
217+
interfaces=[],
218+
type_aliases=[],
219+
)
190220

191221

192222
def make_class(**args):
@@ -209,6 +239,10 @@ def make_type_alias(**args):
209239
return TypeAlias(**(type_alias_dict | args))
210240

211241

242+
def make_module(**args):
243+
return Module(**(module_dict | args))
244+
245+
212246
DEFAULT_RESULT = ".. js:function:: blah()\n"
213247

214248

@@ -562,3 +596,53 @@ def test_type_alias(type_alias_render):
562596
:typeparam T: ABC (extends **number**)
563597
"""
564598
)
599+
600+
601+
def test_auto_module_render(auto_module_render):
602+
assert auto_module_render() == ".. js:module:: blah"
603+
assert auto_module_render(
604+
functions=[
605+
make_function(
606+
name="f",
607+
description="this is a description",
608+
params=[Param("a", description="a description")],
609+
),
610+
make_function(name="g"),
611+
],
612+
attributes=[make_attribute(name="x", type="any"), make_attribute(name="y")],
613+
type_aliases=[
614+
make_type_alias(name="S"),
615+
make_type_alias(name="T"),
616+
# Check that we omit stuff marked with @omitFromAutoModule
617+
make_type_alias(name="U", modifier_tags=["@omitFromAutoModule"]),
618+
],
619+
) == dedent(
620+
"""\
621+
.. js:module:: blah
622+
623+
.. js:typealias:: S
624+
625+
626+
.. js:typealias:: T
627+
628+
629+
.. js:attribute:: x
630+
631+
.. rst-class:: js attribute type
632+
633+
type: **any**
634+
635+
636+
.. js:attribute:: y
637+
638+
639+
.. js:function:: f(a)
640+
641+
this is a description
642+
643+
:param a: a description
644+
645+
646+
.. js:function:: g()
647+
"""
648+
)

tests/test_typedoc_analysis/source/types.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,3 +246,11 @@ export type MappedType3 = { readonly [property in keys]-?: number };
246246
export type TemplateLiteral = `${number}: ${string}`;
247247

248248
export type OptionalType = [number?];
249+
250+
/**
251+
* @hidetype
252+
* @omitFromAutoModule
253+
* @destructure a.b
254+
* @summaryLink :role:`target`
255+
*/
256+
export type CustomTags = {};

tests/test_typedoc_analysis/test_typedoc_analysis.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -742,3 +742,13 @@ def test_template_literal(self):
742742
obj = self.analyzer.get_object(["TemplateLiteral"])
743743
assert isinstance(obj, TypeAlias)
744744
assert join_type(obj.type) == "`${number}: ${string}`"
745+
746+
def test_custom_tags(self):
747+
obj = self.analyzer.get_object(["CustomTags"])
748+
assert isinstance(obj, TypeAlias)
749+
assert "@hidetype" in obj.modifier_tags
750+
assert "@omitFromAutoModule" in obj.modifier_tags
751+
assert [join_description(d) for d in obj.block_tags["summaryLink"]] == [
752+
":role:`target`"
753+
]
754+
assert [join_description(d) for d in obj.block_tags["destructure"]] == ["a.b"]

0 commit comments

Comments
 (0)