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
Scottx611x/is tool based cleanup #2222
Conversation
… can remove `is_tool_based`
…the validation function
Codecov Report
@@ Coverage Diff @@
## develop #2222 +/- ##
==========================================
+ Coverage 48.8% 49.4% +0.59%
==========================================
Files 416 416
Lines 28222 27477 -745
Branches 1307 1307
==========================================
- Hits 13773 13574 -199
+ Misses 14449 13903 -546
Continue to review full report at Codecov.
|
@@ -20,176 +20,45 @@ | |||
|
|||
logger = logging.getLogger(__name__) | |||
|
|||
# Allow JSON Schema to find the JSON pointers we define in our schemas | |||
JSON_SCHEMA_FILE_RESOLVER = RefResolver( |
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.
If you kept this, could pieces like the UUID RE be defined separately? Would that be useful?
@@ -200,9 +69,9 @@ def fetch_objects_required_for_analysis(validated_analysis_config): | |||
:return: dict w/ mapping to the commonly used objects | |||
:raises: RuntimeError | |||
""" | |||
study_uuid = validated_analysis_config["studyUuid"] | |||
study_uuid = validated_analysis_config["study_uuid"] |
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.
Thinking about the dependency between this string and the json schema, it would probably be overkill to have the json created by python code?
refinery/core/models.py
Outdated
tool = workflow_tool.objects.get(analysis__uuid=self.uuid) | ||
except(workflow_tool.DoesNotExist, | ||
workflow_tool.MultipleObjectsReturned) as e: | ||
logger.error("Could not properly fetch Tool: %s", e) |
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.
Is logging an error sufficient? We'd then skip the else and drop to if self.history_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.
@mccalluc Now that I look at the surrounding code the exceptions would be pretty odd to hit, but I don't think we should re-raise anything and stop histories from being deleted as well.
@@ -73,9 +73,6 @@ def refinery_import_state(self): | |||
return get_task_group_state(self.refinery_import_task_group_id) | |||
|
|||
def galaxy_file_import_state(self): | |||
return get_task_group_state(self.galaxy_import_task_group_id) | |||
|
|||
def tool_based_galaxy_file_import_state(self): | |||
if self.galaxy_import_state and self.galaxy_import_progress != 0: |
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.
galaxy_import_state is a field of AnalysisStatus. Is it necessary to check whether it exists?
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.
Yes, you can still construct an AnalysisStatus like so w/o a galaxy_import_state
: AnalysisStatus.objects.create(analysis=analysis)
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.
Right but the field would actually exists with a default value, no?
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 default value for a blank=True
is u''
which is still falsey
For example, this test case passes:
def test_analysis_status_galaxy_import_state_is_falsey_by_default(self):
analysis_status = AnalysisStatus.objects.create(analysis=self.analysis)
self.assertFalse(analysis_status.galaxy_import_state)
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.
Yes but the field is there, so checking for its existence is not necessary.
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.
Its necessary as far as I can tell.
One would need to assert that there has been a galaxy_import_state
set and that some galaxy_import_progress
has happened before going ahead and handing a response over to the front end to display.
Otherwise theres nothing meaningful for the UI to display yet.
I could imagine a scenario occurring where the galaxy_import_state
is still equal to u''
and even though the galaxy_import_state
field is present, passing that information along to the frontend without checking it first would yield odd results.
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.
OK but you are already checking it by self.galaxy_import_progress != 0
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.
Just because there is positive galaxy_import_progress
doesn't mean that a valid galaxy_import_state
has been set as well?
Something like AnalyisStatus.objects.create(analysis=<analysis>, galaxy_import_progress=2)
Would break the UI with your proposed change
refinery/analysis_manager/tasks.py
Outdated
else: | ||
input_file_uuid_list = analysis.get_input_file_uuid_list() | ||
tool = _get_workflow_tool(analysis_uuid) | ||
input_file_uuid_list = tool.get_input_file_uuid_list() | ||
|
||
for input_file_uuid in input_file_uuid_list: |
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.
input_file_uuid_list is used only once. Replace with for input_file_uuid in tool.get_input_file_uuid_list()
and remove the line above?
@@ -486,121 +419,9 @@ def _run_tool_based_galaxy_workflow(analysis_uuid): | |||
return |
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.
Unnecessary? Same as lines 125, 141, 223, 291 and 365?
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.
I've just continued using these return
s as they we're being used beforehand in this area of the codebase. If you are confident that I can remove them then I can.
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.
They were necessary previously because they provided exit points in the middle of the function. Now they are all at the end of their respective functions, so they don't have any effect.
refinery/analysis_manager/tasks.py
Outdated
def _tool_based_galaxy_file_import(analysis_uuid, file_store_item_uuid, | ||
history_dict, library_dict): | ||
def _galaxy_file_import(analysis_uuid, file_store_item_uuid, history_dict, | ||
library_dict): | ||
tool = _get_workflow_tool(analysis_uuid) | ||
|
||
file_store_item = FileStoreItem.objects.get(uuid=file_store_item_uuid) |
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.
Exception handling?
refinery/analysis_manager/tasks.py
Outdated
file_type = 'zip' | ||
# TODO: when changing permanent=True, fix update of % download | ||
# of file | ||
filestore_uuid = create( |
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.
Should fit on one line.
refinery/analysis_manager/utils.py
Outdated
|
||
common_analysis_objects = fetch_objects_required_for_analysis( | ||
validated_analysis_config | ||
common_analysis_objects = ( |
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.
Why wrap this function call in parentheses?
name="{} - {} - {}".format( | ||
tool.get_tool_name(), | ||
get_aware_local_time().strftime("%Y/%m/%d %H:%M:%S"), | ||
tool.get_owner_username().title() |
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.
Username has a title?
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.
I think title
is just a method available to strings in python
refinery/analysis_manager/utils.py
Outdated
Validate incoming Tool Launch Configurations | ||
:param tool_launch_config: json data containing a ToolLaunchConfiguration | ||
Validate incoming Analysis Configurations | ||
:param analysis_config: json data containing an Analysis configuration | ||
""" | ||
with open( |
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.
Exception handling?
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.
All the JsonSchema validations are within the scopes of atomic transactions so I want any exceptions to propagate. I'll make a note.
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.
OK, a comment at the top of this function would be helpful. Btw, it looks like AnalysisConfig.json is essentially a configuration file, so I would move the reading operation out into base settings (similar to tutorial_steps.json, etc). This would make validate_analysis_config() cleaner and more testable. Also, should this file be named using snake case or camel case?
refinery/core/models.py
Outdated
# original galaxy workflow which we don't want to delete | ||
if not self.is_tool_based: | ||
if self.workflow_galaxy_id: | ||
workflow_tool = tool_manager.models.WorkflowTool |
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.
Assigning a model to a variable is an anti-pattern.
@hackdna I think that PRs grow to large sizes and become harder for reviewers when this exact scenario occurs (being asked to provide changes that were not part of a PRs original motivations). I don't see how having concise, directed PRs complicates things at all. |
My comment was specifically about 2f1419f |
refinery/analysis_manager/utils.py
Outdated
|
||
from django.conf import settings | ||
from django.contrib.auth.models import User | ||
from django.http import HttpResponseServerError | ||
from django.utils import timezone | ||
|
||
from jsonschema import RefResolver, ValidationError, validate | ||
from jsonschema import ValidationError, validate |
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.
Should be import jsonschema
refinery/config/settings/base.py
Outdated
JSON_SCHEMA_FILE_RESOLVER = RefResolver( | ||
"file://{}/".format(os.path.join(BASE_DIR, "refinery")), | ||
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.
An instance of RefResolver should not be a Django setting. Also, it looks like base_uri doesn't need to be a file path but could be any URI: something like http://refinery-platform.org to make things simpler.
Finally, a better approach might be to add the $id keyword to the schema and then use from_schema class method to create a resolver?
Fixes #2194
TO DO: