Skip to content

Commit 2bc9991

Browse files
authored
Merge pull request #14 from galaxy-genome-annotation/2.4
Various updates
2 parents 9899006 + 44b9dee commit 2bc9991

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+641
-462
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ python:
55
script:
66
- pip install -U pip setuptools
77
- pip install -U flake8
8-
- flake8 apollo --ignore=E501 --exclude=arrow/commands/,scripts/
8+
- flake8 apollo --ignore=E501,W504 --exclude=arrow/commands/,scripts/
99
- python setup.py install
1010
deploy:
1111
provider: pypi

README.rst

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Apollo API Library
99
:alt: Documentation Status
1010

1111
Apollo is a Python library for interacting with
12-
`WebApollo <https://github.com/gmod/apollo/>`__
12+
`Apollo <https://github.com/gmod/apollo/>`__
1313

1414
Examples
1515
--------
@@ -27,7 +27,7 @@ Examples
2727
public=False
2828
)
2929
30-
# Give webapollo a second to process the uploaded organism.
30+
# Give Apollo a second to process the uploaded organism.
3131
time.sleep(1)
3232
3333
# Then add yourself to permission list
@@ -64,6 +64,12 @@ Or with the new Arrow client:
6464
History
6565
-------
6666

67+
- 3.1
68+
- Added user activate/inactivate
69+
- Added get_creator for user, group and organisms
70+
- Added omitEmptyOrganisms to get_users
71+
- Added support for group admins
72+
- Repaired GFF3/Fasta downloading
6773
- 3.0.4
6874
- `Fixed bug <https://github.com/galaxy-genome-annotation/python-apollo/issues/4>`__ in deleteFeatures (Thanks `@NeillGibson <https://github.com/NeillGibson>`__)
6975
- 3.0.3

apollo/client.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
"""Base apollo client
22
"""
33
import json
4-
import requests
54
import logging
5+
6+
import requests
67
try:
78
from shlex import quote
89
except ImportError:
@@ -63,7 +64,7 @@ def post(self, client_method, data, post_params=None, is_json=True):
6364
raise Exception("Unexpected response from apollo %s: %s" %
6465
(resp.status_code, resp.text))
6566

66-
def get(self, client_method, get_params):
67+
def get(self, client_method, get_params, is_json=True):
6768
"""Make a GET request"""
6869
url = self._wa.apollo_url + self.CLIENT_BASE + client_method
6970
headers = {}
@@ -72,8 +73,11 @@ def get(self, client_method, get_params):
7273
verify=self.__verify, params=get_params,
7374
**self._request_args)
7475
if response.status_code == 200:
75-
data = response.json()
76-
return self._scrub_data(data)
76+
if is_json:
77+
data = response.json()
78+
return self._scrub_data(data)
79+
else:
80+
return response.text
7781
# @see self.body for HTTP response body
7882
raise Exception("Unexpected response from apollo %s: %s" %
7983
(response.status_code, response.text))

apollo/decorators.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
from apollo.exceptions import APIErrorResponseException
22

3+
from decorator import decorator
34

5+
6+
@decorator
47
def raise_error_decorator(fn):
58
def wrapper(*args, **kwargs):
69
r = fn(*args, **kwargs)

apollo/groups/__init__.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,3 +164,54 @@ def update_membership(self, group_id, users=[]):
164164
'users': users,
165165
}
166166
return _fix_group(self.post('updateMembership', data))
167+
168+
def update_group_admin(self, group_id, users=[]):
169+
"""
170+
Update the group's admins
171+
172+
:type group_id: int
173+
:param group_id: Group ID Number
174+
175+
:type users: list of str
176+
:param users: List of emails
177+
178+
:rtype: dict
179+
:return: dictionary of group information
180+
"""
181+
data = {
182+
'groupId': group_id,
183+
'users': users,
184+
}
185+
return _fix_group(self.post('updateGroupAdmin', data))
186+
187+
def get_group_admin(self, group):
188+
"""
189+
Get the group's admins
190+
191+
:type group: str
192+
:param group: group name
193+
194+
:rtype: list
195+
:return: a list containing group admins
196+
"""
197+
data = {
198+
'name': group,
199+
}
200+
response = _fix_group(self.post('getGroupAdmin', data))
201+
return response
202+
203+
def get_group_creator(self, group):
204+
"""
205+
Get the group's creator
206+
207+
:type group: str
208+
:param group: group name
209+
210+
:rtype: list
211+
:return: creator userId
212+
"""
213+
data = {
214+
'name': group,
215+
}
216+
response = _fix_group(self.post('getGroupCreator', data))
217+
return response

