How can I tell if used modules are pure perl? - perl

If I have Perl code which usees a lot of modules, is there a fast and easy way to find out if some of this modules are not pure Perl modules?

#DynaLoader::dl_modules contains the list of XS modules loaded.
perl -MSome::Module1 -MSome::Module2 -M... \
-MDynaLoader -E'say for sort #DynaLoader::dl_modules;'
Or if you wanted to write it as a script:
# Usage: script Some::Module1 Some::Module2 ...
use 5.010;
use DynaLoader qw( );
while (defined($_ = shift(#ARGV))) {
s{::}{/}g;
$_ .= ".pm";
require $_;
}
say for sort #DynaLoader::dl_modules;
Of course, nothing's stopping you from putting it in an existing script either.
use 5.010;
use DynaLoader qw( );
END { say for sort #DynaLoader::dl_modules; }

This looks like a job for what I call a "blowup sensor". You could just boobytrap the hooks, by putting this at the top of the first module:
BEGIN {
require Carp; #Does the stack stuff
# Fool Perl into thinking that these are already loaded.
#INC{ 'XSLoader.pm', 'DynaLoader.pm' } = ( 1, 1 );
# overload boobytrapped stubs
sub XSLoader::load { Carp::confess( 'NOT Pure Perl!' ); }
sub DynaLoader::bootstrap { Carp::confess( 'NOT Pure Perl!' ); }
}

If you have to try which modules in your Perl prog is not installed yet on your machine. You can do it like this:
use ExtUtils::Installed;
my $installed = ExtUtils::Installed->new();
my #miss;
foreach $module ($installed->modules()){
#miss = $installed->validate($module);
}
print join("\n", #miss);

Related

List all the subroutine names in perl program

I am using more modules in my perl program.
example:
use File::copy;
so likewise File module contains Basename, Path, stat and etc..
i want to list all the subroutine(function) names which is in File Package module.
In python has dir(modulename)
It list all the function that used in that module....
example:
#!/usr/bin/python
# Import built-in module math
import math
content = dir(math)
print content
Like python tell any code for in perl
If you want to look at the contents of a namespace in perl, you can use %modulename::.
For main that's either %main:: or %::.
E.g.:
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
sub fish {};
sub carrot {};
print "Stuff defined in Dumper:\n";
print Dumper \%Data::Dumper::;
print "Stuff defined:\n";
print Dumper \%::;
That covers a load of stuff though - including pragmas. But you can check for e.g. subroutines by simply testing it for being a code reference.
foreach my $thing ( keys %:: ) {
if ( defined &$thing ) {
print "sub $thing\n";
}
}
And with reference to the above sample, this prints:
sub Dumper
sub carrot
sub fish
So with reference to your original question:
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use File::Copy;
print "File::Copy has subs of:\n";
foreach my $thing ( keys %File::Copy:: ) {
if ( defined &$thing ) {
print "sub $thing\n";
}
}
Unfortunately you can't do the same thing with the whole File:: namespace, because there's a whole bunch of different modules that could be installed/loaded, but might not be.
You'd have to use e.g. CPAN to check that -
perl -MCPAN -e shell
i /^File::/
Which will list you around 717 modules that are grouped into the File:: tree.
You could look this up on CPAN. Or if you're just after the core modules, then some variant of using Module::CoreList might do what you want.
Something like this:
#!/usr/bin/perl
use strict;
use warnings;
use Module::CoreList;
foreach my $module ( Module::CoreList->find_modules(qr/^File::/) ) {
if ( eval { require $module =~ s|::|/|gr . ".pm" } ) {
print "Module: $module contains\n";
my $key_str = "\%$module\:\:";
my %stuff = eval $key_str;
foreach my $thing ( sort keys %stuff ) {
my $full_sub_path = "$module::$thing";
if ( eval {"defined &$full_sub_path"} ) {
if ( defined &$thing ) {
print "$thing <- $full_sub_path imported by default\n";
}
else {
print "\t$full_sub_path might be loadable\n";
}
}
}
}
else {
print "Module: $module couldn't be loaded\n";
}
}
It's a bit messy because you have to eval various bits of it to test if a module is in fact present and loadable at runtime. Oddly enough, File::Spec::VMS wasn't present on my Win32 system. Can't think why.... :).
Should note - just because you could import a sub from a module (that isn't exported by default) doesn't make it a good idea. By convention, any sub prefixed with an _ is not supposed to be used externally, etc.
My Devel::Examine::Subs module can do this, plus much more. Note that whether it's a method or function is irrelevant, it'll catch both. It works purely on subroutines as found with PPI.
use warnings;
use strict;
use Devel::Examine::Subs;
my $des = Devel::Examine::Subs->new;
my $subs = $des->module(module => 'File::Copy');
for (#$subs){
print "$_\n";
}
Output:
_move
move
syscopy
carp
mv
_eq
_catname
cp
copy
croak
Or a file/full directory. For all Perl files in a directory (recursively), just pass the dir to file param without a file at the end of the path:
my $des = Devel::Examine::Subs->new(file => '/path/to/file.pm');
my $subs = $des->all;
If you just want to print it use the Data::Dumper module and the following method, CGI used as an example:
use strict;
use warnings;
use CGI;
use Data::Dumper;
my $object = CGI->new();
{
no strict 'refs';
print "Instance METHOD IS " . Dumper( \%{ref ($object)."::" }) ;
}
Also note, it's File::Copy, not File::copy.

Can I define a subroutine that can be called like a built-in, everywhere?

Currently, during debugging, I tend to insert
carp Dumper \#foo, \%bar;
statements into my code, and regularly run into the problem that Carp and Data::Dumper are not imported in the current package. To avoid this problem, I defined the following sub in a central file that's always included:
sub main::bla {
use Carp; use Data::Dumper;
carp Dumper #_;
}
So now I can do
main::bla \#foo, \%bar;
everywhere, but the main:: annoys me. Is there something like a global package that's always imported, in any package, automatically (just like built-ins practically are imported everywhere)?
You could just call it
::bla( \#foo, \%bar );
In earlier days, I used to put util functions in a Ut package. And that was fine, but I noticed that my code wasn't really as modular as I thought of it. Each module that depended on Ut functions being there could only succeed if somebody took the trouble to build that namespace.
In the end, I considered use and require statements as simply documenting dependencies. There are more flexible ways to change what code is called by library modules, rather than changing their implementation in main.
For example, you could do this in a single use statement.
use Ut blah => sub {
use Carp;
use Data::Dumper;
carp Dumper #_;
};
And define the import:
sub import {
shift; # It's just me
my ( $name, $impl ) = #_;
if ( $name eq 'blah' && ref( $impl ) eq 'CODE' ) {
*blah = $_[1];
}
...
}
I still use the ut pattern, when I'm developing a lot of code at once. But I don't mind writing
ut:dump_var( $var )
as opposed to saving 3-4 characters (because sometimes I call it U::).
Now, it appears that you don't want to do this long term, and dumping out your variables is a useful thing for development. If you really want to do this, Smart::Comments does it like so:
### #foo
### %bar
All it takes is one use statement.
use Smart::Comments;
Maybe just better to make another Package with Export and needed things?
Like, MyTest.pm:
package MyTest;
use strict;
use Carp;
use Data::Dumper;
use base qw( Exporter );
our #EXPORT = qw(
debug
)
sub debug {
carp Dumper #_;
}
1;
So you can then just write in your script:
use MyTest;
debug {a => 'b', c => 'd' }
Fun fact: Some symbols are magic in that they always refer to their values in the main package. You can assign subroutines to these symbols that and they will be visible in any package.
{
package Foo;
# special names _ ARGV ARGVOUT ENV INC SIG STDERR STDIN STDOUT
sub ENV { print "In main::ENV ...\n" }
sub STDIN { print "In main::STDIN ...\n" }
sub _ { print "In main::_\n" }
# names that begin with ^ + upper case letter, or all digits
*{^T} = sub { scalar localtime };
*{^Gmtime} = sub { scalar gmtime };
*43 = sub { 42 };
use Data::Dumper;
*{^D} = \&Data::Dumper::Dumper;
}
{
package Bar;
&ENV;
STDIN();
print "The time is ", &^T, "\n";
print "In London it is ", &{^Gmtime}, "\n";
print "The answer is ", &43, "\n";
print "\#foo is ", &^D( \#foo );
}
None of this is recommended, unless you want to drive the next person who maintains your code insane.

How can I add a function based on the version of perl?

I'm sorry if this had been asked, but I found it hard to search for.
I use Perl 5.12 locally but some of our machines use Perl 5.8.8 and they won't be updated for the time being.
For auditing I use 'say' on platform 5.12.
I've written a simple function to implement say on 5.8.8 but I don't want to use it on 5.12.
Is there a way to only use my say function on the older version of Perl and use the 'builtin' version of say on 5.12?
You can use the $^V special variable to determine the version of the Perl interpreter:
BEGIN {
if ($^V ge v5.10.1) { # "say" first appeared in 5.10
require feature;
feature->import('say');
}
else {
*say = sub { print #_, "\n" }
}
}
This should work:
BEGIN{
no warnings 'once';
unless( eval{
require feature;
feature->import('say');
1
} ){
*say = sub{
print #_, "\n";
}
}
}

Importing in hierarchical Perl modules into the local namespace

Situation:
I have a module Foo::Quux::Bar, living in ./Bar.pm. I need to be able to unit test Bar. However, it is not advantageous due to circumstances beyond my control to set up a Foo/Quux directory structure.
So what I'd like to do is have some sort of unit_test_use routine that lets me grab Bar.pm and move/copy its functions into the local namespace(Note that Bar has a package Foo::Quux::Bar specifier) for my testing pleasure.
Grubbing around in the Perl documentation has not helped me.
Assuming your Bar.pm exports its functions in the standard way, you can load it with require and do the import manually:
BEGIN {
require 'Bar.pm'; # now the package Foo::Quux::Bar is set up
Foo::Quux::Bar->import;
};
But it's definitely worth looking into setting up the directory structure in the standard way, if you can.
The example below uses the following Bar.pm:
package Foo::Quux::Bar;
use warnings;
use strict;
sub one { 1 }
sub two { "zwei" }
sub three { 0x3333 }
1;
In your test-bar program, you can install a hook that will use the current directory's Bar.pm with
#! /usr/bin/perl
use warnings;
use strict;
use File::Basename;
BEGIN {
sub find_bar {
my(undef,$name) = #_;
if (basename($name) eq "Bar.pm") {
open my $fh, "<", "./Bar.pm" or die "$0: open ./Bar.pm: $!";
$fh;
}
}
unshift #INC => \&find_bar;
}
Hooks in #INC are documented in the perlfunc documentation for require.
Now to import all subs, ignoring any import in Foo::Quux::Bar,
# fake use Foo::Quux::Bar
BEGIN {
require Foo::Quux::Bar;
{
no strict 'refs';
while (my($name,$glob) = each %Foo::Quux::Bar::) {
if (*{ $glob }{CODE}) {
*{ __PACKAGE__ . "::" . $name } = *{ $glob }{CODE};
}
}
}
}
Back out in the test code where the strict pragma is enabled, we can
print map "$_\n", one, two, three;
and get the following output:
1
zwei
13107
Here's what I wrote:
sub import_module_into_main
{
my ($mod_name, $filename) = #_;
require $filename;
no strict;
foreach my $var ( keys( %{$mod_name . "::"}))
{
$main::{$var} = ${$mod_name. "::"}{$var};
}
}
Invoke with this: import_module_into_main("Foo::Quux::Bar", "Bar.pm").

How do I check whether a Perl module is installed? [duplicate]

This question already has answers here:
How can I require an optional Perl module if installed?
(8 answers)
Closed 9 years ago.
I'm writing a small Perl script that depends on some modules that might be available, so during the installation I would have to check if everythings there. I could just write use some::module and see if an error comes up, but a short message like "You need to install some::module" would be more helpful for endusers.
I also could just search every directory in #INC, but as it's Perl, there has to be an easier way.
perl -MSome::Module -e ';'
Whoops, misread the question. I thought you wanted to know in a one-off instance, not discovering it in a recoverable manner. I always use something like this:
sub try_load {
my $mod = shift;
eval("use $mod");
if ($#) {
#print "\$# = $#\n";
return(0);
} else {
return(1);
}
}
Which you use like this:
$module = 'Some::Module';
if (try_load($module)) {
print "loaded\n";
} else {
print "not loaded\n";
}
How about:
die "Some::Module missing!" unless(eval{require Some::Module});
I have a little script that lists all the Perl modules on my system;
#!/usr/bin/perl
use ExtUtils::Installed;
my $instmod = ExtUtils::Installed->new();
foreach my $module ($instmod->modules()) {
my $version = $instmod->version($module) || "???";
print "$module -- $version\n";
}
Inside that foreach loop you might want to do some thing like;
my $match;
if ($module =~ /$match/) {
print "Found $match: $module\n";
}
I use something like this:
BEGIN {
my $module_name = shift; # #ARGV
our $module_exp = $module_name;
eval "use $module_name;";
}
$module_exp =~ s{::}{/}g;
foreach my $key ( grep { m/^$module_exp\./ } keys %INC ) {
print "$key => $INC{$key}\n";
}
But I use this more in the form of a korn shell function:
function wherperl
{
perl -M$1 <<EX_DOC
my \$module = '$1';
\$module =~ s/::/\\//g;
for ( keys %INC ) {
next unless m/^\$module\./;
print \$_ . ' => ' . \$INC{\$_} . "\n";
}
EX_DOC
}
I like to use the cpan utility:
% cpan -D YAML
YAML
-------------------------------------------------------------------------
YAML Ain't Markup Language (tm)
A/AD/ADAMK/YAML-0.70.tar.gz
/usr/local/perls/perl-5.10.0/lib/site_perl/5.10.0/YAML.pm
Installed: 0.68
CPAN: 0.70 Not up to date
Ingy dot Net (INGY)
ingy#cpan.org
This can be a little slow since it has to connect to a CPAN mirror to fetch some of the data, but I also have a local CPAN mirror. :)