/
tool_version_manager.py
115 lines (105 loc) · 6.53 KB
/
tool_version_manager.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import logging
from sqlalchemy import and_, or_
from tool_shed.util import hg_util
from tool_shed.util import metadata_util
from tool_shed.util import repository_util
from galaxy.tools.toolbox.lineages.tool_shed import ToolVersionCache
log = logging.getLogger( __name__ )
class ToolVersionManager( object ):
def __init__( self, app ):
self.app = app
def get_tool_version( self, tool_id ):
context = self.app.install_model.context
return context.query( self.app.install_model.ToolVersion ) \
.filter( self.app.install_model.ToolVersion.table.c.tool_id == tool_id ) \
.first()
def get_tool_version_association( self, parent_tool_version, tool_version ):
"""
Return a ToolVersionAssociation if one exists that associates the two
received tool_versions. This function is called only from Galaxy.
"""
context = self.app.install_model.context
return context.query( self.app.install_model.ToolVersionAssociation ) \
.filter( and_( self.app.install_model.ToolVersionAssociation.table.c.parent_id == parent_tool_version.id,
self.app.install_model.ToolVersionAssociation.table.c.tool_id == tool_version.id ) ) \
.first()
def get_version_lineage_for_tool( self, repository_id, repository_metadata, guid ):
"""
Return the tool version lineage chain in descendant order for the received
guid contained in the received repsitory_metadata.tool_versions. This function
is called only from the Tool Shed.
"""
repository = repository_util.get_repository_by_id( self.app, repository_id )
repo = hg_util.get_repo_for_repository( self.app, repository=repository, repo_path=None, create=False )
# Initialize the tool lineage
version_lineage = [ guid ]
# Get all ancestor guids of the received guid.
current_child_guid = guid
for changeset in hg_util.reversed_upper_bounded_changelog( repo, repository_metadata.changeset_revision ):
ctx = repo.changectx( changeset )
rm = metadata_util.get_repository_metadata_by_changeset_revision( self.app, repository_id, str( ctx ) )
if rm:
parent_guid = rm.tool_versions.get( current_child_guid, None )
if parent_guid:
version_lineage.append( parent_guid )
current_child_guid = parent_guid
# Get all descendant guids of the received guid.
current_parent_guid = guid
for changeset in hg_util.reversed_lower_upper_bounded_changelog( repo,
repository_metadata.changeset_revision,
repository.tip( self.app ) ):
ctx = repo.changectx( changeset )
rm = metadata_util.get_repository_metadata_by_changeset_revision( self.app, repository_id, str( ctx ) )
if rm:
tool_versions = rm.tool_versions
for child_guid, parent_guid in tool_versions.items():
if parent_guid == current_parent_guid:
version_lineage.insert( 0, child_guid )
current_parent_guid = child_guid
break
return version_lineage
def handle_tool_versions( self, tool_version_dicts, tool_shed_repository ):
"""
Using the list of tool_version_dicts retrieved from the Tool Shed (one per changeset
revision up to the currently installed changeset revision), create the parent / child
pairs of tool versions. Each dictionary contains { tool id : parent tool id } pairs.
This function is called only from Galaxy.
"""
context = self.app.install_model.context
for tool_version_dict in tool_version_dicts:
for tool_guid, parent_id in tool_version_dict.items():
tool_version_using_tool_guid = self.get_tool_version( tool_guid )
tool_version_using_parent_id = self.get_tool_version( parent_id )
if not tool_version_using_tool_guid:
tool_version_using_tool_guid = \
self.app.install_model.ToolVersion( tool_id=tool_guid,
tool_shed_repository=tool_shed_repository )
context.add( tool_version_using_tool_guid )
context.flush()
if not tool_version_using_parent_id:
tool_version_using_parent_id = \
self.app.install_model.ToolVersion( tool_id=parent_id,
tool_shed_repository=tool_shed_repository )
context.add( tool_version_using_parent_id )
context.flush()
# Remove existing wrong tool version associations having
# tool_version_using_parent_id as parent or
# tool_version_using_tool_guid as child.
context.query( self.app.install_model.ToolVersionAssociation ) \
.filter( or_( and_( self.app.install_model.ToolVersionAssociation.table.c.parent_id == tool_version_using_parent_id.id,
self.app.install_model.ToolVersionAssociation.table.c.tool_id != tool_version_using_tool_guid.id ),
and_( self.app.install_model.ToolVersionAssociation.table.c.parent_id != tool_version_using_parent_id.id,
self.app.install_model.ToolVersionAssociation.table.c.tool_id == tool_version_using_tool_guid.id ) ) ) \
.delete()
context.flush()
tool_version_association = \
self.get_tool_version_association( tool_version_using_parent_id,
tool_version_using_tool_guid )
if not tool_version_association:
# Associate the two versions as parent / child.
tool_version_association = \
self.app.install_model.ToolVersionAssociation( tool_id=tool_version_using_tool_guid.id,
parent_id=tool_version_using_parent_id.id )
context.add( tool_version_association )
context.flush()
self.app.tool_version_cache = ToolVersionCache(self.app)