From 767d266a24ac1abc9ebf76f39bd3db485c52cada Mon Sep 17 00:00:00 2001 From: Danny McClanahan <1305167+cosmicexplorer@users.noreply.github.com> Date: Tue, 4 Oct 2022 18:25:44 -0400 Subject: [PATCH] match using re.search and use anchors --- tests/arguments.py | 12 ++++++------ tests/general.py | 8 ++++---- vermin/arguments.py | 14 ++++++++------ vermin/config.py | 7 +------ 4 files changed, 19 insertions(+), 22 deletions(-) diff --git a/tests/arguments.py b/tests/arguments.py index 6b615b6d..53c5eeae 100644 --- a/tests/arguments.py +++ b/tests/arguments.py @@ -231,10 +231,10 @@ def test_exclude_regex(self): self.assertContainsDict({"code": 1}, self.parse_args(["--exclude-regex"])) # Needs part. self.assertEmpty(self.config.exclusion_regex()) - args = ["--exclude-regex", r".+\.pyi", - "--exclude-regex", "a/b"] + args = ["--exclude-regex", r"\.pyi$", + "--exclude-regex", "^a/b$"] self.assertContainsDict({"code": 0}, self.parse_args(args)) - expected = [re.compile(r".+\.pyi"), re.compile("a/b")] + expected = [re.compile(r"\.pyi$"), re.compile("^a/b$")] self.assertEqual(expected, self.config.exclusion_regex()) # Expect it sorted. self.assertFalse(self.config.is_excluded_by_regex("a/b.py")) self.assertTrue(self.config.is_excluded_by_regex("asdf.pyi")) @@ -249,8 +249,8 @@ def test_exclude_regex(self): self.assertFalse(self.config.is_excluded_by_regex("a/b/c.py")) self.config.reset() - args = ["--exclude-regex", "a/b/.+", - "--exclude-regex", r"a/.+/.+\.pyi"] + args = ["--exclude-regex", "^a/b/.+$", + "--exclude-regex", r"^a/.+/.+\.pyi$"] self.assertContainsDict({"code": 0}, self.parse_args(args)) self.assertTrue(self.config.is_excluded_by_regex("a/b/c.py")) self.assertTrue(self.config.is_excluded_by_regex("a/b/c/d.py")) @@ -261,7 +261,7 @@ def test_exclude_regex(self): self.config.reset() # Use '[^/]+' instead of '.+' to force only matching files in the top-level. - self.assertContainsDict({"code": 0}, self.parse_args(["--exclude-regex", r"a/b/[^/]+\.pyi"])) + self.assertContainsDict({"code": 0}, self.parse_args(["--exclude-regex", r"^a/b/[^/]+\.pyi$"])) self.assertTrue(self.config.is_excluded_by_regex("a/b/c.pyi")) self.assertFalse(self.config.is_excluded_by_regex("a/b/c.py")) self.assertFalse(self.config.is_excluded_by_regex("a/b/c/d.pyi")) diff --git a/tests/general.py b/tests/general.py index b87ad98e..b53ce785 100644 --- a/tests/general.py +++ b/tests/general.py @@ -322,7 +322,7 @@ def test_exclude_pyi_regex(self): # With the default of --make-paths-absolute, this will match .pyi files in any subdirectory. The # most common use case for --exclude-regex is expected to be for file extensions, so it's great # that that will work regardless of the --make-paths-absolute setting. - self.config.add_exclusion_regex(r".+\.pyi") + self.config.add_exclusion_regex(r"\.pyi$") f = touch(tmp_fld, "code.pyi") with open_wrapper(f, mode="w", encoding="utf-8") as fp: @@ -337,7 +337,7 @@ def test_exclude_directory_regex(self): tmp_fld = mkdtemp() # Excluding the directory .../a should exclude any files recursively beneath it as well. - self.config.add_exclusion_regex(re.escape(join(tmp_fld, "a"))) + self.config.add_exclusion_regex('^' + re.escape(join(tmp_fld, "a")) + '$') # Create .../a and .../a/b directories. os.mkdir(join(tmp_fld, "a")) @@ -359,8 +359,8 @@ def test_exclude_regex_relative(self): # Keep paths relative, and provide patterns matching relative paths. self.config.set_make_paths_absolute(False) - self.config.add_exclusion_regex("a/b") - self.config.add_exclusion_regex("a/[^/]+\.pyi") + self.config.add_exclusion_regex("^a/b$") + self.config.add_exclusion_regex(r"^a/[^/]+\.pyi$") # Create .../a and .../a/b directories. os.mkdir(join(tmp_fld, "a")) diff --git a/vermin/arguments.py b/vermin/arguments.py index d78ed993..6bc7b678 100644 --- a/vermin/arguments.py +++ b/vermin/arguments.py @@ -156,14 +156,16 @@ def print_usage(full=False): " Use no excludes. Clears any excludes specified before this.") print("\n [--exclude-regex ] ...\n" " Exclude files from analysis by matching a regex pattern against their\n" - " entire path as expanded from the vermin command line.\n\n" + " entire path as expanded from the vermin command line. Patterns are matched\n" + " using re.search(), so '^' or '$' anchors should be applied as needed.\n\n" " Examples:\n" - " Exclude any '.pyi' file: --exclude-regex '.+\\.pyi'\n\n" + " Exclude any '.pyi' file: --exclude-regex '\\.pyi$'\n\n" " (Note: the below examples require --no-make-paths-absolute, or prefixing\n" - " the patterns with the absolute path to the current directory.)\n\n" - " Exclude the directory 'a/b/': --exclude-regex 'a/b'\n" - " Exclude '.pyi' files under 'a/b/': --exclude-regex 'a/b/.+\\.pyi'\n" - " Exclude '.pyi' files in exactly 'a/b/': --exclude-regex 'a/b/[^/]+\\.pyi'") + " the patterns with the regex-escaped path to the current directory.)\n\n" + " Exclude the directory 'a/b/': --exclude-regex '^a/b$'\n" + " (This will also exclude any files under 'a/b'.)\n\n" + " Exclude '.pyi' files under 'a/b/': --exclude-regex '^a/b/.+\\.pyi$'\n" + " Exclude '.pyi' files in exactly 'a/b/': --exclude-regex '^a/b/[^/]+\\.pyi$'") print("\n --no-exclude-regex (default)\n" " Use no exclude patterns. Clears any exclude patterns specified before this.") print("\n --make-paths-absolute (default)\n" diff --git a/vermin/config.py b/vermin/config.py index af58bc65..08dc114d 100644 --- a/vermin/config.py +++ b/vermin/config.py @@ -335,12 +335,7 @@ def is_excluded_codecs_encoding(self, name): return "ce={}".format(name) in self.__exclusions def is_excluded_by_regex(self, path): - def matches_completely(rx, p): - m = rx.match(p) - if m is None: - return False - return m.end() == m.endpos - return any(matches_completely(regex, path) for regex in self.__exclusion_regex) + return any(regex.search(path) for regex in self.__exclusion_regex) def make_paths_absolute(self): return self.__make_paths_absolute