quandl 0.2.27 → 0.3.0

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 +8 -8
  2. data/README.md +70 -17
  3. data/Rakefile +7 -86
  4. data/UPGRADE.md +23 -0
  5. data/VERSION +1 -0
  6. data/lib/quandl/command.rb +11 -3
  7. data/lib/quandl/command/config.rb +88 -0
  8. data/lib/quandl/command/presenter.rb +74 -0
  9. data/lib/quandl/command/presenter/record.rb +121 -0
  10. data/lib/quandl/command/presenters/dataset_presenter.rb +19 -0
  11. data/lib/quandl/command/presenters/error_presenter.rb +31 -0
  12. data/lib/quandl/command/presenters/nil_class_presenter.rb +10 -0
  13. data/lib/quandl/command/presenters/scraper_presenter.rb +25 -0
  14. data/lib/quandl/command/presenters/superset_presenter.rb +10 -0
  15. data/lib/quandl/command/task.rb +40 -0
  16. data/lib/quandl/command/task/callbacks.rb +47 -0
  17. data/lib/quandl/command/task/clientable.rb +65 -0
  18. data/lib/quandl/command/task/commandable.rb +104 -0
  19. data/lib/quandl/command/task/configurable.rb +79 -0
  20. data/lib/quandl/command/task/inputable.rb +37 -0
  21. data/lib/quandl/command/task/logging.rb +83 -0
  22. data/lib/quandl/command/task/presentation.rb +37 -0
  23. data/lib/quandl/command/task/reportable.rb +35 -0
  24. data/lib/quandl/command/task/threading.rb +117 -0
  25. data/lib/quandl/command/task/translations.rb +37 -0
  26. data/lib/quandl/command/task/updatable.rb +77 -0
  27. data/lib/quandl/command/tasks.rb +6 -5
  28. data/lib/quandl/command/tasks/delete.rb +10 -67
  29. data/lib/quandl/command/tasks/download.rb +11 -78
  30. data/lib/quandl/command/tasks/info.rb +2 -2
  31. data/lib/quandl/command/tasks/list.rb +12 -24
  32. data/lib/quandl/command/tasks/login.rb +4 -4
  33. data/lib/quandl/command/tasks/replace.rb +58 -0
  34. data/lib/quandl/command/tasks/schedule.rb +106 -0
  35. data/lib/quandl/command/tasks/search.rb +39 -0
  36. data/lib/quandl/command/tasks/superset.rb +59 -0
  37. data/lib/quandl/command/tasks/uninstall.rb +1 -1
  38. data/lib/quandl/command/tasks/update.rb +2 -2
  39. data/lib/quandl/command/tasks/upload.rb +13 -26
  40. data/lib/quandl/command/version.rb +1 -1
  41. data/quandl.gemspec +5 -3
  42. data/spec/fixtures/scraper.rb +6 -0
  43. data/spec/lib/quandl/command/delete_spec.rb +19 -11
  44. data/spec/lib/quandl/command/download_spec.rb +11 -4
  45. data/spec/lib/quandl/command/replace_spec.rb +23 -0
  46. data/spec/lib/quandl/command/schedule_spec.rb +53 -0
  47. data/spec/lib/quandl/command/superset_spec.rb +28 -0
  48. data/spec/lib/quandl/command/upload_spec.rb +71 -24
  49. data/spec/lib/quandl/command_spec.rb +1 -9
  50. data/spec/spec_helper.rb +36 -1
  51. data/tasks/toolbelt/build/tarball.rb +2 -2
  52. metadata +55 -10
  53. data/lib/quandl/command/qconfig.rb +0 -86
  54. data/lib/quandl/command/tasks/base.rb +0 -314
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- OWE2ODc2YmIxMGQyNTJlNTUzY2Q1ZTgyNzI2ZjFhMTdhYmI2NTE1Mw==
4
+ MmI3MGNiMmJjYzNkNzU3ZWQzMjE3NTI0ZTlhNmZlMjMxMGNiMTk5NQ==
5
5
  data.tar.gz: !binary |-
