cnvrg 0.0.1412 → 0.0.1414

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
  SHA1:
3
- metadata.gz: af467f0b591d7f5b4c48f1ea659ce6a8af10fa4a
4
- data.tar.gz: a24c8338c54b12502ad9139f0fd12bd8865c5dc1
3
+ metadata.gz: a3a999e3ce7616d42f0a81033156a8d5819b68fd
4
+ data.tar.gz: 5dfc8054f9ee3f38cefaef9a06b113f72e3d12ba
5
5
  SHA512:
6
- metadata.gz: 560278384f51b69ec1a01c629a9089e48d93b5c6630ae5e406f4de697e593cd6b7368c1634f7a66a8d0f0c6446823f3682121ac14fc936738b2d3b87d8dbbd22
7
- data.tar.gz: 76a8f5b59fe26c179496105ee28efd6103ccf32abfb088759424c4bf52a15dc7b8a7934cf8f72cf8cd7e50323e9455dda0ac02b7283dcada0478a0eb71b2ac01
6
+ metadata.gz: cd4af46476dcb927770dd1c88c782ab9d2125e94cc496441f8b465b8edbcd22a2dd02d9d5dbb299c2aa1ac9fa183b2ece4c802f2041b243949a1bf385c317877
7
+ data.tar.gz: 2ec0f4e18e2571ce46dd77fa20bf7b6d5b5e667c4d76816502d5e86799c47417a0faec100c46d97566278fa4d68ce4779ead5e4e320ce767a6da711b3fc2d721
data/lib/cnvrg/cli.rb CHANGED
@@ -55,6 +55,7 @@ class Thor
55
55
  # with pre-parsed options.
56
56
  array_options = []
57
57
  hash_options = local_options
58
+
58
59
  end
59
60
 
60
61
  # Let Thor::Options parse the options first, so it can remove
@@ -63,32 +64,36 @@ class Thor
63
64
  stop_on_unknown = Thor.stop_on_unknown_option? config[:current_command]
64
65
  opts = Thor::Options.new(parse_options, hash_options, stop_on_unknown)
65
66
  real_options = []
66
- if args.empty?
67
- real_args = [].replace(array_options)
68
67
 
69
- array_options.each_with_index do |p,i|
70
- if !p.starts_with? "--" and !p.starts_with? "-"
71
- break
72
- else
73
- real_options << p
74
- if !p.include? "="
75
- if i+1< array_options.size
76
- real_options << array_options[i+1]
77
- real_args.delete(array_options[i+1])
68
+ real_args = [].replace(array_options)
69
+ if local_options.is_a? (Array) and !local_options.empty?
70
+ array_options.each_with_index do |p, i|
71
+ opt = p
72
+ if p.include? "="
73
+ opt = p.split("=")[0]
74
+ end
75
+ option = is_option(parse_options.values, opt)
76
+ if !option
77
+ break
78
+ else
79
+ real_options << p
80
+ real_args.delete(p)
81
+ if !p.include? "=" and option.type != :boolean
82
+ if i+1< array_options.size
83
+ real_options << array_options[i+1]
84
+ real_args.delete(array_options[i+1])
85
+ end
78
86
  end
87
+
79
88
  end
80
- real_args.delete(p)
81
89
 
82
90
  end
83
- end
84
- args = real_args
85
- else
86
- if local_options.is_a? Array
87
- args = [args + local_options].flatten
88
- end
89
91
 
92
+ args = real_args
93
+ else
90
94
  end
91
95
 
96
+
92
97
  self.options = opts.parse(real_options)
93
98
  self.options = config[:class_options].merge(options) if config[:class_options]
94
99
 
@@ -101,19 +106,26 @@ class Thor
101
106
  # arguments declared using #argument (this is primarily used
102
107
  # by Thor::Group). Tis will leave us with the remaining
103
108
  # positional arguments.
104
- to_parse = args
109
+ to_parse = args
105
110
  to_parse += opts.remaining unless self.class.strict_args_position?(config)
106
111
  thor_args = Thor::Arguments.new(self.class.arguments)
107
112
  thor_args.parse(to_parse).each { |k, v| __send__("#{k}=", v) }
108
113
  @args = thor_args.remaining
