Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Make JSON encoder extension point clear, and call super() properly fr…

…om decoder. Remove from_python(). Fix #42, #44.

We move JsonEncoder out to the module level and transplant the guts of from_python into JsonEncoder.default(). This makes it possible to call super() from the decoder, which would be very awkward from from_python().

The way to make the decoder aware of new types is now to subclass our JsonEncoder and stick your new class into an ElasticSearch object's json_encoder attr.

We take advantage of the new design to call super() from the decoder, which leads us raise a TypeError on unexpected input, as is usual with the json module, rather than a ValueError or other error.
  • Loading branch information...
commit c89ad05c254c3ea7dbdc075be835751df8eff042 1 parent c4f0a8b
@erikrose erikrose authored
Showing with 15 additions and 19 deletions.
  1. +11 −18 pyelasticsearch/client.py
  2. +4 −1 pyelasticsearch/tests.py
View
29 pyelasticsearch/client.py
@@ -120,18 +120,10 @@ def __init__(self, urls, timeout=60, max_retries=0, revival_delay=300):
urls = [u.rstrip('/') for u in urls]
self.servers = DowntimePronePool(urls, revival_delay)
self.revival_delay = revival_delay
-
self.timeout = timeout
self.max_retries = max_retries
self.logger = getLogger('pyelasticsearch')
self.session = requests.session()
-
- json_converter = self.from_python
-
- class JsonEncoder(json.JSONEncoder):
- def default(self, value):
- """Convert more Python data types to ES-understandable JSON."""
- return json_converter(value)
self.json_encoder = JsonEncoder
def _concat(self, items):
@@ -150,7 +142,7 @@ def _concat(self, items):
@classmethod
def _to_query(cls, obj):
- """Convert a native-Python object to a query string representation."""
+ """Convert a native-Python object to a query-string representation."""
# Quick and dirty thus far
if isinstance(obj, string_types):
return obj
@@ -257,9 +249,11 @@ def _raise_exception(self, response, decoded_body):
raise error_class(response.status_code, error_message)
- def _encode_json(self, body):
- """Return body encoded as JSON."""
- return json.dumps(body, cls=self.json_encoder, use_decimal=True)
+ def _encode_json(self, value):
+ """
+ Convert a Python value to a form suitable for ElasticSearch's JSON DSL.
+ """
+ return json.dumps(value, cls=self.json_encoder, use_decimal=True)
def _decode_response(self, response):
"""Return a native-Python representation of a response's JSON blob."""
@@ -897,10 +891,10 @@ def cluster_state(self, query_params=None):
return self.send_request(
'GET', ['_cluster', 'state'], query_params=query_params)
- def from_python(self, value):
- """
- Convert Python values to a form suitable for ElasticSearch's JSON.
- """
+
+class JsonEncoder(json.JSONEncoder):
+ def default(self, value):
+ """Convert more Python data types to ES-understandable JSON."""
iso = _iso_datetime(value)
if iso:
return iso
@@ -908,8 +902,7 @@ def from_python(self, value):
return unicode(value, errors='replace') # TODO: Be stricter.
if isinstance(value, set):
return list(value)
-
- return value
+ return super(JsonEncoder, self).default(value)
def _iso_datetime(value):
View
5 pyelasticsearch/tests.py
@@ -236,7 +236,6 @@ def testErrorHandling(self):
self.assertRaises(ConnectionError, conn.count, '*:*')
# Test invalid JSON.
- self.assertRaises(ValueError, conn._encode_json, object())
resp = requests.Response()
resp._content = six.b('{"busted" "json" "that": ["is] " wrong')
self.assertRaises(InvalidJsonResponseError, conn._decode_response, resp)
@@ -670,6 +669,10 @@ def test_tuple_encoding(self):
self.assertEqual(self.conn._encode_json({'hi': (1, 2, 3)}),
'{"hi": [1, 2, 3]}')
+ def test_unhandled_encoding(self):
+ """Make sure we raise a TypeError when encoding an unsupported type."""
+ self.assertRaises(TypeError, self.conn._encode_json, object())
+
def test_encoding(self):
"""Test encoding a zillion other types."""
self.assertEqual(self.conn._encode_json('abc'), u'"abc"')
Please sign in to comment.
Something went wrong with that request. Please try again.