Skip to content

Unintuitive behaviour when only subpackage provides py.typed #16149

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Ranfir opened this issue Sep 19, 2023 · 10 comments
Open

Unintuitive behaviour when only subpackage provides py.typed #16149

Ranfir opened this issue Sep 19, 2023 · 10 comments
Labels
bug mypy got something wrong

Comments

@Ranfir
Copy link

Ranfir commented Sep 19, 2023

Bug Report

from numba import typed causes mypy to generate spurious attr-defined errors for everything else imported from numba.

To Reproduce

from numba import njit, typed  # error: Module has no attribute "njit"  [attr-defined]

Expected Behavior

scratch.py:1: error: Skipping analyzing "numba": module is installed, but missing library stubs or py.typed marker  [import]
scratch.py:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports

Actual Behavior

scratch.py:1: error: Module "numba" has no attribute "njit"  [attr-defined]

Your Environment

  • Mypy version used: 1.5.1
  • Mypy command-line flags: none
  • Mypy configuration options from mypy.ini (and other config files): none
  • Python version used: 3.8.8, 3.10.9, 3.11.5
$ .venv/bin/pip freeze
importlib-metadata==6.8.0
llvmlite==0.40.1
mypy==1.5.1
mypy-extensions==1.0.0
numba==0.57.1
numpy==1.24.4
tomli==2.0.1
typing_extensions==4.8.0
zipp==3.17.0
@Ranfir Ranfir added the bug mypy got something wrong label Sep 19, 2023
@LukeSavefrogs
Copy link

The same is happening with pydantic.

Example

Take the following snippet as example:

import pydantic

class CustomModel(pydantic.BaseModel):
    """Base class for pydantic models."""
    prop1: str = pydantic.Field(alias="property1", frozen=True)

This code will produce the following mypy errors:

  • Line 3: Name "pydantic.BaseModel" is not defined [name-defined].
  • Line 5: Module has no attribute "Field" [attr-defined].

@hauntsaninja
Copy link
Collaborator

hauntsaninja commented Sep 21, 2023

This is because the numba.typed subpackage provides a py.typed file. As per PEP 561, I think this makes it look like a part of a typed namespace package that only provides that subpackage (see https://peps.python.org/pep-0561/#stub-only-packages). I think this is behaving as per the spec?

I don't know what LukeSavefrogs is about, I cannot reproduce nor have you provided enough information to truly reproduce.

@LukeSavefrogs
Copy link

I don't know what LukeSavefrogs is about, I cannot reproduce nor have you provided enough information to truly reproduce.

Sorry if I was not clear, when I come back home I'll try and see if the issue is related to what you said. Otherwise I'll open a new issue. 😄

@Ranfir
Copy link
Author

Ranfir commented Sep 21, 2023

This is because the numba.typed subpackage provides a py.typed file. As per PEP 561, I think this makes it look like a part of a typed namespace package that only provides that subpackage (see https://peps.python.org/pep-0561/#stub-only-packages). I think this is behaving as per the spec?

Thanks. I hadn't noticed the py.typed file in the numba.typed sub-package.

I don't think numba.typed qualifies as a namespace package in this case. My understanding per PEP 561 is that a sub-package can include a py.typed file to indicate that it and its sub-packages support typing. But in this case, it seems that mypy is seeing the py.typed file in the numba.typed sub-package and applying it to the entire numba package. To demonstrate this, note that omitting typed from the import results in the expected behavior:

from numba import njit

Package maintainers who wish to support type checking of their code MUST add a marker file named py.typed to their package supporting typing. This marker applies recursively: if a top-level package includes it, all its sub-packages MUST support type checking as well.

@LukeSavefrogs
Copy link

I don't know what LukeSavefrogs is about, I cannot reproduce nor have you provided enough information to truly reproduce.

Sorry if I was not clear, when I come back home I'll try and see if the issue is related to what you said. Otherwise I'll open a new issue. 😄

As an addition, I can confirm that pydantic too has a py.typed file

@c-gohlke
Copy link

is there any solution/workaround to this?

I can add

[tool.mypy]
disable_error_code = "attr-defined"

to pyproject.toml, but I would rather this happens at a module level

[tool.mypy-numba]
disable_error_code = "attr-defined"

does not work because the error happens in my modules at import time

@sumkincpp
Copy link

In my case, I cannot simply disable error by code for whole module (readline), though disabling globally in mypy works

[mypy]
strict = True

; # beware of enabling option, it can lead to false positives
; disable_error_code = attr-defined

; this doesn't work xD
[mypy-readline]
disable_error_code = attr-defined

[mypy-readline.*]
disable_error_code = attr-defined

@danielhundhausen
Copy link

danielhundhausen commented Oct 9, 2024

Is there any update on this or recommended way of dealing with it?

@hauntsaninja
Copy link
Collaborator

I don't know about recommended, but here's one possible workaround:

[[tool.mypy.overrides]]
module = "numba.*"
follow_imports = "skip"

It will make mypy simply skip analysis of numba and anything originating from it will be Any.

@hauntsaninja hauntsaninja changed the title Module has no attribute Unintuitive behaviour when only subpackage provides py.typed Oct 10, 2024
@brandonchinn178
Copy link

+1 types-protobuf has the same issue, where

import google.protobuf.descriptor

errors with "Library google not found"

python/typeshed#10986 (comment)

nipunn1313/mypy-protobuf#681

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong
Projects
None yet
Development

No branches or pull requests

7 participants