transcriptic 0.1.3 → 0.2.0

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 (40) hide show
  1. checksums.yaml +7 -0
  2. data/bin/transcriptic +2 -4
  3. data/lib/thor/monkies.rb +3 -0
  4. data/lib/thor/monkies/shell.rb +3 -0
  5. data/lib/transcriptic.rb +86 -2
  6. data/lib/transcriptic/auth.rb +2 -63
  7. data/lib/transcriptic/base_generator.rb +25 -0
  8. data/lib/transcriptic/cli.rb +199 -8
  9. data/lib/transcriptic/client.rb +45 -38
  10. data/lib/transcriptic/commands/project.rb +37 -0
  11. data/lib/transcriptic/core_ext.rb +3 -0
  12. data/lib/transcriptic/core_ext/file.rb +7 -0
  13. data/lib/transcriptic/core_ext/file_utils.rb +15 -0
  14. data/lib/transcriptic/core_ext/pathname.rb +13 -0
  15. data/lib/transcriptic/core_ext/string.rb +8 -0
  16. data/lib/transcriptic/dependencies_generator.rb +13 -0
  17. data/lib/transcriptic/errors.rb +32 -0
  18. data/lib/transcriptic/labfile.rb +73 -0
  19. data/lib/transcriptic/project_generator.rb +56 -0
  20. data/lib/transcriptic/sbt.rb +58 -0
  21. data/lib/transcriptic/templates/LICENSE.erb +20 -0
  22. data/lib/transcriptic/templates/Labfile.erb +12 -0
  23. data/lib/transcriptic/templates/README.erb +3 -0
  24. data/lib/transcriptic/templates/app/Main.erb +11 -0
  25. data/lib/transcriptic/templates/project/Build.erb +59 -0
  26. data/lib/transcriptic/templates/project/Dependencies.erb +10 -0
  27. data/lib/transcriptic/templates/project/build.properties +1 -0
  28. data/lib/transcriptic/templates/project/plugins.sbt +5 -0
  29. data/lib/transcriptic/templates/sbt +1 -0
  30. data/lib/transcriptic/{helpers.rb → ui.rb} +124 -109
  31. data/lib/transcriptic/version.rb +2 -1
  32. data/lib/vendor/{transcriptic/okjson.rb → okjson.rb} +0 -0
  33. metadata +203 -46
  34. data/lib/transcriptic/command.rb +0 -233
  35. data/lib/transcriptic/command/base.rb +0 -157
  36. data/lib/transcriptic/command/console.rb +0 -10
  37. data/lib/transcriptic/command/data.rb +0 -29
  38. data/lib/transcriptic/command/help.rb +0 -124
  39. data/lib/transcriptic/command/login.rb +0 -35
  40. data/lib/transcriptic/command/run.rb +0 -108
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ee17a7a6a96eb5b4e97c7162815443cfca424bec
4
+ data.tar.gz: addfe85a94f4b2856ef5f7ac2ac1f72435801ed9
5
+ SHA512:
6
+ metadata.gz: 350b2fdd82bd58ed2fe9427560a5b89b0fc9fcb70a55d1198c9882c06cf833321a2213f7d6d06d09da6ec00386a23af7b87a8a1d20fbe0b9cd8cd277eac3756d
7
+ data.tar.gz: bcd5b9f30c299b61098115c54a017963bb2cccf921bddf121336e21c19405f21a6d110f9fb797a134bce9931f601694d2618ea9e047a31ee5190847d73d65602
data/bin/transcriptic CHANGED
@@ -3,10 +3,8 @@
3
3
  # resolve bin path, ignoring symlinks
4
4
  require "pathname"
5
5
  bin_file = Pathname.new(__FILE__).realpath
6
-
7
- # add self to libpath
8
6
  $:.unshift File.expand_path("../../lib", bin_file)
9
7
 
10
8
  # start up the CLI
