From dc52dc90eb149f73377e6311d62b32be68c60fe6 Mon Sep 17 00:00:00 2001 From: Erwin Junge Date: Fri, 17 Dec 2021 12:00:07 +0100 Subject: [PATCH 1/2] Add `--ignore-overloaded-functions` flag to ignore overload decorators --- README.rst | 6 ++ docs/changelog.rst | 9 ++ docs/index.rst | 4 + src/interrogate/cli.py | 10 +++ src/interrogate/config.py | 3 + src/interrogate/visit.py | 23 +++++ tests/functional/fixtures/expected_badge.svg | 6 +- .../functional/fixtures/expected_detailed.txt | 86 +++++++++++-------- .../fixtures/expected_detailed_no_module.txt | 86 +++++++++++-------- .../expected_detailed_single_file.txt | 44 ++++++---- .../expected_detailed_skip_covered.txt | 46 +++++----- .../fixtures/expected_no_verbosity.txt | 2 +- .../functional/fixtures/expected_summary.txt | 6 +- .../fixtures/expected_summary_no_module.txt | 8 +- .../expected_summary_skip_covered.txt | 4 +- .../expected_summary_skip_covered_all.txt | 2 +- tests/functional/sample/full.py | 31 +++++++ tests/functional/sample/partial.py | 27 ++++++ tests/functional/test_cli.py | 67 ++++++++------- tests/functional/test_coverage.py | 22 ++++- 20 files changed, 329 insertions(+), 163 deletions(-) diff --git a/README.rst b/README.rst index ff269a4..ced67bd 100644 --- a/README.rst +++ b/README.rst @@ -359,6 +359,7 @@ Configure within your ``pyproject.toml`` (``interrogate`` will automatically det ignore-nested-functions = false ignore-nested-classes = true ignore-setters = false + ignore-overloaded-functions = false fail-under = 95 exclude = ["setup.py", "docs", "build"] ignore-regex = ["^get$", "^mock_.*", ".*BaseClass.*"] @@ -391,6 +392,7 @@ Or configure within your ``setup.cfg`` (``interrogate`` will automatically detec ignore-nested-functions = false ignore-nested-classes = true ignore-setters = false + ignore-overloaded-functions = false fail-under = 95 exclude = setup.py,docs,build ignore-regex = ^get$,^mock_.*,.*BaseClass.* @@ -498,6 +500,10 @@ To view all options available, run ``interrogate --help``: -C, --ignore-nested-classes Ignore nested classes. [default: False] + -O, --ignore-overloaded-functions + Ignore `@typing.overload`-decorated functions. + [default: False] + -p, --ignore-private Ignore private classes, methods, and functions starting with two underscores. [default: False] diff --git a/docs/changelog.rst b/docs/changelog.rst index 66f40fc..cf18734 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -3,6 +3,15 @@ Changelog .. short-log +1.6.0 (UNRELEASED) +------------------ + +Added +^^^^^ + +* Add ``--ignore-overloaded-functions`` flag to ignore overload decorators (`#97 `_). + + 1.5.0 (2021-09-10) ------------------ diff --git a/docs/index.rst b/docs/index.rst index 3cc8dfc..d83833c 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -68,6 +68,10 @@ Command Line Options Ignore nested classes. [default: ``False``] +.. option:: -O, --ignore-overloaded-functions + + Ignore `@typing.overload`-decorated functions. [default: ``False``] + .. option:: -p, --ignore-private Ignore private classes, methods, and functions starting with two underscores. [default: ``False``] diff --git a/src/interrogate/cli.py b/src/interrogate/cli.py index 1676fba..de88712 100644 --- a/src/interrogate/cli.py +++ b/src/interrogate/cli.py @@ -116,6 +116,14 @@ show_default=True, help="Ignore nested classes.", ) +@click.option( + "-O", + "--ignore-overloaded-functions", + is_flag=True, + default=False, + show_default=True, + help="Ignore `@typing.overload`-decorated functions.", +) @click.option( "-p", "--ignore-private", @@ -301,6 +309,7 @@ def main(ctx, paths, **kwargs): .. versionadded:: 1.4.0 ``--ignore-setters`` .. versionadded:: 1.5.0 ``--omit-covered-files`` .. versionadded:: 1.5.0 ``--badge-style`` + .. versionadded:: 1.6.0 ``--ignore-overloaded-functions`` .. versionchanged:: 1.3.1 only generate badge if results change from an existing badge. @@ -339,6 +348,7 @@ def main(ctx, paths, **kwargs): ignore_init_module=kwargs["ignore_init_module"], ignore_nested_classes=kwargs["ignore_nested_classes"], ignore_nested_functions=kwargs["ignore_nested_functions"], + ignore_overloaded_functions=kwargs["ignore_overloaded_functions"], ignore_property_setters=kwargs["ignore_setters"], ignore_property_decorators=kwargs["ignore_property_decorators"], include_regex=kwargs["whitelist_regex"], diff --git a/src/interrogate/config.py b/src/interrogate/config.py index 250f8d2..67ca602 100644 --- a/src/interrogate/config.py +++ b/src/interrogate/config.py @@ -39,6 +39,8 @@ class InterrogateConfig: function names to include. :param bool omit_covered_files: Omit reporting files that have 100% documentation coverage. + :param bool ignore_overloaded_functions: Ignore `@typing.overload`-decorated + functions. """ color = attr.ib(default=False) @@ -54,6 +56,7 @@ class InterrogateConfig: ignore_nested_functions = attr.ib(default=False) ignore_property_setters = attr.ib(default=False) ignore_property_decorators = attr.ib(default=False) + ignore_overloaded_functions = attr.ib(default=False) include_regex = attr.ib(default=False) omit_covered_files = attr.ib(default=False) diff --git a/src/interrogate/visit.py b/src/interrogate/visit.py index b644769..787a4f9 100644 --- a/src/interrogate/visit.py +++ b/src/interrogate/visit.py @@ -190,6 +190,26 @@ def _has_setters(self, node): return True return False + def _has_overload_decorator(self, node): + """Detect if node has a typing.overload decorator.""" + if not hasattr(node, "decorator_list"): + return False + + for dec in node.decorator_list: + if ( + hasattr(dec, "attr") + and hasattr(dec, "value") + and hasattr(dec.value, "id") + and dec.value.id == "typing" + and dec.attr == "overload" + ): + # @typing.overload decorator + return True + if hasattr(dec, "id") and dec.id == "overload": + # @overload decorator + return True + return False + def _is_func_ignored(self, node): """Should the AST visitor ignore this func/method node.""" is_init = node.name == "__init__" @@ -202,6 +222,7 @@ def _is_func_ignored(self, node): ) has_property_decorators = self._has_property_decorators(node) has_setters = self._has_setters(node) + has_overload = self._has_overload_decorator(node) if self.config.ignore_init_method and is_init: return True @@ -211,6 +232,8 @@ def _is_func_ignored(self, node): return True if self.config.ignore_property_setters and has_setters: return True + if self.config.ignore_overloaded_functions and has_overload: + return True return self._is_ignored_common(node) diff --git a/tests/functional/fixtures/expected_badge.svg b/tests/functional/fixtures/expected_badge.svg index a112304..01bcf72 100644 --- a/tests/functional/fixtures/expected_badge.svg +++ b/tests/functional/fixtures/expected_badge.svg @@ -1,5 +1,5 @@ - interrogate: 46.4% + interrogate: 50.0% @@ -12,8 +12,8 @@ interrogate interrogate - 46.4% - 46.4% + 50.0% + 50.0% diff --git a/tests/functional/fixtures/expected_detailed.txt b/tests/functional/fixtures/expected_detailed.txt index ac3aa99..a8456df 100644 --- a/tests/functional/fixtures/expected_detailed.txt +++ b/tests/functional/fixtures/expected_detailed.txt @@ -6,46 +6,58 @@ | empty.py (module) | MISSED | |------------------------------------------------------------------|-----------| | full.py (module) | COVERED | -| Foo (L5) | COVERED | -| Foo.__init__ (L8) | COVERED | -| Foo.__str__ (L12) | COVERED | -| Foo._semiprivate (L16) | COVERED | -| Foo.__private (L20) | COVERED | -| Foo.method_foo (L24) | COVERED | -| Foo.get (L28) | COVERED | -| Foo.get (L32) | COVERED | -| Foo.prop (L37) | COVERED | -| Foo.prop (L42) | COVERED | -| top_level_func (L47) | COVERED | -| top_level_func.inner_func (L50) | COVERED | -| Bar (L55) | COVERED | -| Bar.method_bar (L58) | COVERED | -| Bar.method_bar.InnerBar (L61) | COVERED | -| _SemiprivateClass (L67) | COVERED | -| __PrivateClass (L73) | COVERED | +| Foo (L8) | COVERED | +| Foo.__init__ (L11) | COVERED | +| Foo.__str__ (L15) | COVERED | +| Foo._semiprivate (L19) | COVERED | +| Foo.__private (L23) | COVERED | +| Foo.method_foo (L27) | COVERED | +| Foo.get (L31) | COVERED | +| Foo.get (L35) | COVERED | +| Foo.prop (L40) | COVERED | +| Foo.prop (L45) | COVERED | +| Foo.module_overload (L50) | COVERED | +| Foo.module_overload (L55) | COVERED | +| Foo.module_overload (L59) | COVERED | +| Foo.simple_overload (L64) | COVERED | +| Foo.simple_overload (L69) | COVERED | +| Foo.simple_overload (L73) | COVERED | +| top_level_func (L78) | COVERED | +| top_level_func.inner_func (L81) | COVERED | +| Bar (L86) | COVERED | +| Bar.method_bar (L89) | COVERED | +| Bar.method_bar.InnerBar (L92) | COVERED | +| _SemiprivateClass (L98) | COVERED | +| __PrivateClass (L104) | COVERED | |------------------------------------------------------------------|-----------| | partial.py (module) | COVERED | -| Foo (L5) | COVERED | -| Foo.__init__ (L8) | COVERED | -| Foo.__str__ (L12) | COVERED | -| Foo.__repr__ (L16) | MISSED | -| Foo._semiprivate_documented (L19) | COVERED | -| Foo._semiprivate_undocumented (L23) | MISSED | -| Foo.__private (L26) | MISSED | -| Foo.method_foo (L29) | MISSED | -| Foo.get (L32) | MISSED | +| Foo (L8) | COVERED | +| Foo.__init__ (L11) | COVERED | +| Foo.__str__ (L15) | COVERED | +| Foo.__repr__ (L19) | MISSED | +| Foo._semiprivate_documented (L22) | COVERED | +| Foo._semiprivate_undocumented (L26) | MISSED | +| Foo.__private (L29) | MISSED | +| Foo.method_foo (L32) | MISSED | | Foo.get (L35) | MISSED | -| Foo.a_prop (L39) | MISSED | -| Foo.a_prop (L43) | MISSED | -| documented_top_level_func (L47) | COVERED | -| documented_top_level_func.documented_inner_func (L50) | COVERED | -| undocumented_top_level_func (L55) | MISSED | -| undocumented_top_level_func.undocumented_inner_func (L56) | MISSED | -| Bar (L60) | MISSED | -| Bar.method_bar (L61) | MISSED | -| Bar.method_bar.InnerBar (L62) | MISSED | -| _SemiprivateClass (L66) | MISSED | -| __PrivateClass (L70) | MISSED | +| Foo.get (L38) | MISSED | +| Foo.a_prop (L42) | MISSED | +| Foo.a_prop (L46) | MISSED | +| Foo.module_overload (L50) | MISSED | +| Foo.module_overload (L54) | MISSED | +| Foo.module_overload (L57) | COVERED | +| Foo.simple_overload (L62) | MISSED | +| Foo.simple_overload (L66) | MISSED | +| Foo.simple_overload (L69) | COVERED | +| documented_top_level_func (L74) | COVERED | +| documented_top_level_func.documented_inner_func (L77) | COVERED | +| undocumented_top_level_func (L82) | MISSED | +| undocumented_top_level_func.undocumented_inner_func (L83) | MISSED | +| Bar (L87) | MISSED | +| Bar.method_bar (L88) | MISSED | +| Bar.method_bar.InnerBar (L89) | MISSED | +| _SemiprivateClass (L93) | MISSED | +| __PrivateClass (L97) | MISSED | |------------------------------------------------------------------|-----------| | child_sample/__init__.py (module) | MISSED | |------------------------------------------------------------------|-----------| diff --git a/tests/functional/fixtures/expected_detailed_no_module.txt b/tests/functional/fixtures/expected_detailed_no_module.txt index 5bf7dd7..e3dd5f3 100644 --- a/tests/functional/fixtures/expected_detailed_no_module.txt +++ b/tests/functional/fixtures/expected_detailed_no_module.txt @@ -2,46 +2,58 @@ | Name | Status | |------------------------------------------------------------------|-----------| | full.py | | -| Foo (L5) | COVERED | -| Foo.__init__ (L8) | COVERED | -| Foo.__str__ (L12) | COVERED | -| Foo._semiprivate (L16) | COVERED | -| Foo.__private (L20) | COVERED | -| Foo.method_foo (L24) | COVERED | -| Foo.get (L28) | COVERED | -| Foo.get (L32) | COVERED | -| Foo.prop (L37) | COVERED | -| Foo.prop (L42) | COVERED | -| top_level_func (L47) | COVERED | -| top_level_func.inner_func (L50) | COVERED | -| Bar (L55) | COVERED | -| Bar.method_bar (L58) | COVERED | -| Bar.method_bar.InnerBar (L61) | COVERED | -| _SemiprivateClass (L67) | COVERED | -| __PrivateClass (L73) | COVERED | +| Foo (L8) | COVERED | +| Foo.__init__ (L11) | COVERED | +| Foo.__str__ (L15) | COVERED | +| Foo._semiprivate (L19) | COVERED | +| Foo.__private (L23) | COVERED | +| Foo.method_foo (L27) | COVERED | +| Foo.get (L31) | COVERED | +| Foo.get (L35) | COVERED | +| Foo.prop (L40) | COVERED | +| Foo.prop (L45) | COVERED | +| Foo.module_overload (L50) | COVERED | +| Foo.module_overload (L55) | COVERED | +| Foo.module_overload (L59) | COVERED | +| Foo.simple_overload (L64) | COVERED | +| Foo.simple_overload (L69) | COVERED | +| Foo.simple_overload (L73) | COVERED | +| top_level_func (L78) | COVERED | +| top_level_func.inner_func (L81) | COVERED | +| Bar (L86) | COVERED | +| Bar.method_bar (L89) | COVERED | +| Bar.method_bar.InnerBar (L92) | COVERED | +| _SemiprivateClass (L98) | COVERED | +| __PrivateClass (L104) | COVERED | |------------------------------------------------------------------|-----------| | partial.py | | -| Foo (L5) | COVERED | -| Foo.__init__ (L8) | COVERED | -| Foo.__str__ (L12) | COVERED | -| Foo.__repr__ (L16) | MISSED | -| Foo._semiprivate_documented (L19) | COVERED | -| Foo._semiprivate_undocumented (L23) | MISSED | -| Foo.__private (L26) | MISSED | -| Foo.method_foo (L29) | MISSED | -| Foo.get (L32) | MISSED | +| Foo (L8) | COVERED | +| Foo.__init__ (L11) | COVERED | +| Foo.__str__ (L15) | COVERED | +| Foo.__repr__ (L19) | MISSED | +| Foo._semiprivate_documented (L22) | COVERED | +| Foo._semiprivate_undocumented (L26) | MISSED | +| Foo.__private (L29) | MISSED | +| Foo.method_foo (L32) | MISSED | | Foo.get (L35) | MISSED | -| Foo.a_prop (L39) | MISSED | -| Foo.a_prop (L43) | MISSED | -| documented_top_level_func (L47) | COVERED | -| documented_top_level_func.documented_inner_func (L50) | COVERED | -| undocumented_top_level_func (L55) | MISSED | -| undocumented_top_level_func.undocumented_inner_func (L56) | MISSED | -| Bar (L60) | MISSED | -| Bar.method_bar (L61) | MISSED | -| Bar.method_bar.InnerBar (L62) | MISSED | -| _SemiprivateClass (L66) | MISSED | -| __PrivateClass (L70) | MISSED | +| Foo.get (L38) | MISSED | +| Foo.a_prop (L42) | MISSED | +| Foo.a_prop (L46) | MISSED | +| Foo.module_overload (L50) | MISSED | +| Foo.module_overload (L54) | MISSED | +| Foo.module_overload (L57) | COVERED | +| Foo.simple_overload (L62) | MISSED | +| Foo.simple_overload (L66) | MISSED | +| Foo.simple_overload (L69) | COVERED | +| documented_top_level_func (L74) | COVERED | +| documented_top_level_func.documented_inner_func (L77) | COVERED | +| undocumented_top_level_func (L82) | MISSED | +| undocumented_top_level_func.undocumented_inner_func (L83) | MISSED | +| Bar (L87) | MISSED | +| Bar.method_bar (L88) | MISSED | +| Bar.method_bar.InnerBar (L89) | MISSED | +| _SemiprivateClass (L93) | MISSED | +| __PrivateClass (L97) | MISSED | |------------------------------------------------------------------|-----------| | child_sample/child_sample_module.py | | | ChildFoo (L5) | MISSED | diff --git a/tests/functional/fixtures/expected_detailed_single_file.txt b/tests/functional/fixtures/expected_detailed_single_file.txt index 635a0c8..ffa74e0 100644 --- a/tests/functional/fixtures/expected_detailed_single_file.txt +++ b/tests/functional/fixtures/expected_detailed_single_file.txt @@ -2,29 +2,35 @@ | Name | Status | |-----------------------------------------------------|------------------------| | full.py (module) | COVERED | -| Foo (L5) | COVERED | -| Foo.__init__ (L8) | COVERED | -| Foo.__str__ (L12) | COVERED | -| Foo._semiprivate (L16) | COVERED | -| Foo.__private (L20) | COVERED | -| Foo.method_foo (L24) | COVERED | -| Foo.get (L28) | COVERED | -| Foo.get (L32) | COVERED | -| Foo.prop (L37) | COVERED | -| Foo.prop (L42) | COVERED | -| top_level_func (L47) | COVERED | -| top_level_func.inner_func (L50) | COVERED | -| Bar (L55) | COVERED | -| Bar.method_bar (L58) | COVERED | -| Bar.method_bar.InnerBar (L61) | COVERED | -| _SemiprivateClass (L67) | COVERED | -| __PrivateClass (L73) | COVERED | +| Foo (L8) | COVERED | +| Foo.__init__ (L11) | COVERED | +| Foo.__str__ (L15) | COVERED | +| Foo._semiprivate (L19) | COVERED | +| Foo.__private (L23) | COVERED | +| Foo.method_foo (L27) | COVERED | +| Foo.get (L31) | COVERED | +| Foo.get (L35) | COVERED | +| Foo.prop (L40) | COVERED | +| Foo.prop (L45) | COVERED | +| Foo.module_overload (L50) | COVERED | +| Foo.module_overload (L55) | COVERED | +| Foo.module_overload (L59) | COVERED | +| Foo.simple_overload (L64) | COVERED | +| Foo.simple_overload (L69) | COVERED | +| Foo.simple_overload (L73) | COVERED | +| top_level_func (L78) | COVERED | +| top_level_func.inner_func (L81) | COVERED | +| Bar (L86) | COVERED | +| Bar.method_bar (L89) | COVERED | +| Bar.method_bar.InnerBar (L92) | COVERED | +| _SemiprivateClass (L98) | COVERED | +| __PrivateClass (L104) | COVERED | |-----------------------------------------------------|------------------------| ----------------------------------- Summary ------------------------------------ | Name | Total | Miss | Cover | Cover% | |------------------|--------------|-------------|--------------|---------------| -| full.py | 18 | 0 | 18 | 100% | +| full.py | 24 | 0 | 24 | 100% | |------------------|--------------|-------------|--------------|---------------| -| TOTAL | 18 | 0 | 18 | 100.0% | +| TOTAL | 24 | 0 | 24 | 100.0% | --------------- RESULT: PASSED (minimum: 80.0%, actual: 100.0%) ---------------- diff --git a/tests/functional/fixtures/expected_detailed_skip_covered.txt b/tests/functional/fixtures/expected_detailed_skip_covered.txt index 8715070..0a3416a 100644 --- a/tests/functional/fixtures/expected_detailed_skip_covered.txt +++ b/tests/functional/fixtures/expected_detailed_skip_covered.txt @@ -4,27 +4,33 @@ | empty.py (module) | MISSED | |------------------------------------------------------------------|-----------| | partial.py (module) | COVERED | -| Foo (L5) | COVERED | -| Foo.__init__ (L8) | COVERED | -| Foo.__str__ (L12) | COVERED | -| Foo.__repr__ (L16) | MISSED | -| Foo._semiprivate_documented (L19) | COVERED | -| Foo._semiprivate_undocumented (L23) | MISSED | -| Foo.__private (L26) | MISSED | -| Foo.method_foo (L29) | MISSED | -| Foo.get (L32) | MISSED | +| Foo (L8) | COVERED | +| Foo.__init__ (L11) | COVERED | +| Foo.__str__ (L15) | COVERED | +| Foo.__repr__ (L19) | MISSED | +| Foo._semiprivate_documented (L22) | COVERED | +| Foo._semiprivate_undocumented (L26) | MISSED | +| Foo.__private (L29) | MISSED | +| Foo.method_foo (L32) | MISSED | | Foo.get (L35) | MISSED | -| Foo.a_prop (L39) | MISSED | -| Foo.a_prop (L43) | MISSED | -| documented_top_level_func (L47) | COVERED | -| documented_top_level_func.documented_inner_func (L50) | COVERED | -| undocumented_top_level_func (L55) | MISSED | -| undocumented_top_level_func.undocumented_inner_func (L56) | MISSED | -| Bar (L60) | MISSED | -| Bar.method_bar (L61) | MISSED | -| Bar.method_bar.InnerBar (L62) | MISSED | -| _SemiprivateClass (L66) | MISSED | -| __PrivateClass (L70) | MISSED | +| Foo.get (L38) | MISSED | +| Foo.a_prop (L42) | MISSED | +| Foo.a_prop (L46) | MISSED | +| Foo.module_overload (L50) | MISSED | +| Foo.module_overload (L54) | MISSED | +| Foo.module_overload (L57) | COVERED | +| Foo.simple_overload (L62) | MISSED | +| Foo.simple_overload (L66) | MISSED | +| Foo.simple_overload (L69) | COVERED | +| documented_top_level_func (L74) | COVERED | +| documented_top_level_func.documented_inner_func (L77) | COVERED | +| undocumented_top_level_func (L82) | MISSED | +| undocumented_top_level_func.undocumented_inner_func (L83) | MISSED | +| Bar (L87) | MISSED | +| Bar.method_bar (L88) | MISSED | +| Bar.method_bar.InnerBar (L89) | MISSED | +| _SemiprivateClass (L93) | MISSED | +| __PrivateClass (L97) | MISSED | |------------------------------------------------------------------|-----------| | child_sample/__init__.py (module) | MISSED | |------------------------------------------------------------------|-----------| diff --git a/tests/functional/fixtures/expected_no_verbosity.txt b/tests/functional/fixtures/expected_no_verbosity.txt index 05cfdf8..d071062 100644 --- a/tests/functional/fixtures/expected_no_verbosity.txt +++ b/tests/functional/fixtures/expected_no_verbosity.txt @@ -1 +1 @@ -RESULT: FAILED (minimum: 80.0%, actual: 46.4%) +RESULT: FAILED (minimum: 80.0%, actual: 50.0%) diff --git a/tests/functional/fixtures/expected_summary.txt b/tests/functional/fixtures/expected_summary.txt index bc5d37a..195bbe5 100644 --- a/tests/functional/fixtures/expected_summary.txt +++ b/tests/functional/fixtures/expected_summary.txt @@ -2,9 +2,9 @@ |------------------------------------------|--------|-------|--------|---------| | __init__.py | 1 | 0 | 1 | 100% | | empty.py | 1 | 1 | 0 | 0% | -| full.py | 18 | 0 | 18 | 100% | -| partial.py | 22 | 15 | 7 | 32% | +| full.py | 24 | 0 | 24 | 100% | +| partial.py | 28 | 19 | 9 | 32% | | child_sample/__init__.py | 1 | 1 | 0 | 0% | | child_sample/child_sample_module.py | 13 | 13 | 0 | 0% | |------------------------------------------|--------|-------|--------|---------| -| TOTAL | 56 | 30 | 26 | 46.4% | +| TOTAL | 68 | 34 | 34 | 50.0% | diff --git a/tests/functional/fixtures/expected_summary_no_module.txt b/tests/functional/fixtures/expected_summary_no_module.txt index 9267f16..aba814b 100644 --- a/tests/functional/fixtures/expected_summary_no_module.txt +++ b/tests/functional/fixtures/expected_summary_no_module.txt @@ -1,9 +1,9 @@ ----------------------------------- Summary ------------------------------------ | Name | Total | Miss | Cover | Cover% | |------------------------------------------|--------|-------|--------|---------| -| full.py | 17 | 0 | 17 | 100% | -| partial.py | 21 | 15 | 6 | 29% | +| full.py | 23 | 0 | 23 | 100% | +| partial.py | 27 | 19 | 8 | 30% | | child_sample/child_sample_module.py | 12 | 12 | 0 | 0% | |------------------------------------------|--------|-------|--------|---------| -| TOTAL | 50 | 27 | 23 | 46.0% | ----------------- RESULT: FAILED (minimum: 80.0%, actual: 46.0%) ---------------- +| TOTAL | 62 | 31 | 31 | 50.0% | +---------------- RESULT: FAILED (minimum: 80.0%, actual: 50.0%) ---------------- diff --git a/tests/functional/fixtures/expected_summary_skip_covered.txt b/tests/functional/fixtures/expected_summary_skip_covered.txt index f0b25ed..f8f8c22 100644 --- a/tests/functional/fixtures/expected_summary_skip_covered.txt +++ b/tests/functional/fixtures/expected_summary_skip_covered.txt @@ -1,10 +1,10 @@ | Name | Total | Miss | Cover | Cover% | |------------------------------------------|--------|-------|--------|---------| | empty.py | 1 | 1 | 0 | 0% | -| partial.py | 22 | 15 | 7 | 32% | +| partial.py | 28 | 19 | 9 | 32% | | child_sample/__init__.py | 1 | 1 | 0 | 0% | | child_sample/child_sample_module.py | 13 | 13 | 0 | 0% | |------------------------------------------|--------|-------|--------|---------| -| TOTAL | 56 | 30 | 26 | 46.4% | +| TOTAL | 68 | 34 | 34 | 50.0% | |------------------------------------------------------------------------------| | (2 of 6 files omitted due to complete coverage) | diff --git a/tests/functional/fixtures/expected_summary_skip_covered_all.txt b/tests/functional/fixtures/expected_summary_skip_covered_all.txt index 63b9823..01acd68 100644 --- a/tests/functional/fixtures/expected_summary_skip_covered_all.txt +++ b/tests/functional/fixtures/expected_summary_skip_covered_all.txt @@ -1,5 +1,5 @@ | Name | Total | Miss | Cover | Cover% | |------------------|--------------|-------------|--------------|---------------| -| TOTAL | 18 | 0 | 18 | 100.0% | +| TOTAL | 24 | 0 | 24 | 100.0% | |------------------------------------------------------------------------------| | (1 of 1 file omitted due to complete coverage) | diff --git a/tests/functional/sample/full.py b/tests/functional/sample/full.py index 25b8bee..ac01b70 100644 --- a/tests/functional/sample/full.py +++ b/tests/functional/sample/full.py @@ -1,5 +1,8 @@ # Copyright 2020 Lynn Root """Sample module-level docs""" +import typing + +from typing import overload class Foo(object): @@ -43,6 +46,34 @@ def prop(self): """this method has a set property decorator""" pass + @typing.overload + def module_overload(a: None) -> None: + """overloaded method""" + ... + + @typing.overload + def module_overload(a: int) -> int: + """overloaded method""" + ... + + def module_overload(a): + """overloaded method implementation""" + pass + + @overload + def simple_overload(a: None) -> None: + """overloaded method""" + ... + + @overload + def simple_overload(a: int) -> int: + """overloaded method""" + ... + + def simple_overload(a): + """overloaded method implementation""" + pass + def top_level_func(): """A top level function""" diff --git a/tests/functional/sample/partial.py b/tests/functional/sample/partial.py index 3784fb7..ee349e8 100644 --- a/tests/functional/sample/partial.py +++ b/tests/functional/sample/partial.py @@ -1,5 +1,8 @@ # Copyright 2020 Lynn Root """Sample module-level docs""" +import typing + +from typing import overload class Foo(object): @@ -43,6 +46,30 @@ def a_prop(self): def a_prop(self, x): pass + @typing.overload + def module_overload(a: None) -> None: + ... + + @typing.overload + def module_overload(a: int) -> int: + ... + + def module_overload(a): + """overloaded method implementation""" + pass + + @overload + def simple_overload(a: None) -> None: + ... + + @overload + def simple_overload(a: int) -> int: + ... + + def simple_overload(a): + """overloaded method implementation""" + pass + def documented_top_level_func(): """A documented top level function""" diff --git a/tests/functional/test_cli.py b/tests/functional/test_cli.py index 597b236..e9a3d92 100644 --- a/tests/functional/test_cli.py +++ b/tests/functional/test_cli.py @@ -33,7 +33,7 @@ def test_run_no_paths(runner, monkeypatch, tmpdir): result = runner.invoke(cli.main, []) - assert "actual: 46.4%" in result.output + assert "actual: 50.0%" in result.output assert 1 == result.exit_code @@ -41,37 +41,39 @@ def test_run_no_paths(runner, monkeypatch, tmpdir): "flags,exp_result,exp_exit_code", ( # no flags - ([], 46.4, 1), + ([], 50.0, 1), # ignore init module - (["-I"], 46.3, 1), + (["-I"], 50.0, 1), # ignore module docs - (["-M"], 46.0, 1), + (["-M"], 50.0, 1), # ignore semiprivate docs - (["-s"], 46.9, 1), + (["-s"], 50.8, 1), # ignore private docs - (["-p"], 48.0, 1), + (["-p"], 51.6, 1), # ignore property getter/setter decorators - (["-P"], 46.2, 1), + (["-P"], 50.0, 1), # ignore property setter decorators - (["-S"], 46.3, 1), + (["-S"], 50.0, 1), # ignore magic method docs - (["-m"], 46.2, 1), + (["-m"], 50.0, 1), # ignore init method docs - (["-i"], 45.3, 1), + (["-i"], 49.2, 1), # ignore nested funcs - (["-n"], 45.3, 1), + (["-n"], 49.2, 1), # ignore nested classes - (["-C"], 47.2, 1), + (["-C"], 50.8, 1), + # ignore @typing.overload-decorated functions + (["-O"], 50.0, 1), # ignore regex - (["-r", "^get$"], 46.2, 1), + (["-r", "^get$"], 50.0, 1), # whitelist regex (["-w", "^get$"], 50.0, 1), # exclude file - (["-e", os.path.join(SAMPLE_DIR, "partial.py")], 55.9, 1), + (["-e", os.path.join(SAMPLE_DIR, "partial.py")], 62.5, 1), # exclude file which doesn't exist - (["-e", os.path.join(SAMPLE_DIR, "does.not.exist")], 46.4, 1), + (["-e", os.path.join(SAMPLE_DIR, "does.not.exist")], 50.0, 1), # fail under - (["-f", "40"], 46.4, 0), + (["-f", "40"], 50.0, 0), ), ) def test_run_shortflags(flags, exp_result, exp_exit_code, runner): @@ -87,20 +89,21 @@ def test_run_shortflags(flags, exp_result, exp_exit_code, runner): @pytest.mark.parametrize( "flags,exp_result,exp_exit_code", ( - (["--ignore-init-module"], 46.3, 1), - (["--ignore-module"], 46.0, 1), - (["--ignore-semiprivate"], 46.9, 1), - (["--ignore-private"], 48.0, 1), - (["--ignore-property-decorators"], 46.2, 1), - (["--ignore-setters"], 46.3, 1), - (["--ignore-magic"], 46.2, 1), - (["--ignore-init-method"], 45.3, 1), - (["--ignore-nested-functions"], 45.3, 1), - (["--ignore-nested-classes"], 47.2, 1), - (["--ignore-regex", "^get$"], 46.2, 1), + (["--ignore-init-module"], 50.0, 1), + (["--ignore-module"], 50.0, 1), + (["--ignore-semiprivate"], 50.8, 1), + (["--ignore-private"], 51.6, 1), + (["--ignore-property-decorators"], 50.0, 1), + (["--ignore-setters"], 50.0, 1), + (["--ignore-magic"], 50.0, 1), + (["--ignore-init-method"], 49.2, 1), + (["--ignore-nested-functions"], 49.2, 1), + (["--ignore-nested-classes"], 50.8, 1), + (["--ignore-overloaded-functions"], 50.0, 1), + (["--ignore-regex", "^get$"], 50.0, 1), (["--whitelist-regex", "^get$"], 50.0, 1), - (["--exclude", os.path.join(SAMPLE_DIR, "partial.py")], 55.9, 1), - (["--fail-under", "40"], 46.4, 0), + (["--exclude", os.path.join(SAMPLE_DIR, "partial.py")], 62.5, 1), + (["--fail-under", "40"], 50.0, 0), ), ) def test_run_longflags(flags, exp_result, exp_exit_code, runner): @@ -116,9 +119,9 @@ def test_run_longflags(flags, exp_result, exp_exit_code, runner): @pytest.mark.parametrize( "flags,exp_result,exp_exit_code", ( - (["-i", "-I", "-r" "^method_foo$"], 45.8, 1), - (["-s", "-p", "-M"], 48.6, 1), - (["-m", "-f", "45"], 46.2, 0), + (["-i", "-I", "-r" "^method_foo$"], 50.0, 1), + (["-s", "-p", "-M"], 53.1, 1), + (["-m", "-f", "45"], 50.0, 0), ), ) def test_run_multiple_flags(flags, exp_result, exp_exit_code, runner): diff --git a/tests/functional/test_coverage.py b/tests/functional/test_coverage.py index 12132ca..caf6cbd 100644 --- a/tests/functional/test_coverage.py +++ b/tests/functional/test_coverage.py @@ -44,22 +44,36 @@ def patch_term_width(monkeypatch): SAMPLE_DIR, ], {}, - (56, 26, 30, "46.4"), + (68, 34, 34, "50.0"), ), - ([os.path.join(SAMPLE_DIR, "partial.py")], {}, (22, 7, 15, "31.8")), + ([os.path.join(SAMPLE_DIR, "partial.py")], {}, (28, 9, 19, "32.1")), ( [ os.path.join(SAMPLE_DIR, "full.py"), ], {"ignore_nested_functions": True}, - (17, 17, 0, "100.0"), + (23, 23, 0, "100.0"), ), ( [ os.path.join(SAMPLE_DIR, "partial.py"), ], {"ignore_nested_functions": True}, - (20, 6, 14, "30.0"), + (26, 8, 18, "30.8"), + ), + ( + [ + os.path.join(SAMPLE_DIR, "full.py"), + ], + {"ignore_overloaded_functions": True}, + (20, 20, 0, "100.0"), + ), + ( + [ + os.path.join(SAMPLE_DIR, "partial.py"), + ], + {"ignore_overloaded_functions": True}, + (24, 9, 15, "37.5"), ), ), ) From 61c34c75473e7ed9e6dc617c69e76fe01e13d30b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 6 Apr 2024 18:27:16 +0000 Subject: [PATCH 2/2] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/functional/sample/partial.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/tests/functional/sample/partial.py b/tests/functional/sample/partial.py index 2ef774f..f31d5f4 100644 --- a/tests/functional/sample/partial.py +++ b/tests/functional/sample/partial.py @@ -47,24 +47,20 @@ def a_prop(self, x): pass @typing.overload - def module_overload(a: None) -> None: - ... + def module_overload(a: None) -> None: ... @typing.overload - def module_overload(a: int) -> int: - ... + def module_overload(a: int) -> int: ... def module_overload(a): """overloaded method implementation""" pass @overload - def simple_overload(a: None) -> None: - ... + def simple_overload(a: None) -> None: ... @overload - def simple_overload(a: int) -> int: - ... + def simple_overload(a: int) -> int: ... def simple_overload(a): """overloaded method implementation"""