def get(self, db_id, id): """ Get any entity. :param db_id: :param id: String :return: Entity with descendents in a json tree like: {"content": EntityObj, "children": [JsonObjectNode with Child_1, JsonObjectNode with Child_2]} """ args = self.get_parser.parse_args() logging.info("entity get by id = " + id) db = get_db(db_name_frontend=db_id) if db is None: return "No such db id", 404 entity = common_data_containers.JsonObject.from_id(id=id, db_interface=db) if entity is None: return "No such entity id", 404 else: node = common_data_containers.JsonObjectNode.from_details( content=entity) node.fill_descendents(db_interface=db, depth=args['depth']) # pprint(binfo) return node.to_json_map(), 200
def get(self, db_id, id): """ Get all targetters for this entity. :param db_id: :param id: :return: A list of JsonObjectNode-s with targetters with the following structure. {"content": Annotation, "children": [JsonObjectNode with targetting Entity]} """ logging.info("entity id = " + str(id)) entity = common_data_containers.UllekhanamJsonObject() entity._id = str(id) args = self.get_parser.parse_args() logging.debug(args["filter_json"]) db = get_db(db_name_frontend=db_id) if db is None: return "No such db id", 404 targetters = entity.get_targetting_entities( db_interface=db, entity_type=args["targetter_class"]) targetter_nodes = [ common_data_containers.JsonObjectNode.from_details( content=annotation) for annotation in targetters ] for node in targetter_nodes: node.fill_descendents(db_interface=db, depth=args["depth"] - 1, entity_type=args["targetter_class"]) return common_data_containers.JsonObject.get_json_map_list( targetter_nodes), 200
def get(self, page_id, db_id): """ Get all annotations (pre existing or automatically generated, using open CV) for this page. :param page_id: :param db_id :return: A list of JsonObjectNode-s with annotations with the following structure. {"content": ImageAnnotation, "children": [JsonObjectNode with TextAnnotation_1]} """ logging.info("page get by id = " + str(page_id)) db = get_db(db_name_frontend=db_id) if db is None: return "No such db id", 404 page = common_data_containers.JsonObject.from_id(id=page_id, db_interface=db) if page is None: return "No such book portion id", 404 else: page_image = DocImage.from_path(path=os.path.join( page.get_external_storage_path(db_interface=db), page.list_files(db_interface=db, suffix_pattern="content*") [0])) image_annotations = db.update_image_annotations( page=page, page_image=page_image) image_annotation_nodes = [ common_data_containers.JsonObjectNode.from_details( content=annotation) for annotation in image_annotations ] for node in image_annotation_nodes: node.fill_descendents(db_interface=db) return common_data_containers.JsonObject.get_json_map_list( image_annotation_nodes), 200
def get(self, db_id): """ Get booklist. :return: a list of JsonObjectNode json-s. """ db = get_db(db_name_frontend=db_id) if db is None: return "No such db id", 404 booklist = [book.to_json_map() for book in db.list_books()] # logging.debug(booklist) return booklist, 200
def post(self, db_id): """ Add some trees of entities. (You **cannot** add a DAG graph of nodes in one shot - you'll need multiple calls.) input json: A list of JsonObjectNode-s with entities with the following structure. {"content": Annotation or BookPortion, "children": [JsonObjectNode with child Annotation or BookPortion]} :return: Same as the input trees, with id-s. """ logging.info(str(request.json)) if not check_permission(db_name=db_id): return "", 401 nodes = common_data_containers.JsonObject.make_from_dict_list( request.json) db = get_db(db_name_frontend=db_id) if db is None: return "No such db id", 404 for node in nodes: from jsonschema import ValidationError # noinspection PyUnusedLocal,PyUnusedLocal try: node.update_collection(db_interface=db, user=get_user()) except ValidationError as e: import traceback message = { "message": "Some input object does not fit the schema.", "exception_dump": (traceback.format_exc()) } return message, 417 except common_data_containers.TargetValidationError as e: import traceback message = { "message": "Target validation failed.", "exception_dump": (traceback.format_exc()) } return message, 418 return common_data_containers.JsonObject.get_json_map_list(nodes), 200
def delete(self, db_id): """ Delete trees of entities. input json: A list of JsonObjectNode-s with entities with the following structure. {"content": Annotation or BookPortion, "children": [JsonObjectNode with child Annotation or BookPortion]} :return: Empty. """ if not check_permission(db_name=db_id): return "", 401 nodes = common_data_containers.JsonObject.make_from_dict_list( request.json) db = get_db(db_name_frontend=db_id) if db is None: return "No such db id", 404 for node in nodes: node.delete_in_collection(db_interface=db, user=get_user()) return {}, 200
def get(self, db_id, id): """ Get files associated with an entity. :param db_id: :param id: String :return: Entity with descendents in a json tree like: {"content": EntityObj, "children": [JsonObjectNode with Child_1, JsonObjectNode with Child_2]} """ args = self.get_parser.parse_args() logging.info("entity get by id = " + id) db = get_db(db_name_frontend=db_id) if db is None: return "No such db id", 404 entity = common_data_containers.JsonObject.from_id(id=id, db_interface=db) if entity is None: return "No such entity id", 404 else: return entity.list_files(db_interface=db, suffix_pattern=args["pattern"]), 200
def get(self, db_id, id, file_name): """ Get files associated with an entity. :param db_id: :param id: String :param file_name: String :return: Entity with descendents in a json tree like: {"content": EntityObj, "children": [JsonObjectNode with Child_1, JsonObjectNode with Child_2]} """ logging.info("entity get by id = " + id) db = get_db(db_name_frontend=db_id) if db is None: return "No such db id", 404 entity = common_data_containers.JsonObject.from_id(id=id, db_interface=db) if entity is None: return "No such entity id", 404 else: from flask import send_from_directory return send_from_directory( directory=entity.get_external_storage_path(db_interface=db), filename=file_name)
def import_db(db_name_frontend="ullekhanam_test_v2"): from vedavaapi_py_api.ullekhanam.backend import get_db db = get_db(db_name_frontend=db_name_frontend) db.import_all(rootdir=db.external_file_store)
def dump_db(dest_dir=os.path.join(REPO_ROOT, "books_v2")): from vedavaapi_py_api.ullekhanam.backend import get_db db = get_db(db_name_frontend="ullekhanam_test") logging.debug(db.list_books()) db.dump_books(dest_dir)
def post(self, db_id): """Handle uploading files. :return: Book details in a json tree like: {"content": BookPortionObj, "children": [JsonObjectNode with BookPortion_Pg1, JsonObjectNode with BookPortion_Pg2]} """ from vedavaapi_py_api import ullekhanam if not ullekhanam.api_v1.check_permission(db_name=db_id): return "", 401 db = get_db(db_name_frontend=db_id) if db is None: return "No such db id", 404 book_json = request.form.get("book_json") logging.debug(book_json) # To avoid having to do rollbacks, we try to prevalidate the data to the maximum extant possible. book = common_data_containers.JsonObject.make_from_pickledstring( book_json) if book.base_data != "image" or not isinstance(book, books.BookPortion): message = { "message": "Only image books can be uploaded with this API." } return message, 417 if hasattr(book, "_id"): message = { "message": "overwriting " + book._id + " is not allowed." } logging.warning(str(message)) return message, 405 # Check the files for uploaded_file in request.files.getlist("in_files"): input_filename = os.path.basename(uploaded_file.filename) allowed_extensions = {".jpg", ".png", ".gif"} if not is_extension_allowed(input_filename, allowed_extensions): message = { "message": "Only these extensionsa are allowed: %(exts)s, but filename is %(input_filename)s" % dict(exts=str(allowed_extensions), input_filename=input_filename), } logging.error(message) return message, 418 # Book is validated here. book = book.update_collection(db_interface=db, user=get_user()) try: page_index = -1 for uploaded_file in request.files.getlist("in_files"): page_index = page_index + 1 # TODO: Add image update subroutine and call that. page = books.BookPortion.from_details( title="pg_%000d" % page_index, base_data="image", portion_class="page", targets=[ books.BookPositionTarget.from_details( position=page_index, container_id=book._id) ]) page = page.update_collection(db_interface=db, user=get_user()) page_storage_path = page.get_external_storage_path( db_interface=db) logging.debug(page_storage_path) input_filename = os.path.basename(uploaded_file.filename) logging.debug(input_filename) original_file_path = join(page_storage_path, "original__" + input_filename) os.makedirs(os.path.dirname(original_file_path), exist_ok=True) uploaded_file.save(original_file_path) image_file_name = "content.jpg" tmp_image = cv2.imread(original_file_path) cv2.imwrite(join(page_storage_path, image_file_name), tmp_image) image = Image.open(join(page_storage_path, image_file_name)).convert('RGB') working_filename = "content__resized_for_uniform_display.jpg" out = open(join(page_storage_path, working_filename), "w") img = DocImage.resize(image, (1920, 1080), False) img.save(out, "JPEG", quality=100) out.close() image = Image.open(join(page_storage_path, image_file_name)).convert('RGB') thumbnailname = "thumb.jpg" out = open(join(page_storage_path, thumbnailname), "w") img = DocImage.resize(image, (400, 400), True) img.save(out, "JPEG", quality=100) out.close() except: message = { "message": "Unexpected error while saving files: " + str(sys.exc_info()[0]), "deatils": traceback.format_exc() } logging.error(str(message)) logging.error(traceback.format_exc()) book_portion_node = common_data_containers.JsonObjectNode.from_details( content=book) logging.error("Rolling back and deleting the book!") book_portion_node.delete_in_collection(db_interface=db) return message, 419 book_portion_node = common_data_containers.JsonObjectNode.from_details( content=book) book_portion_node.fill_descendents(db_interface=db) return book_portion_node.to_json_map(), 200