root/galaxy-central/lib/galaxy/webapps/community/model/__init__.py @ 2

リビジョン 2, 11.2 KB (コミッタ: hatakeyama, 14 年 前)

import galaxy-central

行番号 
1"""
2Galaxy Tool Shed data model classes
3
4Naming: try to use class names that have a distinct plural form so that
5the relationship cardinalities are obvious (e.g. prefer Dataset to Data)
6"""
7import os.path, os, errno, sys, codecs, operator, tempfile, logging, tarfile, mimetypes
8from galaxy.util.bunch import Bunch
9from galaxy.util.hash_util import *
10from galaxy.web.form_builder import *
11log = logging.getLogger( __name__ )
12
13class 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        # Relationships
22        self.tools = []
23    def set_password_cleartext( self, cleartext ):
24        """Set 'self.password' to the digest of 'cleartext'."""
25        self.password = new_secure_hash( text_type=cleartext )
26    def check_password( self, cleartext ):
27        """Check if 'cleartext' matches 'self.password' when hashed."""
28        return self.password == new_secure_hash( text_type=cleartext )
29
30class Group( object ):
31    def __init__( self, name = None ):
32        self.name = name
33        self.deleted = False
34
35class Role( object ):
36    private_id = None
37    types = Bunch(
38        PRIVATE = 'private',
39        SYSTEM = 'system',
40        USER = 'user',
41        ADMIN = 'admin',
42        SHARING = 'sharing'
43    )
44    def __init__( self, name="", description="", type="system", deleted=False ):
45        self.name = name
46        self.description = description
47        self.type = type
48        self.deleted = deleted
49
50class UserGroupAssociation( object ):
51    def __init__( self, user, group ):
52        self.user = user
53        self.group = group
54
55class UserRoleAssociation( object ):
56    def __init__( self, user, role ):
57        self.user = user
58        self.role = role
59
60class GroupRoleAssociation( object ):
61    def __init__( self, group, role ):
62        self.group = group
63        self.role = role
64
65class GalaxySession( object ):
66    def __init__( self,
67                  id=None,
68                  user=None,
69                  remote_host=None,
70                  remote_addr=None,
71                  referer=None,
72                  current_history=None,
73                  session_key=None,
74                  is_valid=False,
75                  prev_session_id=None ):
76        self.id = id
77        self.user = user
78        self.remote_host = remote_host
79        self.remote_addr = remote_addr
80        self.referer = referer
81        self.current_history = current_history
82        self.session_key = session_key
83        self.is_valid = is_valid
84        self.prev_session_id = prev_session_id
85
86class Tool( object ):
87    file_path = '/tmp'
88    states = Bunch( NEW = 'new',
89                    ERROR = 'error',
90                    DELETED = 'deleted',
91                    WAITING = 'waiting',
92                    APPROVED = 'approved',
93                    REJECTED = 'rejected',
94                    ARCHIVED = 'archived' )
95    def __init__( self, guid=None, tool_id=None, name=None, description=None, user_description=None,
96                  category=None, version=None, user_id=None, external_filename=None, suite=False ):
97        self.guid = guid
98        self.tool_id = tool_id
99        self.name = name or "Unnamed tool"
100        self.description = description
101        self.user_description = user_description
102        self.version = version or "1.0.0"
103        self.user_id = user_id
104        self.external_filename = external_filename
105        self.deleted = False
106        self.__extension = None
107        self.suite = suite
108    def get_file_name( self ):
109        if not self.external_filename:
110            assert self.id is not None, "ID must be set before filename used (commit the object)"
111            dir = os.path.join( self.file_path, 'tools', *directory_hash_id( self.id ) )
112            # Create directory if it does not exist
113            if not os.path.exists( dir ):
114                os.makedirs( dir )
115            # Return filename inside hashed directory
116            filename = os.path.join( dir, "tool_%d.dat" % self.id )
117        else:
118            filename = self.external_filename
119        # Make filename absolute
120        return os.path.abspath( filename )
121    def set_file_name( self, filename ):
122        if not filename:
123            self.external_filename = None
124        else:
125            self.external_filename = filename
126    file_name = property( get_file_name, set_file_name )
127    def create_from_datatype( self, datatype_bunch ):
128        # TODO: ensure guid is unique and generate a new one if not.
129        self.guid = datatype_bunch.guid
130        self.tool_id = datatype_bunch.id
131        self.name = datatype_bunch.name
132        self.description = datatype_bunch.description
133        self.version = datatype_bunch.version
134        self.user_id = datatype_bunch.user.id
135        self.suite = datatype_bunch.suite
136    @property
137    def state( self ):
138        latest_event = self.latest_event
139        if latest_event:
140            return latest_event.state
141        return None
142    @property
143    def latest_event( self ):
144        if self.events:
145            events = [ tea.event for tea in self.events ]
146            # Get the last event that occurred ( events mapper is sorted descending )
147            return events[0]
148        return None
149    # Tool states
150    @property
151    def is_new( self ):
152        return self.state == self.states.NEW
153    @property
154    def is_error( self ):
155        return self.state == self.states.ERROR
156    @property
157    def is_deleted( self ):
158        return self.state == self.states.DELETED
159    @property
160    def is_waiting( self ):
161        return self.state == self.states.WAITING
162    @property
163    def is_approved( self ):
164        return self.state == self.states.APPROVED
165    @property
166    def is_rejected( self ):
167        return self.state == self.states.REJECTED
168    @property
169    def is_archived( self ):
170        return self.state == self.states.ARCHIVED
171    def get_state_message( self ):
172        if self.is_suite:
173            label = 'tool suite'
174        else:
175            label = 'tool'
176        if self.is_new:
177            return '<font color="red"><b><i>This is an unsubmitted version of this %s</i></b></font>' % label
178        if self.is_error:
179            return '<font color="red"><b><i>This %s is in an error state</i></b></font>' % label
180        if self.is_deleted:
181            return '<font color="red"><b><i>This is a deleted version of this %s</i></b></font>' % label
182        if self.is_waiting:
183            return '<font color="red"><b><i>This version of this %s is awaiting administrative approval</i></b></font>' % label
184        if self.is_approved:
185            return '<b><i>This is the latest approved version of this %s</i></b>' % label
186        if self.is_rejected:
187            return '<font color="red"><b><i>This version of this %s has been rejected by an administrator</i></b></font>' % label
188        if self.is_archived:
189            return '<font color="red"><b><i>This is an archived version of this %s</i></b></font>' % label
190    @property
191    def extension( self ):
192        # if instantiated via a query, this unmapped property won't exist
193        if '_Tool__extension' not in dir( self ):
194            self.__extension = None
195        if self.__extension is None:
196            head = open( self.file_name, 'rb' ).read( 4 )
197            try:
198                assert head[:3] == 'BZh'
199                assert int( head[-1] ) in range( 0, 10 )
200                self.__extension = 'tar.bz2'
201            except AssertionError:
202                pass
203        if self.__extension is None:
204            try:
205                assert head[:2] == '\037\213'
206                self.__extension = 'tar.gz'
207            except:
208                pass
209        if self.__extension is None:
210            self.__extension = 'tar'
211        return self.__extension
212    @property
213    def is_suite( self ):
214        return self.suite
215    @property
216    def label( self ):
217        if self.is_suite:
218            return 'tool suite'
219        else:
220            return 'tool'
221    @property
222    def download_file_name( self ):
223        return '%s_%s.%s' % ( self.tool_id, self.version, self.extension )
224    @property
225    def mimetype( self ):
226        return mimetypes.guess_type( self.download_file_name )[0]
227
228class Event( object ):
229    def __init__( self, state=None, comment='' ):
230        self.state = state
231        self.comment = comment
232
233class ToolEventAssociation( object ):
234    def __init__( self, tool=None, event=None ):
235        self.tool = tool
236        self.event = event
237
238class ItemRatingAssociation( object ):
239    def __init__( self, id=None, user=None, item=None, rating=0, comment='' ):
240        self.id = id
241        self.user = user
242        self.item = item
243        self.rating = rating
244        self.comment = comment
245    def set_item( self, item ):
246        """ Set association's item. """
247        pass
248
249class ToolRatingAssociation( ItemRatingAssociation ):
250    def set_item( self, tool ):
251        self.tool = tool
252
253class Category( object ):
254    def __init__( self, name=None, description=None, deleted=False ):
255        self.name = name
256        self.description = description
257        self.deleted = deleted
258
259class ToolCategoryAssociation( object ):
260    def __init__( self, tool=None, category=None ):
261        self.tool = tool
262        self.category = category
263
264class Tag ( object ):
265    def __init__( self, id=None, type=None, parent_id=None, name=None ):
266        self.id = id
267        self.type = type
268        self.parent_id = parent_id
269        self.name = name
270    def __str__ ( self ):
271        return "Tag(id=%s, type=%i, parent_id=%s, name=%s)" %  ( self.id, self.type, self.parent_id, self.name )
272
273class ItemTagAssociation ( object ):
274    def __init__( self, id=None, user=None, item_id=None, tag_id=None, user_tname=None, value=None ):
275        self.id = id
276        self.user = user
277        self.item_id = item_id
278        self.tag_id = tag_id
279        self.user_tname = user_tname
280        self.value = None
281        self.user_value = None
282       
283class ToolTagAssociation ( ItemTagAssociation ):
284    pass
285
286class ToolAnnotationAssociation( object ):
287    pass
288
289## ---- Utility methods -------------------------------------------------------
290def sort_by_attr( seq, attr ):
291    """
292    Sort the sequence of objects by object's attribute
293    Arguments:
294    seq  - the list or any sequence (including immutable one) of objects to sort.
295    attr - the name of attribute to sort by
296    """
297    # Use the "Schwartzian transform"
298    # Create the auxiliary list of tuples where every i-th tuple has form
299    # (seq[i].attr, i, seq[i]) and sort it. The second item of tuple is needed not
300    # only to provide stable sorting, but mainly to eliminate comparison of objects
301    # (which can be expensive or prohibited) in case of equal attribute values.
302    intermed = map( None, map( getattr, seq, ( attr, ) * len( seq ) ), xrange( len( seq ) ), seq )
303    intermed.sort()
304    return map( operator.getitem, intermed, ( -1, ) * len( intermed ) )
305def directory_hash_id( id ):
306    s = str( id )
307    l = len( s )
308    # Shortcut -- ids 0-999 go under ../000/
309    if l < 4:
310        return [ "000" ]
311    # Pad with zeros until a multiple of three
312    padded = ( ( ( 3 - len( s ) ) % 3 ) * "0" ) + s
313    # Drop the last three digits -- 1000 files per directory
314    padded = padded[:-3]
315    # Break into chunks of three
316    return [ padded[i*3:(i+1)*3] for i in range( len( padded ) // 3 ) ]
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。