From aaf4cf9e73bb0b905133bf13d9fb621992e71534 Mon Sep 17 00:00:00 2001 From: Alex Bourret Date: Fri, 27 Feb 2026 16:23:06 +0100 Subject: [PATCH 1/4] 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/4] 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/4] 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/4] 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"