def api_init_model_ready(project_id): # noqa: F401 """Check if trained model is available """ error_path = get_project_path(project_id) / "error.json" if error_path.exists(): logging.error("error on training") with open(error_path, "r") as f: error_message = json.load(f) return jsonify(message=error_message), 400 try: if get_proba_path(project_id).exists(): # read the file with project info with open(get_project_file_path(project_id), "r") as fp: project_info = json.load(fp) project_info["projectInitReady"] = True # update the file with project info with open(get_project_file_path(project_id), "w") as fp: json.dump(project_info, fp) response = jsonify({'status': 1}) else: response = jsonify({'status': 0}) except Exception as err: logging.error(err) return jsonify(message="Failed to initiate the project."), 500 response.headers.add('Access-Control-Allow-Origin', '*') return response
def main(argv): # parse arguments parser = argparse.ArgumentParser() parser.add_argument("project_id", type=str, help="Project id") parser.add_argument("--label_method", type=str, default=None, help="Label method (for example 'prior')") args = parser.parse_args(argv) try: train_model(args.project_id, args.label_method) except Exception as err: err_type = type(err).__name__ logging.error(f"Project {args.project_id} - {err_type}: {err}") # write error to file is label method is prior (first iteration) if args.label_method == "prior": message = {"message": f"{err_type}: {err}"} fp = get_project_path(args.project_id) / "error.json" with open(fp, 'w') as f: json.dump(message, f) # raise the error for full traceback raise err
def api_init_model_ready(project_id): # noqa: F401 """Check if trained model is available """ error_path = get_project_path(project_id) / "error.json" if error_path.exists(): print("error on training") with open(error_path, "r") as f: error_message = json.load(f) return jsonify(error_message), 400 if get_proba_path(project_id).exists(): logging.info("Model trained - go to review screen") # read the file with project info with open(get_project_file_path(project_id), "r") as fp: project_info = json.load(fp) project_info["projectInitReady"] = True # update the file with project info with open(get_project_file_path(project_id), "w") as fp: json.dump(project_info, fp) response = jsonify({'status': 1}) else: response = jsonify({'status': 0}) response.headers.add('Access-Control-Allow-Origin', '*') return response
def export_project(project_id): """Export the project file. The ASReview project file is a file with .asreview extension. The ASReview project file is a zipped file and contains all information to continue working on the project as well as the orginal dataset. """ # create a temp folder to zip tmpdir = tempfile.TemporaryDirectory() # copy the source tree, but ignore pickle files shutil.copytree(get_project_path(project_id), Path(tmpdir.name, project_id), ignore=shutil.ignore_patterns('*.pickle')) # create the archive shutil.make_archive(Path(tmpdir.name, project_id), "zip", root_dir=Path(tmpdir.name, project_id)) # return the project file to the user return send_file(str(Path(tmpdir.name, f"{project_id}.zip")), as_attachment=True, attachment_filename=f"{project_id}.asreview", cache_timeout=0)
def update_project_info(project_id, project_name=None, project_description=None, project_authors=None): '''Update project info''' project_id_new = re.sub('[^A-Za-z0-9]+', '-', project_name).lower() if not project_id_new and not isinstance(project_id_new, str) \ and len(project_id_new) >= 3: raise ValueError("Project name should be at least 3 characters.") if (project_id != project_id_new) & is_project(project_id_new): raise ValueError("Project name already exists.") try: # read the file with project info with open(get_project_file_path(project_id), "r") as fp: project_info = json.load(fp) project_info["id"] = project_id_new project_info["name"] = project_name project_info["authors"] = project_authors project_info["description"] = project_description # # backwards support <0.10 # if "projectInitReady" not in project_info: # project_info["projectInitReady"] = True # update the file with project info with open(get_project_file_path(project_id), "w") as fp: json.dump(project_info, fp) # rename the folder get_project_path(project_id) \ .rename(Path(asreview_path(), project_id_new)) except Exception as err: raise err return project_info["id"]
def import_project_file(file_name): """Import .asreview project file""" try: # Unzip the project file with zipfile.ZipFile(file_name, "r") as zip_obj: zip_filenames = zip_obj.namelist() # raise error if no ASReview project file if "project.json" not in zip_filenames: raise ValueError("File doesn't contain valid project format.") # extract all files to a temporary folder tmpdir = tempfile.mkdtemp() zip_obj.extractall(path=tmpdir) except zipfile.BadZipFile: raise ValueError("File is not an ASReview file.") try: # Open the project file and check the id. The id needs to be # unique, otherwise it is exended with -copy. import_project = None fp = Path(tmpdir, "project.json") with open(fp, "r+") as f: # load the project info in scope of function import_project = json.load(f) # If the uploaded project already exists, # then overwrite project.json with a copy suffix. while is_project(import_project["id"]): # project update import_project["id"] = f"{import_project['id']}-copy" import_project["name"] = f"{import_project['name']} copy" else: # write to file f.seek(0) json.dump(import_project, f) f.truncate() # location to copy file to fp_copy = get_project_path(import_project["id"]) # Move the project from the temp folder to the projects folder. os.replace(tmpdir, fp_copy) except Exception: # Unknown error. raise ValueError( "Failed to import project " f"'{file_name.filename}'." ) return import_project["id"]
def api_update_project_info(project_id): # noqa: F401 """Get info on the article""" logging.info("Update project info") project_name = request.form['name'] project_description = request.form['description'] project_authors = request.form['authors'] project_id_new = re.sub('[^A-Za-z0-9]+', '-', project_name).lower() try: # read the file with project info with open(get_project_file_path(project_id), "r") as fp: project_info = json.load(fp) project_info["id"] = project_id_new project_info["name"] = project_name project_info["authors"] = project_authors project_info["description"] = project_description # # backwards support <0.10 # if "projectInitReady" not in project_info: # project_info["projectInitReady"] = True # update the file with project info with open(get_project_file_path(project_id), "w") as fp: json.dump(project_info, fp) # rename the folder get_project_path(project_id) \ .rename(Path(asreview_path(), project_id_new)) except Exception as err: logging.error(err) response = jsonify(message="project-update-failure") return response, 500 return api_get_project_info(project_id_new)
def init_project(project_id, project_name=None, project_description=None, project_authors=None): """Initialize the necessary files specific to the web app.""" if not project_id and not isinstance(project_id, str) \ and len(project_id) >= 3: raise ValueError("Project name should be at least 3 characters.") if is_project(project_id): raise ValueError("Project already exists.") try: get_project_path(project_id).mkdir() get_data_path(project_id).mkdir() project_config = { 'version': asreview_version, # todo: Fail without git? 'id': project_id, 'name': project_name, 'description': project_description, 'authors': project_authors, 'created_at_unix': int(time.time()), # project related variables 'projectInitReady': False, 'reviewFinished': False, } # create a file with project info with open(get_project_file_path(project_id), "w") as fp: json.dump(project_config, fp) return project_config except Exception as err: # remove all generated folders and raise error shutil.rmtree(get_project_path()) raise err
def export_project(project_id): """Export a zipped project file""" tmpdir = tempfile.TemporaryDirectory() shutil.make_archive(Path(tmpdir.name, f"export_{project_id}"), "zip", get_project_path(project_id)) fp_tmp_export = Path(tmpdir.name, f"export_{project_id}.zip") return send_file(fp_tmp_export, as_attachment=True, attachment_filename=f"{project_id}.asreview", cache_timeout=0)
def update_project_info(project_id, project_name=None, project_description=None, project_authors=None): '''Update project info''' project_id_new = create_project_id(project_name) if (project_id != project_id_new) & is_project(project_id_new): raise ValueError("Project name already exists.") try: # read the file with project info with open(get_project_file_path(project_id), "r") as fp: project_info = json.load(fp) project_info["id"] = project_id_new project_info["name"] = project_name project_info["authors"] = project_authors project_info["description"] = project_description # # backwards support <0.10 # if "projectInitReady" not in project_info: # project_info["projectInitReady"] = True # update the file with project info with open(get_project_file_path(project_id), "w") as fp: json.dump(project_info, fp) # rename the folder get_project_path(project_id) \ .rename(Path(asreview_path(), project_id_new)) except Exception as err: raise err return project_info["id"]
def clean_project_tmp_files(project_id): """Clean temporary files in a project. Arguments --------- project_id: str The id of the current project. """ project_path = get_project_path(project_id) # clean pickle files for f_pickle in project_path.rglob("*.pickle"): try: os.remove(f_pickle) except OSError as e: print(f"Error: {f_pickle} : {e.strerror}")
def api_clear_model_error(project_id): """Clear model training error""" error_path = get_project_path(project_id) / "error.json" state_path = get_state_path(project_id) if error_path.exists() and state_path.exists(): os.remove(error_path) os.remove(state_path) response = jsonify({'success': True}) response.headers.add('Access-Control-Allow-Origin', '*') return response response = jsonify(message="Failed to clear model training error.") return response, 500
def export_project(project_id): """Export a zipped project file""" Path(asreview_path(), "tmp").mkdir(exist_ok=True) shutil.make_archive( Path(asreview_path(), f"tmp/export_{project_id}"), "zip", get_project_path(project_id) ) fp_tmp_export = Path(asreview_path(), f"tmp/export_{project_id}.zip") return send_file( fp_tmp_export, as_attachment=True, attachment_filename=f"{project_id}.asreview.zip", cache_timeout=0 )
def read_proba_legacy(project_id): """Read a project <0.15 proba values""" # get the old json project file path proba_fp = Path(get_project_path(project_id), "proba.json") with open(proba_fp, "r") as f: # read the JSON file and make a list of the proba's proba = json.load(f) proba = [float(x) for x in proba] # make a dataframe that looks like the new structure as_data = read_data(project_id) proba = pd.DataFrame({"proba": [float(x) for x in proba]}, index=as_data.record_ids) proba.index.name = "record_id" return proba
def api_delete_project(project_id): # noqa: F401 """Get info on the article""" # some checks to check if there is a project to delete if project_id == "" or project_id is None: response = jsonify(message="project-delete-failure") return response, 500 project_path = get_project_path(project_id) if project_path.exists() and project_path.is_dir(): shutil.rmtree(project_path) response = jsonify({'success': True}) response.headers.add('Access-Control-Allow-Origin', '*') return response response = jsonify(message="project-delete-failure") return response, 500
def is_project(project_id): if get_project_path(project_id).exists(): return True return False
def api_import_project(): """Import uploaded project""" # raise error if file not given if 'file' not in request.files: response = jsonify(message="No file found to upload.") return response, 400 # import project id import_project = None # set the project file project_file = request.files['file'] try: with zipfile.ZipFile(project_file, "r") as zip_obj: zip_filenames = zip_obj.namelist() # raise error if no ASReview project file if "project.json" not in zip_filenames: response = jsonify( message="File doesn't contain valid project format.") return response, 404 # extract all files to a temporary folder tmpdir = tempfile.TemporaryDirectory() zip_obj.extractall(path=tmpdir.name) # Open the project file and check the id. The id needs to be # unique, otherwise it is exended with -copy. fp = Path(tmpdir.name, "project.json") with open(fp, "r+") as f: # load the project info in scope of function import_project = json.load(f) # If the uploaded project already exists, # then overwrite project.json with a copy suffix. while is_project(import_project["id"]): # project update import_project["id"] = f"{import_project['id']}-copy" import_project["name"] = f"{import_project['name']} copy" else: # write to file f.seek(0) json.dump(import_project, f) f.truncate() except Exception as err: # Unknown error. logging.error(err) response = jsonify(message="Unknown error when uploading project " f"'{project_file.filename}'.") return response, 400 # location to copy file to fp_copy = get_project_path(import_project["id"]) try: # Move the project from the temp folder to the projects folder. os.rename(tmpdir.name, fp_copy) except Exception as err: logging.error(err) response = jsonify(message=f"Failed to copy project to {fp_copy}.") return response, 400 # return the project info in the same format as project_info return api_get_project_info(import_project["id"])