Skip to content

Commit

Permalink
Test multi-upload for all conditions (fails on symlinked nested folders)
Browse files Browse the repository at this point in the history
  • Loading branch information
garrettmflynn committed Sep 15, 2023
1 parent 8b9f105 commit b8c2691
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 15 deletions.
33 changes: 27 additions & 6 deletions pyflask/apis/neuroconv.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@
generate_dataset,
inspect_nwb_file,
inspect_nwb_folder,
inspect_multiple_filesystem_objects
inspect_multiple_filesystem_objects,
upload_to_dandi,
upload_folder_to_dandi,
upload_multiple_filesystem_objects_to_dandi
)

from errorHandlers import notBadRequestException
Expand Down Expand Up @@ -112,13 +115,11 @@ def post(self):
neuroconv_api.abort(500, str(e))


@neuroconv_api.route("/upload")
@neuroconv_api.route("/upload/project")
class Upload(Resource):
@neuroconv_api.doc(responses={200: "Success", 400: "Bad Request", 500: "Internal server error"})
def post(self):
try:
from manageNeuroconv import upload_to_dandi

return upload_to_dandi(**neuroconv_api.payload)

except Exception as e:
Expand All @@ -131,15 +132,35 @@ class Upload(Resource):
@neuroconv_api.doc(responses={200: "Success", 400: "Bad Request", 500: "Internal server error"})
def post(self):
try:
from manageNeuroconv import upload_folder_to_dandi

return upload_folder_to_dandi(**neuroconv_api.payload)

except Exception as e:
if notBadRequestException(e):
neuroconv_api.abort(500, str(e))


@neuroconv_api.route("/upload")
class Upload(Resource):
@neuroconv_api.doc(responses={200: "Success", 400: "Bad Request", 500: "Internal server error"})
def post(self):
from os.path import isdir

try:
paths = neuroconv_api.payload["filesystem_paths"]

if (len(paths) == 1 and isdir(paths[0])):
kwargs = { **neuroconv_api.payload }
del kwargs["filesystem_paths"]
kwargs["nwb_folder_path"] = paths[0]
return upload_folder_to_dandi(**kwargs)

else:
return upload_multiple_filesystem_objects_to_dandi(**neuroconv_api.payload)

except Exception as e:
if notBadRequestException(e):
neuroconv_api.abort(500, str(e))

@neuroconv_api.route("/inspect_file")
class InspectNWBFile(Resource):
@neuroconv_api.doc(responses={200: "Success", 400: "Bad Request", 500: "Internal server error"})
Expand Down
1 change: 1 addition & 0 deletions pyflask/manageNeuroconv/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
validate_metadata,
upload_to_dandi,
upload_folder_to_dandi,
upload_multiple_filesystem_objects_to_dandi,
listen_to_neuroconv_events,
generate_dataset,
inspect_nwb_file,
Expand Down
9 changes: 9 additions & 0 deletions pyflask/manageNeuroconv/manage_neuroconv.py
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,15 @@ def update_conversion_progress(**kwargs):
return dict(file=str(resolved_output_path))


def upload_multiple_filesystem_objects_to_dandi(**kwargs):
tmp_folder_path = aggregate_in_temp_directory(kwargs['filesystem_paths'], 'upload')
innerKwargs = { **kwargs }
del innerKwargs['filesystem_paths']
innerKwargs["nwb_folder_path"] = tmp_folder_path
result = upload_folder_to_dandi(**innerKwargs)
rmtree(tmp_folder_path)
return result

def upload_folder_to_dandi(
dandiset_id: str,
api_key: str,
Expand Down
11 changes: 7 additions & 4 deletions schemas/json/dandi/standalone.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
{
"properties": {
"nwb_folder_path": {
"type": "string",
"format": "directory"
"filesystem_paths": {
"type": "array",
"items":{
"type": "string",
"format": ["file", "directory"]
}
}
},
"required": ["nwb_folder_path"]
"required": ["filesystem_paths"]
}
4 changes: 4 additions & 0 deletions src/renderer/src/stories/FileSystemSelector.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ const componentCSS = css`
gap: 5px;
}
#button-div > nwb-button {
margin-bottom: 10px;
}
button {
background: WhiteSmoke;
border: 1px solid #c3c3c3;
Expand Down
13 changes: 8 additions & 5 deletions src/renderer/src/stories/pages/uploads/UploadsPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { html } from "lit";
import { JSONSchemaForm } from "../../JSONSchemaForm.js";
import { Page } from "../Page.js";
import { onThrow } from "../../../errors";

const folderPathKey = "filesystem_paths";
import dandiUploadSchema from "../../../../../../schemas/json/dandi/upload.json";
import dandiStandaloneSchema from "../../../../../../schemas/json/dandi/standalone.json";
const dandiSchema = merge(dandiStandaloneSchema, merge(dandiUploadSchema, {}), { arrays: true });
Expand All @@ -18,7 +20,7 @@ import { DandiResults } from "../../DandiResults.js";

export const isStaging = (id) => parseInt(id) >= 100000;

export async function uploadToDandi(info, type = "project" in info ? "" : "folder") {
export async function uploadToDandi(info, type = "project" in info ? "project" : "") {
const api_key = global.data.DANDI?.api_key;
if (!api_key) {
await Swal.fire({
Expand All @@ -31,11 +33,13 @@ export async function uploadToDandi(info, type = "project" in info ? "" : "folde
return this.to("settings");
}

const { dandiset_id } = info

const result = await run(
type ? `upload/${type}` : "upload",
{
...info,
staging: isStaging(info.dandiset_id), // Automatically detect staging IDs
staging: isStaging(dandiset_id), // Automatically detect staging IDs
api_key,
},
{ title: "Uploading to DANDI" }
Expand All @@ -50,7 +54,7 @@ export async function uploadToDandi(info, type = "project" in info ? "" : "folde
if (result)
notyf.open({
type: "success",
message: `${info.project ?? info.nwb_folder_path} successfully uploaded to Dandiset ${info.dandiset_id}`,
message: `${info.project ?? `${info[folderPathKey].length} filesystem entries`} successfully uploaded to Dandiset ${dandiset_id}`,
});

return result;
Expand Down Expand Up @@ -85,13 +89,12 @@ export class UploadsPage extends Page {
},
});

const folderPathKey = "nwb_folder_path";
// NOTE: API Keys and Dandiset IDs persist across selected project
this.form = new JSONSchemaForm({
results: globalState,
schema: dandiSchema,
sort: ([k1]) => {
if (k1 === "nwb_folder_path") return -1;
if (k1 === folderPathKey) return -1;
},
onUpdate: ([id]) => {
if (id === folderPathKey) {
Expand Down

0 comments on commit b8c2691

Please sign in to comment.