/scripts/api/common.py

https://bitbucket.org/chapmanb/galaxy-central/ · Python · 180 lines · 142 code · 17 blank · 21 comment · 43 complexity · cf7cfd7fcf74e05449b71e2506ce8672 MD5 · raw file

  1. import logging
  2. import os
  3. import sys
  4. import urllib2
  5. new_path = [ os.path.join( os.path.dirname( __file__ ), '..', '..', 'lib' ) ]
  6. new_path.extend( sys.path[1:] )
  7. sys.path = new_path
  8. from galaxy import eggs
  9. import pkg_resources
  10. pkg_resources.require( "simplejson" )
  11. import simplejson
  12. pkg_resources.require( "pycrypto" )
  13. from Crypto.Cipher import Blowfish
  14. from Crypto.Util.randpool import RandomPool
  15. from Crypto.Util import number
  16. log = logging.getLogger( __name__ )
  17. def make_url( api_key, url, args=None ):
  18. # Adds the API Key to the URL if it's not already there.
  19. if args is None:
  20. args = []
  21. argsep = '&'
  22. if '?' not in url:
  23. argsep = '?'
  24. if '?key=' not in url and '&key=' not in url:
  25. args.insert( 0, ( 'key', api_key ) )
  26. return url + argsep + '&'.join( [ '='.join( t ) for t in args ] )
  27. def get( api_key, url ):
  28. # Do the actual GET.
  29. url = make_url( api_key, url )
  30. try:
  31. return simplejson.loads( urllib2.urlopen( url ).read() )
  32. except simplejson.decoder.JSONDecodeError, e:
  33. print "URL did not return JSON data"
  34. sys.exit(1)
  35. def post( api_key, url, data ):
  36. # Do the actual POST.
  37. url = make_url( api_key, url )
  38. req = urllib2.Request( url, headers = { 'Content-Type': 'application/json' }, data = simplejson.dumps( data ) )
  39. return simplejson.loads( urllib2.urlopen( req ).read() )
  40. def put( api_key, url, data ):
  41. # Do the actual PUT
  42. url = make_url( api_key, url )
  43. req = urllib2.Request( url, headers = { 'Content-Type': 'application/json' }, data = simplejson.dumps( data ))
  44. req.get_method = lambda: 'PUT'
  45. return simplejson.loads( urllib2.urlopen( req ).read() )
  46. def __del( api_key, url, data ):
  47. # Do the actual DELETE
  48. url = make_url( api_key, url )
  49. req = urllib2.Request( url, headers = { 'Content-Type': 'application/json' }, data = simplejson.dumps( data ))
  50. req.get_method = lambda: 'DELETE'
  51. return simplejson.loads( urllib2.urlopen( req ).read() )
  52. def display( api_key, url, return_formatted=True ):
  53. # Sends an API GET request and acts as a generic formatter for the JSON response.
  54. try:
  55. r = get( api_key, url )
  56. except urllib2.HTTPError, e:
  57. print e
  58. print e.read( 1024 ) # Only return the first 1K of errors.
  59. sys.exit( 1 )
  60. if type( r ) == unicode:
  61. print 'error: %s' % r
  62. return None
  63. if not return_formatted:
  64. return r
  65. elif type( r ) == list:
  66. # Response is a collection as defined in the REST style.
  67. print 'Collection Members'
  68. print '------------------'
  69. for n, i in enumerate(r):
  70. # All collection members should have a name and url in the response.
  71. print '#%d: %s' % (n+1, i.pop( 'url' ) )
  72. if 'name' in i:
  73. print ' name: %s' % i.pop( 'name' )
  74. for k, v in i.items():
  75. print ' %s: %s' % ( k, v )
  76. print ''
  77. print '%d element(s) in collection' % len( r )
  78. elif type( r ) == dict:
  79. # Response is an element as defined in the REST style.
  80. print 'Member Information'
  81. print '------------------'
  82. for k, v in r.items():
  83. print '%s: %s' % ( k, v )
  84. elif type( r ) == str:
  85. print r
  86. else:
  87. print 'response is unknown type: %s' % type( r )
  88. def submit( api_key, url, data, return_formatted=True ):
  89. # Sends an API POST request and acts as a generic formatter for the JSON response.
  90. # 'data' will become the JSON payload read by Galaxy.
  91. try:
  92. r = post( api_key, url, data )
  93. except urllib2.HTTPError, e:
  94. if return_formatted:
  95. print e
  96. print e.read( 1024 )
  97. sys.exit( 1 )
  98. else:
  99. return 'Error. '+ str( e.read( 1024 ) )
  100. if not return_formatted:
  101. return r
  102. print 'Response'
  103. print '--------'
  104. if type( r ) == list:
  105. # Currently the only implemented responses are lists of dicts, because
  106. # submission creates some number of collection elements.
  107. for i in r:
  108. if type( i ) == dict:
  109. if 'url' in i:
  110. print i.pop( 'url' )
  111. else:
  112. print '----'
  113. if 'name' in i:
  114. print ' name: %s' % i.pop( 'name' )
  115. for k, v in i.items():
  116. print ' %s: %s' % ( k, v )
  117. else:
  118. print i
  119. else:
  120. print r
  121. def update( api_key, url, data, return_formatted=True ):
  122. # Sends an API PUT request and acts as a generic formatter for the JSON response.
  123. # 'data' will become the JSON payload read by Galaxy.
  124. try:
  125. r = put( api_key, url, data )
  126. except urllib2.HTTPError, e:
  127. if return_formatted:
  128. print e
  129. print e.read( 1024 )
  130. sys.exit( 1 )
  131. else:
  132. return 'Error. '+ str( e.read( 1024 ) )
  133. if not return_formatted:
  134. return r
  135. print 'Response'
  136. print '--------'
  137. print r
  138. def delete( api_key, url, data, return_formatted=True ):
  139. # Sends an API DELETE request and acts as a generic formatter for the JSON response.
  140. # 'data' will become the JSON payload read by Galaxy.
  141. try:
  142. r = __del( api_key, url, data )
  143. except urllib2.HTTPError, e:
  144. if return_formatted:
  145. print e
  146. print e.read( 1024 )
  147. sys.exit( 1 )
  148. else:
  149. return 'Error. '+ str( e.read( 1024 ) )
  150. if not return_formatted:
  151. return r
  152. print 'Response'
  153. print '--------'
  154. print r
  155. # utility method to encode ID's
  156. def encode_id( config_id_secret, obj_id ):
  157. id_cipher = Blowfish.new( config_id_secret )
  158. # Convert to string
  159. s = str( obj_id )
  160. # Pad to a multiple of 8 with leading "!"
  161. s = ( "!" * ( 8 - len(s) % 8 ) ) + s
  162. # Encrypt
  163. return id_cipher.encrypt( s ).encode( 'hex' )