From 7131354e6b69eaaa8998a8800a5dc9a10be2c991 Mon Sep 17 00:00:00 2001
From: Bryan Brancotte <bryan.brancotte@pasteur.fr>
Date: Tue, 15 Feb 2022 16:40:31 +0100
Subject: [PATCH] allows preventing objects to be indexed

---
 autocomplete_multi_models/business_process.py |  4 ++++
 .../tests/test_business_process.py            | 19 +++++++++++++++++++
 .../tests/test_helpers.py                     |  3 +++
 autocomplete_multi_models/utils.py            |  6 ++++++
 4 files changed, 32 insertions(+)

diff --git a/autocomplete_multi_models/business_process.py b/autocomplete_multi_models/business_process.py
index 763c754..3f3ac19 100644
--- a/autocomplete_multi_models/business_process.py
+++ b/autocomplete_multi_models/business_process.py
@@ -14,6 +14,7 @@ _pattern = re.compile("[^\\w\\d]")
 _AUTOCOMPLETE_MIN_LENGTH = utils.DEFAULT_AUTOCOMPLETE_MIN_LENGTH
 _AUTOCOMPLETE_MIN_SIMILARITY = utils.DEFAULT_AUTOCOMPLETE_MIN_SIMILARITY
 _AUTOCOMPLETE_LIMIT = utils.DEFAULT_AUTOCOMPLETE_LIMIT
+_CAN_BE_INDEXED_BY_AUTOCOMPLETE_FUNCTION_NAME = utils.DEFAULT_CAN_BE_INDEXED_BY_AUTOCOMPLETE_FUNCTION_NAME
 
 
 def get_setting_from_storage(key, default):
@@ -49,6 +50,9 @@ def clean_duplicate():
 
 
 def add_instance_to_index(instance, field_names: List[str]):
+    f = getattr(instance, _CAN_BE_INDEXED_BY_AUTOCOMPLETE_FUNCTION_NAME, None)
+    if f and not f():
+        return
     for field_name in field_names:
         add_text_to_index(getattr(instance, field_name))
 
diff --git a/autocomplete_multi_models/tests/test_business_process.py b/autocomplete_multi_models/tests/test_business_process.py
index ccc8205..722fa2b 100644
--- a/autocomplete_multi_models/tests/test_business_process.py
+++ b/autocomplete_multi_models/tests/test_business_process.py
@@ -145,3 +145,22 @@ class WithTextModelTestCase(test_helpers.WithTextModelTestCase):
 
         signals.instance_delete(sender=test_helpers.WithTextModel, instance=o, field_names=["text"])
         self.assertEqual(1, models.IndexedWord.objects.count())
+
+    def test_conditional_indexing(self):
+        # there is a function indicating that NONONO should be not indexed
+        test_helpers.WithTextModel.objects.create(text="NONONO")
+        test_helpers.WithTextModel.objects.create(text="YESYES")
+        for o in test_helpers.WithTextModel.objects.all():
+            signals.instance_update(sender=test_helpers.WithTextModel, instance=o, field_names=["text"])
+        self.assertFalse(models.IndexedWord.objects.filter(word="NONONO"), "Prevented by class implementation")
+        self.assertTrue(models.IndexedWord.objects.filter(word="YESYES"), "Prevented by class implementation")
+
+    def test_absence_of_conditional_indexing(self):
+        # we remove the function, all instance should be indexed
+        test_helpers.WithTextModel.objects.create(text="NONONO")
+        test_helpers.WithTextModel.objects.create(text="YESYES")
+        for o in test_helpers.WithTextModel.objects.all():
+            setattr(o, utils.DEFAULT_CAN_BE_INDEXED_BY_AUTOCOMPLETE_FUNCTION_NAME, None)
+            signals.instance_update(sender=test_helpers.WithTextModel, instance=o, field_names=["text"])
+        self.assertTrue(models.IndexedWord.objects.filter(word="NONONO"), "Prevented by class implementation")
+        self.assertTrue(models.IndexedWord.objects.filter(word="YESYES"), "Prevented by class implementation")
diff --git a/autocomplete_multi_models/tests/test_helpers.py b/autocomplete_multi_models/tests/test_helpers.py
index 8739e75..5639221 100644
--- a/autocomplete_multi_models/tests/test_helpers.py
+++ b/autocomplete_multi_models/tests/test_helpers.py
@@ -20,6 +20,9 @@ class WithTextModel(models.Model):
         managed = False
         db_table = 'unmanaged_with_text_table'
 
+    def can_be_indexed_by_autocomplete(self):
+        return self.text != "NONONO"
+
     def __str__(self):
         return self.text
 
diff --git a/autocomplete_multi_models/utils.py b/autocomplete_multi_models/utils.py
index 6931cc0..456bc4f 100644
--- a/autocomplete_multi_models/utils.py
+++ b/autocomplete_multi_models/utils.py
@@ -6,6 +6,7 @@ DEFAULT_AUTOCOMPLETE_MIN_LENGTH = 4
 DEFAULT_AUTOCOMPLETE_MIN_SIMILARITY = 0.3
 DEFAULT_AUTOCOMPLETE_LIMIT = 10
 REBUILD_NEEDED = "is_autocomplete_multi_models_rebuild_needed"
+DEFAULT_CAN_BE_INDEXED_BY_AUTOCOMPLETE_FUNCTION_NAME = "can_be_indexed_by_autocomplete"
 
 
 def get_indexed_fields():
@@ -33,6 +34,11 @@ def init_from_settings():
         'AUTOCOMPLETE_LIMIT',
         DEFAULT_AUTOCOMPLETE_LIMIT,
     )
+    business_process._CAN_BE_INDEXED_BY_AUTOCOMPLETE_FUNCTION_NAME = getattr(
+        settings,
+        'CAN_BE_INDEXED_BY_AUTOCOMPLETE_FUNCTION_NAME',
+        DEFAULT_CAN_BE_INDEXED_BY_AUTOCOMPLETE_FUNCTION_NAME,
+    )
     get_set_names = getattr(settings, 'AUTOCOMPLETE_PERSISTENT_VARIABLE_GETTER_SETTER', None)
     if get_set_names is not None:
         get_fcn = import_string(get_set_names[0])
-- 
GitLab