From ff3630f3f979b1bd87592b61c3e0c15f9d2185fc Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 18 Jun 2026 15:37:32 +0100 Subject: [PATCH 1/8] Make addon type a class-level attribute --- medcat-v2/medcat/components/addons/addons.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/medcat-v2/medcat/components/addons/addons.py b/medcat-v2/medcat/components/addons/addons.py index c173fc19b..ef5103210 100644 --- a/medcat-v2/medcat/components/addons/addons.py +++ b/medcat-v2/medcat/components/addons/addons.py @@ -13,12 +13,10 @@ class AddonComponent(BaseComponent, Protocol): """Base/abstract addon component class.""" NAME_PREFIX: str = "addon_" NAME_SPLITTER: str = "." + # NOTE: need to implement + addon_type: str config: ComponentConfig - @property - def addon_type(self) -> str: - pass - def is_core(self) -> bool: return False From ea3c2f75a6e4cd421f1c95e884374b6b326851a5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 18 Jun 2026 15:39:46 +0100 Subject: [PATCH 2/8] Allow filtering of loaded addons based on type --- medcat-v2/medcat/cat.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/medcat-v2/medcat/cat.py b/medcat-v2/medcat/cat.py index 2825ee561..4f747b67c 100644 --- a/medcat-v2/medcat/cat.py +++ b/medcat-v2/medcat/cat.py @@ -905,7 +905,8 @@ def load_cdb(cls, model_pack_path: str) -> CDB: @classmethod def load_addons( cls, model_pack_path: str, - addon_config_dict: Optional[dict[str, dict]] = None + addon_config_dict: Optional[dict[str, dict]] = None, + addon_types: Optional[list[Type[AddonComponent]]] = None, ) -> list[tuple[str, AddonComponent]]: """Load addons based on a model pack path. @@ -917,6 +918,9 @@ def load_addons( For instance, `{"meta_cat.Subject": {'general': {'device': 'cpu'}}}` would apply to the specific MetaCAT. + addon_type (Optional[list[Type[AddonComponent]]]): + The types of adddons to include. If not specified, all + addons will be loaded. Defaults to None. Returns: List[tuple(str, AddonComponent)]: list of pairs of adddon names the addons. @@ -931,6 +935,19 @@ def load_addons( components_folder, folder_name)) and folder_name.startswith(AddonComponent.NAME_PREFIX) ] + if addon_types is not None: + # filter based on specified addon types + had_before = len(addon_paths_and_names) + addon_paths_and_names = [ + (addon_path, addon) + for addon_path, addon in addon_paths_and_names + if any(AddonType.get_folder_name_for_addon_and_name( + AddonType.addon_type, "").startswith(addon_path) + for AddonType in addon_types) + ] + logger.debug( + "Filtered %d addon paths down to %d from based on %s", + had_before, len(addon_paths_and_names), addon_types) loaded_addons = [ addon for addon_path, addon_name in addon_paths_and_names if isinstance(addon := ( From 4fdca75bf538c4ab35cff083699230c8340f32bc Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 18 Jun 2026 16:47:14 +0100 Subject: [PATCH 3/8] Fix filtering logic --- medcat-v2/medcat/cat.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/medcat-v2/medcat/cat.py b/medcat-v2/medcat/cat.py index 4f747b67c..b6f89c26c 100644 --- a/medcat-v2/medcat/cat.py +++ b/medcat-v2/medcat/cat.py @@ -938,12 +938,18 @@ def load_addons( if addon_types is not None: # filter based on specified addon types had_before = len(addon_paths_and_names) + expected_folder_names = [ + addon_type.get_folder_name_for_addon_and_name( + addon_type.addon_type, "") + for addon_type in addon_types + ] addon_paths_and_names = [ (addon_path, addon) for addon_path, addon in addon_paths_and_names - if any(AddonType.get_folder_name_for_addon_and_name( - AddonType.addon_type, "").startswith(addon_path) - for AddonType in addon_types) + if any( + os.path.basename(addon_path).startswith(expected_prefix) + for expected_prefix in expected_folder_names + ) ] logger.debug( "Filtered %d addon paths down to %d from based on %s", From 6acf9853c08b608b597655670fdce24834a5a980 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 18 Jun 2026 16:50:53 +0100 Subject: [PATCH 4/8] Add a few tests for addon filtering --- medcat-v2/tests/test_cat.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/medcat-v2/tests/test_cat.py b/medcat-v2/tests/test_cat.py index e6a366670..6c4565a52 100644 --- a/medcat-v2/tests/test_cat.py +++ b/medcat-v2/tests/test_cat.py @@ -524,10 +524,28 @@ def test_can_load_saved(self): def test_can_load_meta_cat(self): addons = cat.CAT.load_addons(self.mpp) + self.assert_has_one_meta_cat(addons) + + def assert_has_one_meta_cat(self, addons: list[AddonComponent]): self.assertEqual(len(addons), 1) _, addon = addons[0] self.assertIsInstance(addon, MetaCATAddon) + def test_can_filter_addons_empty(self): + # NONE -> empty + addons = cat.CAT.load_addons(self.mpp, addon_types=[]) + self.assertFalse(addons) + + def test_can_filter_addons_non_existing(self): + from medcat.components.addons.relation_extraction.rel_cat import RelCATAddon + addons = cat.CAT.load_addons(self.mpp, addon_types=[RelCATAddon]) + self.assertFalse(addons) + + def test_can_filter_addons_meta_cat(self): + # only meta cat -> same as regular + addons = cat.CAT.load_addons(self.mpp, addon_types=[MetaCATAddon]) + self.assert_has_one_meta_cat(addons) + def test_can_load_meta_cat_with_addon_cnf(self, seed: int = -41): mc: MetaCATAddon = cat.CAT.load_addons( self.mpp, addon_config_dict={ From 398e7001a60590e8a0f887571f95fa654ada888c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 18 Jun 2026 16:54:45 +0100 Subject: [PATCH 5/8] Only load MetaCAT addons in trainer --- medcat-trainer/webapp/api/api/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/medcat-trainer/webapp/api/api/models.py b/medcat-trainer/webapp/api/api/models.py index ec1c673da..1e5afdc6c 100644 --- a/medcat-trainer/webapp/api/api/models.py +++ b/medcat-trainer/webapp/api/api/models.py @@ -116,7 +116,7 @@ def save(self, *args, skip_load=False, **kwargs): try: metaCATmodels = [] # should raise an error if there already is a MetaCAT model with this definition - addons = CAT.load_addons(unpacked_model_pack_path) + addons = CAT.load_addons(unpacked_model_pack_path, addon_types=[MetaCATAddon,]) meta_cat_addons = [ (addon_path, addon) for addon_path, addon in addons if isinstance(addon, MetaCATAddon)] From f32a4f42b973bb9b05ab1acf76f5d5337078a099 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 18 Jun 2026 17:08:42 +0100 Subject: [PATCH 6/8] Update trainer tests for addons --- .../webapp/api/api/tests/test_model_pack_addons.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/medcat-trainer/webapp/api/api/tests/test_model_pack_addons.py b/medcat-trainer/webapp/api/api/tests/test_model_pack_addons.py index 9b2797e63..833cbbb98 100644 --- a/medcat-trainer/webapp/api/api/tests/test_model_pack_addons.py +++ b/medcat-trainer/webapp/api/api/tests/test_model_pack_addons.py @@ -71,7 +71,7 @@ def test_register_model_pack_with_meta_cat_only(self): addons = [(meta_cat_path, _make_meta_cat_addon())] with self._register_model_pack(model_pack, addons) as load_addons: - load_addons.assert_called_once_with(unpacked) + load_addons.assert_called_once_with(unpacked, addon_types=[MetaCATAddon]) self.assertIsNotNone(model_pack.concept_db) self.assertIsNotNone(model_pack.vocab) @@ -87,7 +87,7 @@ def test_register_model_pack_with_rel_cat_only(self): addons = [(rel_cat_path, _make_rel_cat_addon())] with self._register_model_pack(model_pack, addons) as load_addons: - load_addons.assert_called_once_with(unpacked) + load_addons.assert_called_once_with(unpacked, addon_types=[MetaCATAddon]) self.assertIsNotNone(model_pack.concept_db) self.assertIsNotNone(model_pack.vocab) @@ -123,7 +123,7 @@ def test_register_model_pack_with_meta_cat_and_rel_cat(self): ] with self._register_model_pack(model_pack, addons) as load_addons: - load_addons.assert_called_once_with(unpacked) + load_addons.assert_called_once_with(unpacked, addon_types=[MetaCATAddon]) self.assertIsNotNone(model_pack.concept_db) self.assertIsNotNone(model_pack.vocab) @@ -137,7 +137,7 @@ def test_register_model_pack_without_addons(self): model_pack, unpacked = self._prepare_model_pack(name="no-addon-pack") with self._register_model_pack(model_pack, []) as load_addons: - load_addons.assert_called_once_with(unpacked) + load_addons.assert_called_once_with(unpacked, addon_types=[MetaCATAddon]) self.assertIsNotNone(model_pack.concept_db) self.assertIsNotNone(model_pack.vocab) From 407610425a4ed918a507531d2792c2081726ea0d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 19 Jun 2026 10:07:07 +0100 Subject: [PATCH 7/8] Revert "Update trainer tests for addons" This reverts commit f32a4f42b973bb9b05ab1acf76f5d5337078a099. --- .../webapp/api/api/tests/test_model_pack_addons.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/medcat-trainer/webapp/api/api/tests/test_model_pack_addons.py b/medcat-trainer/webapp/api/api/tests/test_model_pack_addons.py index 833cbbb98..9b2797e63 100644 --- a/medcat-trainer/webapp/api/api/tests/test_model_pack_addons.py +++ b/medcat-trainer/webapp/api/api/tests/test_model_pack_addons.py @@ -71,7 +71,7 @@ def test_register_model_pack_with_meta_cat_only(self): addons = [(meta_cat_path, _make_meta_cat_addon())] with self._register_model_pack(model_pack, addons) as load_addons: - load_addons.assert_called_once_with(unpacked, addon_types=[MetaCATAddon]) + load_addons.assert_called_once_with(unpacked) self.assertIsNotNone(model_pack.concept_db) self.assertIsNotNone(model_pack.vocab) @@ -87,7 +87,7 @@ def test_register_model_pack_with_rel_cat_only(self): addons = [(rel_cat_path, _make_rel_cat_addon())] with self._register_model_pack(model_pack, addons) as load_addons: - load_addons.assert_called_once_with(unpacked, addon_types=[MetaCATAddon]) + load_addons.assert_called_once_with(unpacked) self.assertIsNotNone(model_pack.concept_db) self.assertIsNotNone(model_pack.vocab) @@ -123,7 +123,7 @@ def test_register_model_pack_with_meta_cat_and_rel_cat(self): ] with self._register_model_pack(model_pack, addons) as load_addons: - load_addons.assert_called_once_with(unpacked, addon_types=[MetaCATAddon]) + load_addons.assert_called_once_with(unpacked) self.assertIsNotNone(model_pack.concept_db) self.assertIsNotNone(model_pack.vocab) @@ -137,7 +137,7 @@ def test_register_model_pack_without_addons(self): model_pack, unpacked = self._prepare_model_pack(name="no-addon-pack") with self._register_model_pack(model_pack, []) as load_addons: - load_addons.assert_called_once_with(unpacked, addon_types=[MetaCATAddon]) + load_addons.assert_called_once_with(unpacked) self.assertIsNotNone(model_pack.concept_db) self.assertIsNotNone(model_pack.vocab) From fa0cddf5a97d71f605b9a77e253121bc9578d255 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 19 Jun 2026 10:07:08 +0100 Subject: [PATCH 8/8] Revert "Only load MetaCAT addons in trainer" This reverts commit 398e7001a60590e8a0f887571f95fa654ada888c. --- medcat-trainer/webapp/api/api/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/medcat-trainer/webapp/api/api/models.py b/medcat-trainer/webapp/api/api/models.py index 1e5afdc6c..ec1c673da 100644 --- a/medcat-trainer/webapp/api/api/models.py +++ b/medcat-trainer/webapp/api/api/models.py @@ -116,7 +116,7 @@ def save(self, *args, skip_load=False, **kwargs): try: metaCATmodels = [] # should raise an error if there already is a MetaCAT model with this definition - addons = CAT.load_addons(unpacked_model_pack_path, addon_types=[MetaCATAddon,]) + addons = CAT.load_addons(unpacked_model_pack_path) meta_cat_addons = [ (addon_path, addon) for addon_path, addon in addons if isinstance(addon, MetaCATAddon)]