From aa7b93ce992fa9f67cac0c918c480b0a9bb2e7e0 Mon Sep 17 00:00:00 2001 From: Valerii Tatarin Date: Wed, 17 Apr 2024 17:11:13 -0700 Subject: [PATCH 01/21] query_runner: add debug log --- redash/query_runner/query_results.py | 1 + 1 file changed, 1 insertion(+) diff --git a/redash/query_runner/query_results.py b/redash/query_runner/query_results.py index 5bc0eed29a..03e844f182 100644 --- a/redash/query_runner/query_results.py +++ b/redash/query_runner/query_results.py @@ -137,6 +137,7 @@ def create_table(connection, table_name, query_results): for row in query_results["rows"]: values = [flatten(row.get(column)) for column in columns] + logger.debug("INSERT query: %s. VALUES: %s", insert_template, values) connection.execute(insert_template, values) From fb4163c69ed4727e95f60d0db80bd5fd25ef682f Mon Sep 17 00:00:00 2001 From: Valerii Tatarin Date: Wed, 17 Apr 2024 17:14:01 -0700 Subject: [PATCH 02/21] query_runner: add debug log --- redash/query_runner/query_results.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/redash/query_runner/query_results.py b/redash/query_runner/query_results.py index 03e844f182..5478b27ab9 100644 --- a/redash/query_runner/query_results.py +++ b/redash/query_runner/query_results.py @@ -137,7 +137,7 @@ def create_table(connection, table_name, query_results): for row in query_results["rows"]: values = [flatten(row.get(column)) for column in columns] - logger.debug("INSERT query: %s. VALUES: %s", insert_template, values) + logger.debug("INSERT query: %s; VALUES: %s", insert_template, values) connection.execute(insert_template, values) From 4e7e468dce4f42976e625758d54ae969464d3ecb Mon Sep 17 00:00:00 2001 From: Valerii Tatarin Date: Thu, 18 Apr 2024 03:53:34 +0000 Subject: [PATCH 03/21] handle datetime.time --- redash/query_runner/query_results.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/redash/query_runner/query_results.py b/redash/query_runner/query_results.py index 5478b27ab9..9bcefa9dcc 100644 --- a/redash/query_runner/query_results.py +++ b/redash/query_runner/query_results.py @@ -28,6 +28,10 @@ class CreateTableError(Exception): pass +class UnsupportedTypeError(Exception): + pass + + def extract_query_params(query): return re.findall(r"(?:join|from)\s+param_query_(\d+)_{([^}]+)}", query, re.IGNORECASE) @@ -109,7 +113,7 @@ def flatten(value): return json_dumps(value) elif isinstance(value, decimal.Decimal): return float(value) - elif isinstance(value, datetime.timedelta): + elif isinstance(value, (datetime.timedelta, datetime.time)): return str(value) else: return value @@ -137,8 +141,13 @@ def create_table(connection, table_name, query_results): for row in query_results["rows"]: values = [flatten(row.get(column)) for column in columns] - logger.debug("INSERT query: %s; VALUES: %s", insert_template, values) - connection.execute(insert_template, values) + try: + connection.execute(insert_template, values) + except sqlite3.InterfaceError as exc: + raise UnsupportedTypeError("Error inserting data: %s. Template: %s. Value data types: %s", + str(exc), + insert_template, + ",".join(str(type(value)) for value in values)) def prepare_parameterized_query(query, query_params): From 11e4f0b266862463798e99a9583d2c60a2552d1b Mon Sep 17 00:00:00 2001 From: Valerii Tatarin Date: Wed, 17 Apr 2024 20:54:51 -0700 Subject: [PATCH 04/21] query_runner: add debug log --- redash/query_runner/query_results.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/redash/query_runner/query_results.py b/redash/query_runner/query_results.py index 5478b27ab9..9bcefa9dcc 100644 --- a/redash/query_runner/query_results.py +++ b/redash/query_runner/query_results.py @@ -28,6 +28,10 @@ class CreateTableError(Exception): pass +class UnsupportedTypeError(Exception): + pass + + def extract_query_params(query): return re.findall(r"(?:join|from)\s+param_query_(\d+)_{([^}]+)}", query, re.IGNORECASE) @@ -109,7 +113,7 @@ def flatten(value): return json_dumps(value) elif isinstance(value, decimal.Decimal): return float(value) - elif isinstance(value, datetime.timedelta): + elif isinstance(value, (datetime.timedelta, datetime.time)): return str(value) else: return value @@ -137,8 +141,13 @@ def create_table(connection, table_name, query_results): for row in query_results["rows"]: values = [flatten(row.get(column)) for column in columns] - logger.debug("INSERT query: %s; VALUES: %s", insert_template, values) - connection.execute(insert_template, values) + try: + connection.execute(insert_template, values) + except sqlite3.InterfaceError as exc: + raise UnsupportedTypeError("Error inserting data: %s. Template: %s. Value data types: %s", + str(exc), + insert_template, + ",".join(str(type(value)) for value in values)) def prepare_parameterized_query(query, query_params): From 1f4853eb1ce2c86464553df4bf4f03621b1d9c94 Mon Sep 17 00:00:00 2001 From: Valerii Tatarin Date: Wed, 17 Apr 2024 20:58:07 -0700 Subject: [PATCH 05/21] fmt --- redash/query_runner/query_results.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/redash/query_runner/query_results.py b/redash/query_runner/query_results.py index 9bcefa9dcc..80299b7c08 100644 --- a/redash/query_runner/query_results.py +++ b/redash/query_runner/query_results.py @@ -144,10 +144,12 @@ def create_table(connection, table_name, query_results): try: connection.execute(insert_template, values) except sqlite3.InterfaceError as exc: - raise UnsupportedTypeError("Error inserting data: %s. Template: %s. Value data types: %s", - str(exc), - insert_template, - ",".join(str(type(value)) for value in values)) + raise UnsupportedTypeError( + "Error inserting data: %s. Template: %s. Value data types: %s", + str(exc), + insert_template, + ",".join(str(type(value)) for value in values), + ) def prepare_parameterized_query(query, query_params): From e0ae3ba9de81206835cbd8c1e828a17c4c7b568d Mon Sep 17 00:00:00 2001 From: Valerii Tatarin Date: Wed, 17 Apr 2024 23:11:01 -0700 Subject: [PATCH 06/21] add debug --- redash/query_runner/query_results.py | 29 ++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/redash/query_runner/query_results.py b/redash/query_runner/query_results.py index 80299b7c08..05265b75df 100644 --- a/redash/query_runner/query_results.py +++ b/redash/query_runner/query_results.py @@ -28,10 +28,6 @@ class CreateTableError(Exception): pass -class UnsupportedTypeError(Exception): - pass - - def extract_query_params(query): return re.findall(r"(?:join|from)\s+param_query_(\d+)_{([^}]+)}", query, re.IGNORECASE) @@ -113,9 +109,13 @@ def flatten(value): return json_dumps(value) elif isinstance(value, decimal.Decimal): return float(value) - elif isinstance(value, (datetime.timedelta, datetime.time)): + elif isinstance(value, (datetime.date, datetime.time, datetime.datetime, datetime.timedelta)): return str(value) + elif value is None: + return 'NULL' else: + if not isinstance(value, (str, float, int)): + logger.debug("flatten() found new type: %s", str(type(value))) return value @@ -138,18 +138,19 @@ def create_table(connection, table_name, query_results): column_list=column_list, place_holders=",".join(["?"] * len(columns)), ) + logger.debug("INSERT template: %s", insert_template) for row in query_results["rows"]: values = [flatten(row.get(column)) for column in columns] - try: - connection.execute(insert_template, values) - except sqlite3.InterfaceError as exc: - raise UnsupportedTypeError( - "Error inserting data: %s. Template: %s. Value data types: %s", - str(exc), - insert_template, - ",".join(str(type(value)) for value in values), - ) + # try: + # for value in values: + # logger.debug("Value: %s, Type: %s", str(value), str(type(value))) + connection.execute(insert_template, values) + # except Exception as e: + # if logger.isEnabledFor(logging.DEBUG): + # for value in values: + # logger.debug("Value: %s, Type: %s", str(value), str(type(value))) + # raise Exception("Error inserting data: %s", str(e)) def prepare_parameterized_query(query, query_params): From 051ed0791c581e5c82aa150e9821a1185fdd1d61 Mon Sep 17 00:00:00 2001 From: Valerii Tatarin Date: Thu, 18 Apr 2024 19:50:16 +0000 Subject: [PATCH 07/21] athena ds: fallback to default creds if RoleArn is not provided --- redash/query_runner/athena.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/redash/query_runner/athena.py b/redash/query_runner/athena.py index 0a5f648417..8a32a04560 100644 --- a/redash/query_runner/athena.py +++ b/redash/query_runner/athena.py @@ -153,7 +153,9 @@ def type(cls): return "athena" def _get_iam_credentials(self, user=None): - if ASSUME_ROLE: + # Use the default credentials if iam_role is not provided + # 20 is the default botocore ParamValidation: Invalid length for parameter RoleArn, value: 0, valid min length: 20 + if ASSUME_ROLE and len(self.configuration.get("iam_role")) >= 20: role_session_name = "redash" if user is None else user.email sts = boto3.client("sts") creds = sts.assume_role( From 17c00d676e9b456e5eaf016a78f19be597216d26 Mon Sep 17 00:00:00 2001 From: Valerii Tatarin Date: Thu, 18 Apr 2024 20:25:37 +0000 Subject: [PATCH 08/21] pull changes --- redash/query_runner/query_results.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/redash/query_runner/query_results.py b/redash/query_runner/query_results.py index 8ecdbfb3b9..05265b75df 100644 --- a/redash/query_runner/query_results.py +++ b/redash/query_runner/query_results.py @@ -28,10 +28,6 @@ class CreateTableError(Exception): pass -class UnsupportedTypeError(Exception): - pass - - def extract_query_params(query): return re.findall(r"(?:join|from)\s+param_query_(\d+)_{([^}]+)}", query, re.IGNORECASE) From be111d3885baaa1afe5da871987566c107d7453f Mon Sep 17 00:00:00 2001 From: Valerii Tatarin Date: Fri, 19 Apr 2024 00:02:04 +0000 Subject: [PATCH 09/21] expose error messae --- redash/serializers/__init__.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/redash/serializers/__init__.py b/redash/serializers/__init__.py index 41a370e43e..f04f136151 100644 --- a/redash/serializers/__init__.py +++ b/redash/serializers/__init__.py @@ -280,6 +280,7 @@ def serialize_job(job): JobStatus.CANCELED: 5, JobStatus.DEFERRED: 6, JobStatus.SCHEDULED: 7, + JobStatus.STOPPED: 8 } job_status = job.get_status() @@ -301,7 +302,8 @@ def serialize_job(job): error = job.result["error"] status = 4 else: - error = "" + status = 4 + error = str(job.exc_info) result = query_result_id = job.result return { From 26b5f7cb2cbe04e7ecbbfe1e3be7cf9784cd0ecb Mon Sep 17 00:00:00 2001 From: Valerii Tatarin Date: Fri, 19 Apr 2024 01:36:39 +0000 Subject: [PATCH 10/21] expose error messae --- redash/serializers/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/redash/serializers/__init__.py b/redash/serializers/__init__.py index f04f136151..e52d3e5883 100644 --- a/redash/serializers/__init__.py +++ b/redash/serializers/__init__.py @@ -302,7 +302,6 @@ def serialize_job(job): error = job.result["error"] status = 4 else: - status = 4 error = str(job.exc_info) result = query_result_id = job.result From 8d155bf957dd01a0b864879a3f36e4c6222f6b2c Mon Sep 17 00:00:00 2001 From: Valerii Tatarin Date: Fri, 19 Apr 2024 23:24:11 +0000 Subject: [PATCH 11/21] revert additional changes --- redash/query_runner/athena.py | 4 +--- redash/query_runner/query_results.py | 15 +++------------ redash/serializers/__init__.py | 4 +--- 3 files changed, 5 insertions(+), 18 deletions(-) diff --git a/redash/query_runner/athena.py b/redash/query_runner/athena.py index 8a32a04560..0a5f648417 100644 --- a/redash/query_runner/athena.py +++ b/redash/query_runner/athena.py @@ -153,9 +153,7 @@ def type(cls): return "athena" def _get_iam_credentials(self, user=None): - # Use the default credentials if iam_role is not provided - # 20 is the default botocore ParamValidation: Invalid length for parameter RoleArn, value: 0, valid min length: 20 - if ASSUME_ROLE and len(self.configuration.get("iam_role")) >= 20: + if ASSUME_ROLE: role_session_name = "redash" if user is None else user.email sts = boto3.client("sts") creds = sts.assume_role( diff --git a/redash/query_runner/query_results.py b/redash/query_runner/query_results.py index 05265b75df..2effc24fbe 100644 --- a/redash/query_runner/query_results.py +++ b/redash/query_runner/query_results.py @@ -111,11 +111,10 @@ def flatten(value): return float(value) elif isinstance(value, (datetime.date, datetime.time, datetime.datetime, datetime.timedelta)): return str(value) - elif value is None: - return 'NULL' else: - if not isinstance(value, (str, float, int)): - logger.debug("flatten() found new type: %s", str(type(value))) + if logging.isEnabledFor(logging.DEBUG): + if not isinstance(value, (type(None), str, float, int)): + logger.debug("flatten() found unhandled type: %s", str(type(value))) return value @@ -142,15 +141,7 @@ def create_table(connection, table_name, query_results): for row in query_results["rows"]: values = [flatten(row.get(column)) for column in columns] - # try: - # for value in values: - # logger.debug("Value: %s, Type: %s", str(value), str(type(value))) connection.execute(insert_template, values) - # except Exception as e: - # if logger.isEnabledFor(logging.DEBUG): - # for value in values: - # logger.debug("Value: %s, Type: %s", str(value), str(type(value))) - # raise Exception("Error inserting data: %s", str(e)) def prepare_parameterized_query(query, query_params): diff --git a/redash/serializers/__init__.py b/redash/serializers/__init__.py index e52d3e5883..dfc1a05706 100644 --- a/redash/serializers/__init__.py +++ b/redash/serializers/__init__.py @@ -279,8 +279,7 @@ def serialize_job(job): JobStatus.FAILED: 4, JobStatus.CANCELED: 5, JobStatus.DEFERRED: 6, - JobStatus.SCHEDULED: 7, - JobStatus.STOPPED: 8 + JobStatus.SCHEDULED: 7 } job_status = job.get_status() @@ -302,7 +301,6 @@ def serialize_job(job): error = job.result["error"] status = 4 else: - error = str(job.exc_info) result = query_result_id = job.result return { From 374e6bfde86252bf054e7ff883c42ac198154a42 Mon Sep 17 00:00:00 2001 From: Valerii Tatarin Date: Fri, 19 Apr 2024 23:24:44 +0000 Subject: [PATCH 12/21] revert additional changes --- redash/serializers/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/redash/serializers/__init__.py b/redash/serializers/__init__.py index dfc1a05706..60abdc32ba 100644 --- a/redash/serializers/__init__.py +++ b/redash/serializers/__init__.py @@ -279,7 +279,7 @@ def serialize_job(job): JobStatus.FAILED: 4, JobStatus.CANCELED: 5, JobStatus.DEFERRED: 6, - JobStatus.SCHEDULED: 7 + JobStatus.SCHEDULED: 7, } job_status = job.get_status() From 1a7f20434ccc29c88ca52f061d177c2b430d70c3 Mon Sep 17 00:00:00 2001 From: Valerii Tatarin Date: Fri, 19 Apr 2024 23:25:33 +0000 Subject: [PATCH 13/21] revert additional changes --- redash/serializers/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/redash/serializers/__init__.py b/redash/serializers/__init__.py index 60abdc32ba..41a370e43e 100644 --- a/redash/serializers/__init__.py +++ b/redash/serializers/__init__.py @@ -301,6 +301,7 @@ def serialize_job(job): error = job.result["error"] status = 4 else: + error = "" result = query_result_id = job.result return { From d22df7c08b3d37a2b8419a0e19d0d64dc086f907 Mon Sep 17 00:00:00 2001 From: Valerii Tatarin Date: Mon, 29 Apr 2024 15:27:15 -0700 Subject: [PATCH 14/21] Update redash/query_runner/query_results.py Co-authored-by: Andrii Chubatiuk --- redash/query_runner/query_results.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/redash/query_runner/query_results.py b/redash/query_runner/query_results.py index 2effc24fbe..422e0931f6 100644 --- a/redash/query_runner/query_results.py +++ b/redash/query_runner/query_results.py @@ -112,7 +112,7 @@ def flatten(value): elif isinstance(value, (datetime.date, datetime.time, datetime.datetime, datetime.timedelta)): return str(value) else: - if logging.isEnabledFor(logging.DEBUG): + if logger.isEnabledFor(logging.DEBUG): if not isinstance(value, (type(None), str, float, int)): logger.debug("flatten() found unhandled type: %s", str(type(value))) return value From 30776b34b26379acb5c21f522c77faee88b6c3f6 Mon Sep 17 00:00:00 2001 From: Valerii Tatarin Date: Mon, 29 Apr 2024 22:29:10 +0000 Subject: [PATCH 15/21] review edits --- redash/query_runner/query_results.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/redash/query_runner/query_results.py b/redash/query_runner/query_results.py index 422e0931f6..028b7bc229 100644 --- a/redash/query_runner/query_results.py +++ b/redash/query_runner/query_results.py @@ -113,7 +113,7 @@ def flatten(value): return str(value) else: if logger.isEnabledFor(logging.DEBUG): - if not isinstance(value, (type(None), str, float, int)): + if not isinstance(value, (type(None), str, float, int, bool)): logger.debug("flatten() found unhandled type: %s", str(type(value))) return value From a181ba948c685eb89bdb83dc61dff85987f7f9c9 Mon Sep 17 00:00:00 2001 From: Valerii Tatarin Date: Tue, 30 Apr 2024 00:53:28 +0000 Subject: [PATCH 16/21] add tests --- tests/query_runner/test_query_results.py | 55 ++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/tests/query_runner/test_query_results.py b/tests/query_runner/test_query_results.py index 1c7ff70cc8..6c9456617b 100644 --- a/tests/query_runner/test_query_results.py +++ b/tests/query_runner/test_query_results.py @@ -1,6 +1,7 @@ import datetime import decimal import sqlite3 +import logging from unittest import TestCase import mock @@ -18,6 +19,7 @@ get_query_results, prepare_parameterized_query, replace_query_parameters, + flatten, ) from tests import BaseTestCase @@ -248,3 +250,56 @@ def test_non_cached_query_result(self): query_result_data = {"columns": [], "rows": []} qr.return_value = (query_result_data, None) self.assertEqual(query_result_data, get_query_results(self.factory.user, query.id, False)) + + +class TestFlattenFunction(BaseTestCase): + def test_flatten_with_string(self): + self.assertEqual(flatten("hello"), "hello") + + def test_flatten_with_integer(self): + self.assertEqual(flatten(10), 10) + + def test_flatten_with_float(self): + self.assertEqual(flatten(10.5), 10.5) + + def test_flatten_with_boolean(self): + self.assertEqual(flatten(True), True) + + def test_flatten_with_decimal(self): + self.assertEqual(flatten(decimal.Decimal('10.5')), 10.5) + + def test_flatten_with_date(self): + date = datetime.date(2021, 1, 1) + self.assertEqual(flatten(date), "2021-01-01") + + def test_flatten_with_time(self): + time = datetime.time(12, 30) + self.assertEqual(flatten(time), "12:30:00") + + def test_flatten_with_datetime(self): + datetime_obj = datetime.datetime(2021, 1, 1, 12, 30) + self.assertEqual(flatten(datetime_obj), "2021-01-01 12:30:00") + + def test_flatten_with_timedelta(self): + timedelta_obj = datetime.timedelta(days=2) + self.assertEqual(flatten(timedelta_obj), "2 days, 0:00:00") + + def test_flatten_with_list(self): + self.assertEqual(flatten([1, 2, 3]), '[1, 2, 3]') + + def test_flatten_with_dictionary(self): + self.assertEqual(flatten({'key': 'value'}), '{"key": "value"}') + + def test_flatten_with_none(self): + self.assertEqual(flatten(None), None) + + def test_flatten_unhandled_type(self): + class CustomType: + pass + instance = CustomType() + with self.assertLogs('redash.query_runner.query_results', level='DEBUG') as log: + result = flatten(instance) + self.assertEqual(result, instance) # Assuming flatten returns instance directly for unhandled types + + # Check for the presence of a specific log message + self.assertIn("flatten() found unhandled type: %s" % str(type(instance)), log.output[0]) From d3f8caddb2c35afa729ab52f3db217d9a0f495aa Mon Sep 17 00:00:00 2001 From: Valerii Tatarin Date: Tue, 30 Apr 2024 00:57:30 +0000 Subject: [PATCH 17/21] add tests --- tests/query_runner/test_query_results.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/query_runner/test_query_results.py b/tests/query_runner/test_query_results.py index 6c9456617b..e07d88e245 100644 --- a/tests/query_runner/test_query_results.py +++ b/tests/query_runner/test_query_results.py @@ -252,7 +252,7 @@ def test_non_cached_query_result(self): self.assertEqual(query_result_data, get_query_results(self.factory.user, query.id, False)) -class TestFlattenFunction(BaseTestCase): +class TestFlattenFunction(TestCase): def test_flatten_with_string(self): self.assertEqual(flatten("hello"), "hello") From 0778b71b87bb46f34031836c7b65f67ea7c709ed Mon Sep 17 00:00:00 2001 From: Valerii Tatarin Date: Tue, 30 Apr 2024 02:32:11 +0000 Subject: [PATCH 18/21] fmt --- tests/query_runner/test_query_results.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/query_runner/test_query_results.py b/tests/query_runner/test_query_results.py index e07d88e245..14e386b578 100644 --- a/tests/query_runner/test_query_results.py +++ b/tests/query_runner/test_query_results.py @@ -1,7 +1,6 @@ import datetime import decimal import sqlite3 -import logging from unittest import TestCase import mock @@ -16,10 +15,10 @@ extract_query_ids, extract_query_params, fix_column_name, + flatten, get_query_results, prepare_parameterized_query, replace_query_parameters, - flatten, ) from tests import BaseTestCase @@ -252,7 +251,7 @@ def test_non_cached_query_result(self): self.assertEqual(query_result_data, get_query_results(self.factory.user, query.id, False)) -class TestFlattenFunction(TestCase): +class TestFlatten(TestCase): def test_flatten_with_string(self): self.assertEqual(flatten("hello"), "hello") @@ -266,7 +265,7 @@ def test_flatten_with_boolean(self): self.assertEqual(flatten(True), True) def test_flatten_with_decimal(self): - self.assertEqual(flatten(decimal.Decimal('10.5')), 10.5) + self.assertEqual(flatten(decimal.Decimal("10.5")), 10.5) def test_flatten_with_date(self): date = datetime.date(2021, 1, 1) @@ -285,10 +284,10 @@ def test_flatten_with_timedelta(self): self.assertEqual(flatten(timedelta_obj), "2 days, 0:00:00") def test_flatten_with_list(self): - self.assertEqual(flatten([1, 2, 3]), '[1, 2, 3]') + self.assertEqual(flatten([1, 2, 3]), "[1, 2, 3]") def test_flatten_with_dictionary(self): - self.assertEqual(flatten({'key': 'value'}), '{"key": "value"}') + self.assertEqual(flatten({"key": "value"}), '{"key": "value"}') def test_flatten_with_none(self): self.assertEqual(flatten(None), None) @@ -296,8 +295,9 @@ def test_flatten_with_none(self): def test_flatten_unhandled_type(self): class CustomType: pass + instance = CustomType() - with self.assertLogs('redash.query_runner.query_results', level='DEBUG') as log: + with self.assertLogs("redash.query_runner.query_results", level="DEBUG") as log: result = flatten(instance) self.assertEqual(result, instance) # Assuming flatten returns instance directly for unhandled types From a8023fb5fd085ddd09745482739be924583df9d9 Mon Sep 17 00:00:00 2001 From: Valerii Tatarin Date: Tue, 30 Apr 2024 03:30:16 +0000 Subject: [PATCH 19/21] fix --- tests/query_runner/test_query_results.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tests/query_runner/test_query_results.py b/tests/query_runner/test_query_results.py index 14e386b578..5a48745822 100644 --- a/tests/query_runner/test_query_results.py +++ b/tests/query_runner/test_query_results.py @@ -5,6 +5,7 @@ import mock import pytest +import logging from redash.query_runner.query_results import ( CreateTableError, @@ -297,9 +298,5 @@ class CustomType: pass instance = CustomType() - with self.assertLogs("redash.query_runner.query_results", level="DEBUG") as log: - result = flatten(instance) - self.assertEqual(result, instance) # Assuming flatten returns instance directly for unhandled types - - # Check for the presence of a specific log message - self.assertIn("flatten() found unhandled type: %s" % str(type(instance)), log.output[0]) + result = flatten(instance) + self.assertEqual(result, instance) From 4e3cbdb725279413b3a870f39b90f97a9155be1c Mon Sep 17 00:00:00 2001 From: Valerii Tatarin Date: Tue, 30 Apr 2024 03:32:19 +0000 Subject: [PATCH 20/21] fix lint --- tests/query_runner/test_query_results.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/query_runner/test_query_results.py b/tests/query_runner/test_query_results.py index 5a48745822..012d8a71cf 100644 --- a/tests/query_runner/test_query_results.py +++ b/tests/query_runner/test_query_results.py @@ -5,7 +5,6 @@ import mock import pytest -import logging from redash.query_runner.query_results import ( CreateTableError, From 5e69e3f7049407397df2f9f390a8ce4a81e7e630 Mon Sep 17 00:00:00 2001 From: Valerii Tatarin Date: Tue, 30 Apr 2024 04:34:46 +0000 Subject: [PATCH 21/21] fix lint --- tests/query_runner/test_query_results.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tests/query_runner/test_query_results.py b/tests/query_runner/test_query_results.py index 012d8a71cf..49ade3e0e7 100644 --- a/tests/query_runner/test_query_results.py +++ b/tests/query_runner/test_query_results.py @@ -1,5 +1,6 @@ import datetime import decimal +import logging import sqlite3 from unittest import TestCase @@ -292,10 +293,16 @@ def test_flatten_with_dictionary(self): def test_flatten_with_none(self): self.assertEqual(flatten(None), None) + @pytest.fixture(autouse=True) + def inject_fixtures(self, caplog): + self._caplog = caplog + def test_flatten_unhandled_type(self): class CustomType: pass instance = CustomType() - result = flatten(instance) - self.assertEqual(result, instance) + with self._caplog.at_level(logging.DEBUG): + result = flatten(instance) + self.assertEqual(result, instance) + self.assertIn("flatten() found unhandled type: %s" % str(type(instance)), self._caplog.records[0].message)