Thread: [Parseperl-discuss] PPI to get package/versions
Brought to you by:
adamkennedy
From: Todd R. <to...@cp...> - 2010-03-11 00:14:01
|
I want to use PPI to determine all packages and their $VERSION in a given pm file. I've determined how to get the list of packages in the file, but not the version. How can I do this? I've included what I have so far: use PPI; my $file = 'Uplevel.pm'; # Testing with Sub::Uplevel for POC my $doc = PPI::Document->new($file) or die; my $pkgs = $doc->find('PPI::Statement::Package'); foreach my $pkg (@$pkgs) { my $package_name = $pkg->namespace; # I don't know how to get the $VERSION from here. } |
From: Elliot S. <pe...@ga...> - 2010-03-11 03:35:33
|
On 3/10/10 6:13 PM, Todd Rinaldo wrote: > I want to use PPI to determine all packages and their $VERSION in a > given pm file. I've determined how to get the list of packages in the > file, but not the version. How can I do this? The only authoritative way of doing this is to load the module and check it at runtime. (Of course, determining which namespaces got twiddled in the process is difficult. You might want to look at http://search.cpan.org/dist/Module-Extract-VERSION/. If you want to do it yourself via PPI, I would probably set up a state machine that tracked what the current package is and when a $VERSION assignment is found, save it off in a stash of some sort. Alternatively, there's http://perlcritic.tigris.org/source/browse/perlcritic/trunk/distributions/PPIx-Utilities/lib/PPIx/Utilities/Node.pm?revision=3777&view=markup. You could use it to split your module up into namespaces and then look for $VERSION assignments in that. (I haven't released this yet due to wanting to move some code from Perl::Critic into the distribution first, but I'm still debating how to do it.) |
From: Todd R. <to...@cp...> - 2010-03-15 16:50:23
|
On Mar 10, 2010, at 9:07 PM, Elliot Shank wrote: > On 3/10/10 6:13 PM, Todd Rinaldo wrote: >> I want to use PPI to determine all packages and their $VERSION in a >> given pm file. I've determined how to get the list of packages in the >> file, but not the version. How can I do this? > > The only authoritative way of doing this is to load the module and check it at runtime. (Of course, determining which namespaces got twiddled in the process is difficult. > > You might want to look at http://search.cpan.org/dist/Module-Extract-VERSION/. > > If you want to do it yourself via PPI, I would probably set up a state machine that tracked what the current package is and when a $VERSION assignment is found, save it off in a stash of some sort. > > Alternatively, there's http://perlcritic.tigris.org/source/browse/perlcritic/trunk/distributions/PPIx-Utilities/lib/PPIx/Utilities/Node.pm?revision=3777&view=markup. You could use it to split your module up into namespaces and then look for $VERSION assignments in that. (I haven't released this yet due to wanting to move some code from Perl::Critic into the distribution first, but I'm still debating how to do it.) Elliot, thanks for your advice. It took me about 6 hours of struggling with PPI before I realized you were right and that PPI was a lost cause. The approach I've taken so far is to parse the output from $ver = `perl -e 'require $file; print $module::VERSION'`; What I've discovered is how many crazy things people try to do outside a sub in some perl modules. Also I often have to have the module and it's dependencies installed before my parsing will succeed. I played with removing use/require entries from the modules before I try requiring it but this often causes further breaks, especially when modules like Net::DNS (may it eternally burn in a dark place in hell for their evilness) try to alter their identity inside the BEGIN block. I've been forced to do a fallback to M::E::VERSION when I get weirdness in the output from my perl -e approach. I dislike this approach because it misses corner cases where multiple packages live inside a single .pm file. I'm sure you've seen many of these corner cases. How did you deal with them? It seems to me META.yml is desperately in need of a 'provides' section which could properly document the author's modules and versions as they intended. Has anyone heard any discussion of this idea ever? Thanks, Todd |
From: Elliot S. <pe...@ga...> - 2010-03-16 02:02:26
|
On 3/15/10 11:50 AM, Todd Rinaldo wrote: > I'm sure you've seen many of these corner cases. How did you deal with them? I haven't had to deal with $VERSION, so I haven't run into this. Everything I've written has been to process code that I can change, and not arbitrary stuff from the CPAN. > It seems to me META.yml is desperately in need of a 'provides' section > which could properly document the author's modules and versions as they > intended. Has anyone heard any discussion of this idea ever? There is one: e.g. http://cpansearch.perl.org/src/ELLIOTJS/PPIx-Utilities-1.000001/META.yml. Whether it is present or not depends upon what the author had installed at the time that the distribution tarball was created. If you use current Module::Build/ExtUtils::MakeMaker, you'll get a MYMETA.yml after running Build.PL/Makefile.PL which will reflect the actual things that will/would be installed. If you can't tell from the above URL, I've released the code that I discussed earlier: http://search.cpan.org/dist/PPIx-Utilities/. |