Skip to content

Commit 47e189d

Browse files
authored
Merge pull request #46 from dataiku/bug/dss13-sc-216186-api-connect-add-application-atom-xml-to-xml
fix: [sc-216186] [API connect] Add application/atom+xml to XML content type
2 parents 7306d37 + c058f7d commit 47e189d

File tree

9 files changed

+51
-20
lines changed

9 files changed

+51
-20
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Changelog
22

3+
## [Version 1.2.3](https://github.com/dataiku/dss-plugin-api-connect/releases/tag/v1.2.3) - Feature and bugfix release - 2024-11-25
4+
5+
- Fix xml decoding for content type application/atom+xml
6+
- Dump returned content that can't be decoded
7+
- Fix: Empty cells in the recipe's input dataset now produce an empty string instead of a 'nan' string
8+
- Fix: UTF-8 encoding of raw mode body
9+
310
## [Version 1.2.2](https://github.com/dataiku/dss-plugin-api-connect/releases/tag/v1.2.2) - Feature release - 2024-02-14
411

512
- Handle XML and CSV endpoints

parameter-sets/secure-basic/parameter-set.json

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,13 @@
1515
"label": "Azure Single Sign On",
1616
"credentialRequestSettings": {
1717
"type": "BASIC"
18-
},
19-
"mandatory": true
18+
}
2019
},
2120
{
2221
"name": "secure_domain",
2322
"label": "Domain",
2423
"description": "",
25-
"type": "STRING",
26-
"mandatory": true
24+
"type": "STRING"
2725
},
2826
{
2927
"name": "login_type",

parameter-sets/secure-oauth/parameter-set.json

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@
1919
"authorizationEndpoint": " ",
2020
"tokenEndpoint": " ",
2121
"scope": " "
22-
},
23-
"mandatory": true
22+
}
2423
},
2524
{
2625
"name": "authorizationEndpoint",
@@ -47,8 +46,7 @@
4746
"name": "secure_domain",
4847
"label": "Domain",
4948
"description": "",
50-
"type": "STRING",
51-
"mandatory": true
49+
"type": "STRING"
5250
}
5351
]
5452
}

plugin.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"id": "api-connect",
3-
"version": "1.2.2",
3+
"version": "1.2.3",
44
"meta": {
55
"label": "API Connect",
66
"description": "Retrieve data from any REST API",

python-connectors/api-connect_dataset/connector.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
from rest_api_client import RestAPIClient
55
from dku_utils import (
66
get_dku_key_values, get_endpoint_parameters,
7-
parse_keys_for_json, get_value_from_path, get_secure_credentials, decode_csv_data
7+
parse_keys_for_json, get_value_from_path, get_secure_credentials,
8+
decode_csv_data, decode_bytes
89
)
910
from dku_constants import DKUConstants
1011
import json
@@ -57,10 +58,16 @@ def generate_rows(self, dataset_schema=None, dataset_partitioning=None,
5758
record_count += 1
5859
yield self.format_output(data, metadata)
5960
else:
60-
data = decode_csv_data(data)
61-
record_count += len(data)
62-
for row in data:
63-
yield self.format_output(row, metadata)
61+
csv_data = decode_csv_data(data)
62+
if csv_data:
63+
record_count += len(csv_data)
64+
for row in csv_data:
65+
yield self.format_output(row, metadata)
66+
else:
67+
record_count += 1
68+
yield {
69+
DKUConstants.API_RESPONSE_KEY: "{}".format(decode_bytes(data))
70+
}
6471
if is_records_limit and record_count >= records_limit:
6572
break
6673

python-lib/dku_constants.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ class DKUConstants(object):
22
API_RESPONSE_KEY = "api_response"
33
FORBIDDEN_KEYS = ["token", "password", "api_key_value", "secure_token"]
44
FORM_DATA_BODY_FORMAT = "FORM_DATA"
5-
PLUGIN_VERSION = "1.2.2"
5+
PLUGIN_VERSION = "1.2.3"
66
RAW_BODY_FORMAT = "RAW"
77
REPONSE_ERROR_KEY = "dku_error"

python-lib/dku_utils.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import json
22
import copy
3+
import math
34
from jsonpath_ng.ext import parse
45
from safe_logger import SafeLogger
56

@@ -125,7 +126,7 @@ def extract_key_using_json_path(json_dictionary, json_path):
125126
def is_reponse_xml(response):
126127
content_types = response.headers.get("Content-Type", "").split(";")
127128
for content_type in content_types:
128-
if content_type in ["text/xml", "application/soap+xml", "application/xml"]:
129+
if content_type in ["text/xml", "application/soap+xml", "application/xml", "application/atom+xml"]:
129130
return True
130131
return False
131132

@@ -145,12 +146,24 @@ def decode_csv_data(data):
145146
import csv
146147
import io
147148
json_data = None
148-
if isinstance(data, bytes):
149-
data = data.decode("utf-8")
149+
data = decode_bytes(data)
150150
try:
151151
reader = csv.DictReader(io.StringIO(data))
152152
json_data = list(reader)
153153
except Exception as error:
154154
logger.error("Could not extract csv data. Error={}".format(error))
155155
json_data = data
156156
return json_data
157+
158+
159+
def de_NaN(cell_content):
160+
if isinstance(cell_content, float):
161+
if math.isnan(cell_content):
162+
return ''
163+
return cell_content
164+
165+
166+
def decode_bytes(content):
167+
if isinstance(content, bytes):
168+
content = content.decode()
169+
return content

python-lib/rest_api_client.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,10 @@ def request(self, method, url, can_raise_exeption=True, **kwargs):
128128
error_message = None
129129
status_code = None
130130
response_headers = None
131+
if "data" in kwargs:
132+
data = kwargs.get("data")
133+
if isinstance(data, str):
134+
kwargs["data"] = data.encode("utf-8")
131135
try:
132136
response = self.request_with_redirect_retry(method, url, **kwargs)
133137
status_code = response.status_code

python-lib/rest_api_recipe_session.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from dataikuapi.utils import DataikuException
22
from rest_api_client import RestAPIClient
33
from safe_logger import SafeLogger
4-
from dku_utils import parse_keys_for_json, get_value_from_path, decode_csv_data
4+
from dku_utils import parse_keys_for_json, get_value_from_path, decode_csv_data, de_NaN
55
from dku_constants import DKUConstants
66
import copy
77
import json
@@ -49,7 +49,11 @@ def process_dataframe(self, input_parameters_dataframe, is_raw_output):
4949
self.initial_parameter_columns = {}
5050
for column_name in self.column_to_parameter_dict:
5151
parameter_name = self.column_to_parameter_dict[column_name]
52-
self.initial_parameter_columns.update({parameter_name: input_parameters_row.get(column_name)})
52+
self.initial_parameter_columns.update(
53+
{
54+
parameter_name: de_NaN(input_parameters_row.get(column_name))
55+
}
56+
)
5357
updated_endpoint_parameters = copy.deepcopy(self.endpoint_parameters)
5458
updated_endpoint_parameters.update(self.initial_parameter_columns)
5559
logger.info("Processing row #{}, creating client with credential={}, updated_endpoint={}, custom_key_values={}".format(

0 commit comments

Comments
 (0)