NAME

Sub::WrapPackages - add pre- and post-execution wrappers around all the subroutines in packages or around individual subs

SYNOPSIS

use Sub::WrapPackages
    packages => [qw(Foo Bar Baz::*)],   # wrap all subs in Foo and Bar
                                        #   and any Baz::* packages
    subs     => [qw(Barf::a, Barf::b)], # wrap these two subs as well
    wrap_inherited => 1,                # and wrap any methods
                                        #   inherited by Foo, Bar, or
                                        #   Baz::*
    pre      => sub {
        print "called $_[0] with params ".
          join(', ', @_[1..$#_])."\n";
    },
    post     => sub {
        print "$_[0] returned $_[1]\n";
    };

DESCRIPTION

This is mostly a wrapper around Damian Conway's Hook::LexWrap module. Please go and read the docs for that module now. The differences are:

no exporting

We don't export a wrap() function, instead preferring to do all the magic when you use this module. We just wrap named subroutines, no references. I didn't need that functionality so although it's probably available if you look at the source I haven't tested it. Patches welcome!

the subs and packages arrayrefs

In the synopsis above, you will see two named parameters, subs and packages. Any subroutine mentioned in subs will be wrapped. Any packages mentioned in packages will have all their subroutines wrapped, including any that they import.

Any subroutines mentioned in 'subs' must already exist - ie their modules must be loaded - at the time you try to wrap them. Otherwise the order in which modules are loaded doesn't matter due to Stunt Code.

Note, however, that if a module exports a subroutine at load-time using import then that sub will be wrapped in the exporting module but not in the importing module. This is because import() runs before we get a chance to fiddle with things. The code for deferred fiddlage isn't re-entrant. It's probably horribly fragile in all kinds of other ways too.

wrap_inherited

In conjunction with the packages arrayref, this wraps all calls to inherited methods made through those packages. If you call those methods directly in the superclass then they are not affected.

parameters passed to your subs

I threw Damian's ideas out of the window. Instead, your pre-wrapper will be passed the wrapped subroutine's name, and all the parameters to be passed to it. Who knows what will happen if you modify those params, I don't need that so haven't tested it. Patches welcome!

The post-wrapper will be passed the wrapped subroutine's name, and a single parameter for the return value(s) as in Damian's module. Figuring out the difference between returning an array and returning a reference to an array is left as an exercise for the interested reader.

BUGS

Wrapped subroutines may cause perl 5.6.1, and maybe other versions, to segfault when called in void context. I believe this is a bug in Hook::LexWrap.

I say "patches welcome" a lot.

AUTOLOAD and DESTROY are not treated as being special.

FEEDBACK

I like to know who's using my code. All comments, including constructive criticism, are welcome. Please email me.

SOURCE CODE REPOSITORY

http://www.cantrell.org.uk/cgit/cgit.cgi/perlmodules/

COPYRIGHT and LICENCE

Copyright 2003-2009 David Cantrell <david@cantrell.org.uk>

This software is free-as-in-speech software, and may be used, distributed, and modified under the terms of either the GNU General Public Licence version 2 or the Artistic Licence. It's up to you which one you use. The full text of the licences can be found in the files GPL2.txt and ARTISTIC.txt, respectively.

THANKS TO

Thanks also to Adam Trickett who thought this was a jolly good idea, Tom Hukins who prompted me to add support for inherited methods, and Ed Summers, whose code for figgering out what functions a package contains I borrowed out of Acme::Voodoo.

Thanks to Tom Hukins for sending in a test case for the situation when a class and a subclass are both defined in the same file.

Thanks to Dagfinn Ilmari Mannsaker for help with the craziness for fiddling with modules that haven't yet been loaded.

Thanks to Lee Johnson for reporting a bug caused by perl 5.10's constant.pm being Far Too Clever, and providing a patch and test.