apollo/io/__init__.py

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class IOClient(Client):
99

1010
def write_downloadable(self, organism, export_type='FASTA',
1111
seq_type='peptide', export_format='text',
12-
export_gff3_fasta=False, sequences=[]):
12+
export_gff3_fasta=False, sequences=[], region=None):
1313
"""
1414
Prepare a download for an organism
1515
@@ -20,7 +20,7 @@ def write_downloadable(self, organism, export_type='FASTA',
2020
:param sequences: Names of references sequences to add (default is all)
2121
2222
:type export_type: str
23-
:param export_type: Export type. Choices: FASTA, GFF3
23+
:param export_type: Export type. Choices: FASTA, GFF3, VCF
2424
2525
:type seq_type: str
2626
:param seq_type: Export selection. Choices: peptide, cds, cdna, genomic
@@ -31,10 +31,19 @@ def write_downloadable(self, organism, export_type='FASTA',
3131
:type export_gff3_fasta: bool
3232
:param export_gff3_fasta: Export reference sequence when exporting GFF3 annotations.
3333
34+
:type region: str
35+
:param region: Region to export in form sequence:min..max e.g., chr3:1001..1034
36+
3437
:rtype: dict
3538
:return: a dictionary containing download information
3639
"""
3740

41+
if export_format.lower() not in ('gzip', 'text'):
42+
raise Exception("export_format must be one of file, text")
43+
44+
if export_type.lower() not in ('fasta', 'gff3', 'vcf'):
45+
raise Exception("export_type must be one of FASTA, GFF3, VCF")
46+
3847
data = {
3948
'type': export_type,
4049
'seq_type': seq_type,
@@ -46,13 +55,16 @@ def write_downloadable(self, organism, export_type='FASTA',
4655
'exportGff3Fasta': export_gff3_fasta,
4756
}
4857

58+
if region:
59+
data['region'] = region
60+
4961
return self.post('write', data)
5062

5163
def write_text(self, organism, export_type='FASTA', seq_type='peptide',
5264
export_format='text', export_gff3_fasta=False,
53-
sequences=[]):
65+
sequences=[], region=None):
5466
"""
55-
Download or prepare a download for an organism
67+
[DEPRECATED, use write_downloadable] Download or prepare a download for an organism
5668
5769
:type organism: str
5870
:param organism: organism common name
@@ -61,7 +73,7 @@ def write_text(self, organism, export_type='FASTA', seq_type='peptide',
6173
:param sequences: Names of references sequences to add (default is all)
6274
6375
:type export_type: str
64-
:param export_type: Export type. Choices: FASTA, GFF3
76+
:param export_type: Export type. Choices: FASTA, GFF3, VCF
6577
6678
:type seq_type: str
6779
:param seq_type: Export selection. Choices: peptide, cds, cdna, genomic
@@ -72,44 +84,36 @@ def write_text(self, organism, export_type='FASTA', seq_type='peptide',
7284
:type export_gff3_fasta: bool
7385
:param export_gff3_fasta: Export reference sequence when exporting GFF3 annotations.
7486
87+
:type region: str
88+
:param region: Region to export in form sequence:min..max e.g., chr3:1001..1034
89+
7590
:rtype: str
7691
:return: the exported data
7792
"""
78-
if sequences is None:
79-
sequences = []
8093

81-
data = {
82-
'type': export_type,
83-
'seqType': seq_type,
84-
'format': export_format,
85-
'sequences': sequences,
86-
'organism': organism,
87-
'output': 'text',
88-
'exportAllSequences': True if not sequences else len(sequences) == 0,
89-
'exportGff3Fasta': export_gff3_fasta,
90-
}
91-
92-
return self.post('write', data, is_json=False)
94+
return self.write_downloadable(organism, export_type, seq_type,
95+
export_format, export_gff3_fasta,
96+
sequences, region)
9397

