net-imap 0.5.8 → 0.6.3

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: b6d2d79f907ce00d056ead396fafe73bbdf84fc54b01e1f2536d6490c001c723
4
- data.tar.gz: 6fba3cd04144fedd7b178959451631ea14cff8f248ca963961b3945b636cec4b
3
+ metadata.gz: 4249dc5d175bd3ae3a3b3b79e0f368e674ec96045510a8b504e829feefb54f3d
4
+ data.tar.gz: 6adbee15b0303b36ec1c574991d4bdbf518bcd5621c6b668f05df0bc201ba50a
5
5
  SHA512:
6
- metadata.gz: 80f15f967d4260638d423b802204360e25704cc47c59d110a85f401c1554882521097d5014ecc3e7a0a17f87e8995ae87f553d73a26f3c8abc84744ad5d236ed
7
- data.tar.gz: 2790cbc5ee60b3da3648e8bd91df90ecac7c72e0febca11464400460fd5c34db3123d307f39901ea7c313942f2feb11bb3c0f7dbc06b96094b6d1738426b278a
6
+ metadata.gz: a20c230ac3977d9acc09bc964badc60acbedaca84246d1ce67787c78443cdea350ade6907e58b61a5c9f09bf3b12e5e57cd319ef82a096c3780f97dc7017ed31
7
+ data.tar.gz: 68ab8b48664998bbf05d5367fea4e5b06e3ba3b2d4e48ba8ae026069060b23f7dafaf7ecf2681fc5aa4ff0f134e55d9399ca51456ff3a7ec718ba829629866b7
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"
@@ -14,10 +15,12 @@ gem "rdoc"
14
15
  gem "test-unit"
15
16
  gem "test-unit-ruby-core", git: "https://github.com/ruby/test-unit-ruby-core"
16
17
 
18
+ gem "benchmark", require: false
17
19
  gem "benchmark-driver", require: false
20
+ gem "vernier", require: false, platform: :mri
18
21
 
19
22
  group :test do
20
- gem "simplecov", require: false
21
- gem "simplecov-html", require: false
22
- gem "simplecov-json", require: false
23
+ gem "simplecov", require: false, platforms: %i[mri windows]
24
+ gem "simplecov-html", require: false, platforms: %i[mri windows]
25
+ gem "simplecov-json", require: false, platforms: %i[mri windows]
23
26
  end
@@ -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)
@@ -27,24 +27,23 @@ module Net
27
27
 
28
28
  def self.attr_accessor(name) # :nodoc: internal API
29
29
  name = name.to_sym
30
+ raise ArgumentError, "already defined #{name}" if attributes.include?(name)
31
+ attributes << name
30
32
  def_delegators :data, name, :"#{name}="
31
33
  end
32
34
 
33
- def self.attributes
34
- instance_methods.grep(/=\z/).map { _1.to_s.delete_suffix("=").to_sym }
35
- end
36
- private_class_method :attributes
35
+ # An array of Config attribute names
36
+ singleton_class.attr_reader :attributes
37
+ @attributes = []
37
38
 
38
39
  def self.struct # :nodoc: internal API
39
- unless defined?(self::Struct)
40
- const_set :Struct, Struct.new(*attributes)
41
- end
42
- self::Struct
40
+ attributes.freeze
41
+ Struct.new(*attributes)
43
42
  end
44
43
 
45
44
  def initialize # :notnew:
46
45
  super()
47
- @data = AttrAccessors.struct.new
46
+ @data = Config::Struct.new
48
47
  end
49
48
 
50
49
  # Freezes the internal attributes struct, in addition to +self+.
