diff --git a/pyproject.toml b/pyproject.toml index 71cb6f4..e2c3f2b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,6 +41,7 @@ ruff = "^0.5.2" pytest = "^7.4.2" pytest-cov = "^4.1.0" pytest-mock = "^3.11.1" +pydantic = "^2.9" [tool.coverage.paths] source = ["src"] diff --git a/src/pykka/_introspection.py b/src/pykka/_introspection.py index 5bc6775..c7c1a78 100644 --- a/src/pykka/_introspection.py +++ b/src/pykka/_introspection.py @@ -34,7 +34,9 @@ def introspect_attrs( attr = get_attr_from_parent(root, attr_path) - if attr == proxy: + # Keep `proxy` first to use it's `__eq__` method instead of `attr`'s + # unknown implementation. + if proxy == attr: logger.warning( f"{root} attribute {'.'.join(attr_path)!r} " f"is a proxy to itself. " diff --git a/tests/proxy/test_proxy.py b/tests/proxy/test_proxy.py index bd0bbc2..69844c9 100644 --- a/tests/proxy/test_proxy.py +++ b/tests/proxy/test_proxy.py @@ -2,6 +2,7 @@ from typing import TYPE_CHECKING +import pydantic import pytest import pykka @@ -18,10 +19,17 @@ class NestedObject: pass +class PydanticModel(pydantic.BaseModel): + foo: str = "bar" + + class ActorForProxying(Actor): a_nested_object = pykka.traversable(NestedObject()) a_class_attr = "class_attr" + # Include a pydantic model to test that it doesn't break introspection. + a_pydantic_model = PydanticModel() + def __init__(self) -> None: super().__init__() self.an_instance_attr = "an_instance_attr" @@ -108,6 +116,7 @@ def test_dir_on_proxy_lists_attributes_of_the_actor( assert "a_class_attr" in result assert "an_instance_attr" in result assert "a_method" in result + assert "a_pydantic_model" in result def test_dir_on_proxy_lists_private_attributes_of_the_proxy(