Implement a detailed break down of data table fields via API.

Originally this approach was laid out by Kyle Ellrott in this pull request (https://bitbucket.org/galaxy/galaxy-central/pull-request/531/add-downloads-to-tool-data-api/diff). The changes to galaxy.tools.data are entirely his contribution, I only reworked the API and endpoint slightly and did some stylistic fixes and refactoring.
This commit is contained in:
John Chilton
2014-12-15 00:20:35 -05:00
parent 8e285594d7
commit 4262ff7673
4 changed files with 88 additions and 0 deletions
+63
View File
@@ -9,7 +9,11 @@ to modify the tool configurations.
import logging
import os
import os.path
import re
import string
import hashlib
from glob import glob
from galaxy import util
from galaxy.util.odict import odict
@@ -340,6 +344,13 @@ class TabularToolDataTable( ToolDataTable, Dictifiable ):
def get_fields( self ):
return self.data
def get_field(self, value):
rval = None
for i in self.get_named_fields_list():
if i['value'] == value:
rval = TabularToolDataField(i)
return rval
def get_named_fields_list( self ):
rval = []
named_colums = self.get_column_name_list()
@@ -580,6 +591,58 @@ class TabularToolDataTable( ToolDataTable, Dictifiable ):
return rval
class TabularToolDataField(Dictifiable, object):
dict_collection_visible_keys = []
def __init__(self, data):
self.data = data
def __getitem__(self, key):
return self.data[key]
def get_base_path(self):
return os.path.normpath(os.path.abspath( self.data['path'] ))
def get_base_dir(self):
path = self.get_base_path()
if not os.path.isdir(path):
path = os.path.dirname(path)
return path
def clean_base_dir(self, path):
return re.sub( "^" + self.get_base_dir() + r"/*", "", path )
def get_files(self):
return glob( self.get_base_path() + "*" )
def get_filesize_map(self, rm_base_dir=False):
out = {}
for path in self.get_files():
if rm_base_dir:
out[self.clean_base_dir(path)] = os.path.getsize(path)
else:
out[path] = os.path.getsize(path)
return out
def get_fingerprint(self):
sha1 = hashlib.sha1()
fmap = self.get_filesize_map(True)
for k in sorted(fmap.keys()):
sha1.update(k)
sha1.update(str(fmap[k]))
return sha1.hexdigest()
def to_dict(self):
rval = super(TabularToolDataField, self).to_dict()
rval['name'] = self.data['value']
rval['fields'] = self.data
rval['base_dir'] = self.get_base_dir(),
rval['files'] = self.get_filesize_map(True)
rval['fingerprint'] = self.get_fingerprint()
return rval
def expand_here_template(content, here=None):
if here and content:
content = string.Template(content).safe_substitute( { "__HERE__": here })
@@ -64,6 +64,22 @@ class ToolData( BaseAPIController ):
return data_table.remove_entry(split_values)
@web.require_admin
@expose_api
def show_field( self, trans, id, value, **kwds ):
"""
GET /api/tool_data/<id>/fields/<value>
Get information about a partiular field in a tool_data table
"""
return self._data_table_field( id, value ).to_dict()
def _data_table_field( self, id, value ):
out = self._data_table(id).get_field(value)
if out is None:
raise exceptions.ObjectNotFound("No such field %s in data table %s." % (value, id))
return out
def _data_table( self, id ):
try:
return self._data_tables[id]
+1
View File
@@ -171,6 +171,7 @@ def populate_api_routes( webapp, app ):
webapp.mapper.resource( 'dataset', 'datasets', path_prefix='/api' )
webapp.mapper.resource( 'tool_data', 'tool_data', path_prefix='/api' )
webapp.mapper.connect( '/api/tool_data/{id:.+?}/fields/{value:.+?}', action='show_field', controller="tool_data" )
webapp.mapper.resource( 'dataset_collection', 'dataset_collections', path_prefix='/api/')
webapp.mapper.resource( 'sample', 'samples', path_prefix='/api' )
webapp.mapper.resource( 'request', 'requests', path_prefix='/api' )
+8
View File
@@ -28,3 +28,11 @@ class ToolDataApiTestCase( api.ApiTestCase ):
assert first_entry[0] == "data1"
assert first_entry[1] == "data1name"
assert first_entry[2].endswith("test/functional/tool-data/data1/entry.txt")
def test_show_field(self):
show_field_response = self._get( "tool_data/testalpha/fields/data1", admin=True )
self._assert_status_code_is( show_field_response, 200 )
field = show_field_response.json()
self._assert_has_keys( field, "files", "name", "fields", "fingerprint", "base_dir" )
files = field[ "files" ]
assert len( files ) == 2