mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
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:
@@ -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]
|
||||
|
||||
@@ -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' )
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user