etna 0.1.21 → 0.1.26

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 920faf7833d50d01c0a22d7326d0d3c454cdec27479ce81e4bf0b4012891f0bc
4
- data.tar.gz: 189fad452f86a48ee19343eb7d5bd16bb9cf7308d8fd2dee41d042de2a76cc86
3
+ metadata.gz: 7075c5bf9637903a5aae31e83dbec99fc903945b362b5b454a3d31f95c03c6eb
4
+ data.tar.gz: 48e957e8286a613f7a1cafab2512976e625211782ae09a402053161af0f69b87
5
5
  SHA512:
6
- metadata.gz: 64b2fef7604de4803790fea8543d39d8e6466456231ed014e30e633659049348274971c10a3231964664340cd13b616a2612c0cb0c89dd71337b4fb57f9432a5
7
- data.tar.gz: 7ac816e004b1ace47c193f26944586d2eaca6e35a4c9fc7e76ab9dfe524b5f41cbf2f94abfa377006b80f59baaee1690b3582aa07f2a1ea851dc76fada707805
6
+ metadata.gz: 850effed7485f90957cb3ee53ebb97abaa3fe9c32d9de9ff16c5d30585b61f34ccf00bb88c702ee9f1271c8a883526cebc36218904c311c276d6de51aca0d1ba
7
+ data.tar.gz: 1c90072a96341cf75b869d08f9e1cd1e36c2a616873048d83c6c1cd2ffe57850c618745c80ee1e16e63c2c8c4c090cbb8c99ab19ed1541ec06d8b43d29824d0a
@@ -77,7 +77,7 @@ all_flag_completion_names="$all_flag_completion_names "
77
77
  string_flag_completion_names="$string_flag_completion_names "
78
78
  while [[ "$#" != "0" ]]; do
79
79
  if [[ "$#" == "1" ]]; then
80
- all_completion_names="apply_template attributes copy_template help"
80
+ all_completion_names="apply_template attributes copy_template help load_from_redcap"
81
81
  all_completion_names="$all_completion_names $all_flag_completion_names"
82
82
  if [[ -z "$(echo $all_completion_names | xargs)" ]]; then
83
83
  return
@@ -136,7 +136,7 @@ all_flag_completion_names="$all_flag_completion_names "
136
136
  string_flag_completion_names="$string_flag_completion_names "
137
137
  while [[ "$#" != "0" ]]; do
138
138
  if [[ "$#" == "1" ]]; then
139
- all_completion_names="create_file_linking_csv help update_from_csv"
139
+ all_completion_names="create_file_linking_csv help load_table_from_csv update_from_csv"
140
140
  all_completion_names="$all_completion_names $all_flag_completion_names"
141
141
  if [[ -z "$(echo $all_completion_names | xargs)" ]]; then
142
142
  return
@@ -252,6 +252,68 @@ return
252
252
  fi
253
253
  done
254
254
  return
