google-api-client 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -12,81 +12,113 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+
15
16
  require 'json'
16
17
  require 'addressable/uri'
17
18
  require 'addressable/template'
18
- require 'extlib/inflection'
19
+
20
+ require 'google/inflection'
21
+ require 'google/api_client/errors'
19
22
 
20
23
  module Google
21
24
  class APIClient
22
- ##
23
- # An exception that is raised if a method is called with missing or
24
- # invalid parameter values.
25
- class ValidationError < StandardError
26
- end
27
-
28
25
  ##
29
26
  # A service that has been described by a discovery document.
30
- class Service
27
+ class API
31
28
 
32
29
  ##
33
30
  # Creates a description of a particular version of a service.
34
31
  #
35
- # @param [String] service_name
32
+ # @param [String] api
36
33
  # The identifier for the service. Note that while this frequently
37
34
  # matches the first segment of all of the service's RPC names, this
38
35
  # should not be assumed. There is no requirement that these match.
39
- # @param [String] service_version
36
+ # @param [String] version
40
37
  # The identifier for the service version.
41
- # @param [Hash] service_description
38
+ # @param [Hash] api_description
42
39
  # The section of the discovery document that applies to this service
43
40
  # version.
44
41
  #
45
- # @return [Google::APIClient::Service] The constructed service object.
46
- def initialize(service_name, service_version, service_description)
47
- @name = service_name
48
- @version = service_version
49
- @description = service_description
42
+ # @return [Google::APIClient::API] The constructed service object.
43
+ def initialize(document_base, discovery_document)
44
+ @document_base = Addressable::URI.parse(document_base)
45
+ @discovery_document = discovery_document
50
46
  metaclass = (class <<self; self; end)
51
47
  self.resources.each do |resource|
52
- method_name = Extlib::Inflection.underscore(resource.name).to_sym
48
+ method_name = Google::INFLECTOR.underscore(resource.name).to_sym
53
49
  if !self.respond_to?(method_name)
54
50
  metaclass.send(:define_method, method_name) { resource }
55
51
  end
56
52
  end
57
53
  self.methods.each do |method|
58
- method_name = Extlib::Inflection.underscore(method.name).to_sym
54
+ method_name = Google::INFLECTOR.underscore(method.name).to_sym
59
55
  if !self.respond_to?(method_name)
60
56
  metaclass.send(:define_method, method_name) { method }
61
57
  end
62
58
  end
63
59
  end
64
60
 
61
+ ##
62
+ # Returns the id of the service.
63
+ #
64
+ # @return [String] The service id.
65
+ def id
66
+ return @discovery_document['id']
67
+ end
68
+
65
69
  ##
66
70
  # Returns the identifier for the service.
67
71
  #
68
72
  # @return [String] The service identifier.
69
- attr_reader :name
73
+ def name
74
+ return @discovery_document['name']
75
+ end
70
76
 
71
77
  ##
72
78
  # Returns the version of the service.
73
79
  #
74
80
  # @return [String] The service version.
75
- attr_reader :version
81
+ def version
82
+ return @discovery_document['version']
83
+ end
76
84
 
77
85
  ##
78
86
  # Returns the parsed section of the discovery document that applies to
79
87
  # this version of the service.
80
88
  #
81
89
  # @return [Hash] The service description.
82
- attr_reader :description
90
+ def description
91
+ return @discovery_document['description']
92
+ end
93
+
94
+ ##
95
+ # Returns true if this is the preferred version of this API.
96
+ #
97
+ # @return [TrueClass, FalseClass]
98
+ # Whether or not this is the preferred version of this API.
99
+ def preferred
100
+ return @discovery_document['preferred']
101
+ end
102
+
103
+ ##
104
+ # Returns the base URI for the discovery document.
105
+ #
106
+ # @return [Addressable::URI] The base URI.
107
+ attr_reader :document_base
83
108
 
84
109
  ##
85
110
  # Returns the base URI for this version of the service.
86
111
  #
87
112
  # @return [Addressable::URI] The base URI that methods are joined to.
88
- def base
89
- return @base ||= Addressable::URI.parse(self.description['baseUrl'])
113
+ def method_base
114
+ if @discovery_document['basePath']
115
+ return @method_base ||= (
116
+ self.document_base +
117
+ Addressable::URI.parse(@discovery_document['basePath'])
118
+ ).normalize
119
+ else
120
+ return nil
121
+ end
90
122
  end
91
123
 
92
124
  ##
@@ -94,13 +126,13 @@ module Google
94
126
  #
