solvebio 1.5.2 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. data/.travis.yml +13 -8
  2. data/Gemfile +4 -2
  3. data/README.md +5 -3
  4. data/demo/cheatsheet.rb +31 -0
  5. data/lib/cli/auth.rb +6 -6
  6. data/lib/cli/irbrc.rb +2 -1
  7. data/lib/cli/options.rb +1 -1
  8. data/lib/client.rb +85 -83
  9. data/lib/credentials.rb +2 -2
  10. data/lib/main.rb +11 -2
  11. data/lib/query.rb +5 -6
  12. data/lib/resource/annotation.rb +23 -0
  13. data/lib/resource/apiresource.rb +241 -0
  14. data/lib/resource/dataset.rb +91 -0
  15. data/lib/resource/datasetfield.rb +37 -0
  16. data/lib/resource/depository.rb +50 -0
  17. data/lib/resource/depositoryversion.rb +69 -0
  18. data/lib/resource/main.rb +123 -0
  19. data/lib/resource/sample.rb +75 -0
  20. data/lib/{solveobject.rb → resource/solveobject.rb} +43 -22
  21. data/lib/resource/user.rb +5 -0
  22. data/lib/solvebio.rb +1 -1
  23. data/lib/util.rb +29 -0
  24. data/solvebio.gemspec +7 -4
  25. data/test/Makefile +9 -0
  26. data/test/data/sample.vcf.gz +0 -0
  27. data/test/helper.rb +9 -2
  28. data/test/test-annotation.rb +46 -0
  29. data/test/test-auth.rb +8 -4
  30. data/test/test-client.rb +6 -6
  31. data/test/test-conversion.rb +13 -0
  32. data/test/test-dataset.rb +42 -0
  33. data/test/test-depository.rb +35 -0
  34. data/test/test-netrc.rb +13 -3
  35. data/test/test-query-batch.rb +26 -46
  36. data/test/test-query-paging.rb +77 -98
  37. data/test/test-query.rb +47 -64
  38. data/test/test-resource.rb +8 -15
  39. data/test/test-sample-access.rb +59 -0
  40. data/test/test-sample-download.rb +20 -0
  41. data/test/test-tabulate.rb +27 -23
  42. data/test/{test-solveobject.rb → test-util.rb} +17 -2
  43. metadata +128 -56
  44. data/lib/apiresource.rb +0 -130
  45. data/lib/help.rb +0 -46
  46. data/lib/resource.rb +0 -414
