Bug #20808
closedData#pretty_print doesn't handle private or remove attribute readers
Description
Given the next code:
Dog = Data.define(:name) do
def inspect
"Hello!"
end
private
attr_reader :name
end
Dog.new(name: "Fido")
It throws an error:
- An error occurred when inspecting the object: #<NoMethodError: private method `name' called for an instance of Dog>
And isn't using my inspect
function
Updated by byroot (Jean Boussier) 10 months ago
So the problem isn't with inspect
, as it only reproduce in irb
.
It's coming from pretty_inspect
:
>> d.pretty_inspect
/opt/rubies/3.3.5/lib/ruby/3.3.0/pp.rb:432:in `public_send': private method `name' called for an instance of Dog (NoMethodError)
q.pp public_send(member)
^^^^^^^^^^^
from /opt/rubies/3.3.5/lib/ruby/3.3.0/pp.rb:432:in `block (3 levels) in pretty_print'
from /opt/rubies/3.3.5/lib/ruby/3.3.0/prettyprint.rb:255:in `block (2 levels) in group'
from /opt/rubies/3.3.5/lib/ruby/3.3.0/prettyprint.rb:282:in `nest'
from /opt/rubies/3.3.5/lib/ruby/3.3.0/prettyprint.rb:254:in `block in group'
from /opt/rubies/3.3.5/lib/ruby/3.3.0/prettyprint.rb:267:in `group_sub'
from /opt/rubies/3.3.5/lib/ruby/3.3.0/prettyprint.rb:253:in `group'
from /opt/rubies/3.3.5/lib/ruby/3.3.0/pp.rb:430:in `block (2 levels) in pretty_print'
from /opt/rubies/3.3.5/lib/ruby/3.3.0/pp.rb:264:in `block in seplist'
from /opt/rubies/3.3.5/lib/ruby/3.3.0/pp.rb:258:in `each'
from /opt/rubies/3.3.5/lib/ruby/3.3.0/pp.rb:258:in `seplist'
from /opt/rubies/3.3.5/lib/ruby/3.3.0/pp.rb:426:in `block in pretty_print'
from /opt/rubies/3.3.5/lib/ruby/3.3.0/prettyprint.rb:255:in `block (2 levels) in group'
from /opt/rubies/3.3.5/lib/ruby/3.3.0/prettyprint.rb:282:in `nest'
from /opt/rubies/3.3.5/lib/ruby/3.3.0/prettyprint.rb:254:in `block in group'
from /opt/rubies/3.3.5/lib/ruby/3.3.0/prettyprint.rb:267:in `group_sub'
from /opt/rubies/3.3.5/lib/ruby/3.3.0/prettyprint.rb:253:in `group'
Updated by byroot (Jean Boussier) 10 months ago
The pp
implementation for Struct
and Data
both assume all member readers are public:
class Struct # :nodoc:
def pretty_print(q) # :nodoc:
q.group(1, sprintf("#<struct %s", PP.mcall(self, Kernel, :class).name), '>') {
q.seplist(PP.mcall(self, Struct, :members), lambda { q.text "," }) {|member|
q.breakable
q.text member.to_s
q.text '='
q.group(1) {
q.breakable ''
q.pp self[member]
}
}
}
end
def pretty_print_cycle(q) # :nodoc:
q.text sprintf("#<struct %s:...>", PP.mcall(self, Kernel, :class).name)
end
end
class Data # :nodoc:
def pretty_print(q) # :nodoc:
q.group(1, sprintf("#<data %s", PP.mcall(self, Kernel, :class).name), '>') {
q.seplist(PP.mcall(self, Data, :members), lambda { q.text "," }) {|member|
q.breakable
q.text member.to_s
q.text '='
q.group(1) {
q.breakable ''
q.pp public_send(member)
}
}
}
end
def pretty_print_cycle(q) # :nodoc:
q.text sprintf("#<data %s:...>", PP.mcall(self, Kernel, :class).name)
end
end if "3.2" <= RUBY_VERSION
Updated by byroot (Jean Boussier) 10 months ago
Struct and Data both assume all member readers are public:
Actually I misread. The Struct
one uses Struct#[]
so it would work with Struct. Data
however has no such method, so two solutions I can think of are:
- Use
send
, but only work for private. If instead the method is renamed or removed, it will still fail. - Rescue
NoMethodError
, and skip displaying that field.
Updated by byroot (Jean Boussier) 10 months ago
cc @akr (Akira Tanaka) , as maintainer of PP perhaps you have an opinion on how this sort of issue should be handled?
Updated by mame (Yusuke Endoh) 10 months ago
The code in question is written by @osyo and committed by @nobu (Nobuyoshi Nakada). Just FYI.
Updated by byroot (Jean Boussier) 10 months ago
- Subject changed from Cannot override Data#inspect to Data#pretty_print doesn't handle private or remove attribute readers
Updated by mame (Yusuke Endoh) 9 months ago
Discussed the dev meeting. @akr (Akira Tanaka) said using __send__
instead of public_send
would be good.
Updated by byroot (Jean Boussier) 9 months ago
Proposed patch: https://github.com/ruby/pp/pull/29
Updated by byroot (Jean Boussier) 9 months ago
- Status changed from Open to Closed
Applied in changeset git|107a4da122126e6d0e0ad12898d7511e472709a3.
[ruby/pp] Data#pretty_print handle privated or removed members
[Bug #20808]
The previous implementation assumed all members are accessible,
but it's possible for users to change the visibility of members or
to entirely remove the accessor.