Skip to content

Commit

Permalink
✨ Responses with no args can return frozen dup hash
Browse files Browse the repository at this point in the history
This adds a new `:frozen_dup` option to `config.responses_without_block`
which allows it to return a frozen copy of the responses hash, with each
response type array also being a frozen copy.  This seems like a
reasonable API so, now that we have a config option to control it, it
will tentatively become the new default in v0.6.
  • Loading branch information
nevans committed Oct 7, 2024
1 parent d378c94 commit 6411ac1
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 6 deletions.
15 changes: 12 additions & 3 deletions lib/net/imap.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2497,6 +2497,7 @@ def idle_done
private_constant :RESPONSES_DEPRECATION_MSG

# :call-seq:
# responses -> hash of {String => Array} (see deprecation note)
# responses(type) -> frozen array
# responses {|hash| ...} -> block result
# responses(type) {|array| ...} -> block result
Expand Down Expand Up @@ -2533,9 +2534,10 @@ def idle_done
# frozen, and it is unsafe to modify elements in the array from multiple
# threads.
#
# Calling without +type+ or a block is unsafe and deprecated. Future
# releases may raise ArgumentError unless a block is given. See
# Config#responses_without_block.
# With the default v0.5 config, calling #responses without any arguments
# is unsafe and prints a warning. In v0.6, it will return a frozen hash
# with frozen array values. Set Config#responses_without_block to silence
# the warning or opt-in to the frozen dup behavior.
#
# Previously unhandled responses are automatically cleared before entering a
# mailbox with #select or #examine. Long-lived connections can receive many
Expand Down Expand Up @@ -2565,6 +2567,13 @@ def responses(type = nil)
raise ArgumentError, RESPONSES_DEPRECATION_MSG
when :warn
warn(RESPONSES_DEPRECATION_MSG, uplevel: 1, category: :deprecated)
when :frozen_dup
synchronize {
responses = @responses.transform_values(&:freeze)
responses.default_proc = nil
responses.default = [].freeze
return responses.freeze
}
end
@responses
end
Expand Down
20 changes: 17 additions & 3 deletions lib/net/imap/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -242,16 +242,30 @@ def self.[](config)
# :markup: markdown
#
# Controls the behavior of Net::IMAP#responses when called without any
# arguments (a type or block). Valid options are `:warn`,
# arguments (`type` or block). Valid options are `:frozen_dup`, `:warn`,
# `:silence_deprecation_warning`, or `:raise`.
#
# [+:silence_deprecation_warning+]
# Return the responses hash without any deprecation warnings.
#
# [+:warn+]
# Return the responses hash, after printing a deprecation warning.
#
# [+:frozen_dup+]
# Return a frozen copy of the unhandled responses. This is always the
# behavior when calling IMAP#responses with a `type` argument but
# without a block.
#
# [+:raise+]
# Raise an ArgumentError with the deprecation warning.
#
# | Starting with version | The default value is |
# |-------------------------|--------------------------------|
# | v0.4.13 | +:silence_deprecation_warning+ |
# | v0.5 | +:warn+ |
# | _eventually_ | +:raise+ |
# | v0.6 _(planned)_ | +:frozen_dup+ |
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
alias responses_without_args= responses_without_block=
Expand Down
9 changes: 9 additions & 0 deletions test/net/imap/test_imap_responses.rb
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,15 @@ def assert_responses_warn
assert_equal [], imap.responses["FAKE"]
end
assert_empty stderr
# opt-in to future behavior
imap.config.responses_without_block = :frozen_dup
stderr = EnvUtil.verbose_warning do
assert imap.responses.frozen?
assert imap.responses["CAPABILITY"].frozen?
assert_equal(%w[IMAP4REV1 NAMESPACE MOVE IDLE UTF8=ACCEPT],
imap.responses["CAPABILITY"].last)
end
assert_empty stderr
end
end

Expand Down

0 comments on commit 6411ac1

Please sign in to comment.