Skip to content

Commit 1c50a14

Browse files
committed
Add --pep561-override option to force packages as typed even they don't have a py.typed file
1 parent b2edab2 commit 1c50a14

File tree

4 files changed

+20
-7
lines changed

4 files changed

+20
-7
lines changed

mypy/config_parser.py

+1
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ def split_and_match_files(paths: str) -> List[str]:
8585
'package_root': lambda s: [p.strip() for p in s.split(',')],
8686
'cache_dir': expand_path,
8787
'python_executable': expand_path,
88+
'pep561_override': lambda s: [p.strip() for p in s.split(',')],
8889
} # type: Final
8990

9091

mypy/main.py

+4
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,10 @@ def add_invertible_flag(flag: str,
467467
imports_group.add_argument(
468468
'--no-silence-site-packages', action='store_true',
469469
help="Do not silence errors in PEP 561 compliant installed packages")
470+
imports_group.add_argument(
471+
'--pep561-override', action='append', default=[],
472+
help="Consider the given package typed even if it does not claim to be "
473+
"PEP 561 compatible (may be repeated)")
470474

471475
platform_group = parser.add_argument_group(
472476
title='Platform configuration',

mypy/modulefinder.py

+13-7
Original file line numberDiff line numberDiff line change
@@ -168,19 +168,25 @@ def find_module(self, id: str) -> ModuleSearchResult:
168168

169169
def _find_module_non_stub_helper(self, components: List[str],
170170
pkg_dir: str) -> Union[OnePackageDir, ModuleNotFoundReason]:
171-
plausible_match = False
171+
plausible_match = None # type: Optional[Tuple[str, OnePackageDir]]
172172
dir_path = pkg_dir
173173
for index, component in enumerate(components):
174174
dir_path = os.path.join(dir_path, component)
175175
if self.fscache.isfile(os.path.join(dir_path, 'py.typed')):
176176
return os.path.join(pkg_dir, *components[:-1]), index == 0
177-
elif not plausible_match and (self.fscache.isdir(dir_path)
178-
or self.fscache.isfile(dir_path + ".py")):
179-
plausible_match = True
180-
if plausible_match:
181-
return ModuleNotFoundReason.FOUND_WITHOUT_TYPE_HINTS
182-
else:
177+
elif not plausible_match and (
178+
self.fscache.isfile(os.path.join(dir_path, '__init__.py'))
179+
or self.fscache.isfile(dir_path + ".py")):
180+
plausible_match = (
181+
'.'.join(components[:(index + 1)]),
182+
(os.path.join(pkg_dir, *components[:-1]), index == 0)
183+
)
184+
if not plausible_match:
183185
return ModuleNotFoundReason.NOT_FOUND
186+
elif self.options and plausible_match[0] in self.options.pep561_override:
187+
return plausible_match[1]
188+
else:
189+
return ModuleNotFoundReason.FOUND_WITHOUT_TYPE_HINTS
184190

185191
def _update_ns_ancestors(self, components: List[str], match: Tuple[str, bool]) -> None:
186192
path, verify = match

mypy/options.py

+2
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,8 @@ def __init__(self) -> None:
267267
self.transform_source = None # type: Optional[Callable[[Any], Any]]
268268
# Print full path to each file in the report.
269269
self.show_absolute_path = False # type: bool
270+
# Consider packages typed even if they do not declare PEP-561 compatiblity
271+
self.pep561_override = [] # type: List[str]
270272

271273
# To avoid breaking plugin compatibility, keep providing new_semantic_analyzer
272274
@property

0 commit comments

Comments
 (0)