@@ -54,22 +54,66 @@ class IMAP
54
54
# plain_client.config.inherited?(:debug) # => true
55
55
# plain_client.config.debug? # => false
56
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
+ # The versioned default configs inherit certain specific config options from
77
+ # Config.global, for example #debug:
78
+ #
79
+ # client = Net::IMAP.new(hostname, config: 0.4)
80
+ # Net::IMAP.debug = false
81
+ # client.config.debug? # => false
82
+ #
83
+ # Net::IMAP.debug = true
84
+ # client.config.debug? # => true
57
85
#
58
86
# == Thread Safety
59
87
#
60
88
# *NOTE:* Updates to config objects are not synchronized for thread-safety.
61
89
#
62
90
class Config
91
+ # Array of attribute names that are _not_ loaded by #load_defaults.
92
+ DEFAULT_TO_INHERIT = %i[ debug ] . freeze
93
+ private_constant :DEFAULT_TO_INHERIT
94
+
63
95
# The default config, which is hardcoded and frozen.
64
96
def self . default ; @default end
65
97
66
98
# The global config object. Also available from Net::IMAP.config.
67
99
def self . global ; @global end
68
100
101
+ # A hash of hard-coded configurations, indexed by version number.
102
+ def self . version_defaults ; @version_defaults end
103
+ @version_defaults = { }
104
+
69
105
# :call-seq:
106
+ # Net::IMAP::Config[number] -> versioned config
107
+ # Net::IMAP::Config[symbol] -> named config
70
108
# Net::IMAP::Config[hash] -> new frozen config
71
109
# Net::IMAP::Config[config] -> same config
72
110
#
111
+ # Given a version number, returns the default configuration for the target
112
+ # version. See Config@Versioned+defaults.
113
+ #
114
+ # Given a version name, returns the default configuration for the target
115
+ # version. See Config@Named+defaults.
116
+ #
73
117
# Given a Hash, creates a new _frozen_ config which inherits from
74
118
# Config.global. Use Config.new for an unfrozen config.
75
119
#
@@ -80,9 +124,16 @@ def self.[](config)
80
124
elsif config . respond_to? ( :to_hash )
81
125
new ( global , **config ) . freeze
82
126
else
83
- raise TypeError , "no implicit conversion of %s to %s" % [
84
- config . class , Config
85
- ]
127
+ version_defaults . fetch ( config ) {
128
+ case config
129
+ when Numeric
130
+ raise RangeError , "unknown config version: %p" % [ config ]
131
+ else
132
+ raise TypeError , "no implicit conversion of %s to %s" % [
133
+ config . class , Config
134
+ ]
135
+ end
136
+ }
86
137
end
87
138
end
88
139
@@ -208,6 +259,23 @@ def to_h; data.members.to_h { [_1, send(_1)] } end
208
259
209
260
@global = default . new
210
261
262
+ version_defaults [ 0.4 ] = Config [
263
+ default . to_h . reject { |k , v | DEFAULT_TO_INHERIT . include? ( k ) }
264
+ ]
265
+
266
+ version_defaults [ 0 ] = Config [ 0.4 ] . dup . update (
267
+ sasl_ir : false ,
268
+ ) . freeze
269
+ version_defaults [ 0.0 ] = Config [ 0 ]
270
+ version_defaults [ 0.1 ] = Config [ 0 ]
271
+ version_defaults [ 0.2 ] = Config [ 0 ]
272
+ version_defaults [ 0.3 ] = Config [ 0 ]
273
+
274
+ version_defaults [ 0.5 ] = Config [ 0.4 ] . dup . update (
275
+ responses_without_block : :warn ,
276
+ ) . freeze
277
+
278
+ version_defaults . freeze
211
279
end
212
280
end
213
281
end
0 commit comments