Skip to content

Commit f53a901

Browse files
authored
[RAPTOR-15441] remove cgi package usage (#1806)
1 parent 4622ee0 commit f53a901

File tree

2 files changed

+47
-14
lines changed

2 files changed

+47
-14
lines changed

custom_model_runner/datarobot_drum/drum/root_predictors/transform_helpers.py

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@
77
import pandas as pd
88
import logging
99

10-
from cgi import FieldStorage
1110
from io import BytesIO, StringIO
1211

1312
from scipy.io import mmwrite, mmread
1413
from scipy.sparse import issparse
1514
from scipy.sparse import csr_matrix
15+
from werkzeug.formparser import parse_form_data
1616

1717
from datarobot_drum.drum.enum import X_FORMAT_KEY, X_TRANSFORM_KEY
1818

@@ -102,20 +102,18 @@ def read_mtx_payload(response_dict, transform_key):
102102

103103

104104
def parse_multi_part_response(response):
105+
environ = {
106+
"wsgi.input": BytesIO(response.content),
107+
"REQUEST_METHOD": "POST",
108+
"CONTENT_TYPE": response.headers["Content-Type"],
109+
"CONTENT_LENGTH": str(len(response.content)),
110+
}
111+
_, form, files = parse_form_data(environ)
105112
parsed_response = {}
106-
fs = FieldStorage(
107-
fp=BytesIO(response.content),
108-
headers=response.headers,
109-
environ={
110-
"REQUEST_METHOD": "POST",
111-
"CONTENT_TYPE": response.headers["Content-Type"],
112-
},
113-
)
114-
for child in fs.list:
115-
key = child.name
116-
value = child.file.read()
117-
parsed_response.update({key: value})
118-
113+
for key, value in form.items():
114+
parsed_response[key] = value
115+
for key, file_storage in files.items():
116+
parsed_response[key] = file_storage.read()
119117
return parsed_response
120118

121119

tests/unit/datarobot_drum/drum/root_predictors/test_transform_helpers.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@
77
import pandas as pd
88
import numpy as np
99
import pytest
10+
import types
1011
from scipy.sparse import coo_matrix
1112

1213
from datarobot_drum.drum.root_predictors.transform_helpers import (
1314
validate_and_convert_column_names_for_serialization,
15+
parse_multi_part_response,
1416
)
1517

1618

@@ -44,3 +46,36 @@ def test_validate_and_convert_column_names_for_serialization(columns, expected_c
4446
else:
4547
output_df = validate_and_convert_column_names_for_serialization(df)
4648
assert list(output_df.columns.values) == expected_columns
49+
50+
51+
def test_parse_multi_part_response():
52+
file_content1 = b"value1"
53+
file_content2 = b"value2"
54+
boundary = "boundary123"
55+
content = (
56+
(
57+
f"--{boundary}\r\n"
58+
'Content-Disposition: form-data; name="X.format"\r\n\r\n'
59+
"csv\r\n"
60+
f"--{boundary}\r\n"
61+
'Content-Disposition: form-data; name="key1"; filename="file1.txt"\r\n'
62+
"Content-Type: text/plain\r\n\r\n"
63+
).encode("utf-8")
64+
+ file_content1
65+
+ (
66+
f"\r\n--{boundary}\r\n"
67+
'Content-Disposition: form-data; name="key2"; filename="file2.txt"\r\n'
68+
"Content-Type: text/plain\r\n\r\n"
69+
).encode("utf-8")
70+
+ file_content2
71+
+ f"\r\n--{boundary}--\r\n".encode("utf-8")
72+
)
73+
74+
response = types.SimpleNamespace()
75+
response.content = content
76+
response.headers = {"Content-Type": f"multipart/form-data; boundary={boundary}"}
77+
78+
result = parse_multi_part_response(response)
79+
assert result["X.format"] == "csv"
80+
assert result["key1"] == file_content1
81+
assert result["key2"] == file_content2

0 commit comments

Comments
 (0)