'MyPy - how do you actually use typeshed stubs in annotations?

Note: this answer on SO does NOT answer my question. It merely restates what I already have read.

How is this supposed to work? Everything I read says typeshed is bundled with MyPy and contains stubs for third party libraries. I have MyPy installed and running in a virtualenv and I'm trying to use it to type Flask code but I'm just not getting it.

I have a background in TypeScript, and I was looking for something similar but I don't understand how we are supposed to use stubs with MyPy. For example, I have this function:

def create_app(config_name="default"):
    app: Flask = Flask(__name__)
    app.config.from_object(Configuration)
    CORS(app)
    register_extensions(app)
    register_blueprints(app)

    @app.route("/health")
    def health_check():
        return json.dumps({"status": "up"})

    return app

Pretty standard for Flask, but with strict disallow any settings this becomes an unsalvageable mess. What is the type of app? I know that typeshed has stubs for flask but I cannot figure out how to actually utilize those stubs. The typeshed docs say:

If you're just using mypy (or pytype or PyCharm), as opposed to developing it, you don't need to interact with the typeshed repo at all: a copy of typeshed is bundled with mypy.

So I'm assuming I do not need to import the types, the docs don't make any mention of importing them anyway.

For example, there is a stub called app.pyi but if I annotate the function like this:

def create_app(config_name="default") -> app:

I get the error name app is not defined. If I import it:

from typeshed import app

I get the error Return type becomes any due to an unfollowed import which, as far as I can tell, means there is no such module typeshed or it has no member called app.

So how do I actually get access to these typeshed stubs? My last resort is to simply clone the typeshed repo and point mypy to it as a custom typeshed dir, but I'd really like to do things the proper way.



Solution 1:[1]

Although for this specific instance you can just use imports from the package itself, there are cases where you do need to import types from typeshed for annotations (in my case it was trying to use the wsgi type StartResponse.

These are importable, but only inside an if TYPE_CHECKING: block like so:

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from _typeshed.wsgi import StartResponse

def application(environ: Dict, start_response: "StartResponse"):
    # etc

This only works (and should only be necessary) for types found in the mypy/typeshed/stdlib/_typeshed directory.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 ptd