Repository: python/mypy

Issue:
Stubgen crashing on 0.560+
First reported by @henryJack on gitter, it appears stubgen is broken on Windows.

Steps to repro:
```
test>pip install git+https://github.com/python/mypy
test>tree /f
Folder PATH listing
C:.
└───pkg
        test.py
        __init__.py
test>stubgen pkg
Traceback (most recent call last):
  File "c:\python36\lib\site-packages\mypy\stubgen.py", line 150, in find_module_path_and_all
    mod = importlib.import_module(module)
  File "c:\python36\lib\importlib\__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 994, in _gcd_import
  File "<frozen importlib._bootstrap>", line 971, in _find_and_load
  File "<frozen importlib._bootstrap>", line 953, in _find_and_load_unlocked
ModuleNotFoundError: No module named 'pkg'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "c:\python36\lib\site-packages\mypy\stubgen.py", line 102, in generate_stub_for_module
    interpreter=interpreter)
  File "c:\python36\lib\site-packages\mypy\stubgen.py", line 152, in find_module_path_and_all
    raise CantImport(module)
mypy.stubgen.CantImport: pkg
Failed to import pkg; skipping it
```


Discussion:
Sure this isn't because there's no `__init__.py` file? Or does a similar
setup on other platforms cause a tidy error message?

Silly me. With and without an `__init__.py` it will crash the same. Original issue updated.
Hate to say it guys, but if you just do a regular install `pip install mypy` you get the same error :(
So `importlib.import_module` cannot find anything in the current directory, even at the entry point. I'm pretty sure this is a setuptools bug, but I'm going to wait till tomorrow when it isn't 4am to triple check :)
Confirmed on Mac. But for a top-level module it still works. What's going on? Did this ever work?
Yes, it 100% used to work
What do you mean by "top-level"? Why would you need to make that distinction?
Yeah, it's definitely install-related -- if I run it as `python3 -m mypy.stubgen pkg` it works.
The difference seems to be that when I run the 'stubgen' script installed in my bin directory, `sys.path` does not include the current directory, while when I just run `python -c mypy.stubgen` it does (the first element of `sys.path` is `''` in that case).

I'm beginning to think that this is actually a feature of setuptools -- stubgen will have to do some work to put the current directory back into `sys.path`. That leads to a fairly straightforward fix I suppose (but I haven't tried making it yet). Also to another workaround: set `PYTHONPATH=.`.

Note that in `--py2` mode a different path is taken that doesn't have this problem.
OK, it's not a *setuptools* feature, it's a *Python* feature. When you run a script, the first item of `sys.path` is the directory containing the script, not the current directory.

It's reasonable, and stubgen will just have to address this.
@gvanrossum , adding `PYTHONPATH=.` isn't a great fix. If you do `stubgen --recursive pkg` it will still break for nested modules...

also, if you try `stubgen .` for a package you're in, you get slapped too
I didn't meant it as a fix, just as a workaround until the code is fixed.
Also @gvanrossum, how did you run `python -c mypy.stubgen`, I get... 
```python -c "import mypy; mypy.stubgen"```

```
Traceback (most recent call last):
  File "<string>", line 1, in <module>
AttributeError: module 'mypy' has no attribute 'stubgen'```
You have to do `python -c "from mypy import stubgen"`.


Resolving patch:
diff --git a/mypy/stubgen.py b/mypy/stubgen.py
--- a/mypy/stubgen.py
+++ b/mypy/stubgen.py
@@ -880,6 +880,11 @@ def walk_packages(packages: List[str]) -> Iterator[str]:
 
 
 def main() -> None:
+    # Make sure that the current directory is in sys.path so that
+    # stubgen can be run on packages in the current directory.
+    if '' not in sys.path:
+        sys.path.insert(0, '')
+
     options = parse_options(sys.argv[1:])
     if not os.path.isdir(options.output_dir):
         raise SystemExit('Directory "{}" does not exist'.format(options.output_dir))


Test patch: