diff --git a/pysolr.py b/pysolr.py index 59b4fcbd..b5e700bd 100644 --- a/pysolr.py +++ b/pysolr.py @@ -191,6 +191,9 @@ def safe_urlencode(params, doseq=0): which can't fail down to ascii. """ if IS_PY3: + for key, val in params.items(): + if isinstance(val, bool): + params[key] = str(val).lower() return urlencode(params, doseq) if hasattr(params, "items"): @@ -300,6 +303,16 @@ def __iter__(self): result = result._next_page_query and result._next_page_query() +def get_nested(obj, keys, default=None): + """Nested key lookup for a dict-like object.""" + try: + for k in keys: + obj = obj[k] + return obj + except KeyError: + return default + + class Solr(object): """ The main object for working with Solr. @@ -528,7 +541,7 @@ def _update( path_handler = handler if self.use_qt_param: path_handler = "select" - query_vars.append("qt=%s" % safe_urlencode(handler, True)) + query_vars.append("qt=%s" % handler) path = "%s/" % path_handler @@ -830,11 +843,17 @@ def search(self, q, search_handler=None, **kwargs): response = self._select(params, handler=search_handler) decoded = self.decoder.decode(response) - self.log.debug( - "Found '%s' search results.", - # cover both cases: there is no response key or value is None - (decoded.get("response", {}) or {}).get("numFound", 0), - ) + if decoded.get("grouped"): + group_key = next(iter(decoded["grouped"])) + self.log.debug( + "Found results grouped by '%s' with %d matches", + group_key, + decoded["grouped"][group_key]["matches"], + ) + else: + self.log.debug( + "Found %d docs", get_nested(decoded, ["response", "numFound"], 0) + ) cursorMark = params.get("cursorMark", None) if cursorMark != decoded.get("nextCursorMark", cursorMark): diff --git a/tests/test_client.py b/tests/test_client.py index 7a7ed5af..9f23b9b1 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -3,6 +3,7 @@ from __future__ import absolute_import, unicode_literals import datetime +import json import random import time import unittest @@ -17,7 +18,7 @@ clean_xml_string, force_bytes, force_unicode, - json, + get_nested, safe_urlencode, sanitize, unescape_html, @@ -72,6 +73,9 @@ def test_safe_urlencode(self): "test=Hello \u2603!&test=Helllo world!", ) + # Boolean options for Solr should be in lowercase. + self.assertTrue("True" not in safe_urlencode({"group": True})) + def test_sanitize(self): self.assertEqual( sanitize( @@ -101,6 +105,12 @@ def test_force_bytes(self): def test_clean_xml_string(self): self.assertEqual(clean_xml_string("\x00\x0b\x0d\uffff"), "\x0d") + def test_get_nested(self): + doc = {"a": {"b": {"c": 2023}}} + self.assertEqual(get_nested(doc, ["a", "e"]), None) + self.assertEqual(get_nested(doc, ["a"]), doc["a"]) + self.assertEqual(get_nested(doc, ["a", "b", "c"]), doc["a"]["b"]["c"]) + class ResultsTestCase(unittest.TestCase): def test_init(self):