net-imap 0.5.12 → 0.6.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 57bfc92d10c2b8f139254627f6998a5c6e1c83111c41dac22a1cae22fdc11a75
4
- data.tar.gz: 7ca4ce789ff544967728d1b4b9106617f5c7a1b0b79beae999d0e22505e2b49c
3
+ metadata.gz: 561e6151a9540c8eaa6c12fd16d625061843a053fb0b0c8a2f215eb1a518ef70
4
+ data.tar.gz: 5be61c15097d2e0007822fc6c4825f59795d6078d6cf9b5cbe6ed4dd2bd1d22e
5
5
  SHA512:
6
- metadata.gz: 8ec55fe5a02b72fa061cb77f23c592806fd8361d4b371f8f124fed106c93ac01359af7bb4f194341ad66035ba24e1ddee3a100ab2de08d60367e0af2a9c3c94b
7
- data.tar.gz: b97339aae765227112a0e7308a68e969028495b243438e0dc37f049cfa310c385f4735bf5bd2460711d907c99a43abb1f8411aa72d742b5e4a3c337916500167
6
+ metadata.gz: f84a8adf89f177e953fe57e390b027232bc4c7325ecb0049221a88db87fccc76a09281aea87c4f48de05bc547db1248b628b9c271134a466aedba953305001cc
7
+ data.tar.gz: 0b82898fb8581bab9a30c5b3edb96c89d81c4bddf197ade29a25ef166db827983a6c2c25d1eda9989a9f985cfcbec52f4bf484dbc1b57cfde32f432dcd0dfbc3
data/Gemfile CHANGED
@@ -4,9 +4,10 @@ source "https://rubygems.org"
4
4
 
5
5
  gemspec
6
6
 
7
- gem "digest"
7
+ # gem "digest" # not included as a workaround for #576
8
8
  gem "strscan"
9
9
  gem "base64"
10
+ gem "psych", ">= 5.3.0" # 5.2.5 for Data serialization, 5.3.0 for TruffleRuby
10
11
 
11
12
  gem "irb"
12
13
  gem "rake"
@@ -3,7 +3,6 @@
3
3
  require "date"
4
4
 
5
5
  require_relative "errors"
6
- require_relative "data_lite"
7
6
 
8
7
  module Net
9
8
  class IMAP < Protocol
@@ -185,73 +184,6 @@ module Net
185
184
  end
186
185
  end
187
186
 
188
- # *DEPRECATED*. Replaced by SequenceSet.
189
- class MessageSet < CommandData # :nodoc:
190
- def send_data(imap, tag)
191
- imap.__send__(:put_string, format_internal(data))
192
- end
193
-
194
- def validate
195
- validate_internal(data)
196
- end
197
-
198
- private
199
-
200
- def initialize(data:)
201
- super
202
- warn("DEPRECATED: #{MessageSet} should be replaced with #{SequenceSet}.",
203
- uplevel: 1, category: :deprecated)
204
- begin
205
- # to ensure the input works with SequenceSet, too
206
- SequenceSet.new(data)
207
- rescue
208
- warn "MessageSet input is incompatible with SequenceSet: [%s] %s" % [
209
- $!.class, $!.message
210
- ]
211
- end
212
- end
213
-
214
- def format_internal(data)
215
- case data
216
- when "*"
217
- return data
218
- when Integer
219
- if data == -1
220
- return "*"
221
- else
222
- return data.to_s
223
- end
224
- when Range
225
- return format_internal(data.first) +
226
- ":" + format_internal(data.last)
227
- when Array
228
- return data.collect {|i| format_internal(i)}.join(",")
229
- when ThreadMember
230
- return data.seqno.to_s +
231
- ":" + data.children.collect {|i| format_internal(i).join(",")}
232
- end
233
- end
234
-
235
- def validate_internal(data)
236
- case data
237
- when "*"
238
- when Integer
239
- NumValidator.ensure_nz_number(data)
240
- when Range
241
- when Array
242
- data.each do |i|
243
- validate_internal(i)
244
- end
245
- when ThreadMember
246
- data.children.each do |i|
247
- validate_internal(i)
248
- end
249
- else
250
- raise DataFormatError, data.inspect
251
- end
252
- end
253
- end
254
-
255
187
  class ClientID < CommandData # :nodoc:
256
188
 
257
189
  def send_data(imap, tag)
@@ -54,9 +54,22 @@ module Net
54
54
  # Creates a new config, which inherits from +self+.
55
55
  def new(**attrs) self.class.new(self, **attrs) end
56
56
 
57
+ # :call-seq:
58
+ # inherited?(attr) -> true or false
59
+ # inherited?(*attrs) -> true or false
60
+ # inherited? -> true or false
61
+ #
57
62
  # Returns +true+ if +attr+ is inherited from #parent and not overridden
58
63
  # by this config.
59
- def inherited?(attr) data[attr] == INHERITED end
64
+ #
65
+ # When multiple +attrs+ are given, returns +true+ if *all* of them are
66
+ # inherited, or +false+ if any of them are overriden. When no +attrs+
67
+ # are given, returns +true+ if *all* attributes are inherited, or
68
+ # +false+ if any attribute is overriden.
69
+ def inherited?(*attrs)
70
+ attrs = data.members if attrs.empty?
71
+ attrs.all? { data[_1] == INHERITED }
72
+ end
60
73
 
61
74
  # :call-seq:
62
75
  # reset -> self
@@ -0,0 +1,93 @@
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
+ # Adds a +defaults+ parameter to +attr_accessor+, which is used to compile
13
+ # Config.version_defaults.
14
+ module AttrVersionDefaults
15
+ # The <tt>x.y</tt> part of Net::IMAP::VERSION, as a Rational number.
16
+ CURRENT_VERSION = VERSION.to_r
17
+
18
+ # The config version used for <tt>Config[:next]</tt>.
19
+ NEXT_VERSION = CURRENT_VERSION + 0.1r
20
+
21
+ # The config version used for <tt>Config[:future]</tt>.
22
+ FUTURE_VERSION = 1.0r
23
+
24
+ VERSIONS = ((0.0r..FUTURE_VERSION) % 0.1r).to_a.freeze
25
+
26
+ # See Config.version_defaults.
27
+ singleton_class.attr_accessor :version_defaults
28
+
29
+ @version_defaults = Hash.new {|h, k|
30
+ # NOTE: String responds to both so the order is significant.
31
+ # And ignore non-numeric conversion to zero, because: "wat!?".to_r == 0
32
+ (h.fetch(k.to_r, nil) || h.fetch(k.to_f, nil) if k.is_a?(Numeric)) ||
33
+ (h.fetch(k.to_sym, nil) if k.respond_to?(:to_sym)) ||
34
+ (h.fetch(k.to_r, nil) if k.respond_to?(:to_r) && k.to_r != 0r) ||
35
+ (h.fetch(k.to_f, nil) if k.respond_to?(:to_f) && k.to_f != 0.0)
36
+ }
37
+
38
+ # :stopdoc: internal APIs only
39
+
40
+ def attr_accessor(name, defaults: nil, default: (unset = true), **kw)
41
+ unless unset
42
+ version = DEFAULT_TO_INHERIT.include?(name) ? nil : 0.0r
43
+ defaults = { version => default }
44
+ end
45
+ defaults&.each_pair do |version, default|
46
+ AttrVersionDefaults.version_defaults[version] ||= {}
47
+ AttrVersionDefaults.version_defaults[version][name] = default
48
+ end
49
+ super(name, **kw)
50
+ end
51
+
52
+ def self.compile_default!
53
+ raise "Config.default already compiled" if Config.default
54
+ default = VERSIONS.select { _1 <= CURRENT_VERSION }
55
+ .filter_map { version_defaults[_1] }
56
+ .prepend(version_defaults.delete(nil))
57
+ .inject(&:merge)
58
+ Config.new(**default).freeze
59
+ end
60
+
61
+ def self.compile_version_defaults!
62
+ # Temporarily assign Config.default, enabling #load_defaults(:default)
63
+ version_defaults[:default] = Config.default
64
+ # Use #load_defaults so some attributes are inherited from global.
65
+ version_defaults[:default] = Config.new.load_defaults(:default).freeze
66
+ version_defaults[0.0r] = Config[version_defaults.fetch(0.0r)]
67
+
68
+ VERSIONS.each_cons(2) do |prior, version|
69
+ updates = version_defaults[version]
70
+ version_defaults[version] = version_defaults[prior]
71
+ .then { updates ? _1.dup.update(**updates).freeze : _1 }
72
+ end
73
+
74
+ # Safe conversions one way only:
75
+ # 0.6r.to_f == 0.6 # => true
76
+ # 0.6 .to_r == 0.6r # => false
77
+ version_defaults.to_a.each do |k, v|
78
+ next unless k in Rational
79
+ version_defaults[k.to_f] = v
80
+ end
81
+
82
+ version_defaults[:original] = Config[0.0r]
83
+ version_defaults[:current] = Config[CURRENT_VERSION]
84
+ version_defaults[:next] = Config[NEXT_VERSION]
85
+ version_defaults[:future] = Config[FUTURE_VERSION]
86
+
87
+ version_defaults.freeze
88
+ end
89
+
90
+ end
91
+ end
92
+ end
93
+ end
@@ -3,6 +3,7 @@
3
3
  require_relative "config/attr_accessors"
4
4
  require_relative "config/attr_inheritance"
5
5
  require_relative "config/attr_type_coercion"
6
+ require_relative "config/attr_version_defaults"
6
7
 
7
8
  module Net
8
9
  class IMAP
@@ -141,15 +142,7 @@ module Net
141
142
  # Net::IMAP::Config[0.5] == Net::IMAP::Config[0.5r] # => true
142
143
  # Net::IMAP::Config["current"] == Net::IMAP::Config[:current] # => true
143
144
  # Net::IMAP::Config["0.5.6"] == Net::IMAP::Config[0.5r] # => true
144
- def self.version_defaults; @version_defaults end
145
- @version_defaults = Hash.new {|h, k|
146
- # NOTE: String responds to both so the order is significant.
147
- # And ignore non-numeric conversion to zero, because: "wat!?".to_r == 0
148
- (h.fetch(k.to_r, nil) || h.fetch(k.to_f, nil) if k.is_a?(Numeric)) ||
149
- (h.fetch(k.to_sym, nil) if k.respond_to?(:to_sym)) ||
150
- (h.fetch(k.to_r, nil) if k.respond_to?(:to_r) && k.to_r != 0r) ||
151
- (h.fetch(k.to_f, nil) if k.respond_to?(:to_f) && k.to_f != 0.0)
152
- }
145
+ def self.version_defaults; AttrVersionDefaults.version_defaults end
153
146
 
154
147
  # :call-seq:
155
148
  # Net::IMAP::Config[number] -> versioned config
@@ -189,6 +182,7 @@ module Net
189
182
  include AttrAccessors
190
183
  include AttrInheritance
191
184
  include AttrTypeCoercion
185
+ extend AttrVersionDefaults
192
186
 
193
187
  # The debug mode (boolean). The default value is +false+.
194
188
  #
@@ -200,7 +194,7 @@ module Net
200
194
  #
201
195
  # *NOTE:* Versioned default configs inherit #debug from Config.global, and
202
196
  # #load_defaults will not override #debug.
203
- attr_accessor :debug, type: :boolean
197
+ attr_accessor :debug, type: :boolean, default: false
204
198
 
205
199
  # method: debug?
206
200
  # :call-seq: debug? -> boolean
@@ -218,7 +212,7 @@ module Net
218
212
  # See Net::IMAP.new and Net::IMAP#starttls.
219
213
  #
220
214
  # The default value is +30+ seconds.
221
- attr_accessor :open_timeout, type: Integer
215
+ attr_accessor :open_timeout, type: Integer, default: 30
222
216
 
223
217
  # Seconds to wait until an IDLE response is received, after
224
218
  # the client asks to leave the IDLE state.
@@ -226,7 +220,7 @@ module Net
226
220
  # See Net::IMAP#idle and Net::IMAP#idle_done.
227
221
  #
228
222
  # The default value is +5+ seconds.
229
- attr_accessor :idle_response_timeout, type: Integer
223
+ attr_accessor :idle_response_timeout, type: Integer, default: 5
230
224
 
231
225
  # Whether to use the +SASL-IR+ extension when the server and \SASL
232
226
  # mechanism both support it. Can be overridden by the +sasl_ir+ keyword
@@ -240,9 +234,25 @@ module Net
240
234
  # Do not use +SASL-IR+, even when it is supported by the server and the
241
235
  # mechanism.
242
236
  #
237
+ # [+:when_capabilities_cached+]
238
+ # Use +SASL-IR+ when Net::IMAP#capabilities_cached? is +true+ and it is
239
+ # supported by the server and the mechanism, but do not send a
240
+ # +CAPABILITY+ command to discover the server capabilities.
241
+ #
242
+ # <em>(+:when_capabilities_cached+ option was added by +v0.6.0+)</em>
243
+ #
243
244
  # [+true+ <em>(default since +v0.4+)</em>]
244
245
  # Use +SASL-IR+ when it is supported by the server and the mechanism.
245
- attr_accessor :sasl_ir, type: :boolean
246
+ attr_accessor :sasl_ir, type: Enum[
247
+ false, :when_capabilities_cached, true
248
+ ], defaults: {
249
+ 0.0r => false,
250
+ 0.4r => true,
251
+ }
252
+
253
+ # :stopdoc:
254
+ alias sasl_ir? sasl_ir
255
+ # :startdoc:
246
256
 
247
257
  # Controls the behavior of Net::IMAP#login when the +LOGINDISABLED+
248
258
  # capability is present. When enforced, Net::IMAP will raise a
@@ -266,7 +276,10 @@ module Net
266
276
  #
267
277
  attr_accessor :enforce_logindisabled, type: Enum[
268
278
  false, :when_capabilities_cached, true
269
- ]
279
+ ], defaults: {
280
+ 0.0r => false,
281
+ 0.5r => true,
282
+ }
270
283
 
271
284
  # The maximum allowed server response size. When +nil+, there is no limit
272
285
  # on response size.
@@ -300,7 +313,10 @@ module Net
300
313
  #
301
314
  # * original: +nil+ <em>(no limit)</em>
302
315
  # * +0.5+: 512 MiB
303
- attr_accessor :max_response_size, type: Integer?
316
+ attr_accessor :max_response_size, type: Integer?, defaults: {
317
+ 0.0r => nil,
318
+ 0.5r => 512 << 20, # 512 MiB
319
+ }
304
320
 
305
321
  # Controls the behavior of Net::IMAP#responses when called without any
306
322
  # arguments (+type+ or +block+).
@@ -330,7 +346,11 @@ module Net
330
346
  # Note: #responses_without_args is an alias for #responses_without_block.
331
347
  attr_accessor :responses_without_block, type: Enum[
332
348
  :silence_deprecation_warning, :warn, :frozen_dup, :raise,
333
- ]
349
+ ], defaults: {
350
+ 0.0r => :silence_deprecation_warning,
351
+ 0.5r => :warn,
352
+ 0.6r => :frozen_dup,
353
+ }
334
354
 
335
355
  alias responses_without_args responses_without_block # :nodoc:
336
356
  alias responses_without_args= responses_without_block= # :nodoc:
@@ -340,66 +360,69 @@ module Net
340
360
  #
341
361
  # Alias for responses_without_block
342
362
 
343
- # Whether ResponseParser should use the deprecated UIDPlusData or
344
- # CopyUIDData for +COPYUID+ response codes, and UIDPlusData or
345
- # AppendUIDData for +APPENDUID+ response codes.
346
- #
347
- # UIDPlusData stores its data in arrays of numbers, which is vulnerable to
348
- # a memory exhaustion denial of service attack from an untrusted or
349
- # compromised server. Set this option to +false+ to completely block this
350
- # vulnerability. Otherwise, parser_max_deprecated_uidplus_data_size
351
- # mitigates this vulnerability.
363
+ # **NOTE:** <em>+UIDPlusData+ has been removed since +v0.6.0+, and this
364
+ # config option only affects deprecation warnings.
365
+ # This config option will be **removed** in +v0.7.0+.</em>
352
366
  #
353
- # AppendUIDData and CopyUIDData are _mostly_ backward-compatible with
354
- # UIDPlusData. Most applications should be able to upgrade with little
355
- # or no changes.
367
+ # ResponseParser always returns CopyUIDData for +COPYUID+ response codes,
368
+ # and AppendUIDData for +APPENDUID+ response codes. Previously, this
369
+ # option determined when UIDPlusData would be returned instead.
356
370
  #
357
- # <em>(Parser support for +UIDPLUS+ added in +v0.3.2+.)</em>
371
+ # Parser support for +UIDPLUS+ added in +v0.3.2+.
358
372
  #
359
- # <em>(Config option added in +v0.4.19+ and +v0.5.6+.)</em>
373
+ # Config option added in +v0.4.19+ and +v0.5.6+.
360
374
  #
361
- # <em>UIDPlusData will be removed in +v0.6+ and this config setting will
362
- # be ignored.</em>
375
+ # <em>UIDPlusData removed in +v0.6.0+.</em>
363
376
  #
364
- # ==== Valid options
377
+ # ==== Options
365
378
  #
366
379
  # [+true+ <em>(original default)</em>]
367
- # ResponseParser only uses UIDPlusData.
380
+ # <em>Since v0.6.0:</em>
381
+ # Prints a deprecation warning when parsing +COPYUID+ or +APPENDUID+.
368
382
  #
369
383
  # [+:up_to_max_size+ <em>(default since +v0.5.6+)</em>]
370
- # ResponseParser uses UIDPlusData when the +uid-set+ size is below
371
- # parser_max_deprecated_uidplus_data_size. Above that size,
372
- # ResponseParser uses AppendUIDData or CopyUIDData.
384
+ # <em>Since v0.6.0:</em>
385
+ # Prints a deprecation warning when parsing +COPYUID+ or +APPENDUID+.
373
386
  #
374
- # [+false+ <em>(planned default for +v0.6+)</em>]
375
- # ResponseParser _only_ uses AppendUIDData and CopyUIDData.
387
+ # [+false+ <em>(default since +v0.6.0+)</em>]
388
+ # This is the only supported option <em>(since v0.6.0)</em>.
376
389
  attr_accessor :parser_use_deprecated_uidplus_data, type: Enum[
377
390
  true, :up_to_max_size, false
378
- ]
391
+ ], defaults: {
392
+ 0.0r => true,
393
+ 0.5r => :up_to_max_size,
394
+ 0.6r => false,
395
+ }
379
396
 
380
- # The maximum +uid-set+ size that ResponseParser will parse into
381
- # deprecated UIDPlusData. This limit only applies when
382
- # parser_use_deprecated_uidplus_data is not +false+.
397
+ # **NOTE:** <em>+UIDPlusData+ has been removed since +v0.6.0+, and this
398
+ # config option is ignored.
399
+ # This config option will be **removed** in +v0.7.0+.</em>
383
400
  #
384
- # <em>(Parser support for +UIDPLUS+ added in +v0.3.2+.)</em>
401
+ # ResponseParser always returns CopyUIDData for +COPYUID+ response codes,
402
+ # and AppendUIDData for +APPENDUID+ response codes. Previously, this
403
+ # option determined when UIDPlusData would be returned instead.
385
404
  #
