net-imap 0.4.11 → 0.4.14

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e22c26fdbf5de244369b13bf5fa5661d2c7d2f0bbe60c34d0357f55c149fcdc2
4
- data.tar.gz: 8be09a272a068e900760f1e06730d48bdc789bf95c016899fcce20d2c0576f14
3
+ metadata.gz: 06be993e038a4432ec954b11701ce86f946c456f9125d2b539e6c21d05e728ab
4
+ data.tar.gz: 7807fb77537a843e9d9a2ad0ad892dc3e75af3a734f2c4c68a1e2cbae4d34ef1
5
5
  SHA512:
6
- metadata.gz: 4763081be958834e25897ff73405dc3a7fc635a7871212bde11b04ea2a5ec2bbd97ed97be0d916bd7643a5d43f939d17eaef32e2b9f64ed02cf8876eda7391f8
7
- data.tar.gz: cf9aaa5a9a8cc36d23b5e8078f9d447379ed63d4534cb7c1ed12ac6fee3b8b344147960293aa14af1220ee66b1a0de400b1f1e352aed5c930786e2fb2276e215
6
+ metadata.gz: 182edade4a45d1c6f4772332f2f9cd4704827895770764202aa843bfbb754defff11a8037c1955e352642201c57cea850ea51aa8e4fe6c1761b36c78562b1c5b
7
+ data.tar.gz: 2fff884a15a87ae7cb4a5ac422f743b5accd1ea98b34bf994cbb18238577cc259a1a672a04e5dac14864ad61bdafd90c43c160ede8ba369246fd3bb265e5cff2
data/BSDL ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved.
2
+
3
+ Redistribution and use in source and binary forms, with or without
4
+ modification, are permitted provided that the following conditions
5
+ are met:
6
+ 1. Redistributions of source code must retain the above copyright
7
+ notice, this list of conditions and the following disclaimer.
8
+ 2. Redistributions in binary form must reproduce the above copyright
9
+ notice, this list of conditions and the following disclaimer in the
10
+ documentation and/or other materials provided with the distribution.
11
+
12
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
13
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
15
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
16
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
18
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
22
+ SUCH DAMAGE.
data/COPYING ADDED
@@ -0,0 +1,56 @@
1
+ Ruby is copyrighted free software by Yukihiro Matsumoto <matz@netlab.jp>.
2
+ You can redistribute it and/or modify it under either the terms of the
3
+ 2-clause BSDL (see the file BSDL), or the conditions below:
4
+
5
+ 1. You may make and give away verbatim copies of the source form of the
6
+ software without restriction, provided that you duplicate all of the
7
+ original copyright notices and associated disclaimers.
8
+
9
+ 2. You may modify your copy of the software in any way, provided that
10
+ you do at least ONE of the following:
11
+
12
+ a. place your modifications in the Public Domain or otherwise
13
+ make them Freely Available, such as by posting said
14
+ modifications to Usenet or an equivalent medium, or by allowing
15
+ the author to include your modifications in the software.
16
+
17
+ b. use the modified software only within your corporation or
18
+ organization.
19
+
20
+ c. give non-standard binaries non-standard names, with
21
+ instructions on where to get the original software distribution.
22
+
23
+ d. make other distribution arrangements with the author.
24
+
25
+ 3. You may distribute the software in object code or binary form,
26
+ provided that you do at least ONE of the following:
27
+
28
+ a. distribute the binaries and library files of the software,
29
+ together with instructions (in the manual page or equivalent)
30
+ on where to get the original distribution.
31
+
32
+ b. accompany the distribution with the machine-readable source of
33
+ the software.
34
+
35
+ c. give non-standard binaries non-standard names, with
36
+ instructions on where to get the original software distribution.
37
+
38
+ d. make other distribution arrangements with the author.
39
+
40
+ 4. You may modify and include the part of the software into any other
41
+ software (possibly commercial). But some files in the distribution
42
+ are not written by the author, so that they are not under these terms.
43
+
44
+ For the list of those files and their copying conditions, see the
45
+ file LEGAL.
46
+
47
+ 5. The scripts and library files supplied as input to or produced as
48
+ output from the software do not automatically fall under the
49
+ copyright of the software, but belong to whomever generated them,
50
+ and may be sold commercially, and may be aggregated with this
51
+ software.
52
+
53
+ 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
54
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
55
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
56
+ PURPOSE.
data/LICENSE.txt CHANGED
@@ -1,25 +1,6 @@
1
- Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved.
2
-
3
- Redistribution and use in source and binary forms, with or without
4
- modification, are permitted provided that the following conditions
5
- are met:
6
- 1. Redistributions of source code must retain the above copyright
7
- notice, this list of conditions and the following disclaimer.
8
- 2. Redistributions in binary form must reproduce the above copyright
9
- notice, this list of conditions and the following disclaimer in the
10
- documentation and/or other materials provided with the distribution.
11
-
12
- THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
13
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
15
- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
16
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
18
- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19
- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20
- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21
- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
22
- SUCH DAMAGE.
1
+ All the files in this distribution are covered under either the Ruby license or
2
+ the BSD-2-Clause license (see the file COPYING) except some documentation mentioned
3
+ below.
23
4
 
