From c792609ed1f63722cb982b5b8bbd5f09c18c225c Mon Sep 17 00:00:00 2001 From: Ruben Horn <> Date: Fri, 21 Mar 2025 16:04:38 +0100 Subject: [PATCH] Added option --skip-mangled --- README.md | 2 ++ docstr_coverage/cli.py | 7 +++++++ docstr_coverage/coverage.py | 7 +++++++ docstr_coverage/ignore_config.py | 7 +++++++ docstr_coverage/printers.py | 8 ++++++++ tests/config_files/with_ignore.yml | 1 + tests/config_files/without_ignore.yml | 1 + tests/test_config_file.py | 2 ++ tests/test_coverage.py | 14 ++++++++++++++ 9 files changed, 49 insertions(+) diff --git a/README.md b/README.md index 1974a6e..33e2eb7 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,7 @@ docstr-coverage some_project/src - _--skip-init, -i_ - Ignore all `__init__` methods - _--skip-file-doc, -f_ - Ignore module docstrings (at the top of files) - _--skip-private, -P_ - Ignore private functions (starting with a single underscore) +- _--skip-mangled, -M_ - Ignore mangled functions (starting with a double underscore) - _--skip-class-def, -c_ - Ignore docstrings of class definitions - _--skip-property, -sp_ - Ignore functions with `@property` decorator - _--include-setter, -is_ - Include functions with `@setter` decorator (skipped by default) @@ -122,6 +123,7 @@ skip_file_doc: True # Boolean skip_init: True # Boolean skip_class_def: True # Boolean skip_private: True # Boolean +skip_mangled: True # Boolean follow_links: True # Boolean accept_empty: True # Boolean ignore_names_file: .*/test # regex diff --git a/docstr_coverage/cli.py b/docstr_coverage/cli.py index d2b4762..71d334a 100644 --- a/docstr_coverage/cli.py +++ b/docstr_coverage/cli.py @@ -201,6 +201,12 @@ def _assert_valid_key_value(k, v): is_flag=True, help="Ignore docstrings of functions starting with a single underscore", ) +@click.option( + "-M", + "--skip-mangled", + is_flag=True, + help="Ignore docstrings of functions starting with a double underscore", +) @click.option("-l", "--follow-links", is_flag=True, help="Follow symlinks") @click.option( "-F", @@ -336,6 +342,7 @@ def execute(paths, **kwargs): skip_init=kwargs["skip_init"], skip_class_def=kwargs["skip_class_def"], skip_private=kwargs["skip_private"], + skip_mangled=kwargs["skip_mangled"], skip_property=kwargs["skip_property"], skip_setter=not kwargs["include_setter"], skip_deleter=not kwargs["include_deleter"], diff --git a/docstr_coverage/coverage.py b/docstr_coverage/coverage.py index 792f1e4..89217c5 100644 --- a/docstr_coverage/coverage.py +++ b/docstr_coverage/coverage.py @@ -109,6 +109,8 @@ def _analyze_docstrings_on_node( ignore_reason = "skip-class-def set to True" elif ignore_config.skip_private and name.startswith("_") and not name.startswith("__"): ignore_reason = "skip-private set to True" + elif ignore_config.skip_mangled and name.startswith("__"): + ignore_reason = "skip-mangled set to True" elif ignore_config.ignore_names and _do_ignore_node( filename, base, name, ignore_config.ignore_names ): @@ -140,6 +142,7 @@ def get_docstring_coverage( skip_init: bool = False, skip_class_def: bool = False, skip_private: bool = False, + skip_mangled: bool = False, verbose: int = 0, ignore_names: Tuple[List[str], ...] = (), ) -> Tuple[Dict, Dict]: @@ -169,6 +172,9 @@ def get_docstring_coverage( skip_private: Boolean, default=False If True, skips function definitions beginning with a single underscore and does not include them in the report. + skip_mangled: Boolean, default=False + If True, skips function definitions beginning with a double underscore and does + not include them in the report. verbose: Int in [0, 1, 2, 3], default=0 0) No printing. 1) Print total stats only. @@ -210,6 +216,7 @@ def get_docstring_coverage( skip_init=skip_init, skip_class_def=skip_class_def, skip_private=skip_private, + skip_mangled=skip_mangled, ignore_names=ignore_names, ) results = analyze(filenames, ignore_config) diff --git a/docstr_coverage/ignore_config.py b/docstr_coverage/ignore_config.py index 908cef0..3bec186 100644 --- a/docstr_coverage/ignore_config.py +++ b/docstr_coverage/ignore_config.py @@ -13,6 +13,7 @@ def __init__( skip_init: bool = False, skip_class_def: bool = False, skip_private: bool = False, + skip_mangled: bool = False, skip_property: bool = False, skip_setter: bool = True, skip_deleter: bool = True, @@ -23,6 +24,7 @@ def __init__( self._skip_init = skip_init self._skip_class_def = skip_class_def self._skip_private = skip_private + self._skip_mangled = skip_mangled self._skip_property = skip_property self._skip_setter = skip_setter self._skip_deleter = skip_deleter @@ -62,6 +64,11 @@ def skip_class_def(self): def skip_private(self): """If True, skip function definitions beginning with a single underscore.""" return self._skip_private + + @property + def skip_mangled(self): + """If True, skip function definitions beginning with a double underscore.""" + return self._skip_mangled @property def skip_property(self): diff --git a/docstr_coverage/printers.py b/docstr_coverage/printers.py index 99b46a6..2da81f0 100644 --- a/docstr_coverage/printers.py +++ b/docstr_coverage/printers.py @@ -71,6 +71,7 @@ class OverallCoverageStat: is_skip_init: bool is_skip_magic: bool is_skip_private: bool + is_skip_mangled: bool missing: int needed: int num_empty_files: int @@ -135,6 +136,7 @@ def overall_coverage_stat(self) -> Union[OverallCoverageStat, float]: is_skip_init=self.ignore_config.skip_init, is_skip_magic=self.ignore_config.skip_magic, is_skip_private=self.ignore_config.skip_private, + is_skip_mangled=self.ignore_config.skip_mangled, missing=count.missing, needed=count.needed, num_empty_files=count.num_empty_files, @@ -324,6 +326,9 @@ def _generate_overall_stat_string(self) -> str: if self.overall_coverage_stat.is_skip_private: prefix += " (skipped private methods)" + if self.overall_coverage_stat.is_skip_mangled: + prefix += " (skipped mangled method names)" + final_string: str = "" if self.overall_coverage_stat.num_files > 1: @@ -444,6 +449,9 @@ def _generate_overall_stat_string(self) -> str: if self.overall_coverage_stat.is_skip_private: final_string += "- skipped private methods\n" + if self.overall_coverage_stat.is_skip_mangled: + final_string += "- skipped mangled method names\n" + final_string += "\n" final_string += self._generate_markdown_table( diff --git a/tests/config_files/with_ignore.yml b/tests/config_files/with_ignore.yml index 8a75139..d4c7797 100644 --- a/tests/config_files/with_ignore.yml +++ b/tests/config_files/with_ignore.yml @@ -24,4 +24,5 @@ skip_file_doc: true skip_init: true skip_magic: true skip_private: true +skip_mangled: true verbose: '2' diff --git a/tests/config_files/without_ignore.yml b/tests/config_files/without_ignore.yml index df7a61d..6421969 100644 --- a/tests/config_files/without_ignore.yml +++ b/tests/config_files/without_ignore.yml @@ -6,4 +6,5 @@ skip_file_doc: true skip_init: true skip_magic: true skip_private: true +skip_mangled: true verbose: '2' diff --git a/tests/test_config_file.py b/tests/test_config_file.py index b7a5c0f..371ecec 100644 --- a/tests/test_config_file.py +++ b/tests/test_config_file.py @@ -16,6 +16,7 @@ "skip_init": True, "skip_class_def": True, "skip_private": True, + "skip_mangled": False, "follow_links": True, "fail_under": 90, "percentage_only": True, @@ -28,6 +29,7 @@ "skip_init": True, "skip_class_def": True, "skip_private": True, + "skip_mangled": False, "follow_links": True, "fail_under": 90, "percentage_only": True, diff --git a/tests/test_coverage.py b/tests/test_coverage.py index 248fa27..4ccf59b 100644 --- a/tests/test_coverage.py +++ b/tests/test_coverage.py @@ -498,6 +498,20 @@ def test_skip_private(): } assert total_results == {"missing_count": 2, "needed_count": 3, "coverage": 33.333333333333336} +def test_skip_mangled(): + ignore_config = IgnoreConfig(skip_mangled=True) + result = analyze([PRIVATE_NO_DOCS_PATH], ignore_config=ignore_config) + file_results, total_results = result.to_legacy() + assert file_results[PRIVATE_NO_DOCS_PATH] == { + "missing": ["_foo", "_afoo"], + "module_doc": True, + "missing_count": 2, + "needed_count": 3, + "coverage": 33.333333333333336, + "empty": False, + } + assert total_results == {"missing_count": 2, "needed_count": 3, "coverage": 33.333333333333336} + def test_long_doc(): """Regression test on issue 79.