Repository: python/mypy

Issue:
mypy crashes when run from a directory without write access
Mypy shouldn't write cache files for code supplied on the command line.  Additionally, if you don't have write access to the directory, mypy will crash.


Discussion:
The command line is treated as a module named `__main__` and I don't see any evidence that cache files are written for that name.

However the crash is real: in a directory with no write permission:
```
(v36) guido-mbp:tmp guido$ PYTHONPATH=.. python3 -m mypy -c pass
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "/usr/local/lib/python3.6/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "/Users/guido/src/mypy/mypy/__main__.py", line 5, in <module>
    main(None)
  File "/Users/guido/src/mypy/mypy/main.py", line 46, in main
    res = type_check_only(sources, bin_dir, options)
  File "/Users/guido/src/mypy/mypy/main.py", line 93, in type_check_only
    options=options)
  File "/Users/guido/src/mypy/mypy/build.py", line 188, in build
    graph = dispatch(sources, manager)
  File "/Users/guido/src/mypy/mypy/build.py", line 1595, in dispatch
    process_graph(graph, manager)
  File "/Users/guido/src/mypy/mypy/build.py", line 1838, in process_graph
    process_stale_scc(graph, scc, manager)
  File "/Users/guido/src/mypy/mypy/build.py", line 1946, in process_stale_scc
    graph[id].write_cache()
  File "/Users/guido/src/mypy/mypy/build.py", line 1576, in write_cache
    self.manager)
  File "/Users/guido/src/mypy/mypy/build.py", line 867, in write_cache
    os.makedirs(parent, exist_ok=True)
  File "/Users/guido/v36/lib/python3.6/os.py", line 210, in makedirs
    makedirs(head, mode, exist_ok)
  File "/Users/guido/v36/lib/python3.6/os.py", line 220, in makedirs
    mkdir(name, mode)
PermissionError: [Errno 13] Permission denied: '.mypy_cache'
```
(To be clear, I think it's a feature that it tries to write cache files for modules *imported* from the command line.)
That makes sense.  I assume that includes the default imports, because something like `mypy -c "1"` will still crash.
I don't think this is related to `-c` at all; the crash happens also if I run `mypy some/file.py` in a directory I don't have write access to.
Yeah, we really should just catch exceptions from makedirs in write_cache.

Is it worth a 0.511 release? I dunno.
I think we should also never write cache files when running with `-c`.
After talking f2f, I don't have any strong objections about writing the cache with `-c` in the absence of user complaints.  Let's limit this issue to the problem of mypy crashing when it doesn't have write access to the current directory.

Resolving patch:
diff --git a/mypy/build.py b/mypy/build.py
--- a/mypy/build.py
+++ b/mypy/build.py
@@ -864,7 +864,6 @@ def write_cache(id: str, path: str, tree: MypyFile,
 
     # Make sure directory for cache files exists
     parent = os.path.dirname(data_json)
-    os.makedirs(parent, exist_ok=True)
     assert os.path.dirname(meta_json) == parent
 
     # Construct temp file names
@@ -882,6 +881,7 @@ def write_cache(id: str, path: str, tree: MypyFile,
 
     # Obtain and set up metadata
     try:
+        os.makedirs(parent, exist_ok=True)
         st = manager.get_stat(path)
     except OSError as err:
         manager.log("Cannot get stat for {}: {}".format(path, err))


Test patch: