Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

CPAN modules for inspecting a Perl distribution?

by nysus (Parson)
on Oct 12, 2018 at 19:30 UTC ( [id://1223938]=perlquestion: print w/replies, xml ) Need Help??

nysus has asked for the wisdom of the Perl Monks concerning the following question:

I've downloaded a distribution with many modules and submodules. I'm wondering if there is a tool out there to help analyze the contents of the distribution's modules. It might, for example, give me a simple breakdown of all the different modules and what directory they are in as well as provide a listing of what functions/methods each module provided and other relevant information that might help me more quickly assess how the distribution is laid out. Does any such beast exist? Thanks.

$PM = "Perl Monk's";
$MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon Curate Priest";
$nysus = $PM . ' ' . $MCF;
Click here if you love Perl Monks

  • Comment on CPAN modules for inspecting a Perl distribution?

Replies are listed 'Best First'.
Re: CPAN modules for inspecting a Perl distribution?
by LanX (Saint) on Oct 12, 2018 at 20:31 UTC

        I'm the author of Devel::Examine::Subs, so if you have any issues or questions, feel free to ask away here, or email me using my CPAN page's address.

Re: CPAN modules for inspecting a Perl distribution?
by pryrt (Abbot) on Oct 12, 2018 at 20:25 UTC
    I think this will do approximately what you want (from a linuxy command line): find . -type f -iname '*.pm' -exec egrep -iH '^\s*sub' {} \;. Not 100% effective, but it would be a pretty good first-level approximation (assuming it's not an XS distro)

      Thanks. But I'm looking for something that would provide some kind of standard report of the distribution's contents. Something that could help point me at a glance to what the major modules were, which modules had the most functions/lines, etc. instead of just peeking inside random files for 10 min.

      $PM = "Perl Monk's";
      $MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon Curate Priest";
      $nysus = $PM . ' ' . $MCF;
      Click here if you love Perl Monks

Re: CPAN modules for inspecting a Perl distribution?
by Laurent_R (Canon) on Oct 13, 2018 at 22:00 UTC
    Hmm, not sure this is going to be useful for you.

    Very recently, I had to generate a dynamic tree of program calls. This is a proprietary language in which a program may call a subroutine (well, it's called a procedure in that language) or may call an external program written in the same language. What I needed was a full tree of all programs called by a certain subroutine of the main invoicing program, including programs called by the called programs.

    All those programs are not Perl programs, but I used Perl to parse the main invoicing program and to recursively parse programs called by the main program.

    Basically, my program first reads statically the program passed as a parameter and stores in a hash of arrays all the procedures of the program, with the name of the procedure as a key, and an anonymous array of the interesting code lines as a value. Once this is done, I'm doing a dynamic analysis of internal subs and and external programs called, so we have two levels of recursion here: one at the internal procedure call level (calling the procedure analysis sub) and one at the program level (calling the external program analysis sub).

    I'm basically calling my program with a program name and a specific procedure name as argument, then reading the content of the procedure, and calling recursively either the procedure analysis sub or the external analysis sub.

    I ended up with a 300+ line program generating a complete tree of function and external program calls. And that program generates a complete tree of procedure and external program calls for the input program and procedure.

    I can't publish my program, but I could provide a pseudo-code example if you wish.

    HTH.

Re: CPAN modules for inspecting a Perl distribution?
by Anonymous Monk on Oct 12, 2018 at 20:55 UTC
    Module::Metadata can find some metadata about modules in a similar manner to PAUSE, and package_versions_from_directory can be used to find what it provides in a similar way. Finding functions and methods on the other hand depends on what you want to look for: 1. functions that have been defined at runtime, which would be discovered by loading the module and searching its stash for CODE entries which you could use Package::Stash for, or 2. functions that are visibly defined in the file, found by statically parsing the code using something like PPI.
Re: CPAN modules for inspecting a Perl distribution?
by nysus (Parson) on Oct 13, 2018 at 19:08 UTC

    Here's a script I hacked together that gives me a basic report on a distribution. It provides a simple listing of each module, sorted by modules with most lines of code along with the number of subroutines in the module, followed by a summary report.

    #! /usr/bin/env perl use strict; use warnings; use Devel::Examine::Subs; use SourceCode::LineCounter::Perl; use Data::Dumper qw(Dumper); my $filename = '/path/to/module/directory'; my $des = Devel::Examine::Subs->new( file => $filename ); my $files = $des->all( ); my %subs = (); my $subroutine_total = 0; my $counter = SourceCode::LineCounter::Perl->new; $counter->accumulate(1); for my $file (sort keys %$files) { my $name = $file =~ s/$filename//r; my $old_count = $counter->code; $counter->count( $file ); my $lines_of_code = $counter->code - $old_count; my $number_of_subs = scalar @{$files->{$file}}; $subroutine_total += $number_of_subs; $subs{$name}{sub_names} = join("\n", @{$files->{$file}}); $subs{$name}{lines_of_code} = $lines_of_code; $subs{$name}{subroutines} = $number_of_subs; } print "File listing:\n================\n"; for my $file (sort { $subs{$b}{lines_of_code} <=> $subs{$a}{lines_of_c +ode} } sort keys %subs) { print $file . "\n"; print "Number of subroutines: " . $subs{$file}{subroutines}; print "\n"; print "Lines of code: " . $subs{$file}{lines_of_code}. "\n"; # print $subs{$file}{sub_names}; print "\n\n"; } print "\nTotal # files: " . scalar (keys %subs); print "\nTotal # subroutines: " . $subroutine_total; print "\nTotal # lines: " . $counter->total; print "\nTotal # lines of code: " . $counter->code;

    $PM = "Perl Monk's";
    $MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon Curate Priest";
    $nysus = $PM . ' ' . $MCF;
    Click here if you love Perl Monks

      I like your approach, but it gave me a lot of doubles and it took ages. Here's my stab at it

      Thanks for the motivation :)


      Enjoy, Have FUN! H.Merijn

        That's a sweet looking report. I'm going to steal that. Regarding slowness, I timed my script vs. yours:

        My script: real 0m12.515s user 0m11.919s sys 0m0.505s Your script: real 0m15.987s user 0m15.229s sys 0m0.660s

        This was done on the Rex v 1.6.0 module, which is pretty hefty. When you say "doubles," do you mean that some files were reported twice?

        $PM = "Perl Monk's";
        $MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon Curate Priest";
        $nysus = $PM . ' ' . $MCF;
        Click here if you love Perl Monks

        Curious to know what these lines are for:

        delete $SIG{__WARN__}; delete $SIG{__DIE__};

        $PM = "Perl Monk's";
        $MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon Curate Priest";
        $nysus = $PM . ' ' . $MCF;
        Click here if you love Perl Monks

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1223938]
Approved by Athanasius
Front-paged by haukex
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (4)
As of 2024-03-29 15:38 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found