109
114
  end
110
115
 
116
+ def is_option (options, p)
117
+ options.each do |o|
118
+ if (!o.aliases.nil? and o.aliases[0].split(",").include? p) or o.switch_name.eql? p
119
+ return o
120
+ end
121
+ end
122
+ return false
123
+ end
124
+
111
125
  end
112
126
  end
113
127
 
114
128
 
115
-
116
-
117
129
  module Cnvrg
118
130
 
119
131
  class CLI < Thor
@@ -235,61 +247,65 @@ module Cnvrg
235
247
  desc 'set_default_owner', 'set default owner'
236
248
 
237
249
  def set_default_owner
250
+ begin
251
+ path = File.expand_path('~')+"/.cnvrg/config.yml"
252
+ if !File.exist?(path)
253
+ say "Couldn't find ~/.cnvrg/config.yml file, please logout and login again", Thor::Shell::Color::RED
238
254
 
239
- path = File.expand_path('~')+"/.cnvrg/config.yml"
240
- if !File.exist?(path)
241
- say "Couldn't find ~/.cnvrg/config.yml file, please logout and login again", Thor::Shell::Color::RED
242
-
243
- exit(0)
244
- end
245
- config = YAML.load_file(path)
246
-
247
- username = config.to_h[:username]
248
- res = Cnvrg::API.request("/users/#{username}/get_possible_owners", 'GET')
249
- if Cnvrg::CLI.is_response_success(res)
250
- owner = username
251
- result = res["result"]
252
- owners = result["owners"]
253
- urls = result["urls"]
254
- choose_owner = result["username"]
255
- if owners.empty?
256
- else
257
- owners << choose_owner
258
- chosen = false
259
- while !chosen
260
- owners_id = owners.each_with_index.map { |x, i| "#{i+1}. #{x}" }
261
- choose_owner = ask("Choose default owner:\n"+owners_id.join("\n")+"\n")
262
-
263
- if choose_owner =~ /[[:digit:]]/
264
- ow_index = choose_owner.to_i-1
265
- if ow_index<0 or ow_index >= owners.size
266
- say "No such owner, please choose again", Thor::Shell::Color::BLUE
267
- chosen = false
268
- next
269
- end
270
- choose_owner = owners[choose_owner.to_i-1]
271
- chosen = true
255
+ exit(0)
256
+ end
257
+ config = YAML.load_file(path)
272
258
 
273
- else
259
+ username = config.to_h[:username]
260
+ res = Cnvrg::API.request("/users/#{username}/get_possible_owners", 'GET')
261
+ if Cnvrg::CLI.is_response_success(res)
262
+ owner = username
263
+ result = res["result"]
264
+ owners = result["owners"]
265
+ urls = result["urls"]
266
+ choose_owner = result["username"]
267
+ if owners.empty?
268
+ else
269
+ owners << choose_owner
270
+ chosen = false
271
+ while !chosen
272
+ owners_id = owners.each_with_index.map { |x, i| "#{i+1}. #{x}" }
273
+ choose_owner = ask("Choose default owner:\n"+owners_id.join("\n")+"\n")
274
+
275
+ if choose_owner =~ /[[:digit:]]/
276
+ ow_index = choose_owner.to_i-1
277
+ if ow_index<0 or ow_index >= owners.size
278
+ say "No such owner, please choose again", Thor::Shell::Color::BLUE
279
+ chosen = false
280
+ next
281
+ end
282
+ choose_owner = owners[choose_owner.to_i-1]
283
+ chosen = true
274
284
 
275
- owners_lower = owners.map { |o| o.downcase }
276
- ow_index = owners_lower.index(choose_owner.downcase)
277
- if ow_index.nil?
278
- say "Could not find owner named #{choose_owner}", Thor::Shell::Color::RED
279
285
  else
280
- chosen = true
286
+
287
+ owners_lower = owners.map { |o| o.downcase }
288
+ ow_index = owners_lower.index(choose_owner.downcase)
289
+ if ow_index.nil?
290
+ say "Could not find owner named #{choose_owner}", Thor::Shell::Color::RED
291
+ else
292
+ chosen = true
293
+ end
281
294
  end
