Skip to content

Version 3 adds breaking type annotations that do not comply with mypy #3226

@gothicVI

Description

@gothicVI
Contributor

With the release of dash 3.0 our CI/CD fails for stuff that used to work.
Here's a minimum working example:

from dash import Dash, dcc, html
from dash.dependencies import Input, Output
from typing import Callable

app = Dash(__name__)

def create_layout() -> html.Div:
    return html.Div([
        dcc.Input(id='input-text', type='text', value='', placeholder='Enter text'),
        html.Div(id='output-text')
    ])  

app.layout = create_layout

@app.callback(Output('output-text', 'children'), Input('input-text', 'value'))
def update_output(value: str) -> str:
    return f'You entered: {value}'

if __name__ == '__main__':
    app.run(debug=True, port=9000)

running mypy on this file results in:

$ mypy t.py --strict
t.py:1: error: Skipping analyzing "dash": module is installed, but missing library stubs or py.typed marker  [import-untyped]
t.py:2: error: Skipping analyzing "dash.dependencies": module is installed, but missing library stubs or py.typed marker  [import-untyped]
t.py:2: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports
t.py:15: error: Untyped decorator makes function "update_output" untyped  [misc]
Found 3 errors in 1 file (checked 1 source file)

which we used to solve by adding # type: ignore[misc] to every callback call and by adding

[[tool.mypy.overrides]]
module = [
  "dash.*",
  "dash_ag_grid",
  "dash_bootstrap_components.*",
  "plotly.*",
]
ignore_missing_imports = true

to our pyproject.toml.

However, when updating to version 3, we get:

$ mypy --strict t.py 
t.py:8: error: Returning Any from function declared to return "Div"  [no-any-return]
t.py:13: error: Property "layout" defined in "Dash" is read-only  [misc]
t.py:15: error: Call to untyped function "Input" in typed context  [no-untyped-call]
t.py:15: error: Call to untyped function "Output" in typed context  [no-untyped-call]
t.py:15: error: Call to untyped function "callback" in typed context  [no-untyped-call]
t.py:15: note: Error code "no-untyped-call" not covered by "type: ignore" comment
Found 5 errors in 1 file (checked 1 source file)

without changing anything else.

This can't be intended behavior, right? How to fix that?

community post: https://community.plotly.com/t/dash-3-0-fails-mypy/91308

Activity

T4rk1n

T4rk1n commented on Mar 18, 2025

@T4rk1n
Contributor

I only had trouble with mypy, the typing generation tests were originally designed with mypy but at some point it updated and couldn't find types anymore. There is a py.typed file in dash package.

I suggest switching over to pyright, that is what is used in vscode and 10x better imo.

gothicVI

gothicVI commented on Mar 18, 2025

@gothicVI
ContributorAuthor

I'll give that a look but we can not simply dump mypy from our code base.
This needs to be fixed not on a linter level because there is something wrong in the code.

E.g. looking at https://github.com/plotly/dash/blob/dev/dash/dependencies.py#L29 and following it is clear, that there are no type annotations for Input, Output, State, and their superclass DashDependency. So there's no point in having py.typed in the code base if the code is not typed.

added
bugsomething broken
P2considered for next cycle
on Mar 18, 2025
gothicVI

gothicVI commented on Mar 20, 2025

@gothicVI
ContributorAuthor

There are several issues with the claimed "typedness" for dash. In a fresh virtual environment I get:

$ mypy .
dash-core-components is not a valid Python package name
$ cd dash
mypy: "types.py" shadows library module "types"
note: A user-defined top-level module with name "types" is not supported
$ cd ..
$ pyright 
# see https://gist.github.com/gothicVI/34eb60a2a2f61b02d6a2c50027355a11 for very long output
$ cd dash
$ pyright 
# see https://gist.github.com/gothicVI/b2f30b6cbfbc648909eb3f82c4560c2c for lengthy output

which tells me that the packages violates python conventions and is not typed.
@T4rk1n how does that work for you?

gvwilson

gvwilson commented on Mar 20, 2025

@gvwilson
Contributor

Hi @gothicVI - thanks for filing this issue. We're aware that there's still work to do on Dash typing, and given resources at our end we have to take it in stages. If you would like to post a PR with a handful of the changes you would like to see, we can review that right away, and it will help us figure out how much effort it will be to solve the whole problem. Thanks - @gvwilson

self-assigned this
on Mar 20, 2025
changed the title [-][BUG] Dash 3.0 fails mypy[/-] [+]add/change type annotations to satisfy mypy and other tools[/+] on Mar 20, 2025
gothicVI

gothicVI commented on Mar 20, 2025

@gothicVI
ContributorAuthor

Hi @gvwilson thanks for taking a look. To be completely honest I do not know how to start contributing in that regard because I do not fully understand the internal workings yet. I might give it a look but can't prommis any PR.

I think the most needed changes would be to figure out what exactly breaks mypy when changing to version 3. Don't get me wrong, mypy did complain earlier due to there not being any annotations or stub files so we commented that out as mentioned above. But the release of version 3 did break that which it shouldn't. If needed revert the changes for the moment!

After that I'd suggest sticking to the general python conventions like no - in module names and not shadowing of built in libraries like types. I'd also suggest switching from setup.py to pyproject.toml and to include mypy and potentially other linters or analyzers into the regular process. Set up pre-commit and a CI pipeline for, e.g., ruff, mypy, and pyright and have every pushed commit be checked.

Please do not get me wrong. I love this project and this should not be understood as a personal attack against anyone who contributed typing code! Yet I think it is quite dangerous to push a major version upgrade without thorough testing - especially in such a large project that so many other projects rely on.

gvwilson

gvwilson commented on Mar 20, 2025

@gvwilson
Contributor

HI @gothicVI - thanks very much for your quick feedback. Reverting these changes isn't an option - there are a great many features that our users have wanted for a long time - so I'd like to focus on ways to move forward. If you can start a PR to convert from setup.py to pyproject.toml (which ought to be more straightforward than adding typing) that would be a great help. Thanks - @gvwilson

gothicVI

gothicVI commented on Mar 25, 2025

@gothicVI
ContributorAuthor

@gvwilson I didn't mean to revert the release of version 3 but just the commits that break the typing system.

Either way, can you or anyone else confirm that the new version breaks mypy at all?

Independently I've looked into converting the setup.py approach to a pyproject.toml approach.
However, I can't even build the current project state due to dash/labextension/dist/dash-jupyterlab.tgz being required but missing. What's happening here? How does the build process even work?

My attempt at conversion can be found here: gothicVI@ed59db7
I'd start a PR once I'm sure the project can be built at all.

changed the title [-]add/change type annotations to satisfy mypy and other tools[/-] [+]Version 3 adds breaking type annotations that do not comply with mypy[/+] on Mar 25, 2025
gothicVI

gothicVI commented on Mar 31, 2025

@gothicVI
ContributorAuthor

@gvwilson any news?

25 remaining items

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2considered for next cyclebugsomething brokenregressionthis used to work

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @gvwilson@T4rk1n@gothicVI@ndrezn

        Issue actions

          Version 3 adds breaking type annotations that do not comply with mypy · Issue #3226 · plotly/dash