386
- # <em>Support for limiting UIDPlusData to a maximum size was added in
387
- # +v0.3.8+, +v0.4.19+, and +v0.5.6+.</em>
405
+ # Parser support for +UIDPLUS+ added in +v0.3.2+.
388
406
  #
389
- # <em>UIDPlusData will be removed in +v0.6+.</em>
407
+ # Support for limiting UIDPlusData to a maximum size was added in
408
+ # +v0.3.8+, +v0.4.19+, and +v0.5.6+.
390
409
  #
391
- # ==== Versioned Defaults
410
+ # <em>UIDPlusData was removed in +v0.6.0+.</em>
392
411
  #
393
- # Because this limit guards against a remote server causing catastrophic
394
- # memory exhaustion, the versioned default (used by #load_defaults) also
395
- # applies to versions without the feature.
412
+ # ==== Versioned Defaults
396
413
  #
397
414
  # * +0.3+ and prior: <tt>10,000</tt>
398
415
  # * +0.4+: <tt>1,000</tt>
399
416
  # * +0.5+: <tt>100</tt>
400
417
  # * +0.6+: <tt>0</tt>
401
418
  #
402
- attr_accessor :parser_max_deprecated_uidplus_data_size, type: Integer
419
+ attr_accessor :parser_max_deprecated_uidplus_data_size, type: Integer,
420
+ defaults: {
421
+ 0.0r => 10_000,
422
+ 0.4r => 1_000,
423
+ 0.5r => 100,
424
+ 0.6r => 0,
425
+ }
403
426
 
404
427
  # Creates a new config object and initialize its attribute with +attrs+.
405
428
  #
@@ -468,85 +491,150 @@ module Net
468
491
  # Returns all config attributes in a hash.
469
492
  def to_h; data.members.to_h { [_1, send(_1)] } end
470
493
 
494
+ # Returns a string representation of overriden config attributes and the
495
+ # inheritance chain.
496
+ #
497
+ # Attributes overridden by ancestors are also inspected, recursively.
498
+ # Attributes that are inherited from default configs are not shown (see
499
+ # Config@Versioned+defaults and Config@Named+defaults).
500
+ #
501
+ # # (Line breaks have been added to the example output for legibility.)
502
+ #
503
+ # Net::IMAP::Config.new(0.4)
504
+ # .new(open_timeout: 10, enforce_logindisabled: true)
505
+ # .inspect
506
+ # #=> "#<Net::IMAP::Config:0x0000745871125410 open_timeout=10 enforce_logindisabled=true
507
+ # # inherits from Net::IMAP::Config[0.4]
508
+ # # inherits from Net::IMAP::Config.global
509
+ # # inherits from Net::IMAP::Config.default>"
510
+ #
511
+ # Non-default attributes are listed after the ancestor config from which
512
+ # they are inherited.
513
+ #
514
+ # # (Line breaks have been added to the example output for legibility.)
515
+ #
516
+ # config = Net::IMAP::Config.global
517
+ # .new(open_timeout: 10, idle_response_timeout: 2)
518
+ # .new(enforce_logindisabled: :when_capabilities_cached, sasl_ir: false)
519
+ # config.inspect
520
+ # #=> "#<Net::IMAP::Config:0x00007ce2a1e20e40 sasl_ir=false enforce_logindisabled=:when_capabilities_cached
521
+ # # inherits from Net::IMAP::Config:0x00007ce2a1e20f80 open_timeout=10 idle_response_timeout=2
522
+ # # inherits from Net::IMAP::Config.global
523
+ # # inherits from Net::IMAP::Config.default>"
524
+ #
525
+ # Net::IMAP.debug = true
526
+ # config.inspect
527
+ # #=> "#<Net::IMAP::Config:0x00007ce2a1e20e40 sasl_ir=false enforce_logindisabled=:when_capabilities_cached
528
+ # # inherits from Net::IMAP::Config:0x00007ce2a1e20f80 open_timeout=10 idle_response_timeout=2
529
+ # # inherits from Net::IMAP::Config.global debug=true
530
+ # # inherits from Net::IMAP::Config.default>"
531
+ #
532
+ # Use +pp+ (see #pretty_print) to inspect _all_ config attributes,
533
+ # including default values.
534
+ #
535
+ # Use #to_h to inspect all config attributes ignoring inheritance.
536
+ def inspect;
537
+ "#<#{inspect_recursive}>"
538
+ end
539
+ alias to_s inspect
540
+
541
+ # Used by PP[https://docs.ruby-lang.org/en/master/PP.html] to create a
542
+ # string representation of all config attributes and the inheritance
543
+ # chain. Inherited attributes are listed with the ancestor config from
544
+ # which they are inherited.
545
+ #
546
+ # pp Config.new[0.4].new(open_timeout: 10, idle_response_timeout: 10)
547
+ # # #<Net::IMAP::Config:0x0000745871125410
548
+ # # open_timeout=10
549
+ # # idle_response_timeout=10
550
+ # # inherits from Net::IMAP::Config[0.4]
551
+ # # responses_without_block=:silence_deprecation_warning
552
+ # # max_response_size=nil
553
+ # # sasl_ir=true
554
+ # # enforce_logindisabled=false
555
+ # # parser_use_deprecated_uidplus_data=true
556
+ # # parser_max_deprecated_uidplus_data_size=1000
557
+ # # inherits from Net::IMAP::Config.global
558
+ # # inherits from Net::IMAP::Config.default
559
+ # # debug=false>
560
+ #
561
+ # Related: #inspect, #to_h.
562
+ def pretty_print(pp)
563
+ pp.group(2, "#<", ">") do
564
+ pretty_print_recursive(pp)
565
+ end
566
+ end
567
+
568
+ # :stopdoc:
569
+
471
570
  protected
