Skip Menu |

This queue is for tickets about the Class-Sniff CPAN distribution.

Report information
The Basics
Id: 43318
Status: resolved
Priority: 0/
Queue: Class-Sniff

People
Owner: ovid [...] cpan.org
Requestors: jesse+cpan [...] fsck.com
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: 0.08
Fixed in: (no value)



Subject: Class::Sniff seems to detect things that aren't "real" classes/packages
I decided today to run Class::Sniff against a loaded copy of RT. I got a whole bunch of false positives for classes using the script pasted below. It found a bunch of ::SUPER packages as well as packages for every filename required, which isn't quite right. RT's classes all do this: eval "require RT::Ticket_Overlay"; if ($@ && $@ !~ qr{^Can't locate RT/Ticket_Overlay.pm}) { die $@; }; eval "require RT::Ticket_Vendor"; if ($@ && $@ !~ qr{^Can't locate RT/Ticket_Vendor.pm}) { die $@; }; eval "require RT::Ticket_Local"; if ($@ && $@ !~ qr{^Can't locate RT/Ticket_Local.pm}) { die $@; }; nowhere is there a "package RT::Ticket_Local" statement. But Class::Sniff still finds RT::Ticket_Local. I'm happy to test fixes, but I'm not quite sure what they are. #!/usr/bin/env perl use strict; use warnings; use Class::Sniff; use RT; RT::LoadConfig; RT::Init; my @sniffs = Class::Sniff->new_from_namespace({ namespace => 'RT', universal => 1, }); my $graph = $sniffs[0]->combine_graphs( @sniffs[ 1 .. $#sniffs ] ); my $graphviz = $graph->as_graphviz(); open my $DOT, '|dot -Tpng -o graph.png' or die("Cannot open pipe to dot: $!" ); print $DOT $graphviz;
Hi Jesse, Thanks for the bug report. I can't install RT (I can't seem to install the latest DBD::mysql and I need to head to be soon). The problem with some 'non-existent' packages showing up appears to be a bug in Perl 5's handling of evaling the 'require $module'. #!/usr/bin/perl -l print $::{'Foo::'} || 'Not found'; eval "use Foo"; print $::{'Foo::'} || 'Not found'; eval "require Foo"; print $::{'Foo::'} || 'Not found'; That prints: Not found Not found *main::Foo:: So we're getting a symbol table entry for those. I've emailed P5P for clarification. I believe the ::SUPER entries are a side-effect of calling: sub method { my $self = shift; $self->SUPER::method(@_); # ... } I can work around that by skipping ::SUPER packages, though with the caveat that anyone who is foolish enough to have a SUPER embedded in a class name is asking for trouble and won't see it in the results :) Can you attach the PNG you created? That might help me understand this better. Cheers, Ovid
On Sun Feb 15 17:20:36 2009, Jesse wrote: Show quoted text
> I decided today to run Class::Sniff against a loaded copy of RT. > > I got a whole bunch of false positives for classes using the script > pasted below. > > > It found a bunch of ::SUPER packages as well as packages for every > filename required, which isn't quite right. > > > RT's classes all do this: > > eval "require RT::Ticket_Overlay"; > if ($@ && $@ !~ qr{^Can't locate RT/Ticket_Overlay.pm}) { > die $@; > };
In thinking about this a bit more, I think I'll be able to check for the existence of @ISA in the in the symbol table entry for %RT::Ticket_Overlay::. That might work, but I need to head to bed right now, so this will be later. Cheers, Ovid
On Sun Feb 15 17:20:36 2009, Jesse wrote: Show quoted text
> I decided today to run Class::Sniff against a loaded copy of RT. > > I got a whole bunch of false positives for classes using the script > pasted below. > > > It found a bunch of ::SUPER packages as well as packages for every > filename required, which isn't quite right. > > > RT's classes all do this: > > eval "require RT::Ticket_Overlay"; > if ($@ && $@ !~ qr{^Can't locate RT/Ticket_Overlay.pm}) { > die $@; > };
Hi Jesse, I've not gotten to the SUPER issue yet, but I've added experimental support for "fake" package detection. Basically, a fake package is any package which has a symbol table entry but no @ISA or no methods. It's a nasty hack, but I'm hoping it's a practical one. Can you give it a spin? The code is at: http://github.com/Ovid/class--sniff/tree/master Cheers, Ovid
On Sun Feb 15 17:20:36 2009, Jesse wrote: Show quoted text
> I decided today to run Class::Sniff against a loaded copy of RT. > > I got a whole bunch of false positives for classes using the script > pasted below. > > > It found a bunch of ::SUPER packages as well as packages for every > filename required, which isn't quite right. > > > RT's classes all do this: > > eval "require RT::Ticket_Overlay"; > if ($@ && $@ !~ qr{^Can't locate RT/Ticket_Overlay.pm}) { > die $@; > }; > > eval "require RT::Ticket_Vendor"; > if ($@ && $@ !~ qr{^Can't locate RT/Ticket_Vendor.pm}) { > die $@; > }; > > eval "require RT::Ticket_Local"; > if ($@ && $@ !~ qr{^Can't locate RT/Ticket_Local.pm}) { > die $@; > }; > > nowhere is there a "package RT::Ticket_Local" statement. But > Class::Sniff still finds RT::Ticket_Local. > > I'm happy to test fixes, but I'm not quite sure what they are. > > > #!/usr/bin/env perl > > use strict; > use warnings; > > use Class::Sniff; > use RT; > RT::LoadConfig; > RT::Init; > > my @sniffs = Class::Sniff->new_from_namespace({ > namespace => 'RT', > universal => 1, > }); > my $graph = $sniffs[0]->combine_graphs( @sniffs[ 1 .. $#sniffs
I believe you'll find this resolved in 0.08_02. You'll need to create the sniffs like this: : my @sniffs = Class::Sniff->new_from_namespace({ : namespace => 'RT', : universal => 1, : clean => 1, : }); The 'clean => 1' parameters tells Class::Sniff to generate a "clean" run and ignore pseudo-packages such as '::SUPER'. The new 'csniff' utility might also help: csniff --namespace RT:: lib/ --png > rt.png I still can't install RT, but I did get a partial load with csniff: http://i82.photobucket.com/albums/j275/publius_ovidius/Geek%20Stuff/rt.png Let me know if this works for you and I'll close the ticket. Cheers, Ovid
I haven't heard back on this ticket, so I'm assuming my last work fixed the issue. Please reopen the ticket if there's a problem. Cheers, Ovid