282
- end
283
295
 
284
- end
296
+ end
285
297
 
286
298
 
299
+ end
300
+ if set_owner(choose_owner, result["username"], urls[ow_index])
301
+ say "Setting default owner: #{choose_owner}", Thor::Shell::Color::GREEN
302
+ else
303
+ say "Setting default owenr has failed, try to run cnvrg --config-default-owner", Thor::Shell::Color::RED
304
+ end
287
305
  end
288
- if set_owner(choose_owner, result["username"], urls[ow_index])
289
- say "Setting default owner: #{choose_owner}", Thor::Shell::Color::GREEN
290
- else
291
- say "Setting default owenr has failed, try to run cnvrg --config-default-owner", Thor::Shell::Color::RED
292
- end
306
+ rescue SignalException
307
+ say "\nAborting"
308
+ exit(1)
293
309
  end
294
310
  end
295
311
 
@@ -721,7 +737,7 @@ module Cnvrg
721
737
  say "Downloading data", Thor::Shell::Color::BLUE
722
738
 
723
739
 
724
- download_data(false, false, path = working_dir,in_dir=false)
740
+ download_data(false, false, path = working_dir, in_dir=false)
725
741
 
726
742
 
727
743
  check = Helpers.checkmark
@@ -811,7 +827,7 @@ module Cnvrg
811
827
  method_option :verbose, :type => :boolean, :aliases => ["-v"], :default => false
812
828
  method_option :sync, :type => :boolean, :aliases => ["-s"], :default => false
813
829
 
814
- def download_data(verbose, sync, path=Dir.pwd,in_dir=true)
830
+ def download_data(verbose, sync, path=Dir.pwd, in_dir=true)
815
831
  begin
816
832
  verify_logged_in(in_dir)
817
833
  log_start(__method__, args, options)
@@ -1183,7 +1199,7 @@ module Cnvrg
1183
1199
 
1184
1200
 
1185
1201
  @files.rollback_commit(commit_sha1)
1186
- say "Rolling Back all changes.", Thor::Shell::Color::RED
1202
+ say "Can't upload, Rolling Back all changes.", Thor::Shell::Color::RED
1187
1203
  exit(1)
1188
1204
  end
1189
1205
 
@@ -1193,7 +1209,7 @@ module Cnvrg
1193
1209
 
1194
1210
 
1195
1211
  @files.rollback_commit(commit_sha1)
1196
- say "Rolling Back all changes.", Thor::Shell::Color::RED
1212
+ say "Can't upload, Rolling Back all changes.", Thor::Shell::Color::RED
1197
1213
  exit(1)
1198
1214
  end
1199
1215
 
@@ -2060,34 +2076,32 @@ module Cnvrg
2060
2076
  options_hash = Hash[options]
2061
2077
  real_options = []
2062
2078
  options_hash.each do |o|
2063
- real_options << o if (!o[1].eql? "" and !["small","medium","large","gpu","gpuxl","gpuxxl"].include? o[0])
2079
+ real_options << o if (!o[1].eql? "" and !["small", "medium", "large", "gpu", "gpuxl", "gpuxxl"].include? o[0])
2064
2080
  end
2065
2081
  if local
2066
- exec_options = real_options.map { |x| "--#{x[0]}=#{x[1]}" }.flatten.join(" ")
2067
- cmd_to_exec = "#{exec_options} #{cmd.join(" ")}"
2068
- return exec(cmd_to_exec)
2082
+ invoke :exec, cmd, :sync_before => sync_before, :sync_after => sync_after, :title => title,
2083
+ :log => log, :email_notification => email_notification, :upload_output => upload_output,
2084
+ :commit => commit, :image => image, :data => data, :data_commit => data_commit, :ignore => ignore
2085
+ return
2069
2086
  else
2070
- real_options.delete(["local",false])
2087
+ real_options.delete(["local", false])
2071
2088
  instances = {"small" => options["small"], "medium" => options["medium"], "large" => options["large"],
2072
- "gpu" => options["gpu"], "gpuxl" => options["gpuxl"], "gpuxxl" => options["gpuxxl"]}
2089
+ "gpu" => options["gpu"], "gpuxl" => options["gpuxl"], "gpuxxl" => options["gpuxxl"]}
2073
2090
  instance_type = get_instance_type(instances)
