Repository: pfmoore/editables (language: python)

Issue:
TypeError: MetaPathFinder.invalidate_caches() missing 1 required positional argument: 'self'
When `editables` meta path finder is loaded and appears in `sys.meta_path`, running `importlib.invalidate_caches()` gives the following traceback:

```pycon
>>> from importlib import invalidate_caches
>>> invalidate_caches()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/pawamoy/.basher-packages/pyenv/pyenv/versions/3.11.4/lib/python3.11/importlib/__init__.py", line 70, in invalidate_caches
    finder.invalidate_caches()
TypeError: MetaPathFinder.invalidate_caches() missing 1 required positional argument: 'self'
```

It seems to be because your meta path finder is added as a class to `sys.meta_path` rather than an instance (not sure if this is actually `editables` responsibility, or PDM which is the tool using `editables` in my environment):

```pycon
>>> import sys
>>> sys.meta_path
[
    <_distutils_hack.DistutilsMetaFinder object at 0x7f8af931a190>,
    <class '_frozen_importlib.BuiltinImporter'>,
    <class '_frozen_importlib.FrozenImporter'>,
    <class '_frozen_importlib_external.PathFinder'>,
    <class 'editables.redirector.RedirectingFinder'>,
]
```

When `invalidate_caches` iterates and gets to `editables.redirector.RedirectingFinder`, it sees that it has an `invalidate_caches` attribute and calls it, but the `finder` is a class and therefore `self` is missing.

For reference:

```python
def invalidate_caches():
    """Call the invalidate_caches() method on all meta path finders stored in
    sys.meta_path (where implemented)."""
    for finder in sys.meta_path:
        if hasattr(finder, 'invalidate_caches'):
            finder.invalidate_caches()  # I guess finder is supposed to be an instance here, not a class
```

Possible solutions:

- change things so that the finder is instantiated
- or implement an `invalidate_caches()` **classmethod** in the finder class


Discussion / hints:

Fix patch:
diff --git a/src/editables/redirector.py b/src/editables/redirector.py
index e898d81..7bdef59 100644
--- a/src/editables/redirector.py
+++ b/src/editables/redirector.py
@@ -37,3 +37,11 @@ def install(cls) -> None:
                 break
         else:
             sys.meta_path.append(cls)
+
+    @classmethod
+    def invalidate_caches(cls) -> None:
+        # importlib.invalidate_caches calls finders' invalidate_caches methods,
+        # and since we install this meta path finder as a class rather than an instance,
+        # we have to override the inherited invalidate_caches method (using self)
+        # as a classmethod instead
+        pass


Test patch:
diff --git a/tests/test_redirects.py b/tests/test_redirects.py
index eead159..65a2059 100644
--- a/tests/test_redirects.py
+++ b/tests/test_redirects.py
@@ -1,4 +1,5 @@
 import contextlib
+import importlib
 import sys
 
 from editables.redirector import RedirectingFinder as F
@@ -81,3 +82,10 @@ def test_redirects(tmp_path):
         import pkg.sub
 
         assert pkg.sub.val == 42
+
+
+def test_cache_invalidation():
+    F.install()
+    # assert that the finder matches importlib's expectations
+    # see https://github.com/pfmoore/editables/issues/31
+    importlib.invalidate_caches()