Repository: python/mypy

Issue:
dmypy issue with `mypy.ini` 
In http://github.com/zulip/zulip/, we've been running `dmypy` with this commit from master: https://github.com/python/mypy.git@6a934d32124991a77ea433856cf2d62871ceb632#egg=mypy==0.610+dev.6a934d32124991a77ea433856cf2d62871ceb632

Generally, it's been great, but we've been prevented from turning it on by default because I've been seeing it throw occasional errors like this (generally shows up after a lot of rebasing; I switch branches dozens of times a day as part of merging things):

```
(zulip-py3-venv) tabbott@zaset:~/zulip$ ./tools/run-mypy -d
zproject/test_settings.py:22: error: Need type annotation for 'REALM_HOSTS'
zproject/test_settings.py:43: error: Incompatible types in assignment (expression has type "None", variable has type "str")
zproject/test_settings.py:61: error: Incompatible types in assignment (expression has type "Tuple[str, ...]", variable has type "Tuple[str, str, str, str]")
zproject/test_settings.py:80: error: Dict entry 2 has incompatible type "str": "int"; expected "str": "Union[Dict[str, int], str, None]"
zproject/test_settings.py:80: error: Dict entry 3 has incompatible type "str": "int"; expected "str": "Union[Dict[str, int], str, None]"
zproject/test_settings.py:152: error: Need type annotation for 'PUSH_NOTIFICATION_BOUNCER_URL'
```

but this shouldn't be happening, since we have this in our `mypy.ini`:

```
[mypy-zproject.test_settings]                                                                                                            
ignore_errors = True                                                                                                                     
```

I have it reproduced currently in my laptop, so if there's something I can do to dump data from `dmypy` or otherwise help debug, I'd love to do that.

As a sidenote, why `dmypy` instead of `mypyd`?  I feel like the latter is the traditional UNIX name :)


Discussion:
@msullivan might have some ideas about why this can happen.
It looks like we don't use the per-module options when rechecking module top levels due to a trigger!
Both of these tests fail with errors in the second stage:
```
[case testRefreshIgnoreErrors]
[file mypy.ini]
[[mypy]
[[mypy-b]
ignore_errors = True
[file a.py]
y = '1'
[file a.py.2]
y = 1
[file b.py]
from a import y
x = None
[out]
==
```
and
```
[case testRefreshOptions]
[file mypy.ini]
[[mypy]
disallow_any_generics = True
[[mypy-b]
disallow_any_generics = False
[file a.py]
y = '1'
[file a.py.2]
y = 1
[file b.py]
from typing import List
from a import y
x = []  # type: List
[builtins fixtures/list.pyi]
[out]
==
```

I can take a look at fixing this tomorrow, it probably will be simple.

This bug falls into the annoying category of "bad enough that I wish it was going to be fixed in the release going out tomorrow" but "not bad enough to be worth cherry-picking a fix at this point". Sigh.

Resolving patch:
diff --git a/mypy/semanal_pass3.py b/mypy/semanal_pass3.py
--- a/mypy/semanal_pass3.py
+++ b/mypy/semanal_pass3.py
@@ -77,6 +77,7 @@ def visit_file(self, file_node: MypyFile, fnam: str, options: Options,
     def refresh_partial(self, node: Union[MypyFile, FuncItem, OverloadedFuncDef],
                         patches: List[Tuple[int, Callable[[], None]]]) -> None:
         """Refresh a stale target in fine-grained incremental mode."""
+        self.options = self.sem.options
         self.patches = patches
         if isinstance(node, MypyFile):
             self.recurse_into_functions = False
diff --git a/mypy/server/update.py b/mypy/server/update.py
--- a/mypy/server/update.py
+++ b/mypy/server/update.py
@@ -852,8 +852,9 @@ def key(node: DeferredNode) -> int:
 
     nodes = sorted(nodeset, key=key)
 
-    # TODO: ignore_all argument to set_file_ignored_lines
-    manager.errors.set_file_ignored_lines(file_node.path, file_node.ignored_lines)
+    options = graph[module_id].options
+    manager.errors.set_file_ignored_lines(
+        file_node.path, file_node.ignored_lines, options.ignore_errors)
 
     targets = set()
     for node in nodes:
@@ -871,7 +872,6 @@ def key(node: DeferredNode) -> int:
 
     # Second pass of semantic analysis. We don't redo the first pass, because it only
     # does local things that won't go stale.
-    options = graph[module_id].options
     for deferred in nodes:
         with semantic_analyzer.file_context(
                 file_node=file_node,


Test patch:
diff --git a/test-data/unit/fine-grained.test b/test-data/unit/fine-grained.test
--- a/test-data/unit/fine-grained.test
+++ b/test-data/unit/fine-grained.test
@@ -7139,3 +7139,55 @@ def f() -> int: return 0
 def f() -> str: return '0'
 [out]
 ==
+
+[case testRefreshIgnoreErrors1]
+[file mypy.ini]
+[[mypy]
+[[mypy-b]
+ignore_errors = True
+[file a.py]
+y = '1'
+[file a.py.2]
+y = 1
+[file b.py]
+from a import y
+def fu() -> None:
+    1+'lurr'
+    y
+[out]
+==
+
+[case testRefreshIgnoreErrors2]
+[file mypy.ini]
+[[mypy]
+[[mypy-b]
+ignore_errors = True
+[file b.py]
+def fu() -> int:
+    1+'lurr'
+    return 1
+[file b.py.2]
+def fu() -> int:
+    1+'lurr'
+    return 2
+[out]
+==
+
+
+[case testRefreshOptions]
+[file mypy.ini]
+[[mypy]
+disallow_any_generics = True
+[[mypy-b]
+disallow_any_generics = False
+[file a.py]
+y = '1'
+[file a.py.2]
+y = 1
+[file b.py]
+from typing import List
+from a import y
+x = []  # type: List
+[builtins fixtures/list.pyi]
+[out]
+==