11
- require "transcriptic/cli"
12
- Transcriptic::CLI.start(*ARGV)
9
+ require "transcriptic"
10
+ Transcriptic::CLI::Base.start(ARGV)
@@ -0,0 +1,3 @@
1
+ Dir["#{File.dirname(__FILE__)}/monkies/*.rb"].sort.each do |path|
2
+ require "thor/monkies/#{File.basename(path, '.rb')}"
3
+ end
@@ -0,0 +1,3 @@
1
+ require 'transcriptic/ui'
2
+
3
+ Thor::Base.shell.send(:include, Transcriptic::UI)
data/lib/transcriptic.rb CHANGED
@@ -1,3 +1,87 @@
1
- module Transcriptic; end
1
+ require 'digest'
2
+ require 'forwardable'
3
+ require 'hashie'
4
+ require 'json'
5
+ require 'pathname'
6
+ require 'solve'
7
+ require 'thor'
8
+ require 'tmpdir'
9
+ require 'uri'
10
+ require 'zlib'
11
+ require 'celluloid'
12
+ require 'active_support/core_ext'
13
+ require 'chozo/core_ext'
14
+ require 'rexml/document'
15
+ require 'rest-client'
16
+ require 'uri'
17
+ require 'net/http'
18
+ require 'time'
2
19
 
3
- require "transcriptic/client"
20
+ require 'vendor/okjson'
21
+
22
+ require 'transcriptic/version'
23
+ require 'transcriptic/core_ext'
24
+ require 'transcriptic/errors'
25
+ require 'thor/monkies'
26
+
27
+ module Transcriptic
28
+ class << self
29
+ attr_accessor :ui
30
+
31
+ def root
32
+ @root ||= Pathname.new(File.expand_path('../', File.dirname(__FILE__)))
33
+ end
34
+
35
+ def find_labfile(path = Dir.pwd)
36
+ path = Pathname.new(path)
37
+ path.ascend do |potential_root|
38
+ if potential_root.entries.collect(&:to_s).include?('Labfile')
39
+ return potential_root.join('Labfile')
40
+ end
41
+ end
42
+ end
43
+
44
+ def home_directory
45
+ running_on_windows? ? ENV['USERPROFILE'].gsub("\\","/") : ENV['HOME']
46
+ end
47
+
48
+ def running_on_windows?
49
+ RUBY_PLATFORM =~ /mswin32|mingw32/
50
+ end
51
+
52
+ def running_on_a_mac?
53
+ RUBY_PLATFORM =~ /-darwin\d/
54
+ end
55
+
56
+ def transcriptic_path
57
+ ENV['TRANSCRIPTIC_PATH'] || File.expand_path('~/.transcriptic')
58
+ end
59
+
60
+ def ui
61
+ @ui ||= Thor::Base.shell.new
62
+ end
63
+
64
+ def logger
65
+ Celluloid.logger
66
+ end
67
+
68
+ def tmp_dir
69
+ File.join(transcriptic_path, 'tmp')
70
+ end
71
+
72
+ def mktmpdir
73
+ FileUtils.mkdir_p(tmp_dir)
74
+ Dir.mktmpdir(nil, tmp_dir)
75
+ end
76
+
77
+ end
78
+ end
79
+
80
+
81
+ require 'transcriptic/auth'
82
+ require 'transcriptic/labfile'
83
+ require 'transcriptic/project_generator'
84
+ require 'transcriptic/dependencies_generator'
85
+ require 'transcriptic/client'
86
+ require 'transcriptic/sbt'
87
+ require 'transcriptic/cli'
@@ -1,7 +1,3 @@
1
- require "transcriptic"
2
- require "transcriptic/client"
3
- require "transcriptic/helpers"
4
-
5
1
  class Transcriptic::Auth
6
2
  class << self
7
3
  attr_accessor :credentials
@@ -28,8 +24,6 @@ class Transcriptic::Auth
28
24
  @client = nil
29
25
  end
30
26
 
31
- include Transcriptic::Helpers
32
-
33
27
  # just a stub; will raise if not authenticated
34
28
  def check
