This is an automated email from the ASF dual-hosted git repository.

iilyak pushed a commit to branch improve-errors-in-mango-tests
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 9cdb361f5febc4279e6d039efd1693d672bf11c8
Author: ILYA Khlopotov <[email protected]>
AuthorDate: Thu Sep 18 11:57:35 2025 -0700

    Print response body on  errors from mango test suite
    
    Add `body` to error messages do error would look like
    
    ```
    ======================================================================
    ERROR: test_group_field_number_is_unsupported 
(99-test_query.TestQuery.test_group_field_number_is_unsupported)
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "~/Code/couchdb/src/mango/test/99-test_query.py", line 163, in 
test_group_field_number_is_unsupported
        self.db.create_text_index(name="animals")
      File "~/Code/couchdb/src/mango/test/mango.py", line 261, in 
create_text_index
        raise_for_status(r)
      File "~/Code/couchdb/src/mango/test/mango.py", line 102, in 
raise_for_status
        raise SearchException(err) from None
    mango.SearchException: 503 Server Error: Service Unavailable for url: 
http://127.0.0.1:15984/mango_test_123c0654f1e84db7aed9d380062d8131/_index
    body: {"error":"required index service unavailable","reason":"text"}
    ```
---
 src/mango/test/02-basic-find-test.py |  2 +-
 src/mango/test/mango.py              | 38 ++++++++++++++++++++++++------------
 2 files changed, 27 insertions(+), 13 deletions(-)

diff --git a/src/mango/test/02-basic-find-test.py 
b/src/mango/test/02-basic-find-test.py
index 9a701b06d..cae772b8a 100644
--- a/src/mango/test/02-basic-find-test.py
+++ b/src/mango/test/02-basic-find-test.py
@@ -139,7 +139,7 @@ class BasicFindTests(mango.UserDocsTests):
             '"location.city":{"$exists":true}}}'
         )
         r = self.db.sess.post(self.db.path("_find"), data=body)
-        r.raise_for_status()
+        mango.raise_for_status(r)
         docs = r.json()["docs"]
 
         # expectation is that only the second instance
diff --git a/src/mango/test/mango.py b/src/mango/test/mango.py
index f0a8b1582..972bbd4aa 100644
--- a/src/mango/test/mango.py
+++ b/src/mango/test/mango.py
@@ -25,6 +25,15 @@ import friend_docs
 import user_docs
 import limit_docs
 
+class SearchException(requests.exceptions.HTTPError):
+    def __init__(self, err: requests.exceptions.HTTPError):
+        super().__init__(str(err), response=err.response)
+        self.request = err.request
+        self.response = err.response
+    def __str__(self):
+        formatted = super().__str__()
+        body = "body: {}".format(self.response.text)
+        return '\n'.join([formatted, body])
 
 COUCH_HOST = os.environ.get("COUCH_HOST") or "http://127.0.0.1:15984";
 COUCH_USER = os.environ.get("COUCH_USER")
@@ -65,6 +74,11 @@ def delay(n=5, t=0.5):
     for i in range(0, n):
         time.sleep(t)
 
+def raise_for_status(resp):
+    try:
+        resp.raise_for_status()
+    except requests.exceptions.HTTPError as err:
+        raise SearchException(err) from None
 
 class Concurrently(object):
     def __init__(self, thread, thread_args, start=True):
@@ -108,11 +122,11 @@ class Database(object):
         if r.status_code == 404:
             p = str(partitioned).lower()
             r = self.sess.put(self.url, params={"q": q, "n": n, "partitioned": 
p})
-            r.raise_for_status()
+            raise_for_status(r)
 
     def delete(self):
         r = self.sess.delete(self.url)
-        r.raise_for_status()
+        raise_for_status(r)
 
     def recreate(self):
         r = self.sess.get(self.url)
@@ -132,32 +146,32 @@ class Database(object):
     def save_docs_with_conflicts(self, docs, **kwargs):
         body = json.dumps({"docs": docs, "new_edits": False})
         r = self.sess.post(self.path("_bulk_docs"), data=body, params=kwargs)
-        r.raise_for_status()
+        raise_for_status(r)
 
     def save_docs(self, docs, **kwargs):
         for offset in range(0, len(docs), BULK_BATCH_SIZE):
             chunk = docs[offset : (offset + BULK_BATCH_SIZE)]
             body = {"docs": chunk}
             r = self.sess.post(self.path("_bulk_docs"), json=body, 
params=kwargs)
-            r.raise_for_status()
+            raise_for_status(r)
             for doc, result in zip(chunk, r.json()):
                 doc["_id"] = result["id"]
                 doc["_rev"] = result["rev"]
 
     def open_doc(self, docid):
         r = self.sess.get(self.path(docid))
-        r.raise_for_status()
+        raise_for_status(r)
         return r.json()
 
     def delete_doc(self, docid):
         r = self.sess.get(self.path(docid))
-        r.raise_for_status()
+        raise_for_status(r)
         original_rev = r.json()["_rev"]
         self.sess.delete(self.path(docid), params={"rev": original_rev})
 
     def ddoc_info(self, ddocid):
         r = self.sess.get(self.path([ddocid, "_info"]))
-        r.raise_for_status()
+        raise_for_status(r)
         return r.json()
 
     def create_index(
@@ -180,7 +194,7 @@ class Database(object):
             body["index"]["partial_filter_selector"] = partial_filter_selector
         body = json.dumps(body)
         r = self.sess.post(self.path("_index"), data=body)
-        r.raise_for_status()
+        raise_for_status(r)
         assert r.json()["id"] is not None
         assert r.json()["name"] is not None
 
@@ -223,7 +237,7 @@ class Database(object):
             body["ddoc"] = ddoc
         body = json.dumps(body)
         r = self.sess.post(self.path("_index"), data=body)
-        r.raise_for_status()
+        raise_for_status(r)
         return r.json()["result"] == "created"
 
     def list_indexes(self, limit="", skip=""):
@@ -232,7 +246,7 @@ class Database(object):
         if skip != "":
             skip = "skip=" + str(skip)
         r = self.sess.get(self.path("_index?" + limit + ";" + skip))
-        r.raise_for_status()
+        raise_for_status(r)
         return r.json()["indexes"]
 
     def get_index(self, ddocid, name):
@@ -255,7 +269,7 @@ class Database(object):
     def delete_index(self, ddocid, name, idx_type="json"):
         path = ["_index", ddocid, idx_type, name]
         r = self.sess.delete(self.path(path), params={"w": "3"})
-        r.raise_for_status()
+        raise_for_status(r)
 
         while len(self.get_index(ddocid, name)) == 1:
             delay(t=0.1)
@@ -314,7 +328,7 @@ class Database(object):
         else:
             path = self.path("{}_find".format(ppath))
         r = self.sess.post(path, data=body)
-        r.raise_for_status()
+        raise_for_status(r)
         if explain or return_raw:
             return r.json()
         else:

Reply via email to