Actions
Bug #20808
openData#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) 14 days 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) 14 days 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) 14 days 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) 14 days 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) 14 days ago
The code in question is written by @osyo (manga osyo) and committed by @nobu (Nobuyoshi Nakada). Just FYI.
Updated by byroot (Jean Boussier) 14 days ago
- Subject changed from Cannot override Data#inspect to Data#pretty_print doesn't handle private or remove attribute readers
Actions
Like0
Like1Like0Like1Like0Like0Like0