472
571
 
473
- def defaults_hash
474
- to_h.reject {|k,v| DEFAULT_TO_INHERIT.include?(k) }
572
+ def named_default?
573
+ equal?(Config.default) ||
574
+ AttrVersionDefaults::VERSIONS.any? { equal? Config[_1] }
475
575
  end
476
576
 
477
- @default = new(
478
- debug: false,
479
- open_timeout: 30,
480
- idle_response_timeout: 5,
481
- sasl_ir: true,
482
- enforce_logindisabled: true,
483
- max_response_size: 512 << 20, # 512 MiB
484
- responses_without_block: :warn,
485
- parser_use_deprecated_uidplus_data: :up_to_max_size,
486
- parser_max_deprecated_uidplus_data_size: 100,
487
- ).freeze
488
-
489
- @global = default.new
490
-
491
- version_defaults[:default] = Config[default.send(:defaults_hash)]
492
-
493
- version_defaults[0r] = Config[:default].dup.update(
494
- sasl_ir: false,
495
- responses_without_block: :silence_deprecation_warning,
496
- enforce_logindisabled: false,
497
- max_response_size: nil,
498
- parser_use_deprecated_uidplus_data: true,
499
- parser_max_deprecated_uidplus_data_size: 10_000,
500
- ).freeze
501
- version_defaults[0.0r] = Config[0r]
502
- version_defaults[0.1r] = Config[0r]
503
- version_defaults[0.2r] = Config[0r]
504
- version_defaults[0.3r] = Config[0r]
505
-
506
- version_defaults[0.4r] = Config[0.3r].dup.update(
507
- sasl_ir: true,
508
- parser_max_deprecated_uidplus_data_size: 1000,
509
- ).freeze
510
-
511
- version_defaults[0.5r] = Config[0.4r].dup.update(
512
- enforce_logindisabled: true,
513
- max_response_size: 512 << 20, # 512 MiB
514
- responses_without_block: :warn,
515
- parser_use_deprecated_uidplus_data: :up_to_max_size,
516
- parser_max_deprecated_uidplus_data_size: 100,
517
- ).freeze
518
-
519
- version_defaults[0.6r] = Config[0.5r].dup.update(
520
- responses_without_block: :frozen_dup,
521
- parser_use_deprecated_uidplus_data: false,
522
- parser_max_deprecated_uidplus_data_size: 0,
523
- ).freeze
524
-
525
- version_defaults[0.7r] = Config[0.6r].dup.update(
526
- ).freeze
527
-
528
- # Safe conversions one way only:
529
- # 0.6r.to_f == 0.6 # => true
530
- # 0.6 .to_r == 0.6r # => false
531
- version_defaults.to_a.each do |k, v|
532
- next unless k in Rational
533
- version_defaults[k.to_f] = v
577
+ def name
578
+ if equal? Config.default then "#{Config}.default"
579
+ elsif equal? Config.global then "#{Config}.global"
580
+ elsif equal? Config[0.0r] then "#{Config}[:original]"
581
+ elsif equal? Config[:default] then "#{Config}[:default]"
582
+ elsif (v = AttrVersionDefaults::VERSIONS.find { equal? Config[_1] })
583
+ "%s[%0.1f]" % [Config, v]
584
+ else
585
+ Kernel.instance_method(:to_s).bind_call(self).delete("<#>")
586
+ end
587
+ end
588
+
589
+ def inspect_recursive(attrs = AttrAccessors.struct.members)
590
+ strings = [name]
591
+ assigned = assigned_attrs_hash(attrs)
592
+ strings.concat assigned.map { "%s=%p" % _1 }
593
+ if parent
594
+ if parent.equal?(Config.default)
595
+ inherited_overrides = []
596
+ elsif parent
597
+ inherited_overrides = attrs - assigned.keys
598
+ inherited_overrides &= DEFAULT_TO_INHERIT if parent.named_default?
599
+ end
600
+ strings << "inherits from #{parent.inspect_recursive(inherited_overrides)}"
601
+ end
602
+ strings.join " "
534
603
  end
