quandl 0.2.22

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +16 -0
  3. data/.travis.yml +20 -0
  4. data/Gemfile +14 -0
  5. data/Guardfile +8 -0
  6. data/LICENSE +7 -0
  7. data/README.md +316 -0
  8. data/Rakefile +39 -0
  9. data/UPGRADE.md +143 -0
  10. data/bin/quandl +26 -0
  11. data/dist/resources/pkg/Distribution.erb +15 -0
  12. data/dist/resources/pkg/PackageInfo.erb +6 -0
  13. data/dist/resources/pkg/postinstall +45 -0
  14. data/dist/resources/pkg/quandl +25 -0
  15. data/dist/resources/ruby/PackageInfo +3 -0
  16. data/lib/commander/command/quandl_ext.rb +21 -0
  17. data/lib/quandl/command.rb +45 -0
  18. data/lib/quandl/command/client_ext.rb +1 -0
  19. data/lib/quandl/command/client_ext/user.rb +11 -0
  20. data/lib/quandl/command/compatibility_check.rb +11 -0
  21. data/lib/quandl/command/qconfig.rb +76 -0
  22. data/lib/quandl/command/tasks.rb +15 -0
  23. data/lib/quandl/command/tasks/base.rb +263 -0
  24. data/lib/quandl/command/tasks/delete.rb +58 -0
  25. data/lib/quandl/command/tasks/download.rb +111 -0
  26. data/lib/quandl/command/tasks/info.rb +46 -0
  27. data/lib/quandl/command/tasks/list.rb +40 -0
  28. data/lib/quandl/command/tasks/login.rb +46 -0
  29. data/lib/quandl/command/tasks/update.rb +205 -0
  30. data/lib/quandl/command/tasks/upload.rb +69 -0
  31. data/lib/quandl/command/version.rb +5 -0
  32. data/lib/quandl/utility.rb +2 -0
  33. data/lib/quandl/utility/config.rb +43 -0
  34. data/lib/quandl/utility/ruby_version.rb +143 -0
  35. data/quandl.gemspec +39 -0
  36. data/scripts/compile_ruby_pkg.sh +34 -0
  37. data/scripts/install.sh +51 -0
  38. data/scripts/win/quandl_toolbelt.iss +82 -0
  39. data/spec/lib/quandl/command/delete_spec.rb +31 -0
  40. data/spec/lib/quandl/command/download_spec.rb +42 -0
  41. data/spec/lib/quandl/command/upload_spec.rb +39 -0
  42. data/spec/lib/quandl/command_spec.rb +46 -0
  43. data/spec/spec_helper.rb +20 -0
  44. data/tasks/toolbelt.rake +133 -0
  45. data/tasks/toolbelt.rb +92 -0
  46. data/tasks/toolbelt/build.rb +2 -0
  47. data/tasks/toolbelt/build/darwin.rb +71 -0
  48. data/tasks/toolbelt/build/ruby.rb +105 -0
  49. data/tasks/toolbelt/build/tarball.rb +73 -0
  50. data/tasks/toolbelt/build/windows.rb +25 -0
  51. data/tasks/toolbelt/push.rb +15 -0
  52. data/tasks/toolbelt/storage.rb +28 -0
  53. data/tasks/toolbelt/tar.rb +21 -0
  54. metadata +354 -0
