Repository: netromdk/vermin

Issue:
AttributeError: 'str' object has no attribute 'search'
**Describe the bug**
If you define `exclusion_regex` in `setup.cfg`, the string is treated as a regex pattern object leading to:
```
Traceback (most recent call last):
  File "/opt/homebrew/Cellar/python@3.11/3.11.6/Frameworks/Python.framework/Versions/3.11/lib/python3.11/multiprocessing/pool.py", line 125, in worker
    result = (True, func(*args, **kwds))
                    ^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/lib/python3.11/site-packages/vermin/detection.py", line 484, in detect_paths_incremental
    if any(ic in path for ic in ignore_chars) or config.is_excluded_by_regex(path):
                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/lib/python3.11/site-packages/vermin/config.py", line 338, in is_excluded_by_regex
    return any(regex.search(path) for regex in self.__exclusion_regex)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/lib/python3.11/site-packages/vermin/config.py", line 338, in <genexpr>
    return any(regex.search(path) for regex in self.__exclusion_regex)
               ^^^^^^^^^^^^
AttributeError: 'str' object has no attribute 'search'
"""

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/opt/homebrew/bin/vermin", line 8, in <module>
    sys.exit(main())
             ^^^^^^
  File "/opt/homebrew/lib/python3.11/site-packages/vermin/main.py", line 39, in main
    paths = list(set(detect_paths(paths, hidden=config.analyze_hidden(),
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/lib/python3.11/site-packages/vermin/detection.py", line 531, in detect_paths
    for (acc, further_args) in act(args):
  File "/opt/homebrew/Cellar/python@3.11/3.11.6/Frameworks/Python.framework/Versions/3.11/lib/python3.11/multiprocessing/pool.py", line 873, in next
    raise value
AttributeError: 'str' object has no attribute 'search'
```

**To Reproduce**
```sh
$ python3 -m pip install -U vermin
$ mkdir repro && cd repro
$ echo -e "[vermin]\nexclusion_regex =\n    'foo/'" > setup.cfg
$ touch foo.py
$ vermin ./foo.py # boom
```

**Expected behavior**
No exception

**Environment (please complete the following information):**
```sh
$ vermin --version
1.5.2
$ python3 --version
Python 3.11.6
```

Discussion:

Patch:
diff --git a/vermin/config.py b/vermin/config.py
index 2a63f27..d5da9df 100644
--- a/vermin/config.py
+++ b/vermin/config.py
@@ -47,7 +47,7 @@ class Config:
     self.__show_tips = other_config.show_tips()
     self.__analyze_hidden = other_config.analyze_hidden()
     self.__exclusions = set(other_config.exclusions())
-    self.__exclusion_regex = set(other_config.exclusion_regex())
+    self.__exclusion_regex = {re.compile(r) for r in other_config.exclusion_regex()}
     self.__make_paths_absolute = other_config.make_paths_absolute()
     self.__backports = other_config.backports()
     self.__features = other_config.features()


Test patch:
diff --git a/tests/config.py b/tests/config.py
index 5b6c676..b412fc4 100644
--- a/tests/config.py
+++ b/tests/config.py
@@ -39,6 +39,7 @@ class VerminConfigTests(VerminTest):
     other.set_show_tips(False)
     other.set_analyze_hidden(True)
     other.add_exclusion("foo.bar.baz")
+    other.add_exclusion_regex("foo/")
     self.assertTrue(other.add_backport("typing"))
     self.assertTrue(other.enable_feature("fstring-self-doc"))
     self.assertTrue(other.add_target("2.3"))
@@ -58,6 +59,7 @@ class VerminConfigTests(VerminTest):
     self.assertEqual(other.show_tips(), self.config.show_tips())
     self.assertEqual(other.analyze_hidden(), self.config.analyze_hidden())
     self.assertEqual(other.exclusions(), self.config.exclusions())
+    self.assertEqual(other.exclusion_regex(), self.config.exclusion_regex())
     self.assertEqual(other.backports(), self.config.backports())
     self.assertEqual(other.features(), self.config.features())
     self.assertEqual(other.targets(), self.config.targets())
diff --git a/tests/general.py b/tests/general.py
index 78c226c..f36ba6b 100644
--- a/tests/general.py
+++ b/tests/general.py
@@ -380,7 +380,13 @@ test.py:6:9:2.7:3.2:'argparse' module
       paths = detect_paths(["a"], config=self.config)
       self.assertEqual(paths, [join("a", "code.py")])
 
-    rmtree(tmp_fld)
+    # When running on Windows, this can sometimes fail:
+    #   PermissionError: [WinError 32] The process cannot access the file because it is being used
+    #                    by another process:
+    #                    'C:\\Users\\RUNNER~1\\AppData\\Local\\Temp\\tmpAAAANNNN'
+    # But we can ignore that since the files reside in a temporary folder anyway, and the
+    # folders/files aren't being used any longer either.
+    rmtree(tmp_fld, ignore_errors=True)
 
   def test_detect_vermin_min_versions(self):
     paths = detect_paths([abspath("vermin")], config=self.config)