2074
2091
  if !instance_type.nil? and !instance_type.empty?
2075
- real_options << ["machine_type",instance_type]
2076
- end
2077
- exec_options = real_options.map { |x| "--#{x[0]}=#{x[1]}" }.flatten.join(" ")
2078
- cmd_to_exec = "#{exec_options} #{cmd.join(" ")}"
2079
- return exec_remote(cmd_to_exec)
2080
- # invoke :exec_remote, [cmd_to_exec], :sync_before => sync_before, :sync_after => sync_after, :title => title, :machine_type => instance_type,
2081
- # :schedule => schedule, :log => log, :email_notification => email_notification, :upload_output => upload_output, :commit => commit,
2082
- # :image => image, :grid => grid, :data => data, :data_commit => data_commit, :ignore => ignore
2083
- # return
2092
+ real_options << ["machine_type", instance_type]
2093
+ end
2094
+ # exec_options = real_options.map { |x| "--#{x[0]}=#{x[1]}" }.flatten.join(" ")
2095
+ # cmd_to_exec = "#{exec_options} #{cmd.join(" ")}"
2096
+ # return exec_remote(cmd_to_exec)
2097
+ invoke :exec_remote, cmd, :sync_before => sync_before, :sync_after => sync_after, :title => title, :machine_type => instance_type,
2098
+ :schedule => schedule, :log => log, :email_notification => email_notification, :upload_output => upload_output, :commit => commit,
2099
+ :image => image, :grid => grid, :data => data, :data_commit => data_commit, :ignore => ignore
2100
+ return
2084
2101
  end
2085
2102
 
2086
2103
  # if local
2087
- # invoke :exec, [cmd_to_exec.split(" ")], :sync_before => sync_before, :sync_after => sync_after, :title => title,
2088
- # :log => log, :email_notification => email_notification, :upload_output => upload_output,
2089
- # :commit => commit, :image => image, :data => data, :data_commit => data_commit, :ignore => ignore
2090
- # return
2104
+ #
2091
2105
  # else
2092
2106
 
2093
2107
 
@@ -2100,41 +2114,21 @@ module Cnvrg
2100
2114
 
2101
2115
 
2102
2116
  desc '', '', :hide => true
2103
- method_option :sync_before, :type => :boolean, :aliases => ["-sb"], :default => true
2104
- method_option :sync_after, :type => :boolean, :aliases => ["-sa"], :default => true
2117
+ method_option :sync_before, :type => :boolean, :aliases => ["-sb,--sync_before"], :default => true
2118
+ method_option :sync_after, :type => :boolean, :aliases => ["-sa,--sync_after"], :default => true
2105
2119
  method_option :title, :type => :string, :aliases => ["-t"], :default => ""
2106
2120
  method_option :log, :type => :boolean, :aliases => ["-l", "--log"], :default => false
2107
- method_option :email_notification, :type => :boolean, :aliases => ["-en"], :default => false
2108
- method_option :upload_output, :type => :string, :aliases => ["-uo"], :default => ""
2121
+ method_option :email_notification, :type => :boolean, :aliases => ["-en,--email_notification"], :default => false
2122
+ method_option :upload_output, :type => :string, :aliases => ["-uo,--upload_output"], :default => ""
2109
2123
  method_option :commit, :type => :string, :aliases => ["-c"], :default => ""
2110
2124
  method_option :image, :type => :string, :aliases => ["-i"], :default => ""
2111
- method_option :indocker, :type => :boolean, :default => false
2125
+ method_option :indocker, :type => :boolean, :aliases => ["--indocker"], :default => false
2112
2126
  method_option :data, :type => :string, :aliases => ["-d", "--data"], :default => ""
2113
2127
  method_option :data_commit, :type => :string, :aliases => ["-dc", "--data_commit"], :default => ""
2114
2128
  method_option :ignore, :type => :string, :aliases => ["-i"], :desc => "ignore following files", :default => ""
2115
2129
 
2116
2130
 
2117
2131
  def exec(*cmd)
