How to use a module's @EXPORT array to document its exported objects?

H

Henry Law

I have a library of modules for a Perl application which has code
running on a Windows client and on a Linux server. Code writing and
documenting is done on the client. The number of subroutines has
expanded considerably, and I'm still developing, so I'm trying to
develop a simple utility which will document which objects are exported
from each module, and its version.

I've looked on CPAN without finding anything simple that does what I
want (but I'm not convinced I searched with the right strings, so
pointers would be welcomed), so I knocked up a simple application. It
_almost_ works and I would like it if someone can help me make the last
jump.

Here's the core of my code, using a standard module so you can run it if
you need to:

#! /usr/bin/perl
use strict; use warnings;
require File::Copy;
foreach my $exported_sub (@File::Copy::EXPORT_OK) {
print "$exported_sub\n";
}

For this particular module it works fine:
F:\>tryit.pl
cp
mv

But if I run it on my Windows _development_ _client_ against one of the
_server_ modules the "require" statement croaks because the server has a
different set of Perl modules installed. I get "Can't locate xxx in
@INC (@INC contains ..." messages.

So can I get access to the @EXPORT variables from a module without
causing the "require" statement to fail because it can't load dependent
modules? Or can I suppress the "Can't locate" messages safely just for
the tool? Or is there some other way of extracting the names of the
exported objects easily?

I realise that I could work around the problem either by running the
documentation tool on the server for the server modules, or by
installing the server modules on the client where I'm running the
documentation tool. The former is inconvenient; the latter ugly and
maybe not even possible.
 
A

anno4000

Henry Law said:
...expanded considerably, and I'm still developing, so I'm trying to
develop a simple utility which will document which objects are exported
from each module, and its version.
[...]

Here's the core of my code, using a standard module so you can run it if
you need to:

#! /usr/bin/perl
use strict; use warnings;
require File::Copy;
foreach my $exported_sub (@File::Copy::EXPORT_OK) {
print "$exported_sub\n";
}

For this particular module it works fine:
F:\>tryit.pl
cp
mv

But if I run it on my Windows _development_ _client_ against one of the
_server_ modules the "require" statement croaks because the server has a
different set of Perl modules installed. I get "Can't locate xxx in
@INC (@INC contains ..." messages.

So can I get access to the @EXPORT variables from a module without
causing the "require" statement to fail because it can't load dependent
modules? Or can I suppress the "Can't locate" messages safely just for
the tool?

The latter. perldoc -f eval.

Anno
 
H

Henry Law

The latter. perldoc -f eval.

OK, I see the basic principle: wrap up my "require" in an eval statement
so that the program doesn't crash. But the eval still fails with the
same error (now visible in $@), and doesn't create the variables, or
make them visible.

Snippet of the code
eval {require NFB::Utilities::Server};
warn $@ if $@;
print "Version of NFB::Utilities::Server is
$NFB::Utilities::Server::VERSION\n";

The variable $NFB::Utilities::Server::VERSION (which I can see is
defined in the module) is undefined, as is the @EXPORT_OK array etc.

I must be missing something ...
 
A

anno4000

Henry Law said:
OK, I see the basic principle: wrap up my "require" in an eval statement
so that the program doesn't crash. But the eval still fails with the
same error (now visible in $@), and doesn't create the variables, or
make them visible.

Snippet of the code
eval {require NFB::Utilities::Server};
warn $@ if $@;
print "Version of NFB::Utilities::Server is
$NFB::Utilities::Server::VERSION\n";

The variable $NFB::Utilities::Server::VERSION (which I can see is
defined in the module) is undefined, as is the @EXPORT_OK array etc.

I must be missing something ...

No, I was missing something. I missed the fact that the missing
module was called one level down, so to speak.

So, in your example above, the module NBF::Utilities::Server calls
some module Nowhere::Around and fails. Apparently you aren't free
to modify NBF::Utilities::Server, otherwise the obvious solution
would be to change it so it doesn't immediately die when
Nowhere::Around is missing.

Without changing NBF::Utilities::Server, you can try to fake that
Nowhere::Around is already loaded:

$INC{ 'Nowhere/Around.pm'} = 'fooled you';
require NBF::Utilities::Server;

That may work, but if NBF::Utilities::Server tries to use things
from Nowhere::Around during initialization you're out of luck again.

Anno
 
H

Henry Law

A. Sinan Unur said:
I do not understand why that is ugly or impossible in most cases. It
seems to me that the development environment ought to be as similar to
the deployment environment as possible.

Well, yes in a way, but the server bits of the code I'm writing run on a
Linux server which doesn't have lots of the end-user stuff installed
(Tk, for example), and the client end (which is where I also do the code
writing and documenting) is Windows. And some of the server modules
aren't available for the ActiveState Perl environment (well, I've not
been able to find them).
module info

in the search box.

Having had two wizard-level Perl people working on the case it's clear
to me that this idea isn't going to work so I'll stop trying and find
another way.

I'll do that CPAN search. Thanks, Anno and Sinan.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top