6
- NTc0MDA0MzU0YTY5ODJjNmQwYzM1NGI2NDEzYjY0YmQwNDUxYTc2Nw==
6
+ NzUwMGIyYjkxZGRkYTk5ZTc0ZTk3YTFjNzY5YzMzZDQ5OTY3ODNlYg==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- MmNiMzVmODUxNWE1YWJiNjUxY2IwNDRmZDM0Nzk5YzdjNzEwNzgxMzk2YjYx
10
- ZGNlZTA1OWYzZWJhMDVkNmY1MDg0MDFjMzQ5NDRiN2FiZTA4NDdmZTNlNTZh
11
- ZTE2NTAxNWIxZWFjZTg3MzQ1NDQzMTI5MGQ2MWFjZWJkZjhhM2E=
9
+ YmJjMTA3OGI1ODJhZWRjY2VkOWFkNzgxMTM4MTA5NmE0NzA1MDExZDFmNTBh
10
+ MmUzNTgyMzM0OGIxYWY5MmJlNjk0ODIxZDhmYTNjMTRlYzE4NzA2NzAzNWIx
11
+ NjU4ODMyOTgwZWYyYmU0OWQ4ZTg1ZWE3Y2NmZjk0YmFjZmM1NWQ=
12
12
  data.tar.gz: !binary |-
