diff --git a/src/griffe/mixins.py b/src/griffe/mixins.py index f1e52662..f52b4f0f 100644 --- a/src/griffe/mixins.py +++ b/src/griffe/mixins.py @@ -367,8 +367,8 @@ def is_public(self) -> bool: # TODO: Return regular True/False values in next version. if self.public is not None: # type: ignore[attr-defined] return _True if self.public else _False # type: ignore[return-value,attr-defined] - if self.is_wildcard_exposed: - return _True # type: ignore[return-value] + if self.parent and self.parent.is_module and bool(self.parent.exports): # type: ignore[attr-defined] + return _True if self.name in self.parent.exports else _False # type: ignore[attr-defined,return-value] if self.has_private_name: return _False # type: ignore[return-value] # The following condition effectively filters out imported objects. @@ -389,6 +389,9 @@ def __init__(self, value: bool) -> None: # noqa: FBT001 def __bool__(self) -> bool: return self.value + def __repr__(self) -> str: + return repr(self.value) + def __call__(self, *args: Any, **kwargs: Any) -> bool: # noqa: ARG002 warnings.warn( "This method is now a property and should be accessed as such (without parentheses).", diff --git a/tests/test_diff.py b/tests/test_diff.py index c1663a31..ef51846b 100644 --- a/tests/test_diff.py +++ b/tests/test_diff.py @@ -181,7 +181,7 @@ def test_diff_griffe(old_code: str, new_code: str, expected_breakages: list[Brea for breakage, expected_kind in zip(breaking, expected_breakages): assert breakage.kind is expected_kind # check with aliases - import_a = "from ._mod_a import a" + import_a = "from ._mod_a import a\n__all__ = ['a']" old_modules = {"__init__.py": import_a, "_mod_a.py": old_code} new_modules = {"__init__.py": new_code and import_a, "_mod_a.py": new_code} with temporary_visited_package("package_old", old_modules) as old_package: # noqa: SIM117 diff --git a/tests/test_public_api.py b/tests/test_public_api.py new file mode 100644 index 00000000..cbdbbf93 --- /dev/null +++ b/tests/test_public_api.py @@ -0,0 +1,10 @@ +"""Tests for public API handling.""" + +from griffe.tests import temporary_visited_module + + +def test_not_detecting_imported_objects_as_public() -> None: + """Imported objects not listed in `__all__` must not be considered public.""" + with temporary_visited_module("from abc import ABC\ndef func(): ...") as module: + assert not module["ABC"].is_public + assert module["func"].is_public # control case