You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
They are in charge of transforming python objects, record(s), into a certain format or representation (e.g. JSON, XML). It is in charge of serializing both single and list of objects responses. The API should look like:
classSerializerMixinInterface:
"""Serializer Interface."""defserialize_object(self, object, response_ctx, *args, **kwargs):
"""Serialize a single record reponse according to the response ctx."""raiseNotImplementedError()
defserialize_object_list(self, object_list, response_ctx, *args, **kwargs):
"""Serialize a list of records reponse according to the response ctx."""raiseNotImplementedError()
defserialize_error(self, error, response_ctx, *args, **kwargs):
"""Serialize an error reponse according to the response ctx."""raiseNotImplementedError()
Things that are required by serialize_object:
What
Where is it
How is it currently accessed
pid_value
In the PersistentIdentifier object
An enriched Record API class containing a record has been defined. An instance of said Record class is the object received as parameter
self link, which implies view name to user url_for and the pid_value
link factory is still an open question
the record link generation is passed as a partial function in the response_ctx argument. Then it is called with the record object for the pid_value
Things that are required by serialize_object_list:
What
Where is it
How is it currently accessed
pid_value
In the PersistentIdentifier object
This problem is delegated to each call of serialize_object. See more details above.
self link, which implies view name to user url_for and the pid_value
link factory is still an open question
This problem is delegated to each call of serialize_object. See more details above.
paginated links, which implies view name to user url_for
pagination values are available in the resource_requestctx.
however, the function is still not coded. how is it passed to the serializer? another partial?
aggregations
in the ES response
currently they are passed to the function as a parameter. however, it should be independent of it.
total
in the ES reponse
it could simply be calculated as the total of records passed in the list, should be resilient enough to rely on that.
Ideally serialize_object_list should not be much more than a simple loop on the list calling serialize_object for each one. Could it be already be coded by default with some "add_extra" function that adds the total, aggregations, etc form context?
The main problem here relies on how the ES response is treated and where, in order for this function to receive a list of python objects. In addition, how much overhead (memory/time) does this add? Somehow we are serializing back and forth (ES --> Python --> Accepted-Mimetype, instead of ES --> Accepted-Mimetype). Nonetheless, this way is much more clean and maintainable.
Open questions:
Formatting, should this take care of "prettyprint"?
Should auxiliary functions such as metadata processing be defined in the interface?. For example, process_metadata is used mainly to replace_refs. It is small/Invenio specific enough to be accommodated into serialize_object. If for cleanness/clarity sake it should be splitted into more functions it should be up to the specific serializer. A new mixin could be defined for Invenio specific serializers.
The object received by serialize_object, and every object of the object list received by serialize_object, should implement an interface (called Serializable now, but a better name can be found). This interface would allow to access certain properties such as:
Note that the above return values above are examples for the Record. Another case would be for example a User class, when being serialized it would need to build the self link. For that the id() would return for example the user_name.
Response
classItemResponse:
"""Item response representation. Builds up a reponse based on the response_code and the content."""def__init__(self, serializer=None, *args, **kwargs):
self.serializer=serializerdefmake_response(code, content):
# This should do the link building (e.g. sign posting): self, pagination, query, etc.# In case of list responses, it would also take care of extras such as aggregationrequest.make_response(
response_code=code,
body=self.serializer.serialize_object(content) # content is the object,headers=self.make_header()
)
defmake_error_response(reason, message):
request.make_response(
get_http_code_for_error(reason), message
)
classItemView(BaseView):
"""Item view representation. Allows reading, (partial) updating and deleting an item."""def__init__(self, *args, **kwargs):
super(ItemView, self).__init__(*args, **kwargs)
self.item_parser=self.resource.config.item_request_parserself.item_serializers=self.resource.config.item_serializers@content_regotiation# this decorator might be added to the BaseView in the same fashion than `with_request_resourcectx`@authentication# this would add to the resource_requestctx the user needs/datadefget(self, *args, **kwargs):
resource_requestctx.request_args=self.item_parser.parse()
item_handler=self.item_handlers[request_resourcectx.accept_mimetype] # this could be pushed up to the content-negotiationtry:
content=self.resource.read()
returnitem_handler.make_response(200, content)
exceptase:
returnitem_handler.make_error_response(e.reason, e.message)
Table of contents
Serializers
They are in charge of transforming python objects, record(s), into a certain format or representation (e.g. JSON, XML). It is in charge of serializing both single and list of objects responses. The API should look like:
Things that are required by
serialize_object
:pid_value
PersistentIdentifier
objectRecord
API class containing a record has been defined. An instance of said Record class is the object received as parameterurl_for
and thepid_value
response_ctx
argument. Then it is called with the record object for thepid_value
Things that are required by
serialize_object_list
:pid_value
PersistentIdentifier
objectserialize_object
. See more details above.url_for
and thepid_value
serialize_object
. See more details above.url_for
resource_requestctx
.Ideally
serialize_object_list
should not be much more than a simple loop on the list callingserialize_object
for each one. Could it be already be coded by default with some "add_extra" function that adds the total, aggregations, etc form context?The main problem here relies on how the ES response is treated and where, in order for this function to receive a list of python objects. In addition, how much overhead (memory/time) does this add? Somehow we are serializing back and forth (ES --> Python --> Accepted-Mimetype, instead of ES --> Accepted-Mimetype). Nonetheless, this way is much more clean and maintainable.
Open questions:
process_metadata
is used mainly toreplace_refs
. It is small/Invenio specific enough to be accommodated intoserialize_object
. If for cleanness/clarity sake it should be splitted into more functions it should be up to the specific serializer. A new mixin could be defined for Invenio specific serializers.Related to
errors.py
and decouple error abstraction from serialization #3.Serializable
The object received by
serialize_object
, and every object of the object list received byserialize_object
, should implement an interface (calledSerializable
now, but a better name can be found). This interface would allow to access certain properties such as:Note that the above return values above are examples for the
Record
. Another case would be for example aUser
class, when being serialized it would need to build the self link. For that theid()
would return for example theuser_name
.Response
More at https://codimd.web.cern.ch/lMgvRdXRQZS45oKqqrRZpw
The text was updated successfully, but these errors were encountered: