I have a project with the following (partial) directory structure
.
├── mypy.ini
├── src
│ ├── preppy
│ │ ├── cli.py
│ │ ├── __main__.py
│ │ ├── model.py
│ │ └── tools.py
├── pyproject.toml
└── tests
In cli.py
, I have the following code (lines 13 and 14 in the file):
from .model import Problem
from .tools import get_abs_path, transcode
I also have similarly styled relative imports in model.py
and __main__.py
All similar imports throw errors in both pylint
(2.5.3) and mypy
(0.761) when the tools are automatically run in my IDE (Code - OSS), e.g.:
Attempted relative import beyond top-level package pylint(relative-beyond-top-level) [13,1]
Cannot find implementation or library stub for module named '.model' mypy(error) [13,1]
Attempted relative import beyond top-level package pylint(relative-beyond-top-level) [14,1]
Cannot find implementation or library stub for module named '.tools' mypy(error) [14,1]
See https://mypy.readthedocs.io/en/latest/running_mypy.html#missing-imports mypy(note) [13,1]
When I add a blank __init__.py
file to the folder, the errors disappear.
I don't need this __init__.py
file for the package to work.
I thought that post-PEP 420, it shouldn't be required, especially if it's just there to satisfy linters.
Is there something else I'm doing wrong, or should I just add the __init__.py
and get over it :) ?
Config for pylint
is in pyproject.toml
:
[tool.pylint.'MESSAGES CONTROL']
# Pylint and black disagree on hanging indentation.
disable = "C0330"
[tool.pylint.MISCELLANEOUS]
# Note: By default, "TODO" is flagged, this is disabled by omitting it
# from the list below.
notes = "FIXME,XXX"
Config for mypy
is in mypy.ini
:
[mypy]
disallow_untyped_calls = True
disallow_untyped_defs = True
disallow_incomplete_defs = True
disallow_untyped_decorators = True
mypy_path = src
namespace_packages = True
[mypy-openpyxl]
ignore_missing_imports = True
[mypy-pulp]
ignore_missing_imports = True
[mypy-pytest]
ignore_missing_imports = True
I'm running python 3.8.0.
PEP 420 does not allow to "create a package by omitting __init__.py
", it enforces to "create a namespace package by omitting __init__.py
". This means:
__init__.py
.__init__.py
.While using a namespace package like a regular package usually works, it may unexpectedly fail when package names clash. In most cases, a namespace package is not desirable.