13
- YjVjMjhhZmFkMjNlYmY2MWYyYmI3MzRiNzhhYjg2YzI3Y2M3NjllMDI4NzFl
14
- NTNiNTVjOWNjYjgzZjg0NjZiN2I0MTgwOGM2MTcxMmEzOTI3MTM0ZWVhMjli
15
- YjBmM2IwZDgyMjMyYWI4NDZmM2VkNjIzMjA1YTY4NTYyNmRiNzQ=
13
+ NWJiNzYyYWE5MmVkOGQxNGUwYjE5MTMzZGRiZTAxMzBlMTIxNmJkNDI4NGQz
14
+ MjkxMjFkYzlmNzljNTJhZjlkOWQyMmVkN2JhMTE4YzdiZTYyNGRjOGRjOGM4
15
+ ZTg0M2Q3YTM0MmQxY2U3ODE4NWYxYzNkN2MwY2RhM2ZkY2NhNTg=
data/README.md CHANGED
@@ -1,16 +1,33 @@
1
- # Getting Started
1
+ [![Code Climate](https://codeclimate.com/github/quandl/quandl_command.png)](https://codeclimate.com/github/quandl/quandl_command)
2
+
3
+ # Quandl Toolbelt
4
+
5
+ ** The Quandl Toolbelt is currently in ALPHA TESTING. You are nevertheless welcome to try it. **
2
6
 
3
7
  The Quandl toolbelt enables you to create and maintain time series data on Quandl.com. The Quandl toolbelt is extremly simple to understand and use. (We use it to maintain the 8 million datasets currently on the site.)
4
8
 
5
9
  ## Installation
6
10
 
7
- ### Mac or Linux
11
+ ### Mac
12
+
13
+ **[quandl-toolbelt.pkg](http://s3.amazonaws.com/quandl-command/quandl-toolbelt.pkg)**
8
14
 
9
- curl -s http://s3.amazonaws.com/quandl-command/install.sh | bash
10
15
 
11
16
  ### Windows
12
17
 
13
- [Executable Installer](http://s3.amazonaws.com/quandl-command/Quandl+Setup.exe)
18
+ **[Quandl Setup.exe]( http://s3.amazonaws.com/quandl-command/Quandl+Setup.exe)**
19
+
20
+
21
+ ### Gemfile
22
+
23
+ In your Gemfile, add:
24
+
25
+ ```ruby
26
+ gem "quandl"
27
+ ```
28
+
29
+
30
+
14
31
 
15
32
  ## Login
16
33
 
@@ -23,15 +40,10 @@ Once the toolbelt is installed, the next step is to login to Quandl:
23
40
  username: tammer1
24
41
  email: tammer@quandl.com
25
42
 
26
- If you have a Quandl password, you can do this:
43
+ If you have a Quandl password, you can also use `quandl login --method password`. (You might not have a Quandl password if you log in using Github, Google, Linkedin or Twitter)
44
+
27
45
 
28
- $ quandl login --method password
29
- quandl login
30
- Username or Email: Tammer1
31
- Password: ******
32
- You've successfully authorized Tammer1!
33
46
 
34
- (You might not have a Quandl password if you log in using Github, Google, Linkedin or Twitter)
35
47
 
36
48
  ## Create a Dataset
37
49
 
@@ -52,6 +64,9 @@ Now send it to Quandl:
52
64
 
53
65
  You just created a dataset on Quandl.com: `www.quandl.com/<your-username>/AAA`
54
66
 
67
+
68
+
69
+
55
70
  ## Update a Dataset
56
71
 
57
72
  The new dataset will now exist on Quandl forever. You can send new data and/or update metadata whenever you want. For example, create [data_update.csv](https://raw2.github.com/quandl/toolbelt_help/master/data_udpate.csv):
@@ -74,6 +89,9 @@ Notice that the dataset now has three rows and a new description:
74
89
  You might also want to edit it more at [www.quandl.com/edit/<your user name>/FOO](#)
75
90
  -->
76
91
 
92
+
93
+
94
+
77
95
  ## Delete a Dataset
78
96
 
79
97
  You can delete the dataset:
@@ -86,6 +104,7 @@ You can delete the dataset:
86
104
 
87
105
 
88
106
 
107
+
89
108
  ## Scrapers and Other Data Producing Programs
90
109
 
91
110
  As long as your program outputs Quandl flavored CSV as above, it is ready for use with the Quandl toolbelt. Consider this scraper, written in both Ruby ([scraper1.rb](https://raw2.github.com/quandl/toolbelt_help/master/scraper1.rb)) and Python ([scraper1.py](https://raw2.github.com/quandl/toolbelt_help/master/scraper1.py)):
@@ -132,10 +151,16 @@ The scraper will be run daily at 17:30 (in your time zone). Every day when it r
132
151
  You now have a dataset on Quandl that refreshes daily!
133
152
  -->
134
153
 
154
+
155
+
156
+
135
157
  ## Scheduling Your Scripts
136
158
 
137
159
  This feature is not ready for use yet. When it is ready you will be able to send any script to Quandl. Quandl will then run the script on a schedule and send the output to `quandl upload` for you. You can (optionally) receive emails when the script succeeds or fails.
138
160
 
161
+
162
+
163
+
139
164
  ## Many Datasets via One Input Stream
140
165
 
141
166
  You can send multiple datasets with a single call to `quandl upload`. [Scraper2.rb](https://raw2.github.com/quandl/toolbelt_help/master/scraper2.rb) ([Scraper2.py](https://raw2.github.com/quandl/toolbelt_help/master/scraper2.py)) produces the most recent closing data for two stocks:
@@ -156,10 +181,14 @@ Creates or updates both `quandl.com/<your-username>/AAPL` and `quandl.com/<your-
156
181
 
157
182
  You can send an infinite number of datasets via one call to `quandl upload`.
158
183
 
184
+
185
+
186
+
159
187
  ## Quandl Flavored CSV
160
188
 
161
189
  Quandl "flavored" CSV is just just plain vanilla CSV prepended with metadata in [YAML](http://en.wikipedia.org/wiki/YAML) format. Metadata is seperated from data by a single line containing one or more dashes "-".
162
190
 
191
+
163
192
  ### Quick Reference
164
193
 
165
194
  Here is the entire specification by example for quick reference:
@@ -184,6 +213,7 @@ Here is the entire specification by example for quick reference:
184
213
  Date,Price,Volume # if omitted on new dataset, default headings are created
185
214
  2012-01-01,32.23 # the csv data. date can be almost any format you want
186
215
 
216
+
187
217
  ### Metadata Specifications
188
218
 
189
219
  |Field|Description|Required?|
@@ -196,11 +226,13 @@ Here is the entire specification by example for quick reference:
196
226
  |private|true or false; default is false|private data is visible to only you|
197
227
 
198
228
 
229
+
230
+
199
231
  ## Example Scrapers
200
232
 
201
233
  ### Shibor
202
234
 
203
- [www.shibor.org](http://www.shibor.org) publishes Shibor rates which Quandl republishes at [www.quandl.com/TAMMER1/SHIBOR](http://www.quandl.com/USER_YY/SHIBOR)
235
+ [www.shibor.org](http://www.shibor.org) publishes Shibor rates which Quandl republishes at [www.quandl.com/TAMMER1/SHIBOR](http://www.quandl.com/TAMMER1/SHIBOR)
204
236
 
205
237
  This dataset is maintained via [this ruby script](https://github.com/tammer/scrapers/blob/master/shibor.rb) that fetches the 10 most recent days of data from Shibor.org.
206
238
 
@@ -218,9 +250,10 @@ The backfill for this dataset was manually downloaded and converted into a simpl
218
250
 
219
251
  quandl upload shibor_backfill.csv
220
252
 
253
+
221
254
  ### Hsieh Trend Following Factors
222
255
 
223
- Professor David Hsieh maintains hedge fund trend following risk factors at [faculty.fuqua.duke.edu/~dah7/HFRFData.htm](https://faculty.fuqua.duke.edu/~dah7/HFRFData.htm). They are available on Quandl at [quandl.com/TAMMER1/TFRF](http://www.quandl.com/USER_YY/TFRF).
256
+ Professor David Hsieh maintains hedge fund trend following risk factors at [faculty.fuqua.duke.edu/~dah7/HFRFData.htm](https://faculty.fuqua.duke.edu/~dah7/HFRFData.htm). They are available on Quandl at [quandl.com/TAMMER1/TFRF](http://www.quandl.com/TAMMER1/TFRF).
224
257
 
225
258
  The data is maintained by running [hsieh.rb](https://github.com/tammer/scrapers/blob/master/hsieh.rb) every day. To see the output of the script:
226
259
 
@@ -230,6 +263,7 @@ To keep the data up to date, we scheduled a daily run of:
230
263
 
231
264
  curl "https://raw.github.com/tammer/scrapers/master/hsieh.rb" | ruby | quandl upload
232
265
 
266
+
233
267
  ### Copyright Data
234
268
 
235
269
  Some data publishers provide data on the condition that you not republish it. When scraping such sites, be sure to set the private flag to be true so that only you can see the data, at which point you should be in compliance, since you are simply storing a single copy on a private cloud based repository; (no different from storing a copy on Google Docs or Dropbox).
@@ -240,16 +274,23 @@ For example, if you happen to need the MSCI Far East Index on Quandl, you can sc
240
274
 
241
275
  Now you have the data you need on Quandl while remaining compliant with MSCI's terms of use.
242
276
 
277
+
243
278
  ### Additional Examples
244
279
 
245
280
  |Dataset|Scraper|
246
281
  |-------|----|
247
282
  | [Litecoin vs USD](http://quandl.com/TAMMER1/LTCUSD)| [litecoin.rb](https://github.com/tammer/scrapers/blob/master/litecoin.rb)|
248
283
 
284
+
285
+
286
+
249
287
  ## Full Reference
250
288
 
251
289
  Other features of the Toolbelt including `quandl download`, `quandl info`, `quandl list` and other minor features are documented in the [Quandl Toolbelt Reference](#) page.
252
290
 
291
+
292
+
293
+
253
294
  ## FAQ
254
295
 
255
296
  ### How can I use ":" in the name or description field?
@@ -270,7 +311,7 @@ or
270
311
 
271
312
  From Python:
272
313
 
273
- print "description: \"I love colons : : :\""
314
+ print "description: \"I love colons : : :\""
274
315
 
275
316
 
276
317
  ### Are the Datasets Publicly Accessible?
@@ -281,11 +322,13 @@ You decide. By default it is public. use:
281
322
 
282
323
  To make the dataset visible only to you.
283
324
 
325
+
284
326
  ### Can you handle high frequency (intra-day) data?
285
327
 
286
328
  No.
287
329
 
288
- ### How to I including Blank or Nils
330
+
331
+ ### How do I including Blank or Nils
289
332
 
290
333
  This is how you include nil datums:
291
334
 
@@ -301,15 +344,25 @@ This is how you include nil datums:
301
344
 
302
345
  This dataset can be seen on Quandl right [here](http://www.quandl.com/TAMMER1/NIL)
303
346
 
347
+
304
348
  ### Your SHIBOR script seems to download the past 10 days' worth of data...
305
349
 
306
350
  ...Assuming that happens daily, then you'll have overlapping data (e.g., the most recent day's data is new, but the prior nine days worth of data should be in the database already). How does Quandl deal with that? What if the underlying data changes - will Quandl update the previous nine days of data? Will it record what the data used to be based on the 'original' dataset?
307
351
 
308
352
  Answer: If you upload data for dates where data already exists, the new data over-writes the old data. Thus if you send redundant data, it is harmless. Shibor.rb is written this way for two reason: 1) helpful in case the publisher changes something a few days later. 2) helpful if we miss run for a couple of days for some reason.
309
353
 
310
- ### A given municipal bond doesn't trade every day. So, if I set up a separate 'id' for each bond, then each day there will be some bonds that get pricing updates and others that don't. Are there any issues with this, or can Quandl handle this kind of 'sparse' data?
311
354
 
312
- Sparse data is not a problem.
355
+ ### A given municipal bond doesn't trade every day...
356
+
357
+ So, if I set up a separate 'id' for each bond, then each day there will be some bonds that get pricing updates and others that don't. Are there any issues with this, or can Quandl handle this kind of 'sparse' data?
358
+
359
+ Answer: Sparse data is not a problem.
360
+
361
+
362
+ ### Why can't I find my dataset using search on Quandl.
363
+
364
+ If it is private, it will not appear in search ever. If it is public, it can take up to 1 hour before our index is updated with your new dataset.
365
+
313
366
 
314
367
  ### My Question is not answered!
315
368
 
data/Rakefile CHANGED
@@ -21,90 +21,11 @@ RSpec::Core::RakeTask.new(:spec) do |task|
21
21
  task.pattern = "spec/**/*_spec.rb"
22
22
  end
23
23
 
24
- def checkout_master!
25
- raise "You have unstaged commits." if %x{git status} =~ /Changes not staged for commit/
26
- sh "git checkout master"
27
- raise "Unable to checkout master" unless %x{git branch | grep '*'} =~ /master/
24
+ require 'quandl/utility/rake_tasks'
25
+ Quandl::Utility::Tasks.configure do |c|
26
+ c.name = 'quandl'
27
+ c.version_path = 'VERSION'
28
+ c.changelog_path = 'UPGRADE.md'
29
+ c.tag_prefix = 'v'
30
+ c.changelog_matching = ['^QUGC','^WIKI']
28
31
  end
29
-
30
- def verify_version!(version)
31
- raise ArgumentError, "Expected version format is: MAJOR.MINOR.PATCH, got: #{version}" unless version =~ /[0-9]+\.[0-9]+\.[0-9]+/
32
- raise "Version '#{version}' has already been documented in UPGRADE.md" if file_contains_matching("UPGRADE.md", /## #{version}/)
33
- end
34
-
35
- def file_contains_matching(file_path, matching)
36
- matched = false
37
- f = File.open(file_path)
38
- f.each_line do |line|
39
- if line =~ matching
40
- matched = true
41
- break
42
- end
43
- end
44
- f.close
45
- matched
46
- end
47
-
48
- namespace :quandl do
49
- desc "bump version and generate UPGRADE documentation"
50
- task :bump, :version do |t,args|
51
- version = args['version']
52
- checkout_master!
53
- verify_version!(version)
54
- # update UPGRADE.md with commits
55
- Rake::Task["quandl:generate:documentation"].execute args.to_hash.stringify_keys!
56
- Rake::Task["quandl:version:bump"].execute args.to_hash.stringify_keys!
57
- end
58
- desc "build and push gem & distros"
59
- task :release do |t,args|
60
- checkout_master!
61
- # tag git revision with version, build quandl.gem, push to rubygems
62
- Rake::Task["release"].execute
63
- # build windows exe, mac pkg, tarball
64
- Rake::Task["toolbelt:release:all"].execute
65
- end
66
- namespace :version do
67
- task :bump, :version do |t,args|
68
- version_file = 'lib/quandl/command/version.rb'
69
- IO.write(version_file, File.open(version_file) do |f|
70
- f.read.gsub(Quandl::Command::VERSION, args['version'])
71
- end
72
- )
73
- sh(%Q{git commit -am "Bump version to: #{args['version']}"})
74
- end
75
- end
76
- namespace :generate do
77
- task :documentation, :version do |t,args|
78
- version = args['version']
79
- verify_version!(version)
80
- # collect commits that match JIRA syntax
81
- commits = %x{ git --no-pager log --since="v#{Quandl::Command::VERSION}" --pretty=oneline --grep='^QUGC' }
82
- # split newlines and exclude reference, select uniq
83
- commits = commits.split("\n").collect{|c| "* #{c[41..-1]}" }.uniq
84
- # compose prepend string
85
- commits = "## #{version} \n\n" + commits.join("\n") + "\n\n\n\n"
86
- # prepend to UPGRADE.md
87
- File.write( 'UPGRADE.md', commits + File.read('UPGRADE.md') )
88
- end
89
- end
90
- end
91
-
92
- namespace :rubies do
93
-
94
- rubies = [
95
- 'ruby-1.9.3-p194',
96
- 'ruby-1.9.3-p484',
97
- 'ruby-2.0.0-p353',
98
- ]
99
-
100
- desc "rspec all the rubies"
101
- task :spec do |t, args|
102
- rubies.each do |ruby|
103
- cmd = "rvm #{ruby} do bundle exec rspec"
104
- puts(cmd)
105
- system(cmd)
106
- end
107
- end
108
-
109
- end
110
-
data/UPGRADE.md CHANGED
@@ -1,3 +1,26 @@
1
+ ## 0.3.0
2
+
3
+ * QUGC-132 Add thread_pool locking so that requests for the same dataset are not made in parallel
4
+ * QUGC-120 update Task::Threading to catch SIGINT and shutdown thread_pool. Second occurence of SIGINT will exit immediately.
5
+ * QUGC-117 add option for specifying logfile output --stdout and --stderr
6
+ * QUGC-118 add option to specify environment -E --environment
7
+ * QUGC-119 only use thread pool when needed
8
+ * QUGC-119 given 1 thread skip using thread pool so that we can debug more easily, but leave threadpool implemented otherwise
9
+ * QUGC-55 POST crash input back to us. Quandl Toolbelt has crashed. Can we please send the crash report back to Quandl.com?
10
+ * QUGC-113 bump client for error propagation
11
+ * QUGC-109 load task modules into Task
12
+ * QUGC-109 refactor quandl/command/task.rb into modules
13
+ * QUGC-89 quandl list inherits from quandl search and implements the same paging behaviour.
14
+ * QUGC-89 quandl search will return an unlimited number of results.
15
+ * QUGC-99 Add 'quandl search' to Toolbelt
16
+ * QUGC-104 bump gems to fix when upload fails output is not json
17
+ * QUGC-98 Add basic presenter classes
18
+ * QUGC-95 rename ruby package identifier to avoid clobbering other ruby packages
19
+ * WIKI-153 bump quandl_client to 2.5.2 for scraper models
20
+ * WIKI-153 Add schedule task with subtasks: add, delete, replace, list, show
21
+
22
+
23
+
1
24
  ## 0.2.27
2
25
 
3
26
  * add option to force update
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.3.0
@@ -10,10 +10,12 @@ end
10
10
 
11
11
  require 'quandl/lang'
12
12
  require "quandl/command/version"
13
- require 'quandl/command/qconfig'
13
+ require 'quandl/command/config'
14
+ require 'quandl/command/presenter'
14
15
  require 'quandl/command/tasks'
15
16
 
16
17
  Quandl::Logger.use(Quandl::Logger::Outputs)
18
+ I18n.enforce_available_locales = false
17
19
 
18
20
  module Quandl::Command
19
21
  extend ActiveSupport::Concern
@@ -27,8 +29,14 @@ module Quandl::Command
27
29
  default_command :help
28
30
 
29
31
  global_option '-T', '--token STRING', 'secret token used to authenticate requests.'
30
- global_option '-V', '--verbose', 'display detailed log messages'
31
- global_option '-U', '--url STRING', 'API url.'
32
+ global_option '-V', '--verbose', 'use detailed log output'
33
+ global_option '-U', '--url STRING', 'the API host that will be used'
34
+ global_option '-F', '--output-format STRING', 'the output format [ pipes, json, qdf ]'
35
+ global_option '-C', '--output-column INTEGER', 'the column to output'
36
+ global_option '-E', '--environment INTEGER', 'the environment to load'
37
+ global_option '--threads INTEGER', 'how many threads to use for concurrent operations'
38
+ global_option '--stdout STRING', 'where to redirect stdout'
39
+ global_option '--stderr STRING', 'where to redirect stderr'
32
40
  global_option '--force-yes', 'force y/n with yes'
33
41
 
34
42
  Tasks.each{|t| t.configure(self) }
@@ -0,0 +1,88 @@
1
+ require 'fileutils'
2
+ require 'yaml'
3
+ require 'ostruct'
4
+ require 'quandl/support/attributes'
5
+
6
+ module Quandl
7
+ module Command
8
+ class Config
9
+
10
+ include Quandl::Support::Attributes
11
+
12
+ define_attributes :token, :quandl_url, :last_checked_for_update, :output_format, :send_crash_reports, :stdout, :stderr
13
+
14
+ attr_accessor :options
15
+
16
+ def initialize(opts={})
17
+ self.options = opts.symbolize_keys
18
+ convert_legacy_config
19
+ ensure_directory_is_present
20
+ @attributes = read_config_from_file.stringify_keys
21
+ end
22
+
23
+ def stdout
24
+ options[:stdout] || read_attribute(:stdout)
25
+ end
26
+
27
+ def stderr
28
+ options[:stderr] || read_attribute(:stderr)
29
+ end
30
+
31
+ def quandl_url
32
+ return @quandl_url if @quandl_url.present?
33
+ @quandl_url = options[:url] if options[:url].present?
34
+ @quandl_url = ENV['QUANDL_URL'] if @quandl_url.blank?
35
+ @quandl_url = read_attribute(:quandl_url) if @quandl_url.blank?
36
+ @quandl_url = 'http://quandl.com/api/' if @quandl_url.blank?
37
+ @quandl_url
38
+ end
39
+
40
+ def auth_token
41
+ return @auth_token if @auth_token.present?
42
+ @auth_token = options[:token] if options[:token].present?
43
+ @auth_token = ENV['QUANDL_TOKEN'] if @auth_token.blank?
44
+ @auth_token = read_attribute(:token) if @auth_token.blank?
45
+ @auth_token
46
+ end
47
+
48
+ def file_path
49
+ options[:file_path]
50
+ end
51
+
52
+ def file_dir
53
+ File.dirname(file_path)
54
+ end
55
+
56
+ private
57
+
58
+ def ensure_directory_is_present
59
+ return if File.exists?(file_path)
60
+ FileUtils.mkdir(file_dir) unless Dir.exists?(file_dir)
61
+ File.write( file_path, YAML.dump({}) )
62
+ end
63
+
64
+ def convert_legacy_config
65
+ return if File.directory?(file_dir) || !File.exists?(file_dir)
66
+ # otherwise move the old .quandl into .quandl/config
67
+ FileUtils.mv(file_dir, "#{file_dir}.old")
68
+ FileUtils.mkdir(file_dir)
69
+ token = File.read("#{file_dir}.old")
70
+ File.write(file_path, "token: #{token}")
71
+ end
72
+
73
+ def write_attribute(*args)
74
+ super(*args)
75
+ write_config_to_file
76
+ end
77
+
78
+ def read_config_from_file
79
+ YAML.load(File.read(file_path))
80
+ end
81
+
82
+ def write_config_to_file
83
+ File.write( file_path, YAML.dump(attributes) )
84
+ end
85
+
86
+ end
87
+ end
88
+ end