35
29
  client.list
@@ -59,9 +53,9 @@ class Transcriptic::Auth
59
53
 
60
54
  def credentials_file
61
55
  if host == default_host
62
- "#{home_directory}/.transcriptic/credentials"
56
+ "#{Transcriptic.home_directory}/.transcriptic/credentials"
63
57
  else
64
- "#{home_directory}/.transcriptic/credentials.#{host}"
58
+ "#{Transcriptic.home_directory}/.transcriptic/credentials.#{host}"
65
59
  end
66
60
  end
67
61
 
@@ -138,61 +132,6 @@ class Transcriptic::Auth
138
132
  delete_credentials
139
133
  raise e
140
134
  end
141
- check_for_associated_ssh_key unless Transcriptic::Command.current_command == "keys:add"
142
- end
143
-
144
- def check_for_associated_ssh_key
145
- return unless client.get_keys.length.zero?
146
- associate_or_generate_ssh_key
147
- end
148
-
149
- def associate_or_generate_ssh_key
150
- public_keys = available_ssh_public_keys.sort
151
-
152
- case public_keys.length
153
- when 0 then
154
- display "Could not find an existing public key."
155
- display "Would you like to generate one? [Yn] ", false
156
- unless ask.strip.downcase == "n"
157
- display "Generating new SSH public key."
158
- generate_ssh_key("id_rsa")
159
- associate_key("#{home_directory}/.ssh/id_rsa.pub")
160
- end
161
- when 1 then
162
- display "Found existing public key: #{public_keys.first}"
163
- associate_key(public_keys.first)
164
- else
165
- display "Found the following SSH public keys:"
166
- public_keys.each_with_index do |key, index|
167
- display "#{index+1}) #{File.basename(key)}"
168
- end
169
- display "Which would you like to use with your Transcriptic account? ", false
170
- chosen = public_keys[ask.to_i-1] rescue error("Invalid choice")
171
- associate_key(chosen)
172
- end
173
- end
174
-
175
- def generate_ssh_key(keyfile)
176
- ssh_dir = File.join(home_directory, ".ssh")
177
- unless File.exists?(ssh_dir)
178
- FileUtils.mkdir_p ssh_dir
179
- File.chmod(0700, ssh_dir)
180
- end
181
- `ssh-keygen -t rsa -N "" -f \"#{home_directory}/.ssh/#{keyfile}\" 2>&1`
182
- end
183
-
184
- def associate_key(key)
185
- display "Uploading ssh public key #{key}"
186
- client.add_key(File.read(key)).inspect
187
- end
188
-
189
- def available_ssh_public_keys
190
- keys = [
191
- "#{home_directory}/.ssh/id_rsa.pub",
192
- "#{home_directory}/.ssh/id_dsa.pub"
193
- ]
194
- keys.concat(Dir["#{home_directory}/.ssh/*.pub"])
195
- keys.select { |d| File.exists?(d) }.uniq
196
135
  end
197
136
 
198
137
  def retry_login?
@@ -0,0 +1,25 @@
1
+ require 'thor/group'
2
+
3
+ module Transcriptic
4
+ class BaseGenerator < Thor::Group
5
+ class << self
6
+ def source_root
7
+ Transcriptic.root.join('lib/transcriptic/templates')
8
+ end
9
+ end
10
+
11
+ shell = Transcriptic.ui
12
+
13
+ argument :path,
14
+ type: :string,
15
+ required: true
16
+
17
+ include Thor::Actions
18
+
19
+ private
20
+
21
+ def target
22
+ @target ||= Pathname.new(File.expand_path(path))
23
+ end
24
+ end
25
+ end
@@ -1,12 +1,203 @@
1
- require "transcriptic"
2
- require "transcriptic/command"
1
+ module Transcriptic
2
+ module CLI
3
+ class Base < Thor
4
+ include Transcriptic::UI
3
5
 
