| -- Tests for reports | |
| -- | |
| -- This file follows syntax of cmdline.test. | |
| [case testConfigErrorUnknownReport] | |
| # cmd: mypy -c pass | |
| [file mypy.ini] | |
| \[mypy] | |
| bad_report = . | |
| [out] | |
| mypy.ini: [mypy]: Unrecognized report type: bad_report | |
| == Return code: 0 | |
| [case testCoberturaParser] | |
| # cmd: mypy --cobertura-xml-report build pkg | |
| [file pkg/__init__.py] | |
| [file pkg/a.py] | |
| from typing import Dict | |
| def foo() -> Dict: | |
| z = {'hello': 'world'} | |
| return z | |
| [file pkg/subpkg/__init__.py] | |
| [file pkg/subpkg/a.py] | |
| def bar() -> str: | |
| return 'world' | |
| def untyped_function(): | |
| return 42 | |
| [outfile build/cobertura.xml] | |
| <coverage timestamp="$TIMESTAMP" version="$VERSION" line-rate="0.7500" branch-rate="0" lines-covered="6" lines-valid="8"> | |
| <sources> | |
| <source>$PWD</source> | |
| </sources> | |
| <packages> | |
| <package complexity="1.0" name="pkg" branch-rate="0" line-rate="1.0000"> | |
| <classes> | |
| <class complexity="1.0" filename="pkg/__init__.py" name="__init__.py" branch-rate="0" line-rate="1.0"> | |
| <methods/> | |
| <lines/> | |
| </class> | |
| <class complexity="1.0" filename="pkg/a.py" name="a.py" branch-rate="0" line-rate="1.0000"> | |
| <methods/> | |
| <lines> | |
| <line branch="false" hits="1" number="1" precision="precise"/> | |
| <line branch="true" hits="1" number="3" precision="imprecise" condition-coverage="50% (1/2)"/> | |
| <line branch="false" hits="1" number="4" precision="precise"/> | |
| <line branch="false" hits="1" number="5" precision="precise"/> | |
| </lines> | |
| </class> | |
| </classes> | |
| </package> | |
| <package complexity="1.0" name="pkg.subpkg" branch-rate="0" line-rate="0.5000"> | |
| <classes> | |
| <class complexity="1.0" filename="pkg/subpkg/__init__.py" name="__init__.py" branch-rate="0" line-rate="1.0"> | |
| <methods/> | |
| <lines/> | |
| </class> | |
| <class complexity="1.0" filename="pkg/subpkg/a.py" name="a.py" branch-rate="0" line-rate="0.5000"> | |
| <methods/> | |
| <lines> | |
| <line branch="false" hits="1" number="1" precision="precise"/> | |
| <line branch="false" hits="1" number="2" precision="precise"/> | |
| <line branch="false" hits="0" number="3" precision="any"/> | |
| <line branch="false" hits="0" number="4" precision="any"/> | |
| </lines> | |
| </class> | |
| </classes> | |
| </package> | |
| </packages> | |
| </coverage> | |
| [case testCoberturaStarUnpacking] | |
| # cmd: mypy --cobertura-xml-report build a.py | |
| [file a.py] | |
| from typing import TypedDict | |
| class MyDict(TypedDict): | |
| a: int | |
| def foo(a: int) -> MyDict: | |
| return {"a": a} | |
| md: MyDict = MyDict(**foo(42)) | |
| [outfile build/cobertura.xml] | |
| <coverage timestamp="$TIMESTAMP" version="$VERSION" line-rate="1.0000" branch-rate="0" lines-covered="6" lines-valid="6"> | |
| <sources> | |
| <source>$PWD</source> | |
| </sources> | |
| <packages> | |
| <package complexity="1.0" name="a" branch-rate="0" line-rate="1.0000"> | |
| <classes> | |
| <class complexity="1.0" filename="a.py" name="a.py" branch-rate="0" line-rate="1.0000"> | |
| <methods/> | |
| <lines> | |
| <line branch="false" hits="1" number="1" precision="precise"/> | |
| <line branch="false" hits="1" number="3" precision="precise"/> | |
| <line branch="false" hits="1" number="4" precision="precise"/> | |
| <line branch="false" hits="1" number="6" precision="precise"/> | |
| <line branch="false" hits="1" number="7" precision="precise"/> | |
| <line branch="false" hits="1" number="8" precision="precise"/> | |
| </lines> | |
| </class> | |
| </classes> | |
| </package> | |
| </packages> | |
| </coverage> | |
| [case testAnyExprReportDivisionByZero] | |
| # cmd: mypy --any-exprs-report=out -c 'pass' | |
| [case testClassDefIsNotTreatedAsEmpty] | |
| # cmd: mypy --html-report report n.py | |
| [file n.py] | |
| class A(object): | |
| pass # line indented with tab; hex 1f here: () | |
| [file report/mypy-html.css] | |
| [file report/index.html] | |
| [outfile report/html/n.py.html] | |
| <html> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <link rel="stylesheet" type="text/css" href="../mypy-html.css"> | |
| </head> | |
| <body> | |
| <h2>n</h2> | |
| <table> | |
| <caption>n.py</caption> | |
| <tbody><tr> | |
| <td class="table-lines"><pre><span id="L1" class="lineno"><a class="lineno" href="#L1">1</a></span> | |
| <span id="L2" class="lineno"><a class="lineno" href="#L2">2</a></span> | |
| </pre></td> | |
| <td class="table-code"><pre><span class="line-precise" title="No Anys on this line!">class A(object):</span> | |
| <span class="line-precise" title="No Anys on this line!"> pass # line indented with tab; hex 1f here: (?)</span> | |
| </pre></td> | |
| </tr></tbody> | |
| </table> | |
| </body> | |
| </html> | |
| [case testNoCrashRecursiveAliasInReport] | |
| # cmd: mypy --any-exprs-report report n.py | |
| [file n.py] | |
| from typing import Union, List, Any, TypeVar | |
| Nested = List[Union[Any, Nested]] | |
| T = TypeVar("T") | |
| NestedGen = List[Union[T, NestedGen[T]]] | |
| x: Nested | |
| y: NestedGen[int] | |
| z: NestedGen[Any] | |
| [file report/any-exprs.txt] | |
| [outfile report/types-of-anys.txt] | |
| Name Unannotated Explicit Unimported Omitted Generics Error Special Form Implementation Artifact | |
| ----------------------------------------------------------------------------------------------------------------- | |
| n 0 2 0 8 0 0 0 | |
| ----------------------------------------------------------------------------------------------------------------- | |
| Total 0 2 0 8 0 0 0 | |
| [case testTypeVarTreatedAsEmptyLine] | |
| # cmd: mypy --html-report report n.py | |
| [file n.py] | |
| from typing import TypeVar | |
| T = TypeVar('T') | |
| [file report/mypy-html.css] | |
| [file report/index.html] | |
| [outfile report/html/n.py.html] | |
| <html> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <link rel="stylesheet" type="text/css" href="../mypy-html.css"> | |
| </head> | |
| <body> | |
| <h2>n</h2> | |
| <table> | |
| <caption>n.py</caption> | |
| <tbody><tr> | |
| <td class="table-lines"><pre><span id="L1" class="lineno"><a class="lineno" href="#L1">1</a></span> | |
| <span id="L2" class="lineno"><a class="lineno" href="#L2">2</a></span> | |
| <span id="L3" class="lineno"><a class="lineno" href="#L3">3</a></span> | |
| </pre></td> | |
| <td class="table-code"><pre><span class="line-precise" title="No Anys on this line!">from typing import TypeVar</span> | |
| <span class="line-empty" title="No Anys on this line!"></span> | |
| <span class="line-empty" title="No Anys on this line!">T = TypeVar('T')</span> | |
| </pre></td> | |
| </tr></tbody> | |
| </table> | |
| </body> | |
| </html> | |
| [case testUnreachableCodeMarkedAsAny] | |
| # cmd: mypy --html-report report n.py | |
| [file any.py] | |
| from typing import Any | |
| def any_f(x: Any) -> None: | |
| pass | |
| [file n.py] | |
| from any import any_f | |
| def bar(x): | |
| # type: (str) -> None | |
| any_f(x) | |
| assert False | |
| any_f(x) | |
| [file report/mypy-html.css] | |
| [file report/index.html] | |
| [outfile report/html/n.py.html] | |
| <html> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <link rel="stylesheet" type="text/css" href="../mypy-html.css"> | |
| </head> | |
| <body> | |
| <h2>n</h2> | |
| <table> | |
| <caption>n.py</caption> | |
| <tbody><tr> | |
| <td class="table-lines"><pre><span id="L1" class="lineno"><a class="lineno" href="#L1">1</a></span> | |
| <span id="L2" class="lineno"><a class="lineno" href="#L2">2</a></span> | |
| <span id="L3" class="lineno"><a class="lineno" href="#L3">3</a></span> | |
| <span id="L4" class="lineno"><a class="lineno" href="#L4">4</a></span> | |
| <span id="L5" class="lineno"><a class="lineno" href="#L5">5</a></span> | |
| <span id="L6" class="lineno"><a class="lineno" href="#L6">6</a></span> | |
| </pre></td> | |
| <td class="table-code"><pre><span class="line-precise" title="No Anys on this line!">from any import any_f</span> | |
| <span class="line-precise" title="No Anys on this line!">def bar(x):</span> | |
| <span class="line-empty" title="No Anys on this line!"> # type: (str) -> None</span> | |
| <span class="line-any" title="Any Types on this line: | |
| Explicit (x1)"> any_f(x)</span> | |
| <span class="line-precise" title="No Anys on this line!"> assert False</span> | |
| <span class="line-unanalyzed" title="No Anys on this line!"> any_f(x)</span> | |
| </pre></td> | |
| </tr></tbody> | |
| </table> | |
| </body> | |
| </html> | |
| [case testHtmlReportMemberExprNoUnanalyzed] | |
| # cmd: mypy --html-report report n.py | |
| [file n.py] | |
| import sys | |
| old_stdout = sys.stdout | |
| [file report/mypy-html.css] | |
| [file report/index.html] | |
| [outfile report/html/n.py.html] | |
| <html> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <link rel="stylesheet" type="text/css" href="../mypy-html.css"> | |
| </head> | |
| <body> | |
| <h2>n</h2> | |
| <table> | |
| <caption>n.py</caption> | |
| <tbody><tr> | |
| <td class="table-lines"><pre><span id="L1" class="lineno"><a class="lineno" href="#L1">1</a></span> | |
| <span id="L2" class="lineno"><a class="lineno" href="#L2">2</a></span> | |
| <span id="L3" class="lineno"><a class="lineno" href="#L3">3</a></span> | |
| </pre></td> | |
| <td class="table-code"><pre><span class="line-precise" title="No Anys on this line!">import sys</span> | |
| <span class="line-empty" title="No Anys on this line!"></span> | |
| <span class="line-precise" title="No Anys on this line!">old_stdout = sys.stdout</span> | |
| </pre></td> | |
| </tr></tbody> | |
| </table> | |
| </body> | |
| </html> | |
| [case testAnyExprReportIncludesDeadCode] | |
| # cmd: mypy --any-exprs-report report i.py j.py | |
| [file i.py] | |
| def bar(x): | |
| # type: (str) -> None | |
| print(x) | |
| assert False | |
| print(x) # dead code! | |
| [file j.py] | |
| def bar(x): | |
| # type: (str) -> None | |
| print(x) | |
| assert False | |
| [file report/types-of-anys.txt] | |
| [outfile report/any-exprs.txt] | |
| Name Anys Exprs Coverage | |
| --------------------------------- | |
| i 1 6 83.33% | |
| j 0 5 100.00% | |
| --------------------------------- | |
| Total 1 11 90.91% | |
| [case testAnyExprReportHigherKindedTypesAreNotAny] | |
| # cmd: mypy --any-exprs-report report i.py | |
| [file i.py] | |
| from enum import Enum | |
| from typing import NewType, NamedTuple, TypedDict, TypeVar | |
| T = TypeVar('T') # no error | |
| def f(t: T) -> T: | |
| return t | |
| Point = NamedTuple('Point', [('x', int), ('y', int)]) # no error | |
| def origin() -> Point: | |
| return Point(x=0, y=0) | |
| NT = NewType('NT', int) # no error | |
| def nt() -> NT: | |
| return NT(1) | |
| E = Enum('E', '1, 2, 3') # no error | |
| def k(s: E) -> None: pass | |
| Movie = TypedDict('Movie', {'name': str, 'year': int}) | |
| def g(m: Movie) -> Movie: | |
| return m | |
| [file report/types-of-anys.txt] | |
| [outfile report/any-exprs.txt] | |
| Name Anys Exprs Coverage | |
| --------------------------------- | |
| i 0 14 100.00% | |
| --------------------------------- | |
| Total 0 14 100.00% | |
| [case testAnyExpressionsReportTypesOfAny] | |
| # cmd: mypy --any-exprs-report report n.py | |
| [file n.py] | |
| from typing import Any, List | |
| from nonexistent import C # type: ignore | |
| def any_f(x: Any) -> None: # Explicit | |
| pass | |
| def a(x) -> None: # Unannotated | |
| any_f(x) | |
| x: Any = 2 # Explicit | |
| y: C = None # Unimported | |
| def b() -> List: # Omitted Generics | |
| return [1, 2, 3] | |
| g = 1 | |
| z = g.does_not_exist() # type: ignore # Error | |
| [file report/any-exprs.txt] | |
| [outfile report/types-of-anys.txt] | |
| Name Unannotated Explicit Unimported Omitted Generics Error Special Form Implementation Artifact | |
| ----------------------------------------------------------------------------------------------------------------- | |
| n 2 3 1 1 3 0 0 | |
| ----------------------------------------------------------------------------------------------------------------- | |
| Total 2 3 1 1 3 0 0 | |
| [case testAnyExpressionsReportUnqualifiedError] | |
| # cmd: mypy --any-exprs-report report n.py | |
| [file n.py] | |
| z = does_not_exist() # type: ignore # Error | |
| [file report/any-exprs.txt] | |
| [outfile report/types-of-anys.txt] | |
| Name Unannotated Explicit Unimported Omitted Generics Error Special Form Implementation Artifact | |
| ----------------------------------------------------------------------------------------------------------------- | |
| n 0 0 0 0 3 0 0 | |
| ----------------------------------------------------------------------------------------------------------------- | |
| Total 0 0 0 0 3 0 0 | |
| [case testAnyExpressionsReportUntypedDef] | |
| # cmd: mypy --any-exprs-report report n.py | |
| [file n.py] | |
| def foo(): | |
| x = 0 | |
| f = 0 | |
| [file report/any-exprs.txt] | |
| [outfile report/types-of-anys.txt] | |
| Name Unannotated Explicit Unimported Omitted Generics Error Special Form Implementation Artifact | |
| ----------------------------------------------------------------------------------------------------------------- | |
| n 0 0 0 0 0 0 0 | |
| ----------------------------------------------------------------------------------------------------------------- | |
| Total 0 0 0 0 0 0 0 | |
| [case testTrickyCoverage] | |
| # cmd: mypy --linecoverage-report=report n.py | |
| [file n.py] | |
| def blah(x): return x | |
| @blah | |
| def f(x: int) -> None: pass | |
| class Foo: | |
| @blah | |
| #hi | |
| def f(self, x: int) -> None: | |
| pass | |
| @blah | |
| 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 | |
| [case testAnyExprReportIgnoresSpecialForms] | |
| # cmd: mypy --any-exprs-report report i.py j.py k.py l.py | |
| [file i.py] | |
| async def some_function() -> None: | |
| pass | |
| [file j.py] | |
| from typing import Any | |
| async def some_function() -> Any: | |
| pass | |
| [file k.py] | |
| from typing import NamedTuple | |
| def a() -> None: | |
| _FuzzyMatch(0, 0) | |
| _FuzzyMatch = NamedTuple('_FuzzyMatch', [ | |
| ('match_length', int), | |
| ('start_pos', int), | |
| ]) | |
| def b() -> None: | |
| _FuzzyMatch(0, 0) | |
| [file l.py] | |
| async def some_function(x) -> None: | |
| pass | |
| [file report/any-exprs.txt] | |
| [outfile report/types-of-anys.txt] | |
| Name Unannotated Explicit Unimported Omitted Generics Error Special Form Implementation Artifact | |
| ----------------------------------------------------------------------------------------------------------------- | |
| i 0 0 0 0 0 0 0 | |
| j 0 1 0 0 0 0 0 | |
| k 0 0 0 0 0 0 0 | |
| l 1 0 0 0 0 0 0 | |
| ----------------------------------------------------------------------------------------------------------------- | |
| Total 1 1 0 0 0 0 0 | |
| [case testSpecialAnyHtmlReport] | |
| # cmd: mypy --html-report report n.py | |
| [file n.py] | |
| from typing import Callable | |
| SourceToDisplay = Callable[[int], int] | |
| DisplayToSource = Callable[[int], int] | |
| [file report/mypy-html.css] | |
| [file report/index.html] | |
| [outfile report/html/n.py.html] | |
| <html> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <link rel="stylesheet" type="text/css" href="../mypy-html.css"> | |
| </head> | |
| <body> | |
| <h2>n</h2> | |
| <table> | |
| <caption>n.py</caption> | |
| <tbody><tr> | |
| <td class="table-lines"><pre><span id="L1" class="lineno"><a class="lineno" href="#L1">1</a></span> | |
| <span id="L2" class="lineno"><a class="lineno" href="#L2">2</a></span> | |
| <span id="L3" class="lineno"><a class="lineno" href="#L3">3</a></span> | |
| <span id="L4" class="lineno"><a class="lineno" href="#L4">4</a></span> | |
| </pre></td> | |
| <td class="table-code"><pre><span class="line-precise" title="No Anys on this line!">from typing import Callable</span> | |
| <span class="line-empty" title="No Anys on this line!"></span> | |
| <span class="line-precise" title="No Anys on this line!">SourceToDisplay = Callable[[int], int]</span> | |
| <span class="line-precise" title="No Anys on this line!">DisplayToSource = Callable[[int], int]</span> | |
| </pre></td> | |
| </tr></tbody> | |
| </table> | |
| </body> | |
| </html> | |
| [case testHtmlReportOnNamespacePackagesWithExplicitBases] | |
| # cmd: mypy --html-report report -p folder | |
| [file folder/subfolder/something.py] | |
| class Something: | |
| pass | |
| [file folder/main.py] | |
| from .subfolder.something import Something | |
| print(Something()) | |
| [file folder/__init__.py] | |
| [file mypy.ini] | |
| \[mypy] | |
| explicit_package_bases = True | |
| namespace_packages = True | |
| [file report/mypy-html.css] | |
| [file report/index.html] | |
| [outfile report/html/folder/subfolder/something.py.html] | |
| <html> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <link rel="stylesheet" type="text/css" href="../../../mypy-html.css"> | |
| </head> | |
| <body> | |
| <h2>folder.subfolder.something</h2> | |
| <table> | |
| <caption>folder/subfolder/something.py</caption> | |
| <tbody><tr> | |
| <td class="table-lines"><pre><span id="L1" class="lineno"><a class="lineno" href="#L1">1</a></span> | |
| <span id="L2" class="lineno"><a class="lineno" href="#L2">2</a></span> | |
| </pre></td> | |
| <td class="table-code"><pre><span class="line-precise" title="No Anys on this line!">class Something:</span> | |
| <span class="line-precise" title="No Anys on this line!"> pass</span> | |
| </pre></td> | |
| </tr></tbody> | |
| </table> | |
| </body> | |
| </html> | |
| [case testLinecountReportCrashOnNamespacePackages] | |
| # cmd: mypy --linecount-report report -p folder | |
| -- Regression test for https://github.com/python/mypy/issues/15979 | |
| [file folder/subfolder/something.py] | |
| class Something: | |
| pass | |
| [case testReportIsADirectoryErrorCrashOnNamespacePackages] | |
| # cmd: mypy --linecoverage-report report -p folder | |
| -- Regression test for https://github.com/python/mypy/issues/18128 | |
| -- "IsADirectoryError for namespace packages when using --linecoverage-report" | |
| [file folder/subfolder/something.py] | |
| class Something: | |
| pass | |
| [case testReportCoberturaCrashOnNamespacePackages] | |
| # cmd: mypy --cobertura-xml-report report -p folder | |
| -- Regression test for https://github.com/python/mypy/issues/19843 | |
| [file folder/subfolder/something.py] | |
| -- This output is not important, but due to the way tests are run we need to check it. | |
| [outfile report/cobertura.xml] | |
| <coverage timestamp="$TIMESTAMP" version="$VERSION" line-rate="1.0" branch-rate="0" lines-covered="0" lines-valid="0"> | |
| <sources> | |
| <source>$PWD</source> | |
| </sources> | |
| <packages> | |
| <package complexity="1.0" name="folder" branch-rate="0" line-rate="1.0"> | |
| <classes> | |
| <class complexity="1.0" filename="folder" name="folder" branch-rate="0" line-rate="1.0"> | |
| <methods/> | |
| <lines/> | |
| </class> | |
| <class complexity="1.0" filename="folder/subfolder" name="subfolder" branch-rate="0" line-rate="1.0"> | |
| <methods/> | |
| <lines/> | |
| </class> | |
| </classes> | |
| </package> | |
| <package complexity="1.0" name="folder.subfolder" branch-rate="0" line-rate="1.0"> | |
| <classes> | |
| <class complexity="1.0" filename="folder/subfolder/something.py" name="something.py" branch-rate="0" line-rate="1.0"> | |
| <methods/> | |
| <lines/> | |
| </class> | |
| </classes> | |
| </package> | |
| </packages> | |
| </coverage> |