123456789_123456789_123456789_123456789_123456789_

Class: Net::IMAP::Config

Overview

Config (available since v0.4.13) stores configuration options for ::Net::IMAP clients. The global configuration can be seen at either config or .global, and the client-specific configuration can be seen at #config.

When creating a new client, all unhandled keyword arguments to new are delegated to .new. Every client has its own config.

debug_client = Net::IMAP.new(hostname, debug: true)
quiet_client = Net::IMAP.new(hostname, debug: false)
debug_client.config.debug?  # => true
quiet_client.config.debug?  # => false

Inheritance

Configs have a 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 .global.

plain_client = Net::IMAP.new(hostname)
debug_client = Net::IMAP.new(hostname, debug: true)
quiet_client = Net::IMAP.new(hostname, debug: false)

plain_client.config.inherited?(:debug)  # => true
debug_client.config.inherited?(:debug)  # => false
quiet_client.config.inherited?(:debug)  # => false

plain_client.config.debug?  # => false
debug_client.config.debug?  # => true
quiet_client.config.debug?  # => false

# Net::IMAP.debug is delegated to Net::IMAP::Config.global.debug
Net::IMAP.debug = true
plain_client.config.debug?  # => true
debug_client.config.debug?  # => true
quiet_client.config.debug?  # => false

Net::IMAP.debug = false
plain_client.config.debug = true
plain_client.config.inherited?(:debug)  # => false
plain_client.config.debug?  # => true
plain_client.config.reset(:debug)
plain_client.config.inherited?(:debug)  # => true
plain_client.config.debug?  # => false

Versioned defaults

The effective default configuration for a specific x.y version of net-imap can be loaded with the config keyword argument to new. Requesting default configurations for previous versions enables extra backward compatibility with those versions:

client = Net::IMAP.new(hostname, config: 0.3)
client.config.sasl_ir                  # => false
client.config.responses_without_block  # => :silence_deprecation_warning

client = Net::IMAP.new(hostname, config: 0.4)
client.config.sasl_ir                  # => true
client.config.responses_without_block  # => :silence_deprecation_warning

client = Net::IMAP.new(hostname, config: 0.5)
client.config.sasl_ir                  # => true
client.config.responses_without_block  # => :warn

client = Net::IMAP.new(hostname, config: :future)
client.config.sasl_ir                  # => true
client.config.responses_without_block  # => :frozen_dup

The versioned default configs inherit certain specific config options from .global, for example #debug:

client = Net::IMAP.new(hostname, config: 0.4)
Net::IMAP.debug = false
client.config.debug?  # => false

Net::IMAP.debug = true
client.config.debug?  # => true

Use #load_defaults to globally behave like a specific version:

client = Net::IMAP.new(hostname)
client.config.sasl_ir              # => true
Net::IMAP.config.load_defaults 0.3
client.config.sasl_ir              # => false

Named defaults

In addition to x.y version numbers, the following aliases are supported:

:default

An alias for :current.

NOTE: This is not the same as Config.default. It inherits some attributes from Config.global, for example: #debug.

:current

An alias for the current x.y version’s defaults.

:next

The planned config for the next x.y version.

:future

The planned eventual config for some future x.y version.

For example, to disable all currently deprecated behavior:

client = Net::IMAP.new(hostname, config: :future)
client.config.response_without_args     # => :frozen_dup
client.responses.frozen?                # => true
client.responses.values.all?(&:frozen?) # => true

Thread Safety

NOTE: Updates to config objects are not synchronized for thread-safety.

Constant Summary

AttrInheritance - Included

INHERITED

AttrTypeCoercion - Included

Enum, NilOrInteger, Types

Class Attribute Summary

Class Method Summary

AttrVersionDefaults - Extended

Instance Attribute Summary

AttrInheritance - Included

#parent

The parent Config object.

AttrAccessors - Included

#data

internal API.

Instance Method Summary

AttrInheritance - Included

#inherited?

Returns true if attr is inherited from #parent and not overridden by this config.

#initialize

:notnew:

#new

Creates a new config, which inherits from self.

#reset

Resets an attr to inherit from the #parent config.

#initialize_copy

AttrAccessors - Included

#freeze

Freezes the internal attributes struct, in addition to self.

#initialize

:notnew:

#initialize_clone, #initialize_dup

Constructor Details

.new(parent = Config.global, **attrs) {|_self| ... } ⇒ Config

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.

Yields:

  • (_self)

Yield Parameters:

  • _self (Config)

    the object that the method was called on

[ GitHub ]

  
# File 'lib/net/imap/config.rb', line 432

def initialize(parent = Config.global, **attrs)
  super(parent)
  update(**attrs)
  yield self if block_given?
end

Class Method Details

Net::IMAP::ConfigConfig Net::IMAP::ConfigConfig Net::IMAP::ConfigConfig Net::IMAP::ConfigConfig

Given a version number, returns the default configuration for the target version. See Config@Versioned+defaults.

Given a version name, returns the default configuration for the target version. See Config@Named+defaults.

Given a Hash, creates a new frozen config which inherits from .global. Use .new for an unfrozen config.

Given a config, returns that same config.

[ GitHub ]

  
# File 'lib/net/imap/config.rb', line 163

def self.[](config)
  if    config.is_a?(Config)         then config
  elsif config.nil? && global.nil?   then nil
  elsif config.respond_to?(:to_hash) then new(global, **config).freeze
  else
    version_defaults[config] or
      case config
      when Numeric
        raise RangeError, "unknown config version: %p" % [config]
      when String, Symbol
        raise KeyError, "unknown config name: %p" % [config]
      else
        raise TypeError, "no implicit conversion of %s to %s" % [
          config.class, Config
        ]
      end
  end
end

.default

The default config, which is hardcoded and frozen.

[ GitHub ]

  
# File 'lib/net/imap/config.rb', line 129

def self.default; @default end

.global

The global config object. Also available from Net::IMAP.config.

[ GitHub ]

  
# File 'lib/net/imap/config.rb', line 132

def self.global; @global if defined?(@global) end

.version_defaults

A hash of hard-coded configurations, indexed by version number or name. Values can be accessed with any object that responds to to_sym or to_r+/+to_f with a non-zero number.

.[] gets named or numbered versions from this hash.

For example:

Net::IMAP::Config.version_defaults[0.5] == Net::IMAP::Config[0.5]
Net::IMAP::Config[0.5]       == Net::IMAP::Config[0.5r]     # => true
Net::IMAP::Config["current"] == Net::IMAP::Config[:current] # => true
Net::IMAP::Config["0.5.6"]   == Net::IMAP::Config[0.5r]     # => true
[ GitHub ]

  
# File 'lib/net/imap/config.rb', line 145

def self.version_defaults; AttrVersionDefaults.version_defaults end

Instance Attribute Details

#named_default?Boolean (readonly, protected)

This method is for internal use only.
[ GitHub ]

  
# File 'lib/net/imap/config.rb', line 572

def named_default?
  equal?(Config.default) ||
    AttrVersionDefaults::VERSIONS.any? { equal? Config[_1] }
end

Instance Method Details

#assigned_attrs_hash(attrs) (protected)

This method is for internal use only.
[ GitHub ]

  
# File 'lib/net/imap/config.rb', line 625

def assigned_attrs_hash(attrs)
  own_attrs = attrs.reject { inherited?(_1) }
  own_attrs.to_h { [_1, data[_1]] }
end

#defaults_hash (protected)

This method is for internal use only.
[ GitHub ]

  
# File 'lib/net/imap/config.rb', line 630

def defaults_hash
  to_h.reject {|k,v| DEFAULT_TO_INHERIT.include?(k) }
end

#inspect Also known as: #to_s

Returns a string representation of overriden config attributes and the inheritance chain.

Attributes overridden by ancestors are also inspected, recursively. Attributes that are inherited from default configs are not shown (see Config@Versioned+defaults and Config@Named+defaults).

# (Line breaks have been added to the example output for legibility.)

Net::IMAP::Config.new(0.4)
  .new(open_timeout: 10, enforce_logindisabled: true)
  .inspect
#=> "#<Net::IMAP::Config:0x0000745871125410 open_timeout=10 enforce_logindisabled=true
#      inherits from Net::IMAP::Config[0.4]
#      inherits from Net::IMAP::Config.global
#      inherits from Net::IMAP::Config.default>"

Non-default attributes are listed after the ancestor config from which they are inherited.

# (Line breaks have been added to the example output for legibility.)

config = Net::IMAP::Config.global
  .new(open_timeout: 10, idle_response_timeout: 2)
  .new(enforce_logindisabled: :when_capabilities_cached, sasl_ir: false)
config.inspect
#=> "#<Net::IMAP::Config:0x00007ce2a1e20e40 sasl_ir=false enforce_logindisabled=:when_capabilities_cached
#      inherits from Net::IMAP::Config:0x00007ce2a1e20f80 open_timeout=10 idle_response_timeout=2
#      inherits from Net::IMAP::Config.global
#      inherits from Net::IMAP::Config.default>"

Net::IMAP.debug = true
config.inspect
#=> "#<Net::IMAP::Config:0x00007ce2a1e20e40 sasl_ir=false enforce_logindisabled=:when_capabilities_cached
#      inherits from Net::IMAP::Config:0x00007ce2a1e20f80 open_timeout=10 idle_response_timeout=2
#      inherits from Net::IMAP::Config.global debug=true
#      inherits from Net::IMAP::Config.default>"

Use pp (see #pretty_print) to inspect all config attributes, including default values.

Use #to_h to inspect all config attributes ignoring inheritance.

[ GitHub ]

  
# File 'lib/net/imap/config.rb', line 536

def inspect;
  "#<#{inspect_recursive}>"
end

#inspect_recursive(attrs = AttrAccessors.struct.members) (protected)

This method is for internal use only.
[ GitHub ]

  
# File 'lib/net/imap/config.rb', line 589

def inspect_recursive(attrs = AttrAccessors.struct.members)
  strings  = [name]
  assigned = assigned_attrs_hash(attrs)
  strings.concat assigned.map { "%s=%p" % _1 }
  if parent
    if parent.equal?(Config.default)
      inherited_overrides = []
    elsif parent
      inherited_overrides = attrs - assigned.keys
      inherited_overrides &= DEFAULT_TO_INHERIT if parent.named_default?
    end
    strings << "inherits from #{parent.inspect_recursive(inherited_overrides)}"
  end
  strings.join " "
end

#load_defaults(version) ⇒ self

Resets the current config to behave like the versioned default configuration for version. #parent will not be changed.

Some config attributes default to inheriting from their #parent (which is usually .global) and are left unchanged, for example: #debug.

See Config@Versioned+defaults and Config@Named+defaults.

[ GitHub ]

  
# File 'lib/net/imap/config.rb', line 483

def load_defaults(version)
  [Numeric, Symbol, String].any? { _1 === version } or
    raise ArgumentError, "expected number or symbol, got %p" % [version]
  update(**Config[version].defaults_hash)
end

#name (protected)

This method is for internal use only.
[ GitHub ]

  
# File 'lib/net/imap/config.rb', line 577

def name
  if    equal? Config.default   then "#{Config}.default"
  elsif equal? Config.global    then "#{Config}.global"
  elsif equal? Config[0.0r]     then "#{Config}[:original]"
  elsif equal? Config[:default] then "#{Config}[:default]"
  elsif (v = AttrVersionDefaults::VERSIONS.find { equal? Config[_1] })
    "%s[%0.1f]" % [Config, v]
  else
    Kernel.instance_method(:to_s).bind_call(self).delete("<#>")
  end
end

#pretty_print(pp)

Used by PP to create a string representation of all config attributes and the inheritance chain. Inherited attributes are listed with the ancestor config from which they are inherited.

pp Config.new[0.4].new(open_timeout: 10, idle_response_timeout: 10)
# #<Net::IMAP::Config:0x0000745871125410
#   open_timeout=10
#   idle_response_timeout=10
#   inherits from Net::IMAP::Config[0.4]
#     responses_without_block=:silence_deprecation_warning
#     max_response_size=nil
#     sasl_ir=true
#     enforce_logindisabled=false
#     parser_use_deprecated_uidplus_data=true
#     parser_max_deprecated_uidplus_data_size=1000
#     inherits from Net::IMAP::Config.global
#       inherits from Net::IMAP::Config.default
#         debug=false>

Related: #inspect, #to_h.

[ GitHub ]

  
# File 'lib/net/imap/config.rb', line 562

def pretty_print(pp)
  pp.group(2, "#<", ">") do
    pretty_print_recursive(pp)
  end
end

#pretty_print_recursive(pp, attrs = AttrAccessors.struct.members) (protected)

This method is for internal use only.
[ GitHub ]

  
# File 'lib/net/imap/config.rb', line 605

def pretty_print_recursive(pp, attrs = AttrAccessors.struct.members)
  pp.text name
  assigned = assigned_attrs_hash(attrs)
  pp.breakable
  pp.seplist(assigned, ->{pp.breakable}) do |key, val|
    pp.text key.to_s
    pp.text "="
    pp.pp val
  end
  if parent
    pp.breakable if assigned.any?
    pp.nest(2) do
      pp.text "inherits from "
      parent.pretty_print_recursive(pp, attrs - assigned.keys)
    end
  elsif assigned.empty?
    pp.text "(overridden)"
  end
end

#responses_without_args

This method is for internal use only.
[ GitHub ]

  
# File 'lib/net/imap/config.rb', line 355

alias responses_without_args  responses_without_block  # :nodoc:

#responses_without_args=

This method is for internal use only.
[ GitHub ]

  
# File 'lib/net/imap/config.rb', line 356

alias responses_without_args= responses_without_block= # :nodoc:

#sasl_ir?

This method is for internal use only.
[ GitHub ]

  
# File 'lib/net/imap/config.rb', line 254

alias sasl_ir? sasl_ir

#to_hHash

Returns all config attributes in a hash.

[ GitHub ]

  
# File 'lib/net/imap/config.rb', line 492

def to_h; data.members.to_h { [_1, send(_1)] } end

#to_s

Alias for #inspect.

[ GitHub ]

  
# File 'lib/net/imap/config.rb', line 539

alias to_s inspect

#update(**attrs) ⇒ self

Assigns all of the provided attrs to this config, and returns self.

An ArgumentError is raised unless every key in attrs matches an assignment method on Config.

NOTE: #update is not atomic. If an exception is raised due to an invalid attribute value, attrs may be partially applied.

[ GitHub ]

  
# File 'lib/net/imap/config.rb', line 448

def update(**attrs)
  unless (bad = attrs.keys.reject { respond_to?(:"#{_1}=") }).empty?
    raise ArgumentError, "invalid config options: #{bad.join(", ")}"
  end
  attrs.each do send(:"#{_1}=", _2) end
  self
end

#with(**attrs) ⇒ Config #with(**attrs) {|config| ... } ⇒ result

Without a block, returns a new config which inherits from self. With a block, yields the new config and returns the block’s result.

If no keyword arguments are given, an ArgumentError will be raised.

If self is frozen, the copy will also be frozen.

[ GitHub ]

  
# File 'lib/net/imap/config.rb', line 466

def with(**attrs)
  attrs.empty? and
    raise ArgumentError, "expected keyword arguments, none given"
  copy = new(**attrs)
  copy.freeze if frozen?
  block_given? ? yield(copy) : copy
end