4
- class Transcriptic::CLI
6
+ class << self
7
+ def dispatch(meth, given_args, given_opts, config)
8
+ unless (given_args & ['-h', '--help']).empty?
9
+ if given_args.length == 1
10
+ # transcriptic --help
11
+ super
12
+ else
13
+ command = given_args.first
14
+ super(meth, ['help', command].compact, nil, config)
15
+ end
16
+ else
17
+ super
18
+ end
19
+ end
20
+ end
5
21
 
6
- def self.start(*args)
7
- command = args.shift.strip rescue "help"
8
- Transcriptic::Command.load
9
- Transcriptic::Command.run(command, args)
10
- end
22
+ def initialize(*args)
23
+ super(*args)
24
+
25
+ Transcriptic.logger.level = ::Logger::INFO
26
+
27
+ if @options[:debug]
28
+ Transcriptic.logger.level = ::Logger::DEBUG
29
+ end
30
+
31
+ if @options[:quiet]
32
+ Transcriptic.ui.mute!
33
+ end
34
+
35
+ @options = options.dup # unfreeze frozen options Hash from Thor
36
+ end
37
+
38
+ desc "login", "Log in with your Transcriptic account"
39
+ def login
40
+ Transcriptic::Auth.login
41
+ say "Authentication successful."
42
+ end
43
+
44
+ desc "logout", "Clear local authentication credentials"
45
+ def logout
46
+ Transcriptic::Auth.logout
47
+ say "Local credentials cleared."
48
+ end
49
+
50
+ desc "token", "Display your API token"
51
+ def token
52
+ say Transcriptic::Auth.api_key
53
+ end
54
+
55
+ desc "new NAME", "Generate a new project"
56
+ method_option :package,
57
+ type: :string,
58
+ desc: "Package name (example: edu.stanford.professorname.projectname)"
59
+ method_option :email,
60
+ type: :string,
61
+ desc: 'Email address of project author'
62
+ method_option :author,
63
+ type: :string,
64
+ desc: 'Name of project author'
65
+ method_option :description,
66
+ type: :string,
67
+ desc: 'Brief one-line description of the project'
68
+ def new(name)
69
+ Transcriptic::ProjectGenerator.new([File.join(Dir.pwd, name), name], options).invoke_all
70
+ end
71
+
72
+ desc "logs RUNID", "Get log data from a run"
73
+ def logs(run_id)
74
+ transcriptic.read_logs(run_id)
75
+ end
76
+
77
+ desc "status RUNID", "Show status for a given run ID"
78
+ def status(run_id)
79
+ ret = transcriptic.status(run_id)
80
+ if ret.nil?
81
+ error "#{run_id} not found for #{transcriptic.user}"
82
+ end
83
+ say(ret.inspect)
84
+ end
11
85
 
