td 0.7.1 → 0.7.2
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.
- data/ChangeLog +8 -1
- data/lib/td/api.rb +15 -3
- data/lib/td/api_iface.rb +9 -0
- data/lib/td/command/account.rb +2 -2
- data/lib/td/command/common.rb +2 -7
- data/lib/td/command/database.rb +3 -6
- data/lib/td/command/import.rb +1 -2
- data/lib/td/command/query.rb +144 -23
- data/lib/td/command/table.rb +3 -6
- data/lib/td/command/td.rb +40 -28
- data/lib/td/config.rb +88 -67
- data/lib/td/version.rb +1 -1
- metadata +3 -3
data/ChangeLog
CHANGED
@@ -1,10 +1,17 @@
|
|
1
1
|
|
2
|
+
== 2011-08-15 version 0.7.2
|
3
|
+
|
4
|
+
* Supports TD_API_KEY and TD_CONFIG_PATH environment variable
|
5
|
+
* query, show-job: supports --output and --format options
|
6
|
+
* show-jobs: supports --page, --skip, --from and --around options
|
7
|
+
|
8
|
+
|
2
9
|
== 2011-08-15 version 0.7.1
|
3
10
|
|
4
11
|
* Validate name of a database/table on create-database/create-log-table
|
5
12
|
subcommands
|
6
|
-
* Uses /v3/job/result?format=msgpack API to get result of a job
|
7
13
|
* -d, --database DB_NAME option is now required on query subcommand
|
14
|
+
* Uses /v3/job/result?format=msgpack API to get result of a job
|
8
15
|
* API server can be changed using TD_API_SERVER=HOST:PORT environment variable
|
9
16
|
|
10
17
|
|
data/lib/td/api.rb
CHANGED
@@ -130,15 +130,20 @@ class API
|
|
130
130
|
@iface.job_result(job_id)
|
131
131
|
end
|
132
132
|
|
133
|
+
# => result:String
|
134
|
+
def job_result_format(job_id, format)
|
135
|
+
@iface.job_result_format(job_id, format)
|
136
|
+
end
|
137
|
+
|
133
138
|
# => nil
|
134
139
|
def job_result_each(job_id, &block)
|
135
140
|
@iface.job_result_each(job_id, &block)
|
136
141
|
end
|
137
142
|
|
138
143
|
# => time:Flaot
|
139
|
-
|
144
|
+
def import(db_name, table_name, format, stream, stream_size=stream.lstat.size)
|
140
145
|
@iface.import(db_name, table_name, format, stream, stream_size)
|
141
|
-
|
146
|
+
end
|
142
147
|
|
143
148
|
def self.validate_database_name(name)
|
144
149
|
name = name.to_s
|
@@ -300,11 +305,16 @@ class Job < APIObject
|
|
300
305
|
@result
|
301
306
|
end
|
302
307
|
|
308
|
+
def result_format(format)
|
309
|
+
return nil unless finished?
|
310
|
+
@api.job_result_format(@job_id, format)
|
311
|
+
end
|
312
|
+
|
303
313
|
def result_each(&block)
|
304
314
|
if @result
|
305
315
|
@result.each(&block)
|
306
316
|
else
|
307
|
-
@api.job_result_each(&block)
|
317
|
+
@api.job_result_each(@job_id, &block)
|
308
318
|
end
|
309
319
|
nil
|
310
320
|
end
|
@@ -323,10 +333,12 @@ class Job < APIObject
|
|
323
333
|
end
|
324
334
|
|
325
335
|
def success?
|
336
|
+
update_status! unless @status
|
326
337
|
@status == "success"
|
327
338
|
end
|
328
339
|
|
329
340
|
def error?
|
341
|
+
update_status! unless @status
|
330
342
|
@status == "error"
|
331
343
|
end
|
332
344
|
|
data/lib/td/api_iface.rb
CHANGED
@@ -161,6 +161,15 @@ class APIInterface
|
|
161
161
|
return result
|
162
162
|
end
|
163
163
|
|
164
|
+
def job_result_format(job_id, format)
|
165
|
+
# TODO chunked encoding
|
166
|
+
code, body, res = get("/v3/job/result/#{e job_id}", {'format'=>format})
|
167
|
+
if code != "200"
|
168
|
+
raise_error("Get job result failed", res)
|
169
|
+
end
|
170
|
+
return body
|
171
|
+
end
|
172
|
+
|
164
173
|
def job_result_each(job_id, &block)
|
165
174
|
# TODO chunked encoding
|
166
175
|
require 'msgpack'
|
data/lib/td/command/account.rb
CHANGED
@@ -17,7 +17,7 @@ module Command
|
|
17
17
|
require 'td/config'
|
18
18
|
conf = nil
|
19
19
|
begin
|
20
|
-
conf = Config.read
|
20
|
+
conf = Config.read
|
21
21
|
rescue ConfigError
|
22
22
|
end
|
23
23
|
if conf && conf['account.user']
|
@@ -74,7 +74,7 @@ module Command
|
|
74
74
|
conf ||= Config.new
|
75
75
|
conf["account.user"] = user_name
|
76
76
|
conf["account.apikey"] = api.apikey
|
77
|
-
conf.save
|
77
|
+
conf.save
|
78
78
|
|
79
79
|
$stderr.puts "Use '#{$prog} create-database <db_name>' to create a database."
|
80
80
|
end
|
data/lib/td/command/common.rb
CHANGED
@@ -56,13 +56,8 @@ EOF
|
|
56
56
|
op
|
57
57
|
end
|
58
58
|
|
59
|
-
def
|
60
|
-
|
61
|
-
Config.read($TRD_CONFIG_PATH)
|
62
|
-
end
|
63
|
-
|
64
|
-
def cmd_api(conf)
|
65
|
-
apikey = conf['account.apikey']
|
59
|
+
def cmd_api
|
60
|
+
apikey = Config.apikey
|
66
61
|
unless apikey
|
67
62
|
raise ConfigError, "Account is not configured."
|
68
63
|
end
|
data/lib/td/command/database.rb
CHANGED
@@ -6,8 +6,7 @@ module Command
|
|
6
6
|
op = cmd_opt 'create-database', :db_name
|
7
7
|
db_name = op.cmd_parse
|
8
8
|
|
9
|
-
|
10
|
-
api = cmd_api(conf)
|
9
|
+
api = cmd_api
|
11
10
|
|
12
11
|
API.validate_database_name(db_name)
|
13
12
|
|
@@ -34,8 +33,7 @@ module Command
|
|
34
33
|
|
35
34
|
db_name = op.cmd_parse
|
36
35
|
|
37
|
-
|
38
|
-
api = cmd_api(conf)
|
36
|
+
api = cmd_api
|
39
37
|
|
40
38
|
begin
|
41
39
|
db = api.database(db_name)
|
@@ -58,8 +56,7 @@ module Command
|
|
58
56
|
op = cmd_opt 'show-databases'
|
59
57
|
op.cmd_parse
|
60
58
|
|
61
|
-
|
62
|
-
api = cmd_api(conf)
|
59
|
+
api = cmd_api
|
63
60
|
|
64
61
|
dbs = api.databases
|
65
62
|
|
data/lib/td/command/import.rb
CHANGED
data/lib/td/command/query.rb
CHANGED
@@ -8,19 +8,29 @@ module Command
|
|
8
8
|
op.banner << "\noptions:\n"
|
9
9
|
|
10
10
|
db_name = nil
|
11
|
+
wait = false
|
12
|
+
output = nil
|
13
|
+
format = 'tsv'
|
14
|
+
|
11
15
|
op.on('-d', '--database DB_NAME', 'use the database (required)') {|s|
|
12
16
|
db_name = s
|
13
17
|
}
|
14
|
-
|
15
|
-
wait = false
|
16
18
|
op.on('-w', '--wait', 'wait for finishing the job', TrueClass) {|b|
|
17
19
|
wait = b
|
18
20
|
}
|
21
|
+
op.on('-o', '--output PATH', 'write result to the file') {|s|
|
22
|
+
output = s
|
23
|
+
}
|
24
|
+
op.on('-f', '--format FORMAT', 'format of the result to write to the file (tsv, csv, json or msgpack)') {|s|
|
25
|
+
unless ['tsv', 'csv', 'json', 'msgpack'].include?(s)
|
26
|
+
raise "Unknown format #{s.dump}. Supported format: tsv, csv, json, msgpack"
|
27
|
+
end
|
28
|
+
format = s
|
29
|
+
}
|
19
30
|
|
20
31
|
sql = op.cmd_parse
|
21
32
|
|
22
|
-
|
23
|
-
api = cmd_api(conf)
|
33
|
+
api = cmd_api
|
24
34
|
|
25
35
|
unless db_name
|
26
36
|
$stderr.puts "-d, --database DB_NAME option is required."
|
@@ -38,22 +48,56 @@ module Command
|
|
38
48
|
if wait && !job.finished?
|
39
49
|
wait_job(job)
|
40
50
|
puts "Status : #{job.status}"
|
41
|
-
|
42
|
-
|
51
|
+
if job.success?
|
52
|
+
puts "Result :"
|
53
|
+
show_result(job, output, format)
|
54
|
+
end
|
43
55
|
end
|
44
56
|
end
|
45
57
|
|
46
58
|
def show_jobs
|
47
|
-
op = cmd_opt 'show-jobs', :max
|
48
|
-
|
59
|
+
op = cmd_opt 'show-jobs', :max?
|
60
|
+
|
61
|
+
op.banner << "\noptions:\n"
|
62
|
+
|
63
|
+
page = 0
|
64
|
+
skip = 0
|
65
|
+
from = nil
|
66
|
+
around = nil
|
67
|
+
|
68
|
+
op.on('-p', '--page PAGE', 'skip N pages', Integer) {|i|
|
69
|
+
page = i
|
70
|
+
}
|
71
|
+
op.on('-s', '--skip N', 'skip N jobs', Integer) {|i|
|
72
|
+
skip = i
|
73
|
+
}
|
74
|
+
op.on('-f', '--from JOB_ID', 'show jobs from the id', Integer) {|i|
|
75
|
+
from = i
|
76
|
+
}
|
77
|
+
op.on('-a', '--around JOB_ID', 'show jobs around the id', Integer) {|i|
|
78
|
+
around = i
|
79
|
+
}
|
80
|
+
|
81
|
+
max = op.cmd_parse
|
49
82
|
|
50
83
|
max = (max || 20).to_i
|
51
|
-
from = (from || 0).to_i
|
52
84
|
|
53
|
-
|
54
|
-
api = cmd_api(conf)
|
85
|
+
api = cmd_api
|
55
86
|
|
56
|
-
|
87
|
+
if from || around
|
88
|
+
jobs = api.jobs(0, 1)
|
89
|
+
if last = jobs[0]
|
90
|
+
if from
|
91
|
+
skip += last.job_id.to_i - from - (max-1)
|
92
|
+
else
|
93
|
+
skip += last.job_id.to_i - around - (max-1) + (max-1)/2
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
if page
|
98
|
+
skip += max * page
|
99
|
+
end
|
100
|
+
jobs = api.jobs(skip, skip+max-1)
|
57
101
|
|
58
102
|
rows = []
|
59
103
|
jobs.each {|job|
|
@@ -95,19 +139,29 @@ module Command
|
|
95
139
|
op.banner << "\noptions:\n"
|
96
140
|
|
97
141
|
verbose = nil
|
142
|
+
wait = false
|
143
|
+
output = nil
|
144
|
+
format = 'tsv'
|
145
|
+
|
98
146
|
op.on('-v', '--verbose', 'show logs', TrueClass) {|b|
|
99
147
|
verbose = b
|
100
148
|
}
|
101
|
-
|
102
|
-
wait = false
|
103
149
|
op.on('-w', '--wait', 'wait for finishing the job', TrueClass) {|b|
|
104
150
|
wait = b
|
105
151
|
}
|
152
|
+
op.on('-o', '--output PATH', 'write result to the file') {|s|
|
153
|
+
output = s
|
154
|
+
}
|
155
|
+
op.on('-f', '--format FORMAT', 'format of the result to write to the file (tsv, csv, json or msgpack)') {|s|
|
156
|
+
unless ['tsv', 'csv', 'json', 'msgpack'].include?(s)
|
157
|
+
raise "Unknown format #{s.dump}. Supported format: tsv, csv, json, msgpack"
|
158
|
+
end
|
159
|
+
format = s
|
160
|
+
}
|
106
161
|
|
107
162
|
job_id = op.cmd_parse
|
108
163
|
|
109
|
-
|
110
|
-
api = cmd_api(conf)
|
164
|
+
api = cmd_api
|
111
165
|
|
112
166
|
job = api.job(job_id)
|
113
167
|
|
@@ -118,13 +172,15 @@ module Command
|
|
118
172
|
|
119
173
|
if wait && !job.finished?
|
120
174
|
wait_job(job)
|
121
|
-
|
122
|
-
|
175
|
+
if job.success?
|
176
|
+
puts "Result :"
|
177
|
+
show_result(job, output, format)
|
178
|
+
end
|
123
179
|
|
124
180
|
else
|
125
|
-
if job.
|
181
|
+
if job.success?
|
126
182
|
puts "Result :"
|
127
|
-
|
183
|
+
show_result(job, output, format)
|
128
184
|
end
|
129
185
|
|
130
186
|
if verbose
|
@@ -166,10 +222,75 @@ module Command
|
|
166
222
|
end
|
167
223
|
end
|
168
224
|
|
169
|
-
def
|
225
|
+
def show_result(job, output, format)
|
226
|
+
if output
|
227
|
+
write_result(job, output, format)
|
228
|
+
puts "written to #{output} in #{format} format"
|
229
|
+
else
|
230
|
+
render_result(job)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
def write_result(job, output, format)
|
235
|
+
case format
|
236
|
+
when 'json'
|
237
|
+
require 'json'
|
238
|
+
first = true
|
239
|
+
File.open(output, "w") {|f|
|
240
|
+
f.write "["
|
241
|
+
job.result_each {|row|
|
242
|
+
if first
|
243
|
+
first = false
|
244
|
+
else
|
245
|
+
f.write ","
|
246
|
+
end
|
247
|
+
f.write row.to_json
|
248
|
+
}
|
249
|
+
f.write "]"
|
250
|
+
}
|
251
|
+
|
252
|
+
when 'msgpack'
|
253
|
+
File.open(output, "w") {|f|
|
254
|
+
f.write job.result_format('msgpack')
|
255
|
+
}
|
256
|
+
|
257
|
+
when 'csv'
|
258
|
+
require 'json'
|
259
|
+
require 'csv'
|
260
|
+
CSV.open(output, "w") {|writer|
|
261
|
+
job.result_each {|row|
|
262
|
+
writer << row.map {|col| col.is_a?(String) ? col.to_s : col.to_json }
|
263
|
+
}
|
264
|
+
}
|
265
|
+
|
266
|
+
when 'tsv'
|
267
|
+
require 'json'
|
268
|
+
File.open(output, "w") {|f|
|
269
|
+
job.result_each {|row|
|
270
|
+
first = true
|
271
|
+
row.each {|col|
|
272
|
+
if first
|
273
|
+
first = false
|
274
|
+
else
|
275
|
+
f.write "\t"
|
276
|
+
end
|
277
|
+
f.write col.is_a?(String) ? col.to_s : col.to_json
|
278
|
+
}
|
279
|
+
f.write "\n"
|
280
|
+
}
|
281
|
+
}
|
282
|
+
|
283
|
+
else
|
284
|
+
raise "Unknown format #{format.inspect}"
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
def render_result(job)
|
170
289
|
require 'json'
|
171
|
-
rows =
|
172
|
-
|
290
|
+
rows = []
|
291
|
+
job.result_each {|row|
|
292
|
+
# TODO limit number of rows to show
|
293
|
+
rows << row.map {|v|
|
173
294
|
if v.is_a?(String)
|
174
295
|
v.to_s
|
175
296
|
else
|
data/lib/td/command/table.rb
CHANGED
@@ -3,8 +3,7 @@ module TD
|
|
3
3
|
module Command
|
4
4
|
|
5
5
|
def create_table_type(type, db_name, table_name)
|
6
|
-
|
7
|
-
api = cmd_api(conf)
|
6
|
+
api = cmd_api
|
8
7
|
|
9
8
|
API.validate_table_name(table_name)
|
10
9
|
|
@@ -43,8 +42,7 @@ module Command
|
|
43
42
|
op = cmd_opt 'drop-table', :db_name, :table_name
|
44
43
|
db_name, table_name = op.cmd_parse
|
45
44
|
|
46
|
-
|
47
|
-
api = cmd_api(conf)
|
45
|
+
api = cmd_api
|
48
46
|
|
49
47
|
begin
|
50
48
|
api.delete_table(db_name, table_name)
|
@@ -62,8 +60,7 @@ module Command
|
|
62
60
|
op = cmd_opt 'show-tables', :db_name?
|
63
61
|
db_name = op.cmd_parse
|
64
62
|
|
65
|
-
|
66
|
-
api = cmd_api(conf)
|
63
|
+
api = cmd_api
|
67
64
|
|
68
65
|
if db_name
|
69
66
|
db = find_database(api, db_name)
|
data/lib/td/command/td.rb
CHANGED
@@ -13,33 +13,38 @@ EOF
|
|
13
13
|
op.summary_indent = " "
|
14
14
|
|
15
15
|
(class<<self;self;end).module_eval do
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
16
|
+
define_method(:usage) do |errmsg|
|
17
|
+
require 'td/command/list'
|
18
|
+
puts op.to_s
|
19
|
+
puts ""
|
20
|
+
puts "commands:"
|
21
|
+
puts TD::Command::List.help(op.summary_indent)
|
22
|
+
puts ""
|
23
|
+
puts "Type 'td help COMMAND' for more information on a specific command."
|
24
|
+
if errmsg
|
25
|
+
puts "error: #{errmsg}"
|
26
|
+
exit 1
|
27
|
+
else
|
28
|
+
exit 0
|
29
|
+
end
|
30
|
+
end
|
31
31
|
end
|
32
32
|
|
33
|
-
config_path =
|
33
|
+
config_path = nil
|
34
|
+
apikey = nil
|
34
35
|
$verbose = false
|
35
36
|
#$debug = false
|
36
37
|
|
37
38
|
op.on('-c', '--config PATH', "path to config file (~/.td/td.conf)") {|s|
|
38
|
-
|
39
|
+
config_path = s
|
40
|
+
}
|
41
|
+
|
42
|
+
op.on('-k', '--apikey KEY', "use this API key instead of reading the config file") {|s|
|
43
|
+
apikey = s
|
39
44
|
}
|
40
45
|
|
41
46
|
op.on('-v', '--verbose', "verbose mode", TrueClass) {|b|
|
42
|
-
|
47
|
+
$verbose = b
|
43
48
|
}
|
44
49
|
|
45
50
|
#op.on('-d', '--debug', "debug mode", TrueClass) {|b|
|
@@ -47,30 +52,37 @@ op.on('-v', '--verbose', "verbose mode", TrueClass) {|b|
|
|
47
52
|
#}
|
48
53
|
|
49
54
|
begin
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
55
|
+
op.order!(ARGV)
|
56
|
+
usage nil if ARGV.empty?
|
57
|
+
cmd = ARGV.shift
|
58
|
+
|
59
|
+
require 'td/config'
|
60
|
+
if config_path
|
61
|
+
TD::Config.path = config_path
|
62
|
+
end
|
63
|
+
if apikey
|
64
|
+
TD::Config.apikey = apikey
|
65
|
+
end
|
54
66
|
rescue
|
55
|
-
|
67
|
+
usage $!.to_s
|
56
68
|
end
|
57
69
|
|
58
70
|
require 'td/command/list'
|
59
71
|
|
60
72
|
method = TD::Command::List.get_method(cmd)
|
61
73
|
unless method
|
62
|
-
|
74
|
+
$stderr.puts "'#{cmd}' is not a td command. Run '#{$prog}' to show the list."
|
63
75
|
TD::Command::List.show_guess(cmd)
|
64
|
-
|
76
|
+
exit 1
|
65
77
|
end
|
66
78
|
|
67
79
|
require 'td/error'
|
68
80
|
|
69
81
|
begin
|
70
|
-
|
82
|
+
method.call
|
71
83
|
rescue TD::ConfigError
|
72
|
-
|
73
|
-
|
84
|
+
$stderr.puts "TreasureData account is not configured yet."
|
85
|
+
$stderr.puts "Run '#{$prog} account' first."
|
74
86
|
rescue
|
75
87
|
$stderr.puts "error #{$!.class}: backtrace:"
|
76
88
|
$!.backtrace.each {|b|
|
data/lib/td/config.rb
CHANGED
@@ -4,75 +4,96 @@ module TD
|
|
4
4
|
|
5
5
|
|
6
6
|
class Config
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
@path = path
|
31
|
-
begin
|
32
|
-
data = File.read(@path)
|
33
|
-
rescue
|
34
|
-
e = ConfigNotFoundError.new($!.to_s)
|
7
|
+
def initialize
|
8
|
+
@path = nil
|
9
|
+
@conf = {} # section.key = val
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.read(path=Config.path, create=false)
|
13
|
+
new.read(path)
|
14
|
+
end
|
15
|
+
|
16
|
+
def [](cate_key)
|
17
|
+
@conf[cate_key]
|
18
|
+
end
|
19
|
+
|
20
|
+
def []=(cate_key, val)
|
21
|
+
@conf[cate_key] = val
|
22
|
+
end
|
23
|
+
|
24
|
+
def read(path=@path)
|
25
|
+
@path = path
|
26
|
+
begin
|
27
|
+
data = File.read(@path)
|
28
|
+
rescue
|
29
|
+
e = ConfigNotFoundError.new($!.to_s)
|
35
30
|
e.set_backtrace($!.backtrace)
|
36
31
|
raise e
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
32
|
+
end
|
33
|
+
|
34
|
+
section = ""
|
35
|
+
|
36
|
+
data.each_line {|line|
|
37
|
+
line.strip!
|
38
|
+
case line
|
39
|
+
when /^#/
|
40
|
+
next
|
41
|
+
when /\[(.+)\]/
|
42
|
+
section = $~[1]
|
43
|
+
when /^(\w+)\s*=\s*(.+?)\s*$/
|
44
|
+
key = $~[1]
|
45
|
+
val = $~[2]
|
46
|
+
@conf["#{section}.#{key}"] = val
|
47
|
+
else
|
48
|
+
raise ConfigParseError, "invalid config line '#{line}' at #{@path}"
|
49
|
+
end
|
50
|
+
}
|
51
|
+
|
52
|
+
self
|
53
|
+
end
|
54
|
+
|
55
|
+
def save(path=@path||Config.path)
|
56
|
+
@path = path
|
57
|
+
write
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
def write
|
62
|
+
require 'fileutils'
|
63
|
+
FileUtils.mkdir_p File.dirname(@path)
|
64
|
+
File.open(@path, "w") {|f|
|
65
|
+
@conf.keys.map {|cate_key|
|
66
|
+
cate_key.split('.',2)
|
67
|
+
}.zip(@conf.values).group_by {|(section,key),val|
|
68
|
+
section
|
69
|
+
}.each {|section,cate_key_vals|
|
70
|
+
f.puts "[#{section}]"
|
71
|
+
cate_key_vals.each {|(section,key),val|
|
72
|
+
f.puts " #{key} = #{val}"
|
73
|
+
}
|
74
|
+
}
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
78
|
+
@@path = ENV['TD_CONFIG_PATH'] || File.join(ENV['HOME'], '.td', 'td.conf')
|
79
|
+
@@apikey = ENV['TD_API_KEY']
|
80
|
+
@@apikey = nil if @@apikey == ""
|
81
|
+
|
82
|
+
def self.path
|
83
|
+
@@path
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.path=(path)
|
87
|
+
@@path = path
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.apikey
|
91
|
+
@@apikey || Config.read['account.apikey']
|
92
|
+
end
|
93
|
+
|
94
|
+
def self.apikey=(apikey)
|
95
|
+
@@apikey = apikey
|
96
|
+
end
|
76
97
|
end
|
77
98
|
|
78
99
|
|
data/lib/td/version.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: td
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 7
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 7
|
9
|
-
-
|
10
|
-
version: 0.7.
|
9
|
+
- 2
|
10
|
+
version: 0.7.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Sadayuki Furuhashi
|