data/lib/apiresource.rb DELETED
@@ -1,130 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- require_relative 'solveobject'
3
- require_relative 'client'
4
-
5
- class SolveBio::APIResource < SolveBio::SolveObject
6
-
7
- def self.retrieve(cls, id, params={})
8
- instance = cls.new(id, params)
9
- instance.refresh()
10
- return instance
11
- end
12
-
13
- def refresh
14
- refresh_from request('get', instance_url)
15
- return self
16
- end
17
-
18
- def self.class_url(cls)
19
- # cls_name = cls.class_name()
20
- cls_name = cls.to_s.sub('SolveBio::', '')
21
- # pluralize
22
- if cls_name.end_with?('y')
23
- cls_name = cls_name[0..-2] + 'ie'
24
- end
25
- cls_name = camelcase_to_underscore(cls_name)
26
- return "/v1/#{cls_name}s"
27
- end
28
-
29
-
30
- # Get instance URL by ID or full name (if available)
31
- def instance_url
32
- id = self['id']
33
- base = SolveBio::APIResource.class_url(self.class)
34
-
35
- if id
36
- return "#{base}/#{id}"
37
- else
38
- msg = 'Could not determine which URL to request: %s instance ' +
39
- 'has invalid ID: %s' % [self.class, id]
40
- raise Exception, msg
41
- end
42
- end
43
- end
44
-
45
- module SolveBio::ListableAPIResource
46
-
47
- def self.included base
48
- base.extend ClassMethods
49
- end
50
-
51
- module ClassMethods
52
- def all(params={})
53
- url = SolveBio::APIResource.class_url(self)
54
- response = SolveBio::Client.client.request('get', url, params)
55
- return response.to_solvebio
56
- end
57
- end
58
- end
59
-
60
-
61
- module SolveBio::SearchableAPIResource
62
-
63
- def self.included base
64
- base.extend ClassMethods
65
- end
66
-
67
- module ClassMethods
68
- def search(query='', params={})
69
- params['q'] = query
70
- url = SolveBio::APIResource.class_url(self)
71
- response = SolveBio::Client.client.request('get', url, params)
72
- return response.to_solvebio
73
- end
74
- end
75
- end
76
-
77
- module SolveBio::CreateableAPIResource
78
-
79
- def self.included base
80
- base.extend ClassMethods
81
- end
82
-
83
- module ClassMethods
84
- def create(params={})
85
- url = SolveBio::APIResource.class_url(self)
86
- response = SolveBio::Client.client.request('post', url, params)
87
- return to_solve_object(response)
88
- end
89
- end
90
- end
91
-
92
- module SolveBio::UpdateableAPIResource
93
-
94
- def self.included base
95
- base.extend ClassMethods
96
- end
97
-
98
- module ClassMethods
99
- def save
100
- refresh_from(request('patch', instance_url(),
101
- serialize(self)))
102
- return self
103
- end
104
-
105
- def serialize(obj)
106
- params = {}
107
- if obj.unsaved_values
108
- obj.unsaved_values.each do |k|
109
- next if k == 'id'
110
- params[k] = getattr(obj, k) or ''
111
- end
112
- end
113
- return params
114
- end
115
- end
116
- end
117
-
118
- class SolveBio::DeletableAPIResource
119
- def self.included base
120
- base.extend ClassMethods
121
- end
122
-
123
- module ClassMethods
124
-
125
- def delete(params={})
126
- refresh_from(request('delete', instance_url(), params))
127
- return self
128
- end
129
- end
130
- end
data/lib/help.rb DELETED
@@ -1,46 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # -*- coding: utf-8 -*-
3
- require 'uri'
4
- require_relative 'main'
5
-
6
- module SolveBio::HelpableAPIResource
7
-
8
- attr_reader :have_launchy
9
-
10
- @@have_launchy = false
11
- begin
12
- @@have_launchy = require 'launchy'
13
- rescue LoadError
14
- end
15
-
16
- def self.included base
17
- base.send :include, InstanceMethods
18
- end
19
-
20
- module InstanceMethods
21
- def help
22
- open_help(self['full_name'])
23
- end
24
- end
25
-
26
- def open_help(path)
27
- url = URI::join('https://www.solvebio.com/', path)
28
- if @@have_launchy
29
- Launchy.open(url)
30
- else
31
- puts('The SolveBio Ruby client needs the "launchy" gem to ' +
32
- "open help url: #{url.to_s}")
33
- end
34
- end
35
- end
36
-
37
- # Demo code
38
- if __FILE__ == $0
39
- include SolveBio::HelpableAPIResource
40
- if @@have_launchy
41
- open_help('docs')
42
- sleep 1
43
- else
44
- puts "Don't have launchy"
45
- end
46
- end
data/lib/resource.rb DELETED
@@ -1,414 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- # from utils.tabulate import tabulate
3
-
4
- require_relative 'solveobject'
5
- require_relative 'apiresource'
6
- require_relative 'client'
7
- require_relative 'query'
8
- require_relative 'help'
9
-
10
- class SolveBio::ListObject < SolveBio::SolveObject
11
-
12
- include Enumerable
13
-
14
- def all(params={})
15
- return request('get', self['url'], params)
16
- end
17
-
18
- def create(params={})
19
- return request('post', self['url'], params)
20
- end
21
-
22
- def next_page(params={})
23
- if self['links']['next']
24
- return request('get', self['links']['next'], params)
25
- end
26
- return nil
27
- end
28
-
29
- def prev_page(params={})
30
- if self['links']['prev']
31
- request('get', self['links']['prev'], params)
32
- end
33
- return nil
34
- end
35
-
36
- def at(i)
37
- self.to_a[i]
38
- end
39
-
40
- def to_a
41
- return to_solve_object(self['data'])
42
- end
43
-
44
- def each(*pass)
45
- return self unless block_given?
46
- i = 0
47
- ary = self.dup
48
- done = false
49
- until done
50
- if i >= ary['data'].size
51
- ary = next_page
52
- break unless ary
53
- i = 0
54
- end
55
- yield(ary.at(i))
56
- i += 1
57
- end
58
- return self
59
- end
60
-
61
- def first
62
- self['data'][0]
63
- end
64
-
65
- # def max
66
- # self['data'][self['total']]
67
- # end
68
-
69
- end
70
-
71
-
72
- class SingletonAPIResource < SolveBio::APIResource
73
-
74
- def self.retrieve(cls)
75
- return super(SingletonAPIResource, cls).retrieve(nil)
76
- end
77
-
78
- def self.class_url(cls)
79
- # cls_name = cls.class_name()
80
- cls_name = cls.to_s.sub('SolveBio::', '')
81
- cls_name = camelcase_to_underscore(cls_name)
82
- return "/v1/%s #{cls_name}"
83
- end
84
-
85
- def instance_url
86
- class_url()
87
- end
88
- end
89
-
90
-
91
- # API resources
92
-
93
- class SolveBio::User < SingletonAPIResource
94
- end
95
-
96
-
97
- class SolveBio::Depository < SolveBio::APIResource
98
-
99
- include SolveBio::CreateableAPIResource
100
- include SolveBio::ListableAPIResource
101
- include SolveBio::SearchableAPIResource
102
- include SolveBio::UpdateableAPIResource
103
- include SolveBio::HelpableAPIResource
104
-
105
- ALLOW_FULL_NAME_ID = true
106
- FULL_NAME_REGEX = %r{^[\w\-\.]+$}
107
-
108
- # lookup by ID or full name
109
- def self.retrieve(id, params={})
110
- if id.kind_of?(String)
111
- _id = id.strip
112
- id = nil
113
- if _id =~ FULL_NAME_REGEX
114
- params['full_name'] = _id
115
- else
116
- raise Exception, 'Unrecognized full name: "%s"' % _id
117
- end
118
- end
119
-
120
- return SolveBio::APIResource.
121
- retrieve(SolveBio::Depository, id, params)
122
- end
123
-
124
- def versions_url
125
- return SolveBio::APIResource.
126
- retrieve(SolveBio::Depository, self['id'])['versions_url']
127
- end
128
-
129
- def versions(name=nil, params={})
130
- # construct the depo version full name
131
- return SolveBio::DepositoryVersion.
132
- retrieve("#{self['full_name']}/#{name}") if name
133
-
134
- response = SolveBio::Client.
135
- client.request('get', versions_url, params)
136
- return response.to_solvebio
137
- end
138
-
139
- end
140
-
141
- class SolveBio::DepositoryVersion < SolveBio::APIResource
142
-
143
-
144
- include SolveBio::CreateableAPIResource
145
- include SolveBio::ListableAPIResource
146
- include SolveBio::UpdateableAPIResource
147
- include SolveBio::HelpableAPIResource
148
-
149
- ALLOW_FULL_NAME_ID = true
150
-
151
- # FIXME: base off of Depository::FULL_NAME_REGEX
152
- # Sample matches:
153
- # 'Clinvar/2.0.0-1'
154
- FULL_NAME_REGEX = %r{^[\w\.]+/[\w\-\.]+$}
155
-
156
- # Supports lookup by full name
157
- def self.retrieve(id, params={})
158
- if id.kind_of?(String)
159
- _id = id.strip
160
- id = nil
161
- if _id =~ FULL_NAME_REGEX
162
- params['full_name'] = _id
163
- else
164
- raise Exception, 'Unrecognized full name.'
165
- end
166
- end
167
-
168
- return SolveBio::APIResource.
169
- retrieve(SolveBio::DepositoryVersion, id, params)
170
- end
171
-
172
- def datasets_url(name=nil)
173
- name ||= self['name']
174
- "#{self['full_name']}/#{name}"
175
- end
176
-
177
- def datasets(name=nil, params={})
178
- if name
179
- # construct the dataset full name
180
- return SolveBio::Dataset.retrieve(datasets_url(name))
181
- end
182
-
183
- response = SolveBio::Client.
184
- client.request('get', datasets_url, params)
185
- return response.to_solvebio
186
- end
187
-
188
- # Set the released flag and optional release date and save
189
- def release(released_at=nil)
190
- if released_at
191
- @released_at = released_at
192
- end
193
- @released = true
194
- save()
195
- end
196
-
197
- # Unset the released flag and save
198
- def unrelease
199
- @released = false
200
- save()
201
- end
202
-
203
- # FIXME: is there a better field to sort on?
204
- def <=>(other)
205
- self.id <=> other.id
206
- end
207
-
208
- end
209
-
210
- class SolveBio::Dataset < SolveBio::APIResource
211
-
212
- include SolveBio::CreateableAPIResource
213
- include SolveBio::ListableAPIResource
214
- include SolveBio::UpdateableAPIResource
215
- include SolveBio::HelpableAPIResource
216
-
217
- ALLOW_FULL_NAME_ID = true
218
-
219
- # FIXME: base off of DepositoryVersion::FULL_NAME_REGEX
220
- # Sample matches:
221
- # 'Clinvar/2.0.0-1/Variants'
222
- # 'omim/0.0.1-1/omim'
223
- FULL_NAME_REGEX = %r{^([\w\-\.]+/){2}[\w\-\.]+$}
224
-
225
- # Dataset lookup by full string name
226
- def self.retrieve(id, params={})
227
- if id.kind_of?(String)
228
- _id = id.strip
229
- id = nil
230
- if _id =~ FULL_NAME_REGEX
231
- params['full_name'] = _id
232
- else
233
- raise Exception, 'Unrecognized full name.'
234
- end
235
- end
236
-
237
- return SolveBio::APIResource.
238
- retrieve(SolveBio::Dataset, id, params)
239
- end
240
-
241
- def depository_version
242
- return SolveBio::DepositoryVersion.
243
- retrieve(self['depository_version'])
244
- end
245
-
246
- def depository
247
- return SolveBio::Depository.retrieve(self['depository'])
248
- end
249
-
250
- def fields(name=nil, params={})
251
- unless self['fields_url']
252
- raise Exception,
253
- 'Please use Dataset.retrieve({ID}) before doing looking ' +
254
- 'up fields'
255
- end
256
-
257
- if name
258
- # construct the field's full_name if a field name is provided
259
- return DatasetField.retrieve("#{self['full_name']}/#{name}")
260
- end
261
-
262
- SolveBio::Client.
263
- client.request('get', self['fields_url']).to_solvebio
264
- end
265
-
266
- def query(params={})
267
- paging = false
268
- if params.member?(:paging)
269
- paging = params[:paging]
270
- params.delete(:paging)
271
- end
272
- q = paging ? SolveBio::PagingQuery.new(self['id'], params) :
273
- SolveBio::Query.new(self['id'], params)
274
-
275
- if params[:filters]
276
- return q.filter(params[:filters])
277
- end
278
- return q
279
- end
280
-
281
- private
282
- def data_url
283
- unless self['data_url']
284
- unless self['id']
285
- raise Exception,
286
- 'No Dataset ID was provided. ' +
287
- 'Please instantiate the Dataset ' +
288
- 'object with an ID or full_name.'
289
- end
290
- # automatically construct the data_url from the ID
291
- return instance_url() + '/data'
292
- end
293
- return self['data_url']
294
- end
295
-
296
- end
297
-
298
- class SolveBio::DatasetField < SolveBio::APIResource
299
-
300
- include SolveBio::CreateableAPIResource
301
- include SolveBio::ListableAPIResource
302
- include SolveBio::UpdateableAPIResource
303
-
304
- ALLOW_FULL_NAME_ID = true
305
- FULL_NAME_REGEX = %r{^([\w\-\.]+/){3}[\w\-\.]+$}
306
-
307
- # Supports lookup by ID or full name
308
- def self.retrieve(id, params={})
309
- if id.kind_of?(String)
310
- _id = id.strip
311
- id = nil
312
- if FULL_NAME_REGEX =~ _id
313
- params['full_name'] = _id
314
- else
315
- raise Exception, 'Unrecognized full name.'
316
- end
317
- end
318
-
319
- return SolveBio::APIResource.
320
- retrieve(SolveBio::DatasetField, id, params)
321
- end
322
-
323
- def facets_url
324
- return "/v1/dataset_fields/#{self.id}/facets"
325
- end
326
-
327
- def facets(params={})
328
- response = SolveBio::Client.
329
- client.request('get', facets_url, params)
330
- return response.to_solvebio
331
- end
332
-
333
- def help
334
- facets
335
- end
336
- end
337
-
338
- SolveBio::SolveObject::CONVERSION = {
339
- 'Depository' => SolveBio::Depository,
340
- 'DepositoryVersion' => SolveBio::DepositoryVersion,
341
- 'Dataset' => SolveBio::Dataset,
342
- 'DatasetField' => SolveBio::DatasetField,
343
- 'User' => SolveBio::User,
344
- 'list' => SolveBio::ListObject
345
- }
346
-
347
- class Hash
348
- def to_solvebio
349
- resp = self.dup()
350
- klass_name = resp['class_name']
351
- if klass_name.kind_of?(String)
352
- klass = SolveBio::SolveObject::CONVERSION[klass_name] ||
353
- SolveBio::SolveObject
354
- else
355
- klass = SolveBio::SolveObject
356
- end
357
- SolveBio::SolveObject::construct_from(klass, resp)
358
- end
359
- end
360
-
361
- class Array
362
- def to_solvebio
363
- return self.map{|i| to_solve_object(i)}
364
- end
365
- end
366
-
367
-
368
- def to_solve_object(resp)
369
- if resp.kind_of?(Array) or
370
- (not resp.kind_of? SolveBio::SolveObject and resp.kind_of?(Hash))
371
- resp.to_solvebio
372
- else
373
- return resp
374
- end
375
- end
376
-
377
- if __FILE__ == $0
378
- puts '-' * 50
379
- resp = {
380
- 'class_name' => 'Dataset',
381
- 'data_url' => 'https://api.solvebio.com/v1/datasets/25/data',
382
- 'depository' => 'ClinVar',
383
- 'depository_id' => 223,
384
- 'depository_version' => 'ClinVar/2.0.0-1',
385
- 'depository_version_id' => 15,
386
- 'description' => '',
387
- 'fields_url' => 'https://api.solvebio.com/v1/datasets/25/fields',
388
- 'full_name' => 'ClinVar/2.0.0-1/Variants',
389
- 'id' => 25,
390
- 'name' => 'Variants',
391
- 'title' => 'Variants',
392
- 'url' => 'https://api.solvebio.com/v1/datasets/25'
393
- }
394
- so = to_solve_object(resp)
395
- so = resp.to_solvebio
396
- puts so.inspect
397
- puts so.to_s
398
-
399
- if ARGV[0]
400
- require_relative './cli/auth.rb'
401
- include SolveBio::Auth
402
- login
403
- puts '-' * 30, ' HELP ', '-' * 30
404
- puts SolveBio::Depository.retrieve('ClinVar').help
405
- puts '-' * 30, ' Retrieve ClinVar ','-' * 30
406
- puts SolveBio::Depository.retrieve('ClinVar').to_s
407
- puts '-' * 30, ' Versions ClinVar ','-' * 30
408
- puts SolveBio::Depository.retrieve('Clinvar').versions.to_s
409
- puts '-' * 30, ' Dataset ','-' * 30
410
- puts SolveBio::Dataset.retrieve('Clinvar/2.0.0-1/Variants').to_s
411
- puts '-' * 30, ' All Depository ','-' * 30
412
- puts SolveBio::Depository.all.to_s
413
- end
414
- end