255
+ elif [[ "$1" == "load_table_from_csv" ]]; then
256
+ shift
257
+ if [[ "$#" == "1" ]]; then
258
+ all_completion_names="__project_name__"
259
+ if [[ -z "$(echo $all_completion_names | xargs)" ]]; then
260
+ return
261
+ fi
262
+ COMPREPLY=($(compgen -W "$all_completion_names" -- "$1"))
263
+ return
264
+ fi
265
+ shift
266
+ if [[ "$#" == "1" ]]; then
267
+ all_completion_names="__model_name__"
268
+ if [[ -z "$(echo $all_completion_names | xargs)" ]]; then
269
+ return
270
+ fi
271
+ COMPREPLY=($(compgen -W "$all_completion_names" -- "$1"))
272
+ return
273
+ fi
274
+ shift
275
+ if [[ "$#" == "1" ]]; then
276
+ all_completion_names="__file_path__"
277
+ if [[ -z "$(echo $all_completion_names | xargs)" ]]; then
278
+ return
279
+ fi
280
+ COMPREPLY=($(compgen -W "$all_completion_names" -- "$1"))
281
+ return
282
+ fi
283
+ shift
284
+ all_flag_completion_names="$all_flag_completion_names --execute "
285
+ string_flag_completion_names="$string_flag_completion_names "
286
+ while [[ "$#" != "0" ]]; do
287
+ if [[ "$#" == "1" ]]; then
288
+ all_completion_names=""
289
+ all_completion_names="$all_completion_names $all_flag_completion_names"
290
+ if [[ -z "$(echo $all_completion_names | xargs)" ]]; then
291
+ return
292
+ fi
293
+ COMPREPLY=($(compgen -W "$all_completion_names" -- "$1"))
294
+ return
295
+ elif [[ -z "$(echo $all_flag_completion_names | xargs)" ]]; then
296
+ return
297
+ elif [[ "$all_flag_completion_names" =~ $1\ ]]; then
298
+ all_flag_completion_names="${all_flag_completion_names//$1\ /}"
299
+ a=$1
300
+ shift
301
+ if [[ "$string_flag_completion_names" =~ $a\ ]]; then
302
+ if [[ "$#" == "1" ]]; then
303
+ a="${a//--/}"
304
+ a="${a//-/_}"
305
+ i="_completions_for_$a"
306
+ all_completion_names="${!i}"
307
+ COMPREPLY=($(compgen -W "$all_completion_names" -- "$1"))
308
+ return
309
+ fi
310
+ shift
311
+ fi
312
+ else
313
+ return
314
+ fi
315
+ done
316
+ return
255
317
  elif [[ "$1" == "update_from_csv" ]]; then
256
318
  shift
257
319
  if [[ "$#" == "1" ]]; then
@@ -417,6 +479,61 @@ return
417
479
  fi
418
480
  done
419
481
  return
482
+ elif [[ "$1" == "load_from_redcap" ]]; then
483
+ shift
484
+ if [[ "$#" == "1" ]]; then
485
+ all_completion_names="__project_name__"
486
+ if [[ -z "$(echo $all_completion_names | xargs)" ]]; then
487
+ return
488
+ fi
489
+ COMPREPLY=($(compgen -W "$all_completion_names" -- "$1"))
490
+ return
491
+ fi
492
+ shift
493
+ if [[ "$#" == "1" ]]; then
494
+ all_completion_names="__redcap_tokens__"
495
+ if [[ -z "$(echo $all_completion_names | xargs)" ]]; then
496
+ return
497
+ fi
498
+ COMPREPLY=($(compgen -W "$all_completion_names" -- "$1"))
499
+ return
500
+ fi
501
+ shift
502
+ all_flag_completion_names="$all_flag_completion_names --commit --models --record_names "
503
+ string_flag_completion_names="$string_flag_completion_names --models --record_names "
504
+ declare _completions_for_models="__models__"
505
+ declare _completions_for_record_names="__record_names__"
506
+ while [[ "$#" != "0" ]]; do
507
+ if [[ "$#" == "1" ]]; then
508
+ all_completion_names=""
509
+ all_completion_names="$all_completion_names $all_flag_completion_names"
510
+ if [[ -z "$(echo $all_completion_names | xargs)" ]]; then
511
+ return
512
+ fi
513
+ COMPREPLY=($(compgen -W "$all_completion_names" -- "$1"))
514
+ return
515
+ elif [[ -z "$(echo $all_flag_completion_names | xargs)" ]]; then
516
+ return
517
+ elif [[ "$all_flag_completion_names" =~ $1\ ]]; then
518
+ all_flag_completion_names="${all_flag_completion_names//$1\ /}"
519
+ a=$1
520
+ shift
521
+ if [[ "$string_flag_completion_names" =~ $a\ ]]; then
522
+ if [[ "$#" == "1" ]]; then
523
+ a="${a//--/}"
524
+ a="${a//-/_}"
525
+ i="_completions_for_$a"
526
+ all_completion_names="${!i}"
527
+ COMPREPLY=($(compgen -W "$all_completion_names" -- "$1"))
528
+ return
529
+ fi
530
+ shift
531
+ fi
532
+ else
533
+ return
534
+ fi
535
+ done
536
+ return
420
537
  elif [[ -z "$(echo $all_flag_completion_names | xargs)" ]]; then
421
538
  return
422
539
  elif [[ "$all_flag_completion_names" =~ $1\ ]]; then
