diff --git a/lib/net/imap.rb b/lib/net/imap.rb index e7e127e3..2f44d8a4 100644 --- a/lib/net/imap.rb +++ b/lib/net/imap.rb @@ -2503,17 +2503,21 @@ def idle_done private_constant :RESPONSES_DEPRECATION_MSG # :call-seq: + # responses(type) -> frozen array # responses {|hash| ...} -> block result # responses(type) {|array| ...} -> block result # - # Yields unhandled server responses and returns the result of the block. - # Unhandled responses are stored in a hash, with arrays of - # non-+nil+ UntaggedResponse#data keyed by UntaggedResponse#name - # and ResponseCode#data keyed by ResponseCode#name. + # Yields or returns unhandled server responses. Unhandled responses are + # stored in a hash, with arrays of UntaggedResponse#data keyed by + # UntaggedResponse#name and non-+nil+ untagged ResponseCode#data + # keyed by ResponseCode#name. + # + # When a block is given, yields unhandled responses and returns the block's + # result. Without a block, returns the unhandled responses. # # [With +type+] - # Yield only the array of responses for that +type+. - # When no block is given, an +ArgumentError+ is raised. + # Yield or return only the array of responses for that +type+. + # When no block is given, the returned array is a frozen copy. # [Without +type+] # Yield or return the entire responses hash. # @@ -2534,7 +2538,7 @@ def idle_done # For example: # # imap.select("inbox") - # p imap.responses("EXISTS", &:last) + # p imap.responses("EXISTS").last # #=> 2 # p imap.responses("UIDNEXT", &:last) # #=> 123456 @@ -2592,7 +2596,7 @@ def responses(type = nil) if block_given? synchronize { yield(type ? @responses[type.to_s.upcase] : @responses) } elsif type - raise ArgumentError, "Pass a block or use #clear_responses" + synchronize { @responses[type.to_s.upcase].dup.freeze } else case config.responses_without_block when :raise diff --git a/lib/net/imap/config.rb b/lib/net/imap/config.rb index 972a5b26..c7be267b 100644 --- a/lib/net/imap/config.rb +++ b/lib/net/imap/config.rb @@ -240,10 +240,19 @@ def self.[](config) # [+:raise+ (planned future default)] # Raise an ArgumentError with the deprecation warning. # + # Note: #responses_without_args is an alias for #responses_without_block. attr_accessor :responses_without_block, type: [ - :silence_deprecation_warning, :warn, :raise, + :silence_deprecation_warning, :warn, :frozen_dup, :raise, ] + alias responses_without_args responses_without_block # :nodoc: + alias responses_without_args= responses_without_block= # :nodoc: + + ## + # :attr_accessor: responses_without_args + # + # Alias for responses_without_block + # Creates a new config object and initialize its attribute with +attrs+. # # If +parent+ is not given, the global config is used by default. diff --git a/test/net/imap/test_imap_responses.rb b/test/net/imap/test_imap_responses.rb index 07e2c9a8..911a3434 100644 --- a/test/net/imap/test_imap_responses.rb +++ b/test/net/imap/test_imap_responses.rb @@ -89,12 +89,35 @@ def for_each_config_option(imap) end end - # with with a type and no block: always raise an exception + # with with a type and no block: always returns a frozen duplicate test "#responses(type, &nil)" do with_fake_server do |server, imap| - for_each_config_option(imap) do - assert_raise(ArgumentError) do imap.responses("CAPABILITY") end + stderr = EnvUtil.verbose_warning do + # Config options make no difference to responses(type) + for_each_config_option(imap) do + # responses available before SELECT/EXAMINE + assert imap.responses("CAPABILITY").frozen? + assert_equal(%w[IMAP4REV1 NAMESPACE MOVE IDLE UTF8=ACCEPT], + imap.responses("CAPABILITY").last) + end + # responses are cleared after SELECT/EXAMINE + imap.select "INBOX" + for_each_config_option(imap) do + assert imap.responses("CAPABILITY").frozen? + assert imap.responses("EXISTS").frozen? + assert imap.responses("UIDVALIDITIY").frozen? + assert_equal [], imap.responses("CAPABILITY") + assert_equal [172], imap.responses("EXISTS") + assert_equal [3857529045], imap.responses("UIDVALIDITY") + assert_equal 1, imap.responses("RECENT").last + assert imap.responses("UIDNEXT").frozen? + assert_equal [4392], imap.responses("UIDNEXT") + assert imap.responses("FLAGS").frozen? + assert_equal(%i[Answered Flagged Deleted Seen Draft], + imap.responses("FLAGS").last) + end end + assert_empty stderr # never warn when type is given end end