Skip to content

Commit c833a40

Browse files
committed
should_index: handle unbound method
1 parent 4bcc6a0 commit c833a40

File tree

3 files changed

+43
-4
lines changed

3 files changed

+43
-4
lines changed

src/models.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,9 @@ def __init__(self, model, client):
101101
should_index_attr_name = self.should_index
102102
if isinstance(attr, bool):
103103
self.should_index = lambda instance: getattr(instance, should_index_attr_name) is True
104+
self.should_index._is_default = True
104105
else:
105-
raise AlgoliaIndexError('{} should be a callable or a boolean attribute.'.format(
106+
raise AlgoliaIndexError('{} should be a bound callable or a boolean attribute.'.format(
106107
self.should_index))
107108
else:
108109
raise AlgoliaIndexError('{} is not an attribute of {}.'.format(
@@ -194,7 +195,7 @@ def _build_object(self, instance):
194195
def update_obj_index(self, instance):
195196
'''Update the object.'''
196197
if self.should_index:
197-
if not self.should_index(instance):
198+
if not self._should_really_index(instance):
198199
# Should not index, but since we don't now the state of the
199200
# instance, we need to send a DELETE request to ensure that if
200201
# the instance was previously indexed, it will be removed.
@@ -206,8 +207,20 @@ def update_obj_index(self, instance):
206207
logger.debug('UPDATE %s FROM %s', obj['objectID'], self.model)
207208

208209
def _should_index(self, instance):
209-
'''Return true if the object should be indexed.'''
210-
return self.should_index(instance) if self.should_index else True
210+
"""Return true if the object should be indexed (including when self.should_index is not set)."""
211+
if self.should_index:
212+
return self._should_really_index(instance)
213+
else:
214+
return True
215+
216+
def _should_really_index(self, instance):
217+
"""Return true if according to should_index the object should be indexed."""
218+
if hasattr(self.should_index, "__self__") or hasattr(self.should_index, '_is_default'):
219+
# bound method or lambda, let's use instance
220+
return self.should_index(instance)
221+
else:
222+
# unbound method, simply call without arguments
223+
return self.should_index()
211224

212225
def delete_obj_index(self, instance):
213226
'''Delete the object.'''

tests/models.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,11 @@ def geolocations(self):
1919

2020
def has_name(self):
2121
return self.name is not None
22+
23+
@staticmethod
24+
def static_should_index():
25+
return True
26+
27+
@staticmethod
28+
def static_should_not_index():
29+
return False

tests/test_index.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,24 @@ class ExampleIndex(AlgoliaIndex):
182182
self.assertFalse(index._should_index(instance_should_not),
183183
"We should not index an instance when should_index(instance) returns False")
184184

185+
def test_should_index_unbound(self):
186+
class ExampleIndex(AlgoliaIndex):
187+
fields = 'name'
188+
should_index = 'static_should_index'
189+
index = ExampleIndex(Example, self.client)
190+
obj = index._build_object(self.instance)
191+
self.assertTrue(index._should_index(self.instance),
192+
"We should index an instance when should_index() returns True")
193+
194+
class ExampleIndex(AlgoliaIndex):
195+
fields = 'name'
196+
should_index = 'static_should_not_index'
197+
index = ExampleIndex(Example, self.client)
198+
instance_should_not = Example()
199+
obj = index._build_object(instance_should_not)
200+
self.assertFalse(index._should_index(instance_should_not),
201+
"We should not index an instance when should_index() returns False")
202+
185203
def test_should_index_attr(self):
186204
class ExampleIndex(AlgoliaIndex):
187205
fields = 'name'

0 commit comments

Comments
 (0)