@@ -54,7 +54,7 @@ class EtnaApp
54
54
  boolean_flags << '--ignore-ssl'
55
55
 
56
56
  def execute(host, ignore_ssl: false)
57
- polyphemus_client ||= Etna::Clients::Polyphemus.new(
57
+ polyphemus_client = Etna::Clients::Polyphemus.new(
58
58
  host: host,
59
59
  token: token(ignore_environment: true),
60
60
  ignore_ssl: ignore_ssl)
@@ -62,7 +62,7 @@ class EtnaApp
62
62
  polyphemus_client: polyphemus_client,
63
63
  config_file: EtnaApp.config_file_path)
64
64
  config = workflow.update_configuration_file(ignore_ssl: ignore_ssl)
65
- logger.info("Updated #{config.environment} configuration from #{host}.")
65
+ logger&.info("Updated #{config.environment} configuration from #{host}.")
66
66
  end
67
67
 
68
68
  def setup(config)
@@ -299,6 +299,87 @@ class EtnaApp
299
299
  workflow.write_csv_io(filename: file)
300
300
  end
301
301
  end
302
+
303
+ class LoadTableFromCsv < Etna::Command
304
+ include WithEtnaClients
305
+
306
+ boolean_flags << '--execute'
307
+
308
+ def execute(project_name, model_name, file_path, execute: false)
309
+ request = Etna::Clients::Magma::RetrievalRequest.new(project_name: project_name)
310
+ request.model_name = model_name
311
+ request.attribute_names = 'all'
312
+ request.record_names = 'all'
313
+ model = magma_client.retrieve(request).models.model(model_name)
314
+ model_parent_name = model.template.attributes.all.select do |attribute|
315
+ attribute.attribute_type == Etna::Clients::Magma::AttributeType::PARENT
316
+ end.first.name
317
+
318
+ other_attribute_names = model.template.attributes.all.reject do |attribute|
319
+ attribute.attribute_type == Etna::Clients::Magma::AttributeType::PARENT
320
+ end.map do |attribute|
321
+ attribute.name
322
+ end
323
+
324
+ # NOTE: This does not call ensure_parent currently because of MVIR1 consent--
325
+ # if the timepoint doesn't exist, the patient may be no study? (one example, at least)
326
+ update_request = Etna::Clients::Magma::UpdateRequest.new(project_name: project_name)
327
+
328
+ data = CSV.parse(File.read(file_path), headers: true)
329
+
330
+ data.by_row.each do |row|
331
+ revision = {}
332
+ other_attribute_names.each do |attribute_name|
333
+ revision[attribute_name] = row[attribute_name] unless row[attribute_name].nil?
334
+ end
335
+ update_request.append_table(model_parent_name, row[model_parent_name], model_name, revision)
336
+ end
337
+
338
+ puts update_request
339
+
340
+ if execute
341
+ magma_client.update_json(update_request)
342
+ end
343
+ end
344
+ end
345
+ end
346
+
347
+ class LoadFromRedcap < Etna::Command
348
+ include WithEtnaClients
349
+ include WithLogger
350
+ include StrongConfirmation
351
+
352
+ boolean_flags << '--commit'
353
+ string_flags << '--models'
354
+ string_flags << '--record_names'
355
+
356
+ def execute(project_name, redcap_tokens, models: "all", record_names: nil, commit: false)
357
+ raise "Must provide at least one REDCap token (comma-separated)." unless redcap_tokens.split(',').length > 0
358
+
359
+ puts "NOTE: This is a **preview** of what the data loading will look like. Use the --commit flag to load records into Magma." unless commit
360
+
361
+ polyphemus_client.job(Etna::Clients::Polyphemus::RedcapJobRequest.new(
362
+ model_names: "all" == models ? "all" : models.split(','),
363
+ record_names: nil == record_names || "existing" == record_names ? record_names : record_names.split(','),
364
+ redcap_tokens: redcap_tokens.split(','),
365
+ project_name: project_name,
366
+ commit: commit
367
+ )) do |response|
368
+ response.read_body do |chunk|
369
+ puts clean_sne_message(chunk)
370
+ end
371
+ end
372
+ end
373
+
374
+ def clean_sne_message(chunk)
375
+ chunk.split("\n").reject do |c|
376
+ c.start_with?("retry:") || c.start_with?("event:")
377
+ end.map do |c|
378
+ c.gsub("data:", "").strip
379
+ end.reject do |c|
380
+ c.empty?
381
+ end
382
+ end
302
383
  end
