Permalink
Browse files

Port to_python over from pyelasticsearch so django-haystack works wit…

…h 0.4.

This should keep people from getting "hit in the face" with errors when they try to use the haystack ES backend. :-) pyelasticsearch/pyelasticsearch#86

We removed the internally unused and undocumented to_python in pyelasticsearch 0.4. I copied the version from 4266529eaefb96af0a8e99017740cbb56608dbe4 and removed the `six` dependencies.

I'm actually not sure why haystack needs to call anything like to_python itself; pyelasticsearch implicitly converts most data types, though datetimes are a notable hole. But this is a quick fix.
  • Loading branch information...
1 parent 46b8117 commit 181bbc2c010a135b536e4d1f7a1c5ae4c63e33db @erikrose erikrose committed Mar 20, 2013
Showing with 44 additions and 1 deletion.
  1. +44 −1 haystack/backends/elasticsearch_backend.py
@@ -1,4 +1,5 @@
import datetime
+import re
import warnings
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
@@ -22,6 +23,11 @@
raise MissingDependency("The 'elasticsearch' backend requires the installation of 'pyelasticsearch'. Please refer to the documentation.")
+DATETIME_REGEX = re.compile(
+ r'^(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})T'
+ r'(?P<hour>\d{2}):(?P<minute>\d{2}):(?P<second>\d{2})(\.\d+)?$')
+
+
class ElasticsearchSearchBackend(BaseSearchBackend):
# Word reserved by Elasticsearch for special use.
RESERVED_WORDS = (
@@ -583,7 +589,7 @@ def _process_results(self, raw_results, highlight=False,
if string_key in index.fields and hasattr(index.fields[string_key], 'convert'):
additional_fields[string_key] = index.fields[string_key].convert(value)
else:
- additional_fields[string_key] = self.conn.to_python(value)
+ additional_fields[string_key] = self._to_python(value)
del(additional_fields[DJANGO_CT])
del(additional_fields[DJANGO_ID])
@@ -666,6 +672,43 @@ def build_schema(self, fields):
return (content_field_name, mapping)
+ def _to_python(self, value):
+ """Convert values from ElasticSearch to native Python values."""
+ if isinstance(value, (int, float, complex, list, tuple, bool)):
+ return value
+
+ if isinstance(value, basestring):
+ possible_datetime = DATETIME_REGEX.search(value)
+
+ if possible_datetime:
+ date_values = possible_datetime.groupdict()
+
+ for dk, dv in date_values.items():
+ date_values[dk] = int(dv)
+
+ return datetime(
+ date_values['year'], date_values['month'],
+ date_values['day'], date_values['hour'],
+ date_values['minute'], date_values['second'])
+
+ try:
+ # This is slightly gross but it's hard to tell otherwise what the
+ # string's original type might have been. Be careful who you trust.
+ converted_value = eval(value)
+
+ # Try to handle most built-in types.
+ if isinstance(
+ converted_value,
+ (int, list, tuple, set, dict, float, complex)):
+ return converted_value
+ except Exception:
+ # If it fails (SyntaxError or its ilk) or we don't trust it,
+ # continue on.
+ pass
+
+ return value
+
+
# Sucks that this is almost an exact copy of what's in the Solr backend,
# but we can't import due to dependencies.

0 comments on commit 181bbc2

Please sign in to comment.