Skip to content

Commit e611e4a

Browse files
authored
Merge pull request #950 from Sage-Bionetworks/develop
Release 22.10.1
2 parents c5d49ff + a3ac31e commit e611e4a

File tree

3 files changed

+256
-33
lines changed

3 files changed

+256
-33
lines changed

api/openapi/api.yaml

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,9 +152,10 @@ paths:
152152
schema:
153153
type: object
154154
properties:
155-
# csv_file will be the field name in
155+
# file_name will be the field name in
156156
# this multipart request
157-
csv_file:
157+
file_name:
158+
description: Upload a json or a csv file.
158159
type: string
159160
format: binary
160161
parameters:
@@ -174,6 +175,23 @@ paths:
174175
description: Data Model Component
175176
example: Patient
176177
required: true
178+
- in: query
179+
name: json_str
180+
required: false
181+
schema:
182+
type: string
183+
nullable: false
184+
description: A JSON object
185+
example: '[{
186+
"Patient ID": 123,
187+
"Sex": "Female",
188+
"Year of Birth": "",
189+
"Diagnosis": "Healthy",
190+
"Component": "Patient",
191+
"Cancer Type": "Breast",
192+
"Family History": "Breast, Lung",
193+
}]'
194+
177195
operationId: api.routes.validate_manifest_route
178196
responses:
179197
"200":
@@ -203,7 +221,8 @@ paths:
203221
schema:
204222
type: object
205223
properties:
206-
csv_file:
224+
file_name:
225+
description: Upload a json or a csv file.
207226
type: string
208227
format: binary
209228
parameters:
@@ -251,6 +270,30 @@ paths:
251270
nullable: false
252271
description: Token
253272
required: true
273+
- in: query
274+
name: asset_view
275+
schema:
276+
type: string
277+
nullable: false
278+
description: ID of view listing all project data assets. For example, for Synapse this would be the Synapse ID of the fileview listing all data assets for a given project.(i.e. master_fileview in config.yml)
279+
example: syn28559058
280+
required: true
281+
- in: query
282+
name: json_str
283+
required: false
284+
schema:
285+
type: string
286+
nullable: false
287+
description: A JSON object
288+
example: '[{
289+
"Patient ID": 123,
290+
"Sex": "Female",
291+
"Year of Birth": "",
292+
"Diagnosis": "Healthy",
293+
"Component": "Patient",
294+
"Cancer Type": "Breast",
295+
"Family History": "Breast, Lung",
296+
}]'
254297
operationId: api.routes.submit_manifest_route
255298
responses:
256299
"200":

api/routes.py

Lines changed: 132 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,122 @@ def config_handler(asset_view=None):
4343
f"No configuration file was found at this path: {path_to_config}"
4444
)
4545

