Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changed endpoint format for GET,PUT, DELETE for multiple objects of Class and Collections #590

Merged
merged 8 commits into from Jun 21, 2021
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
19 changes: 0 additions & 19 deletions hydrus/app_factory.py
Expand Up @@ -19,9 +19,6 @@ def app_factory(api_name: str = "api", vocab_route: str = "vocab") -> Flask:
Entrypoint,
ItemCollection,
Item,
Items,
ItemMember,
ItemMembers,
)

app = Flask(__name__)
Expand Down Expand Up @@ -51,21 +48,5 @@ def root_url():
ItemCollection, f"/{api_name}/<string:path>", endpoint="item_collection"
)
api.add_resource(Item, f"/{api_name}/<string:path>/<uuid:id_>", endpoint="item")
api.add_resource(
ItemMember,
f"/{api_name}/<string:path>/<uuid:collection_id_>/<uuid:id_>",
endpoint="member"
)
api.add_resource(
ItemMembers,
f"/{api_name}/<string:path>/<uuid:collection_id_>/delete/<int_list>",
endpoint="members"
)
api.add_resource(
Items,
f"/{api_name}/<string:path>/add/<int_list>",
f"/{api_name}/<string:path>/add",
f"/{api_name}/<string:path>/delete/<int_list>",
)