2118
- real_cmd = []
2119
- args = [].replace(cmd)
2120
- copy_args = [].replace(cmd)
2121
- args.each_with_index do |p,i|
2122
-
2123
- if !p.starts_with? "--" and !p.starts_with? "-"
2124
- break
2125
- else
2126
- real_cmd << p
2127
- if !p.include? "="
2128
- if i+1< args.size
2129
- real_cmd << args[i+1]
2130
- copy_args.delete(args[i+1])
2131
- end
2132
- end
2133
- copy_args.delete(p)
2134
-
2135
- end
2136
- end
2137
-
2138
2132
  log = []
2139
2133
  cpu_average =0
2140
2134
  memory_average = 0
@@ -2199,7 +2193,7 @@ module Cnvrg
2199
2193
  end
2200
2194
  end
2201
2195
  start_commit = @project.last_local_commit
2202
- cmd = copy_args.join("\s")
2196
+ cmd = cmd.join("\s")
2203
2197
 
2204
2198
  say "Running: #{cmd}\n", Thor::Shell::Color::BLUE
2205
2199
 
@@ -2561,24 +2555,6 @@ module Cnvrg
2561
2555
 
2562
2556
 
2563
2557
  def exec_remote(*cmd)
2564
- real_cmd = []
2565
- args = cmd[0].split(" ")
2566
- copy_args = cmd[0].split(" ")
2567
- args.each_with_index do |p,i|
2568
- if !p.starts_with? "--" and !p.starts_with? "-"
2569
- break
2570
- else
2571
- real_cmd << p
2572
- if !p.include? "="
2573
- if i+1< args.size
2574
- real_cmd << args[i+1]
2575
- copy_args.delete(args[i+1])
2576
- end
2577
- end
2578
- copy_args.delete(p)
2579
-
2580
- end
2581
- end
2582
2558
  verify_logged_in(true)
2583
2559
  log_start(__method__, args, options)
2584
2560
  working_dir = is_cnvrg_dir
@@ -2588,7 +2564,6 @@ module Cnvrg
2588
2564
  grid = options["grid"] || nil
2589
2565
  data = options["data"] || nil
2590
2566
  data_commit = options["data_commit"] || nil
2591
- ignore = options[:ignore] || ""
2592
2567
 
2593
2568
  instance_type = options["machine_type"] || nil
2594
2569
  schedule = options["schedule"] || ""
@@ -2618,9 +2593,9 @@ module Cnvrg
2618
2593
  upload_output_option = "--upload_output=#{upload_output}"
2619
2594
  end
2620
2595
  options_hash = Hash[options]
2621
- options_hash.except!("schedule", "machine_type", "image", "upload_output", "grid", "data", "data_commit", "local","small","medium","large","gpu","gpuxl","gpuxxl")
2596
+ options_hash.except!("schedule", "machine_type", "image", "upload_output", "grid", "data", "data_commit", "local", "small", "medium", "large", "gpu", "gpuxl", "gpuxxl")
2622
2597
  exec_options = options_hash.map { |x| "--#{x[0]}=#{x[1]}" }.flatten.join(" ")
2623
- command = "#{exec_options} #{upload_output_option} #{copy_args.flatten.join(" ")}"
2598
+ command = "#{exec_options} #{upload_output_option} #{cmd.flatten.join(" ")}"
2624
2599
  commit_to_run = options["commit"] || nil
2625
2600
  if !schedule.nil? and !schedule.empty?
2626
2601
 
@@ -2657,7 +2632,6 @@ module Cnvrg
2657
2632
 
2658
2633
  say "Running remote experiment", Thor::Shell::Color::BLUE
2659
2634
  exp = Experiment.new(project.owner, project.slug)
2660
-
2661
2635
  res = exp.exec_remote(command, commit_to_run, instance_type, image_slug, schedule, local_timestamp, grid, path_to_cmd, data, data_commit)
2662
2636
  if Cnvrg::CLI.is_response_success(res)
2663
2637
  # if res["result"]["machine"] == -1
@@ -4727,23 +4701,27 @@ module Cnvrg
4727
4701
  class Data < SubCommandBase
4728
4702
  desc "data init", "init data folder"
4729
4703
  method_option :public, :type => :boolean, :aliases => ["-p", "--public"], :default => false
