From aaf4cf9e73bb0b905133bf13d9fb621992e71534 Mon Sep 17 00:00:00 2001 From: Alex Bourret Date: Fri, 27 Feb 2026 16:23:06 +0100 Subject: [PATCH 1/7] fixing last line duplication in csv apis via recipe --- python-lib/rest_api_recipe_session.py | 1 + 1 file changed, 1 insertion(+) diff --git a/python-lib/rest_api_recipe_session.py b/python-lib/rest_api_recipe_session.py index 8a474ba..a7d5427 100644 --- a/python-lib/rest_api_recipe_session.py +++ b/python-lib/rest_api_recipe_session.py @@ -126,6 +126,7 @@ def retrieve_next_page(self, is_raw_output): page_rows.append(base_row) else: json_response = decode_csv_data(json_response) + is_api_returning_dict = False for row in json_response: base_row = copy.deepcopy(metadata) base_row.update(parse_keys_for_json(row)) From ad19d07f6d1a40edd5d188d0cfa54363b8cacb2e Mon Sep 17 00:00:00 2001 From: Alex Bourret Date: Fri, 27 Feb 2026 16:23:14 +0100 Subject: [PATCH 2/7] changelog update --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a815c09..7f8531f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## [Version 1.2.7](https://github.com/dataiku/dss-plugin-api-connect/releases/tag/v1.2.7) - Feature - 2026-02-18 - Detecting dialect for better csv decoding +- Fixing duplication of last line in csv APIs using the recipe ## [Version 1.2.6](https://github.com/dataiku/dss-plugin-api-connect/releases/tag/v1.2.6) - Feature - 2025-09-24 From 3996901629ae399365dc8815b3711743abcafcae Mon Sep 17 00:00:00 2001 From: Alex Bourret Date: Thu, 5 Mar 2026 09:56:08 +0100 Subject: [PATCH 3/7] dumping in text mode as last resort --- python-lib/rest_api_recipe_session.py | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/python-lib/rest_api_recipe_session.py b/python-lib/rest_api_recipe_session.py index a7d5427..fada80a 100644 --- a/python-lib/rest_api_recipe_session.py +++ b/python-lib/rest_api_recipe_session.py @@ -1,7 +1,7 @@ from dataikuapi.utils import DataikuException from rest_api_client import RestAPIClient from safe_logger import SafeLogger -from dku_utils import parse_keys_for_json, get_value_from_path, decode_csv_data, de_NaN +from dku_utils import parse_keys_for_json, get_value_from_path, decode_csv_data, de_NaN, decode_bytes from dku_constants import DKUConstants import copy import json @@ -108,6 +108,7 @@ def retrieve_next_page(self, is_raw_output): # Todo: check api_response key is free and add something overwise base_row = copy.deepcopy(metadata) if is_raw_output: + assert_json(json_response) if is_error_message(json_response): base_row.update(parse_keys_for_json(json_response)) else: @@ -125,9 +126,18 @@ def retrieve_next_page(self, is_raw_output): base_row.update(self.initial_parameter_columns) page_rows.append(base_row) else: - json_response = decode_csv_data(json_response) + decoded_csv_data = decode_csv_data(json_response) is_api_returning_dict = False - for row in json_response: + if not decoded_csv_data and json_response: + logger.warning("Data is not in CSV format. Dumping it in text mode.") + decoded_csv_data = [ + { + DKUConstants.API_RESPONSE_KEY: "{}".format( + decode_bytes(json_response) + ) + } + ] + for row in decoded_csv_data: base_row = copy.deepcopy(metadata) base_row.update(parse_keys_for_json(row)) base_row.update(self.initial_parameter_columns) @@ -182,3 +192,9 @@ def is_error_message(jsons_response): return True else: return False + + +def assert_json(variable_to_check): + if isinstance(variable_to_check, dict) or isinstance(variable_to_check, list): + return + raise Exception("Returned data is not JSON format. Try again with 'Raw JSON output' un-checked.") From 1a4d9fcef954bf43c6da29a97246f7e6f2712ca4 Mon Sep 17 00:00:00 2001 From: Alex Bourret Date: Thu, 5 Mar 2026 09:56:20 +0100 Subject: [PATCH 4/7] beta2 --- python-lib/dku_constants.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python-lib/dku_constants.py b/python-lib/dku_constants.py index d16088e..fab7777 100644 --- a/python-lib/dku_constants.py +++ b/python-lib/dku_constants.py @@ -2,6 +2,6 @@ class DKUConstants(object): API_RESPONSE_KEY = "api_response" FORBIDDEN_KEYS = ["token", "password", "api_key_value", "secure_token"] FORM_DATA_BODY_FORMAT = "FORM_DATA" - PLUGIN_VERSION = "1.2.7-beta.1" + PLUGIN_VERSION = "1.2.7-beta.2" RAW_BODY_FORMAT = "RAW" REPONSE_ERROR_KEY = "dku_error" From 5dc9987bbacb21f12f5e216f1824de455724c3e3 Mon Sep 17 00:00:00 2001 From: Alex Bourret Date: Wed, 15 Apr 2026 10:10:25 +0200 Subject: [PATCH 5/7] removing json assertion, dumping response if json.dumps fails --- python-lib/rest_api_recipe_session.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/python-lib/rest_api_recipe_session.py b/python-lib/rest_api_recipe_session.py index fada80a..8c82f78 100644 --- a/python-lib/rest_api_recipe_session.py +++ b/python-lib/rest_api_recipe_session.py @@ -108,13 +108,17 @@ def retrieve_next_page(self, is_raw_output): # Todo: check api_response key is free and add something overwise base_row = copy.deepcopy(metadata) if is_raw_output: - assert_json(json_response) if is_error_message(json_response): base_row.update(parse_keys_for_json(json_response)) else: - base_row.update({ - DKUConstants.API_RESPONSE_KEY: json.dumps(json_response) - }) + try: + base_row.update({ + DKUConstants.API_RESPONSE_KEY: json.dumps(json_response) + }) + except Exception: + base_row.update({ + DKUConstants.API_RESPONSE_KEY: decode_bytes(json_response) + }) else: if isinstance(json_response, dict): base_row.update(parse_keys_for_json(json_response)) @@ -192,9 +196,3 @@ def is_error_message(jsons_response): return True else: return False - - -def assert_json(variable_to_check): - if isinstance(variable_to_check, dict) or isinstance(variable_to_check, list): - return - raise Exception("Returned data is not JSON format. Try again with 'Raw JSON output' un-checked.") From c1e81b0be4a426d3dcc1117902e84873df1d0e9b Mon Sep 17 00:00:00 2001 From: Alex Bourret Date: Wed, 15 Apr 2026 10:10:37 +0200 Subject: [PATCH 6/7] refacto --- python-connectors/api-connect_dataset/connector.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python-connectors/api-connect_dataset/connector.py b/python-connectors/api-connect_dataset/connector.py index fc155de..59d382f 100644 --- a/python-connectors/api-connect_dataset/connector.py +++ b/python-connectors/api-connect_dataset/connector.py @@ -68,7 +68,7 @@ def generate_rows(self, dataset_schema=None, dataset_partitioning=None, else: record_count += 1 yield { - DKUConstants.API_RESPONSE_KEY: "{}".format(decode_bytes(data)) + DKUConstants.API_RESPONSE_KEY: decode_bytes(data) } if is_records_limit and record_count >= records_limit: break From 7bc0c4932e36f5dbf32f0b448a892f326af3a6b9 Mon Sep 17 00:00:00 2001 From: Alex Bourret Date: Wed, 15 Apr 2026 10:10:46 +0200 Subject: [PATCH 7/7] changelog update --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f8531f..5248b19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - Detecting dialect for better csv decoding - Fixing duplication of last line in csv APIs using the recipe +- Dumping API's response as a last resort ## [Version 1.2.6](https://github.com/dataiku/dss-plugin-api-connect/releases/tag/v1.2.6) - Feature - 2025-09-24