303
384
  end
304
385
  end
@@ -18,6 +18,8 @@ require_relative './etna/spec'
18
18
  require_relative './etna/clients'
19
19
  require_relative './etna/csvs'
20
20
  require_relative './etna/environment_scoped'
21
+ require_relative './etna/filesystem'
22
+ require_relative './etna/formatting'
21
23
 
22
24
  class EtnaApp
23
25
  include Etna::Application
@@ -1,14 +1,12 @@
1
- require 'net/http/persistent'
2
1
  require 'net/http/post/multipart'
3
2
  require 'singleton'
4
3
  require 'rack/utils'
5
4
 
6
5
  module Etna
7
6
  class Client
8
- def initialize(host, token, routes_available: true, persistent: true, ignore_ssl: false)
7
+ def initialize(host, token, routes_available: true, ignore_ssl: false)
9
8
  @host = host.sub(%r!/$!, '')
10
9
  @token = token
11
- @persistent = persistent
12
10
  @ignore_ssl = ignore_ssl
13
11
 
14
12
  if routes_available
@@ -38,6 +36,10 @@ module Etna
38
36
  query_request(Net::HTTP::Get, endpoint, params, &block)
39
37
  end
40
38
 
39
+ def head(endpoint, params = {}, &block)
40
+ query_request(Net::HTTP::Head, endpoint, params, &block)
41
+ end
42
+
41
43
  def options(endpoint, params = {}, &block)
42
44
  query_request(Net::HTTP::Options, endpoint, params, &block)
43
45
  end
@@ -79,16 +81,6 @@ module Etna
79
81
  end
80
82
  end
81
83
 
82
- def persistent_connection
83
- @http ||= begin
84
- http = Net::HTTP::Persistent.new
85
- http.read_timeout = 3600
86
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE if @ignore_ssl
87
- http
88
- end
89
- end
90
-
91
-
92
84
  def body_request(type, endpoint, params = {}, &block)
93
85
  uri = request_uri(endpoint)
94
86
  req = type.new(uri.request_uri, request_params)
@@ -141,36 +133,23 @@ module Etna
141
133
 
142
134
  def request(uri, data)
143
135
  if block_given?
144
- if @persistent
145
- persistent_connection.request(uri, data) do |response|
136
+ verify_mode = @ignore_ssl ?
137
+ OpenSSL::SSL::VERIFY_NONE :
138
+ OpenSSL::SSL::VERIFY_PEER
139
+ Net::HTTP.start(uri.host, uri.port, use_ssl: true, verify_mode: verify_mode) do |http|
140
+ http.request(data) do |response|
146
141
  status_check!(response)
147
142
  yield response
148
143
  end
149
- else
150
- verify_mode = @ignore_ssl ?
151
- OpenSSL::SSL::VERIFY_NONE :
152
- OpenSSL::SSL::VERIFY_PEER
153
- Net::HTTP.start(uri.host, uri.port, use_ssl: true, verify_mode: verify_mode) do |http|
154
- http.request(data) do |response|
155
- status_check!(response)
156
- yield response
157
- end
158
- end
159
144
  end
160
145
  else
161
- if @persistent
162
- response = persistent_connection.request(uri, data)
146
+ verify_mode = @ignore_ssl ?
147
+ OpenSSL::SSL::VERIFY_NONE :
148
+ OpenSSL::SSL::VERIFY_PEER
149
+ Net::HTTP.start(uri.host, uri.port, use_ssl: true, verify_mode: verify_mode) do |http|
150
+ response = http.request(data)
163
151
  status_check!(response)
164
152
  return response
165
- else
166
- verify_mode = @ignore_ssl ?
167
- OpenSSL::SSL::VERIFY_NONE :
168
- OpenSSL::SSL::VERIFY_PEER
169
- Net::HTTP.start(uri.host, uri.port, use_ssl: true, verify_mode: verify_mode) do |http|
170
- response = http.request(data)
171
- status_check!(response)
172
- return response
173
- end
174
153
  end
