Repository: python/mypy

Issue:
Non-existing file of form a.b.py triggers assert '.' not in mod
Repro:
```
mypy a.b.py
```
Regardless of whether `a.b.py` exists or not this gives
```
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 38, in main
    sources, options = process_options(sys.argv[1:])
  File "/Users/guido/src/mypy/mypy/main.py", line 364, in process_options
    targets.append(BuildSource(f, crawl_up(f)[1], None))
  File "/Users/guido/src/mypy/mypy/main.py", line 429, in crawl_up
    assert '.' not in mod
AssertionError
```


Discussion:
Run `mypy a/b.py` instead.

When specifying a file path from the command line, you should use the actual path of the file. This seems like reasonable, not-buggy behavior. I don't think that directory names usually allow for `.`s, and that is sort-of what the error is saying (although it _could_ be a little more clear).

For the record, I arrived here because I was doing the same thing :smile:
@Gazzini I believe Guido is talking about a file with a name `a.b.py`, not file `b.py` in folder `a` which would correspond to `import a.b` in python.
Ah, makes sense. IMO, a good solution would be to rename the file without a "." Character. Maybe use an underscore or something.
The point is that mypy should report this as an error (non-existing file) or process the file as a script (if it exists), not crash in an `assert`.

Resolving patch:
diff --git a/mypy/build.py b/mypy/build.py
--- a/mypy/build.py
+++ b/mypy/build.py
@@ -1243,6 +1243,13 @@ def skipping_module(self, id: str, path: str) -> None:
         manager.errors.set_import_context(save_import_context)
 
     def add_ancestors(self) -> None:
+        if self.path is not None:
+            _, name = os.path.split(self.path)
+            base, _ = os.path.splitext(name)
+            if '.' in base:
+                # This is just a weird filename, don't add anything
+                self.ancestors = []
+                return
         # All parent packages are new ancestors.
         ancestors = []
         parent = self.id
diff --git a/mypy/main.py b/mypy/main.py
--- a/mypy/main.py
+++ b/mypy/main.py
@@ -486,7 +486,6 @@ def crawl_up(arg: str) -> Tuple[str, str]:
     """
     dir, mod = os.path.split(arg)
     mod = strip_py(mod) or mod
-    assert '.' not in mod
     while dir and get_init_file(dir):
         dir, base = os.path.split(dir)
         if not base:


Test patch:
diff --git a/test-data/unit/cmdline.test b/test-data/unit/cmdline.test
--- a/test-data/unit/cmdline.test
+++ b/test-data/unit/cmdline.test
@@ -477,3 +477,31 @@ reveal_type(missing.x)  # Expect Any
 ignore_missing_imports = True
 [out]
 main.py:2: error: Revealed type is 'Any'
+
+[case testDotInFilenameOKScript]
+# cmd: mypy a.b.py c.d.pyi
+[file a.b.py]
+undef
+[file c.d.pyi]
+whatever
+[out]
+c.d.pyi:1: error: Name 'whatever' is not defined
+a.b.py:1: error: Name 'undef' is not defined
+
+[case testDotInFilenameOKFolder]
+# cmd: mypy my.folder
+[file my.folder/tst.py]
+undef
+[out]
+my.folder/tst.py:1: error: Name 'undef' is not defined
+
+[case testDotInFilenameNoImport]
+# cmd: mypy main.py
+[file main.py]
+import a.b
+[file a.b.py]
+whatever
+[out]
+main.py:1: error: Cannot find module named 'a'
+main.py:1: note: (Perhaps setting MYPYPATH or using the "--ignore-missing-imports" flag would help)
+main.py:1: error: Cannot find module named 'a.b'