google-api-client 0.7.1 → 0.8.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.
Files changed (56) hide show
  1. checksums.yaml +13 -5
  2. data/CHANGELOG.md +14 -0
  3. data/Gemfile +0 -36
  4. data/README.md +12 -1
  5. data/Rakefile +1 -8
  6. data/google-api-client.gemspec +40 -0
  7. data/lib/google/api_client.rb +98 -30
  8. data/lib/google/api_client/auth/compute_service_account.rb +1 -1
  9. data/lib/google/api_client/auth/file_storage.rb +19 -44
  10. data/lib/google/api_client/auth/installed_app.rb +11 -7
  11. data/lib/google/api_client/auth/storage.rb +101 -0
  12. data/lib/google/api_client/auth/storages/file_store.rb +58 -0
  13. data/lib/google/api_client/auth/storages/redis_store.rb +54 -0
  14. data/lib/google/api_client/batch.rb +13 -11
  15. data/lib/google/api_client/charset.rb +33 -0
  16. data/lib/google/api_client/client_secrets.rb +9 -6
  17. data/lib/google/api_client/discovery/api.rb +3 -3
  18. data/lib/google/api_client/discovery/resource.rb +3 -3
  19. data/lib/google/api_client/discovery/schema.rb +3 -5
  20. data/lib/google/api_client/errors.rb +5 -0
  21. data/lib/google/api_client/railtie.rb +2 -1
  22. data/lib/google/api_client/request.rb +1 -2
  23. data/lib/google/api_client/result.rb +4 -2
  24. data/lib/google/api_client/service.rb +2 -2
  25. data/lib/google/api_client/service/batch.rb +7 -0
  26. data/lib/google/api_client/service/stub_generator.rb +4 -2
  27. data/lib/google/api_client/service_account.rb +3 -0
  28. data/lib/google/api_client/version.rb +8 -13
  29. data/spec/google/api_client/auth/storage_spec.rb +122 -0
  30. data/spec/google/api_client/auth/storages/file_store_spec.rb +40 -0
  31. data/spec/google/api_client/auth/storages/redis_store_spec.rb +70 -0
  32. data/spec/google/api_client/batch_spec.rb +29 -30
  33. data/spec/google/api_client/client_secrets_spec.rb +53 -0
  34. data/spec/google/api_client/discovery_spec.rb +101 -91
  35. data/spec/google/api_client/gzip_spec.rb +21 -9
  36. data/spec/google/api_client/media_spec.rb +31 -32
  37. data/spec/google/api_client/request_spec.rb +3 -4
  38. data/spec/google/api_client/result_spec.rb +51 -47
  39. data/spec/google/api_client/service_account_spec.rb +40 -35
  40. data/spec/google/api_client/service_spec.rb +144 -112
  41. data/spec/google/api_client/simple_file_store_spec.rb +30 -34
  42. data/spec/google/api_client_spec.rb +139 -40
  43. data/spec/spec_helper.rb +9 -1
  44. metadata +111 -88
  45. data/CONTRIBUTING.md +0 -32
  46. data/lib/cacerts.pem +0 -2183
  47. data/lib/google/inflection.rb +0 -28
  48. data/spec/fixtures/files/privatekey.p12 +0 -0
  49. data/spec/fixtures/files/sample.txt +0 -33
  50. data/spec/fixtures/files/secret.pem +0 -19
  51. data/tasks/gem.rake +0 -97
  52. data/tasks/git.rake +0 -45
  53. data/tasks/metrics.rake +0 -22
  54. data/tasks/spec.rake +0 -57
  55. data/tasks/wiki.rake +0 -82
  56. data/tasks/yard.rake +0 -29
@@ -26,7 +26,7 @@ module Google
26
26
  # client = Google::APIClient.new
27
27
  # flow = Google::APIClient::InstalledAppFlow.new(
28
28
  # :client_id => '691380668085.apps.googleusercontent.com',
