Repository: python/mypy

Issue:
0.990 internal error "IsADirectoryError" when not having __init__.py files
<!--
  Use this form only if mypy reports an "INTERNAL ERROR" and/or gives a traceback.
  Please include the traceback and all other messages below (use `mypy --show-traceback`).
-->

**Crash Report**

MyPy 0.981 was working fine, since update to latest 0.990 it crashes. Adding `__init__.py` to folders seems to solve it

**Traceback**

```
version: 0.990
Traceback (most recent call last):
  File "/home/osteenbergen/Documents/semiotic-iot/.tox/mypy/bin/mypy", line 8, in <module>
    sys.exit(console_entry())
  File "mypy/build.py", line 2067, in wrap_context
  File "mypy/build.py", line 2393, in finish_passes
  File "mypy/build.py", line 876, in report_file
  File "mypy/report.py", line 91, in file
  File "mypy/report.py", line 640, in on_file
  File "/usr/lib/python3.8/tokenize.py", line 392, in open
    buffer = _builtin_open(filename, 'rb')
IsADirectoryError: [Errno 21] Is a directory: 'tests/testresources/monitor'
```

**To Reproduce**

Folder structure
```
tests/example.py
```

example.py
```
print("Hello World!")
```

**Your Environment**

<!-- Include as many relevant details about the environment you experienced the bug in -->

- Mypy version used: `0.990`
- Mypy command-line flags: `--config-file mypy.ini -p tests`
- Mypy configuration options from `mypy.ini` (and other config files):
```
[mypy]
check_untyped_defs = True
disallow_any_generics = True
disallow_incomplete_defs = True
disallow_subclassing_any = True
disallow_untyped_calls = True
disallow_untyped_decorators = True
disallow_untyped_defs = True
ignore_missing_imports = True
no_implicit_optional = True
no_implicit_reexport = True
show_error_codes = True
strict_equality = True
warn_redundant_casts = True
warn_return_any = True
warn_unused_configs = True
warn_unused_ignores = True

cobertura_xml_report = mypy_report
html_report = mypy_report
```
- Python version used: `3.8.13`
- Operating system and version: Ubuntu 20.04

<!--
You can freely edit this text, please remove all the lines
you believe are unnecessary.
-->



Discussion:
If i remove the report generation from the `mypy.ini` it works.
Thanks, similar to https://github.com/python/mypy/pull/13733
`--no-namespace-packages` is an alternative way to get unblocked

Resolving patch:
diff --git a/mypy/report.py b/mypy/report.py
--- a/mypy/report.py
+++ b/mypy/report.py
@@ -637,51 +637,48 @@ def on_file(
         etree.SubElement(class_element, "methods")
         lines_element = etree.SubElement(class_element, "lines")
 
-        with tokenize.open(path) as input_file:
-            class_lines_covered = 0
-            class_total_lines = 0
-            for lineno, _ in enumerate(input_file, 1):
-                status = visitor.line_map.get(lineno, stats.TYPE_EMPTY)
-                hits = 0
-                branch = False
-                if status == stats.TYPE_EMPTY:
-                    continue
-                class_total_lines += 1
-                if status != stats.TYPE_ANY:
-                    class_lines_covered += 1
-                    hits = 1
-                if status == stats.TYPE_IMPRECISE:
-                    branch = True
-                file_info.counts[status] += 1
-                line_element = etree.SubElement(
-                    lines_element,
-                    "line",
-                    branch=str(branch).lower(),
-                    hits=str(hits),
-                    number=str(lineno),
-                    precision=stats.precision_names[status],
-                )
-                if branch:
-                    line_element.attrib["condition-coverage"] = "50% (1/2)"
-            class_element.attrib["branch-rate"] = "0"
-            class_element.attrib["line-rate"] = get_line_rate(
-                class_lines_covered, class_total_lines
+        class_lines_covered = 0
+        class_total_lines = 0
+        for lineno, _ in iterate_python_lines(path):
+            status = visitor.line_map.get(lineno, stats.TYPE_EMPTY)
+            hits = 0
+            branch = False
+            if status == stats.TYPE_EMPTY:
+                continue
+            class_total_lines += 1
+            if status != stats.TYPE_ANY:
+                class_lines_covered += 1
+                hits = 1
+            if status == stats.TYPE_IMPRECISE:
+                branch = True
+            file_info.counts[status] += 1
+            line_element = etree.SubElement(
+                lines_element,
+                "line",
+                branch=str(branch).lower(),
+                hits=str(hits),
+                number=str(lineno),
+                precision=stats.precision_names[status],
             )
-            # parent_module is set to whichever module contains this file.  For most files, we want
-            # to simply strip the last element off of the module.  But for __init__.py files,
-            # the module == the parent module.
-            parent_module = file_info.module.rsplit(".", 1)[0]
-            if file_info.name.endswith("__init__.py"):
-                parent_module = file_info.module
-
-            if parent_module not in self.root_package.packages:
-                self.root_package.packages[parent_module] = CoberturaPackage(parent_module)
-            current_package = self.root_package.packages[parent_module]
-            packages_to_update = [self.root_package, current_package]
-            for package in packages_to_update:
-                package.total_lines += class_total_lines
-                package.covered_lines += class_lines_covered
-            current_package.classes[class_name] = class_element
+            if branch:
+                line_element.attrib["condition-coverage"] = "50% (1/2)"
+        class_element.attrib["branch-rate"] = "0"
+        class_element.attrib["line-rate"] = get_line_rate(class_lines_covered, class_total_lines)
+        # parent_module is set to whichever module contains this file.  For most files, we want
+        # to simply strip the last element off of the module.  But for __init__.py files,
+        # the module == the parent module.
+        parent_module = file_info.module.rsplit(".", 1)[0]
+        if file_info.name.endswith("__init__.py"):
+            parent_module = file_info.module
+
+        if parent_module not in self.root_package.packages:
+            self.root_package.packages[parent_module] = CoberturaPackage(parent_module)
+        current_package = self.root_package.packages[parent_module]
+        packages_to_update = [self.root_package, current_package]
+        for package in packages_to_update:
+            package.total_lines += class_total_lines
+            package.covered_lines += class_lines_covered
+        current_package.classes[class_name] = class_element
 
     def on_finish(self) -> None:
         self.root.attrib["line-rate"] = get_line_rate(


Test patch: