]> git.donarmstrong.com Git - dsa-puppet.git/blob - 3rdparty/modules/aviator/feature/faraday/options.rb
add aimonb/aviator to 3rdparty
[dsa-puppet.git] / 3rdparty / modules / aviator / feature / faraday / options.rb
1 module Faraday
2   # Subclasses Struct with some special helpers for converting from a Hash to
3   # a Struct.
4   class Options < Struct
5     # Public
6     def self.from(value)
7       value ? new.update(value) : new
8     end
9
10     # Public
11     def each
12       return to_enum(:each) unless block_given?
13       members.each do |key|
14         yield(key.to_sym, send(key))
15       end
16     end
17
18     # Public
19     def update(obj)
20       obj.each do |key, value|
21         if sub_options = self.class.options_for(key)
22           value = sub_options.from(value) if value
23         elsif Hash === value
24           hash = {}
25           value.each do |hash_key, hash_value|
26             hash[hash_key] = hash_value
27           end
28           value = hash
29         end
30
31         self.send("#{key}=", value) unless value.nil?
32       end
33       self
34     end
35
36     alias merge! update
37
38     # Public
39     def delete(key)
40       value = send(key)
41       send("#{key}=", nil)
42       value
43     end
44
45     # Public
46     def clear
47       members.each { |member| delete(member) }
48     end
49
50     # Public
51     def merge(value)
52       dup.update(value)
53     end
54
55     # Public
56     def fetch(key, *args)
57       unless symbolized_key_set.include?(key.to_sym)
58         key_setter = "#{key}="
59         if args.size > 0
60           send(key_setter, args.first)
61         elsif block_given?
62           send(key_setter, Proc.new.call(key))
63         else
64           raise self.class.fetch_error_class, "key not found: #{key.inspect}"
65         end
66       end
67       send(key)
68     end
69
70     # Public
71     def values_at(*keys)
72       keys.map { |key| send(key) }
73     end
74
75     # Public
76     def keys
77       members.reject { |member| send(member).nil? }
78     end
79
80     # Public
81     def empty?
82       keys.empty?
83     end
84
85     # Public
86     def each_key
87       return to_enum(:each_key) unless block_given?
88       keys.each do |key|
89         yield(key)
90       end
91     end
92
93     # Public
94     def key?(key)
95       keys.include?(key)
96     end
97
98     alias has_key? key?
99
100     # Public
101     def each_value
102       return to_enum(:each_value) unless block_given?
103       values.each do |value|
104         yield(value)
105       end
106     end
107
108     # Public
109     def value?(value)
110       values.include?(value)
111     end
112
113     alias has_value? value?
114
115     # Public
116     def to_hash
117       hash = {}
118       members.each do |key|
119         value = send(key)
120         hash[key.to_sym] = value unless value.nil?
121       end
122       hash
123     end
124
125     # Internal
126     def inspect
127       values = []
128       members.each do |member|
129         value = send(member)
130         values << "#{member}=#{value.inspect}" if value
131       end
132       values = values.empty? ? ' (empty)' : (' ' << values.join(", "))
133
134       %(#<#{self.class}#{values}>)
135     end
136
137     # Internal
138     def self.options(mapping)
139       attribute_options.update(mapping)
140     end
141
142     # Internal
143     def self.options_for(key)
144       attribute_options[key]
145     end
146
147     # Internal
148     def self.attribute_options
149       @attribute_options ||= {}
150     end
151
152     def self.memoized(key)
153       memoized_attributes[key.to_sym] = Proc.new
154       class_eval <<-RUBY, __FILE__, __LINE__ + 1
155         def #{key}() self[:#{key}]; end
156       RUBY
157     end
158
159     def self.memoized_attributes
160       @memoized_attributes ||= {}
161     end
162
163     def [](key)
164       key = key.to_sym
165       if method = self.class.memoized_attributes[key]
166         super(key) || (self[key] = instance_eval(&method))
167       else
168         super
169       end
170     end
171
172     def symbolized_key_set
173       @symbolized_key_set ||= Set.new(keys.map { |k| k.to_sym })
174     end
175
176     def self.inherited(subclass)
177       super
178       subclass.attribute_options.update(attribute_options)
179       subclass.memoized_attributes.update(memoized_attributes)
180     end
181
182     def self.fetch_error_class
183       @fetch_error_class ||= if Object.const_defined?(:KeyError)
184         ::KeyError
185       else
186         ::IndexError
187       end
188     end
189   end
190
191   class RequestOptions < Options.new(:params_encoder, :proxy, :bind,
192     :timeout, :open_timeout, :boundary,
193     :oauth)
194
195     def []=(key, value)
196       if key && key.to_sym == :proxy
197         super(key, value ? ProxyOptions.from(value) : nil)
198       else
199         super(key, value)
200       end
201     end
202   end
203
204   class SSLOptions < Options.new(:verify, :ca_file, :ca_path, :verify_mode,
205     :cert_store, :client_cert, :client_key, :certificate, :private_key, :verify_depth, :version)
206
207     def verify?
208       verify != false
209     end
210
211     def disable?
212       !verify?
213     end
214   end
215
216   class ProxyOptions < Options.new(:uri, :user, :password)
217     extend Forwardable
218     def_delegators :uri, :scheme, :scheme=, :host, :host=, :port, :port=, :path, :path=
219
220     def self.from(value)
221       case value
222       when String
223         value = {:uri => Utils.URI(value)}
224       when URI
225         value = {:uri => value}
226       when Hash, Options
227         if uri = value.delete(:uri)
228           value[:uri] = Utils.URI(uri)
229         end
230       end
231       super(value)
232     end
233
234     memoized(:user) { uri.user && Utils.unescape(uri.user) }
235     memoized(:password) { uri.password && Utils.unescape(uri.password) }
236   end
237
238   class ConnectionOptions < Options.new(:request, :proxy, :ssl, :builder, :url,
239     :parallel_manager, :params, :headers, :builder_class)
240
241     options :request => RequestOptions, :ssl => SSLOptions
242
243     memoized(:request) { self.class.options_for(:request).new }
244
245     memoized(:ssl) { self.class.options_for(:ssl).new }
246
247     memoized(:builder_class) { RackBuilder }
248
249     def new_builder(block)
250       builder_class.new(&block)
251     end
252   end
253
254   class Env < Options.new(:method, :body, :url, :request, :request_headers,
255     :ssl, :parallel_manager, :params, :response, :response_headers, :status)
256
257     ContentLength = 'Content-Length'.freeze
258     StatusesWithoutBody = Set.new [204, 304]
259     SuccessfulStatuses = 200..299
260
261     # A Set of HTTP verbs that typically send a body.  If no body is set for
262     # these requests, the Content-Length header is set to 0.
263     MethodsWithBodies = Set.new [:post, :put, :patch, :options]
264
265     options :request => RequestOptions,
266       :request_headers => Utils::Headers, :response_headers => Utils::Headers
267
268     extend Forwardable
269
270     def_delegators :request, :params_encoder
271
272     # Public
273     def [](key)
274       if in_member_set?(key)
275         super(key)
276       else
277         custom_members[key]
278       end
279     end
280
281     # Public
282     def []=(key, value)
283       if in_member_set?(key)
284         super(key, value)
285       else
286         custom_members[key] = value
287       end
288     end
289
290     # Public
291     def success?
292       SuccessfulStatuses.include?(status)
293     end
294
295     # Public
296     def needs_body?
297       !body && MethodsWithBodies.include?(method)
298     end
299
300     # Public
301     def clear_body
302       request_headers[ContentLength] = '0'
303       self.body = ''
304     end
305
306     # Public
307     def parse_body?
308       !StatusesWithoutBody.include?(status)
309     end
310
311     # Public
312     def parallel?
313       !!parallel_manager
314     end
315
316     def inspect
317       attrs = [nil]
318       members.each do |mem|
319         if value = send(mem)
320           attrs << "@#{mem}=#{value.inspect}"
321         end
322       end
323       if !custom_members.empty?
324         attrs << "@custom=#{custom_members.inspect}"
325       end
326       %(#<#{self.class}#{attrs.join(" ")}>)
327     end
328
329     # Internal
330     def custom_members
331       @custom_members ||= {}
332     end
333
334     # Internal
335     if members.first.is_a?(Symbol)
336       def in_member_set?(key)
337         self.class.member_set.include?(key.to_sym)
338       end
339     else
340       def in_member_set?(key)
341         self.class.member_set.include?(key.to_s)
342       end
343     end
344
345     # Internal
346     def self.member_set
347       @member_set ||= Set.new(members)
348     end
349   end
350 end