29
- # :client_secret => '...,
29
+ # :client_secret => '...',
30
30
  # :scope => 'https://www.googleapis.com/auth/drive'
31
31
  # )
32
32
  # client.authorization = flow.authorize
@@ -92,9 +92,10 @@ module Google
92
92
  :Logger => WEBrick::Log.new(STDOUT, 0),
93
93
  :AccessLog => []
94
94
  )
95
- trap("INT") { server.shutdown }
96
-
97
- server.mount_proc '/' do |req, res|
95
+ begin
96
+ trap("INT") { server.shutdown }
97
+
98
+ server.mount_proc '/' do |req, res|
98
99
  auth.code = req.query['code']
99
100
  if auth.code
100
101
  auth.fetch_access_token!
@@ -102,10 +103,13 @@ module Google
102
103
  res.status = WEBrick::HTTPStatus::RC_ACCEPTED
103
104
  res.body = RESPONSE_BODY
104
105
  server.stop
105
- end
106
+ end
106
107
 
107
- Launchy.open(auth.authorization_uri.to_s)
108
- server.start
108
+ Launchy.open(auth.authorization_uri.to_s)
109
+ server.start
110
+ ensure
111
+ server.shutdown
112
+ end
109
113
  if @authorization.access_token
110
114
  if storage.respond_to?(:write_credentials)
111
115
  storage.write_credentials(@authorization)
