Skip to content

Ignore typing errors in individual blocks #6948

Open

Description

@exhuma

It is already possible to silence errors using # type: ignore on individual lines, and - since #626) also for a whole file.

Additionally it would be nice to ignore errors on individual blocks. Especially on a class/function level when abstracting away an untyped library. For example:

class MyAbstraction:

    def __init__(self, url: str) -> None:
        self.hostname = url.host  # <-- I want this to be caught by the type-checker

    def some_call(self) -> int:
        # type: ignore
        result = api.untyped_call()
        return result

    def another_large_call(self) -> int:
        # type: ignore
        result_1 = api.untyped_call_1()
        result_2 = api.untyped_call_2()
        result = result_1 + result_2
        return result

When running mypy in "strict" mode the code will be littered with messages like Call to an untyped function ... in a typed context. Currently the only options are:

  • Add # type: ignore on each line causing errors by the external library
    • Disadvantage: Cumbersome (many type-comments needed)
    • Advantage: Only the problematic calls are silenced
  • Add # type: ignore to the file
    • Disadvantage: Typing errors unrelated to the external library become invisible
    • Advantage: Only one line to add

The second option is best used if a module contains only calls to the external library. For new projects this is doable, but older/larger code-bases often need some refactoring for this. And this can be error-prone and seems risky to do only for type-hinting.

Having the option to disable errors on either a class-level or block-level would add a lot of flexibility.

Pinned by ilevkivskyi

