http://qs1969.pair.com?node_id=1157011

cLive ;-) has asked for the wisdom of the Perl Monks concerning the following question:

Never seen this one before...

I'm digging through an issue in a pile of spaghetti code. It is very old, very cluttered and full of "interesting surprises".

One issue I'm trying to debug now is that, by adding a use statement for a module to another, I get an error of:

Tried to use 'Module::Name'; Error: "method_name" is not exported by the Module::Name module

Looking through the use statements of modules used, I see some modules that appear to have nested use statements, eg:

package Module::A; use Module::B; package Module::B; use Module::A;

The methods that are failing are in @EXPORT_OK (this works as expected when using the module on its own.

I note that some modules use 'require Exporter' and others 'use base'.

Basically, apart from stripping the modules down to skeletons, is there a quicker way of getting to the root of this issue?

EDIT: Found the issue. Two modules export the same function name. It looks like this was the first time both modules had been included in the same app, and that the use statement was just copy/pasted even though imported method wasn't used. Removing Exporter from the lesser used module... Eurgh...

Replies are listed 'Best First'.
Re: Chasing up a module dependency issue
by Corion (Patriarch) on Mar 07, 2016 at 16:18 UTC

    I think this comes from a module that uses (resp. inherits from) Exporter and where Module::Name->import is called with method_name as argument. The simplest case would be:

    use Module::Name 'method_name';

    ... but that's likely too obvious and you've tried that already. A more contrived way would be something like:

    my $module = 'Module::Name'; require 'Module/Name.pm'; $module->import('method_name');

    Maybe (maybe) your code is picking up the wrong versions of Module::Name somewhere else in @INC? Dumping \%INC might tell you which version got picked up.

    The easiest "fix" in my opinion would be to preload all the relevant modules at the very top of your program:

    #!perl -w use strict; use Module::A; use Module::B; use Module::Name 'method_name'; ...

    That way, all the modules should be loaded in the correct order...

      use Module::Name 'method_name';

      That is what I think the issue is

      The code appears to work as a whole, under mod_perl, but it's failing the unit tests (that have finally been added to the code recently :)

      What I'm trying to work out is what exactly would cause the wiping out of the @EXPORT_OK. I thought that was scoped to the current package? Or is the error indicative of another issue?

      I really don't want to have to comb through the entire code base, if avoidable. On a hunch, I tried to switch @EXPORT_OK to @EXPORT, but that doesn't appear to have done anything = though mayne I need to look in the spiderweb of module includes and tweak all instances for it to work?

        What you describe shouldn't happen, for the reasons you describe as well. Maybe the unit tests do something weird, or maybe you use use_ok, which can fail (for example due to a syntax error) but the test script itself will continue with a half-compiled module. I fear that this is not really debuggable from afar and mostly tied to your specific source code situation at work...

        Maybe putting a callback into @INC allows you to debug what modules get loaded when, to narrow down the files after which problematic things happen:

        push @INC, sub { print "Loading @_\n"; return () };

        Maybe one of the modules contains a (second) package declaration that matches one found earlier and overwrites something in another package?