/lib/galaxy/webapps/community/model/__init__.py

https://bitbucket.org/cistrome/cistrome-harvard/ · Python · 234 lines · 224 code · 3 blank · 7 comment · 4 complexity · 597dbd9fcb0544d0352a3749d0f2ddb0 MD5 · raw file

  1. """
  2. Galaxy Tool Shed data model classes
  3. Naming: try to use class names that have a distinct plural form so that
  4. the relationship cardinalities are obvious (e.g. prefer Dataset to Data)
  5. """
  6. import os.path, os, errno, sys, codecs, operator, logging, tarfile, mimetypes, ConfigParser
  7. from galaxy import util
  8. from galaxy.util.bunch import Bunch
  9. from galaxy.util.hash_util import *
  10. from galaxy.web.form_builder import *
  11. from mercurial import hg, ui
  12. log = logging.getLogger( __name__ )
  13. class User( object ):
  14. def __init__( self, email=None, password=None ):
  15. self.email = email
  16. self.password = password
  17. self.external = False
  18. self.deleted = False
  19. self.purged = False
  20. self.username = None
  21. def set_password_cleartext( self, cleartext ):
  22. """Set 'self.password' to the digest of 'cleartext'."""
  23. self.password = new_secure_hash( text_type=cleartext )
  24. def check_password( self, cleartext ):
  25. """Check if 'cleartext' matches 'self.password' when hashed."""
  26. return self.password == new_secure_hash( text_type=cleartext )
  27. class Group( object ):
  28. def __init__( self, name = None ):
  29. self.name = name
  30. self.deleted = False
  31. class Role( object ):
  32. private_id = None
  33. types = Bunch(
  34. PRIVATE = 'private',
  35. SYSTEM = 'system',
  36. USER = 'user',
  37. ADMIN = 'admin',
  38. SHARING = 'sharing'
  39. )
  40. def __init__( self, name="", description="", type="system", deleted=False ):
  41. self.name = name
  42. self.description = description
  43. self.type = type
  44. self.deleted = deleted
  45. class UserGroupAssociation( object ):
  46. def __init__( self, user, group ):
  47. self.user = user
  48. self.group = group
  49. class UserRoleAssociation( object ):
  50. def __init__( self, user, role ):
  51. self.user = user
  52. self.role = role
  53. class GroupRoleAssociation( object ):
  54. def __init__( self, group, role ):
  55. self.group = group
  56. self.role = role
  57. class GalaxySession( object ):
  58. def __init__( self,
  59. id=None,
  60. user=None,
  61. remote_host=None,
  62. remote_addr=None,
  63. referer=None,
  64. current_history=None,
  65. session_key=None,
  66. is_valid=False,
  67. prev_session_id=None ):
  68. self.id = id
  69. self.user = user
  70. self.remote_host = remote_host
  71. self.remote_addr = remote_addr
  72. self.referer = referer
  73. self.current_history = current_history
  74. self.session_key = session_key
  75. self.is_valid = is_valid
  76. self.prev_session_id = prev_session_id
  77. class Repository( object ):
  78. file_states = Bunch( NORMAL = 'n',
  79. NEEDS_MERGING = 'm',
  80. MARKED_FOR_REMOVAL = 'r',
  81. MARKED_FOR_ADDITION = 'a',
  82. NOT_TRACKED = '?' )
  83. def __init__( self, name=None, description=None, long_description=None, user_id=None, private=False, email_alerts=None, times_downloaded=0 ):
  84. self.name = name or "Unnamed repository"
  85. self.description = description
  86. self.long_description = long_description
  87. self.user_id = user_id
  88. self.private = private
  89. self.email_alerts = email_alerts
  90. self.times_downloaded = times_downloaded
  91. @property
  92. def repo_path( self ):
  93. # Repository locations on disk are defined in the hgweb.config file
  94. # in the Galaxy install directory. An entry looks something like:
  95. # repos/test/mira_assembler = database/community_files/000/repo_123
  96. # TODO: handle this using the mercurial api.
  97. lhs = "repos/%s/%s" % ( self.user.username, self.name )
  98. hgweb_config = "%s/hgweb.config" % os.getcwd()
  99. if not os.path.exists( hgweb_config ):
  100. raise Exception( "Required file hgweb.config does not exist in directory %s" % os.getcwd() )
  101. config = ConfigParser.ConfigParser()
  102. config.read( hgweb_config )
  103. for option in config.options( "paths" ):
  104. if option == lhs:
  105. return config.get( "paths", option )
  106. raise Exception( "Entry for repository %s missing in %s/hgweb.config file." % ( lhs, os.getcwd() ) )
  107. @property
  108. def revision( self ):
  109. repo = hg.repository( ui.ui(), self.repo_path )
  110. tip_ctx = repo.changectx( repo.changelog.tip() )
  111. return "%s:%s" % ( str( tip_ctx.rev() ), str( repo.changectx( repo.changelog.tip() ) ) )
  112. @property
  113. def tip( self ):
  114. repo = hg.repository( ui.ui(), self.repo_path )
  115. return str( repo.changectx( repo.changelog.tip() ) )
  116. @property
  117. def is_new( self ):
  118. repo = hg.repository( ui.ui(), self.repo_path )
  119. tip_ctx = repo.changectx( repo.changelog.tip() )
  120. return tip_ctx.rev() < 0
  121. @property
  122. def allow_push( self ):
  123. repo = hg.repository( ui.ui(), self.repo_path )
  124. return repo.ui.config( 'web', 'allow_push' )
  125. def set_allow_push( self, usernames, remove_auth='' ):
  126. allow_push = util.listify( self.allow_push )
  127. if remove_auth:
  128. allow_push.remove( remove_auth )
  129. else:
  130. for username in util.listify( usernames ):
  131. if username not in allow_push:
  132. allow_push.append( username )
  133. allow_push = '%s\n' % ','.join( allow_push )
  134. repo = hg.repository( ui.ui(), path=self.repo_path )
  135. # Why doesn't the following work?
  136. #repo.ui.setconfig( 'web', 'allow_push', allow_push )
  137. lines = repo.opener( 'hgrc', 'rb' ).readlines()
  138. fp = repo.opener( 'hgrc', 'wb' )
  139. for line in lines:
  140. if line.startswith( 'allow_push' ):
  141. fp.write( 'allow_push = %s' % allow_push )
  142. else:
  143. fp.write( line )
  144. fp.close()
  145. class RepositoryMetadata( object ):
  146. def __init__( self, repository_id=None, changeset_revision=None, metadata=None, malicious=False ):
  147. self.repository_id = repository_id
  148. self.changeset_revision = changeset_revision
  149. self.metadata = metadata or dict()
  150. self.malicious = malicious
  151. class ItemRatingAssociation( object ):
  152. def __init__( self, id=None, user=None, item=None, rating=0, comment='' ):
  153. self.id = id
  154. self.user = user
  155. self.item = item
  156. self.rating = rating
  157. self.comment = comment
  158. def set_item( self, item ):
  159. """ Set association's item. """
  160. pass
  161. class RepositoryRatingAssociation( ItemRatingAssociation ):
  162. def set_item( self, repository ):
  163. self.repository = repository
  164. class Category( object ):
  165. def __init__( self, name=None, description=None, deleted=False ):
  166. self.name = name
  167. self.description = description
  168. self.deleted = deleted
  169. class RepositoryCategoryAssociation( object ):
  170. def __init__( self, repository=None, category=None ):
  171. self.repository = repository
  172. self.category = category
  173. class Tag ( object ):
  174. def __init__( self, id=None, type=None, parent_id=None, name=None ):
  175. self.id = id
  176. self.type = type
  177. self.parent_id = parent_id
  178. self.name = name
  179. def __str__ ( self ):
  180. return "Tag(id=%s, type=%i, parent_id=%s, name=%s)" % ( self.id, self.type, self.parent_id, self.name )
  181. class ItemTagAssociation ( object ):
  182. def __init__( self, id=None, user=None, item_id=None, tag_id=None, user_tname=None, value=None ):
  183. self.id = id
  184. self.user = user
  185. self.item_id = item_id
  186. self.tag_id = tag_id
  187. self.user_tname = user_tname
  188. self.value = None
  189. self.user_value = None
  190. ## ---- Utility methods -------------------------------------------------------
  191. def sort_by_attr( seq, attr ):
  192. """
  193. Sort the sequence of objects by object's attribute
  194. Arguments:
  195. seq - the list or any sequence (including immutable one) of objects to sort.
  196. attr - the name of attribute to sort by
  197. """
  198. # Use the "Schwartzian transform"
  199. # Create the auxiliary list of tuples where every i-th tuple has form
  200. # (seq[i].attr, i, seq[i]) and sort it. The second item of tuple is needed not
  201. # only to provide stable sorting, but mainly to eliminate comparison of objects
  202. # (which can be expensive or prohibited) in case of equal attribute values.
  203. intermed = map( None, map( getattr, seq, ( attr, ) * len( seq ) ), xrange( len( seq ) ), seq )
  204. intermed.sort()
  205. return map( operator.getitem, intermed, ( -1, ) * len( intermed ) )
  206. def directory_hash_id( id ):
  207. s = str( id )
  208. l = len( s )
  209. # Shortcut -- ids 0-999 go under ../000/
  210. if l < 4:
  211. return [ "000" ]
  212. # Pad with zeros until a multiple of three
  213. padded = ( ( ( 3 - len( s ) ) % 3 ) * "0" ) + s
  214. # Drop the last three digits -- 1000 files per directory
  215. padded = padded[:-3]
  216. # Break into chunks of three
  217. return [ padded[i*3:(i+1)*3] for i in range( len( padded ) // 3 ) ]