What is this module using?

Discussion in 'Perl Misc' started by Tim McDaniel, Apr 18, 2012.

  1. Tim McDaniel

    Tim McDaniel Guest

    Looking at the docs, it appears that Devel::Modlist reports on *all*
    the modules used in an entire script. Is there some way I can
    determine the modules used, directly or transitively, merely by the
    current module?

    --
    Tim McDaniel,
    Tim McDaniel, Apr 18, 2012
    #1
    1. Advertising

  2. Tim McDaniel

    Reini Urban Guest

    On 04/18/2012 06:32 PM, Ben Morrow wrote:
    >
    > Quoth Eli the Bearded<*@eli.users.panix.com>:
    >> In comp.lang.perl.misc, Ben Morrow<> wrote:
    >>> Quoth :
    >>>> Looking at the docs, it appears that Devel::Modlist reports on *all*
    >>>> the modules used in an entire script. Is there some way I can
    >>>> determine the modules used, directly or transitively, merely by the
    >>>> current module?
    >>>
    >>> perl -d:Modlist -mMy::Module -e1 ?

    >>
    >> That's not necessarily going to work. Consider:
    >>
    >> perl -d:Modlist -mCPAN -e1
    >>
    >> When I run that it doesn't mention Storable, LWP::*, or Time::*
    >> but all three were used by CPAN just seconds before when I ran
    >> "install Devel::Modlist":

    >
    > True. Modules loaded at runtime are inherently harder, since you have to
    > run the program (with all possible inputs) to see them.
    >
    > A CORE::GLOBAL::require hook which checks caller() looks like the best
    > answer, to me. You probably want to check (caller)[1] as well as
    > (caller)[0], or just check [1] while being careful to step back over
    > string evals until you find a real file.


    For an easier way, I'd rather print the %INC keys in an END block, as
    require stores the loaded module names there.

    perl -mCPAN -e'END{print(join qq(\n),keys %INC)}'

    This does not print the package names per se, but the relative paths of
    all loaded modules.
    s{/}{::}g; s{\.p[lm]$}{}; will do pretty printing of the names.
    --
    Reini
    Reini Urban, Apr 30, 2012
    #2
    1. Advertising

  3. Tim McDaniel

    Reini Urban Guest

    On 04/30/2012 08:58 AM, Ben Morrow wrote:
    >
    > Quoth Reini Urban<>:
    >> On 04/18/2012 06:32 PM, Ben Morrow wrote:
    >>>
    >>> A CORE::GLOBAL::require hook which checks caller() looks like the best
    >>> answer, to me. You probably want to check (caller)[1] as well as
    >>> (caller)[0], or just check [1] while being careful to step back over
    >>> string evals until you find a real file.

    >>
    >> For an easier way, I'd rather print the %INC keys in an END block, as
    >> require stores the loaded module names there.

    >
    > Read the OP. Tim (the OP) was asking for a way to find modules required
    > (recursively) only by one particular module, not modules required by the
    > whole program. Devel::Modlist is basically a cleaned-up version of
    > 'print %INC in an END block', and Tim was looking for an alternative.


    Oops, you are right, yes.
    --
    Reini
    Reini Urban, May 1, 2012
    #3
  4. Tim McDaniel

    Tim McDaniel Guest

    Back about two years ago (Date: Wed, 18 Apr 2012 21:44:31 +0000 (UTC);
    Message-ID: <jmncjv$ove$>), I wrote
    > Looking at the docs, it appears that Devel::Modlist reports on *all*
    > the modules used in an entire script. Is there some way I can
    > determine the modules used, directly or transitively, merely by the
    > current module?


    Ben Morrow suggested in <jmncjv$ove$>
    > perl -d:Modlist -mMy::Module -e1 ?


    I've gotten around to trying that. The problem is that apparently I
    had a different problem in mind than today's when I wrote

    > determine the modules used, directly or transitively


    With the method above, it's indeed transitive. (Also, if I leave out
    something from the INC path, it errors out at that "use" statement and
    doesn't check anything after. Our system does have a non-trivial
    include list.)

    For today's problem, I want only "directly", not "transitively".

    My group is adding calls subs in new modules and sometimes forgetting
    to add the "use" statements. Each of our modules should "use"
    everything it calls. I'd like a somewhat automated way to check
    statically for missing "use"s before we check in files. So I do not
    want transitive uses, and apparently we're doing a fair number of
    transitive "use"s.

    (I tried -d:Modlist as above with a library path that has only
    Devel::Modlist, but the problem above arises: since I'm leaving out
    many things from the INC path, it errors out at the first "use" of one
    of our modules and doesn't report anything after. And if I include our
    path, as aforesaid I get a lot of transitive uses that I don't want.)

    I'm thinking that I should just write a simple script to read a Perl
    file looking for
    - ^use foo::bar::baz
    save it as one of the uses (ignored any suffixed "nocritic", "no",
    or whatever)
    - foo::bar::baz->
    confirm that foo::bar::baz is in the hash of uses
    - foo::bar::baz::quux not followed by ->
    confirm that foo::bar::baz is in the hash of uses

    We very rarely do "require". We rarely do exports. So the above
    should work well enough 98% of the time. I'm OK with false positives
    in such odd cases, and false negatives (like calling an exported sub
    where you forgot to "use" the module directly) should be rare and you
    deserve the severe tire damage if you do it.

    Comments? Better ideas?

    --
    Tim McDaniel,
    Tim McDaniel, Mar 21, 2014
    #4
  5. (Tim McDaniel) writes:

    [...]

    > My group is adding calls subs in new modules and sometimes forgetting
    > to add the "use" statements. Each of our modules should "use"
    > everything it calls. I'd like a somewhat automated way to check
    > statically for missing "use"s before we check in files.


    This may not be applicable to your problem but what about maintaining a
    single list of use statements in a dedicated file?
    Rainer Weikusat, Mar 21, 2014
    #5
  6. Tim McDaniel

    Tim McDaniel Guest

    In article <>,
    Rainer Weikusat <> wrote:
    > (Tim McDaniel) writes:
    >
    >[...]
    >
    >> My group is adding calls subs in new modules and sometimes forgetting
    >> to add the "use" statements. Each of our modules should "use"
    >> everything it calls. I'd like a somewhat automated way to check
    >> statically for missing "use"s before we check in files.

    >
    >This may not be applicable to your problem but what about maintaining a
    >single list of use statements in a dedicated file?


    Reading and parsing the entire codebase when starting the program
    would take some time.

    --
    Tim McDaniel,
    Tim McDaniel, Mar 21, 2014
    #6
  7. (Tim McDaniel) writes:
    > Rainer Weikusat <> wrote:
    >> (Tim McDaniel) writes:
    >>
    >>[...]
    >>
    >>> My group is adding calls subs in new modules and sometimes forgetting
    >>> to add the "use" statements. Each of our modules should "use"
    >>> everything it calls. I'd like a somewhat automated way to check
    >>> statically for missing "use"s before we check in files.

    >>
    >>This may not be applicable to your problem but what about maintaining a
    >>single list of use statements in a dedicated file?

    >
    > Reading and parsing the entire codebase when starting the program
    > would take some time.


    Insofar use statements are being used to include modules, the entire
    codebase is 'read, parsed and compiled' prior to anything else
    happening:

    It is exactly equivalent to

    BEGIN { require Module; Module->import( LIST ); }
    Rainer Weikusat, Mar 21, 2014
    #7
  8. Tim McDaniel

    Tim McDaniel Guest

    In article <>,
    Rainer Weikusat <> wrote:
    > (Tim McDaniel) writes:
    >> Rainer Weikusat <> wrote:
    >>> (Tim McDaniel) writes:
    >>>
    >>>[...]
    >>>
    >>>> My group is adding calls subs in new modules and sometimes forgetting
    >>>> to add the "use" statements. Each of our modules should "use"
    >>>> everything it calls. I'd like a somewhat automated way to check
    >>>> statically for missing "use"s before we check in files.
    >>>
    >>>This may not be applicable to your problem but what about maintaining a
    >>>single list of use statements in a dedicated file?

    >>
    >> Reading and parsing the entire codebase when starting the program
    >> would take some time.

    >
    >Insofar use statements are being used to include modules, the entire
    >codebase is 'read, parsed and compiled' prior to anything else
    >happening:


    I've been trying to think about this in the general case. The only
    objection I can think of is that a program might not directly or
    indirectly reach the entire codebase. There might be several
    programs, and different (perhaps overlapping, perhaps disjoint) parts
    of the codebase might be used by different programs. I think that
    condition obtains at my ork-place.

    The other objections I considered I don't think would actually be
    problems:
    - conflicting exports: they would have been happening before the "use
    unification"
    - ordering problems with BEGIN blocks: that's such a disaster of a
    design that I don't think it needs to be considered.

    Thank you for the idea and for prompting me to think under what
    conditions it might or might not be useful.

    --
    Tim McDaniel,
    Tim McDaniel, Mar 21, 2014
    #8
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. eric_bellard
    Replies:
    1
    Views:
    5,084
    CarlosRivera
    Oct 7, 2004
  2. Maric Michaud
    Replies:
    0
    Views:
    7,181
    Maric Michaud
    Jun 24, 2006
  3. Floris Bruynooghe
    Replies:
    1
    Views:
    331
    Floris Bruynooghe
    Dec 24, 2008
  4. Nikita Petrov
    Replies:
    2
    Views:
    104
    Gary Wright
    Apr 6, 2008
  5. Replies:
    4
    Views:
    96
    John W. Krahn
    Feb 15, 2006
Loading...

Share This Page