Skip to content

Commit

Permalink
#145: Add first implementation of POST request (create) for entities
Browse files Browse the repository at this point in the history
- This has only been tested on /investigations so far, so further changes may be needed when I test on the rest of the entities
  • Loading branch information
MRichards99 committed Oct 7, 2020
1 parent b33de8a commit 944b877
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 3 deletions.
4 changes: 3 additions & 1 deletion common/icat/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
get_count_with_filters,
get_first_result_with_filters,
update_entities,
create_entities,
)

from common.config import config
Expand Down Expand Up @@ -83,7 +84,8 @@ def get_with_filters(self, session_id, table, filters):
@requires_session_id
@queries_records
def create(self, session_id, table, data):
pass
self.client.sessionId = session_id
return create_entities(self.client, table.__name__, data)

@requires_session_id
@queries_records
Expand Down
73 changes: 71 additions & 2 deletions common/icat/helpers.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
from functools import wraps
import logging
from datetime import datetime, timedelta
from dateutil.parser import parse

from icat.entity import Entity, EntityList
from icat.query import Query
from icat.exception import ICATSessionError, ICATValidationError, ICATInternalError
from icat.exception import (
ICATSessionError,
ICATValidationError,
ICATInternalError,
ICATObjectExistsError,
)
from common.exceptions import (
AuthenticationError,
BadRequestError,
Expand Down Expand Up @@ -795,7 +801,7 @@ def update_entities(client, table_name, data_to_update):
:type client: :class:`icat.client.Client`
:param table_name: Table name to extract which entity to use
:type table_name: :class:`str`
:param data_to_update: The list of filters to be applied to the request
:param data_to_update: The data that to be updated in ICAT
:type data_to_update: :class:`list` or :class:`dict`
:return: The updated record(s) of the given entity
"""
Expand All @@ -818,3 +824,66 @@ def update_entities(client, table_name, data_to_update):
)

return updated_data


def create_entities(client, table_name, data):
"""
Add one or more results for the given entity using the JSON provided in `data`
:param client: ICAT client containing an authenticated user
:type client: :class:`icat.client.Client`
:param table_name: Table name to extract which entity to use
:type table_name: :class:`str`
:param data: The data that needs to be created in ICAT
:type data_to_update: :class:`list` or :class:`dict`
:return: The created record(s) of the given entity
"""

created_data = []

if not isinstance(data, list):
data = [data]

for result in data:
new_entity = client.new(table_name.lower())

for attribute_name, value in result.items():
try:
entity_info = new_entity.getAttrInfo(client, attribute_name)
if entity_info.relType.lower() == "attribute":
if is_str_a_date(value):
value = str_to_datetime_object(None, value)

setattr(new_entity, attribute_name, value)

else:
# This means the attribute has a relationship with another object
related_object = client.get(entity_info.type, value)
setattr(new_entity, attribute_name, related_object)

except ValueError as e:
raise BadRequestError(e)

try:
new_entity.create()
except (ICATValidationError, ICATInternalError) as e:
raise PythonICATError(e)
except ICATObjectExistsError as e:
raise BadRequestError(e)

created_data.append(get_entity_by_id(client, table_name, new_entity.id, True))

return created_data


def is_str_a_date(potential_date):
"""
TODO - Add docstring
"""

try:
# Disabled fuzzy to avoid picking up dates in things like descriptions etc.
parse(potential_date, fuzzy=False)
return True
except ValueError:
return False

0 comments on commit 944b877

Please sign in to comment.