return app
9 changes: 6 additions & 3 deletions hydrus/data/crud.py
Expand Up @@ -149,9 +149,10 @@ def insert_multiple(
valid/defined RDFClass but is not a dictionary neither an Abstract Property

"""
# import pdb;pdb.set_trace()

id_list = id_.split(",")
if id_:
id_list = id_.split(",")
else:
id_list = None

# list to hold all the ids of inserted objects
instance_id_list = []
Expand All @@ -164,6 +165,8 @@ def insert_multiple(
id_of_object_ = id_list[index]
except IndexError:
pass
except TypeError:
pass
inserted_object_id = insert(object_, session, id_of_object_)
instance_id_list.append(inserted_object_id)

Expand Down
113 changes: 23 additions & 90 deletions hydrus/resources.py
Expand Up @@ -106,6 +106,13 @@ def get(self, id_: str, path: str) -> Response:
# Get path of the collection-class
class_path = item_class.path
is_collection = True
# To check if it's a request to GET a single instance from Collection
params = request.args.to_dict()
member_id = params.get('instance', None)
if member_id:
Mec-iS marked this conversation as resolved.
Show resolved Hide resolved
return member_get_check_support(
id_, member_id, class_type, class_path, path
)
if checkClassOp(class_path, "GET"):
return items_get_check_support(
id_, class_type, class_path, path, is_collection
Expand Down Expand Up @@ -165,6 +172,10 @@ def delete(self, id_: str, path: str) -> Response:
:param path - Path for Item type( Specified in APIDoc @id) to be deleted
"""
id_ = str(id_)
params = request.args.to_dict()
if params.get('instance'):
id_list = params.get('instance', None)
return items_delete_members_response(path, id_, id_list)
collections, parsed_classes = get_collections_and_parsed_classes()
is_collection = False
if path in parsed_classes:
Expand Down Expand Up @@ -208,104 +219,26 @@ def put(self, path: str) -> Response:
if not endpoint_["method"]:
# If endpoint and PUT method is not supported in the API
abort(endpoint_["status"])
# If 'instance' is available in request
params = request.args.to_dict()
object_ = json.loads(request.data.decode("utf-8"))
if params.get("instance") or object_.get("data"):
int_list = params.get("instance", None)
return items_put_response(path, int_list)
return item_collection_put_response(path)


class ItemMember(Resource):
"""Handles operations(GET,DELETE) related to member of an Item(Collection).
(Item should be hydra:Collection)"""

@authenticate
def get(self, id_: str, path: str, collection_id_: str) -> Response:
"""
GET object with collection_id = collection_id_
and member = id_ (member of a collection) from the database.
:param id_ : Item ID (Member)
:param collection_id_ : Item ID (Collection)
:param path : Path for Item ( Specified in APIDoc @id)
:return : object with member=id_ and collection_id=collection_id_
"""
collection_id = str(collection_id_)
member_id = str(id_)
collections, parsed_classes = get_collections_and_parsed_classes()
if path in parsed_classes:
abort(405)
if path in collections:
item_class = collections[path]["collection"]
class_type = item_class.name
# Get path of the collection-class
class_path = item_class.path
if checkClassOp(class_path, "GET"):
return member_get_check_support(
collection_id, member_id, class_type, class_path, path
)
abort(405)

@authenticate
def delete(self, id_: str, path: str, collection_id_: str) -> Response:
"""
Delete object with id=id_ from database.
:param id_ - ID of Item to be deleted
:param path - Path for Item type( Specified in APIDoc @id) to be deleted
"""
collection_id = str(collection_id_)
member_id = str(id_)
collections, parsed_classes = get_collections_and_parsed_classes()
if path in parsed_classes:
abort(405)
if path in collections:
item_class = collections[path]["collection"]
class_type = item_class.name
# Get path of the collection-class
class_path = item_class.path
if checkClassOp(class_path, "DELETE"):
return member_delete_check_support(
collection_id, member_id, class_type, path
)
abort(405)


class Items(Resource):
"""Handles operations(PUT,DELETE) related to multiple objects.
(Item should be hydra:Class)"""

@authenticate
def put(self, path, int_list="") -> Response:
"""
To insert multiple objects into the database
:param path: endpoint
:param int_list: Optional String containing ',' separated ID's
:return:
"""
endpoint_ = checkEndpoint("PUT", path)
if not endpoint_["method"]:
# If endpoint and PUT method is not supported in the API
abort(endpoint_["status"])
return items_put_response(path, int_list)

@authenticate
def delete(self, path, int_list):
def delete(self, path):
"""
To delete multiple objects
:param path: endpoints
:param int_list: Optional String containing ',' separated ID's
:return:
"""
return items_delete_response(path, int_list)


class ItemMembers(Resource):
@authenticate
def delete(self, path, collection_id_, int_list):
"""
To delete multiple members from a Collection
:param path: endpoints
:param collection_id_: ID of the collection
:param int_list: Optional String containing ',' separated ID's
:return:
"""
collection_id_ = str(collection_id_)
return items_delete_members_response(path, collection_id_, int_list)
params = request.args.to_dict()
if params.get('instance'):
int_list = params.get('instance', None)
return items_delete_response(path, int_list)
abort(405)


class Contexts(Resource):
Expand Down
8 changes: 4 additions & 4 deletions tests/functional/test_app.py
Expand Up @@ -319,7 +319,7 @@ def test_object_PUT_at_ids(self, test_app_client, constants, doc):
ids = f'{uuid.uuid4()},'
data_['data'] = objects
if 'PUT' in class_methods:
put_response = test_app_client.put(f'{endpoints[endpoint]}/add/{ids}',
put_response = test_app_client.put(f'{endpoints[endpoint]}?instance={ids}',
data=json.dumps(data_))
assert put_response.status_code == 201
assert isinstance(put_response.json['iri'], list)
Expand Down Expand Up @@ -436,7 +436,7 @@ def test_Collections_member_GET(self, test_app_client, constants, doc):
if 'GET' in collection_methods:
for member in dummy_object['members']:
member_id = member['@id'].split('/')[-1]
get_response = test_app_client.get(f'{collection_endpoint}/{member_id}')
get_response = test_app_client.get(f'{collection_endpoint}?instance={member_id}')
assert get_response.status_code == 200

def test_Collections_member_DELETE(self, test_app_client, constants, doc):
Expand All @@ -458,7 +458,7 @@ def test_Collections_member_DELETE(self, test_app_client, constants, doc):
if 'DELETE' in collection_methods:
for member in dummy_object['members']:
member_id = member['@id'].split('/')[-1]
full_endpoint = f'{collection_endpoint}/{member_id}'
full_endpoint = f'{collection_endpoint}?instance={member_id}'
delete_response = test_app_client.delete(full_endpoint)
assert delete_response.status_code == 200

Expand All @@ -480,7 +480,7 @@ def test_Collections_member_DELETE_multiple(self, capsys, test_app_client, const
collection_endpoint = good_response_put.location
if 'DELETE' in collection_methods:
ids_list = get_ids_list(dummy_object)
full_endpoint = f'{collection_endpoint}/delete/{ids_list}'
full_endpoint = f'{collection_endpoint}?instance={ids_list}'
delete_response = test_app_client.delete(full_endpoint)
assert delete_response.status_code == 200

Expand Down