-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
🔀 Merge pull request #291 from ruby/config-class
Add Config class for `debug`, `open_timeout`, and `idle_response_timeout`
- Loading branch information
Showing
13 changed files
with
500 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
# frozen_string_literal: true | ||
# :markup: markdown | ||
|
||
require_relative "config/attr_accessors" | ||
require_relative "config/attr_inheritance" | ||
require_relative "config/attr_type_coercion" | ||
|
||
module Net | ||
class IMAP | ||
|
||
# Net::IMAP::Config stores configuration options for Net::IMAP clients. | ||
# The global configuration can be seen at either Net::IMAP.config or | ||
# Net::IMAP::Config.global, and the client-specific configuration can be | ||
# seen at Net::IMAP#config. When creating a new client, all unhandled | ||
# keyword arguments to Net::IMAP.new are delegated to Config.new. Every | ||
# client has its own config. | ||
# | ||
# ## Inheritance | ||
# | ||
# Configs have a parent[rdoc-ref:Config::AttrInheritance#parent] config, and | ||
# any attributes which have not been set locally will inherit the parent's | ||
# value. Every client creates its own specific config. By default, client | ||
# configs inherit from Config.global which inherits from Config.default. | ||
# | ||
# See the following methods, defined by Config::AttrInheritance: | ||
# - {#new}[rdoc-ref:Config::AttrInheritance#reset] -- create a new config | ||
# which inherits from the receiver. | ||
# - {#inherited?}[rdoc-ref:Config::AttrInheritance#inherited?] -- return | ||
# whether a particular attribute is inherited. | ||
# - {#reset}[rdoc-ref:Config::AttrInheritance#reset] -- reset attributes to | ||
# be inherited. | ||
# | ||
# ## Thread Safety | ||
# | ||
# *NOTE:* Updates to config objects are not synchronized for thread-safety. | ||
# | ||
class Config | ||
# The default config, which is hardcoded and frozen. | ||
def self.default; @default end | ||
|
||
# The global config object. | ||
def self.global; @global end | ||
|
||
def self.[](config) # :nodoc: unfinished API | ||
if config.is_a?(Config) || config.nil? && global.nil? | ||
config | ||
else | ||
raise TypeError, "no implicit conversion of %s to %s" % [ | ||
config.class, Config | ||
] | ||
end | ||
end | ||
|
||
include AttrAccessors | ||
include AttrInheritance | ||
include AttrTypeCoercion | ||
|
||
# The debug mode (boolean) | ||
# | ||
# | Starting with version | The default value is | | ||
# |-----------------------|----------------------| | ||
# | _original_ | +false+ | | ||
attr_accessor :debug, type: :boolean | ||
|
||
# method: debug? | ||
# :call-seq: debug? -> boolean | ||
# | ||
# Alias for #debug | ||
|
||
# Seconds to wait until a connection is opened. | ||
# | ||
# If the IMAP object cannot open a connection within this time, | ||
# it raises a Net::OpenTimeout exception. See Net::IMAP.new. | ||
# | ||
# | Starting with version | The default value is | | ||
# |-----------------------|----------------------| | ||
# | _original_ | +30+ seconds | | ||
attr_accessor :open_timeout, type: Integer | ||
|
||
# Seconds to wait until an IDLE response is received, after | ||
# the client asks to leave the IDLE state. See Net::IMAP#idle_done. | ||
# | ||
# | Starting with version | The default value is | | ||
# |-----------------------|----------------------| | ||
# | _original_ | +5+ seconds | | ||
attr_accessor :idle_response_timeout, type: Integer | ||
|
||
# Creates a new config object and initialize its attribute with +attrs+. | ||
# | ||
# If +parent+ is not given, the global config is used by default. | ||
# | ||
# If a block is given, the new config object is yielded to it. | ||
def initialize(parent = Config.global, **attrs) | ||
super(parent) | ||
attrs.each do send(:"#{_1}=", _2) end | ||
yield self if block_given? | ||
end | ||
|
||
@default = new( | ||
debug: false, | ||
open_timeout: 30, | ||
idle_response_timeout: 5, | ||
).freeze | ||
|
||
@global = default.new | ||
|
||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
# frozen_string_literal: true | ||
|
||
require "forwardable" | ||
|
||
module Net | ||
class IMAP | ||
class Config | ||
|
||
# Config values are stored in a struct rather than ivars to simplify: | ||
# * ensuring that all config objects share a single object shape | ||
# * querying only locally configured values, e.g for inspection. | ||
module AttrAccessors | ||
module Macros # :nodoc: internal API | ||
def attr_accessor(name) AttrAccessors.attr_accessor(name) end | ||
end | ||
private_constant :Macros | ||
|
||
def self.included(mod) | ||
mod.extend Macros | ||
end | ||
private_class_method :included | ||
|
||
extend Forwardable | ||
|
||
def self.attr_accessor(name) # :nodoc: internal API | ||
name = name.to_sym | ||
def_delegators :data, name, :"#{name}=" | ||
end | ||
|
||
def self.attributes | ||
instance_methods.grep(/=\z/).map { _1.to_s.delete_suffix("=").to_sym } | ||
end | ||
private_class_method :attributes | ||
|
||
def self.struct # :nodoc: internal API | ||
unless defined?(self::Struct) | ||
const_set :Struct, Struct.new(*attributes) | ||
end | ||
self::Struct | ||
end | ||
|
||
def initialize # :notnew: | ||
super() | ||
@data = AttrAccessors.struct.new | ||
end | ||
|
||
# Freezes the internal attributes struct, in addition to +self+. | ||
def freeze | ||
data.freeze | ||
super | ||
end | ||
|
||
protected | ||
|
||
attr_reader :data # :nodoc: internal API | ||
|
||
private | ||
|
||
def initialize_dup(other) | ||
super | ||
@data = other.data.dup | ||
end | ||
|
||
end | ||
end | ||
end | ||
end |
Oops, something went wrong.