Ahko26
Ahko26

Reputation: 51

Specifying the return type when the output comes from a library with no type hints / stubs

When importing a library with missing stubs (no type hints), mypy flags it as a module with no stubs. An easy fix is to add # type: ignore after the import, however, all return types become Any. Now if I define a function that returns something coming out of this library, it seems that I would need to define the return type as Any as well.

This seems very generic and I would like to know if there's a more explicit way of defining the return type instead of having Any every time a library doesn't have stubs.

Here's a very simple example using Plotly:

import plotly.express as px # type: ignore
from plotly import graph_objects as go
from pandas import DataFrame

def plot_df(df: DataFrame) -> go.Figure:
    return px.bar(data_frame=df)

which triggers the following mypy error: "error: Return type becomes "Any" due to an unfollowed import [no-any-unimported]". Replacing go.Figure with Any fixes the problem but, again, I'd like to know if there's a better way of doing this.

I am using Python 3.9.16 and here's the configuration of mypy in my pyproject.toml file:

[tool.mypy]
disallow_untyped_defs = true
disallow_any_unimported = true
no_implicit_optional = true
check_untyped_defs = true
warn_return_any = true
warn_unused_ignores = true
show_error_codes = true

Thanks a lot for your help.

Upvotes: 2

Views: 2072

Answers (1)

jsbueno
jsbueno

Reputation: 110516

You can use typing.Cast on the returned values of unmarked functions: that will tell the type of the value returned by the un-instrumented code as it reach yours, and the tooling will be able to follow from there.

One thing to always have in mind is that typing has NO run time effect in Python, the static typing tools essentially "see the code structure" in parallel to the execution - and typing.cast itself has no runtime effect (although it is not "optimized out" of running code: a function call is made, even though on Python 3.11 and later that should be optmized enough)

from typing import cast

...

def plot_df(df: DataFrame) -> go.Figure:
    return cast(go.Figure, px.bar(data_frame=df))

Upvotes: -1

Related Questions