9498
def download(self, uuid, output_format='gzip'):
9599
"""
96-
[CURRENTLY BROKEN] Download pre-prepared data by UUID
100+
Download pre-prepared data by UUID
97101
98102
:type uuid: str
99103
:param uuid: Data UUID
100104
101105
:type output_format: str
102106
:param output_format: Output format of the data, either "gzip" or "text"
103107
104-
:rtype: dict
105-
:return: a dictionary
108+
:rtype: str
109+
:return: The downloaded content
106110
"""
107111

108112
if output_format.lower() not in ('gzip', 'text'):
109-
raise Exception("outputFormat must be one of file, text")
113+
raise Exception("output_format must be one of file, text")
110114

111115
data = {
112116
'format': output_format,
113117
'uuid': uuid,
114118
}
115-
return self.post('write', data)
119+
return self.get('download', get_params=data, is_json=False)

apollo/organisms/__init__.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,3 +166,15 @@ def get_sequences(self, organism_id):
166166
:return: The set of sequences associated with an organism
167167
"""
168168
return self.post('getSequencesForOrganism', {'organism': organism_id})
169+
170+
def get_organism_creator(self, organism_id):
171+
"""
172+
Get the creator of an organism
173+
174+
:type organism_id: str
175+
:param organism_id: Organism ID Number
176+
177+
:rtype: dict
178+
:return: a dictionary containing user information
179+
"""
180+
return self.post('getOrganismCreator', {'organism': organism_id})

apollo/users/__init__.py

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,17 +42,27 @@ def _handle_empty(self, user, response):
4242
"""Apollo likes to return empty user arrays, even when you REALLY
4343
want a user response back... like creating a user."""
4444
if len(response.keys()) == 0:
45-
return self.show_user(user)
45+
response = self.show_user(user)
46+
47+
# And sometimes show_user can return nothing. Ask again...
48+
if len(response) == 0:
49+
response = self.show_user(user)
4650
return response
4751

48-
def get_users(self):
52+
def get_users(self, omit_empty_organisms=False):
4953
"""
5054
Get all users known to this Apollo instance
5155
56+
:type omit_empty_organisms: bool
57+
:param omit_empty_organisms: Will omit users having no access to any organism
58+
5259
:rtype: list of dicts
5360
:return: list of user info dictionaries
5461
"""
55-
res = self.post('loadUsers', {})
62+
payload = {}
63+
if omit_empty_organisms:
64+
payload['omitEmptyOrganisms'] = omit_empty_organisms
65+
res = self.post('loadUsers', payload)
5666
data = [_fix_user(user) for user in res]
5767
return data
5868

@@ -67,7 +77,7 @@ def show_user(self, user):
6777
:return: a dictionary containing user information
6878
"""
6979
res = self.post('loadUsers', {'userId': user})
70-
if isinstance(res, list):
80+
if isinstance(res, list) and len(res) > 0:
7181
res = res[0]
7282
return _fix_user(res)
7383

@@ -235,3 +245,39 @@ def update_user(self, email, first_name, last_name, password, metadata={}):
235245
}
236246
response = self.post('updateUser', data)
237247
return self._handle_empty(email, response)
248+
249+
def get_user_creator(self, user):
250+
"""
251+
Get the creator of a user
252+
253+
:type user: str
254+
:param user: User Email
255+
256+
:rtype: dict
257+
:return: a dictionary containing user information
258+
"""
259+
return self.post('getUserCreator', {'email': user})
260+
261+
def activate_user(self, user):
262+
"""
263+
Activate a user
264+
265+
:type user: str
266+
:param user: User's email
267+
268+
:rtype: dict
269+
:return: an empty dictionary
270+
"""
271+
return self.post('activateUser', {'userToActivate': user})
272+
273+
def inactivate_user(self, user):
274+
"""
275+
Activate a user
276+
277+
:type user: str
278+
:param user: User's email
279+
280+
:rtype: dict
281+
:return: an empty dictionary
282+
"""
283+
return self.post('inactivateUser', {'userToDelete': user})

apollo/util.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,8 @@ def featuresToFeatureSchema(features):
104104
compiled = []
105105
for feature in features:
106106
# if feature.type != 'gene':
107-
# log.warn("Not able to handle %s features just yet...", feature.type)
108-
# continue
107+
# log.warn("Not able to handle %s features just yet...", feature.type)
108+
# continue
109109

110110
for x in _yieldFeatData([feature]):
111111
compiled.append(x)

arrow/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = '3.0.4'
1+
__version__ = '3.1'

0 commit comments

Comments
 (0)