comparison webapollo.py @ 5:7610987e0c48 draft

planemo upload for repository https://github.com/TAMU-CPT/galaxy-webapollo commit 29795b77c0d5c7894219b018a92c5ee7818096c3
author eric-rasche
date Wed, 01 Mar 2017 22:39:58 -0500
parents d4ae83dedb14
children f9a6e151b3b4
comparison
equal deleted inserted replaced
4:23ead6905145 5:7610987e0c48
1 import requests 1 import requests
2 import json 2 import json
3 import os 3 import os
4 import collections 4 import collections
5 import StringIO 5 try:
6 import StringIO as io
7 except:
8 import io
6 import logging 9 import logging
10 import time
11 import argparse
12 from abc import abstractmethod
7 from BCBio import GFF 13 from BCBio import GFF
8 from Bio import SeqIO 14 from Bio import SeqIO
9 logging.getLogger("requests").setLevel(logging.CRITICAL) 15 logging.getLogger("requests").setLevel(logging.CRITICAL)
10 log = logging.getLogger() 16 log = logging.getLogger()
11 17
12 18
19 #############################################
20 ###### BEGIN IMPORT OF CACHING LIBRARY ######
21 #############################################
22 # This code is licensed under the MIT #
23 # License and is a copy of code publicly #
24 # available in rev. #
25 # e27332bc82f4e327aedaec17c9b656ae719322ed #
26 # of https://github.com/tkem/cachetools/ #
27 #############################################
28 class DefaultMapping(collections.MutableMapping):
29
30 __slots__ = ()
31
32 @abstractmethod
33 def __contains__(self, key): # pragma: nocover
34 return False
35
36 @abstractmethod
37 def __getitem__(self, key): # pragma: nocover
38 if hasattr(self.__class__, '__missing__'):
39 return self.__class__.__missing__(self, key)
40 else:
41 raise KeyError(key)
42
43 def get(self, key, default=None):
44 if key in self:
45 return self[key]
46 else:
47 return default
48
49 __marker = object()
50
51 def pop(self, key, default=__marker):
52 if key in self:
53 value = self[key]
54 del self[key]
55 elif default is self.__marker:
56 raise KeyError(key)
57 else:
58 value = default
59 return value
60
61 def setdefault(self, key, default=None):
62 if key in self:
63 value = self[key]
64 else:
65 self[key] = value = default
66 return value
67
68 DefaultMapping.register(dict)
69
70
71 class _DefaultSize(object):
72 def __getitem__(self, _):
73 return 1
74
75 def __setitem__(self, _, value):
76 assert value == 1
77
78 def pop(self, _):
79 return 1
80
81
82 class Cache(DefaultMapping):
83 """Mutable mapping to serve as a simple cache or cache base class."""
84
85 __size = _DefaultSize()
86
87 def __init__(self, maxsize, missing=None, getsizeof=None):
88 if missing:
89 self.__missing = missing
90 if getsizeof:
91 self.__getsizeof = getsizeof
92 self.__size = dict()
93 self.__data = dict()
94 self.__currsize = 0
95 self.__maxsize = maxsize
96
97 def __repr__(self):
98 return '%s(%r, maxsize=%r, currsize=%r)' % (
99 self.__class__.__name__,
100 list(self.__data.items()),
101 self.__maxsize,
102 self.__currsize,
103 )
104
105 def __getitem__(self, key):
106 try:
107 return self.__data[key]
108 except KeyError:
109 return self.__missing__(key)
110
111 def __setitem__(self, key, value):
112 maxsize = self.__maxsize
113 size = self.getsizeof(value)
114 if size > maxsize:
115 raise ValueError('value too large')
116 if key not in self.__data or self.__size[key] < size:
117 while self.__currsize + size > maxsize:
118 self.popitem()
119 if key in self.__data:
120 diffsize = size - self.__size[key]
121 else:
122 diffsize = size
123 self.__data[key] = value
124 self.__size[key] = size
125 self.__currsize += diffsize
126
127 def __delitem__(self, key):
128 size = self.__size.pop(key)
129 del self.__data[key]
130 self.__currsize -= size
131
132 def __contains__(self, key):
133 return key in self.__data
134
135 def __missing__(self, key):
136 value = self.__missing(key)
137 try:
138 self.__setitem__(key, value)
139 except ValueError:
140 pass # value too large
141 return value
142
143 def __iter__(self):
144 return iter(self.__data)
145
146 def __len__(self):
147 return len(self.__data)
148
149 @staticmethod
150 def __getsizeof(value):
151 return 1
152
153 @staticmethod
154 def __missing(key):
155 raise KeyError(key)
156
157 @property
158 def maxsize(self):
159 """The maximum size of the cache."""
160 return self.__maxsize
161
162 @property
163 def currsize(self):
164 """The current size of the cache."""
165 return self.__currsize
166
167 def getsizeof(self, value):
168 """Return the size of a cache element's value."""
169 return self.__getsizeof(value)
170
171
172 class _Link(object):
173
174 __slots__ = ('key', 'expire', 'next', 'prev')
175
176 def __init__(self, key=None, expire=None):
177 self.key = key
178 self.expire = expire
179
180 def __reduce__(self):
181 return _Link, (self.key, self.expire)
182
183 def unlink(self):
184 next = self.next
185 prev = self.prev
186 prev.next = next
187 next.prev = prev
188
189
190 class _Timer(object):
191
192 def __init__(self, timer):
193 self.__timer = timer
194 self.__nesting = 0
195
196 def __call__(self):
197 if self.__nesting == 0:
198 return self.__timer()
199 else:
200 return self.__time
201
202 def __enter__(self):
203 if self.__nesting == 0:
204 self.__time = time = self.__timer()
205 else:
206 time = self.__time
207 self.__nesting += 1
208 return time
209
210 def __exit__(self, *exc):
211 self.__nesting -= 1
212
213 def __reduce__(self):
214 return _Timer, (self.__timer,)
215
216 def __getattr__(self, name):
217 return getattr(self.__timer, name)
218
219
220 class TTLCache(Cache):
221 """LRU Cache implementation with per-item time-to-live (TTL) value."""
222
223 def __init__(self, maxsize, ttl, timer=time.time, missing=None,
224 getsizeof=None):
225 Cache.__init__(self, maxsize, missing, getsizeof)
226 self.__root = root = _Link()
227 root.prev = root.next = root
228 self.__links = collections.OrderedDict()
229 self.__timer = _Timer(timer)
230 self.__ttl = ttl
231
232 def __contains__(self, key):
233 try:
234 link = self.__links[key] # no reordering
235 except KeyError:
236 return False
237 else:
238 return not (link.expire < self.__timer())
239
240 def __getitem__(self, key, cache_getitem=Cache.__getitem__):
241 try:
242 link = self.__getlink(key)
243 except KeyError:
244 expired = False
245 else:
246 expired = link.expire < self.__timer()
247 if expired:
248 return self.__missing__(key)
249 else:
250 return cache_getitem(self, key)
251
252 def __setitem__(self, key, value, cache_setitem=Cache.__setitem__):
253 with self.__timer as time:
254 self.expire(time)
255 cache_setitem(self, key, value)
256 try:
257 link = self.__getlink(key)
258 except KeyError:
259 self.__links[key] = link = _Link(key)
260 else:
261 link.unlink()
262 link.expire = time + self.__ttl
263 link.next = root = self.__root
264 link.prev = prev = root.prev
265 prev.next = root.prev = link
266
267 def __delitem__(self, key, cache_delitem=Cache.__delitem__):
268 cache_delitem(self, key)
269 link = self.__links.pop(key)
270 link.unlink()
271 if link.expire < self.__timer():
272 raise KeyError(key)
273
274 def __iter__(self):
275 root = self.__root
276 curr = root.next
277 while curr is not root:
278 # "freeze" time for iterator access
279 with self.__timer as time:
280 if not (curr.expire < time):
281 yield curr.key
282 curr = curr.next
283
284 def __len__(self):
285 root = self.__root
286 curr = root.next
287 time = self.__timer()
288 count = len(self.__links)
289 while curr is not root and curr.expire < time:
290 count -= 1
291 curr = curr.next
292 return count
293
294 def __setstate__(self, state):
295 self.__dict__.update(state)
296 root = self.__root
297 root.prev = root.next = root
298 for link in sorted(self.__links.values(), key=lambda obj: obj.expire):
299 link.next = root
300 link.prev = prev = root.prev
301 prev.next = root.prev = link
302 self.expire(self.__timer())
303
304 def __repr__(self, cache_repr=Cache.__repr__):
305 with self.__timer as time:
306 self.expire(time)
307 return cache_repr(self)
308
309 @property
310 def currsize(self):
311 with self.__timer as time:
312 self.expire(time)
313 return super(TTLCache, self).currsize
314
315 @property
316 def timer(self):
317 """The timer function used by the cache."""
318 return self.__timer
319
320 @property
321 def ttl(self):
322 """The time-to-live value of the cache's items."""
323 return self.__ttl
324
325 def expire(self, time=None):
326 """Remove expired items from the cache."""
327 if time is None:
328 time = self.__timer()
329 root = self.__root
330 curr = root.next
331 links = self.__links
332 cache_delitem = Cache.__delitem__
333 while curr is not root and curr.expire < time:
334 cache_delitem(self, curr.key)
335 del links[curr.key]
336 next = curr.next
337 curr.unlink()
338 curr = next
339
340 def clear(self):
341 with self.__timer as time:
342 self.expire(time)
343 Cache.clear(self)
344
345 def get(self, *args, **kwargs):
346 with self.__timer:
347 return Cache.get(self, *args, **kwargs)
348
349 def pop(self, *args, **kwargs):
350 with self.__timer:
351 return Cache.pop(self, *args, **kwargs)
352
353 def setdefault(self, *args, **kwargs):
354 with self.__timer:
355 return Cache.setdefault(self, *args, **kwargs)
356
357 def popitem(self):
358 """Remove and return the `(key, value)` pair least recently used that
359 has not already expired.
360
361 """
362 with self.__timer as time:
363 self.expire(time)
364 try:
365 key = next(iter(self.__links))
366 except StopIteration:
367 raise KeyError('%s is empty' % self.__class__.__name__)
368 else:
369 return (key, self.pop(key))
370
371 if hasattr(collections.OrderedDict, 'move_to_end'):
372 def __getlink(self, key):
373 value = self.__links[key]
374 self.__links.move_to_end(key)
375 return value
376 else:
377 def __getlink(self, key):
378 value = self.__links.pop(key)
379 self.__links[key] = value
380 return value
381
382
383 #############################################
384 ###### END IMPORT OF CACHING LIBRARY ######
385 #############################################
386
387 cache = TTLCache(
388 100, # Up to 100 items
389 5 * 60 # 5 minute cache life
390 )
391 userCache = TTLCache(
392 2, # Up to 2 items
393 60 # 1 minute cache life
394 )
395
396 class UnknownUserException(Exception):
397 pass
398
13 def WAAuth(parser): 399 def WAAuth(parser):
14 parser.add_argument('apollo', help='Complete Apollo URL') 400 parser.add_argument('apollo', help='Complete Apollo URL')
15 parser.add_argument('username', help='WA Username') 401 parser.add_argument('username', help='WA Username')
16 parser.add_argument('password', help='WA Password') 402 parser.add_argument('password', help='WA Password')
17 parser.add_argument('--remote_user', default='', help='If set, ignore password, set the header with the name supplied to this argument to the value of email')
18 403
19 404
20 def OrgOrGuess(parser): 405 def OrgOrGuess(parser):
21 parser.add_argument('--org_json', type=file, help='Apollo JSON output, source for common name') 406 parser.add_argument('--org_json', type=argparse.FileType("r"), help='Apollo JSON output, source for common name')
22 parser.add_argument('--org_raw', help='Common Name') 407 parser.add_argument('--org_raw', help='Common Name')
23 parser.add_argument('--org_id', help='Organism ID') 408 parser.add_argument('--org_id', help='Organism ID')
24 409
25 410
26 def CnOrGuess(parser): 411 def CnOrGuess(parser):
27 OrgOrGuess(parser) 412 OrgOrGuess(parser)
28 parser.add_argument('--seq_fasta', type=file, help='Fasta file, IDs used as sequence sources') 413 parser.add_argument('--seq_fasta', type=argparse.FileType("r"), help='Fasta file, IDs used as sequence sources')
29 parser.add_argument('--seq_raw', nargs='*', help='Sequence Names') 414 parser.add_argument('--seq_raw', nargs='*', help='Sequence Names')
30 415
31 416
32 def GuessOrg(args, wa): 417 def GuessOrg(args, wa):
33 if args.org_json: 418 if args.org_json:
61 return org, seqs 446 return org, seqs
62 447
63 448
64 def AssertUser(user_list): 449 def AssertUser(user_list):
65 if len(user_list) == 0: 450 if len(user_list) == 0:
66 raise Exception("Unknown user. Please register first") 451 raise UnknownUserException()
452 elif len(user_list) == 1:
453 return user_list[0]
67 else: 454 else:
68 return user_list[0] 455 raise Exception("Too many users!")
69 456
70 457
71 def AssertAdmin(user): 458 def AssertAdmin(user):
72 if user.role == 'ADMIN': 459 if user.role == 'ADMIN':
73 return True 460 return True
79 466
80 def __init__(self, url, username, password): 467 def __init__(self, url, username, password):
81 self.apollo_url = url 468 self.apollo_url = url
82 self.username = username 469 self.username = username
83 self.password = password 470 self.password = password
471 # TODO: Remove after apollo 2.0.6.
472 self.clientToken = time.time()
84 473
85 self.annotations = AnnotationsClient(self) 474 self.annotations = AnnotationsClient(self)
86 self.groups = GroupsClient(self) 475 self.groups = GroupsClient(self)
87 self.io = IOClient(self) 476 self.io = IOClient(self)
88 self.organisms = OrganismsClient(self) 477 self.organisms = OrganismsClient(self)
91 self.bio = RemoteRecord(self) 480 self.bio = RemoteRecord(self)
92 481
93 def __str__(self): 482 def __str__(self):
94 return '<WebApolloInstance at %s>' % self.apollo_url 483 return '<WebApolloInstance at %s>' % self.apollo_url
95 484
485 def requireUser(self, email):
486 cacheKey = 'user-list'
487 try:
488 # Get the cached value
489 data = userCache[cacheKey]
490 except KeyError:
491 # If we hit a key error above, indicating that
492 # we couldn't find the key, we'll simply re-request
493 # the data
494 data = self.users.loadUsers()
495 userCache[cacheKey] = data
496
497 return AssertUser([x for x in data if x.username == email])
498
96 499
97 class GroupObj(object): 500 class GroupObj(object):
98 def __init__(self, **kwargs): 501 def __init__(self, **kwargs):
99 self.name = kwargs['name'] 502 self.name = kwargs['name']
100 503
160 } 563 }
161 564
162 data.update({ 565 data.update({
163 'username': self._wa.username, 566 'username': self._wa.username,
164 'password': self._wa.password, 567 'password': self._wa.password,
568 'clientToken': self._wa.clientToken,
165 }) 569 })
166 570
167 r = requests.post(url, data=json.dumps(data), headers=headers, 571 r = requests.post(url, data=json.dumps(data), headers=headers,
168 verify=self.__verify, params=post_params, allow_redirects=False, **self._requestArgs) 572 verify=self.__verify, params=post_params, allow_redirects=False, **self._requestArgs)
169 573
264 'features': symbols, 668 'features': symbols,
265 } 669 }
266 data.update(self._extra_data) 670 data.update(self._extra_data)
267 return self.request('setSymbol', data) 671 return self.request('setSymbol', data)
268 672
269 def getComments(self, features): 673 def getComments(self, feature_id):
270 data = { 674 data = {
271 'features': features, 675 'features': [{'uniquename': feature_id}],
676 }
677 data = self._update_data(data)
678 return self.request('getComments', data)
679
680 def addComments(self, feature_id, comment):
681 #TODO: This is probably not great and will delete comments, if I had to guess...
682 data = {
683 'features': [
684 {
685 'uniquename': feature_id,
686 'comments': [comment]
687 }
688 ],
272 } 689 }
273 data = self._update_data(data) 690 data = self._update_data(data)
274 return self.request('getComments', data) 691 return self.request('getComments', data)
275 692
276 def addAttribute(self, features): 693 def addAttribute(self, features):
295 712
296 def addFeature(self, feature, trustme=False): 713 def addFeature(self, feature, trustme=False):
297 if not trustme: 714 if not trustme:
298 raise NotImplementedError("Waiting on better docs from project. If you know what you are doing, pass trustme=True to this function.") 715 raise NotImplementedError("Waiting on better docs from project. If you know what you are doing, pass trustme=True to this function.")
299 716
300 data = {} 717 data = {
301 data.update(feature) 718 'features': feature,
719 }
302 data = self._update_data(data) 720 data = self._update_data(data)
303 return self.request('addFeature', data) 721 return self.request('addFeature', data)
304 722
305 def addTranscript(self, transcript, trustme=False): 723 def addTranscript(self, transcript, trustme=False):
306 if not trustme: 724 if not trustme:
463 'id': group.groupId, 881 'id': group.groupId,
464 'name': group.name, 882 'name': group.name,
465 } 883 }
466 return self.request('getOrganismPermissionsForGroup', data) 884 return self.request('getOrganismPermissionsForGroup', data)
467 885
886 def loadGroup(self, group):
887 return self.loadGroupById(group.groupId)
888
889 def loadGroupById(self, groupId):
890 res = self.request('loadGroups', {'groupId': groupId})
891 if isinstance(res, list):
892 # We can only match one, right?
893 return GroupObj(**res[0])
894 else:
895 return res
896
897 def loadGroupByName(self, name):
898 res = self.request('loadGroups', {'name': name})
899 if isinstance(res, list):
900 # We can only match one, right?
901 return GroupObj(**res[0])
902 else:
903 return res
904
468 def loadGroups(self, group=None): 905 def loadGroups(self, group=None):
469 data = {} 906 res = self.request('loadGroups', {})
907 data = [GroupObj(**x) for x in res]
470 if group is not None: 908 if group is not None:
471 data['groupId'] = group.groupId 909 data = [x for x in data if x.name == group]
472 910
473 return self.request('loadGroups', data) 911 return data
474 912
475 def deleteGroup(self, group): 913 def deleteGroup(self, group):
476 data = { 914 data = {
477 'id': group.groupId, 915 'id': group.groupId,
478 'name': group.name, 916 'name': group.name,
491 def updateOrganismPermission(self, group, organismName, 929 def updateOrganismPermission(self, group, organismName,
492 administrate=False, write=False, read=False, 930 administrate=False, write=False, read=False,
493 export=False): 931 export=False):
494 data = { 932 data = {
495 'groupId': group.groupId, 933 'groupId': group.groupId,
496 'name': organismName, 934 'organism': organismName,
497 'administrate': administrate, 935 'ADMINISTRATE': administrate,
498 'write': write, 936 'WRITE': write,
499 'export': export, 937 'EXPORT': export,
500 'read': read, 938 'READ': read,
501 } 939 }
502 return self.request('updateOrganismPermission', data) 940 return self.request('updateOrganismPermission', data)
503 941
504 def updateMembership(self, group, users): 942 def updateMembership(self, group, users):
505 data = { 943 data = {
704 1142
705 def ParseRecord(self, cn): 1143 def ParseRecord(self, cn):
706 org = self._wa.organisms.findOrganismByCn(cn) 1144 org = self._wa.organisms.findOrganismByCn(cn)
707 self._wa.annotations.setSequence(org['commonName'], org['id']) 1145 self._wa.annotations.setSequence(org['commonName'], org['id'])
708 1146
709 data = StringIO.StringIO(self._wa.io.write( 1147 data = io.StringIO(self._wa.io.write(
710 exportType='GFF3', 1148 exportType='GFF3',
711 seqType='genomic', 1149 seqType='genomic',
712 exportAllSequences=False, 1150 exportAllSequences=False,
713 exportGff3Fasta=True, 1151 exportGff3Fasta=True,
714 output="text", 1152 output="text",
814 1252
815 1253
816 def featuresToFeatureSchema(features): 1254 def featuresToFeatureSchema(features):
817 compiled = [] 1255 compiled = []
818 for feature in features: 1256 for feature in features:
819 if feature.type != 'gene': 1257 # if feature.type != 'gene':
820 log.warn("Not able to handle %s features just yet...", feature.type) 1258 # log.warn("Not able to handle %s features just yet...", feature.type)
821 continue 1259 # continue
822 1260
823 for x in _yieldFeatData([feature]): 1261 for x in _yieldFeatData([feature]):
824 compiled.append(x) 1262 compiled.append(x)
825 return compiled 1263 return compiled
826 1264
832 if 'WRITE' in x['permissions'] or 1270 if 'WRITE' in x['permissions'] or
833 'READ' in x['permissions'] or 1271 'READ' in x['permissions'] or
834 'ADMINISTRATE' in x['permissions'] or 1272 'ADMINISTRATE' in x['permissions'] or
835 user.role == 'ADMIN' 1273 user.role == 'ADMIN'
836 } 1274 }
1275
1276 if 'error' in orgs:
1277 raise Exception("Error received from Apollo server: \"%s\"" % orgs['error'])
1278
837 return [ 1279 return [
838 (org['commonName'], org['id'], False) 1280 (org['commonName'], org['id'], False)
839 for org in sorted(orgs, key=lambda x: x['commonName']) 1281 for org in sorted(orgs, key=lambda x: x['commonName'])
840 if org['commonName'] in permissionMap 1282 if org['commonName'] in permissionMap
841 ] 1283 ]
842 1284
843 1285
1286 def galaxy_list_groups(trans, *args, **kwargs):
1287 email = trans.get_user().email
1288 wa = WebApolloInstance(
1289 os.environ['GALAXY_WEBAPOLLO_URL'],
1290 os.environ['GALAXY_WEBAPOLLO_USER'],
1291 os.environ['GALAXY_WEBAPOLLO_PASSWORD']
1292 )
1293 # Assert that the email exists in apollo
1294 try:
1295 gx_user = wa.requireUser(email)
1296 except UnknownUserException:
1297 return []
1298
1299 # Key for cached data
1300 cacheKey = 'groups-' + email
1301 # We don't want to trust "if key in cache" because between asking and fetch
1302 # it might through key error.
1303 if cacheKey not in cache:
1304 # However if it ISN'T there, we know we're safe to fetch + put in
1305 # there.
1306 data = _galaxy_list_groups(wa, gx_user, *args, **kwargs)
1307 cache[cacheKey] = data
1308 return data
1309 try:
1310 # The cache key may or may not be in the cache at this point, it
1311 # /likely/ is. However we take no chances that it wasn't evicted between
1312 # when we checked above and now, so we reference the object from the
1313 # cache in preparation to return.
1314 data = cache[cacheKey]
1315 return data
1316 except KeyError:
1317 # If access fails due to eviction, we will fail over and can ensure that
1318 # data is inserted.
1319 data = _galaxy_list_groups(wa, gx_user, *args, **kwargs)
1320 cache[cacheKey] = data
1321 return data
1322
1323
1324 def _galaxy_list_groups(wa, gx_user, *args, **kwargs):
1325 # Fetch the groups.
1326 group_data = []
1327 for group in wa.groups.loadGroups():
1328 # Reformat
1329 group_data.append((group.name, group.groupId, False))
1330 return group_data
1331
1332
844 def galaxy_list_orgs(trans, *args, **kwargs): 1333 def galaxy_list_orgs(trans, *args, **kwargs):
845 email = trans.get_user().email 1334 email = trans.get_user().email
846
847 wa = WebApolloInstance( 1335 wa = WebApolloInstance(
848 os.environ.get('GALAXY_WEBAPOLLO_URL', 'https://example.com'), 1336 os.environ['GALAXY_WEBAPOLLO_URL'],
849 os.environ.get('GALAXY_WEBAPOLLO_USER', 'admin'), 1337 os.environ['GALAXY_WEBAPOLLO_USER'],
850 os.environ.get('GALAXY_WEBAPOLLO_PASSWORD', 'admin') 1338 os.environ['GALAXY_WEBAPOLLO_PASSWORD']
851 ) 1339 )
852 1340 try:
853 gx_user = AssertUser(wa.users.loadUsers(email=email)) 1341 gx_user = wa.requireUser(email)
1342 except UnknownUserException:
1343 return []
1344
1345 # Key for cached data
1346 cacheKey = 'orgs-' + email
1347 if cacheKey not in cache:
1348 data = _galaxy_list_orgs(wa, gx_user, *args, **kwargs)
1349 cache[cacheKey] = data
1350 return data
1351 try:
1352 data = cache[cacheKey]
1353 return data
1354 except KeyError:
1355 data = _galaxy_list_orgs(wa, gx_user, *args, **kwargs)
1356 cache[cacheKey] = data
1357 return data
1358
1359
1360 def _galaxy_list_orgs(wa, gx_user, *args, **kwargs):
1361 # Fetch all organisms
854 all_orgs = wa.organisms.findAllOrganisms() 1362 all_orgs = wa.organisms.findAllOrganisms()
855 1363 # Figure out which are accessible to the user
856 orgs = accessible_organisms(gx_user, all_orgs) 1364 orgs = accessible_organisms(gx_user, all_orgs)
857 1365 # Return org list
858 return orgs 1366 return orgs
1367
1368 ## This is all for implementing the command line interface for testing.
1369
1370 class obj(object):
1371 pass
1372
1373
1374 class fakeTrans(object):
1375
1376 def __init__(self, username):
1377 self.un = username
1378
1379 def get_user(self):
1380 o = obj()
1381 o.email = self.un
1382 return o
1383
1384 if __name__ == '__main__':
1385 parser = argparse.ArgumentParser(description='Test access to apollo server')
1386 parser.add_argument('email', help='Email of user to test')
1387 parser.add_argument('--action', choices=['org', 'group'], default='org', help='Data set to test, fetch a list of groups or users known to the requesting user.')
1388 args = parser.parse_args()
1389
1390 trans = fakeTrans(args.email)
1391 if args.action == 'org':
1392 for f in galaxy_list_orgs(trans):
1393 print(f)
1394 else:
1395 for f in galaxy_list_groups(trans):
1396 print(f)