Skip Menu |

This queue is for tickets about the Object-InsideOut CPAN distribution.

Report information
The Basics
Id: 32109
Status: resolved
Priority: 0/
Queue: Object-InsideOut

People
Owner: Nobody in particular
Requestors: perl [...] dannywarren.com
Cc:
AdminCc:

Bug Information
Severity: Unimportant
Broken in: 3.35
Fixed in: (no value)



Subject: Permissions error when calling :Restricted method in an adjacent parent class
First, thank you for all your work on this amazing module. Having this at my disposal makes refactoring old code and building new libraries a pleasure. Please see the attached test.pl and test.error files, as those describe the issue better than I am about to. In short, I am unable to call a :Restricted method from an adjacent parent class. For example, in the following layout... package Baz; { use Object::InsideOut; } package Bar; { use Object::InsideOut; } package Foo; { use Object::InsideOut qw| Bar Baz |; } ..all three objects would report themselves as belonging to Foo, Bar and Baz via "->isa()" or "->meta()->get_classes()". I would therefore expect to be able to call :Restricted methods in Baz from Bar, and vice- versa, since they are now in the hierarchy chain thanks to Foo. However, attempts to call a :Restricted method in Baz from Bar results in a permissions failure. Looking at the Object::InsideOut closure that performs the permission checks... # Returns a 'wrapper' closure back to initialize() that restricts a method # to being only callable from within its class hierarchy sub wrap_RESTRICTED :Sub(Private) { my ($pkg, $method, $code, $except) = @_; return sub { # Caller must be in class hierarchy, or be specified as an exception my $caller = caller(); if (! ((grep { $_ eq $caller } @$except) || $GBL{'isa'}->($caller, $pkg) || $GBL{'isa'}->($pkg, $caller))) { OIO::Method->die('message' => "Can't call restricted method '$pkg->$method' from class '$caller'"); } goto $code; }; } ...I see that it is using the original UNIVERSAL::isa directly instead of passing it through the overloaded one, which returns false in this case and prevents the call to the :Restricted method. If I make it public or add an exemption, it of course works fine. It is entirely possible that I am grossly misunderstanding the hierarchy coupling, so if this is the case please let me know. Given my ignorance of the underlying mechanisms, though, it seems to me like if I get a thumbs up from $self->isa() in my app code, I should be able to call :Restricted methods therein. Thanks in advance for looking at this!
Subject: perl.version
Download perl.version
application/octet-stream 2.9k

Message body not shown because it is not plain text.

Subject: test.pl
package Derp; { use Object::InsideOut; sub say_derp { my ( $self ) = @_; print "Derp isa: " . ( join q{ }, $self->isa() ) . "\n" ; return; } } package Baz; { use Object::InsideOut; sub say_baz :Restricted { my ( $self ) = @_; print "Baz isa: " . ( join q{ }, $self->isa() ) . "\n" ; return; } } package Bar; { use Object::InsideOut; sub say_bar :Restricted { my ( $self ) = @_; print "Bar isa: " . ( join q{ }, $self->isa() ) . "\n" ; # THIS WORKS # Say hello from a public method in one of the other parents # in the hierarchy $self->say_derp(); # THIS FAILS # Say hello from a restricted method in one of the other parents # in the hierarchy $self->say_baz(); } } package Foo; { use Object::InsideOut qw| Bar Baz Derp |; sub say_foo { my ( $self ) = @_; print "Foo isa: " . ( join q{ }, $self->isa() ) . "\n" ; # Say hello from a restricted method in one of our parents, Bar $self->say_bar(); return; } } package main; my $foo = Foo->new(); $foo->say_foo();
Subject: test.error
Download test.error
application/octet-stream 354b

Message body not shown because it is not plain text.

Subject: os.version
Download os.version
application/octet-stream 36b

Message body not shown because it is not plain text.

From: jdhedden [...] cpan.org
Show quoted text
> package Baz; > { use Object::InsideOut; } > > package Bar; > { use Object::InsideOut; } > > package Foo; > { use Object::InsideOut qw| Bar Baz |; } > > > ..all three objects would report themselves as belonging > to Foo, Bar and Baz via "->isa()" or > "->meta()->get_classes()".
Not quite. Bar isa Bar, Baz isa Baz and Foo is all three. package Baz; { use Object::InsideOut; } package Bar; { use Object::InsideOut; } package Foo; { use Object::InsideOut qw| Bar Baz |; } package main; my $baz = Baz->new(); print('BAZ: ', $baz->isa(), "\n"); my $bar = Bar->new(); print('BAR: ', $bar->isa(), "\n"); my $foo = Foo->new(); print('FOO: ', $foo->isa(), "\n"); produces: BAZ: Baz BAR: Bar FOO: BarBazFoo It is a hierarchy, and not an agglomeration. Show quoted text
> I would therefore expect to be able to call :Restricted > methods in Baz from Bar, and vice-versa, since they are > now in the hierarchy chain thanks to Foo.
No. Foo knows about both its parents, but the other two are independent of each other. When you have a hierarchy, child classes know about parent classes higher up in the hierarchy, but parent classes don't know about each other. It's a tree, and not a 'chain'.
Show quoted text
> When you have a hierarchy, child classes know about parent > classes higher up in the hierarchy, but parent classes don't > know about each other.
On reading the docs, I see that this could be made clearer with respect to describing :Restricted methods. I'll do that for the next release. In your case, you can use the 'Exemptions' feature for methods in Bar/Baz you want to call from each other. See the docs for details. Thanks for using OIO.
From: perl [...] dannywarren.com
On Tue Jan 08 17:28:27 2008, JDHEDDEN wrote: Show quoted text
> > When you have a hierarchy, child classes know about parent > > classes higher up in the hierarchy, but parent classes don't > > know about each other.
> > On reading the docs, I see that this could be made clearer > with respect to describing :Restricted methods. I'll do > that for the next release. > > In your case, you can use the 'Exemptions' feature for > methods in Bar/Baz you want to call from each other. See > the docs for details. > > Thanks for using OIO.
...and thank *you* for taking the time to look over my ticket and answering my questions, even though the issue turned out to be a misunderstanding on my part. Looks like I have some more reading and refactoring to do! Thanks again for all your awesome work in this module.
(accidental re-open)