95
127
  # @param [Addressable::URI, #to_str, String] new_base
96
128
  # The new base URI to use for the service.
97
- def base=(new_base)
98
- @base = Addressable::URI.parse(new_base)
129
+ def method_base=(new_method_base)
130
+ @method_base = Addressable::URI.parse(new_method_base)
99
131
  self.resources.each do |resource|
100
- resource.base = @base
132
+ resource.method_base = @method_base
101
133
  end
102
134
  self.methods.each do |method|
103
- method.base = @base
135
+ method.method_base = @method_base
104
136
  end
105
137
  end
106
138
 
@@ -111,8 +143,8 @@ module Google
111
143
  # @return [Array] A list of {Google::APIClient::Resource} objects.
112
144
  def resources
113
145
  return @resources ||= (
114
- (self.description['resources'] || []).inject([]) do |accu, (k, v)|
115
- accu << ::Google::APIClient::Resource.new(self.base, k, v)
146
+ (@discovery_document['resources'] || []).inject([]) do |accu, (k, v)|
147
+ accu << ::Google::APIClient::Resource.new(self.method_base, k, v)
116
148
  accu
117
149
  end
118
150
  )
@@ -125,8 +157,8 @@ module Google
125
157
  # @return [Array] A list of {Google::APIClient::Method} objects.
126
158
  def methods
127
159
  return @methods ||= (
128
- (self.description['methods'] || []).inject([]) do |accu, (k, v)|
129
- accu << ::Google::APIClient::Method.new(self.base, k, v)
160
+ (@discovery_document['methods'] || []).inject([]) do |accu, (k, v)|
161
+ accu << ::Google::APIClient::Method.new(self.method_base, k, v)
130
162
  accu
131
163
  end
132
164
  )
@@ -139,12 +171,12 @@ module Google
139
171
  #
140
172
  # @example
141
173
  # # Discover available methods
142
- # method_names = client.discovered_service('buzz').to_h.keys
174
+ # method_names = client.discovered_api('buzz').to_h.keys
143
175
  def to_h
144
176
  return @hash ||= (begin
145
177
  methods_hash = {}
146
178
  self.methods.each do |method|
147
- methods_hash[method.rpc_name] = method
179
+ methods_hash[method.id] = method
148
180
  end
149
181
  self.resources.each do |resource|
150
182
  methods_hash.merge!(resource.to_h)
@@ -153,55 +185,13 @@ module Google
153
185
  end)
154
186
  end
155
187
 
156
- ##
157
- # Compares two versions of a service.
158
- #
159
- # @param [Object] other The service to compare.
160
- #
161
- # @return [Integer]
162
- # <code>-1</code> if the service is older than <code>other</code>.
163
- # <code>0</code> if the service is the same as <code>other</code>.
164
- # <code>1</code> if the service is newer than <code>other</code>.
165
- # <code>nil</code> if the service cannot be compared to
166
- # <code>other</code>.
167
- def <=>(other)
168
- # We can only compare versions of the same service
169
- if other.kind_of?(self.class) && self.name == other.name
170
- split_version = lambda do |version|
171
- dotted_version = version[/^v?(\d+(.\d+)*)-?(.*?)?$/, 1]
172
- suffix = version[/^v?(\d+(.\d+)*)-?(.*?)?$/, 3]
173
- if dotted_version && suffix
174
- [dotted_version.split('.').map { |v| v.to_i }, suffix]
175
- else
176
- [[-1], version]
177
- end
178
- end
179
- self_sortable, self_suffix = split_version.call(self.version)
180
- other_sortable, other_suffix = split_version.call(other.version)
181
- result = self_sortable <=> other_sortable
182
- if result != 0
183
- return result
184
- # If the dotted versions are equal, check the suffix.
185
- # An omitted suffix should be sorted after an included suffix.
186
- elsif self_suffix == ''
187
- return 1
188
- elsif other_suffix == ''
189
- return -1
190
- else
191
- return self_suffix <=> other_suffix
192
- end
193
- else
194
- return nil
195
- end
196
- end
197
-
198
188
  ##
199
189
  # Returns a <code>String</code> representation of the service's state.
200
190
  #
201
191
  # @return [String] The service's state, as a <code>String</code>.
202
192
  def inspect
203
193
  sprintf(
204
- "#<%s:%#0x NAME:%s>", self.class.to_s, self.object_id, self.name
194
+ "#<%s:%#0x ID:%s>", self.class.to_s, self.object_id, self.id
205
195
  )
206
196
  end
207
197
  end
@@ -221,19 +211,19 @@ module Google
221
211
  # The section of the discovery document that applies to this resource.
222
212
  #
223
213
  # @return [Google::APIClient::Resource] The constructed resource object.
224
- def initialize(base, resource_name, resource_description)
225
- @base = base
214
+ def initialize(method_base, resource_name, discovery_document)
215
+ @method_base = method_base
226
216
  @name = resource_name
227
- @description = resource_description
217
+ @discovery_document = discovery_document
228
218
  metaclass = (class <<self; self; end)
229
219
  self.resources.each do |resource|
230
- method_name = Extlib::Inflection.underscore(resource.name).to_sym
220
+ method_name = Google::INFLECTOR.underscore(resource.name).to_sym
231
221
  if !self.respond_to?(method_name)
232
222
  metaclass.send(:define_method, method_name) { resource }
233
223
  end
234
224
  end
235
225
  self.methods.each do |method|
236
- method_name = Extlib::Inflection.underscore(method.name).to_sym
226
+ method_name = Google::INFLECTOR.underscore(method.name).to_sym
237
227
  if !self.respond_to?(method_name)
238
228
  metaclass.send(:define_method, method_name) { method }
239
229
  end
@@ -257,20 +247,20 @@ module Google
257
247
  # Returns the base URI for this resource.
258
248
  #
259
249
  # @return [Addressable::URI] The base URI that methods are joined to.
260
- attr_reader :base
250
+ attr_reader :method_base
261
251
 
262
252
  ##
263
253
  # Updates the hierarchy of resources and methods with the new base.
264
254
  #
265
255
  # @param [Addressable::URI, #to_str, String] new_base
266
256
  # The new base URI to use for the resource.
267
- def base=(new_base)
268
- @base = Addressable::URI.parse(new_base)
257
+ def method_base=(new_method_base)
258
+ @method_base = Addressable::URI.parse(new_method_base)
269
259
  self.resources.each do |resource|
270
- resource.base = @base
260
+ resource.method_base = @method_base
271
261
  end
272
262
  self.methods.each do |method|
273
- method.base = @base
263
+ method.method_base = @method_base
274
264
  end
275
265
  end
276
266
 
@@ -280,8 +270,8 @@ module Google
280
270
  # @return [Array] A list of {Google::APIClient::Resource} objects.
281
271
  def resources
282
272
  return @resources ||= (
283
- (self.description['resources'] || []).inject([]) do |accu, (k, v)|
284
- accu << ::Google::APIClient::Resource.new(self.base, k, v)
273
+ (@discovery_document['resources'] || []).inject([]) do |accu, (k, v)|
274
+ accu << ::Google::APIClient::Resource.new(self.method_base, k, v)
285
275
  accu
286
276
  end
287
277
  )
@@ -293,8 +283,8 @@ module Google
293
283
  # @return [Array] A list of {Google::APIClient::Method} objects.
294
284
  def methods
295
285
  return @methods ||= (
296
- (self.description['methods'] || []).inject([]) do |accu, (k, v)|
297
- accu << ::Google::APIClient::Method.new(self.base, k, v)
286
+ (@discovery_document['methods'] || []).inject([]) do |accu, (k, v)|
287
+ accu << ::Google::APIClient::Method.new(self.method_base, k, v)
298
288
  accu
299
289
  end
300
290
  )
