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

logging.getLogger() infers wrong type when used in combination with logging.setLoggerClass() #1801

Closed
zmwangx opened this issue Dec 31, 2017 · 3 comments

Comments

@zmwangx
Copy link
Contributor

zmwangx commented Dec 31, 2017

Consider test.py:

import logging

class Logger(logging.Logger):
    pass

logging.setLoggerClass(Logger)
logger = logging.getLogger(__name__)  # type: Logger
$ mypy test.py
test.py:7: error: Incompatible types in assignment (expression has type "logging.Logger", variable has type "test.Logger")

The problem here is that logging.getLogger() actually returns a logger of the class set previously by logging.setLoggerClass(), but the stub is inflexible and just assumes logging.Logger.

I'm not sure how to fix this, or whether it's fixable with mypy's current feature set. I'd be happy to take this on if someone could point me in the right direction.

In the meantime, is there a better workaround than just # type: ignore the line?

@zmwangx
Copy link
Contributor Author

zmwangx commented Dec 31, 2017

Uh, I realized my workaround is wrong; using a # type: ignore only suppresses the error on that line, and mypy, not getting a type hint as in # type: Logger, moves on with the assumption that logger is logging.Logger, and declares any custom method as nonexistent:

import logging

class Logger(logging.Logger):
    def foo(self):
	pass

logging.setLoggerClass(Logger)
logger = logging.getLogger(__name__)  # type: ignore
logger.foo()
$ mypy test.py
test.py:9: error: "Logger" has no attribute "foo"

So I learned a new workaround — casting:

import logging
from typing import cast

class Logger(logging.Logger):
    def foo(self):
        pass

logging.setLoggerClass(Logger)
logger = cast(Logger, logging.getLogger(__name__))
logger.foo()
$ mypy test.py  # this time happy

This feels rather intrusive, but I can settle with this if there's no satisfactory fix.

@JelleZijlstra
Copy link
Member

This doesn't feel like something the type system can support in a straightforward manner. I think a cast is your best bet.

@JelleZijlstra
Copy link
Member

I don't think we should fix this in typeshed. The only fix I can see is to make getLogger return Any, but I feel like that sacrifices too much type safety in the common case for a rare use case.

Feel free to reopen if you think there is a tractable fix.

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

No branches or pull requests

2 participants