175
154
  end
176
155
  end
@@ -0,0 +1,39 @@
1
+ require 'base64'
2
+ require 'json'
3
+ require 'date'
4
+
5
+ module Etna
6
+ module Clients
7
+ class BaseClient
8
+ attr_reader :host, :token, :ignore_ssl
9
+ def initialize(host:, token:, ignore_ssl: false)
10
+ raise "#{self.class.name} client configuration is missing host." unless host
11
+ raise "#{self.class.name} client configuration is missing token." unless token
12
+
13
+ @token = token
14
+ raise "Your token is expired." if token_expired?
15
+
16
+ @etna_client = ::Etna::Client.new(
17
+ host,
18
+ token,
19
+ routes_available: false,
20
+ ignore_ssl: ignore_ssl)
21
+ @host = host
22
+ @ignore_ssl = ignore_ssl
23
+ end
24
+
25
+ def token_expired?
26
+ # Has the token already expired?
27
+ token_will_expire?(0)
28
+ end
29
+
30
+ def token_will_expire?(offset=3000)
31
+ # offset in seconds
32
+ # Will the user's token expire in the given amount of time?
33
+ epoch_seconds = JSON.parse(Base64.urlsafe_decode64(token.split('.')[1]))["exp"]
34
+ expiration = DateTime.strptime(epoch_seconds.to_s, "%s")
35
+ expiration <= DateTime.now.new_offset + offset
36
+ end
37
+ end
38
+ end
39
+ end
@@ -1,23 +1,12 @@
1
- require 'net/http/persistent'
2
1
  require 'net/http/post/multipart'
3
2
  require 'singleton'
4
3
  require_relative '../../client'
5
4
  require_relative './models'
5
+ require_relative '../base_client'
6
6
 
7
7
  module Etna
8
8
  module Clients
9
- class Janus
10
- def initialize(host:, token:, persistent: true, ignore_ssl: false)
11
- raise 'Janus client configuration is missing host.' unless host
12
- raise 'Janus client configuration is missing token.' unless token
13
- @etna_client = ::Etna::Client.new(
14
- host,
15
- token,
16
- routes_available: false,
17
- persistent: persistent,
18
- ignore_ssl: ignore_ssl)
19
- end
20
-
9
+ class Janus < Etna::Clients::BaseClient
21
10
  def get_project(get_project_request = GetProjectRequest.new)
22
11
  html = nil
23
12
  @etna_client.get(
@@ -1,11 +1,12 @@
1
1
  require 'ostruct'
2
2
  require_relative '../../json_serializable_struct'
3
+ require_relative '../base_client'
3
4
 
4
5
  # TODO: In the near future, I'd like to transition to specifying apis via SWAGGER and generating model stubs from the
5
6
  # common definitions. For nowe I've written them out by hand here.
6
7
  module Etna
7
8
  module Clients
8
- class Janus
9
+ class Janus < Etna::Clients::BaseClient
9
10
  class GetProjectRequest < Struct.new(:project_name, keyword_init: true)
10
11
  include JsonSerializableStruct
11
12
 
@@ -1,27 +1,12 @@
1
- require 'net/http/persistent'
2
1
  require 'net/http/post/multipart'
3
2
  require 'singleton'
3
+ require_relative '../base_client'
4
4
  require_relative '../../client'
5
5
  require_relative './models'
6
6
 
7
7
  module Etna
8
8
  module Clients
9
- class Magma
10
- attr_reader :host, :token, :ignore_ssl
11
- def initialize(host:, token:, persistent: true, ignore_ssl: false)
12
- raise 'Magma client configuration is missing host.' unless host
13
- raise 'Magma client configuration is missing token.' unless token
14
- @etna_client = ::Etna::Client.new(
15
- host,
16
- token,
17
- routes_available: false,
18
- persistent: persistent,
19
- ignore_ssl: ignore_ssl)
20
- @host = host
21
- @token = token
22
- @ignore_ssl = ignore_ssl
23
- end
24
-
9
+ class Magma < Etna::Clients::BaseClient
25
10
  # This endpoint returns models and records by name:
26
11
  # e.g. params:
27
12
  # {