Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/apify/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def is_running_in_ipython() -> bool:
]


def docs_group(group_name: GroupName) -> Callable: # noqa: ARG001
def docs_group(group_name: GroupName) -> Callable[[T], T]: # noqa: ARG001
"""Mark a symbol for rendering and grouping in documentation.

This decorator is used solely for documentation purposes and does not modify the behavior
Expand All @@ -98,13 +98,13 @@ def docs_group(group_name: GroupName) -> Callable: # noqa: ARG001
The original callable without modification.
"""

def wrapper(func: Callable) -> Callable:
def wrapper(func: T) -> T:
return func

return wrapper


def docs_name(symbol_name: str) -> Callable: # noqa: ARG001
def docs_name(symbol_name: str) -> Callable[[T], T]: # noqa: ARG001
"""Rename a symbol for documentation rendering.

This decorator modifies only the displayed name of the symbol in the generated documentation
Expand All @@ -117,7 +117,7 @@ def docs_name(symbol_name: str) -> Callable: # noqa: ARG001
The original callable without modification.
"""

def wrapper(func: Callable) -> Callable:
def wrapper(func: T) -> T:
return func

return wrapper
Expand Down
30 changes: 29 additions & 1 deletion tests/unit/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
from __future__ import annotations

from enum import Enum
from typing import TYPE_CHECKING
from unittest.mock import patch

import pytest

from apify._utils import get_system_info, is_running_in_ipython, maybe_extract_enum_member_value
from apify._utils import docs_group, docs_name, get_system_info, is_running_in_ipython, maybe_extract_enum_member_value


def test_ipython_detection_when_active() -> None:
Expand Down Expand Up @@ -54,3 +55,30 @@ def test_maybe_extract_enum_member_value_with_non_enum() -> None:
assert maybe_extract_enum_member_value('hello') == 'hello'
assert maybe_extract_enum_member_value(42) == 42
assert maybe_extract_enum_member_value(None) is None


if TYPE_CHECKING:
# Regression guard: if `docs_group`/`docs_name` stop being identity-typed (`Callable[[T], T]`),
# the decorated classes degrade to `Unknown`, the accesses below stop erroring, and the
# then-unused suppressions fail the type check (`unused-ignore-comment = "error"`).

@docs_group('Actor')
class _DocsGroupDecorated:
pass

@docs_name('Renamed')
class _DocsNameDecorated:
pass

_ = _DocsGroupDecorated.nonexistent # ty: ignore[unresolved-attribute]
_ = _DocsNameDecorated.nonexistent # ty: ignore[unresolved-attribute]


def test_docs_decorators_return_original_object() -> None:
"""Test that `docs_group` and `docs_name` return the decorated object unchanged."""

class Sample:
pass

assert docs_group('Actor')(Sample) is Sample
assert docs_name('Renamed')(Sample) is Sample
Loading