question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Mypy complains with type-hints

See original GitHub issue

First of all, this library is really, really handy. Logging is so much easier with it. Thanks! Regarding the issue:

I’m working on a project that enforces type-hints with Mypy, and I’m intercepting some logging activity from another process, thus using the InterceptHandler documented on the README file:

# main.py

from loguru import logger

class InterceptHandler(logging.Handler):
    def emit(self, record) -> None:
        # Get corresponding Loguru level if it exists
        try:
            level = logger.level(record.levelname).name
        except ValueError:
            level = record.levelno

        # Find caller from where originated the logged message
        frame, depth = logging.currentframe(), 2
        while frame.f_code.co_filename == logging.__file__:
            frame = frame.f_back
            depth += 1

        logger.opt(depth=depth, exception=record.exc_info).log(level, record.getMessage())


logging.basicConfig(handlers=[InterceptHandler()], level=0)

logger.remove()
logger.add(sys.stderr, format="<green>{time:HH:mm:ss.SSS}</green> | <level>{message}</level>")

logger.info("Hi!")

This is working perfectly, but Mypy is complaining about the missing type-hints:

main.py:4: error: Function is missing a type annotation
main.py:14: error: Incompatible types in assignment (expression has type "Optional[FrameType]", variable has type "FrameType")
Found 2 errors in 1 file (checked 1 source file)

The first one is noticing that the record argument is not typed and the second one is noticing the type of the variable is changing.

Is there a recommended way of solving them?

I tried to import Record from loguru to type-hint the record argument but got several errors after:

main.py:4: error: Argument 1 of "emit" is incompatible with supertype "Handler"; supertype defines the argument type as "LogRecord"
main.py:4: note: This violates the Liskov substitution principle
main.py:4: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides
main.py:7: error: "Record" has no attribute "levelname"
main.py:9: error: "Record" has no attribute "levelno"
main.py:17: error: "Record" has no attribute "exc_info"
main.py:17: error: "Record" has no attribute "getMessage"
Found 5 errors in 1 file (checked 1 source file)

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
Delgancommented, May 25, 2021

Hey @rafaellehmkuhl, glad you like Loguru, thanks!

About your issue: the InterceptHander inherits from logging.Handler. The emit() method is the one from the standard logging module, just as the record is. The record is not from a Loguru type, it’s a logging.LogRecord object. I guess Mypy should stop complaining if you use this type hint instead. 👍

0reactions
rafaellehmkuhlcommented, Jun 8, 2021

@patrickelectric came with this solution:

from logging import LogRecord
from types import FrameType
from typing import Any, List, Optional, Union

class InterceptHandler(logging.Handler):
    def emit(self, record: LogRecord) -> None:
        # Get corresponding Loguru level if it exists
        level: Union[int, str]
        try:
            level = logger.level(record.levelname).name
        except ValueError:
            level = record.levelno

        # Find caller from where originated the logged message
        frame: Optional[FrameType]
        frame, depth = logging.currentframe(), 2
        while frame and frame.f_code.co_filename == logging.__file__:
            frame = frame.f_back
            depth += 1

        logger.opt(depth=depth, exception=record.exc_info).log(level, record.getMessage())

I think its pretty much what is needed. Tested here and it works fine.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Common issues and solutions - mypy 0.991 documentation
This section has examples of cases when you need to update your code to use static typing, and ideas for working around issues...
Read more >
Mypy errors with variable reuse with different types · Issue #1174
An optional flag that causes mypy to complain about questionable ... Initial type hints for function_wrapper pytorch/pytorch#4947.
Read more >
Mypy complains about incompatible type when variable type ...
My understanding is that str is a Hashable , but since dict is a mutable data type you must be passing the exact...
Read more >
PEP 484 – Type Hints - Python Enhancement Proposals
The proposal is strongly inspired by mypy. For example, the type “sequence of integers” can be written as Sequence[int] . The square brackets...
Read more >
Mypy Documentation - Read the Docs
Adding type hints for mypy does not interfere with the way your program ... Mypy complains if it can't find a stub (or...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found