net-imap 0.4.1 → 0.4.3

Sign up to get free protection for your applications and to get access to all the features.
data/lib/net/imap.rb CHANGED
@@ -662,7 +662,7 @@ module Net
662
662
  # * {IMAP URLAUTH Authorization Mechanism Registry}[https://www.iana.org/assignments/urlauth-authorization-mechanism-registry/urlauth-authorization-mechanism-registry.xhtml]
663
663
  #
664
664
  class IMAP < Protocol
665
- VERSION = "0.4.1"
665
+ VERSION = "0.4.3"
666
666
 
667
667
  # Aliases for supported capabilities, to be used with the #enable command.
668
668
  ENABLE_ALIASES = {
@@ -1045,7 +1045,7 @@ module Net
1045
1045
  # ===== Capabilities
1046
1046
  #
1047
1047
  # The server's capabilities must include +ID+
1048
- # [RFC2971[https://tools.ietf.org/html/rfc2971]]
1048
+ # [RFC2971[https://tools.ietf.org/html/rfc2971]].
1049
1049
  def id(client_id=nil)
1050
1050
  synchronize do
1051
1051
  send_command("ID", ClientID.new(client_id))
@@ -1058,7 +1058,7 @@ module Net
1058
1058
  #
1059
1059
  # This allows the server to send unsolicited untagged EXPUNGE #responses,
1060
1060
  # but does not execute any client request. \IMAP servers are permitted to
1061
- # send unsolicited untagged responses at any time, except for `EXPUNGE`.
1061
+ # send unsolicited untagged responses at any time, except for +EXPUNGE+:
1062
1062
  #
1063
1063
  # * +EXPUNGE+ can only be sent while a command is in progress.
1064
1064
  # * +EXPUNGE+ must _not_ be sent during #fetch, #store, or #search.
@@ -1143,10 +1143,7 @@ module Net
1143
1143
  end
1144
1144
 
1145
1145
  # :call-seq:
1146
- # authenticate(mechanism, *,
1147
- # sasl_ir: true,
1148
- # registry: Net::IMAP::SASL.authenticators,
1149
- # **, &) -> ok_resp
1146
+ # authenticate(mechanism, *, sasl_ir: true, registry: Net::IMAP::SASL.authenticators, **, &) -> ok_resp
1150
1147
  #
1151
1148
  # Sends an {AUTHENTICATE command [IMAP4rev1 §6.2.2]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.2.2]
1152
1149
  # to authenticate the client. If successful, the connection enters the
@@ -1330,7 +1327,7 @@ module Net
1330
1327
  # the server may return an untagged "NO" response with a "UIDNOTSTICKY"
1331
1328
  # response code indicating that the mailstore does not support persistent
1332
1329
  # UIDs:
1333
- # @responses["NO"].last.code.name == "UIDNOTSTICKY"
1330
+ # imap.responses("NO", &:last)&.code&.name == "UIDNOTSTICKY"
1334
1331
  def select(mailbox)
1335
1332
  synchronize do
1336
1333
  @responses.clear
@@ -1420,10 +1417,10 @@ module Net
1420
1417
  # to the client. +refname+ provides a context (for instance, a base
1421
1418
  # directory in a directory-based mailbox hierarchy). +mailbox+ specifies a
1422
1419
  # mailbox or (via wildcards) mailboxes under that context. Two wildcards
1423
- # may be used in +mailbox+: '*', which matches all characters *including*
1424
- # the hierarchy delimiter (for instance, '/' on a UNIX-hosted
1425
- # directory-based mailbox hierarchy); and '%', which matches all characters
1426
- # *except* the hierarchy delimiter.
1420
+ # may be used in +mailbox+: <tt>"*"</tt>, which matches all characters
1421
+ # *including* the hierarchy delimiter (for instance, "/" on a UNIX-hosted
1422
+ # directory-based mailbox hierarchy); and <tt>"%"</tt>, which matches all
1423
+ # characters *except* the hierarchy delimiter.
1427
1424
  #
1428
1425
  # If +refname+ is empty, +mailbox+ is used directly to determine
1429
1426
  # which mailboxes to match. If +mailbox+ is empty, the root
@@ -1471,16 +1468,16 @@ module Net
1471
1468
  # servers, then folder creation (and listing, moving, etc) can lead to
1472
1469
  # errors.
1473
1470
  #
1474
- # From RFC2342:
1475
- #
1476
- # Although typically a server will support only a single Personal
1471
+ # From RFC2342[https://tools.ietf.org/html/rfc2342]:
1472
+ # >>>
1473
+ # <em>Although typically a server will support only a single Personal
1477
1474
  # Namespace, and a single Other User's Namespace, circumstances exist
1478
1475
  # where there MAY be multiples of these, and a client MUST be prepared
1479
1476
  # for them. If a client is configured such that it is required to create
1480
1477
  # a certain mailbox, there can be circumstances where it is unclear which
1481
1478
  # Personal Namespaces it should create the mailbox in. In these
1482
1479
  # situations a client SHOULD let the user select which namespaces to
1483
- # create the mailbox in.
1480
+ # create the mailbox in.</em>
1484
1481
  #
1485
1482
  # Related: #list, Namespaces, Namespace
1486
1483
  #
@@ -1668,9 +1665,9 @@ module Net
1668
1665
  # or more attributes whose statuses are to be requested. Supported
1669
1666
  # attributes include:
1670
1667
  #
1671
- # MESSAGES:: the number of messages in the mailbox.
1672
- # RECENT:: the number of recent messages in the mailbox.
1673
- # UNSEEN:: the number of unseen messages in the mailbox.
1668
+ # MESSAGES:: the number of messages in the mailbox.
1669
+ # RECENT:: the number of recent messages in the mailbox.
1670
+ # UNSEEN:: the number of unseen messages in the mailbox.
1674
1671
  #
1675
1672
  # The return value is a hash of attributes. For example:
1676
1673
  #
@@ -1935,11 +1932,11 @@ module Net
1935
1932
  # to alter data associated with messages in the mailbox, in particular their
1936
1933
  # flags. The +set+ parameter is a number, an array of numbers, or a Range
1937
1934
  # object. Each number is a message sequence number. +attr+ is the name of a
1938
- # data item to store: 'FLAGS' will replace the message's flag list with the
1939
- # provided one, '+FLAGS' will add the provided flags, and '-FLAGS' will
1940
- # remove them. +flags+ is a list of flags.
1935
+ # data item to store: <tt>"FLAGS"</tt> will replace the message's flag list
1936
+ # with the provided one, <tt>"+FLAGS"</tt> will add the provided flags, and
1937
+ # <tt>"-FLAGS"</tt> will remove them. +flags+ is a list of flags.
1941
1938
  #
1942
- # The return value is an array of FetchData
1939
+ # The return value is an array of FetchData.
1943
1940
  #
1944
1941
  # Related: #uid_store
1945
1942
  #
@@ -2522,7 +2519,8 @@ module Net
2522
2519
  when /\A(?:BAD)\z/ni
2523
2520
  raise BadResponseError, resp
2524
2521
  else
2525
- raise UnknownResponseError, resp
2522
+ disconnect
2523
+ raise InvalidResponseError, "invalid tagged resp: %p" % [resp.raw.chomp]
2526
2524
  end
2527
2525
  end
2528
2526
 
data/net-imap.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  name = File.basename(__FILE__, ".gemspec")
4
4
  version = ["lib", Array.new(name.count("-"), "..").join("/")].find do |dir|
5
- break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line|
5
+ break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb"), :encoding=> 'utf-8') do |line|
6
6
  /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1
7
7
  end rescue nil
8
8
  end
@@ -25,7 +25,8 @@ Gem::Specification.new do |spec|
25
25
  # Specify which files should be added to the gem when it is released.
26
26
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
27
27
  spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
28
- `git ls-files -z 2>/dev/null`.split("\x0").reject { |f| f.match(%r{^(bin|test|spec|features|rfcs)/}) }
28
+ `git ls-files -z 2>/dev/null`.split("\x0")
29
+ .reject {|f| f.match(%r{^(bin|test|spec|benchmarks|features|rfcs)/}) }
29
30
  end
30
31
  spec.bindir = "exe"
31
32
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ PARSER_TEST_FIXTURES = FileList.new "test/net/imap/fixtures/response_parser/*.yml"
4
+ CLOBBER.include "benchmarks/parser.yml"
5
+ CLEAN.include "benchmarks/Gemfile-*"
6
+
7
+ BENCHMARK_INIT = <<RUBY
8
+ require "yaml"
9
+ require "net/imap"
10
+
11
+ def load_response(file, name)
12
+ YAML.unsafe_load_file(file).dig(:tests, name, :response)
13
+ .force_encoding "ASCII-8BIT" \\
14
+ or abort "ERRORO: missing %p fixture data in %p" % [name, file]
15
+ end
16
+
17
+ parser = Net::IMAP::ResponseParser.new
18
+ RUBY
19
+
20
+ PER_BENCHMARK_PRELUDE = <<RUBY
21
+ response = load_response(%p,
22
+ %p)
23
+ RUBY
24
+
25
+ file "benchmarks/parser.yml" => PARSER_TEST_FIXTURES do |t|
26
+ require "yaml"
27
+ require "pathname"
28
+ require "net/imap"
29
+
30
+ path = Pathname.new(__dir__) / "../test/net/imap/fixtures/response_parser"
31
+ files = path.glob("*.yml")
32
+ tests = files.flat_map {|file|
33
+ file.read
34
+ .gsub(%r{([-:]) !ruby/struct:\S+}) { $1 }
35
+ .then {
36
+ YAML.safe_load(_1, filename: file,
37
+ permitted_classes: [Symbol, Regexp], aliases: true)
38
+ }
39
+ .fetch(:tests)
40
+ .select {|test_name, test|
41
+ :parser_assert_equal == test.fetch(:test_type) {
42
+ test.key?(:expected) ? :parser_assert_equal : :parser_pending
43
+ }
44
+ }
45
+ .map {|test_name, _|
46
+ [file.relative_path_from(__dir__).to_s, test_name.to_s]
47
+ }
48
+ }
49
+
50
+ benchmarks = tests.map {|file, fixture_name|
51
+ {"name" => fixture_name.delete_prefix("test_"),
52
+ "prelude" => PER_BENCHMARK_PRELUDE % [file, fixture_name],
53
+ "script" => "parser.parse(response)"}
54
+ }
55
+ .sort_by { _1["name"] }
56
+
57
+ YAML.dump({"prelude" => BENCHMARK_INIT, "benchmark" => benchmarks})
58
+ .then { File.write t.name, _1 }
59
+ end
60
+
61
+ namespace :benchmarks do
62
+ desc "Generate benchmarks from fixture data"
63
+ task :generate => "benchmarks/parser.yml"
64
+
65
+ desc "run the parser benchmarks comparing multiple gem versions"
66
+ task :compare => :generate do |task, args|
67
+ cd Pathname.new(__dir__) + ".."
68
+ current = `git describe --tags --dirty`.chomp
69
+ current = "dev" if current.empty?
70
+ versions = args.to_a
71
+ if versions.empty?
72
+ latest = %x{git describe --tags --abbrev=0 --match 'v*.*.*'}.chomp
73
+ versions = latest.empty? ? [] : [latest.delete_prefix("v")]
74
+ end
75
+ versions = versions.to_h { [_1, "Gemfile-v#{_1}"] }
76
+ cd "benchmarks" do
77
+ versions.each do |version, gemfile|
78
+ File.write gemfile, <<~RUBY
79
+ # frozen_string_literal: true
80
+ source "https://rubygems.org"
81
+ gem "net-imap", #{version.dump}
82
+ RUBY
83
+ end
84
+ versions = {current => "../Gemfile" , **versions}.map {
85
+ "%s::/usr/bin/env BUNDLE_GEMFILE=%s ruby" % _1
86
+ }.join(";")
87
+
88
+ extra = ENV.fetch("BENCHMARK_ARGS", "").shellsplit
89
+
90
+ sh("benchmark-driver",
91
+ "--bundler",
92
+ "-e", versions,
93
+ "parser.yml",
94
+ *extra)
95
+ end
96
+ end
97
+
98
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: net-imap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.4.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shugo Maeda
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2023-10-09 00:00:00.000000000 Z
12
+ date: 2023-10-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: net-protocol
@@ -83,10 +83,6 @@ files:
83
83
  - LICENSE.txt
84
84
  - README.md
85
85
  - Rakefile
86
- - benchmarks/generate_parser_benchmarks
87
- - benchmarks/parser.yml
88
- - benchmarks/stringprep.yml
89
- - benchmarks/table-regexps.yml
90
86
  - docs/styles.css
91
87
  - lib/net/imap.rb
92
88
  - lib/net/imap/authenticators.rb
@@ -123,6 +119,7 @@ files:
123
119
  - lib/net/imap/stringprep/tables.rb
124
120
  - lib/net/imap/stringprep/trace.rb
125
121
  - net-imap.gemspec
122
+ - rakelib/benchmarks.rake
126
123
  - rakelib/rdoc.rake
127
124
  - rakelib/rfcs.rake
128
125
  - rakelib/saslprep.rake
@@ -1,52 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "yaml"
4
- require "pathname"
5
- require "net/imap"
6
-
7
- path = Pathname.new(__dir__) / "../test/net/imap/fixtures/response_parser"
8
- files = path.glob("*.yml")
9
- tests = files.flat_map {|file|
10
- file.to_s
11
- .then { YAML.unsafe_load_file _1 }
12
- .fetch(:tests)
13
- .select {|test_name, test|
14
- :parser_assert_equal == test.fetch(:test_type) {
15
- test.key?(:expected) ? :parser_assert_equal : :parser_pending
16
- }
17
- }
18
- .map {|test_name, _|
19
- [
20
- file.relative_path_from(__dir__).to_s,
21
- test_name.to_s,
22
- ]
23
- }
24
- }
25
-
26
- init = <<RUBY
27
- require "yaml"
28
- require "net/imap"
29
-
30
- def load_response(file, name)
31
- YAML.unsafe_load_file(file).dig(:tests, name, :response)
32
- .force_encoding "ASCII-8BIT" \\
33
- or abort "ERRORO: missing %p fixture data in %p" % [name, file]
34
- end
35
-
36
- parser = Net::IMAP::ResponseParser.new
37
- RUBY
38
-
39
- prelude = <<RUBY
40
- response = load_response(%p,
41
- %p)
42
- RUBY
43
- script = "parser.parse(response)"
44
-
45
- benchmarks = tests.map {|file, fixture_name|
46
- name = fixture_name.delete_prefix("test_")
47
- {name:, prelude: prelude % [file, fixture_name], script:}
48
- .transform_keys(&:to_s)
49
- }
50
- .sort_by { _1["name"] }
51
-
52
- puts YAML.dump({"prelude" => init, "benchmark" => benchmarks})