diff --git a/app.py b/app.py index abf0709..8fa934d 100644 --- a/app.py +++ b/app.py @@ -674,6 +674,9 @@ async def new_batch_import(): container_name = data["container_name"] user_id = container_name + folder_name = data["folder_name"] + if folder_name == "" : + folder_name = None nb_pictures = data["nb_pictures"] if not container_name or not(isinstance(nb_pictures, int)) or nb_pictures <= 0 : @@ -686,7 +689,7 @@ async def new_batch_import(): connection = datastore.get_connection() cursor = datastore.get_cursor(connection) - picture_set_id = await datastore.create_picture_set(cursor, container_client, user_id, nb_pictures) + picture_set_id = await datastore.create_picture_set(cursor, container_client, user_id, nb_pictures, folder_name) datastore.end_query(connection, cursor) if picture_set_id: return jsonify({"session_id" : picture_set_id}), 200 diff --git a/requirements.txt b/requirements.txt index 30070c8..0805835 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,4 +10,4 @@ cryptography pyyaml pydantic python-magic -nachet-datastore @git+https://github.com/ai-cfia/nachet-datastore.git@main +nachet-datastore @git+https://github.com/ai-cfia/nachet-datastore.git@b0d85ce68ed08928b7240c35d9d462cda48ba294 diff --git a/storage/datastore_storage_api.py b/storage/datastore_storage_api.py index 1108e11..0c4f944 100644 --- a/storage/datastore_storage_api.py +++ b/storage/datastore_storage_api.py @@ -1,9 +1,11 @@ """ This module provide an absraction to the nachet-datastore interface. """ +import os import datastore from datastore import db from datastore import user as user_datastore +from datastore import Nachet as nachet_datastore import datastore.bin.deployment_mass_import import datastore.bin.upload_picture_set @@ -21,8 +23,11 @@ class GetPipelinesError(DatastoreError): class UserNotFoundError(DatastoreError): pass +NACHET_DB_URL = os.getenv("NACHET_DB_URL") +NACHET_SCHEMA = os.getenv("NACHET_SCHEMA") + def get_connection() : - return db.connect_db() + return db.connect_db(NACHET_DB_URL, NACHET_SCHEMA) def get_cursor(connection): return db.cursor(connection) @@ -38,7 +43,7 @@ async def get_all_seeds() -> list: try: connection = get_connection() cursor = get_cursor(connection) - return await datastore.get_seed_info(cursor) + return await nachet_datastore.get_seed_info(cursor) except Exception as error: # TODO modify Exception for more specific exception raise SeedNotFoundError(error.args[0]) @@ -89,12 +94,12 @@ async def get_picture_id(cursor, user_id, image_hash_value, container_client) : """ Return the picture_id of the image """ - picture_id = await datastore.upload_picture_unknown(cursor, str(user_id), image_hash_value, container_client) + picture_id = await nachet_datastore.upload_picture_unknown(cursor, str(user_id), image_hash_value, container_client) return picture_id def upload_pictures(cursor, user_id, picture_set_id, container_client, pictures, seed_name: str, zoom_level: float = None, nb_seeds: int = None) : try : - return datastore.upload_pictures(cursor, user_id, picture_set_id, container_client, pictures, seed_name, zoom_level, nb_seeds) + return nachet_datastore.upload_pictures(cursor, user_id, picture_set_id, container_client, pictures, seed_name, zoom_level, nb_seeds) except Exception as error: raise DatastoreError(error) @@ -112,23 +117,23 @@ async def get_pipelines() -> list: try: connection = get_connection() cursor = get_cursor(connection) - pipelines = await datastore.get_ml_structure(cursor) + pipelines = await nachet_datastore.get_ml_structure(cursor) return pipelines except Exception as error: # TODO modify Exception for more specific exception raise GetPipelinesError(error.args[0]) async def save_inference_result(cursor, user_id:str, inference_dict, picture_id:str, pipeline_id:str, type:int): - return await datastore.register_inference_result(cursor, user_id, inference_dict, picture_id, pipeline_id, type) + return await nachet_datastore.register_inference_result(cursor, user_id, inference_dict, picture_id, pipeline_id, type) async def save_perfect_feedback(cursor, inference_id:str, user_id:str, boxes_id): - await datastore.new_perfect_inference_feeback(cursor, inference_id, user_id, boxes_id) + await nachet_datastore.new_perfect_inference_feeback(cursor, inference_id, user_id, boxes_id) async def save_annoted_feedback(cursor, feedback_dict): - await datastore.new_correction_inference_feedback(cursor, feedback_dict) + await nachet_datastore.new_correction_inference_feedback(cursor, feedback_dict) async def delete_directory_request(cursor, user_id, picture_set_id): try : - return len(await datastore.find_validated_pictures(cursor, user_id, picture_set_id)) > 0 + return len(await nachet_datastore.find_validated_pictures(cursor, user_id, picture_set_id)) > 0 except Exception as error: raise DatastoreError(error) @@ -140,7 +145,7 @@ async def delete_directory_permanently(cursor, user_id, picture_set_id, containe async def delete_directory_with_archive(cursor, user_id, picture_set_id, container_client): try : - return await datastore.delete_picture_set_with_archive(cursor, user_id, picture_set_id, container_client) + return await nachet_datastore.delete_picture_set_with_archive(cursor, user_id, picture_set_id, container_client) except Exception as error: raise DatastoreError(error) diff --git a/tests/test_image_batch_import.py b/tests/test_image_batch_import.py index b7f51e3..26f9ea7 100644 --- a/tests/test_image_batch_import.py +++ b/tests/test_image_batch_import.py @@ -11,24 +11,24 @@ def setUp(self): self.test_client = app.test_client() self.container_name = "a427278e-28df-428f-8937-ddeeef44e72f" self.nb_pictures = 1 - self.folder_name = None - + self.folder_name = "test_batch_import" + self.session_id = None def tearDown(self): - if(self.folder_name is not None): + if(self.session_id is not None): response = asyncio.run( self.test_client.post( - '/del', + '/delete-permanently', headers={ "Content-Type": "application/json", "Access-Control-Allow-Origin": "*", }, json={ "container_name": self.container_name, - "folder_name": self.folder_name + "folder_uuid": self.session_id }) ) if(response.status_code == 200): - self.folder_name = None + self.session_id = None self.test_client = None def test_new_batch_import_successfull(self): @@ -42,6 +42,7 @@ def test_new_batch_import_successfull(self): }, json={ "container_name": self.container_name, + "folder_name": self.folder_name, "nb_pictures": self.nb_pictures }) ) @@ -50,7 +51,7 @@ def test_new_batch_import_successfull(self): result_json = json.loads(asyncio.run(response.get_data())) self.assertTrue(result_json.get("session_id") is not None) - self.folder_name = result_json.get("session_id") + self.session_id = result_json.get("session_id") def test_new_batch_import_missing_arguments_error(self): """ @@ -66,6 +67,7 @@ def test_new_batch_import_missing_arguments_error(self): "Access-Control-Allow-Origin": "*", }, json={ + "folder_name": self.folder_name, "nb_pictures": self.nb_pictures }) ) @@ -89,6 +91,7 @@ def test_new_batch_import_wrong_nb_pictures(self): }, json={ "container_name": "", + "folder_name": self.folder_name, "nb_pictures": self.nb_pictures }) ) @@ -106,6 +109,7 @@ def test_new_batch_import_wrong_nb_pictures(self): }, json={ "container_name": self.container_name, + "folder_name": self.folder_name, "nb_pictures": "1" }) ) @@ -123,6 +127,7 @@ def test_new_batch_import_wrong_nb_pictures(self): }, json={ "container_name": self.container_name, + "folder_name": "test_batch_import", "nb_pictures": 0 }) ) @@ -136,7 +141,8 @@ def setUp(self): self.test_client = app.test_client() self.container_name = "a427278e-28df-428f-8937-ddeeef44e72f" self.nb_pictures = 1 - + self.folder_name = "test_batch_import" + self.session_id = None response = asyncio.run( self.test_client.post( '/new-batch-import', @@ -146,12 +152,16 @@ def setUp(self): }, json={ "container_name": self.container_name, + "folder_name": self.folder_name, "nb_pictures": self.nb_pictures }) ) - result_json = json.loads(asyncio.run(response.get_data())) - self.folder_name = result_json.get("session_id") + if response.status_code == 200: + print("Setup : folder successfully created") + else : + print(result_json) + self.session_id = result_json.get("session_id") self.seed_name = "Ambrosia artemisiifolia" self.zoom_level = None @@ -164,22 +174,22 @@ def setUp(self): self.image = self.image_header + self.image_src def tearDown(self): - if(self.folder_name is not None): + if(self.session_id is not None): response = asyncio.run( self.test_client.post( - '/del', + '/delete-permanently', headers={ "Content-Type": "application/json", "Access-Control-Allow-Origin": "*", }, json={ "container_name": self.container_name, - "folder_name": self.folder_name + "folder_uuid": self.session_id }) ) if(response.status_code == 200): - self.folder_name = None - # does delete folder also delete pictures ? + print("Teardown : folder successfully deleted") + self.session_id = None self.test_client = None def test_upload_picture_successfull(self): @@ -192,7 +202,7 @@ def test_upload_picture_successfull(self): }, json={ "container_name": self.container_name, - "session_id": self.folder_name, + "session_id": self.session_id, "seed_name": self.seed_name, "zoom_level": self.zoom_level, "nb_seeds": self.nb_seeds, @@ -245,7 +255,7 @@ def test_upload_picture_wrong_arguments_error(self): }, json={ "container_name": "", # wrong container_name - "session_id": self.folder_name, + "session_id": self.session_id, "seed_name": self.seed_name, "zoom_level": self.zoom_level, "nb_seeds": self.nb_seeds,