Activity

  1. brandtbucher commented on Jun 7, 2019

    @brandtbucher
    Member

    See #6830 (the PR that closed #626). It’s not currently possible to get the line number of the colon that immediately precedes an indented block from the AST alone... at least not without resorting to error-prone guessing. We can't reliably tell the difference between this:

    def f() -> (
        None
    ):  # type: ignore
        ...

    And this:

    def f() -> (
        None):
        # type: ignore
        ...

    So I think block-scoped ignores using a # type: ignore comment on the first line are not very likely. Perhaps there is another way, like @no_type_check, but with preserved annotations in the function signature.

    I wanted this also, but I don't think it's worth changing mypy's source parsing 🙁.

  2. JelleZijlstra commented on Jun 7, 2019

    @JelleZijlstra
    Member

    You can use the @typing.no_type_check decorator for this.

  3. rwarren commented on May 7, 2020

    @rwarren

    @typing.no_type_check works perfectly (thanks @JelleZijlstra).

    Why is this issue still open?

  4. JelleZijlstra commented on May 7, 2020

    @JelleZijlstra
    Member

    The original issue asked for something slightly different (block-scoped type-ignore), which is a bit different from @no_type_check, which is always function-scoped.

    I'm not sure block-scoped type-ignores are all that necessary, but it's a reasonable request.

  5. leonardoramirezr commented on Jul 6, 2020

    @leonardoramirezr

    Try with:

    from typing import Any, cast
    
    import api as untype_api # It is import to use a different name to untyped module
    api = cast(Any, untype_api)
    
    class MyAbstraction:
         def some_call(self) -> int:
            result = api.untyped_call() # this shouldn't show type warnings.
            return result
  6. jentyk commented on Mar 3, 2021

    @jentyk

    It would be nice if @typing.no_type_check would be also a class decorator

  7. kamilturek commented on Mar 3, 2021

    @kamilturek
    Contributor

    It would be nice if @typing.no_type_check would be also a class decorator

    @jentyk According to the docs it should work as well as a class decorator, but it isn't apparently true.
    https://docs.python.org/3/library/typing.html#typing.no_type_check

    Mentioned here #607.

  8. analog-cbarber commented on Aug 25, 2021

    @analog-cbarber
    Contributor

    pylint supports this type of pragma, so it is clearly theoretically possible.

  9. analog-cbarber commented on Aug 25, 2021

    @analog-cbarber
    Contributor

    Also no_type_check only takes a single argument for the decorated object. There is no way to limit the ignore to one particular class of error. For example. there is no way to apply

    # type: ignore[misc]
    

    to a function. You have to ignore everything or write a separate comment for each instance. And if you add a new decorator for this purpose, then using it would mean adding a runtime dependency to mypy just for that.

  10. filips123 commented on Jul 21, 2022

    @filips123

    What about introducing two comments to disable and enable specific rule(s) between them? For example:

    class MyAbstraction:
        def __init__(self, url: str) -> None:
            self.hostname = url.host
    
        def large_call(self) -> int:
            # type: off[no-untyped-call]
            result_1 = api.untyped_call_1()
            result_2 = api.untyped_call_2()
            result_3 = api.untyped_call_2()
            result_4 = api.untyped_call_2()
            result = result_1 + result_2 + result_3 + result_4
            return result
            # type: on[no-untyped-call]

    This is also similar to formatters such as Black which uses # fmt: off and # fmt: on comments. It's still not disabling specific rule for a whole block with one comment, but two comments (at the start and the end) for a function are still better than having to put a comment on every line with typing error, especially on larger functions.

  11. etandel commented on Sep 1, 2022

    @etandel

    What about having something like typing.no_type_check() be usable as a context manager?
    For instance:

    import typing
    
    
    class MyAbstraction:
        ...
    
        def another_large_call(self) -> int:
    		x : int = f()  # This is checked
    
            with typing.no_type_check: # no lines inside this context are checked
    	        result_1 = api.untyped_call_1()
    	        result_2 = api.untyped_call_2()
    	        result = result_1 + result_2
    
    		y: str = g() # this is also checked
            return result
  12. exhuma commented on Sep 15, 2022

    @exhuma
    Author

    I don't like the context-manager idea. Type-hints are just hints with no behaviour during runtime. They are PEP-3107 "annotations". The with block is a runtime construct. And mixing this feels wrong. The annotations can be extracted by static analysis tools but should have no impact on the runtime. When we add a "with" block they will trigger runtime behaviour. Even if typing.no_type_check is part of the standard library it could still cause unexpected side-effects during runtime.

    I initially thought about a with block as well, as it just "looks right" when looking at the code. But I dismissed it because it mixes runtime with static-analysis.

    This is a "gut-feeling" and may be subjective as I have no concrete proof that this can cause problems. If there are any, I'd be happy to learn.

  13. anentropic commented on May 19, 2023

    @anentropic

    Another case...

    I have code like this:

    class TurnLogAdmin(ModelView, model=TurnLog):
        column_list = [
            TurnLog.id,
            TurnLog.turn_id,
            TurnLog.timestamp,
            TurnLog.key,
        ]  # type: ignore

    Due to issues between SQLModel (which mashes SQL Alchemy and Pydantic models together, resulting in difficult typing situation) and sqladmin (whose typings expect SQL Alchemy model fields here)... mypy generates a type error for each element of the list:

    src/server/app.py:60: error: List item 0 has incompatible type "Optional[int]"; expected "Union[str, InstrumentedAttribute]"  [list-item]
    src/server/app.py:61: error: List item 1 has incompatible type "int"; expected "Union[str, InstrumentedAttribute]"  [list-item]
    src/server/app.py:62: error: List item 2 has incompatible type "datetime"; expected "Union[str, InstrumentedAttribute]"  [list-item]
    

    I was hoping the # type: ignore on the last line would cover the whole list literal, but it has no effect. Since there is no block-ignore syntax it seems like I need an ignore comment for each line individually.

    FWIW #6648 and #1032 seem to intend that the ignore comment would cover the whole expression

    but perhaps multi-line list literal is a different construct? (I'm not sure exactly what does and doesn't count as an 'expression' ... https://docs.python.org/3/reference/expressions.html seems to include list literals though)

  14. ilevkivskyi commented on Aug 13, 2023

    @ilevkivskyi
    Member

    For those who wants this for the --disallow-untyped-calls problems: #15845 added a new flag to not show this error for calls to functions/methods from specific packages/modules/classes (will be available in next mypy release).

  15. MattSom commented on Jan 17, 2024

    @MattSom

    A solution for blocks or class annotation would come in handy. Mypy can't handle things going on inside django ORM constraint definitions.

  16. GhostOps77 commented on Apr 14, 2024

    @GhostOps77

    It would be great if there's start and stop comments to pause mypy's type check, like

    # mypy: off
    ...
    # mypy: on
    

    cuz i do need to exclude only a block of code (i.e., an if block)

  17. vtgn commented on Nov 17, 2024

    @vtgn

    So what's new about this feature? I'm disappointed too that this standard feature still doesn't exist.

  18. belliriccardo commented on Apr 2, 2025

    @belliriccardo

    Hi! Are there any news about this development? I've seen it requested for Pylance as well ( microsoft/pylance-release#2512 ; I've also pinged that issue ), maybe there is a common ground on how to define the type checking start/end? So that the two different type checkers don't end up requiring different syntax

  19. laoshaw commented on Sep 20, 2025

    @laoshaw

    use '#type: off' and '#type: on' will be better so it works for both mypy and pyright/pylance.

  20. bersbersbers commented on Sep 20, 2025

    @bersbersbers

    use '#type: off' and '#type: on' will be better so it works for both mypy and pyright/pylance.

    That depends. If you just work around an issue on one of the type checkers you may not want to disable the other one.

  21. mithom commented on Mar 3, 2026

    @mithom

    i assume this issue is just silently being ignored right now? 😢

  22. exhuma commented on Mar 3, 2026

    @exhuma
    Author

    I remain hopeful 😅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions