Skip to content

Commit 6093acb

Browse files
committed
🔍 Improve Config#inspect output
Viewing config objects in Irb was _much_ too messy to easily inspect: it every attribute for each ancestor, and most of them would simply be the Net::IMAP::Config::AttrInheritance::INHERITED const, repeated over and over. Now, `Net::IMAP::Config#inspect` only shows overridden config attributes within the inheritance chain.
1 parent 61b2e4d commit 6093acb

File tree

2 files changed

+128
-0
lines changed

2 files changed

+128
-0
lines changed

lib/net/imap/config.rb

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,8 +485,92 @@ def load_defaults(version)
485485
# Returns all config attributes in a hash.
486486
def to_h; data.members.to_h { [_1, send(_1)] } end
487487

488+
# Returns a string representation of overriden config attributes and the
489+
# inheritance chain.
490+
#
491+
# Attributes overridden by ancestors are also inspected, recursively.
492+
# Attributes that are inherited from default configs are not shown (see
493+
# Config@Versioned+defaults and Config@Named+defaults).
494+
#
495+
# # (Line breaks have been added to the example output for legibility.)
496+
#
497+
# Net::IMAP::Config.new(0.4)
498+
# .new(open_timeout: 10, enforce_logindisabled: true)
499+
# .inspect
500+
# #=> "#<Net::IMAP::Config:0x0000745871125410 open_timeout=10 enforce_logindisabled=true
501+
# # inherits from Net::IMAP::Config[0.4]
502+
# # inherits from Net::IMAP::Config.global
503+
# # inherits from Net::IMAP::Config.default>"
504+
#
505+
# Non-default attributes are listed after the ancestor config from which
506+
# they are inherited.
507+
#
508+
# # (Line breaks have been added to the example output for legibility.)
509+
#
510+
# config = Net::IMAP::Config.global
511+
# .new(open_timeout: 10, idle_response_timeout: 2)
512+
# .new(enforce_logindisabled: :when_capabilities_cached, sasl_ir: false)
513+
# config.inspect
514+
# #=> "#<Net::IMAP::Config:0x00007ce2a1e20e40 sasl_ir=false enforce_logindisabled=:when_capabilities_cached
515+
# # inherits from Net::IMAP::Config:0x00007ce2a1e20f80 open_timeout=10 idle_response_timeout=2
516+
# # inherits from Net::IMAP::Config.global
517+
# # inherits from Net::IMAP::Config.default>"
518+
#
519+
# Net::IMAP.debug = true
520+
# config.inspect
521+
# #=> "#<Net::IMAP::Config:0x00007ce2a1e20e40 sasl_ir=false enforce_logindisabled=:when_capabilities_cached
522+
# # inherits from Net::IMAP::Config:0x00007ce2a1e20f80 open_timeout=10 idle_response_timeout=2
523+
# # inherits from Net::IMAP::Config.global debug=true
524+
# # inherits from Net::IMAP::Config.default>"
525+
#
526+
# Use #to_h to inspect all config attributes ignoring inheritance.
527+
def inspect;
528+
"#<#{inspect_recursive}>"
529+
end
530+
alias to_s inspect
531+
532+
# :stopdoc:
533+
488534
protected
489535

536+
def named_default?
537+
equal?(Config.default) ||
538+
AttrVersionDefaults::VERSIONS.any? { equal? Config[_1] }
539+
end
540+
541+
def name
542+
if equal? Config.default then "#{Config}.default"
543+
elsif equal? Config.global then "#{Config}.global"
544+
elsif equal? Config[0.0r] then "#{Config}[:original]"
545+
elsif equal? Config[:default] then "#{Config}[:default]"
546+
elsif (v = AttrVersionDefaults::VERSIONS.find { equal? Config[_1] })
547+
"%s[%0.1f]" % [Config, v]
548+
else
549+
Kernel.instance_method(:to_s).bind_call(self).delete("<#>")
550+
end
551+
end
552+
553+
def inspect_recursive(attrs = AttrAccessors.struct.members)
554+
strings = [name]
555+
assigned = assigned_attrs_hash(attrs)
556+
strings.concat assigned.map { "%s=%p" % _1 }
557+
if parent
558+
if parent.equal?(Config.default)
559+
inherited_overrides = []
560+
elsif parent
561+
inherited_overrides = attrs - assigned.keys
562+
inherited_overrides &= DEFAULT_TO_INHERIT if parent.named_default?
563+
end
564+
strings << "inherits from #{parent.inspect_recursive(inherited_overrides)}"
565+
end
566+
strings.join " "
567+
end
568+
569+
def assigned_attrs_hash(attrs)
570+
own_attrs = attrs.reject { inherited?(_1) }
571+
own_attrs.to_h { [_1, data[_1]] }
572+
end
573+
490574
def defaults_hash
491575
to_h.reject {|k,v| DEFAULT_TO_INHERIT.include?(k) }
492576
end

test/net/imap/test_config.rb

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,4 +440,48 @@ def duck.to_r = 1/11111
440440
assert_raise(TypeError) do config.max_response_size = :invalid end
441441
end
442442

443+
def config_id(config)
444+
Kernel.instance_method(:to_s).bind_call(config).match(/0x(\h*)>/)[1]
445+
end
446+
447+
test "#inspect" do
448+
assert_equal(
449+
"#<#{Config}.global inherits from #{Config}.default>",
450+
Config.global.inspect
451+
)
452+
453+
Config.global.debug = true
454+
assert_equal(
455+
"#<#{Config}.global debug=true inherits from #{Config}.default>",
456+
Config.global.inspect
457+
)
458+
459+
config = Config.global.new(sasl_ir: true)
460+
id = config_id(config)
461+
assert_equal(
462+
"#<#{Config}:0x#{id} sasl_ir=true " \
463+
"inherits from #{Config}.global debug=true " \
464+
"inherits from #{Config}.default>",
465+
config.inspect
466+
)
467+
468+
Config.global.reset(:debug)
469+
nested = Config[0.4].new(sasl_ir: true).new(open_timeout: 60)
470+
assert_equal(
471+
"#<#{Config}:0x#{config_id(nested)} open_timeout=60 " \
472+
"inherits from #{Config}:0x#{config_id(nested.parent)} sasl_ir=true " \
473+
"inherits from #{Config}[0.4] " \
474+
"inherits from #{Config}.global " \
475+
"inherits from #{Config}.default>",
476+
nested.inspect
477+
)
478+
479+
config_attrs = Config::AttrAccessors.struct.members
480+
.map { / #{_1}=.+/.source }.join
481+
assert_match(
482+
/#<#{Config}.default#{config_attrs}>/,
483+
Config.default.inspect
484+
)
485+
end
486+
443487
end

0 commit comments

Comments
 (0)