From 8e7407cb154d8966f0f1b42847375012e02c2be9 Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Mon, 19 Oct 2020 00:52:03 -0700 Subject: [PATCH 1/4] add a test --- test-data/unit/cmdline.test | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test-data/unit/cmdline.test b/test-data/unit/cmdline.test index 9d74bdc9a1be..c731cd64dcc2 100644 --- a/test-data/unit/cmdline.test +++ b/test-data/unit/cmdline.test @@ -791,6 +791,17 @@ def bar(a: int, b: int) -> str: [out] src/anamespace/foo/bar.py:2: error: Incompatible return value type (got "int", expected "str") +[case testNestedPEP420Packages] +# cmd: mypy -p bottles --namespace-packages +[file bottles/jars/secret/glitter.py] +x: str = 0 +[file bottles/jars/sprinkle.py] +from bottles.jars.secret.glitter import x +x + 1 +[out] +bottles/jars/secret/glitter.py:1: error: Incompatible types in assignment (expression has type "int", variable has type "str") +bottles/jars/sprinkle.py:2: error: Unsupported operand types for + ("str" and "int") + [case testFollowImportStubs1] # cmd: mypy main.py [file mypy.ini] From 5a0c2fb3d69927504444ec51901ab83ad35279ae Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Mon, 19 Oct 2020 10:52:17 -0700 Subject: [PATCH 2/4] modulefinder: make -p handle namespace packages correctly Fixes part of #5759 The other part is passing files arguments, which we make steps towards in #9614 --- mypy/modulefinder.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mypy/modulefinder.py b/mypy/modulefinder.py index c5109fa53f3d..5dc5689915bc 100644 --- a/mypy/modulefinder.py +++ b/mypy/modulefinder.py @@ -387,13 +387,13 @@ def find_modules_recursive(self, module: str) -> List[BuildSource]: if mod not in hits: hits.add(mod) result += self.find_modules_recursive(module + '.' + mod) - elif os.path.isdir(module_path) and module in self.ns_packages: - # Even more subtler: handle recursive decent into PEP 420 + elif os.path.isdir(module_path) and any(module.startswith(p) for p in self.ns_packages): + # Even subtler: handle recursive decent into PEP 420 # namespace packages that are explicitly listed on the command # line with -p/--packages. for item in sorted(self.fscache.listdir(module_path)): - if os.path.isdir(os.path.join(module_path, item)): - result += self.find_modules_recursive(module + '.' + item) + item, _ = os.path.splitext(item) + result += self.find_modules_recursive(module + '.' + item) return result From 92090162927bc1513ff9fe2306b11d76358f4e6b Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Mon, 19 Oct 2020 13:02:35 -0700 Subject: [PATCH 3/4] the joys of python 3.5 --- test-data/unit/cmdline.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-data/unit/cmdline.test b/test-data/unit/cmdline.test index c731cd64dcc2..2892446b2279 100644 --- a/test-data/unit/cmdline.test +++ b/test-data/unit/cmdline.test @@ -794,7 +794,7 @@ src/anamespace/foo/bar.py:2: error: Incompatible return value type (got "int", e [case testNestedPEP420Packages] # cmd: mypy -p bottles --namespace-packages [file bottles/jars/secret/glitter.py] -x: str = 0 +x = 0 # type: str [file bottles/jars/sprinkle.py] from bottles.jars.secret.glitter import x x + 1 From 3b056b76221bbb1885afcb13697888fe9db24fbd Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Fri, 23 Oct 2020 15:22:00 -0700 Subject: [PATCH 4/4] modulefinder: remove useless check --- mypy/modulefinder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/modulefinder.py b/mypy/modulefinder.py index 5dc5689915bc..576354c5abcb 100644 --- a/mypy/modulefinder.py +++ b/mypy/modulefinder.py @@ -387,7 +387,7 @@ def find_modules_recursive(self, module: str) -> List[BuildSource]: if mod not in hits: hits.add(mod) result += self.find_modules_recursive(module + '.' + mod) - elif os.path.isdir(module_path) and any(module.startswith(p) for p in self.ns_packages): + elif os.path.isdir(module_path): # Even subtler: handle recursive decent into PEP 420 # namespace packages that are explicitly listed on the command # line with -p/--packages.