4704
+
4730
4705
  def init
4731
4706
  cli = Cnvrg::CLI.new()
4732
4707
  public = options["public"]
4733
4708
  cli.init_data(public)
4734
4709
  end
4710
+
4735
4711
  desc "data upload", "upload data folder"
4736
4712
  method_option :ignore, :type => :array, :aliases => ["-i", "--i"], :desc => "ignore following files"
4737
4713
  method_option :verbose, :type => :boolean, :aliases => ["-v"], :default => false
4738
4714
  method_option :sync, :type => :boolean, :aliases => ["-s"], :default => false
4715
+
4739
4716
  def upload
4740
4717
  cli = Cnvrg::CLI.new()
4741
4718
  ignore = options["ignore"]
4742
4719
  verbose = options["verbose"]
4743
4720
  sync = options["sync"]
4744
4721
 
4745
- cli.upload_data_tar(ignore, verbose,sync)
4722
+ cli.upload_data_tar(ignore, verbose, sync)
4746
4723
  end
4724
+
4747
4725
  desc 'data download', 'pull data'
4748
4726
  method_option :verbose, :type => :boolean, :aliases => ["-v"], :default => false
4749
4727
  method_option :sync, :type => :boolean, :aliases => ["-s"], :default => false
@@ -4753,22 +4731,27 @@ module Cnvrg
4753
4731
  verbose = options["verbose"]
4754
4732
  sync = options["sync"]
4755
4733
 
4756
- cli.download_data(verbose,sync,Dir.pwd)
4734
+ cli.download_data(verbose, sync, Dir.pwd)
4757
4735
 
4758
4736
  end
4737
+
4759
4738
  desc 'data clone', 'clone datset'
4739
+
4760
4740
  def clone(dataset_url)
4761
4741
  cli = Cnvrg::CLI.new()
4762
4742
  cli.clone_data(dataset_url)
4763
4743
 
4764
4744
  end
4745
+
4765
4746
  desc 'data list', 'list of datasets'
4747
+
4766
4748
  def list()
4767
4749
  cli = Cnvrg::CLI.new()
4768
4750
 
4769
4751
  cli.list_dataset()
4770
4752
 
4771
4753
  end
4754
+
4772
4755
  desc 'data commits', 'pull data'
4773
4756
 
4774
4757
  def commits()
@@ -249,12 +249,12 @@ module Cnvrg
249
249
 
250
250
  s4cmd=`pip freeze |grep s4cmd > /dev/null 2>&1` ; s4cmd_suc=$?.success?
251
251
  if !s4cmd_suc
252
- `pip install s4cmd > /dev/null 2>&1`
252
+ `pip install s4cmd > /dev/null 2>&1` ; s4cmd_install_suc=$?.success?
253
253
  end
254
254
 
255
255
  end
256
256
 
257
- if !is_python
257
+ if !s4cmd_suc or !s4cmd_install_suc
258
258
  s3 = Aws::S3::Resource.new(
259
259
  :access_key_id => URLcrypt.decrypt(upload_resp["result"]["sts_a"]),
260
260
  :secret_access_key => URLcrypt.decrypt(upload_resp["result"]["sts_s"]),
@@ -303,7 +303,7 @@ module Cnvrg
303
303
 
304
304
  return resp
305
305
 
306
- rescue =>e
306
+ rescue
307
307
  if File.exist? tmp
308
308
  FileUtils.rm_rf [tmp]
309
309
  end
data/lib/cnvrg/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module Cnvrg
2
- VERSION = '0.0.1412'
2
+ VERSION = '0.0.1414'
3
3
  end
4
4
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cnvrg
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1412
4
+ version: 0.0.1414
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yochay Ettun
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2017-05-28 00:00:00.000000000 Z
12
+ date: 2017-05-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -359,9 +359,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
359
359
  version: '0'
360
360
  requirements: []
361
361
  rubyforge_project:
362
- rubygems_version: 2.5.1
362
+ rubygems_version: 2.6.3
363
363
  signing_key:
364
364
  specification_version: 4
365
365
  summary: A CLI tool for interacting with cnvrg.io.
366
366
  test_files: []
367
- has_rdoc: