From 0c16adbe2ef4de6df4d59ad23ac5bb57772bfecd Mon Sep 17 00:00:00 2001 From: nick evans Date: Tue, 18 Nov 2025 11:50:08 -0500 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A7=20Add=20recursive=20`Config#inheri?= =?UTF-8?q?ts=5Fdefaults=3F`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Returns `true` when all attributes inherit from `Config.default`, the version number (as a Rational) when all attributes inherit from a versioned default, `nil` if any attributes inherit from `Config.global` overrides (but not from non-global ancestors), or `false` when any attributes have been overridden by `self` or an ancestor (besides global or default configs), --- lib/net/imap/config/attr_inheritance.rb | 30 +++++++++++++++ test/net/imap/test_config.rb | 50 +++++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/lib/net/imap/config/attr_inheritance.rb b/lib/net/imap/config/attr_inheritance.rb index c62539a6..daa6736d 100644 --- a/lib/net/imap/config/attr_inheritance.rb +++ b/lib/net/imap/config/attr_inheritance.rb @@ -73,6 +73,36 @@ def inherited?(*attrs) attrs.all? { data[_1] == INHERITED } end + # :call-seq: + # inherits_defaults?(*attrs) -> true | Rational | nil | false + # + # Returns whether all +attrs+ are inherited from a default config. + # When no +attrs+ are given, returns whether *all* attributes are + # inherited from a default config. + # + # Returns +true+ when all attributes inherit from Config.default, the + # version number (as a Rational) when all attributes inherit from a + # versioned default (see Config@Versioned+defaults), +nil+ if any + # attributes inherit from Config.global overrides (but not from + # non-global ancestors), or +false+ when any attributes have been + # overridden by +self+ or an ancestor (besides global or default + # configs), + # + # Related: #overrides? + def inherits_defaults?(*attrs) + if equal?(Config.default) + true + elsif equal?(Config.global) + true if inherited?(*attrs) + elsif (v = AttrVersionDefaults::VERSIONS.find { equal? Config[_1] }) + attrs = DEFAULT_TO_INHERIT if attrs.empty? + attrs &= DEFAULT_TO_INHERIT + (attrs.empty? || parent.inherits_defaults?(*attrs)) && v + else + inherited?(*attrs) && parent.inherits_defaults?(*attrs) + end + end + # :call-seq: # overrides?(attr) -> true or false # overrides?(*attrs) -> true or false diff --git a/test/net/imap/test_config.rb b/test/net/imap/test_config.rb index 13671bc7..5c03adf6 100644 --- a/test/net/imap/test_config.rb +++ b/test/net/imap/test_config.rb @@ -349,6 +349,56 @@ def duck.to_r = 1/11111 assert child.inherited?(:debug, :idle_response_timeout, :open_timeout) end + test "#inherits_defaults?" do + assert_same true, Config.default.inherits_defaults? + assert_same true, Config.default.inherits_defaults?(:sasl_ir, :open_timeout) + + assert_equal true, Config.global.inherits_defaults? + Config.version_defaults.each do |name, config| + version = config.inherits_defaults? + assert_kind_of Rational, version + assert_same Config[version], config + assert_same version, config.inherits_defaults?(:sasl_ir, :open_timeout) + end + + Config.global.debug = false + assert_equal nil, Config.global.inherits_defaults? + assert_equal true, Config.global.inherits_defaults?(:sasl_ir, :open_timeout) + Config.version_defaults.each do |name, config| + assert_equal nil, config.inherits_defaults? + version = config.inherits_defaults?(:sasl_ir, :open_timeout) + assert_kind_of Rational, version + assert_same Config[version], config + end + + config = Config.new 0.5 + assert_equal nil, config.inherits_defaults? + Config.global.reset + assert_equal 0.5r, config.inherits_defaults? + + config.debug = false + assert_equal false, config.inherits_defaults? + assert_equal 0.5r, config.inherits_defaults?(:sasl_ir, :open_timeout) + + child = config.new debug: true, sasl_ir: true + assert_equal false, child.inherits_defaults? + assert_equal false, child.inherits_defaults?(:sasl_ir, :open_timeout) + assert_equal 0.5r, child.inherits_defaults?(:open_timeout) + + Config.global.sasl_ir = true + Config.global.open_timeout = 111 + # inherits defaults from 0.5 + assert_equal false, config.inherits_defaults? + assert_equal 0.5r, config.inherits_defaults?(:sasl_ir, :open_timeout) + config.reset + assert_equal 0.5r, config.inherits_defaults? + # inherits overrides from global + config = Config.new + assert_equal nil, config.inherits_defaults? + assert_equal nil, config.inherits_defaults?(:sasl_ir, :open_timeout) + assert_equal true, config.inherits_defaults?(:debug) + end + test "#overrides?" do base = Config.new debug: false, open_timeout: 99, idle_response_timeout: 15 child = base.new debug: true, open_timeout: 15, idle_response_timeout: 10