-
Notifications
You must be signed in to change notification settings - Fork 1
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
Feature/adding mset replacement functionality 20210615 #445
base: develop
Are you sure you want to change the base?
Feature/adding mset replacement functionality 20210615 #445
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
I don't think this would work yet, replaced_msets
is joining MSetReplacementEvent
with MetadataSet
based on metadataset_id
which is referring to the new metadataset rather than the old metadataset_s_.
The MetaDataSet
class will need an attribute
MetaDataSet.replaced_by_event_id # foreign key
MetaDataSet.replaced_by_event # relationship
which refers to the replacement event if it was replaced. To be able to access also the replacement events in which a metadataset is in the "new" role there should also be a relationship attribute
MetaDataSet.replaces_event # relationship
based on MsetReplacementEvent.metadataset_id
. Maybe that attribute should also be renamed to new_metadataset_id
to make immediately clear which role the foreign entity linked here has.
datameta/models/db.py
Outdated
user_id = Column(Integer, ForeignKey('users.id'), nullable=False) | ||
datetime = Column(DateTime, nullable=False) | ||
# former 'is_deprecated' label from MetaDataSet | ||
reason = Column(String(140), nullable=False) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reason = Column(String(140), nullable=False) | |
label = Column(String(140), nullable=False) |
datameta/api/metadatasets.py
Outdated
if replaces and not replaces_label: | ||
return HTTPBadRequest() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please return a proper validation error with a message. Also the inverse case should be checked and fail with a proper message (I mean the case label specified without any replacements to make)
datameta/api/metadatasets.py
Outdated
if target_mset is None: | ||
raise HTTPForbidden() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The invalid replacement IDs should be collected and returned as a validation error
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Generally looking good, comments below.
datameta/api/metadatasets.py
Outdated
if replaces and not replaces_label: | ||
raise errors.get_validation_error(messages=['No reason (label) given for Metadataset replacement.']) # maybe label should be reason. | ||
if not replaces and replaces_label: | ||
raise errors.get_validation_error(messages=["No metadataset ids specified (replacement reason (label) is given."]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
raise errors.get_validation_error(messages=["No metadataset ids specified (replacement reason (label) is given."]) | |
raise errors.get_validation_error(messages=["No metadataset IDs specified (replacement reason (label) is given."]) |
@@ -279,7 +311,7 @@ def get_metadatasets(request: Request) -> List[MetaDataSetResponse]: | |||
query = query.filter(Submission.date < submitted_before.astimezone(timezone.utc)) | |||
if awaiting_service is not None: | |||
if awaiting_service not in readable_services_by_id: | |||
raise errors.get_validation_error(messages=['Invalid service ID specified'], fields=['awaitingServices']) | |||
raise errors.get_validation_error(messages=['Invalid service ID specified'], fields=['awaitingService']) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
datameta/api/metadatasets.py
Outdated
for _, target_mset in msets: | ||
target_mset.replaced_via_event_id = mset_repl_evt.id |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This requires checking whether replaced_via_event_id
was previously set. Only if it is None
, a replacement is legal. Otherwise, a validation error should be returned.
datameta/api/metadatasets.py
Outdated
if missing_msets: | ||
messages, entities = zip(*missing_msets) | ||
raise errors.get_validation_error(messages=messages, entities=entities) | ||
|
||
already_replaced = [ | ||
(f"MetaDataSet was already replaced via event {target_mset.replaced_via_event_id}", mset_id) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This exposes an internal database ID. Also, I'd hide the event logic to the user and rather print the ID of the new mset (get_identifier
).
datameta/api/metadatasets.py
Outdated
@@ -220,7 +220,7 @@ def replace_metadatasets(request: Request) -> SubmissionResponse: | |||
|
|||
if missing_msets: | |||
messages, entities = zip(*missing_msets) | |||
raise errors.get_validation_error(messages=list(messages), entities=list(entities)) | |||
raise errors.get_validation_error(messages=list(messages), entities=list(entities)) # @lkuchenb: any idea why these list-casts are necessary to please mypy? they're not required in e.g validation.py:63 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
zip()
returns tuples, not lists
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that i know :P but why does it not complain in validation.py, line 63, which also uses zip-derived values for the arguments?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No idea. But we should probably not be so strict about the argument type in errors.get_validation_error
and relax it to Iterable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
raise errors.get_validation_error(messages=list(messages), entities=list(entities)) # @lkuchenb: any idea why these list-casts are necessary to please mypy? they're not required in e.g validation.py:63 | |
raise errors.get_validation_error(messages=list(messages), entities=list(entities)) |
The breaking test fixed via 0289f2a is probably due to something I don't understand regarding the fixtures. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot, also for already incorporating the visualization of the replacements in the "View" pane!
Here are my remarks:
datameta/api/metadatasets.py
Outdated
@@ -220,7 +220,7 @@ def replace_metadatasets(request: Request) -> SubmissionResponse: | |||
|
|||
if missing_msets: | |||
messages, entities = zip(*missing_msets) | |||
raise errors.get_validation_error(messages=list(messages), entities=list(entities)) | |||
raise errors.get_validation_error(messages=list(messages), entities=list(entities)) # @lkuchenb: any idea why these list-casts are necessary to please mypy? they're not required in e.g validation.py:63 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
raise errors.get_validation_error(messages=list(messages), entities=list(entities)) # @lkuchenb: any idea why these list-casts are necessary to please mypy? they're not required in e.g validation.py:63 | |
raise errors.get_validation_error(messages=list(messages), entities=list(entities)) |
@@ -224,6 +224,7 @@ def post(request: Request): | |||
submission_datetime = mdata_set.submission.date.isoformat(), | |||
submission_label = mdata_set.submission.label, | |||
service_executions = service_executions, | |||
replaced_by = get_identifier(mdata_set.replaced_via_event.new_metadataset) if mdata_set.replaced_via_event else None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will fire two additional queries for every mdata_set
, first when accessing the replaced_via_event
attribute, then when accessing the new_metadataset
attribute. Since we know we will be accessing those fields, we can instruct SQLAlchemy not to use lazy loading, but to join the corresponding relations already when we query the mdata_sets
. Please add the corresponding joins in L177.
Co-authored-by: Leon Kuchenbecker <[email protected]>
I tried to merge it yesterday, only some minor conflicts arose. |
No description provided.