@@ -54,9 +54,72 @@ 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
+ #
70
+ # Related: #overrides?
71
+ def inherited?(*attrs)
72
+ attrs = data.members if attrs.empty?
73
+ attrs.all? { data[_1] == INHERITED }
74
+ end
75
+
76
+ # :call-seq:
77
+ # inherits_defaults?(*attrs) -> true | Rational | nil | false
78
+ #
79
+ # Returns whether all +attrs+ are inherited from a default config.
80
+ # When no +attrs+ are given, returns whether *all* attributes are
81
+ # inherited from a default config.
82
+ #
83
+ # Returns +true+ when all attributes inherit from Config.default, the
84
+ # version number (as a Rational) when all attributes inherit from a
85
+ # versioned default (see Config@Versioned+defaults), +nil+ if any
86
+ # attributes inherit from Config.global overrides (but not from
87
+ # non-global ancestors), or +false+ when any attributes have been
88
+ # overridden by +self+ or an ancestor (besides global or default
89
+ # configs),
90
+ #
91
+ # Related: #overrides?
92
+ def inherits_defaults?(*attrs)
93
+ if equal?(Config.default)
94
+ true
95
+ elsif equal?(Config.global)
96
+ true if inherited?(*attrs)
97
+ elsif (v = AttrVersionDefaults::VERSIONS.find { equal? Config[_1] })
98
+ attrs = DEFAULT_TO_INHERIT if attrs.empty?
99
+ attrs &= DEFAULT_TO_INHERIT
100
+ (attrs.empty? || parent.inherits_defaults?(*attrs)) && v
101
+ else
102
+ inherited?(*attrs) && parent.inherits_defaults?(*attrs)
103
+ end
104
+ end
105
+
106
+ # :call-seq:
107
+ # overrides?(attr) -> true or false
108
+ # overrides?(*attrs) -> true or false
109
+ # overrides? -> true or false
110
+ #
111
+ # Returns +true+ if +attr+ is defined on this config and not inherited
112
+ # from #parent.
113
+ #
114
+ # When multiple +attrs+ are given, returns +true+ if
115
+ # *any* of them are defined on +self+. When no +attrs+ are given,
116
+ # returns +true+ if *any* attribute is overriden.
117
+ #
118
+ # Related: #inherited?
119
+ def overrides?(*attrs)
120
+ attrs = data.members if attrs.empty?
121
+ attrs.any? { data[_1] != INHERITED }
122
+ end
60
123
 
61
124
  # :call-seq:
62
125
  # reset -> self
@@ -28,10 +28,22 @@ module Net
28
28
  end
29
29
  private_class_method :included
30
30
 
31
- if defined?(Ractor.make_shareable)
32
- def self.safe(...) Ractor.make_shareable nil.instance_eval(...).freeze end
31
+ if defined?(Ractor.shareable_proc)
32
+ def self.safe(&b)
33
+ case obj = b.call
34
+ when Proc
35
+ Ractor.shareable_proc(&obj)
36
+ else
37
+ Ractor.make_shareable obj
38
+ end
39
+ end
40
+ elsif defined?(Ractor.make_shareable)
41
+ def self.safe(&b)
42
+ obj = nil.instance_eval(&b).freeze
43
+ Ractor.make_shareable obj
44
+ end
33
45
  else
34
- def self.safe(...) nil.instance_eval(...).freeze end
46
+ def self.safe(&b) nil.instance_eval(&b).freeze end
35
47
  end
36
48
  private_class_method :safe
37
49
 
@@ -48,10 +60,10 @@ module Net
48
60
  NilOrInteger = safe{->val { Integer val unless val.nil? }}
49
61
 
50
62
  Enum = ->(*enum) {
51
- enum = safe{enum}
52
- expected = -"one of #{enum.map(&:inspect).join(", ")}"
63
+ safe_enum = safe{enum}
64
+ expected = -"one of #{safe_enum.map(&:inspect).join(", ")}"
53
65
  safe{->val {
54
- return val if enum.include?(val)
66
+ return val if safe_enum.include?(val)
55
67
  raise ArgumentError, "expected %s, got %p" % [expected, val]
56
68
  }}
57
69
  }
@@ -0,0 +1,90 @@
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_reader :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
+ version_defaults[0.0r] = Config[version_defaults.fetch(0.0r)]
63
+
64
+ VERSIONS.each_cons(2) do |prior, version|
65
+ updates = version_defaults[version]
66
+ version_defaults[version] = version_defaults[prior]
67
+ .then { updates ? _1.dup.update(**updates).freeze : _1 }
68
+ end
69
+
70
+ # Safe conversions one way only:
71
+ # 0.6r.to_f == 0.6 # => true
72
+ # 0.6 .to_r == 0.6r # => false
73
+ version_defaults.to_a.each do |k, v|
74
+ next unless k in Rational
75
+ version_defaults[k.to_f] = v
76
+ end
77
+
78
+ version_defaults[:original] = Config[0.0r]
79
+ version_defaults[:current] = Config[CURRENT_VERSION]
80
+ version_defaults[:default] = Config[CURRENT_VERSION]
81
+ version_defaults[:next] = Config[NEXT_VERSION]
82
+ version_defaults[:future] = Config[FUTURE_VERSION]
83
+
84
+ version_defaults.freeze
85
+ end
86
+
87
+ end
88
+ end
89
+ end
90
+ end