46-
def csv_path_handler():
47-
manifest_file = connexion.request.files["csv_file"]
46+
class JsonConverter:
47+
'''
48+
Mainly handle converting json str or json file to csv
49+
'''
50+
def readJson(self, json_str=None, manifest_file=None):
51+
'''
52+
The purpose of this function is to read either json str or json file
53+
input:
54+
json_str: json object
55+
manifest_file: manifest file object
56+
output:
57+
return a dataframe
58+
'''
59+
if json_str:
60+
df = pd.read_json(json_str)
61+
elif manifest_file:
62+
df = pd.read_json(manifest_file.read())
63+
return df
64+
65+
def get_file(self, file_key):
66+
'''
67+
The purpose of this function is to get the file uploaded by user
68+
input:
69+
file_key: Defined in api.yaml. This key refers to the files uploaded.
70+
manifest_file: manifest file object
71+
output:
72+
return file object
73+
'''
74+
75+
manifest_file = connexion.request.files[file_key]
76+
return manifest_file
77+
78+
def IsJsonFile(self, manifest_file):
79+
'''
80+
The purpose of this function is check if the manifest file that gets uploaded is a json or not
81+
input:
82+
manifest_file: manifest file object
83+
output:
84+
return True if it is json
85+
'''
86+
87+
file_type = manifest_file.content_type
88+
if file_type == 'application/json':
89+
return True
90+
else:
91+
return False
92+
93+
def convert_df_to_csv(self, df, file_name):
94+
'''
95+
The purpose of this function is to convert dataframe to a temporary CSV file
96+
input:
97+
df: dataframe
98+
file_name: file name of the output csv
99+
output:
100+
return temporary file path of the output csv
101+
'''
102+
103+
# convert dataframe to a temporary csv file
104+
temp_dir = tempfile.gettempdir()
105+
temp_path = os.path.join(temp_dir, file_name)
106+
df.to_csv(temp_path, encoding = 'utf-8', index=False)
107+
return temp_path
108+
109+
def convert_json_str_to_csv(self, json_str, file_name):
110+
'''
111+
The purpose of this function is to convert json str to a temporary csv file
112+
input:
113+
json_str: json object
114+
file_name: file name of the output csv
115+
output:
116+
return temporary file path of the output csv
117+
'''
118+
119+
# convert json to df
120+
df = self.readJson(json_str = json_str)
121+
122+
# convert dataframe to a temporary csv file
123+
temp_path = self.convert_df_to_csv(df, file_name)
124+
125+
return temp_path
126+
127+
def convert_json_file_to_csv(self, file_key):
128+
'''
129+
The purpose of this function is to convert json str to a temporary csv file
130+
input:
131+
file_key: Defined in api.yaml. This key refers to the files uploaded.
132+
output:
133+
return temporary file path of the output csv
134+
'''
135+
136+
# get manifest file
137+
manifest_file = self.get_file(file_key)
138+
139+
if self.IsJsonFile(manifest_file):
140+
# read json as dataframe
141+
df = self.readJson(manifest_file = manifest_file)
142+
# get base file name
143+
base = os.path.splitext(manifest_file.filename)[0]
144+
# name the new csv file
145+
new_file_name = base + '.csv'
146+
# convert to csv
147+
temp_path = self.convert_df_to_csv(df, new_file_name)
148+
return temp_path
149+
else:
150+
temp_path = save_file(file_key='file_name')
151+
return temp_path
152+
153+
154+
155+
def save_file(file_key="csv_file"):
156+
'''
157+
input:
158+
file_key: Defined in api.yaml. This key refers to the files uploaded. By default, set to "csv_file"
159+
Return a temporary file path for the uploaded a given file
160+
'''
161+
manifest_file = connexion.request.files[file_key]
48162

49163
# save contents of incoming manifest CSV file to temp file
50164
temp_dir = tempfile.gettempdir()
@@ -158,12 +272,17 @@ def create_single_manifest(data_type, dataset_id=None):
158272
return all_results
159273

160274

161-
def validate_manifest_route(schema_url, data_type):
275+
def validate_manifest_route(schema_url, data_type, json_str=None):
162276
# call config_handler()
163277
config_handler()
164278

165279
#Get path to temp file where manifest file contents will be saved
166-
temp_path = csv_path_handler()
280+
jsc = JsonConverter()
281+
282+
if json_str:
283+
temp_path = jsc.convert_json_str_to_csv(json_str = json_str, file_name = "example_json")
284+
else:
285+
temp_path = jsc.convert_json_file_to_csv("file_name")
167286

168287
# get path to temporary JSON-LD file
169288
jsonld = get_temp_jsonld(schema_url)
@@ -181,12 +300,16 @@ def validate_manifest_route(schema_url, data_type):
181300
return res_dict
182301

183302

184-
def submit_manifest_route(schema_url, manifest_record_type=None):
303+
def submit_manifest_route(schema_url, asset_view=None, manifest_record_type=None, json_str=None):
185304
# call config_handler()
186-
config_handler()
305+
config_handler(asset_view = asset_view)
187306

188-
# Get path to temp file where manifest file contents will be saved
189-
temp_path = csv_path_handler()
307+
# convert Json file to CSV if applicable
308+
jsc = JsonConverter()
309+
if json_str:
310+
temp_path = jsc.convert_json_str_to_csv(json_str = json_str, file_name = "example_json.csv")
311+
else:
312+
temp_path = jsc.convert_json_file_to_csv("file_name")
190313

191314
dataset_id = connexion.request.args["dataset_id"]
192315

@@ -216,7 +339,7 @@ def populate_manifest_route(schema_url, title=None, data_type=None):
216339
jsonld = get_temp_jsonld(schema_url)
217340

218341
# Get path to temp file where manifest file contents will be saved
219-
temp_path = csv_path_handler()
342+
temp_path = save_file()
220343

221344
#Initalize MetadataModel
222345
metadata_model = MetadataModel(inputMModelLocation=jsonld, inputMModelLocationType='local')

0 commit comments

Comments
 (0)