@@ -309,7 +299,7 @@ module Google
309
299
  return @hash ||= (begin
310
300
  methods_hash = {}
311
301
  self.methods.each do |method|
312
- methods_hash[method.rpc_name] = method
302
+ methods_hash[method.id] = method
313
303
  end
314
304
  self.resources.each do |resource|
315
305
  methods_hash.merge!(resource.to_h)
@@ -336,7 +326,7 @@ module Google
336
326
  ##
337
327
  # Creates a description of a particular method.
338
328
  #
339
- # @param [Addressable::URI] base
329
+ # @param [Addressable::URI] method_base
340
330
  # The base URI for the service.
341
331
  # @param [String] method_name
342
332
  # The identifier for the method.
@@ -344,10 +334,10 @@ module Google
344
334
  # The section of the discovery document that applies to this method.
345
335
  #
346
336
  # @return [Google::APIClient::Method] The constructed method object.
347
- def initialize(base, method_name, method_description)
348
- @base = base
337
+ def initialize(method_base, method_name, discovery_document)
338
+ @method_base = method_base
349
339
  @name = method_name
350
- @description = method_description
340
+ @discovery_document = discovery_document
351
341
  end
352
342
 
353
343
  ##
@@ -368,24 +358,24 @@ module Google
368
358
  #
369
359
  # @return [Addressable::URI]
370
360
  # The base URI that this method will be joined to.
371
- attr_reader :base
361
+ attr_reader :method_base
372
362
 
373
363
  ##
374
364
  # Updates the method with the new base.
375
365
  #
376
366
  # @param [Addressable::URI, #to_str, String] new_base
377
367
  # The new base URI to use for the method.
378
- def base=(new_base)
379
- @base = Addressable::URI.parse(new_base)
368
+ def method_base=(new_method_base)
369
+ @method_base = Addressable::URI.parse(new_method_base)
380
370
  @uri_template = nil
381
371
  end
382
372
 
383
373
  ##
384
- # Returns the RPC name for the method.
374
+ # Returns the method ID.
385
375
  #
386
- # @return [String] The RPC name.
387
- def rpc_name
388
- return self.description['rpcName']
376
+ # @return [String] The method identifier.
377
+ def id
378
+ return @discovery_document['id']
389
379
  end
390
380
 
391
381
  ##
@@ -398,8 +388,9 @@ module Google
398
388
  # a join operation on a URI, but we have to treat these as Strings
399
389
  # because of the way the discovery document provides the URIs.
400
390
  # This should be fixed soon.
401
- return @uri_template ||=
402
- Addressable::Template.new(base.to_s + self.description['pathUrl'])
391
+ return @uri_template ||= Addressable::Template.new(
392
+ self.method_base + @discovery_document['path']
393
+ )
403
394
  end
404
395
 
405
396
  ##
@@ -474,7 +465,7 @@ module Google
474
465
  if !headers.kind_of?(Array) && !headers.kind_of?(Hash)
475
466
  raise TypeError, "Expected Hash or Array, got #{headers.class}."
476
467
  end
477
- method = self.description['httpMethod'] || 'GET'
468
+ method = @discovery_document['httpMethod'] || 'GET'
478
469
  uri = self.generate_uri(parameters)
479
470
  headers = headers.to_a if headers.kind_of?(Hash)
480
471
  return [method, uri.to_str, headers, [body]]
@@ -487,7 +478,7 @@ module Google
487
478
  # @return [Hash] The parameter descriptions.
488
479
  def parameter_descriptions
489
480
  @parameter_descriptions ||= (
490
- self.description['parameters'] || {}
481
+ @discovery_document['parameters'] || {}
491
482
  ).inject({}) { |h,(k,v)| h[k]=v; h }
492
483
  end
493
484
 
@@ -497,7 +488,7 @@ module Google
497
488
  # @return [Array] The parameters.
498
489
  def parameters
499
490
  @parameters ||= ((
500
- self.description['parameters'] || {}
491
+ @discovery_document['parameters'] || {}
501
492
  ).inject({}) { |h,(k,v)| h[k]=v; h }).keys
502
493
  end
503
494
 
@@ -551,6 +542,12 @@ module Google
551
542
  end
552
543
  parameters.each do |k, v|
553
544
  if self.parameter_descriptions[k]
545
+ enum = self.parameter_descriptions[k]['enum']
546
+ if enum && !enum.include?(v)
547
+ raise ArgumentError,
548
+ "Parameter '#{k}' has an invalid value: #{v}. " +
549
+ "Must be one of #{enum.inspect}."
550
+ end
554
551
  pattern = self.parameter_descriptions[k]['pattern']
555
552
  if pattern
556
553
  regexp = Regexp.new("^#{pattern}$")
@@ -571,7 +568,8 @@ module Google
571
568
  # @return [String] The method's state, as a <code>String</code>.
572
569
  def inspect
573
570
  sprintf(
574
- "#<%s:%#0x NAME:%s>", self.class.to_s, self.object_id, self.rpc_name
571
+ "#<%s:%#0x ID:%s>",
572
+ self.class.to_s, self.object_id, self.id
575
573
  )
576
574
  end
577
575
  end
@@ -0,0 +1,13 @@
1
+ module Google
2
+ class APIClient
3
+ module ENV
4
+ OS_VERSION = if RUBY_PLATFORM =~ /win32/
5
+ `ver`.sub(/\s*\[Version\s*/, '/').sub(']', '')
6
+ elsif RUBY_PLATFORM =~ /darwin/i
7
+ "Mac OS X/#{`sw_vers -productVersion`}"
8
+ else
9
+ `uname -sr`.sub(' ', '/')
10
+ end
11
+ end
12
+ end
13
+ end