535
604
 
536
- current = VERSION.to_r
537
- version_defaults[:original] = Config[0]
538
- version_defaults[:current] = Config[current]
539
- version_defaults[:next] = Config[current + 0.1r]
540
- version_defaults[:future] = Config[current + 0.2r]
605
+ def pretty_print_recursive(pp, attrs = AttrAccessors.struct.members)
606
+ pp.text name
607
+ assigned = assigned_attrs_hash(attrs)
608
+ pp.breakable
609
+ pp.seplist(assigned, ->{pp.breakable}) do |key, val|
610
+ pp.text key.to_s
611
+ pp.text "="
612
+ pp.pp val
613
+ end
614
+ if parent
615
+ pp.breakable if assigned.any?
616
+ pp.nest(2) do
617
+ pp.text "inherits from "
618
+ parent.pretty_print_recursive(pp, attrs - assigned.keys)
619
+ end
620
+ elsif assigned.empty?
621
+ pp.text "(overridden)"
622
+ end
623
+ end
541
624
 
542
- version_defaults.freeze
625
+ def assigned_attrs_hash(attrs)
626
+ own_attrs = attrs.reject { inherited?(_1) }
627
+ own_attrs.to_h { [_1, data[_1]] }
628
+ end
543
629
 
544
- if ($VERBOSE || $DEBUG) && self[:current].to_h != self[:default].to_h
545
- warn "Misconfigured Net::IMAP::Config[:current] => %p,\n" \
546
- " not equal to Net::IMAP::Config[:default] => %p" % [
547
- self[:current].to_h, self[:default].to_h
548
- ]
630
+ def defaults_hash
631
+ to_h.reject {|k,v| DEFAULT_TO_INHERIT.include?(k) }
549
632
  end
633
+
634
+ @default = AttrVersionDefaults.compile_default!
635
+ @global = default.new
636
+ AttrVersionDefaults.compile_version_defaults!
637
+
550
638
  end
551
639
  end
552
640
  end