@@ -0,0 +1,101 @@
1
+ # Copyright 2013 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 'signet/oauth_2/client'
16
+
17
+ module Google
18
+ class APIClient
19
+ ##
20
+ # Represents cached OAuth 2 tokens stored on local disk in a
21
+ # JSON serialized file. Meant to resemble the serialized format
22
+ # http://google-api-python-client.googlecode.com/hg/docs/epy/oauth2client.file.Storage-class.html
23
+ #
24
+ class Storage
25
+
26
+ AUTHORIZATION_URI = 'https://accounts.google.com/o/oauth2/auth'
27
+ TOKEN_CREDENTIAL_URI = 'https://accounts.google.com/o/oauth2/token'
28
+
29
+ # @return [Object] Storage object.
30
+ attr_accessor :store
31
+
32
+ # @return [Signet::OAuth2::Client]
33
+ attr_reader :authorization
34
+
35
+ ##
36
+ # Initializes the Storage object.
37
+ #
38
+ # @params [Object] Storage object
39
+ def initialize(store)
40
+ @store= store
41
+ end
42
+
43
+ ##
44
+ # Write the credentials to the specified store.
45
+ #
46
+ # @params [Signet::OAuth2::Client] authorization
47
+ # Optional authorization instance. If not provided, the authorization
48
+ # already associated with this instance will be written.
49
+ def write_credentials(authorization=nil)
50
+ @authorization = authorization if authorization
51
+ if @authorization.respond_to?(:refresh_token) && @authorization.refresh_token
52
+ store.write_credentials(credentials_hash)
53
+ end
54
+ end
55
+
56
+ ##
57
+ # Loads credentials and authorizes an client.
58
+ # @return [Object] Signet::OAuth2::Client or NIL
59
+ def authorize
60
+ @authorization = nil
61
+ cached_credentials = load_credentials
62
+ if cached_credentials && cached_credentials.size > 0
63
+ @authorization = Signet::OAuth2::Client.new(cached_credentials)
64
+ @authorization.issued_at = Time.at(cached_credentials['issued_at'].to_i)
65
+ self.refresh_authorization if @authorization.expired?
66
+ end
67
+ return @authorization
68
+ end
69
+
70
+ ##
71
+ # refresh credentials and save them to store
72
+ def refresh_authorization
73
+ authorization.refresh!
74
+ self.write_credentials
75
+ end
76
+
77
+ private
78
+
79
+ ##
80
+ # Attempt to read in credentials from the specified store.
81
+ def load_credentials
82
+ store.load_credentials
83
+ end
84
+
85
+ ##
86
+ # @return [Hash] with credentials
87
+ def credentials_hash
88
+ {
89
+ :access_token => authorization.access_token,
90
+ :authorization_uri => AUTHORIZATION_URI,
91
+ :client_id => authorization.client_id,
92
+ :client_secret => authorization.client_secret,
93
+ :expires_in => authorization.expires_in,
94
+ :refresh_token => authorization.refresh_token,
95
+ :token_credential_uri => TOKEN_CREDENTIAL_URI,
96
+ :issued_at => authorization.issued_at.to_i
97
+ }
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,58 @@
1
+ # Copyright 2013 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
+ # Represents cached OAuth 2 tokens stored on local disk in a
21
+ # JSON serialized file. Meant to resemble the serialized format
22
+ # http://google-api-python-client.googlecode.com/hg/docs/epy/oauth2client.file.Storage-class.html
23
+ #
24
+ class FileStore
25
+
26
+ attr_accessor :path
27
+
28
+ ##
29
+ # Initializes the FileStorage object.
30
+ #
31
+ # @param [String] path
32
+ # Path to the credentials file.
33
+ def initialize(path)
34
+ @path= path
35
+ end
36
+
37
+ ##
38
+ # Attempt to read in credentials from the specified file.
39
+ def load_credentials
40
+ open(path, 'r') { |f| JSON.parse(f.read) }
41
+ rescue
42
+ nil
43
+ end
44
+
45
+ ##
46
+ # Write the credentials to the specified file.
47
+ #
48
+ # @param [Signet::OAuth2::Client] authorization
49
+ # Optional authorization instance. If not provided, the authorization
50
+ # already associated with this instance will be written.
51
+ def write_credentials(credentials_hash)
52
+ open(self.path, 'w+') do |f|
53
+ f.write(credentials_hash.to_json)
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,54 @@
1
+ # Copyright 2013 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
+ class RedisStore
20
+
21
+ DEFAULT_REDIS_CREDENTIALS_KEY = "google_api_credentials"
22
+
23
+ attr_accessor :redis
24
+
25
+ ##
26
+ # Initializes the RedisStore object.
27
+ #
28
+ # @params [Object] Redis instance
29
+ def initialize(redis, key = nil)
30
+ @redis= redis
31
+ @redis_credentials_key = key
32
+ end
33
+
34
+ ##
35
+ # Attempt to read in credentials from redis.
36
+ def load_credentials
37
+ credentials = redis.get redis_credentials_key
38
+ JSON.parse(credentials) if credentials
39
+ end
40
+
41
+ def redis_credentials_key
42
+ @redis_credentials_key || DEFAULT_REDIS_CREDENTIALS_KEY
43
+ end
44
+
45
+ ##
46
+ # Write the credentials to redis.
47
+ #
48
+ # @params [Hash] credentials
49
+ def write_credentials(credentials_hash)
50
+ redis.set(redis_credentials_key, credentials_hash.to_json)
51
+ end
52
+ end
53
+ end
54
+ end
@@ -14,7 +14,7 @@
14
14
 
15
15
  require 'addressable/uri'
16
16
  require 'google/api_client/reference'
17
- require 'uuidtools'
17
+ require 'securerandom'
18
18
 
19
19
  module Google
20
20
  class APIClient
@@ -90,8 +90,7 @@ module Google
90
90
  @global_callback = block if block_given?
91
91
  @last_auto_id = 0
92
92
 
93
- # TODO(sgomes): Use SecureRandom.uuid, drop UUIDTools when we drop 1.8
94
- @base_id = UUIDTools::UUID.random_create.to_s
93
+ @base_id = SecureRandom.uuid
95
94
 
96
95
  options[:uri] ||= 'https://www.googleapis.com/batch'
97
96
  options[:http_method] ||= 'POST'
@@ -140,14 +139,17 @@ module Google
140
139
  # the HTTP response.
141
140
  def process_http_response(response)
142
141
  content_type = find_header('Content-Type', response.headers)
143
- boundary = /.*boundary=(.+)/.match(content_type)[1]
144
- parts = response.body.split(/--#{Regexp.escape(boundary)}/)
145
- parts = parts[1...-1]
146
- parts.each do |part|
147
- call_response = deserialize_call_response(part)
148
- _, call, callback = @calls.assoc(call_response.call_id)
149
- result = Google::APIClient::Result.new(call, call_response)
150
- callback.call(result) if callback
142
+ m = /.*boundary=(.+)/.match(content_type)
143
+ if m
144
+ boundary = m[1]
145
+ parts = response.body.split(/--#{Regexp.escape(boundary)}/)
146
+ parts = parts[1...-1]
147
+ parts.each do |part|
148
+ call_response = deserialize_call_response(part)
149
+ _, call, callback = @calls.assoc(call_response.call_id)
150
+ result = Google::APIClient::Result.new(call, call_response)
151
+ callback.call(result) if callback
152
+ end
151
153
  end
152
154
  Google::APIClient::Result.new(self, response)
153
155
  end
@@ -0,0 +1,33 @@
1
+ require 'faraday'
2
+ require 'zlib'
3
+
4
+ module Google
5
+ class APIClient
6
+ class Charset < Faraday::Response::Middleware
7
+ include Google::APIClient::Logging
8
+
9
+ def charset_for_content_type(type)
10
+ if type
11
+ m = type.match(/(?:charset|encoding)="?([a-z0-9-]+)"?/i)
12
+ if m
13
+ return Encoding.find(m[1])
14
+ end
15
+ end
16
+ nil
17
+ end
18
+
19
+ def adjust_encoding(env)
20
+ charset = charset_for_content_type(env[:response_headers]['content-type'])
21
+ if charset && env[:body].encoding != charset
22
+ env[:body].force_encoding(charset)
23
+ end
24
+ end
25
+
26
+ def on_complete(env)
27
+ adjust_encoding(env)
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ Faraday::Response.register_middleware :charset => Google::APIClient::Charset
@@ -13,7 +13,6 @@
13
13
  # limitations under the License.
14
14
 
15
15
 
16
- require 'multi_json'
17
16
  require 'compat/multi_json'
18
17
 
19
18
 
@@ -63,7 +62,7 @@ module Google
63
62
  end
64
63
  while filename == nil
65
64
  search_path ||= File.expand_path('.')
66
- if File.exist?(File.join(search_path, 'client_secrets.json'))
65
+ if File.exists?(File.join(search_path, 'client_secrets.json'))
67
66
  filename = File.join(search_path, 'client_secrets.json')
68
67
  elsif search_path == '/' || search_path =~ /[a-zA-Z]:[\/\\]/
69
68
  raise ArgumentError,
@@ -89,12 +88,12 @@ module Google
89
88
  @client_id = fdata[:client_id] || fdata["client_id"]
90
89
  @client_secret = fdata[:client_secret] || fdata["client_secret"]
91
90
  @redirect_uris = fdata[:redirect_uris] || fdata["redirect_uris"]
92
- @redirect_uris ||= [fdata[:redirect_uri]]
91
+ @redirect_uris ||= [fdata[:redirect_uri] || fdata["redirect_uri"]].compact
93
92
  @javascript_origins = (
94
93
  fdata[:javascript_origins] ||
95
94
  fdata["javascript_origins"]
96
95
  )
97
- @javascript_origins ||= [fdata[:javascript_origin]]
96
+ @javascript_origins ||= [fdata[:javascript_origin] || fdata["javascript_origin"]].compact
98
97
  @authorization_uri = fdata[:auth_uri] || fdata["auth_uri"]
99
98
  @authorization_uri ||= fdata[:authorization_uri]
100
99
  @token_credential_uri = fdata[:token_uri] || fdata["token_uri"]
@@ -121,7 +120,11 @@ module Google
121
120
  # @return [String]
122
121
  # JSON
123
122
  def to_json
124
- return MultiJson.dump({
123
+ return MultiJson.dump(to_hash)
124
+ end
125
+
126
+ def to_hash
127
+ {
125
128
  self.flow => ({
126
129
  'client_id' => self.client_id,
127
130
  'client_secret' => self.client_secret,
@@ -142,7 +145,7 @@ module Google
142
145
  end
143
146
  accu
144
147
  end
145
- })
148
+ }
146
149
  end
147
150
 
148
151
  def to_authorization
@@ -15,7 +15,7 @@
15
15
 
16
16
  require 'addressable/uri'
17
17
  require 'multi_json'
18
- require 'google/inflection'
18
+ require 'active_support/inflector'
19
19
  require 'google/api_client/discovery/resource'
20
20
  require 'google/api_client/discovery/method'
21
21
  require 'google/api_client/discovery/media'
@@ -41,13 +41,13 @@ module Google
41
41
  @discovery_document = discovery_document
42
42
  metaclass = (class << self; self; end)
43
43
  self.discovered_resources.each do |resource|
44
- method_name = Google::INFLECTOR.underscore(resource.name).to_sym
44
+ method_name = ActiveSupport::Inflector.underscore(resource.name).to_sym
45
45
  if !self.respond_to?(method_name)
46
46
  metaclass.send(:define_method, method_name) { resource }
47
47
  end
48
48
  end
49
49
  self.discovered_methods.each do |method|
50
- method_name = Google::INFLECTOR.underscore(method.name).to_sym
50
+ method_name = ActiveSupport::Inflector.underscore(method.name).to_sym
51
51
  if !self.respond_to?(method_name)
52
52
  metaclass.send(:define_method, method_name) { method }
53
53
  end
@@ -15,7 +15,7 @@
15
15
 
16
16
  require 'addressable/uri'
17
17
 
18
- require 'google/inflection'
18
+ require 'active_support/inflector'
19
19
  require 'google/api_client/discovery/method'
20
20
 
21
21
 
@@ -45,13 +45,13 @@ module Google
45
45
  @discovery_document = discovery_document
46
46
  metaclass = (class <<self; self; end)
47
47
  self.discovered_resources.each do |resource|
48
- method_name = Google::INFLECTOR.underscore(resource.name).to_sym
48
+ method_name = ActiveSupport::Inflector.underscore(resource.name).to_sym
49
49
  if !self.respond_to?(method_name)
50
50
  metaclass.send(:define_method, method_name) { resource }
51
51
  end
52
52
  end
53
53
  self.discovered_methods.each do |method|
54
- method_name = Google::INFLECTOR.underscore(method.name).to_sym
54
+ method_name = ActiveSupport::Inflector.underscore(method.name).to_sym
55
55
  if !self.respond_to?(method_name)
56
56
  metaclass.send(:define_method, method_name) { method }
57
57
  end
@@ -21,7 +21,7 @@ require 'autoparse'
21
21
  require 'addressable/uri'
22
22
  require 'addressable/template'
23
23
 
24
- require 'google/inflection'
24
+ require 'active_support/inflector'
25
25
  require 'google/api_client/errors'
26
26
 
27
27
 
@@ -78,10 +78,8 @@ module Google
78
78
  # puts schema_data.inspect
79
79
 
80
80
  if schema_name
81
- api_name_string =
82
- Google::INFLECTOR.camelize(api.name)
83
- api_version_string =
84
- Google::INFLECTOR.camelize(api.version).gsub('.', '_')
81
+ api_name_string = ActiveSupport::Inflector.camelize(api.name)
82
+ api_version_string = ActiveSupport::Inflector.camelize(api.version).gsub('.', '_')
85
83
  # This is for compatibility with Ruby 1.8.7.
86
84
  # TODO(bobaman) Remove this when we eventually stop supporting 1.8.7.
87
85
  args = []