Skip to content

Commit 92e9751

Browse files
authored
Support Union type on its own (#570)
1 parent ddac8c8 commit 92e9751

File tree

3 files changed

+21
-12
lines changed

3 files changed

+21
-12
lines changed

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ repos:
2727
rev: "v0.14.0"
2828
hooks:
2929
- id: ruff-format
30-
- id: ruff
30+
- id: ruff-check
3131
args: ["--fix", "--unsafe-fixes", "--exit-non-zero-on-fix"]
3232
- repo: https://github.com/rbubley/mirrors-prettier
3333
rev: "v3.6.2" # Use the sha / tag you want to point at

src/sphinx_autodoc_typehints/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,8 @@ def format_annotation(annotation: Any, config: Config, *, short_literals: bool =
300300
return f"\\{' | '.join(f'``{arg!r}``' for arg in args)}"
301301
formatted_args = f"\\[{', '.join(f'``{arg!r}``' for arg in args)}]"
302302
elif is_bars_union:
303+
if not args:
304+
return f":py:{'class' if sys.version_info >= (3, 14) else 'data'}:`{prefix}typing.Union`"
303305
return " | ".join([format_annotation(arg, config, short_literals=short_literals) for arg in args])
304306

305307
if args and not formatted_args:

tests/test_sphinx_autodoc_typehints.py

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,10 @@ def test_parse_annotation(annotation: Any, module: str, class_name: str, args: t
244244
r":py:data:`~typing.Tuple`\ \[:py:class:`str`, :py:data:`...<Ellipsis>`]",
245245
id="Tuple-str-Ellipsis",
246246
),
247-
pytest.param(Union, "" if sys.version_info >= (3, 14) else ":py:data:`~typing.Union`", id="Union"),
247+
pytest.param(Union, f":py:{'class' if sys.version_info >= (3, 14) else 'data'}:`~typing.Union`", id="Union"),
248+
pytest.param(
249+
types.UnionType, f":py:{'class' if sys.version_info >= (3, 14) else 'data'}:`~typing.Union`", id="UnionType"
250+
),
248251
pytest.param(
249252
Union[str, bool],
250253
":py:class:`str` | :py:class:`bool`"
@@ -280,6 +283,12 @@ def test_parse_annotation(annotation: Any, module: str, class_name: str, args: t
280283
else r":py:data:`~typing.Optional`\ \[:py:class:`str`]",
281284
id="Optional-str-None",
282285
),
286+
pytest.param(
287+
type[T] | types.UnionType,
288+
":py:class:`type`\\ \\[:py:class:`~typing.TypeVar`\\ \\(``T``)] | "
289+
f":py:{'class' if sys.version_info >= (3, 14) else 'data'}:`~typing.Union`",
290+
id="typevar union bar uniontype",
291+
),
283292
pytest.param(
284293
Optional[str | bool],
285294
":py:class:`str` | :py:class:`bool` | :py:obj:`None`"
@@ -436,18 +445,16 @@ def test_format_annotation(inv: Inventory, annotation: Any, expected_result: str
436445
assert format_annotation(annotation, conf) == expected_result
437446

438447
# Test for the correct role (class vs data) using the official Sphinx inventory
439-
if any(modname in expected_result for modname in ("typing", "types")) and not (
440-
sys.version_info >= (3, 14) and isinstance(annotation, Union)
448+
if (
449+
result.count(":py:") == 1
450+
and ("typing" in result or "types" in result)
451+
and (match := re.match(r"^:py:(?P<role>class|data|func):`~(?P<name>[^`]+)`", result))
441452
):
442-
m = re.match(r"^:py:(?P<role>class|data|func):`~(?P<name>[^`]+)`", result)
443-
assert m, "No match"
444-
name = m.group("name")
453+
name = match.group("name")
445454
expected_role = next((o.role for o in inv.objects if o.name == name), None)
446-
if expected_role:
447-
if expected_role == "function":
448-
expected_role = "func"
449-
450-
assert m.group("role") == expected_role
455+
if expected_role and expected_role == "function":
456+
expected_role = "func"
457+
assert match.group("role") == expected_role
451458

452459

453460
@pytest.mark.parametrize(

0 commit comments

Comments
 (0)