Repository: cthoyt/class-resolver

Issue:
Combine subclass and entrypoint instantiation
While the entrypoint loader in PyKEEN seems to be very clever, it's still sort of a problem for collab users. It might be better to provide a mixed version where there are some base classes that are in PyKEEN, plus the possibility to add extra stuff

Discussion:
codecov-commenter: # [Codecov](https://codecov.io/gh/cthoyt/class-resolver/pull/37?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Charles+Tapley+Hoyt) Report
> Merging [#37](https://codecov.io/gh/cthoyt/class-resolver/pull/37?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Charles+Tapley+Hoyt) (b309bc6) into [main](https://codecov.io/gh/cthoyt/class-resolver/commit/c594e2eab7f481f75c67abd24a8a53b16ed7a278?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Charles+Tapley+Hoyt) (c594e2e) will **increase** coverage by `0.10%`.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/cthoyt/class-resolver/pull/37/graphs/tree.svg?width=650&height=150&src=pr&token=4VPTLCIMVC&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Charles+Tapley+Hoyt)](https://codecov.io/gh/cthoyt/class-resolver/pull/37?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Charles+Tapley+Hoyt)

```diff
@@            Coverage Diff             @@
##             main      #37      +/-   ##
==========================================
+ Coverage   92.87%   92.98%   +0.10%     
==========================================
  Files           9        9              
  Lines         337      342       +5     
  Branches       64       65       +1     
==========================================
+ Hits          313      318       +5     
  Misses         17       17              
  Partials        7        7              
```


| [Impacted Files](https://codecov.io/gh/cthoyt/class-resolver/pull/37?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Charles+Tapley+Hoyt) | Coverage Δ | |
|---|---|---|
| [src/class\_resolver/base.py](https://codecov.io/gh/cthoyt/class-resolver/pull/37/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Charles+Tapley+Hoyt#diff-c3JjL2NsYXNzX3Jlc29sdmVyL2Jhc2UucHk=) | `97.29% <100.00%> (+0.12%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/cthoyt/class-resolver/pull/37?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Charles+Tapley+Hoyt).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Charles+Tapley+Hoyt)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/cthoyt/class-resolver/pull/37?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Charles+Tapley+Hoyt). Last update [c594e2e...b309bc6](https://codecov.io/gh/cthoyt/class-resolver/pull/37?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Charles+Tapley+Hoyt). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Charles+Tapley+Hoyt).


Patch:
diff --git a/src/class_resolver/base.py b/src/class_resolver/base.py
index 138ab7e..0b5aad7 100644
--- a/src/class_resolver/base.py
+++ b/src/class_resolver/base.py
@@ -234,6 +234,11 @@ class BaseResolver(ABC, Generic[X, Y]):
             **kwargs,
         )
 
+    def register_entrypoint(self, group: str) -> None:
+        """Register additional entries from an entrypoint."""
+        for element in self._from_entrypoint(group).difference(self.lookup_dict.values()):
+            self.register(element)
+
     @staticmethod
     def _from_entrypoint(group: str) -> Set[X]:
         elements = set()


Test patch:
diff --git a/tests/test_function_resolver.py b/tests/test_function_resolver.py
index e32948a..c2b498b 100644
--- a/tests/test_function_resolver.py
+++ b/tests/test_function_resolver.py
@@ -2,6 +2,7 @@
 
 """Tests for the function resolver."""
 
+import operator
 import unittest
 
 from class_resolver import FunctionResolver
@@ -102,3 +103,12 @@ class TestFunctionResolver(unittest.TestCase):
         self.assertEqual({"add", "sub", "mul"}, set(resolver.lookup_dict))
         self.assertEqual(set(), set(resolver.synonyms))
         self.assertNotIn("expected_failure", resolver.lookup_dict)
+
+    def test_late_entrypoints(self):
+        """Test loading late entrypoints."""
+        resolver = FunctionResolver([operator.add, operator.sub])
+        self.assertEqual({"add", "sub"}, set(resolver.lookup_dict))
+        resolver.register_entrypoint("class_resolver_demo")
+        self.assertEqual({"add", "sub", "mul"}, set(resolver.lookup_dict))
+        self.assertEqual(set(), set(resolver.synonyms))
+        self.assertNotIn("expected_failure", resolver.lookup_dict)