@@ -0,0 +1,46 @@
1
+ class Quandl::Command::Tasks::Info < Quandl::Command::Tasks::Base
2
+
3
+ description "Display information about the Quandl Toolbelt."
4
+
5
+ def execute
6
+ info title "Quandl Toolbelt"
7
+ info current_user.info
8
+ info toolbelt_info
9
+
10
+ debug title "Package Versions"
11
+ debug package_info
12
+ end
13
+
14
+ def title(name)
15
+ name = name.to_s
16
+ "\n#{name}\n" + ( name.length.times.collect{'='}.join )
17
+ end
18
+
19
+ def user_info
20
+ [
21
+ "username: #{current_user.username}",
22
+ "email: #{current_user.email}",
23
+ ].join("\n")
24
+ end
25
+
26
+ def toolbelt_info
27
+ [
28
+ "host: #{quandl_url}",
29
+ "token: #{auth_token}",
30
+ "version: #{Quandl::Command::VERSION}",
31
+ ].join("\n")
32
+ end
33
+
34
+ def package_info
35
+ quandl_package_versions.sort_by{|p| p[:package].to_s }.collect{|p| "#{ p[:package] } ( #{ p[:version] } )" }.join("\n")
36
+ end
37
+
38
+ def quandl_package_versions
39
+ Quandl.constants.collect do |c|
40
+ package = "Quandl::#{c}".constantize
41
+ version = "Quandl::#{c}::VERSION".constantize rescue nil
42
+ { package: package, version: version } unless version.nil?
43
+ end.compact
44
+ end
45
+
46
+ end
@@ -0,0 +1,40 @@
1
+ class Quandl::Command::Tasks::List < Quandl::Command::Tasks::Base
2
+
3
+ description "List datasets matching conditions."
4
+ options({
5
+ String => {
6
+ match: "Only return datasets matching: [match]",
7
+ source_code: "Return datasets matching: [SOURCE_CODE]"
8
+ },
9
+ Integer => {
10
+ limit: "How datasets to return per page.",
11
+ page: "Return datasets starting from: [page]",
12
+ }
13
+ })
14
+
15
+ authenticated_users_only!
16
+
17
+ def execute
18
+ # find dataset
19
+ debug "search_params: #{search_params}"
20
+ dataset = Quandl::Client::Dataset.where( search_params ).fetch
21
+ codes = dataset.collect(&:full_code)
22
+ # fail on errors
23
+ info codes.join("\n")
24
+ end
25
+
26
+ def search_params
27
+ search_params = {}
28
+ search_params[:query] = options.match if options.match.present?
29
+ search_params[:source_code] = options.source_code.to_s.upcase if options.source_code.present?
30
+ search_params[:per_page] = options.limit if options.limit.present?
31
+ search_params[:page] = page
32
+ search_params[:self_search] = search_params[:source_code].present? ? false : true
33
+ search_params
34
+ end
35
+
36
+ def page
37
+ options.page.to_i || 1
38
+ end
39
+
40
+ end
@@ -0,0 +1,46 @@
1
+ class Quandl::Command::Tasks::Login < Quandl::Command::Tasks::Base
2
+
3
+ description "Login to quandl with username and email."
4
+
5
+ options String => { method: 'Login method? ( password | token )' }
6
+
7
+ def execute
8
+ authenticate!
9
+ reload_session!
10
+ if current_user.present?
11
+ info "You have successfully authenticated!"
12
+ info current_user.info
13
+ else
14
+ error "Failed to authenticate!"
15
+ end
16
+ end
17
+
18
+ def authenticate!
19
+ return execute_password_login if options.method == 'password'
20
+ execute_token_login
21
+ end
22
+
23
+ def execute_token_login
24
+ info("Obtain your Auth Token from this page: http://www.quandl.com/users/info")
25
+ token = ask("Auth Token: "){ |q| q.echo = "*" }
26
+ write_auth_token(token)
27
+ end
28
+
29
+ def execute_password_login
30
+ # request login and password
31
+ login = ask("Username or Email: ")
32
+ password = ask("Password: "){ |q| q.echo = "*" }
33
+ # attempt to login
34
+ user = Quandl::Client::User.login( login: login, password: password )
35
+ # fail on errors
36
+ return error( user.human_status ) unless user.auth_token.present?
37
+ # output qdf
38
+ write_auth_token(user.auth_token)
39
+ info "You've successfully authorized #{login}!"
40
+ end
41
+
42
+ def write_auth_token(token)
43
+ QConfig.configuration.token = token
44
+ end
45
+
46
+ end
@@ -0,0 +1,205 @@
1
+ class Quandl::Command::Tasks::Update < Quandl::Command::Tasks::Base
2
+
3
+ # curl -s https://s3.amazonaws.com/quandl-command/install.sh | bash
4
+
5
+ description "Update Quandl Toolbelt to the latest version."
6
+ syntax %Q{quandl update [revision]
7
+
8
+ Examples:
9
+
10
+ $ quandl update
11
+ Updating from 0.2.18 ...
12
+ You are up to date! ( 0.3.1 )
13
+
14
+ $ quandl update beta1
15
+ Updating from 0.3.1 ...
16
+ You are up to date! ( 0.3.1-beta1 )}
17
+
18
+ PACKAGE_URL = 'http://s3.amazonaws.com/quandl-command/'
19
+
20
+ class << self
21
+ def package_url(revision=nil)
22
+ # are we on windows?
23
+ platform = Quandl::Utility::Config.windows? ? 'windows' : nil
24
+ # build filename
25
+ filename = ['quandl-command', platform, revision, 'tar.gz'].compact.join(".")
26
+ # append s3 url
27
+ File.join(PACKAGE_URL, filename)
28
+ end
29
+ end
30
+
31
+ def execute
32
+ # load libraries needed by this action
33
+ require_dependencies
34
+ return unless assert_update_requirements!
35
+ info "Updating from #{Quandl::Command::VERSION} ... "
36
+ # wipe update/ and backup/ folders
37
+ prepare_for_update
38
+ download_tarball
39
+ # ensure package was downloaded
40
+ return error("'#{package_url}' not found") unless File.exists?(tarball_path)
41
+ # install
42
+ extract_tarball
43
+ copy_windows_specific_files if Quandl::Utility::Config.windows?
44
+ install_update
45
+ configure_update
46
+ ensure_correct_permissions
47
+ # success
48
+ version = %x{quandl -v}.to_s.strip.rstrip
49
+ info "You are up to date! ( #{version} )"
50
+
51
+ rescue => err
52
+ # log error
53
+ error(err)
54
+ debug(err.backtrace.join("\n"))
55
+ # report failure and rollback
56
+ info("----\nAn error has occured! Rolling back to previous version ... ")
57
+ info("If the problem persists reinstall with: #{installer_url}")
58
+ rollback_update
59
+ end
60
+
61
+ def installer_url
62
+ return File.join(PACKAGE_URL, "Quandl Setup.exe") if Quandl::Utility::Config.windows?
63
+ return File.join(PACKAGE_URL, "quandl-toolbelt.pkg") if Quandl::Utility::Config.macosx?
64
+ end
65
+
66
+ def package_path
67
+ @package_path ||= File.join(update_path, "quandl-command")
68
+ end
69
+
70
+ def tarball_path
71
+ @tarball_path ||= File.join(update_path, "update.tar.gz")
72
+ end
73
+
74
+ def package_url
75
+ @package_url ||= self.class.package_url(args.first)
76
+ end
77
+
78
+ def update_path
79
+ @update_path ||= File.join( root_path, 'update' )
80
+ end
81
+
82
+ def backup_path
83
+ @backup_path ||= File.join( root_path, 'backup' )
84
+ end
85
+
86
+ def root_path
87
+ Quandl::Command::Tasks.root
88
+ end
89
+
90
+
91
+ private
92
+
93
+ def require_dependencies
94
+ require 'quandl/utility/config'
95
+ require 'zlib'
96
+ require 'archive/tar/minitar'
97
+ end
98
+
99
+ def assert_update_requirements!
100
+ return fatal("update is destructive and disabled in development!") if Dir.exists?(File.join(root_path, ".git"))
101
+ true
102
+ end
103
+
104
+ def prepare_for_update
105
+ [backup_path, update_path].each do |path|
106
+ # remove previous directory if present
107
+ rm_rf(path) if Dir.exists?(path)
108
+ # create new directory
109
+ mkdir_p(path) unless Dir.exists?(path)
110
+ end
111
+ end
112
+
113
+ def download_tarball
114
+ debug "Downloading '#{package_url}' to '#{tarball_path}'"
115
+ # download new package
116
+ uri = URI( package_url )
117
+ # open connection to storage host
118
+ Net::HTTP.start( uri.host, uri.port ) do |http|
119
+ # download file
120
+ resp = http.get( uri.path )
121
+ # write tar file if it was found
122
+ open( tarball_path, "wb"){|f| f.write(resp.body) } unless resp.code == '404'
123
+ end
124
+ end
125
+
126
+ def extract_tarball
127
+ debug "Archive::Tar::Minitar.unpack( '#{tarball_path}', '#{update_path}' )"
128
+ # extract into update_path
129
+ Archive::Tar::Minitar.unpack( Zlib::GzipReader.open(tarball_path), update_path )
130
+ end
131
+
132
+ def copy_windows_specific_files
133
+ files = ['bin/quandl.bat']
134
+ files.each do |file|
135
+ source_path = File.join(root_path, file)
136
+ cp source_path, File.join(package_path, file) if File.exists?(source_path)
137
+ end
138
+ end
139
+
140
+ def install_update
141
+ debug "Installing '#{update_path}' to '#{root_path}'"
142
+ # install each folder into the live directory
143
+ Dir.glob(File.join(package_path, "/*")) do |update_dir|
144
+ # current folder
145
+ folder_name = File.basename(update_dir)
146
+ # get live dir
147
+ live_dir = File.join(root_path, folder_name )
148
+ # move live to backup (skip this step if it doesn't exist since it might be a new folder)
149
+ mv live_dir, File.join(backup_path, folder_name) if File.exists?(live_dir)
150
+ # move update to live
151
+ mv update_dir, live_dir
152
+ end
153
+ end
154
+
155
+ def configure_update
156
+ if Dir.exists?("#{root_path}/ruby")
157
+ bin_file = File.read("#{root_path}/bin/quandl")
158
+ bin_file.gsub!("#!/usr/bin/env ruby", "#!/#{root_path}/ruby/bin/ruby")
159
+ File.write("#{root_path}/bin/quandl", bin_file)
160
+ end
161
+ end
162
+
163
+ def rollback_update
164
+ Dir.glob(File.join(backup_path, "/*")) do |backup_dir|
165
+ # current folder
166
+ folder_name = File.basename(backup_dir)
167
+ # get live dir
168
+ live_dir = File.join(root_path, folder_name )
169
+ # move live to update
170
+ mv live_dir, File.join(package_path, folder_name)
171
+ # move backup to live
172
+ mv backup_dir, live_dir
173
+ end
174
+ end
175
+
176
+ def ensure_correct_permissions
177
+ chmod("+x", File.join(root_path, 'bin/quandl'))
178
+ end
179
+
180
+ def chmod(*args)
181
+ debug("FileUtils.chmod #{args.to_a.join(' ')}")
182
+ FileUtils.chmod(*args)
183
+ end
184
+
185
+ def cp(old_path, new_path)
186
+ debug("FileUtils.cp #{old_path} #{new_path}")
187
+ FileUtils.cp( old_path, new_path )
188
+ end
189
+
190
+ def mv(old_path, new_path)
191
+ debug("FileUtils.mv #{old_path} #{new_path}")
192
+ FileUtils.mv( old_path, new_path )
193
+ end
194
+
195
+ def rm_rf(*args)
196
+ debug( "FileUtils.rm_rf #{args.to_a.join(" ")}")
197
+ FileUtils.rm_rf(*args)
198
+ end
199
+
200
+ def mkdir_p(*args)
201
+ debug( "FileUtils.mkdir_p #{args.to_a.join(" ")}")
202
+ FileUtils.mkdir_p(*args)
203
+ end
204
+
205
+ end
@@ -0,0 +1,69 @@
1
+ class Quandl::Command::Tasks::Upload < Quandl::Command::Tasks::Base
2
+
3
+ description "Upload a dataset using its quandl code."
4
+ syntax %{quandl upload file.qdf
5
+
6
+ Examples:
7
+
8
+ $ quandl upload file.qcsv
9
+ OK | 98ms | http://quandl.com/USERNAME/CODE_1
10
+ OK | 72ms | http://quandl.com/USERNAME/CODE_2
11
+
12
+ $ ruby code.rb | quandl upload
13
+ OK | 98ms | http://quandl.com/USERNAME/CODE_1
14
+ OK | 72ms | http://quandl.com/USERNAME/CODE_2
15
+
16
+ Quandl CSV Format:
17
+
18
+ code: YOUR_QUANDL_CODE
19
+ name: Dataset Title
20
+ description: Dataset description.
21
+ private: false
22
+ -
23
+ Date, First, Second, Third
24
+ 2013-11-22,1252.0,454.95,448.2
25
+ 2013-11-21,452.25,457.75,449.1
26
+ }
27
+ options({
28
+ Integer => {
29
+ threads: "How many workers to use during download.",
30
+ }
31
+ })
32
+
33
+ authenticated_users_only!
34
+
35
+ def execute
36
+ # datasets from file_path if given
37
+ interface = file_path.present? ? File.open(file_path, "r") : $stdin
38
+ # for each dataset streamed from interface
39
+ Quandl::Format::Dataset.each_line(interface) do |dataset|
40
+ pool.process{ upload( dataset ) }
41
+ end
42
+ pool.shutdown
43
+ end
44
+
45
+ def upload(dataset)
46
+ # display debug info when verbose
47
+ debug dataset.attributes.to_s
48
+ # upload
49
+ dataset.upload if dataset.valid?
50
+ # output report to $stdout or $stderr
51
+ report(dataset)
52
+ end
53
+
54
+ def report(dataset)
55
+ if [200,201].include?( dataset.client.status )
56
+ info table dataset.client.human_status,
57
+ dataset.client.elapsed_request_time_ms,
58
+ dataset.client.full_url
59
+ else
60
+ error(dataset.human_errors)
61
+ end
62
+ debug "---"
63
+ end
64
+
65
+ def file_path
66
+ args.first
67
+ end
68
+
69
+ end
@@ -0,0 +1,5 @@
1
+ module Quandl
2
+ module Command
3
+ VERSION = '0.2.22'
4
+ end
5
+ end
@@ -0,0 +1,2 @@
1
+ module Quandl::Utility
2
+ end
@@ -0,0 +1,43 @@
1
+ require 'rbconfig'
2
+
3
+ module Quandl::Utility
4
+ module Config
5
+ class << self
6
+
7
+ def windows?
8
+ host_os == :windows
9
+ end
10
+
11
+ def macosx?
12
+ host_os == :macosx
13
+ end
14
+
15
+ def linux?
16
+ host_os == :linux
17
+ end
18
+
19
+ def unix?
20
+ host_os == :unix
21
+ end
22
+
23
+ def host_os
24
+ @os ||= (
25
+ host_os = RbConfig::CONFIG['host_os']
26
+ case host_os
27
+ when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
28
+ :windows
29
+ when /darwin|mac os/
30
+ :macosx
31
+ when /linux/
32
+ :linux
33
+ when /solaris|bsd/
34
+ :unix
35
+ else
36
+ raise Error::WebDriverError, "unknown os: #{host_os.inspect}"
37
+ end
38
+ )
39
+ end
40
+
41
+ end
42
+ end
43
+ end