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 +4 -4
- data/Gemfile +7 -4
- data/lib/net/imap/command_data.rb +0 -68
- data/lib/net/imap/config/attr_accessors.rb +8 -9
- data/lib/net/imap/config/attr_inheritance.rb +64 -1
- data/lib/net/imap/config/attr_type_coercion.rb +18 -6
- data/lib/net/imap/config/attr_version_defaults.rb +90 -0
- data/lib/net/imap/config.rb +210 -122
- data/lib/net/imap/connection_state.rb +1 -1
- data/lib/net/imap/data_encoding.rb +77 -28
- data/lib/net/imap/errors.rb +152 -0
- data/lib/net/imap/esearch_result.rb +48 -3
- data/lib/net/imap/flags.rb +1 -1
- data/lib/net/imap/response_data.rb +2 -4
- data/lib/net/imap/response_parser/parser_utils.rb +14 -23
- data/lib/net/imap/response_parser.rb +27 -17
- data/lib/net/imap/search_result.rb +8 -3
- data/lib/net/imap/sequence_set.rb +936 -397
- data/lib/net/imap/uidplus_data.rb +2 -63
- data/lib/net/imap/vanished_data.rb +10 -1
- data/lib/net/imap.rb +79 -40
- data/net-imap.gemspec +1 -1
- data/rakelib/string_prep_tables_generator.rb +4 -2
- metadata +4 -4
- data/lib/net/imap/data_lite.rb +0 -226
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4249dc5d175bd3ae3a3b3b79e0f368e674ec96045510a8b504e829feefb54f3d
|
|
4
|
+
data.tar.gz: 6adbee15b0303b36ec1c574991d4bdbf518bcd5621c6b668f05df0bc201ba50a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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
|
-
|
|
40
|
-
|
|
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 =
|
|
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
|
-
|
|
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.
|
|
32
|
-
def self.safe(
|
|
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(
|
|
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
|
-
|
|
52
|
-
expected = -"one of #{
|
|
63
|
+
safe_enum = safe{enum}
|
|
64
|
+
expected = -"one of #{safe_enum.map(&:inspect).join(", ")}"
|
|
53
65
|
safe{->val {
|
|
54
|
-
return val if
|
|
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
|