Skip to content

Cache invalidation issue with missing installed .pyi file #8211

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

Closed
ericvw opened this issue Dec 27, 2019 · 1 comment
Closed

Cache invalidation issue with missing installed .pyi file #8211

ericvw opened this issue Dec 27, 2019 · 1 comment

Comments

@ericvw
Copy link

ericvw commented Dec 27, 2019

There appears to be a cache invalidation issue with mypy running over a Python 2 and 3 compatible subpackage.

The reproducible test script is below. However, a few things should be noted:

  • While .pyi file is erroneously not specified in package_data – it is critical for illustrating the issue. This is technically a bug in the packaging part when stumbling across this. It should also be noted that adding the .pyi file to be installed does resolve the issue. However, mypy acts in an unexpected way when it is not properly packaged.
  • Note that the packages line in setup.py only installs the subpackage only. The reason being is that for Python 2, we don't want some_package/__init__.py being installed which is provided by a separate Python package (e.g., install_requires['some_package; python_version < "3.3"']).
# In an activated virtual environment...

mkdir -p mypy_test_case
cd mypy_test_case

cat >setup.py <<EOF
from setuptools import setup
setup(
    name="some_package.some_subpackage",
    version="0.0.1",
    package_dir={"": "src"},
    packages=["some_package.some_subpackage"],
    package_data={"some_package.some_subpackage": ["py.typed"]},
)
EOF

mkdir -p src/some_package/some_subpackage
touch src/some_package/__init__.py
touch src/some_package/some_subpackage/py.typed

cat >src/some_package/some_subpackage/__init__.py <<EOF
from ._some_submodule import find_the_answer
def print_the_answer() -> None:
    print(find_the_answer())
EOF

cat >src/some_package/some_subpackage/_some_submodule.pyi <<EOF
def find_the_answer() -> int: ...
EOF

python -m pip install .
python -m pip install mypy

# Observe mypy passes.
python -m mypy -vv --strict src/some_package/some_subpackage
# Observe mypy fails.
python -m mypy -vv --strict -m some_package.some_subpackage
# Observe mypy passes.
python -m mypy -vv --strict -m some_package.some_subpackage

What is interesting is that the second invocation of mypy fails with something like:

Parsing /Users/eric/.pyenv/versions/test-dev/lib/python3.8/site-packages/some_package/some_subpackage/__init__.py (some_package.some_subpackage)
/Users/eric/.pyenv/versions/test-dev/lib/python3.8/site-packages/some_package/some_subpackage/__init__.py:1: error: Cannot find implementation or library stub for module named 'some_package.some_subpackage._some_submodule'
/Users/eric/.pyenv/versions/test-dev/lib/python3.8/site-packages/some_package/some_subpackage/__init__.py:1: note: See https://mypy.readthedocs.io/en/latest/running_mypy.html#missing-imports

However, the third (last) invocation succeeds 🤷‍♂.

Quickly looking at the verbose output (-vv) it appears that when the first invocation of mypy is run, it caches the dependency for _some_submodule.pyi. When the second invocation occurs, it complains because it is unable to find _some_submodule.pyi or _some_submodule.py — then deletes the cached metadata. Upon the third run of mypy, it re-parses and succeeds, treating, I believe, the unknown import as Any.

My expectation would be for the second and third invocation to either both fail or both succeed.

@hauntsaninja
Copy link
Collaborator

Thanks, sounds like another duplicate of #9852

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

No branches or pull requests

2 participants