24
5
  -------------------------------------------------------------------------
25
6
 
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "forwardable"
4
+
5
+ module Net
6
+ class IMAP
7
+ class Config
8
+ # >>>
9
+ # *NOTE:* This module is an internal implementation detail, with no
10
+ # guarantee of backward compatibility.
11
+ #
12
+ # +attr_accessor+ values are stored in a struct rather than ivars, making
13
+ # it simpler to ensure that all config objects share a single object
14
+ # shape. This also simplifies iteration over all defined attributes.
15
+ module AttrAccessors
16
+ module Macros # :nodoc: internal API
17
+ def attr_accessor(name) AttrAccessors.attr_accessor(name) end
18
+ end
19
+ private_constant :Macros
20
+
21
+ def self.included(mod)
22
+ mod.extend Macros
23
+ end
24
+ private_class_method :included
25
+
26
+ extend Forwardable
27
+
28
+ def self.attr_accessor(name) # :nodoc: internal API
29
+ name = name.to_sym
30
+ def_delegators :data, name, :"#{name}="
31
+ end
32
+
33
+ def self.attributes
34
+ instance_methods.grep(/=\z/).map { _1.to_s.delete_suffix("=").to_sym }
35
+ end
36
+ private_class_method :attributes
37
+
38
+ def self.struct # :nodoc: internal API
39
+ unless defined?(self::Struct)
40
+ const_set :Struct, Struct.new(*attributes)
41
+ end
42
+ self::Struct
43
+ end
44
+
45
+ def initialize # :notnew:
46
+ super()
47
+ @data = AttrAccessors.struct.new
48
+ end
49
+
50
+ # Freezes the internal attributes struct, in addition to +self+.
51
+ def freeze
52
+ data.freeze
53
+ super
54
+ end
55
+
56
+ protected
57
+
58
+ attr_reader :data # :nodoc: internal API
59
+
60
+ private
61
+
62
+ def initialize_clone(other)
63
+ super
64
+ @data = other.data.clone
65
+ end
66
+
67
+ def initialize_dup(other)
68
+ super
69
+ @data = other.data.dup
70
+ end
71
+
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Net
4
+ class IMAP
5
+ class Config
6
+ # >>>
7
+ # *NOTE:* The public methods on this module are part of the stable
8
+ # public API of Net::IMAP::Config. But the module itself is an internal
9
+ # implementation detail, with no guarantee of backward compatibility.
10
+ #
11
+ # +attr_accessor+ methods will delegate to their #parent when the local
12
+ # value does not contain an override. Inheritance forms a singly linked
13
+ # list, so lookup will be <tt>O(n)</tt> on the number of ancestors. In
14
+ # practice, the ancestor chain is not expected to be long. Without
15
+ # customization, it is only three deep:
16
+ # >>>
17
+ # IMAP#config → Config.global → Config.default
18
+ #
19
+ # When creating a client with the +config+ keyword, for example to use
20
+ # the appropriate defaults for an application or a library while still
21
+ # relying on global for configuration of +debug+ or +logger+, most likely
22
+ # the ancestor chain is still only four deep:
23
+ # >>>
24
+ # IMAP#config → alternate defaults → Config.global → Config.default
25
+ module AttrInheritance
26
+ INHERITED = Module.new.freeze
27
+ private_constant :INHERITED
28
+
29
+ module Macros # :nodoc: internal API
30
+ def attr_accessor(name) super; AttrInheritance.attr_accessor(name) end
31
+ end
32
+ private_constant :Macros
33
+
34
+ def self.included(mod)
35
+ mod.extend Macros
36
+ end
37
+ private_class_method :included
38
+
39
+ def self.attr_accessor(name) # :nodoc: internal API
40
+ module_eval <<~RUBY, __FILE__, __LINE__ + 1
41
+ def #{name}; (val = super) == INHERITED ? parent&.#{name} : val end
42
+ RUBY
43
+ end
44
+
45
+ # The parent Config object
46
+ attr_reader :parent
47
+
48
+ def initialize(parent = nil) # :notnew:
49
+ super()
50
+ @parent = Config[parent]
51
+ reset
52
+ end
53
+
54
+ # Creates a new config, which inherits from +self+.
55
+ def new(**attrs) self.class.new(self, **attrs) end
56
+
57
+ # Returns +true+ if +attr+ is inherited from #parent and not overridden
58
+ # by this config.
59
+ def inherited?(attr) data[attr] == INHERITED end
60
+
61
+ # :call-seq:
62
+ # reset -> self
63
+ # reset(attr) -> attribute value
64
+ #
65
+ # Resets an +attr+ to inherit from the #parent config.
66
+ #
67
+ # When +attr+ is nil or not given, all attributes are reset.
68
+ def reset(attr = nil)
69
+ if attr.nil?
70
+ data.members.each do |attr| data[attr] = INHERITED end
71
+ self
72
+ elsif inherited?(attr)
73
+ nil
74
+ else
75
+ old, data[attr] = data[attr], INHERITED
76
+ old
77
+ end
78
+ end
79
+
80
+ private
81
+
82
+ def initialize_copy(other)
83
+ super
84
+ @parent ||= other # only default has nil parent
85
+ end
86
+
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Net
4
+ class IMAP
5
+ class Config
6
+ # >>>
7
+ # *NOTE:* This module is an internal implementation detail, with no
8
+ # guarantee of backward compatibility.
9
+ #
10
+ # Adds a +type+ keyword parameter to +attr_accessor+, to enforce that
11
+ # config attributes have valid types, for example: boolean, numeric,
12
+ # enumeration, non-nullable, etc.
13
+ module AttrTypeCoercion
14
+ # :stopdoc: internal APIs only
15
+
16
+ module Macros # :nodoc: internal API
17
+ def attr_accessor(attr, type: nil)
18
+ super(attr)
19
+ AttrTypeCoercion.attr_accessor(attr, type: type)
20
+ end
21
+ end
22
+ private_constant :Macros
23
+
24
+ def self.included(mod)
25
+ mod.extend Macros
26
+ end
27
+ private_class_method :included
28
+
29
+ def self.attr_accessor(attr, type: nil)
30
+ return unless type
31
+ if :boolean == type then boolean attr
32
+ elsif Integer == type then integer attr
33
+ elsif Array === type then enum attr, type
34
+ else raise ArgumentError, "unknown type coercion %p" % [type]
35
+ end
36
+ end
37
+
38
+ def self.boolean(attr)
39
+ define_method :"#{attr}=" do |val| super !!val end
40
+ define_method :"#{attr}?" do send attr end
41
+ end
42
+
43
+ def self.integer(attr)
44
+ define_method :"#{attr}=" do |val| super Integer val end
45
+ end
46
+
47
+ def self.enum(attr, enum)
48
+ enum = enum.dup.freeze
49
+ expected = -"one of #{enum.map(&:inspect).join(", ")}"
50
+ define_method :"#{attr}=" do |val|
51
+ unless enum.include?(val)
52
+ raise ArgumentError, "expected %s, got %p" % [expected, val]
53
+ end
54
+ super val
55
+ end
56
+ end
57
+
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,339 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "config/attr_accessors"
4
+ require_relative "config/attr_inheritance"
5
+ require_relative "config/attr_type_coercion"
6
+
7
+ module Net
8
+ class IMAP
9
+
10
+ # Net::IMAP::Config stores configuration options for Net::IMAP clients.
11
+ # The global configuration can be seen at either Net::IMAP.config or
12
+ # Net::IMAP::Config.global, and the client-specific configuration can be
13
+ # seen at Net::IMAP#config.
14
+ #
15
+ # When creating a new client, all unhandled keyword arguments to
16
+ # Net::IMAP.new are delegated to Config.new. Every client has its own
17
+ # config.
18
+ #
19
+ # debug_client = Net::IMAP.new(hostname, debug: true)
20
+ # quiet_client = Net::IMAP.new(hostname, debug: false)
21
+ # debug_client.config.debug? # => true
22
+ # quiet_client.config.debug? # => false
23
+ #
24
+ # == Inheritance
25
+ #
26
+ # Configs have a parent[rdoc-ref:Config::AttrInheritance#parent] config, and
27
+ # any attributes which have not been set locally will inherit the parent's
28
+ # value. Every client creates its own specific config. By default, client
29
+ # configs inherit from Config.global.
30
+ #
31
+ # plain_client = Net::IMAP.new(hostname)
32
+ # debug_client = Net::IMAP.new(hostname, debug: true)
33
+ # quiet_client = Net::IMAP.new(hostname, debug: false)
34
+ #
35
+ # plain_client.config.inherited?(:debug) # => true
36
+ # debug_client.config.inherited?(:debug) # => false
37
+ # quiet_client.config.inherited?(:debug) # => false
38
+ #
39
+ # plain_client.config.debug? # => false
40
+ # debug_client.config.debug? # => true
41
+ # quiet_client.config.debug? # => false
42
+ #
43
+ # # Net::IMAP.debug is delegated to Net::IMAP::Config.global.debug
44
+ # Net::IMAP.debug = true
45
+ # plain_client.config.debug? # => true
46
+ # debug_client.config.debug? # => true
47
+ # quiet_client.config.debug? # => false
48
+ #
49
+ # Net::IMAP.debug = false
50
+ # plain_client.config.debug = true
51
+ # plain_client.config.inherited?(:debug) # => false
52
+ # plain_client.config.debug? # => true
53
+ # plain_client.config.reset(:debug)
54
+ # plain_client.config.inherited?(:debug) # => true
55
+ # plain_client.config.debug? # => false
56
+ #
57
+ # == Versioned defaults
58
+ #
59
+ # The effective default configuration for a specific +x.y+ version of
60
+ # +net-imap+ can be loaded with the +config+ keyword argument to
61
+ # Net::IMAP.new. Requesting default configurations for previous versions
62
+ # enables extra backward compatibility with those versions:
63
+ #
64
+ # client = Net::IMAP.new(hostname, config: 0.3)
65
+ # client.config.sasl_ir # => false
66
+ # client.config.responses_without_block # => :silence_deprecation_warning
67
+ #
68
+ # client = Net::IMAP.new(hostname, config: 0.4)
69
+ # client.config.sasl_ir # => true
70
+ # client.config.responses_without_block # => :silence_deprecation_warning
71
+ #
72
+ # client = Net::IMAP.new(hostname, config: 0.5)
73
+ # client.config.sasl_ir # => true
74
+ # client.config.responses_without_block # => :warn
75
+ #
76
+ # client = Net::IMAP.new(hostname, config: :future)
77
+ # client.config.sasl_ir # => true
78
+ # client.config.responses_without_block # => :raise
79
+ #
80
+ # The versioned default configs inherit certain specific config options from
81
+ # Config.global, for example #debug:
82
+ #
83
+ # client = Net::IMAP.new(hostname, config: 0.4)
84
+ # Net::IMAP.debug = false
85
+ # client.config.debug? # => false
86
+ #
87
+ # Net::IMAP.debug = true
88
+ # client.config.debug? # => true
89
+ #
90
+ # Use #load_defaults to globally behave like a specific version:
91
+ # client = Net::IMAP.new(hostname)
92
+ # client.config.sasl_ir # => true
93
+ # Net::IMAP.config.load_defaults 0.3
94
+ # client.config.sasl_ir # => false
95
+ #
96
+ # === Named defaults
97
+ # In addition to +x.y+ version numbers, the following aliases are supported:
98
+ #
99
+ # [+:default+]
100
+ # An alias for +:current+.
101
+ #
102
+ # >>>
103
+ # *NOTE*: This is _not_ the same as Config.default. It inherits some
104
+ # attributes from Config.global, for example: #debug.
105
+ # [+:current+]
106
+ # An alias for the current +x.y+ version's defaults.
107
+ # [+:next+]
108
+ # The _planned_ config for the next +x.y+ version.
109
+ # [+:future+]
110
+ # The _planned_ eventual config for some future +x.y+ version.
111
+ #
112
+ # For example, to raise exceptions for all current deprecations:
113
+ # client = Net::IMAP.new(hostname, config: :future)
114
+ # client.responses # raises an ArgumentError
115
+ #
116
+ # == Thread Safety
117
+ #
118
+ # *NOTE:* Updates to config objects are not synchronized for thread-safety.
119
+ #
120
+ class Config
121
+ # Array of attribute names that are _not_ loaded by #load_defaults.
122
+ DEFAULT_TO_INHERIT = %i[debug].freeze
123
+ private_constant :DEFAULT_TO_INHERIT
124
+
125
+ # The default config, which is hardcoded and frozen.
126
+ def self.default; @default end
127
+
128
+ # The global config object. Also available from Net::IMAP.config.
129
+ def self.global; @global if defined?(@global) end
130
+
131
+ # A hash of hard-coded configurations, indexed by version number.
132
+ def self.version_defaults; @version_defaults end
133
+ @version_defaults = {}
134
+
135
+ # :call-seq:
136
+ # Net::IMAP::Config[number] -> versioned config
137
+ # Net::IMAP::Config[symbol] -> named config
138
+ # Net::IMAP::Config[hash] -> new frozen config
139
+ # Net::IMAP::Config[config] -> same config
140
+ #
141
+ # Given a version number, returns the default configuration for the target
142
+ # version. See Config@Versioned+defaults.
143
+ #
144
+ # Given a version name, returns the default configuration for the target
145
+ # version. See Config@Named+defaults.
146
+ #
147
+ # Given a Hash, creates a new _frozen_ config which inherits from
148
+ # Config.global. Use Config.new for an unfrozen config.
149
+ #
150
+ # Given a config, returns that same config.
151
+ def self.[](config)
152
+ if config.is_a?(Config) then config
153
+ elsif config.nil? && global.nil? then nil
154
+ elsif config.respond_to?(:to_hash) then new(global, **config).freeze
155
+ else
156
+ version_defaults.fetch(config) do
157
+ case config
158
+ when Numeric
159
+ raise RangeError, "unknown config version: %p" % [config]
160
+ when Symbol
161
+ raise KeyError, "unknown config name: %p" % [config]
162
+ else
163
+ raise TypeError, "no implicit conversion of %s to %s" % [
164
+ config.class, Config
165
+ ]
166
+ end
167
+ end
168
+ end
169
+ end
170
+
171
+ include AttrAccessors
172
+ include AttrInheritance
173
+ include AttrTypeCoercion
174
+
175
+ # The debug mode (boolean)
176
+ #
177
+ # The default value is +false+.
178
+ attr_accessor :debug, type: :boolean
179
+
180
+ # method: debug?
181
+ # :call-seq: debug? -> boolean
182
+ #
183
+ # Alias for #debug
184
+
185
+ # Seconds to wait until a connection is opened.
186
+ #
187
+ # If the IMAP object cannot open a connection within this time,
188
+ # it raises a Net::OpenTimeout exception.
189
+ #
190
+ # See Net::IMAP.new.
191
+ #
192
+ # The default value is +30+ seconds.
193
+ attr_accessor :open_timeout, type: Integer
194
+
195
+ # Seconds to wait until an IDLE response is received, after
196
+ # the client asks to leave the IDLE state.
197
+ #
198
+ # See Net::IMAP#idle and Net::IMAP#idle_done.
199
+ #
200
+ # The default value is +5+ seconds.
201
+ attr_accessor :idle_response_timeout, type: Integer
202
+
203
+ # :markup: markdown
204
+ #
205
+ # Whether to use the +SASL-IR+ extension when the server and \SASL
206
+ # mechanism both support it.
207
+ #
208
+ # See Net::IMAP#authenticate.
209
+ #
210
+ # | Starting with version | The default value is |
211
+ # |-----------------------|------------------------------------------|
212
+ # | _original_ | +false+ <em>(extension unsupported)</em> |
213
+ # | v0.4 | +true+ <em>(support added)</em> |
214
+ attr_accessor :sasl_ir, type: :boolean
215
+
216
+ # :markup: markdown
217
+ #
218
+ # Controls the behavior of Net::IMAP#responses when called without a
219
+ # block. Valid options are `:warn`, `:raise`, or
220
+ # `:silence_deprecation_warning`.
221
+ #
222
+ # | Starting with version | The default value is |
223
+ # |-------------------------|--------------------------------|
224
+ # | v0.4.13 | +:silence_deprecation_warning+ |
225
+ # | v0.5 <em>(planned)</em> | +:warn+ |
226
+ # | _eventually_ | +:raise+ |
227
+ attr_accessor :responses_without_block, type: [
228
+ :silence_deprecation_warning, :warn, :raise,
229
+ ]
230
+
231
+ # Creates a new config object and initialize its attribute with +attrs+.
232
+ #
233
+ # If +parent+ is not given, the global config is used by default.
234
+ #
235
+ # If a block is given, the new config object is yielded to it.
236
+ def initialize(parent = Config.global, **attrs)
237
+ super(parent)
238
+ update(**attrs)
239
+ yield self if block_given?
240
+ end
241
+
242
+ # :call-seq: update(**attrs) -> self
243
+ #
244
+ # Assigns all of the provided +attrs+ to this config, and returns +self+.
245
+ #
246
+ # An ArgumentError is raised unless every key in +attrs+ matches an
247
+ # assignment method on Config.
248
+ #
249
+ # >>>
250
+ # *NOTE:* #update is not atomic. If an exception is raised due to an
251
+ # invalid attribute value, +attrs+ may be partially applied.
252
+ def update(**attrs)
253
+ unless (bad = attrs.keys.reject { respond_to?(:"#{_1}=") }).empty?
254
+ raise ArgumentError, "invalid config options: #{bad.join(", ")}"
255
+ end
256
+ attrs.each do send(:"#{_1}=", _2) end
257
+ self
258
+ end
259
+
260
+ # :call-seq:
261
+ # with(**attrs) -> config
262
+ # with(**attrs) {|config| } -> result
263
+ #
264
+ # Without a block, returns a new config which inherits from self. With a
265
+ # block, yields the new config and returns the block's result.
266
+ #
267
+ # If no keyword arguments are given, an ArgumentError will be raised.
268
+ #
269
+ # If +self+ is frozen, the copy will also be frozen.
270
+ def with(**attrs)
271
+ attrs.empty? and
272
+ raise ArgumentError, "expected keyword arguments, none given"
273
+ copy = new(**attrs)
274
+ copy.freeze if frozen?
275
+ block_given? ? yield(copy) : copy
276
+ end
277
+
278
+ # :call-seq: load_defaults(version) -> self
279
+ #
280
+ # Resets the current config to behave like the versioned default
281
+ # configuration for +version+. #parent will not be changed.
282
+ #
283
+ # Some config attributes default to inheriting from their #parent (which
284
+ # is usually Config.global) and are left unchanged, for example: #debug.
285
+ #
286
+ # See Config@Versioned+defaults and Config@Named+defaults.
287
+ def load_defaults(version)
288
+ [Numeric, Symbol, String].any? { _1 === version } or
289
+ raise ArgumentError, "expected number or symbol, got %p" % [version]
290
+ update(**Config[version].defaults_hash)
291
+ end
292
+
293
+ # :call-seq: to_h -> hash
294
+ #
295
+ # Returns all config attributes in a hash.
296
+ def to_h; data.members.to_h { [_1, send(_1)] } end
297
+
298
+ protected
299
+
300
+ def defaults_hash
301
+ to_h.reject {|k,v| DEFAULT_TO_INHERIT.include?(k) }
302
+ end
303
+
304
+ @default = new(
305
+ debug: false,
306
+ open_timeout: 30,
307
+ idle_response_timeout: 5,
308
+ sasl_ir: true,
309
+ responses_without_block: :silence_deprecation_warning,
310
+ ).freeze
311
+
312
+ @global = default.new
313
+
314
+ version_defaults[0.4] = Config[default.send(:defaults_hash)]
315
+
316
+ version_defaults[0] = Config[0.4].dup.update(
317
+ sasl_ir: false,
318
+ ).freeze
319
+ version_defaults[0.0] = Config[0]
320
+ version_defaults[0.1] = Config[0]
321
+ version_defaults[0.2] = Config[0]
322
+ version_defaults[0.3] = Config[0]
323
+
324
+ version_defaults[0.5] = Config[0.4].dup.update(
325
+ responses_without_block: :warn,
326
+ ).freeze
327
+
328
+ version_defaults[:default] = Config[0.4]
329
+ version_defaults[:current] = Config[0.4]
330
+ version_defaults[:next] = Config[0.5]
331
+
332
+ version_defaults[:future] = Config[0.5].dup.update(
333
+ responses_without_block: :raise,
334
+ ).freeze
335
+
336
+ version_defaults.freeze
337
+ end
338
+ end
339
+ end