quandl 0.2.22

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 (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