Repository: python/mypy

Issue:
Mypy report does not get generated when cache is fresh
Mypy report does not get generated when cache is fresh (i.e. not stale).

Say we have a python file `a.py`:

a.py
```
def foo():
	pass
```

Without `.mypy_cache` folder xml report generated by `mypy a.py --xml-report .` is as follows:

index.xml
```
<?xml-stylesheet type="text/xsl" href="mypy-html.xslt"?><mypy-report-index name="index"><file module="a" name="a.py" total="2" any="1" empty="1" imprecise="0" precise="0" unanalyzed="0"/></mypy-report-index>
```

However running `mypy a.py --xml-report .` again produces this:

index.xml
```
<?xml-stylesheet type="text/xsl" href="mypy-html.xslt"?><mypy-report-index name="index"/>
```

Removing `.mypy_cache` and running it again properly generates the report.


Versions:

python version: 3.6.5
mypy version: mypy-0.610+dev.76d60b018c93f6879a01a30f89bf0586c610bc06
lxml version: lxml-4.2.1




Discussion:
Same thing happens to me with the html report.
Unfortunately this is a known problem with the reports. Use
--no-incremental for reports.

If this isn't a duplicate, a `bug` label might aid visibility.
Technically it's already mentioned here: https://github.com/python/mypy/issues/1123#issuecomment-441231087

But I'm happy to keep this open as a separate issue. It's unlikely to be fixed in any way other than forcing incremental mode off when generating the reports though...

Resolving patch:
diff --git a/mypy/build.py b/mypy/build.py
--- a/mypy/build.py
+++ b/mypy/build.py
@@ -504,8 +504,10 @@ def __init__(self, data_dir: str,
         self.stale_modules = set()  # type: Set[str]
         self.rechecked_modules = set()  # type: Set[str]
         self.flush_errors = flush_errors
-        self.cache_enabled = options.incremental and (
-            not options.fine_grained_incremental or options.use_fine_grained_cache)
+        self.cache_enabled = (options.incremental
+                              and (not options.fine_grained_incremental
+                                   or options.use_fine_grained_cache)
+                              and not reports.reporters)
         self.fscache = fscache
         self.find_module_cache = FindModuleCache(self.search_paths, self.fscache, self.options)
         if options.sqlite_cache:


Test patch:
diff --git a/mypy/test/testcmdline.py b/mypy/test/testcmdline.py
--- a/mypy/test/testcmdline.py
+++ b/mypy/test/testcmdline.py
@@ -32,10 +32,11 @@ class PythonCmdlineSuite(DataSuite):
     native_sep = True
 
     def run_case(self, testcase: DataDrivenTestCase) -> None:
-        test_python_cmdline(testcase)
+        for step in [1] + sorted(testcase.output2):
+            test_python_cmdline(testcase, step)
 
 
-def test_python_cmdline(testcase: DataDrivenTestCase) -> None:
+def test_python_cmdline(testcase: DataDrivenTestCase, step: int) -> None:
     assert testcase.old_cwd is not None, "test was not properly set up"
     # Write the program to a file.
     program = '_program.py'
@@ -75,12 +76,14 @@ def test_python_cmdline(testcase: DataDrivenTestCase) -> None:
         # Ignore stdout, but we insist on empty stderr and zero status.
         if err or result:
             raise AssertionError(
-                'Expected zero status and empty stderr, got %d and\n%s' %
-                (result, '\n'.join(err + out)))
+                'Expected zero status and empty stderr%s, got %d and\n%s' %
+                (' on step %d' % step if testcase.output2 else '',
+                 result, '\n'.join(err + out)))
         for path, expected_content in testcase.output_files:
             if not os.path.exists(path):
                 raise AssertionError(
-                    'Expected file {} was not produced by test case'.format(path))
+                    'Expected file {} was not produced by test case{}'.format(
+                        path, ' on step %d' % step if testcase.output2 else ''))
             with open(path, 'r', encoding='utf8') as output_file:
                 actual_output_content = output_file.read().splitlines()
             normalized_output = normalize_file_output(actual_output_content,
@@ -93,17 +96,19 @@ def test_python_cmdline(testcase: DataDrivenTestCase) -> None:
                                          for line in normalized_output]
                 normalized_output = normalize_error_messages(normalized_output)
             assert_string_arrays_equal(expected_content.splitlines(), normalized_output,
-                                       'Output file {} did not match its expected output'.format(
-                                           path))
+                                       'Output file {} did not match its expected output{}'.format(
+                                           path, ' on step %d' % step if testcase.output2 else ''))
     else:
         if testcase.normalize_output:
             out = normalize_error_messages(err + out)
         obvious_result = 1 if out else 0
         if obvious_result != result:
             out.append('== Return code: {}'.format(result))
-        assert_string_arrays_equal(testcase.output, out,
-                                   'Invalid output ({}, line {})'.format(
-                                       testcase.file, testcase.line))
+        expected_out = testcase.output if step == 1 else testcase.output2[step]
+        assert_string_arrays_equal(expected_out, out,
+                                   'Invalid output ({}, line {}){}'.format(
+                                       testcase.file, testcase.line,
+                                       ' on step %d' % step if testcase.output2 else ''))
 
 
 def parse_args(line: str) -> List[str]:
diff --git a/test-data/unit/reports.test b/test-data/unit/reports.test
--- a/test-data/unit/reports.test
+++ b/test-data/unit/reports.test
@@ -357,3 +357,15 @@ class Foo:
 @attr.s
 class Z(object):
     pass
+
+[case testCoverageIgnoresCache]
+-- Performs two runs to verify that cached information does not prevent
+-- modules from being included in reports.
+# cmd: mypy --linecount-report report a.py
+[file a.py]
+empty = False
+[out]
+[out2]
+[outfile report/linecount.txt]
+      1       1      0      0 total
+      1       1      0      0 a