Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add --ignore-overloaded-functions flag to ignore overload decorators #98

Merged
merged 3 commits into from
Apr 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.*"]
Expand Down Expand Up @@ -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.*
Expand Down Expand Up @@ -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]
Expand Down
5 changes: 3 additions & 2 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ Changelog
Added
^^^^^

- Support for Python 3.11 & 3.12.
* Add ``--ignore-overloaded-functions`` flag to ignore overload decorators (`#97 <https://github.com/econchick/interrogate/issues/97>`_).
* Support for Python 3.11 & 3.12.

Removed
^^^^^^^

- Support for Python 3.6 & 3.7.
-*Support for Python 3.6 & 3.7.

.. short-log

Expand Down
4 changes: 4 additions & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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``]
Expand Down
10 changes: 10 additions & 0 deletions src/interrogate/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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"],
Expand Down
3 changes: 3 additions & 0 deletions src/interrogate/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)

Expand Down
23 changes: 23 additions & 0 deletions src/interrogate/visit.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,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__"
Expand All @@ -192,6 +212,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
Expand All @@ -201,6 +222,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)

Expand Down
6 changes: 3 additions & 3 deletions tests/functional/fixtures/expected_badge.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
86 changes: 49 additions & 37 deletions tests/functional/fixtures/expected_detailed.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
|------------------------------------------------------------------|-----------|
Expand Down
Loading
Loading