Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changes to behavior of runtime_checkable() in py 3.12 #560

Closed
peterschutt opened this issue Oct 16, 2023 · 6 comments · Fixed by #561
Closed

Changes to behavior of runtime_checkable() in py 3.12 #560

peterschutt opened this issue Oct 16, 2023 · 6 comments · Fixed by #561

Comments

@peterschutt
Copy link
Contributor

I came across this - not sure if you'd consider it a bug but hopefully worth bringing to your attention.

We had some code that tries to handle multiple logging libraries which was essentially doing this:

from structlog import get_logger
from structlog.types import BindableLogger


logger = get_logger()

if isinstance(logger, BindableLogger):
    ...

The isinstance() check is True for python versions <3.12, and False on 3.12.

This is due to a change in the way that typing.runtime_checkable() works:

Changed in version 3.12: The internal implementation of isinstance() checks against runtime-checkable protocols now uses inspect.getattr_static() to look up attributes (previously, hasattr() was used). As a result, some objects which used to be considered instances of a runtime-checkable protocol may no longer be considered instances of that protocol on Python 3.12+, and vice versa. Most users are unlikely to be affected by this change.

inspect.getattr_static() doesn't call __getattr__, which means it doesn't see the proxied attributes of the underying bound logger.

I think the difference might be that the _context attribute doesn't exist on the proxy.

@runtime_checkable
class BindableLogger(Protocol):
"""
**Protocol**: Methods shared among all bound loggers and that are relied on
by *structlog*.
.. versionadded:: 20.2.0
"""
_context: Context

@hynek
Copy link
Owner

hynek commented Oct 16, 2023

The vanilla get_logger returns an Any, I suspect that's more likely to be the issue? See also https://www.structlog.org/en/stable/typing.html

@peterschutt
Copy link
Contributor Author

This isn't a static typing issue. It is a runtime issue on python 3.12 where the BindableLogger protocol (which is marked @runtime_checkable) returns False on an isinstance() check against an instance of BoundLoggerLazyProxy.

@hynek
Copy link
Owner

hynek commented Oct 16, 2023

Ah yes sorry ugh this is ugly I'll see what we can do.

@peterschutt
Copy link
Contributor Author

Thanks @hynek!

@hynek
Copy link
Owner

hynek commented Oct 16, 2023

This should be fixed by #561 – please lmk if you run into other similar issues!

Is this issue something that blocks you?

@peterschutt
Copy link
Contributor Author

please lmk if you run into other similar issues!

Will do!

Is this issue something that blocks you?

No, we swapped out the isinstance() with an inspection of the repr to the same effect. Once you cut next release I'll change it back but we are on our way for now :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants