google-api-client 0.1.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.
- data/CHANGELOG +3 -0
- data/LICENSE +202 -0
- data/README +68 -0
- data/Rakefile +52 -0
- data/bin/google-api +295 -0
- data/lib/google/api_client.rb +375 -0
- data/lib/google/api_client/discovery.rb +535 -0
- data/lib/google/api_client/parsers/json_parser.rb +40 -0
- data/lib/google/api_client/version.rb +25 -0
- data/spec/google/api_client/discovery_spec.rb +428 -0
- data/spec/google/api_client/parsers/json_parser_spec.rb +51 -0
- data/spec/google/api_client_spec.rb +79 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +5 -0
- data/tasks/clobber.rake +2 -0
- data/tasks/gem.rake +76 -0
- data/tasks/git.rake +40 -0
- data/tasks/metrics.rake +22 -0
- data/tasks/rdoc.rake +26 -0
- data/tasks/spec.rake +78 -0
- data/tasks/yard.rake +26 -0
- metadata +281 -0
@@ -0,0 +1,40 @@
|
|
1
|
+
# Copyright 2010 Google Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require 'json'
|
16
|
+
|
17
|
+
module Google
|
18
|
+
class APIClient
|
19
|
+
##
|
20
|
+
# Provides a consistent interface by which to parse request and response
|
21
|
+
# content.
|
22
|
+
# TODO(mattpok): ensure floats, URLs, dates are parsed correctly
|
23
|
+
module JSONParser
|
24
|
+
|
25
|
+
def self.serialize(hash)
|
26
|
+
# JSON parser used can accept arrays as well, but we will limit
|
27
|
+
# to only allow hash to JSON string parsing to keep a simple interface
|
28
|
+
unless hash.instance_of? Hash
|
29
|
+
raise ArgumentError,
|
30
|
+
"JSON generate expected a Hash but got a #{hash.class}."
|
31
|
+
end
|
32
|
+
return JSON.generate(hash)
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.parse(json_string)
|
36
|
+
return JSON.parse(json_string)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# Copyright 2010 Google Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
module Google
|
16
|
+
class APIClient
|
17
|
+
module VERSION
|
18
|
+
MAJOR = 0
|
19
|
+
MINOR = 1
|
20
|
+
TINY = 0
|
21
|
+
|
22
|
+
STRING = [MAJOR, MINOR, TINY].join('.')
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,428 @@
|
|
1
|
+
# Copyright 2010 Google Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require 'spec_helper'
|
16
|
+
|
17
|
+
require 'signet/oauth_1/client'
|
18
|
+
require 'httpadapter/adapters/net_http'
|
19
|
+
|
20
|
+
require 'google/api_client'
|
21
|
+
require 'google/api_client/version'
|
22
|
+
require 'google/api_client/parsers/json_parser'
|
23
|
+
|
24
|
+
describe Google::APIClient, 'unconfigured' do
|
25
|
+
before do
|
26
|
+
@client = Google::APIClient.new
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should not be able to determine the discovery URI' do
|
30
|
+
(lambda do
|
31
|
+
@client.discovery_uri
|
32
|
+
end).should raise_error(ArgumentError)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe Google::APIClient, 'configured for a bogus API' do
|
37
|
+
before do
|
38
|
+
@client = Google::APIClient.new(:service => 'bogus')
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should not be able to retrieve the discovery document' do
|
42
|
+
(lambda do
|
43
|
+
@client.discovery_document
|
44
|
+
end).should raise_error(Google::APIClient::TransmissionError)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe Google::APIClient, 'configured for bogus authorization' do
|
49
|
+
it 'should raise a type error' do
|
50
|
+
(lambda do
|
51
|
+
Google::APIClient.new(:service => 'prediction', :authorization => 42)
|
52
|
+
end).should raise_error(TypeError)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe Google::APIClient, 'configured for the prediction API' do
|
57
|
+
before do
|
58
|
+
@client = Google::APIClient.new(:service => 'prediction')
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should correctly determine the discovery URI' do
|
62
|
+
@client.discovery_uri.should ===
|
63
|
+
'http://www.googleapis.com/discovery/0.1/describe?api=prediction'
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'should have multiple versions available' do
|
67
|
+
@client.discovered_services.size.should > 1
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should find APIs that are in the discovery document' do
|
71
|
+
@client.discovered_service('prediction').name.should == 'prediction'
|
72
|
+
@client.discovered_service('prediction').version.should == 'v1'
|
73
|
+
@client.discovered_service(:prediction).name.should == 'prediction'
|
74
|
+
@client.discovered_service(:prediction).version.should == 'v1'
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'should find API versions that are in the discovery document' do
|
78
|
+
@client.discovered_service('prediction', 'v1.1').version.should == 'v1.1'
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'should not find APIs that are not in the discovery document' do
|
82
|
+
@client.discovered_service('bogus').should == nil
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should raise an error for bogus services' do
|
86
|
+
(lambda do
|
87
|
+
@client.discovered_service(42)
|
88
|
+
end).should raise_error(TypeError)
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'should find methods that are in the discovery document' do
|
92
|
+
@client.discovered_method('prediction.training.insert').name.should ==
|
93
|
+
'insert'
|
94
|
+
@client.discovered_method(:'prediction.training.insert').name.should ==
|
95
|
+
'insert'
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'should find methods for versions that are in the discovery document' do
|
99
|
+
@client.discovered_method(
|
100
|
+
'prediction.training.delete', 'v1.1'
|
101
|
+
).should_not == nil
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'should not find methods that are not in the discovery document' do
|
105
|
+
@client.discovered_method('prediction.training.delete', 'v1').should == nil
|
106
|
+
@client.discovered_method('prediction.bogus').should == nil
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'should raise an error for bogus methods' do
|
110
|
+
(lambda do
|
111
|
+
@client.discovered_method(42)
|
112
|
+
end).should raise_error(TypeError)
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'should correctly determine the latest version' do
|
116
|
+
@client.latest_service_version('prediction').version.should_not == 'v1'
|
117
|
+
@client.latest_service_version(:prediction).version.should_not == 'v1'
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'should raise an error for bogus services' do
|
121
|
+
(lambda do
|
122
|
+
@client.latest_service_version(42)
|
123
|
+
end).should raise_error(TypeError)
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'should correctly determine the latest version' do
|
127
|
+
# Sanity check the algorithm
|
128
|
+
@client.discovered_services.clear
|
129
|
+
@client.discovered_services <<
|
130
|
+
Google::APIClient::Service.new('magic', 'v1', {})
|
131
|
+
@client.discovered_services <<
|
132
|
+
Google::APIClient::Service.new('magic', 'v1.1', {})
|
133
|
+
@client.discovered_services <<
|
134
|
+
Google::APIClient::Service.new('magic', 'v1.10', {})
|
135
|
+
@client.discovered_services <<
|
136
|
+
Google::APIClient::Service.new('magic', 'v10.0.1', {})
|
137
|
+
@client.discovered_services <<
|
138
|
+
Google::APIClient::Service.new('magic', 'v10.1', {})
|
139
|
+
@client.discovered_services <<
|
140
|
+
Google::APIClient::Service.new('magic', 'v2.1', {})
|
141
|
+
@client.discovered_services <<
|
142
|
+
Google::APIClient::Service.new('magic', 'v10.0', {})
|
143
|
+
@client.latest_service_version('magic').version.should == 'v10.1'
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'should correctly determine the latest version' do
|
147
|
+
# Sanity check the algorithm
|
148
|
+
@client.discovered_services.clear
|
149
|
+
@client.discovered_services <<
|
150
|
+
Google::APIClient::Service.new('one', 'v3', {})
|
151
|
+
@client.discovered_services <<
|
152
|
+
Google::APIClient::Service.new('two', 'v1', {})
|
153
|
+
@client.discovered_services <<
|
154
|
+
Google::APIClient::Service.new('two', 'v1.1-r1c3', {})
|
155
|
+
@client.discovered_services <<
|
156
|
+
Google::APIClient::Service.new('two', 'v2', {})
|
157
|
+
@client.discovered_services <<
|
158
|
+
Google::APIClient::Service.new('two', 'v2beta1', {})
|
159
|
+
@client.latest_service_version('two').version.should == 'v2'
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'should return nil for bogus service names' do
|
163
|
+
# Sanity check the algorithm
|
164
|
+
@client.latest_service_version('bogus').should == nil
|
165
|
+
end
|
166
|
+
|
167
|
+
it 'should generate valid requests' do
|
168
|
+
request = @client.generate_request(
|
169
|
+
'prediction.training.insert',
|
170
|
+
{'query' => '12345'}
|
171
|
+
)
|
172
|
+
method, uri, headers, body = request
|
173
|
+
method.should == 'POST'
|
174
|
+
uri.should ==
|
175
|
+
'https://www.googleapis.com/prediction/v1/training?query=12345'
|
176
|
+
(headers.inject({}) { |h,(k,v)| h[k]=v; h }).should == {}
|
177
|
+
body.should respond_to(:each)
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'should generate requests against the correct URIs' do
|
181
|
+
request = @client.generate_request(
|
182
|
+
:'prediction.training.insert',
|
183
|
+
{'query' => '12345'}
|
184
|
+
)
|
185
|
+
method, uri, headers, body = request
|
186
|
+
uri.should ==
|
187
|
+
'https://www.googleapis.com/prediction/v1/training?query=12345'
|
188
|
+
end
|
189
|
+
|
190
|
+
it 'should generate requests against the correct URIs' do
|
191
|
+
prediction = @client.discovered_service('prediction', 'v1')
|
192
|
+
request = @client.generate_request(
|
193
|
+
prediction.training.insert,
|
194
|
+
{'query' => '12345'}
|
195
|
+
)
|
196
|
+
method, uri, headers, body = request
|
197
|
+
uri.should ==
|
198
|
+
'https://www.googleapis.com/prediction/v1/training?query=12345'
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'should generate signed requests' do
|
202
|
+
@client.authorization = :oauth_1
|
203
|
+
@client.authorization.token_credential_key = '12345'
|
204
|
+
@client.authorization.token_credential_secret = '12345'
|
205
|
+
request = @client.generate_request(
|
206
|
+
'prediction.training.insert',
|
207
|
+
{'query' => '12345'}
|
208
|
+
)
|
209
|
+
method, uri, headers, body = request
|
210
|
+
headers = headers.inject({}) { |h,(k,v)| h[k]=v; h }
|
211
|
+
headers.keys.should include('Authorization')
|
212
|
+
headers['Authorization'].should =~ /^OAuth/
|
213
|
+
end
|
214
|
+
|
215
|
+
it 'should not be able to execute improperly authorized requests' do
|
216
|
+
@client.authorization = :oauth_1
|
217
|
+
@client.authorization.token_credential_key = '12345'
|
218
|
+
@client.authorization.token_credential_secret = '12345'
|
219
|
+
response = @client.execute(
|
220
|
+
'prediction.training.insert',
|
221
|
+
{'query' => '12345'}
|
222
|
+
)
|
223
|
+
status, headers, body = response
|
224
|
+
status.should == 401
|
225
|
+
end
|
226
|
+
|
227
|
+
it 'should raise an error for bogus methods' do
|
228
|
+
(lambda do
|
229
|
+
@client.generate_request(42)
|
230
|
+
end).should raise_error(TypeError)
|
231
|
+
end
|
232
|
+
|
233
|
+
it 'should raise an error for bogus methods' do
|
234
|
+
(lambda do
|
235
|
+
@client.generate_request(@client.discovered_service('prediction'))
|
236
|
+
end).should raise_error(TypeError)
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
describe Google::APIClient, 'configured for the buzz API' do
|
241
|
+
before do
|
242
|
+
@client = Google::APIClient.new(:service => 'buzz')
|
243
|
+
end
|
244
|
+
|
245
|
+
it 'should correctly determine the discovery URI' do
|
246
|
+
@client.discovery_uri.should ===
|
247
|
+
'http://www.googleapis.com/discovery/0.1/describe?api=buzz'
|
248
|
+
end
|
249
|
+
|
250
|
+
it 'should find APIs that are in the discovery document' do
|
251
|
+
@client.discovered_service('buzz').name.should == 'buzz'
|
252
|
+
@client.discovered_service('buzz').version.should == 'v1'
|
253
|
+
end
|
254
|
+
|
255
|
+
it 'should not find APIs that are not in the discovery document' do
|
256
|
+
@client.discovered_service('bogus').should == nil
|
257
|
+
end
|
258
|
+
|
259
|
+
it 'should find methods that are in the discovery document' do
|
260
|
+
# TODO(bobaman) Fix this when the RPC names are correct
|
261
|
+
@client.discovered_method('chili.activities.list').name.should == 'list'
|
262
|
+
end
|
263
|
+
|
264
|
+
it 'should not find methods that are not in the discovery document' do
|
265
|
+
@client.discovered_method('buzz.bogus').should == nil
|
266
|
+
end
|
267
|
+
|
268
|
+
it 'should generate requests against the correct URIs' do
|
269
|
+
# TODO(bobaman) Fix this when the RPC names are correct
|
270
|
+
request = @client.generate_request(
|
271
|
+
'chili.activities.list',
|
272
|
+
{'userId' => 'hikingfan', 'scope' => '@public'},
|
273
|
+
'',
|
274
|
+
[],
|
275
|
+
{:signed => false}
|
276
|
+
)
|
277
|
+
method, uri, headers, body = request
|
278
|
+
uri.should ==
|
279
|
+
'https://www.googleapis.com/buzz/v1/activities/hikingfan/@public'
|
280
|
+
end
|
281
|
+
|
282
|
+
it 'should correctly validate parameters' do
|
283
|
+
# TODO(bobaman) Fix this when the RPC names are correct
|
284
|
+
(lambda do
|
285
|
+
@client.generate_request(
|
286
|
+
'chili.activities.list',
|
287
|
+
{'alt' => 'json'},
|
288
|
+
'',
|
289
|
+
[],
|
290
|
+
{:signed => false}
|
291
|
+
)
|
292
|
+
end).should raise_error(ArgumentError)
|
293
|
+
end
|
294
|
+
|
295
|
+
it 'should correctly validate parameters' do
|
296
|
+
# TODO(bobaman) Fix this when the RPC names are correct
|
297
|
+
(lambda do
|
298
|
+
@client.generate_request(
|
299
|
+
'chili.activities.list',
|
300
|
+
{'userId' => 'hikingfan', 'scope' => '@bogus'},
|
301
|
+
'',
|
302
|
+
[],
|
303
|
+
{:signed => false}
|
304
|
+
)
|
305
|
+
end).should raise_error(ArgumentError)
|
306
|
+
end
|
307
|
+
|
308
|
+
it 'should be able to execute requests without authorization' do
|
309
|
+
# TODO(bobaman) Fix this when the RPC names are correct
|
310
|
+
response = @client.execute(
|
311
|
+
'chili.activities.list',
|
312
|
+
{'alt' => 'json', 'userId' => 'hikingfan', 'scope' => '@public'},
|
313
|
+
'',
|
314
|
+
[],
|
315
|
+
{:signed => false}
|
316
|
+
)
|
317
|
+
status, headers, body = response
|
318
|
+
status.should == 200
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
describe Google::APIClient, 'configured for the latitude API' do
|
323
|
+
before do
|
324
|
+
@client = Google::APIClient.new(:service => 'latitude')
|
325
|
+
end
|
326
|
+
|
327
|
+
it 'should correctly determine the discovery URI' do
|
328
|
+
@client.discovery_uri.should ===
|
329
|
+
'http://www.googleapis.com/discovery/0.1/describe?api=latitude'
|
330
|
+
end
|
331
|
+
|
332
|
+
it 'should find APIs that are in the discovery document' do
|
333
|
+
@client.discovered_service('latitude').name.should == 'latitude'
|
334
|
+
@client.discovered_service('latitude').version.should == 'v1'
|
335
|
+
end
|
336
|
+
|
337
|
+
it 'should not find APIs that are not in the discovery document' do
|
338
|
+
@client.discovered_service('bogus').should == nil
|
339
|
+
end
|
340
|
+
|
341
|
+
it 'should find methods that are in the discovery document' do
|
342
|
+
@client.discovered_method('latitude.currentLocation.get').name.should ==
|
343
|
+
'get'
|
344
|
+
end
|
345
|
+
|
346
|
+
it 'should not find methods that are not in the discovery document' do
|
347
|
+
@client.discovered_method('latitude.bogus').should == nil
|
348
|
+
end
|
349
|
+
|
350
|
+
it 'should generate requests against the correct URIs' do
|
351
|
+
request = @client.generate_request(
|
352
|
+
'latitude.currentLocation.get',
|
353
|
+
{},
|
354
|
+
'',
|
355
|
+
[],
|
356
|
+
{:signed => false}
|
357
|
+
)
|
358
|
+
method, uri, headers, body = request
|
359
|
+
uri.should ==
|
360
|
+
'https://www.googleapis.com/latitude/v1/currentLocation'
|
361
|
+
end
|
362
|
+
|
363
|
+
it 'should not be able to execute requests without authorization' do
|
364
|
+
response = @client.execute(
|
365
|
+
'latitude.currentLocation.get',
|
366
|
+
{},
|
367
|
+
'',
|
368
|
+
[],
|
369
|
+
{:signed => false}
|
370
|
+
)
|
371
|
+
status, headers, body = response
|
372
|
+
status.should == 401
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
describe Google::APIClient, 'configured for the moderator API' do
|
377
|
+
before do
|
378
|
+
@client = Google::APIClient.new(:service => 'moderator')
|
379
|
+
end
|
380
|
+
|
381
|
+
it 'should correctly determine the discovery URI' do
|
382
|
+
@client.discovery_uri.should ===
|
383
|
+
'http://www.googleapis.com/discovery/0.1/describe?api=moderator'
|
384
|
+
end
|
385
|
+
|
386
|
+
it 'should find APIs that are in the discovery document' do
|
387
|
+
@client.discovered_service('moderator').name.should == 'moderator'
|
388
|
+
@client.discovered_service('moderator').version.should == 'v1'
|
389
|
+
end
|
390
|
+
|
391
|
+
it 'should not find APIs that are not in the discovery document' do
|
392
|
+
@client.discovered_service('bogus').should == nil
|
393
|
+
end
|
394
|
+
|
395
|
+
it 'should find methods that are in the discovery document' do
|
396
|
+
@client.discovered_method('moderator.profiles.get').name.should ==
|
397
|
+
'get'
|
398
|
+
end
|
399
|
+
|
400
|
+
it 'should not find methods that are not in the discovery document' do
|
401
|
+
@client.discovered_method('moderator.bogus').should == nil
|
402
|
+
end
|
403
|
+
|
404
|
+
it 'should generate requests against the correct URIs' do
|
405
|
+
request = @client.generate_request(
|
406
|
+
'moderator.profiles.get',
|
407
|
+
{},
|
408
|
+
'',
|
409
|
+
[],
|
410
|
+
{:signed => false}
|
411
|
+
)
|
412
|
+
method, uri, headers, body = request
|
413
|
+
uri.should ==
|
414
|
+
'https://www.googleapis.com/moderator/v1/profiles/@me'
|
415
|
+
end
|
416
|
+
|
417
|
+
it 'should not be able to execute requests without authorization' do
|
418
|
+
response = @client.execute(
|
419
|
+
'moderator.profiles.get',
|
420
|
+
{},
|
421
|
+
'',
|
422
|
+
[],
|
423
|
+
{:signed => false}
|
424
|
+
)
|
425
|
+
status, headers, body = response
|
426
|
+
status.should == 401
|
427
|
+
end
|
428
|
+
end
|