86
+ desc "list", "List your in-flight run IDs"
87
+ def list
88
+ ret = transcriptic.list
89
+ if ret.empty?
90
+ say "No runs for #{transcriptic.user}"
91
+ return
92
+ end
93
+ say("Runs:")
94
+ ret.each do |run|
95
+ say " #{run.name}"
96
+ end
97
+ end
98
+
99
+ desc "update", "Update the project's dependencies"
100
+ def update
101
+ require_labfile!
102
+ output_with_arrow "Updating dependencies..."
103
+ labfile = Transcriptic::Labfile.from_file(Transcriptic.find_labfile)
104
+ Transcriptic::DependenciesGenerator.new([Dir.pwd, labfile.dependencies], options).invoke_all
105
+ end
106
+
107
+ desc "compile", "Compile the project"
108
+ def compile
109
+ require_labfile!
110
+ update
111
+ Transcriptic::SBT.compile
112
+ end
113
+
114
+ desc "analyze OBJECTPATH", "Analyze a protocol. Object path is of the form edu.foo.bar where bar is the name of your Protocol object."
115
+ method_options :raw => :boolean, :iterations => :integer
116
+ def analyze(object_path)
117
+ raw = options.raw ? "--raw" : ""
118
+ iterations = options.iterations ? options.iterations : 5
119
+ require_labfile!
120
+ update
121
+ Transcriptic::SBT.stage
122
+ data = `target/start #{object_path} --verify #{raw} --iterations #{iterations}`
123
+ if not options.raw
124
+ json = json_decode(data)
125
+ output_with_arrow "Verification successful for #{object_path}"
126
+ output_with_indent "Expected cost: $#{json["price_avg"]}, maximum observed cost: $#{json["price_max"]}"
127
+ else
128
+ say data
129
+ end
130
+ end
131
+
132
+ desc "publish", "Packages up the current project and uploads it to the Autoprotocol central repository"
133
+ def publish
134
+ labfile = require_labfile!
135
+ if compile
136
+ dependencies = labfile.dependencies.map {|d| "#{d[:group]}.#{d[:name]}/#{d[:version]}" }.join(", ")
137
+ output_with_arrow "Preparing to publish..."
138
+ output_with_arrow "Project name: #{labfile.options[:name]}, Author: #{labfile.options[:author]}, Email: #{labfile.options[:email]}"
139
+ if labfile.options[:description]
140
+ output_with_arrow "Description: #{labfile.options[:description]}"
141
+ else
142
+ display format_with_bang("Warning: No description provided.")
143
+ end
144
+ if labfile.dependencies.length > 0
145
+ output_with_arrow "Dependencies: #{dependencies}}"
146
+ end
147
+ confirm(format_with_bang("Are you sure you want to publish version #{labfile.options[:version]} of this project? (y/N)"))
148
+ output_with_arrow "Not yet available!"
149
+ end
150
+ end
151
+
152
+ desc "launch OBJECTPATH", "Packages up the current project, uploads it to Transcriptic, and starts the protocol object at OBJECTPATH running."
153
+ def launch(object_path)
154
+ require_labfile!
155
+ output_with_arrow "Not yet available!"
156
+ return
157
+
158
+ fd = create_protocol_fd_for_path(path)
159
+ if 1 == fd
160
+ Transcriptic.ui.error_with_failure "Couldn't packaged protocol filename or directory!"
161
+ end
162
+ if args.empty?
163
+ project_id = "default"
164
+ else
165
+ project_id = args.shift
166
+ end
167
+ run = action("Uploading `#{path}`") {
168
+ transcriptic.create_run(fd, project_id)
169
+ }
170
+
171
+ if run["success"]
172
+ Transcriptic.ui.output_with_arrow "Protocol received: #{run["protocol_format"]} detected"
173
+ Transcriptic.ui.output_with_arrow "Protocol received: #{run["nsteps"]} steps, expected cost: #{run["exp_cost"]}, total possible cost: #{run["max_cost"]}"
174
+ Transcriptic.ui.output_with_arrow "Protocol received: expected runtime: #{run["exp_time"]}, total possible runtime: #{run["max_time"]}"
175
+ if Transcriptic.ui.confirm_quote
176
+ Transcriptic.ui.display
177
+ Transcriptic.ui.action("Launching") {
178
+ transcriptic.launch_run(run["run_id"])
179
+ }
180
+ Transcriptic.ui.output_with_arrow "Protocol run launched. ID: #{run["run_id"]}"
181
+ Transcriptic.ui.output_with_arrow "Monitor at: https://secure.transcriptic.com/#{run["organization_id"]}/#{run["project_id"]}/runs/#{run["run_id"]}"
182
+ end
183
+ else
184
+ Transcriptic.ui.error_with_failure "Error creating protocol run."
185
+ end
186
+ end
187
+
188
+ private
189
+ def transcriptic
190
+ Transcriptic::Auth.client
191
+ end
192
+
193
+ def require_labfile!
194
+ labfile = Transcriptic.find_labfile
195
+ if labfile.nil?
196
+ error("Can't find Labfile! You must run this command from within an autoprotocol project directory.")
197
+ end
198
+ Transcriptic::Labfile.from_file(labfile)
199
+ end
200
+
201
+ end
202
+ end
12
203
  end