--- /dev/null
+2008-03-16 - 3.8
+ Set INSTALLDIRS correctly in Makefile.PL
+ A couple of other fixups to play nicely in Core
+
+2008-03-12 - 3.7
+ Ignore editor cruft by default (Dave Rolsky and Matt Trout)
+ Doc patches (Matt Trout)
+ Prevent prototype mismatch warnings under Error.pm (Christopher H. Laco)
+ Don't pick up the ::SUPER pseudo stash in 5.8 (Alex Vandiver)
+ Make things work under VOS (Nicholas Clark and Paul Green)
+ Fix warning under Devel::Cover (Brian Cassidy)
+ Make tests run under Taint again
+ Get rid of Build.PL
+
+2007-04-07 - 3.6
+ Include blead perl patch from Craig Berry that gives better
+ Module::Pluggable::Object::search_paths portability as
+ prompted by VMS test failures.
+
+2007-01-29 - 3.5
+ Patch from Audrey Tang to prevent clobbering of $@
+
+2006-11-27 - 3.4
+ Make sure we don't fail taint checking when other
+ Module::Pluggable::* modules are installed.
+
+2006-11-24 - 3.3
+ Few more patches from Jos Boumans to get ready for CORE
+
+2006-11-15 - 3.2
+ Remove Class::Inspector dependency and inline code
+ Prepare for assimilation into CORE
+
+2006-07-11 - 3.1
+ Force Test::More version to be latest which stops it trampling on $_
+ Use Class::Inspector tests to check to see Package is loaded thus
+ preventing incompatability problems introduced by last patch.
+
+2006-06-07 - 3.01
+ Fix from Brian Cassidy in Devel::InnerPackage
+
+2006-06-06 - 3.0
+ Big refactor to split stuff up into more manageable pieces
+
+
+2006-04-05 - 2.98
+ Allow the ability to provide the file matching regex
+
+2006-02-06 - 2.97
+ Patch from Ricardo Signes to fix bug where File::Find
+ is not topic-safe in 5.6.1
+
+2005-09-01 - 2.96
+ Patch from Alex Vandiver to sort an edge case where the package
+ stash to contain "::"
+
+2005-07-30 - 2.95
+ Patch from Alex Vandiver to sort ::ISA::CACHE issues.
+ More patches from Christopher H. Laco to sort out only and except
+ and to fix calling search_path( add => ... ) before plugins()
+
+2005-07-09 - 2.9 More Tainting fixes
+ Patches from Christopher H. Laco and Joe McMahon to do more taint fixing
+ Suggestion from Christopher H. Laco to do a can check before instatiating
+
+2005-03-18 - 2.8 Minor fixes
+
+ Patch from Marcus Thiesen to fix so ISA cache magic
+ Patch from Anthony D. Urso to get M::P to work under taint
+
+
+2005-02-14 - 2.7 Allow redefinition of search_path
+
+ A patch from Barbie to allow you to do
+
+ $self->search_path( add => 'Some::Path' );
+ $self->search_path( new => 'Some::New::Path' );
+
+
+2005-02-02 - 2.6 Problems under tests
+
+ Richard Clamp diagnosed a problem as being due to the
+ fact that we exclude anything not from blib if there
+ was blib.pm is %INC. Of course if the module being
+ tested used another module that used Module::Pluggable
+ then the second module would fail.
+
+ Fixed it by checking to see if the caller had (^|/)blib/
+ in their filename.
+
+2004-12-20 - 2.5 'Inspiration' from Module::Pluggable::Fast
+
+ Noticed Sebastian Riedel's curious Module::Pluggable::Fast
+ which appears to break API backwards compatability in order
+ to inline an explicit call to 'new'. It has no tests.
+
+ A quick benchmark showed that it was about 10% faster
+ because of cruft that had accumulated over time. So
+ a few quick changes and now Module::Pluggable is only
+ 3% slower. Which is nice.
+
+ Also added a patch from Barbie to fix things under Windows.
+
+2004-12-15 - 2.4 Bug fix
+
+ There seemed to be some irregularities in how 5.8.1 worked
+ with the list_packages method. Fixed thanks to Schwern,
+ Michael Cummings and Jos Boumans.
+
+ Added some more documentation.
+
+ Added ability to specify except and only as regexes.
+
+2004-10-27 - 2.3 Niceties
+
+ Allow you to explicitly stop looking for inner packages.
+ Made it nicer to have single element search_dirs and search_paths.
+
+
+2004-10-08 - 2.2 Dieting
+
+ Thanks to suggestion and patches from Adam Kennedy
+ Module::Pluggable has dumped some weight and got rid of
+ the none Core dependecies of File::Find::Rule and
+ UNIVERSAL::require
+
+
+2004-08-25 - 2.1 Small buglette
+
+ Require inner packages when appropriate. This helps towards
+ making things work with PAR. Thanks to Brian Cassidy.
+
+ Never released.
+
+2004-08-19 - 2.0 Working inner packages
+
+ As long as you have require or instantiate set then we'll also find
+ inner packages. Why I didn't fix this way back in 1.3 I don't know.
+
+2004-07-18 - 1.9 Add 'package' option
+
+ This lets you install a method in another package's
+ namespace. Thanks to Simon Cozens.
+
+2004-07-08 - 1.8 Fix those two options
+
+ They worked before but now they're more robust.
+
+2004-07-07 - 1.7 Add support for limiting plugins
+
+ Added 'only' and ''except' options.
+
+2004-06-03 - 1.6 Add a traditional Makefile.PL
+
+ Even though I think Module::Build is much better.
+
+2004-05-25 - 1.5 Build.PL stupidity
+
+ Must add prereqs. Doh.
+
+2004-05-25 - 1.4 Multiple instances
+
+ Made it so you could use it twice in the same package.
+ Removed the inner package stuff inorder to fix it properly.
+
+2004-05-06 - 1.3 Ability to search in inner packages
+
+ Simon Cozens donated some code to allow us to search
+ inner packages.
+
+2004-05-06 - 1.2 Fix minor buglet
+
+ Apply a patch from Tom Insam to fix requiring without
+ instantiating and make require failures more verbose.
+
+2003-12-15 - 1.11 Update MANIFEST.
+
+ So that make dist works properly.
+
+2003-12-15 - 1.1 Make it work with multi level plugins
+
+ Apparently Foo::Plugin::Bar::Quux doesn't work.
+ Thanks to Darren Chamberlain for spotting this.
+
+2003-12-15 - 1.00 Add some more features
+
+ Added the ability to require without instantiating (for Tom Insam)
+ Prevented the names from being explicitly sorted (again, for Tom Insam)
+ Added in the ability to provide other search directorys.
+
+2003-11-27 - 0.95 Some Test::More issues
+
+ Explicitly number the tests which fixes some test more failures
+
+
+2003-10-21 - 0.9 We can rebuild you, we have the technology
+
+ Having used this in the wild some changes to make it better.
+
+
+2003-10-20 - 0.8 Fix.
+
+ Namespace issues.
+
+
+2003-10-17 - 0.7 And take your Build.PL with you
+
+ Pesky MANIFEST.SKIP
+
+
+2003-10-15 - 0.6 Initial release
+
+ Be free my pretty. EMANCIPIA!
--- /dev/null
+
+Same as practically every other Perl module ...
+
+ % perl Build.PL
+ % perl Build
+ % perl Build test
+ % sudo Build install
+
+N.B : If you don't already have Module::Build then running Makefile.PL
+will prompt you to install it.
+
+
--- /dev/null
+Changes
+INSTALL
+lib/Devel/InnerPackage.pm
+lib/Module/Pluggable.pm
+lib/Module/Pluggable/Object.pm
+Makefile.PL
+MANIFEST This list of files
+MANIFEST.SKIP
+META.yml
+README
+t/01use.t
+t/02alsoworks.t
+t/02works.t
+t/02works_taint.t
+t/03diffname.t
+t/04acmedir.t
+t/04acmedir_single.t
+t/04acmepath.t
+t/04acmepath_single.t
+t/05postpath.t
+t/06multipath.t
+t/07instantiate.t
+t/08nothing.t
+t/09require.t
+t/10innerpack.t
+t/10innerpack_inner.t
+t/10innerpack_noinner.t
+t/10innerpack_override.t
+t/10innerpack_super.t
+t/11usetwice.t
+t/12only.t
+t/12onlyarray.t
+t/12onlyregex.t
+t/13except.t
+t/13exceptarray.t
+t/13exceptregex.t
+t/14package.t
+t/15topicsafe.t
+t/16different_extension.t
+t/17devel_inner_package.t
+t/18skipped_package.t
+t/19can_ok_clobber.t
+t/20dodgy_files.t
+t/21editor_junk.t
+t/acme/Acme/MyTest/Plugin/Foo.pm
+t/lib/Acme/MyTest/Plugin/Foo.pm
+t/lib/EditorJunk/Plugin/Bar.pm
+t/lib/EditorJunk/Plugin/Bar.pm.swo
+t/lib/EditorJunk/Plugin/Bar.pm.swp
+t/lib/EditorJunk/Plugin/Bar.pm~
+t/lib/EditorJunk/Plugin/Foo.pm
+t/lib/ExtTest/Plugin/Bar.plugin
+t/lib/ExtTest/Plugin/Foo.plugin
+t/lib/ExtTest/Plugin/Quux/Foo.plugin
+t/lib/InnerTest/Plugin/Foo.pm
+t/lib/MyOtherTest/Plugin/Bar.pm
+t/lib/MyOtherTest/Plugin/Foo.pm
+t/lib/MyOtherTest/Plugin/Quux.pm
+t/lib/MyOtherTest/Plugin/Quux/Foo.pm
+t/lib/MyTest/Extend/Plugin/Bar.pm
+t/lib/MyTest/Plugin/Bar.pm
+t/lib/MyTest/Plugin/Foo.pm
+t/lib/MyTest/Plugin/Quux/Foo.pm
+t/lib/No/Middle.pm
+t/lib/OddTest/Plugin/Foo.pm
+t/lib/TA/C/A/I.pm
--- /dev/null
+Build$
+_build
+blib
+Makefile$
+\.tar\.gz$
+\.svn
+\.bak$
+^Module-Pluggable
+t/lib/OddTest/Plugin/-Dodgy.pm
+t/lib/EditorJunk/Plugin/#Bar.pm#
+t/lib/EditorJunk/Plugin/.#Bar.pm
+
--- /dev/null
+--- #YAML:1.0
+name: Module-Pluggable
+version: 3.8
+abstract: ~
+license: ~
+author: ~
+generated_by: ExtUtils::MakeMaker version 6.38
+distribution_type: module
+requires:
+ File::Basename: 0
+ File::Spec: 3.00
+ Test::More: 0.62
+meta-spec:
+ url: http://module-build.sourceforge.net/META-spec-v1.3.html
+ version: 1.3
--- /dev/null
+# Note: this file was auto-generated by Module::Build::Compat version 0.03
+use ExtUtils::MakeMaker;
+use FindBin;
+use File::Spec::Functions qw(catfile);
+
+# VOS and VMS can't handle dodgy plugin names
+# and VOS can't even unpack them so we create them on the
+# fly and only run the tests if they're present
+my %dodgy_files = (
+ catfile(qw(OddTest Plugin -Dodgy.pm)) => 'OddTest::Plugin::-Dodgy',
+ catfile(qw(EditorJunk Plugin #Bar.pm#)) => 'EditorJunk::Bar',
+ catfile(qw(EditorJunk Plugin .#Bar.pm)) => 'EditorJunk::Bar',
+);
+
+my $core = grep { $_ eq 'PERL_CORE=1' } @ARGV;
+my @path = $core ? (File::Spec->updir, File::Spec->updir, File::Spec->updir,
+ "t", "Module_Pluggable") : ($FindBin::Bin,"t");
+
+my @files;
+if ($^O ne 'VMS' && $^O ne 'VOS') {
+ foreach my $test (keys %dodgy_files) {
+ my ($file) = (catfile($FindBin::Bin,"t","lib", $test)=~/^(.*)$/);
+ if (open(my $fh, ">", $file)) {
+ my $name = $dodgy_files{$test};
+ print $fh "package $name;\nsub new {}\n1;";
+ close($fh);
+ push @files, $file;
+ }
+ }
+}
+
+
+WriteMakefile
+(
+ 'NAME' => 'Module::Pluggable',
+ 'VERSION_FROM' => 'lib/Module/Pluggable.pm',
+ 'PREREQ_PM' => {
+ 'File::Basename' => '0',
+ 'File::Spec' => '3.00',
+ 'Test::More' => '0.62'
+ },
+ 'EXE_FILES' => [],
+ 'INSTALLDIRS' => ($] >= 5.008009) ? "perl" : "site",
+ 'PL_FILES' => {},
+ 'realclean' => {FILES=> join ' ', @files},
+ # In the core pods will be built by installman.
+ $core ? (MAN3PODS => {}) : (),
+ )
+;
--- /dev/null
+NAME
+ Module::Pluggable - automatically give your module the ability to have
+ plugins
+
+SYNOPSIS
+ Simple use Module::Pluggable -
+
+ package MyClass;
+ use Module::Pluggable;
+
+ and then later ...
+
+ use MyClass;
+ my $mc = MyClass->new();
+ # returns the names of all plugins installed under MyClass::Plugin::*
+ my @plugins = $mc->plugins();
+
+EXAMPLE
+ Why would you want to do this? Say you have something that wants to pass
+ an object to a number of different plugins in turn. For example you may
+ want to extract meta-data from every email you get sent and do something
+ with it. Plugins make sense here because then you can keep adding new
+ meta data parsers and all the logic and docs for each one will be self
+ contained and new handlers are easy to add without changing the core
+ code. For that, you might do something like ...
+
+ package Email::Examiner;
+
+ use strict;
+ use Email::Simple;
+ use Module::Pluggable require => 1;
+
+ sub handle_email {
+ my $self = shift;
+ my $email = shift;
+
+ foreach my $plugin ($self->plugins) {
+ $plugin->examine($email);
+ }
+
+ return 1;
+ }
+
+ .. and all the plugins will get a chance in turn to look at it.
+
+ This can be trivally extended so that plugins could save the email
+ somewhere and then no other plugin should try and do that. Simply have
+ it so that the "examine" method returns 1 if it has saved the email
+ somewhere. You might also wnat to be paranoid and check to see if the
+ plugin has an "examine" method.
+
+ foreach my $plugin ($self->plugins) {
+ next unless $plugin->can('examine');
+ last if $plugin->examine($email);
+ }
+
+ And so on. The sky's the limit.
+
+DESCRIPTION
+ Provides a simple but, hopefully, extensible way of having 'plugins' for
+ your module. Obviously this isn't going to be the be all and end all of
+ solutions but it works for me.
+
+ Essentially all it does is export a method into your namespace that
+ looks through a search path for .pm files and turn those into class
+ names.
+
+ Optionally it instantiates those classes for you.
+
+ADVANCED USAGE
+ Alternatively, if you don't want to use 'plugins' as the method ...
+
+ package MyClass;
+ use Module::Pluggable sub_name => 'foo';
+
+ and then later ...
+
+ my @plugins = $mc->foo();
+
+ Or if you want to look in another namespace
+
+ package MyClass;
+ use Module::Pluggable search_path => ['Acme::MyClass::Plugin', 'MyClass::Extend'];
+
+ or directory
+
+ use Module::Pluggable search_dirs => ['mylibs/Foo'];
+
+ Or if you want to instantiate each plugin rather than just return the
+ name
+
+ package MyClass;
+ use Module::Pluggable instantiate => 'new';
+
+ and then
+
+ # whatever is passed to 'plugins' will be passed
+ # to 'new' for each plugin
+ my @plugins = $mc->plugins(@options);
+
+ alternatively you can just require the module without instantiating it
+
+ package MyClass;
+ use Module::Pluggable require => 1;
+
+ since requiring automatically searches inner packages, which may not be
+ desirable, you can turn this off
+
+ package MyClass;
+ use Module::Pluggable require => 1, inner => 0;
+
+ You can limit the plugins loaded using the except option, either as a
+ string, array ref or regex
+
+ package MyClass;
+ use Module::Pluggable except => 'MyClass::Plugin::Foo';
+
+ or
+
+ package MyClass;
+ use Module::Pluggable except => ['MyClass::Plugin::Foo', 'MyClass::Plugin::Bar'];
+
+ or
+
+ package MyClass;
+ use Module::Pluggable except => qr/^MyClass::Plugin::(Foo|Bar)$/;
+
+ and similarly for only which will only load plugins which match.
+
+ Remember you can use the module more than once
+
+ package MyClass;
+ use Module::Pluggable search_path => 'MyClass::Filters' sub_name => 'filters';
+ use Module::Pluggable search_path => 'MyClass::Plugins' sub_name => 'plugins';
+
+ and then later ...
+
+ my @filters = $self->filters;
+ my @plugins = $self->plugins;
+
+INNER PACKAGES
+ If you have, for example, a file lib/Something/Plugin/Foo.pm that
+ contains package definitions for both "Something::Plugin::Foo" and
+ "Something::Plugin::Bar" then as long as you either have either the
+ require or instantiate option set then we'll also find
+ "Something::Plugin::Bar". Nifty!
+
+OPTIONS
+ You can pass a hash of options when importing this module.
+
+ The options can be ...
+
+ sub_name
+ The name of the subroutine to create in your namespace.
+
+ By default this is 'plugins'
+
+ search_path
+ An array ref of namespaces to look in.
+
+ search_dirs
+ An array ref of directorys to look in before @INC.
+
+ instantiate
+ Call this method on the class. In general this will probably be 'new'
+ but it can be whatever you want. Whatever arguments are passed to
+ 'plugins' will be passed to the method.
+
+ The default is 'undef' i.e just return the class name.
+
+ require
+ Just require the class, don't instantiate (overrides 'instantiate');
+
+ inner
+ If set to 0 will not search inner packages. If set to 1 will override
+ "require".
+
+ only
+ Takes a string, array ref or regex describing the names of the only
+ plugins to return. Whilst this may seem perverse ... well, it is. But it
+ also makes sense. Trust me.
+
+ except
+ Similar to "only" it takes a description of plugins to exclude from
+ returning. This is slightly less perverse.
+
+ package
+ This is for use by extension modules which build on "Module::Pluggable":
+ passing a "package" option allows you to place the plugin method in a
+ different package other than your own.
+
+ file_regex
+ By default "Module::Pluggable" only looks for *.pm* files.
+
+ By supplying a new "file_regex" then you can change this behaviour e.g
+
+ file_regex => qr/\.plugin$/
+
+ include_editor_junk
+ By default "Module::Pluggable" ignores files that look like they were
+ left behind by editors. Currently this means files ending in ~ (~), the
+ extensions .swp or .swo, or files beginning with .#.
+
+ Setting "include_editor_junk" changes "Module::Pluggable" so it does not
+ ignore any files it finds.
+
+METHODs
+ search_path
+ The method "search_path" is exported into you namespace as well. You can
+ call that at any time to change or replace the search_path.
+
+ $self->search_path( add => "New::Path" ); # add
+ $self->search_path( new => "New::Path" ); # replace
+
+FUTURE PLANS
+ This does everything I need and I can't really think of any other
+ features I want to add. Famous last words of course
+
+ Recently tried fixed to find inner packages and to make it 'just work'
+ with PAR but there are still some issues.
+
+ However suggestions (and patches) are welcome.
+
+AUTHOR
+ Simon Wistow <simon@thegestalt.org>
+
+COPYING
+ Copyright, 2006 Simon Wistow
+
+ Distributed under the same terms as Perl itself.
+
+BUGS
+ None known.
+
+SEE ALSO
+ File::Spec, File::Find, File::Basename, Class::Factory::Util,
+ Module::Pluggable::Ordered
+
--- /dev/null
+libmodule-pluggable-perl (3.8-1maemo1) fremantle; urgency=low
+
+ * New Maemo packaging
+
+ -- Nito Martinez <Nito@Qindel.ES> Fri, 16 Apr 2010 06:45:02 +0100
+
+
+libmodule-pluggable-perl (3.8-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- gregor herrmann <gregor+debian@comodo.priv.at> Mon, 17 Mar 2008 20:50:42 +0100
+
+libmodule-pluggable-perl (3.7-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Roberto C. Sanchez <roberto@debian.org> Sun, 16 Mar 2008 02:30:40 -0400
+
+libmodule-pluggable-perl (3.6-2) unstable; urgency=low
+
+ [ Stephen Gran ]
+ * Lower debhelper compatibility level back to 5.
+
+ [ gregor herrmann ]
+ * debian/control: Added: Vcs-Svn field (source stanza); Vcs-Browser
+ field (source stanza); Homepage field (source stanza). Removed: XS-
+ Vcs-Svn fields.
+ * Set Standards-Version to 3.7.3 (no changes).
+ * Set debhelper compatibility level to 6.
+ * debian/watch: use dist-based URL.
+ * Remove debian/docs and don't install README (text version of POD
+ documentation) any more.
+ * debian/rules: replace with template from dh-make-perl to update it;
+ switch to using Build.PL instead of Makefile.PL (also closes: #467873).
+ * debian/copyright: update years of copyright, switch to new format.
+
+ -- gregor herrmann <gregor+debian@comodo.priv.at> Wed, 27 Feb 2008 19:11:31 +0100
+
+libmodule-pluggable-perl (3.6-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- gregor herrmann <gregor+debian@comodo.priv.at> Fri, 13 Apr 2007 21:13:42 +0200
+
+libmodule-pluggable-perl (3.4-1) unstable; urgency=low
+
+ * New upstream release
+
+ -- Krzysztof Krzyzaniak (eloy) <eloy@debian.org> Wed, 29 Nov 2006 10:10:20 +0100
+
+libmodule-pluggable-perl (3.01-1) unstable; urgency=low
+
+ * New upstream release
+ * debian/control:
+ - Uploaders: added me
+ - Standards-Version: increased to 3.7.2 without any changes
+
+ -- Krzysztof Krzyzaniak (eloy) <eloy@debian.org> Wed, 7 Jun 2006 15:09:35 +0200
+
+libmodule-pluggable-perl (2.97-1) unstable; urgency=low
+
+ * New upstream release (Closes: #329593)
+ * Adopted for the Debian Perl Group. (Closes: #358894)
+ * Upgrade to Standards-Version 3.6.2. No changes needed.
+ * Upgrade to debhelper compatibility level 5.
+ * Move debhelper from Build-Depends-Indep to Build-Depends, as
+ it's required by the 'clean' target.
+ * Don't ignore the result of 'make realclean'.
+ * Add dependency on ${misc:Depends}, as recommended by debhelper.
+ * Run 'make test' at build time.
+ * Updated debian/copyright, since the license is nowadays
+ 'under the same terms as Perl itself'.
+
+ -- Niko Tyni <ntyni@iki.fi> Fri, 31 Mar 2006 21:48:21 +0300
+
+libmodule-pluggable-perl (2.6-1) unstable; urgency=low
+
+ * New upstream release
+ * remove dependencies on MODULE::Universal and File::Find::Rule
+ * change to my shiny new @debian.org address
+
+ -- S. Zachariah Sprackett <zacs@debian.org> Thu, 17 Feb 2005 18:14:13 -0500
+
+libmodule-pluggable-perl (2.0-1) unstable; urgency=low
+
+ * New upstream release which adds proper support for inner packages
+ * Added watch file now that we're into version 2.0
+ - hopefully upstream won't break this by releasing a 2.11 which comes
+ before 2.2 again
+ * Minor text change in the package description
+
+ -- S. Zachariah Sprackett <zac@sprackett.com> Fri, 20 Aug 2004 13:46:17 -0400
+
+libmodule-pluggable-perl (1.9-1) unstable; urgency=low
+
+ * New upstream release.
+ * Allows install of a method in another package's namespace
+
+ -- S. Zachariah Sprackett <zac@sprackett.com> Tue, 10 Aug 2004 21:44:36 -0400
+
+libmodule-pluggable-perl (1.8-1) unstable; urgency=low
+
+ * Initial Release.
+
+ -- S. Zachariah Sprackett <zac@sprackett.com> Thu, 15 Jul 2004 20:43:25 -0400
--- /dev/null
+Source: libmodule-pluggable-perl
+Section: perl
+Priority: optional
+Maintainer: Debian Perl Group <pkg-perl-maintainers@lists.alioth.debian.org>
+Uploaders: Niko Tyni <ntyni@iki.fi>, Krzysztof Krzyzaniak (eloy) <eloy@debian.org>, gregor herrmann <gregor+debian@comodo.priv.at>
+Build-Depends: debhelper (>= 5)
+Build-Depends-Indep: perl (>= 5.6.0-16), perl-modules
+Standards-Version: 3.7.3
+Homepage: http://search.cpan.org/dist/Module-Pluggable/
+Vcs-Svn: svn://svn.debian.org/pkg-perl/trunk/libmodule-pluggable-perl/
+Vcs-Browser: http://svn.debian.org/wsvn/pkg-perl/trunk/libmodule-pluggable-perl/
+
+Package: libmodule-pluggable-perl
+Architecture: all
+Depends: ${perl:Depends}, ${misc:Depends}
+Description: Automatically provide your module the ability to accept plugins
+ Provides a simple yet extensible way of supporting 'plugins' for your
+ module. It exports a method into your namespace that looks through a search
+ path for .pm files and turns those into class names.
--- /dev/null
+Upstream Author: Simon Wistow <simon@thegestalt.org>
+Upstream source location: http://search.cpan.org/dist/Module-Pluggable/
+
+Files: *
+Copyright: Copyright, 2003-2006 Simon Wistow
+License: GPL-1+ | Artistic
+ Distributed under the same terms as Perl itself.
+
+Perl is distributed under your choice of the GNU General Public License or
+the Artistic License. On Debian GNU/Linux systems, the complete text of the
+GNU General Public License can be found in \`/usr/share/common-licenses/GPL\'
+and the Artistic Licence in \`/usr/share/common-licenses/Artistic\'.
+
+Files: debian/*
+Copyright:
+ Copyright 2004-2005, S. Zachariah Sprackett <zac@sprackett.com>
+ Copyright 2006-2008, Debian Perl Group
+License: GPL-1+ | Artistic
+ The packaging is licensed under the same terms as the software itself.
--- /dev/null
+#!/usr/bin/make -f
+# This debian/rules file is provided as a template for normal perl
+# packages. It was created by Marc Brockschmidt <marc@dch-faq.de> for
+# the Debian Perl Group (http://pkg-perl.alioth.debian.org/) but may
+# be used freely wherever it is useful.
+#
+# It was later modified by Jason Kohles <email@jasonkohles.com>
+# http://www.jasonkohles.com/ to support Module::Build installed modules
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+# If set to a true value then MakeMaker's prompt function will
+# always return the default without waiting for user input.
+export PERL_MM_USE_DEFAULT=1
+
+PACKAGE=$(shell dh_listpackages)
+
+ifndef PERL
+PERL = /usr/bin/perl
+endif
+
+TMP =$(CURDIR)/debian/$(PACKAGE)
+
+build: build-stamp
+build-stamp:
+ dh_testdir
+
+ $(PERL) Makefile.PL INSTALLDIRS=vendor
+ $(MAKE)
+ $(MAKE) test
+
+ touch $@
+
+clean:
+ dh_testdir
+ dh_testroot
+
+ dh_clean build-stamp install-stamp
+ [ ! -f Makefile ] || $(MAKE) realclean
+
+install: install-stamp
+install-stamp: build-stamp
+ dh_testdir
+ dh_testroot
+ dh_clean -k
+
+ $(MAKE) install DESTDIR=$(TMP) PREFIX=/usr
+ [ ! -d $(TMP)/usr/lib/perl5 ] || rmdir --ignore-fail-on-non-empty --parents --verbose $(TMP)/usr/lib/perl5
+
+ touch $@
+
+binary-arch:
+# We have nothing to do here for an architecture-independent package
+
+binary-indep: build install
+ dh_testdir
+ dh_testroot
+ dh_installdocs
+ dh_installchangelogs Changes
+ dh_perl
+ dh_compress
+ dh_fixperms
+ dh_installdeb
+ dh_gencontrol
+ dh_md5sums
+ dh_builddeb
+
+source diff:
+ @echo >&2 'source and diff are obsolete - use dpkg-source -b'; false
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary
--- /dev/null
+version=3
+http://search.cpan.org/dist/Module-Pluggable/ .*/Module-Pluggable-v?(\d[\d_.]+)\.(?:tar(?:\.gz|\.bz2)?|tgz|zip)
--- /dev/null
+package Devel::InnerPackage;
+
+use strict;
+use base qw(Exporter);
+use vars qw($VERSION @EXPORT_OK);
+
+$VERSION = '0.3';
+@EXPORT_OK = qw(list_packages);
+
+=pod
+
+=head1 NAME
+
+
+Devel::InnerPackage - find all the inner packages of a package
+
+=head1 SYNOPSIS
+
+ use Foo::Bar;
+ use Devel::InnerPackage qw(list_packages);
+
+ my @inner_packages = list_packages('Foo::Bar');
+
+
+=head1 DESCRIPTION
+
+
+Given a file like this
+
+
+ package Foo::Bar;
+
+ sub foo {}
+
+
+ package Foo::Bar::Quux;
+
+ sub quux {}
+
+ package Foo::Bar::Quirka;
+
+ sub quirka {}
+
+ 1;
+
+then
+
+ list_packages('Foo::Bar');
+
+will return
+
+ Foo::Bar::Quux
+ Foo::Bar::Quirka
+
+=head1 METHODS
+
+=head2 list_packages <package name>
+
+Return a list of all inner packages of that package.
+
+=cut
+
+sub list_packages {
+ my $pack = shift; $pack .= "::" unless $pack =~ m!::$!;
+
+ no strict 'refs';
+ my @packs;
+ my @stuff = grep !/^(main|)::$/, keys %{$pack};
+ for my $cand (grep /::$/, @stuff)
+ {
+ $cand =~ s!::$!!;
+ my @children = list_packages($pack.$cand);
+
+ push @packs, "$pack$cand" unless $cand =~ /^::/ ||
+ !__PACKAGE__->_loaded($pack.$cand); # or @children;
+ push @packs, @children;
+ }
+ return grep {$_ !~ /::(::ISA::CACHE|SUPER)/} @packs;
+}
+
+### XXX this is an inlining of the Class-Inspector->loaded()
+### method, but inlined to remove the dependency.
+sub _loaded {
+ my ($class, $name) = @_;
+
+ no strict 'refs';
+
+ # Handle by far the two most common cases
+ # This is very fast and handles 99% of cases.
+ return 1 if defined ${"${name}::VERSION"};
+ return 1 if defined @{"${name}::ISA"};
+
+ # Are there any symbol table entries other than other namespaces
+ foreach ( keys %{"${name}::"} ) {
+ next if substr($_, -2, 2) eq '::';
+ return 1 if defined &{"${name}::$_"};
+ }
+
+ # No functions, and it doesn't have a version, and isn't anything.
+ # As an absolute last resort, check for an entry in %INC
+ my $filename = join( '/', split /(?:'|::)/, $name ) . '.pm';
+ return 1 if defined $INC{$filename};
+
+ '';
+}
+
+
+=head1 AUTHOR
+
+Simon Wistow <simon@thegestalt.org>
+
+=head1 COPYING
+
+Copyright, 2005 Simon Wistow
+
+Distributed under the same terms as Perl itself.
+
+=head1 BUGS
+
+None known.
+
+=cut
+
+
+
+
+
+1;
--- /dev/null
+package Module::Pluggable;
+
+use strict;
+use vars qw($VERSION);
+use Module::Pluggable::Object;
+
+# ObQuote:
+# Bob Porter: Looks like you've been missing a lot of work lately.
+# Peter Gibbons: I wouldn't say I've been missing it, Bob!
+
+
+$VERSION = '3.8';
+
+sub import {
+ my $class = shift;
+ my %opts = @_;
+
+ my ($pkg, $file) = caller;
+ # the default name for the method is 'plugins'
+ my $sub = $opts{'sub_name'} || 'plugins';
+ # get our package
+ my ($package) = $opts{'package'} || $pkg;
+ $opts{filename} = $file;
+ $opts{package} = $package;
+
+
+ my $finder = Module::Pluggable::Object->new(%opts);
+ my $subroutine = sub { my $self = shift; return $finder->plugins(@_) };
+
+ my $searchsub = sub {
+ my $self = shift;
+ my ($action,@paths) = @_;
+
+ $finder->{'search_path'} = ["${package}::Plugin"] if ($action eq 'add' and not $finder->{'search_path'} );
+ push @{$finder->{'search_path'}}, @paths if ($action eq 'add');
+ $finder->{'search_path'} = \@paths if ($action eq 'new');
+ return $finder->{'search_path'};
+ };
+
+
+ my $onlysub = sub {
+ my ($self, $only) = @_;
+
+ if (defined $only) {
+ $finder->{'only'} = $only;
+ };
+
+ return $finder->{'only'};
+ };
+
+ my $exceptsub = sub {
+ my ($self, $except) = @_;
+
+ if (defined $except) {
+ $finder->{'except'} = $except;
+ };
+
+ return $finder->{'except'};
+ };
+
+
+ no strict 'refs';
+ no warnings qw(redefine prototype);
+
+ *{"$package\::$sub"} = $subroutine;
+ *{"$package\::search_path"} = $searchsub;
+ *{"$package\::only"} = $onlysub;
+ *{"$package\::except"} = $exceptsub;
+
+}
+
+1;
+
+=pod
+
+=head1 NAME
+
+Module::Pluggable - automatically give your module the ability to have plugins
+
+=head1 SYNOPSIS
+
+
+Simple use Module::Pluggable -
+
+ package MyClass;
+ use Module::Pluggable;
+
+
+and then later ...
+
+ use MyClass;
+ my $mc = MyClass->new();
+ # returns the names of all plugins installed under MyClass::Plugin::*
+ my @plugins = $mc->plugins();
+
+=head1 EXAMPLE
+
+Why would you want to do this? Say you have something that wants to pass an
+object to a number of different plugins in turn. For example you may
+want to extract meta-data from every email you get sent and do something
+with it. Plugins make sense here because then you can keep adding new
+meta data parsers and all the logic and docs for each one will be
+self contained and new handlers are easy to add without changing the
+core code. For that, you might do something like ...
+
+ package Email::Examiner;
+
+ use strict;
+ use Email::Simple;
+ use Module::Pluggable require => 1;
+
+ sub handle_email {
+ my $self = shift;
+ my $email = shift;
+
+ foreach my $plugin ($self->plugins) {
+ $plugin->examine($email);
+ }
+
+ return 1;
+ }
+
+
+
+.. and all the plugins will get a chance in turn to look at it.
+
+This can be trivally extended so that plugins could save the email
+somewhere and then no other plugin should try and do that.
+Simply have it so that the C<examine> method returns C<1> if
+it has saved the email somewhere. You might also wnat to be paranoid
+and check to see if the plugin has an C<examine> method.
+
+ foreach my $plugin ($self->plugins) {
+ next unless $plugin->can('examine');
+ last if $plugin->examine($email);
+ }
+
+
+And so on. The sky's the limit.
+
+
+=head1 DESCRIPTION
+
+Provides a simple but, hopefully, extensible way of having 'plugins' for
+your module. Obviously this isn't going to be the be all and end all of
+solutions but it works for me.
+
+Essentially all it does is export a method into your namespace that
+looks through a search path for .pm files and turn those into class names.
+
+Optionally it instantiates those classes for you.
+
+=head1 ADVANCED USAGE
+
+
+Alternatively, if you don't want to use 'plugins' as the method ...
+
+ package MyClass;
+ use Module::Pluggable sub_name => 'foo';
+
+
+and then later ...
+
+ my @plugins = $mc->foo();
+
+
+Or if you want to look in another namespace
+
+ package MyClass;
+ use Module::Pluggable search_path => ['Acme::MyClass::Plugin', 'MyClass::Extend'];
+
+or directory
+
+ use Module::Pluggable search_dirs => ['mylibs/Foo'];
+
+
+Or if you want to instantiate each plugin rather than just return the name
+
+ package MyClass;
+ use Module::Pluggable instantiate => 'new';
+
+and then
+
+ # whatever is passed to 'plugins' will be passed
+ # to 'new' for each plugin
+ my @plugins = $mc->plugins(@options);
+
+
+alternatively you can just require the module without instantiating it
+
+ package MyClass;
+ use Module::Pluggable require => 1;
+
+since requiring automatically searches inner packages, which may not be desirable, you can turn this off
+
+
+ package MyClass;
+ use Module::Pluggable require => 1, inner => 0;
+
+
+You can limit the plugins loaded using the except option, either as a string,
+array ref or regex
+
+ package MyClass;
+ use Module::Pluggable except => 'MyClass::Plugin::Foo';
+
+or
+
+ package MyClass;
+ use Module::Pluggable except => ['MyClass::Plugin::Foo', 'MyClass::Plugin::Bar'];
+
+or
+
+ package MyClass;
+ use Module::Pluggable except => qr/^MyClass::Plugin::(Foo|Bar)$/;
+
+
+and similarly for only which will only load plugins which match.
+
+Remember you can use the module more than once
+
+ package MyClass;
+ use Module::Pluggable search_path => 'MyClass::Filters' sub_name => 'filters';
+ use Module::Pluggable search_path => 'MyClass::Plugins' sub_name => 'plugins';
+
+and then later ...
+
+ my @filters = $self->filters;
+ my @plugins = $self->plugins;
+
+=head1 INNER PACKAGES
+
+If you have, for example, a file B<lib/Something/Plugin/Foo.pm> that
+contains package definitions for both C<Something::Plugin::Foo> and
+C<Something::Plugin::Bar> then as long as you either have either
+the B<require> or B<instantiate> option set then we'll also find
+C<Something::Plugin::Bar>. Nifty!
+
+=head1 OPTIONS
+
+You can pass a hash of options when importing this module.
+
+The options can be ...
+
+=head2 sub_name
+
+The name of the subroutine to create in your namespace.
+
+By default this is 'plugins'
+
+=head2 search_path
+
+An array ref of namespaces to look in.
+
+=head2 search_dirs
+
+An array ref of directorys to look in before @INC.
+
+=head2 instantiate
+
+Call this method on the class. In general this will probably be 'new'
+but it can be whatever you want. Whatever arguments are passed to 'plugins'
+will be passed to the method.
+
+The default is 'undef' i.e just return the class name.
+
+=head2 require
+
+Just require the class, don't instantiate (overrides 'instantiate');
+
+=head2 inner
+
+If set to 0 will B<not> search inner packages.
+If set to 1 will override C<require>.
+
+=head2 only
+
+Takes a string, array ref or regex describing the names of the only plugins to
+return. Whilst this may seem perverse ... well, it is. But it also
+makes sense. Trust me.
+
+=head2 except
+
+Similar to C<only> it takes a description of plugins to exclude
+from returning. This is slightly less perverse.
+
+=head2 package
+
+This is for use by extension modules which build on C<Module::Pluggable>:
+passing a C<package> option allows you to place the plugin method in a
+different package other than your own.
+
+=head2 file_regex
+
+By default C<Module::Pluggable> only looks for I<.pm> files.
+
+By supplying a new C<file_regex> then you can change this behaviour e.g
+
+ file_regex => qr/\.plugin$/
+
+=head2 include_editor_junk
+
+By default C<Module::Pluggable> ignores files that look like they were
+left behind by editors. Currently this means files ending in F<~> (~),
+the extensions F<.swp> or F<.swo>, or files beginning with F<.#>.
+
+Setting C<include_editor_junk> changes C<Module::Pluggable> so it does
+not ignore any files it finds.
+
+
+=head1 METHODs
+
+=head2 search_path
+
+The method C<search_path> is exported into you namespace as well.
+You can call that at any time to change or replace the
+search_path.
+
+ $self->search_path( add => "New::Path" ); # add
+ $self->search_path( new => "New::Path" ); # replace
+
+
+
+=head1 FUTURE PLANS
+
+This does everything I need and I can't really think of any other
+features I want to add. Famous last words of course
+
+Recently tried fixed to find inner packages and to make it
+'just work' with PAR but there are still some issues.
+
+
+However suggestions (and patches) are welcome.
+
+=head1 AUTHOR
+
+Simon Wistow <simon@thegestalt.org>
+
+=head1 COPYING
+
+Copyright, 2006 Simon Wistow
+
+Distributed under the same terms as Perl itself.
+
+=head1 BUGS
+
+None known.
+
+=head1 SEE ALSO
+
+L<File::Spec>, L<File::Find>, L<File::Basename>, L<Class::Factory::Util>, L<Module::Pluggable::Ordered>
+
+=cut
+
+
--- /dev/null
+package Module::Pluggable::Object;
+
+use strict;
+use File::Find ();
+use File::Basename;
+use File::Spec::Functions qw(splitdir catdir curdir catfile abs2rel);
+use Carp qw(croak carp);
+use Devel::InnerPackage;
+use Data::Dumper;
+use vars qw($VERSION);
+
+$VERSION = '3.6';
+
+
+sub new {
+ my $class = shift;
+ my %opts = @_;
+
+ return bless \%opts, $class;
+
+}
+
+### Eugggh, this code smells
+### This is what happens when you keep adding patches
+### *sigh*
+
+
+sub plugins {
+ my $self = shift;
+
+ # override 'require'
+ $self->{'require'} = 1 if $self->{'inner'};
+
+ my $filename = $self->{'filename'};
+ my $pkg = $self->{'package'};
+
+ # automatically turn a scalar search path or namespace into a arrayref
+ for (qw(search_path search_dirs)) {
+ $self->{$_} = [ $self->{$_} ] if exists $self->{$_} && !ref($self->{$_});
+ }
+
+
+
+
+ # default search path is '<Module>::<Name>::Plugin'
+ $self->{'search_path'} = ["${pkg}::Plugin"] unless $self->{'search_path'};
+
+
+ #my %opts = %$self;
+
+
+ # check to see if we're running under test
+ my @SEARCHDIR = exists $INC{"blib.pm"} && defined $filename && $filename =~ m!(^|/)blib/! ? grep {/blib/} @INC : @INC;
+
+ # add any search_dir params
+ unshift @SEARCHDIR, @{$self->{'search_dirs'}} if defined $self->{'search_dirs'};
+
+
+ my @plugins = $self->search_directories(@SEARCHDIR);
+
+ # push @plugins, map { print STDERR "$_\n"; $_->require } list_packages($_) for (@{$self->{'search_path'}});
+
+ # return blank unless we've found anything
+ return () unless @plugins;
+
+
+ # exceptions
+ my %only;
+ my %except;
+ my $only;
+ my $except;
+
+ if (defined $self->{'only'}) {
+ if (ref($self->{'only'}) eq 'ARRAY') {
+ %only = map { $_ => 1 } @{$self->{'only'}};
+ } elsif (ref($self->{'only'}) eq 'Regexp') {
+ $only = $self->{'only'}
+ } elsif (ref($self->{'only'}) eq '') {
+ $only{$self->{'only'}} = 1;
+ }
+ }
+
+
+ if (defined $self->{'except'}) {
+ if (ref($self->{'except'}) eq 'ARRAY') {
+ %except = map { $_ => 1 } @{$self->{'except'}};
+ } elsif (ref($self->{'except'}) eq 'Regexp') {
+ $except = $self->{'except'}
+ } elsif (ref($self->{'except'}) eq '') {
+ $except{$self->{'except'}} = 1;
+ }
+ }
+
+
+ # remove duplicates
+ # probably not necessary but hey ho
+ my %plugins;
+ for(@plugins) {
+ next if (keys %only && !$only{$_} );
+ next unless (!defined $only || m!$only! );
+
+ next if (keys %except && $except{$_} );
+ next if (defined $except && m!$except! );
+ $plugins{$_} = 1;
+ }
+
+ # are we instantiating or requring?
+ if (defined $self->{'instantiate'}) {
+ my $method = $self->{'instantiate'};
+ return map { ($_->can($method)) ? $_->$method(@_) : () } keys %plugins;
+ } else {
+ # no? just return the names
+ return keys %plugins;
+ }
+
+
+}
+
+sub search_directories {
+ my $self = shift;
+ my @SEARCHDIR = @_;
+
+ my @plugins;
+ # go through our @INC
+ foreach my $dir (@SEARCHDIR) {
+ push @plugins, $self->search_paths($dir);
+ }
+
+ return @plugins;
+}
+
+
+sub search_paths {
+ my $self = shift;
+ my $dir = shift;
+ my @plugins;
+
+ my $file_regex = $self->{'file_regex'} || qr/\.pm$/;
+
+
+ # and each directory in our search path
+ foreach my $searchpath (@{$self->{'search_path'}}) {
+ # create the search directory in a cross platform goodness way
+ my $sp = catdir($dir, (split /::/, $searchpath));
+
+ # if it doesn't exist or it's not a dir then skip it
+ next unless ( -e $sp && -d _ ); # Use the cached stat the second time
+
+ my @files = $self->find_files($sp);
+
+ # foreach one we've found
+ foreach my $file (@files) {
+ # untaint the file; accept .pm only
+ next unless ($file) = ($file =~ /(.*$file_regex)$/);
+ # parse the file to get the name
+ my ($name, $directory, $suffix) = fileparse($file, $file_regex);
+
+ next if (!$self->{include_editor_junk} && $self->_is_editor_junk($name));
+
+ $directory = abs2rel($directory, $sp);
+
+ # If we have a mixed-case package name, assume case has been preserved
+ # correctly. Otherwise, root through the file to locate the case-preserved
+ # version of the package name.
+ my @pkg_dirs = ();
+ if ( $name eq lc($name) || $name eq uc($name) ) {
+ my $pkg_file = catfile($sp, $directory, "$name$suffix");
+ open PKGFILE, "<$pkg_file" or die "search_paths: Can't open $pkg_file: $!";
+ my $in_pod = 0;
+ while ( my $line = <PKGFILE> ) {
+ $in_pod = 1 if $line =~ m/^=\w/;
+ $in_pod = 0 if $line =~ /^=cut/;
+ next if ($in_pod || $line =~ /^=cut/); # skip pod text
+ next if $line =~ /^\s*#/; # and comments
+ if ( $line =~ m/^\s*package\s+(.*::)?($name)\s*;/i ) {
+ @pkg_dirs = split /::/, $1;
+ $name = $2;
+ last;
+ }
+ }
+ close PKGFILE;
+ }
+
+ # then create the class name in a cross platform way
+ $directory =~ s/^[a-z]://i if($^O =~ /MSWin32|dos/); # remove volume
+ my @dirs = ();
+ if ($directory) {
+ ($directory) = ($directory =~ /(.*)/);
+ @dirs = grep(length($_), splitdir($directory))
+ unless $directory eq curdir();
+ for my $d (reverse @dirs) {
+ my $pkg_dir = pop @pkg_dirs;
+ last unless defined $pkg_dir;
+ $d =~ s/\Q$pkg_dir\E/$pkg_dir/i; # Correct case
+ }
+ } else {
+ $directory = "";
+ }
+ my $plugin = join '::', $searchpath, @dirs, $name;
+
+ next unless $plugin =~ m!(?:[a-z\d]+)[a-z\d]!i;
+
+ my $err = $self->handle_finding_plugin($plugin);
+ carp "Couldn't require $plugin : $err" if $err;
+
+ push @plugins, $plugin;
+ }
+
+ # now add stuff that may have been in package
+ # NOTE we should probably use all the stuff we've been given already
+ # but then we can't unload it :(
+ push @plugins, $self->handle_innerpackages($searchpath) unless (exists $self->{inner} && !$self->{inner});
+ } # foreach $searchpath
+
+ return @plugins;
+}
+
+sub _is_editor_junk {
+ my $self = shift;
+ my $name = shift;
+
+ # Emacs (and other Unix-y editors) leave temp files ending in a
+ # tilde as a backup.
+ return 1 if $name =~ /~$/;
+ # Emacs makes these files while a buffer is edited but not yet
+ # saved.
+ return 1 if $name =~ /^\.#/;
+ # Vim can leave these files behind if it crashes.
+ return 1 if $name =~ /\.sw[po]$/;
+
+ return 0;
+}
+
+sub handle_finding_plugin {
+ my $self = shift;
+ my $plugin = shift;
+
+ return unless (defined $self->{'instantiate'} || $self->{'require'});
+ $self->_require($plugin);
+}
+
+sub find_files {
+ my $self = shift;
+ my $search_path = shift;
+ my $file_regex = $self->{'file_regex'} || qr/\.pm$/;
+
+
+ # find all the .pm files in it
+ # this isn't perfect and won't find multiple plugins per file
+ #my $cwd = Cwd::getcwd;
+ my @files = ();
+ { # for the benefit of perl 5.6.1's Find, localize topic
+ local $_;
+ File::Find::find( { no_chdir => 1,
+ wanted => sub {
+ # Inlined from File::Find::Rule C< name => '*.pm' >
+ return unless $File::Find::name =~ /$file_regex/;
+ (my $path = $File::Find::name) =~ s#^\\./##;
+ push @files, $path;
+ }
+ }, $search_path );
+ }
+ #chdir $cwd;
+ return @files;
+
+}
+
+sub handle_innerpackages {
+ my $self = shift;
+ my $path = shift;
+ my @plugins;
+
+
+ foreach my $plugin (Devel::InnerPackage::list_packages($path)) {
+ my $err = $self->handle_finding_plugin($plugin);
+ #next if $err;
+ #next unless $INC{$plugin};
+ push @plugins, $plugin;
+ }
+ return @plugins;
+
+}
+
+
+sub _require {
+ my $self = shift;
+ my $pack = shift;
+ local $@;
+ eval "CORE::require $pack";
+ return $@;
+}
+
+
+1;
+
+=pod
+
+=head1 NAME
+
+Module::Pluggable::Object - automatically give your module the ability to have plugins
+
+=head1 SYNOPSIS
+
+
+Simple use Module::Pluggable -
+
+ package MyClass;
+ use Module::Pluggable::Object;
+
+ my $finder = Module::Pluggable::Object->new(%opts);
+ print "My plugins are: ".join(", ", $finder->plugins)."\n";
+
+=head1 DESCRIPTION
+
+Provides a simple but, hopefully, extensible way of having 'plugins' for
+your module. Obviously this isn't going to be the be all and end all of
+solutions but it works for me.
+
+Essentially all it does is export a method into your namespace that
+looks through a search path for .pm files and turn those into class names.
+
+Optionally it instantiates those classes for you.
+
+This object is wrapped by C<Module::Pluggable>. If you want to do something
+odd or add non-general special features you're probably best to wrap this
+and produce your own subclass.
+
+=head1 OPTIONS
+
+See the C<Module::Pluggable> docs.
+
+=head1 AUTHOR
+
+Simon Wistow <simon@thegestalt.org>
+
+=head1 COPYING
+
+Copyright, 2006 Simon Wistow
+
+Distributed under the same terms as Perl itself.
+
+=head1 BUGS
+
+None known.
+
+=head1 SEE ALSO
+
+L<Module::Pluggable>
+
+=cut
+
--- /dev/null
+#!perl -w
+
+use strict;
+use Test::More tests => 3;
+
+use_ok('Module::Pluggable');
+use_ok('Module::Pluggable::Object');
+use_ok('Devel::InnerPackage');
+
--- /dev/null
+#!perl -w
+
+use strict;
+use FindBin;
+use lib (($FindBin::Bin."/lib")=~/^(.*)$/);
+use Test::More tests => 5;
+
+my $foo;
+ok($foo = MyOtherTest->new());
+
+my @plugins;
+my @expected = qw(MyOtherTest::Plugin::Bar MyOtherTest::Plugin::Foo MyOtherTest::Plugin::Quux MyOtherTest::Plugin::Quux::Foo);
+ok(@plugins = sort $foo->plugins);
+
+
+
+is_deeply(\@plugins, \@expected, "is deeply");
+
+@plugins = ();
+
+ok(@plugins = sort MyOtherTest->plugins);
+
+
+
+
+is_deeply(\@plugins, \@expected, "is deeply class");
+
+
+
+package MyOtherTest;
+
+use strict;
+use Module::Pluggable;
+
+
+sub new {
+ my $class = shift;
+ return bless {}, $class;
+
+}
+1;
+
--- /dev/null
+#!perl -w
+
+use strict;
+use FindBin;
+use lib (($FindBin::Bin."/lib")=~/^(.*)$/);
+use Test::More tests => 5;
+
+my $foo;
+ok($foo = MyTest->new());
+
+my @plugins;
+my @expected = qw(MyTest::Plugin::Bar MyTest::Plugin::Foo MyTest::Plugin::Quux::Foo);
+ok(@plugins = sort $foo->plugins);
+
+
+
+is_deeply(\@plugins, \@expected, "is deeply");
+
+@plugins = ();
+
+ok(@plugins = sort MyTest->plugins);
+
+
+
+
+is_deeply(\@plugins, \@expected, "is deeply class");
+
+
+
+package MyTest;
+
+use strict;
+use Module::Pluggable;
+
+
+sub new {
+ my $class = shift;
+ return bless {}, $class;
+
+}
+1;
+
--- /dev/null
+#!perl -wT
+
+# NOTE: Module::Pluggable is going into core
+# and CORE tests can't modify @INC under taint
+# so this is a work around to make sure it
+# still works under taint checking.
+
+use strict;
+use Test::More tests => 5;
+
+my $foo;
+ok($foo = MyTest->new());
+
+my @plugins;
+my @expected = qw(Module::Pluggable::Object);
+ok(@plugins = sort $foo->plugins);
+
+
+ok(grep {/Module::Pluggable::Object/} @plugins, "Contains Module::Pluggable::Object");
+
+@plugins = ();
+
+ok(@plugins = sort MyTest->plugins);
+
+ok(grep {/Module::Pluggable::Object/} @plugins, "Contains Module::Pluggable::Object under class method");
+
+
+
+package MyTest;
+
+use strict;
+use Module::Pluggable search_path => 'Module::Pluggable';
+
+
+sub new {
+ my $class = shift;
+ return bless {}, $class;
+
+}
+1;
+
--- /dev/null
+#!perl -w
+
+use strict;
+use FindBin;
+use lib (($FindBin::Bin."/lib")=~/^(.*)$/);
+use Test::More tests => 3;
+
+my $foo;
+ok($foo = MyTest->new());
+
+my @plugins;
+my @expected = qw(MyTest::Plugin::Bar MyTest::Plugin::Foo MyTest::Plugin::Quux::Foo);
+ok(@plugins = sort $foo->foo);
+is_deeply(\@plugins, \@expected);
+
+
+
+package MyTest;
+
+use strict;
+use Module::Pluggable ( sub_name => 'foo');
+
+
+sub new {
+ my $class = shift;
+ return bless {}, $class;
+
+}
+1;
+
--- /dev/null
+#!perl -w
+
+use strict;
+use FindBin;
+use lib (($FindBin::Bin."/lib")=~/^(.*)$/);
+use Test::More tests => 3;
+
+
+my $foo;
+ok($foo = MyTest->new());
+
+my @plugins;
+my @expected = qw(Acme::MyTest::Plugin::Foo);
+ok(@plugins = sort $foo->plugins);
+is_deeply(\@plugins, \@expected);
+
+
+package MyTest;
+use File::Spec::Functions qw(catdir);
+use strict;
+use Module::Pluggable search_path => ["Acme::MyTest::Plugin"], search_dirs => [ "t/acme" ];
+
+
+sub new {
+ my $class = shift;
+ return bless {}, $class;
+
+}
+1;
+
--- /dev/null
+#!perl -w
+
+use strict;
+use FindBin;
+use lib (($FindBin::Bin."/lib")=~/^(.*)$/);
+use Test::More tests => 3;
+
+
+my $foo;
+ok($foo = MyTest->new());
+
+my @plugins;
+my @expected = qw(Acme::MyTest::Plugin::Foo);
+ok(@plugins = sort $foo->plugins);
+is_deeply(\@plugins, \@expected);
+
+
+package MyTest;
+use File::Spec::Functions qw(catdir);
+use strict;
+use Module::Pluggable search_path => "Acme::MyTest::Plugin", search_dirs => "t/acme" ;
+
+
+sub new {
+ my $class = shift;
+ return bless {}, $class;
+
+}
+1;
+
--- /dev/null
+#!perl -w
+
+use strict;
+use FindBin;
+use lib (($FindBin::Bin."/lib")=~/^(.*)$/);
+use Test::More tests => 3;
+
+
+my $foo;
+ok($foo = MyTest->new());
+
+my @plugins;
+my @expected = qw(Acme::MyTest::Plugin::Foo);
+ok(@plugins = sort $foo->plugins);
+is_deeply(\@plugins, \@expected);
+
+
+package MyTest;
+use File::Spec::Functions qw(catdir);
+use strict;
+use Module::Pluggable (search_path => ["Acme::MyTest::Plugin"]);
+
+
+sub new {
+ my $class = shift;
+ return bless {}, $class;
+
+}
+1;
+
--- /dev/null
+#!perl -w
+
+use strict;
+use FindBin;
+use lib (($FindBin::Bin."/lib")=~/^(.*)$/);
+use Test::More tests => 3;
+
+
+my $foo;
+ok($foo = MyTest->new());
+
+my @plugins;
+my @expected = qw(Acme::MyTest::Plugin::Foo);
+ok(@plugins = sort $foo->plugins);
+is_deeply(\@plugins, \@expected);
+
+
+package MyTest;
+use File::Spec::Functions qw(catdir);
+use strict;
+use Module::Pluggable search_path => "Acme::MyTest::Plugin";
+
+
+sub new {
+ my $class = shift;
+ return bless {}, $class;
+
+}
+1;
+
--- /dev/null
+#!perl -w
+
+use strict;
+use FindBin;
+use lib (($FindBin::Bin."/lib")=~/^(.*)$/);
+use Test::More tests => 3;
+
+
+my $foo;
+ok($foo = MyTest->new());
+
+my @plugins;
+my @expected = qw(MyTest::Extend::Plugin::Bar);
+ok(@plugins = sort $foo->plugins);
+is_deeply(\@plugins, \@expected);
+
+
+
+package MyTest;
+use File::Spec::Functions qw(catdir);
+use strict;
+use Module::Pluggable (search_path => ["MyTest::Extend::Plugin"]);
+
+
+sub new {
+ my $class = shift;
+ return bless {}, $class;
+
+}
+1;
+
--- /dev/null
+#!perl -w
+
+use strict;
+use FindBin;
+use lib (($FindBin::Bin."/lib")=~/^(.*)$/);
+use Test::More tests => 3;
+
+
+my $foo;
+ok($foo = MyTest->new());
+
+my @plugins;
+my @expected = qw(Acme::MyTest::Plugin::Foo MyTest::Extend::Plugin::Bar);
+ok(@plugins = sort $foo->plugins);
+
+is_deeply(\@plugins, \@expected);
+
+
+
+package MyTest;
+use File::Spec::Functions qw(catdir);
+use strict;
+use File::Spec::Functions qw(catdir);
+use Module::Pluggable (search_path => ["MyTest::Extend::Plugin", "Acme::MyTest::Plugin"]);
+
+
+sub new {
+ my $class = shift;
+ return bless {}, $class;
+
+}
+1;
+
--- /dev/null
+#!perl -w
+
+use strict;
+use FindBin;
+use lib (($FindBin::Bin."/lib")=~/^(.*)$/);
+use Test::More tests => 6;
+
+my $foo;
+ok($foo = MyTest->new());
+
+
+
+my @plugins;
+ok(@plugins = sort $foo->booga(nork => 'fark'));
+is(ref $plugins[0],'MyTest::Extend::Plugin::Bar');
+is($plugins[0]->nork,'fark');
+
+
+@plugins = ();
+eval { @plugins = $foo->wooga( nork => 'fark') };
+is($@, '');
+is(scalar(@plugins),0);
+
+
+package MyTest;
+use File::Spec::Functions qw(catdir);
+use strict;
+use FindBin;
+use lib (($FindBin::Bin."/lib")=~/^(.*)$/);
+use Module::Pluggable (search_path => ["MyTest::Extend::Plugin"], sub_name => 'booga', instantiate => 'new');
+use Module::Pluggable (search_path => ["MyTest::Extend::Plugin"], sub_name => 'wooga', instantiate => 'nosomuchmethod');
+
+
+sub new {
+ my $class = shift;
+ return bless {}, $class;
+
+}
+1;
+
--- /dev/null
+#!perl -w
+
+use strict;
+use FindBin;
+use lib (($FindBin::Bin."/lib")=~/^(.*)$/);
+use Test::More tests => 2;
+
+
+my $foo;
+ok($foo = MyTest->new());
+
+my @expected = ();
+my @plugins = sort $foo->plugins;
+is_deeply(\@plugins, \@expected);
+
+
+package MyTest;
+use File::Spec::Functions qw(catdir);
+use strict;
+use Module::Pluggable (search_path => ["No::Such::Modules"]);
+use base qw(Module::Pluggable);
+
+
+sub new {
+ my $class = shift;
+ return bless {}, $class;
+
+}
+1;
+
--- /dev/null
+#!perl -w
+
+use strict;
+use FindBin;
+use lib (($FindBin::Bin."/lib")=~/^(.*)$/);
+use Test::More tests => 2;
+
+my $t = MyTest->new();
+
+
+ok($t->plugins());
+
+ok(keys %{MyTest::Plugin::Foo::});
+
+
+package MyTest;
+use File::Spec::Functions qw(catdir);
+use strict;
+use Module::Pluggable (require => 1);
+use base qw(Module::Pluggable);
+
+
+sub new {
+ my $class = shift;
+ return bless {}, $class;
+
+}
+1;
+
--- /dev/null
+#!perl -w
+
+use strict;
+use FindBin;
+use lib (($FindBin::Bin."/lib")=~/^(.*)$/);
+use Test::More tests => 4;
+
+
+
+my $t = InnerTest->new();
+
+my %plugins = map { $_ => 1 } $t->plugins;
+
+ok(keys %plugins, "Got some plugins");
+ok($plugins{'InnerTest::Plugin::Foo'}, "Got Foo");
+ok($plugins{'InnerTest::Plugin::Bar'}, "Got Bar - the inner package");
+ok($plugins{'InnerTest::Plugin::Quux'}, "Got Quux - the other inner package");
+
+
+
+package InnerTest;
+use strict;
+use Module::Pluggable require => 1;
+use base qw(Module::Pluggable);
+
+
+sub new {
+ my $class = shift;
+ return bless {}, $class;
+
+}
+
+
+1;
+
--- /dev/null
+#!perl -w
+
+use strict;
+use FindBin;
+use lib (($FindBin::Bin."/lib")=~/^(.*)$/);
+use Test::More tests => 3;
+
+
+
+my $t = InnerTest->new();
+
+my %plugins = map { $_ => 1 } $t->plugins;
+
+ok(keys %plugins, "Got some plugins");
+ok($plugins{'InnerTest::Plugin::Foo'}, "Got Foo");
+ok($plugins{'InnerTest::Plugin::Bar'}, "Got Bar - the inner package");
+
+
+
+package InnerTest;
+use strict;
+use Module::Pluggable inner => 1;
+use base qw(Module::Pluggable);
+
+
+sub new {
+ my $class = shift;
+ return bless {}, $class;
+
+}
+
+
+1;
+
--- /dev/null
+#!perl -w
+
+use strict;
+use FindBin;
+use lib (($FindBin::Bin."/lib")=~/^(.*)$/);
+use Test::More tests => 3;
+
+
+
+my $t = InnerTest->new();
+
+my %plugins = map { $_ => 1 } $t->plugins;
+
+ok(keys %plugins, "Got some plugins");
+ok($plugins{'InnerTest::Plugin::Foo'}, "Got Foo");
+ok(!$plugins{'InnerTest::Plugin::Bar'}, "Didn't get Bar - the inner package");
+
+
+
+package InnerTest;
+use strict;
+use Module::Pluggable require => 1, inner => 0;
+use base qw(Module::Pluggable);
+
+
+sub new {
+ my $class = shift;
+ return bless {}, $class;
+
+}
+
+
+1;
+
--- /dev/null
+#!perl -w
+
+use strict;
+use FindBin;
+use lib (($FindBin::Bin."/lib")=~/^(.*)$/);
+use Test::More tests => 3;
+
+
+
+my $t = InnerTest->new();
+
+my %plugins = map { $_ => 1 } $t->plugins;
+
+ok(keys %plugins, "Got some plugins");
+ok($plugins{'InnerTest::Plugin::Foo'}, "Got Foo");
+ok($plugins{'InnerTest::Plugin::Bar'}, "Got Bar - the inner package");
+
+
+
+package InnerTest;
+use strict;
+use Module::Pluggable require => 0, inner => 1;
+use base qw(Module::Pluggable);
+
+
+sub new {
+ my $class = shift;
+ return bless {}, $class;
+
+}
+
+
+1;
+
--- /dev/null
+#!perl -wT
+
+use Test::More tests => 3;
+use strict;
+use_ok('Devel::InnerPackage');
+Bar->whee;
+is_deeply([Devel::InnerPackage::list_packages("Bar")],[], "Don't pick up ::SUPER pseudo stash");
+is_deeply([Devel::InnerPackage::list_packages("Foo")],['Foo::Bar'], "Still pick up other inner package");
+
+package Foo;
+
+sub whee {
+ 1;
+}
+
+package Foo::Bar;
+
+sub whee {}
+
+package Bar;
+use base 'Foo';
+
+sub whee {
+ shift->SUPER::whee;
+ 2;
+}
+
+
+1;
--- /dev/null
+#!perl -w
+
+use strict;
+use FindBin;
+use lib (($FindBin::Bin."/lib")=~/^(.*)$/);
+use Test::More tests => 3;
+
+my $foo;
+ok($foo = MyTest->new());
+
+my @plugins;
+my @expected = qw(MyTest::Extend::Plugin::Bar MyTest::Plugin::Bar MyTest::Plugin::Foo MyTest::Plugin::Quux::Foo);
+
+push @plugins, $foo->plugins;
+push @plugins, $foo->foo;
+
+@plugins = sort @plugins;
+is_deeply(\@plugins, \@expected);
+
+@plugins = ();
+
+push @plugins, MyTest->plugins;
+push @plugins, MyTest->foo;
+@plugins = sort @plugins;
+is_deeply(\@plugins, \@expected);
+
+
+
+package MyTest;
+
+use strict;
+use Module::Pluggable;
+use Module::Pluggable ( search_path => [ "MyTest::Extend::Plugin" ] , sub_name => 'foo' );
+
+
+sub new {
+ my $class = shift;
+ return bless {}, $class;
+
+}
+
+
+1;
+
--- /dev/null
+#!perl -w
+
+use strict;
+use FindBin;
+use lib (($FindBin::Bin."/lib")=~/^(.*)$/);
+use Test::More tests => 10;
+
+{
+ my $foo;
+ ok($foo = MyTest->new());
+
+ my @plugins;
+ my @expected = qw(MyTest::Plugin::Foo);
+ ok(@plugins = sort $foo->plugins);
+ is_deeply(\@plugins, \@expected);
+
+ @plugins = ();
+
+ ok(@plugins = sort MyTest->plugins);
+ is_deeply(\@plugins, \@expected);
+}
+
+{
+ my $foo;
+ ok($foo = MyTestSub->new());
+
+ my @plugins;
+ my @expected = qw(MyTest::Plugin::Foo);
+ ok(@plugins = sort $foo->plugins);
+ is_deeply(\@plugins, \@expected);
+
+ @plugins = ();
+
+ ok(@plugins = sort MyTestSub->plugins);
+ is_deeply(\@plugins, \@expected);
+}
+
+package MyTest;
+
+use strict;
+use Module::Pluggable only => "MyTest::Plugin::Foo";
+
+
+sub new {
+ my $class = shift;
+ return bless {}, $class;
+
+}
+
+package MyTestSub;
+
+use strict;
+use Module::Pluggable search_path => "MyTest::Plugin";
+
+
+sub new {
+ my $class = shift;
+ my $self = bless {}, $class;
+
+ $self->only("MyTest::Plugin::Foo");
+
+ return $self;
+}
+1;
--- /dev/null
+#!perl -w
+
+use strict;
+use FindBin;
+use lib (($FindBin::Bin."/lib")=~/^(.*)$/);
+use Test::More tests => 10;
+
+{
+ my $foo;
+ ok($foo = MyTest->new());
+
+ my @plugins;
+ my @expected = qw(MyTest::Plugin::Foo);
+ ok(@plugins = sort $foo->plugins);
+ is_deeply(\@plugins, \@expected);
+
+ @plugins = ();
+
+ ok(@plugins = sort MyTest->plugins);
+ is_deeply(\@plugins, \@expected);
+}
+
+{
+ my $foo;
+ ok($foo = MyTestSub->new());
+
+ my @plugins;
+ my @expected = qw(MyTest::Plugin::Foo);
+ ok(@plugins = sort $foo->plugins);
+ is_deeply(\@plugins, \@expected);
+
+ @plugins = ();
+
+ ok(@plugins = sort MyTestSub->plugins);
+ is_deeply(\@plugins, \@expected);
+}
+
+package MyTest;
+
+use strict;
+use Module::Pluggable only => [ "MyTest::Plugin::Foo" ];
+
+
+sub new {
+ my $class = shift;
+ return bless {}, $class;
+
+}
+
+package MyTestSub;
+
+use strict;
+use Module::Pluggable search_path => "MyTest::Plugin";
+
+
+sub new {
+ my $class = shift;
+ my $self = bless {}, $class;
+
+ $self->only(["MyTest::Plugin::Foo"]);
+
+ return $self;
+}
+1;
+
--- /dev/null
+#!perl -w
+
+use strict;
+use FindBin;
+use lib (($FindBin::Bin."/lib")=~/^(.*)$/);
+use Test::More tests => 10;
+
+{
+ my $foo;
+ ok($foo = MyTest->new());
+
+ my @plugins;
+ my @expected = qw(MyTest::Plugin::Foo);
+ ok(@plugins = sort $foo->plugins);
+ is_deeply(\@plugins, \@expected);
+
+ @plugins = ();
+
+ ok(@plugins = sort MyTest->plugins);
+ is_deeply(\@plugins, \@expected);
+}
+
+{
+ my $foo;
+ ok($foo = MyTestSub->new());
+
+ my @plugins;
+ my @expected = qw(MyTest::Plugin::Foo);
+ ok(@plugins = sort $foo->plugins);
+ is_deeply(\@plugins, \@expected);
+
+ @plugins = ();
+
+ ok(@plugins = sort MyTestSub->plugins);
+ is_deeply(\@plugins, \@expected);
+}
+
+package MyTest;
+
+use strict;
+use Module::Pluggable only => qr/MyTest::Plugin::Foo$/;
+
+
+sub new {
+ my $class = shift;
+ return bless {}, $class;
+
+}
+
+package MyTestSub;
+
+use strict;
+use Module::Pluggable search_path => "MyTest::Plugin";
+
+
+sub new {
+ my $class = shift;
+ my $self = bless {}, $class;
+
+ $self->only(qr/MyTest::Plugin::Foo$/);
+
+ return $self;
+}
+1;
+
--- /dev/null
+#!perl -w
+
+use strict;
+use FindBin;
+use lib (($FindBin::Bin."/lib")=~/^(.*)$/);
+use Test::More tests => 10;
+
+{
+ my $foo;
+ ok($foo = MyTest->new());
+
+ my @plugins;
+ my @expected = qw(MyTest::Plugin::Bar MyTest::Plugin::Quux::Foo);
+ ok(@plugins = sort $foo->plugins);
+
+ is_deeply(\@plugins, \@expected);
+
+ @plugins = ();
+
+ ok(@plugins = sort MyTest->plugins);
+ is_deeply(\@plugins, \@expected);
+}
+
+{
+ my $foo;
+ ok($foo = MyTestSub->new());
+
+ my @plugins;
+ my @expected = qw(MyTest::Plugin::Bar MyTest::Plugin::Quux::Foo);
+ ok(@plugins = sort $foo->plugins);
+
+ is_deeply(\@plugins, \@expected);
+
+ @plugins = ();
+
+ ok(@plugins = sort MyTestSub->plugins);
+ is_deeply(\@plugins, \@expected);
+}
+
+package MyTest;
+
+use strict;
+use Module::Pluggable except => "MyTest::Plugin::Foo";
+
+
+
+sub new {
+ my $class = shift;
+ return bless {}, $class;
+
+}
+
+package MyTestSub;
+
+use strict;
+use Module::Pluggable search_path => "MyTest::Plugin";
+
+
+sub new {
+ my $class = shift;
+ my $self = bless {}, $class;
+
+ $self->except("MyTest::Plugin::Foo");
+
+ return $self;
+}
+1;
+
--- /dev/null
+#!perl -wT
+
+use strict;
+use FindBin;
+use lib (($FindBin::Bin."/lib")=~/^(.*)$/);
+use Test::More tests => 10;
+
+{
+ my $foo;
+ ok($foo = MyTest->new());
+
+ my @plugins;
+ my @expected = qw(MyTest::Plugin::Bar MyTest::Plugin::Quux::Foo);
+ ok(@plugins = sort $foo->plugins);
+
+ is_deeply(\@plugins, \@expected);
+
+ @plugins = ();
+
+ ok(@plugins = sort MyTest->plugins);
+ is_deeply(\@plugins, \@expected);
+}
+
+{
+ my $foo;
+ ok($foo = MyTestSub->new());
+
+ my @plugins;
+ my @expected = qw(MyTest::Plugin::Bar MyTest::Plugin::Quux::Foo);
+ ok(@plugins = sort $foo->plugins);
+
+ is_deeply(\@plugins, \@expected);
+
+ @plugins = ();
+
+ ok(@plugins = sort MyTestSub->plugins);
+ is_deeply(\@plugins, \@expected);
+}
+
+package MyTest;
+
+use strict;
+use Module::Pluggable except => [ "MyTest::Plugin::Foo" ];
+
+
+
+sub new {
+ my $class = shift;
+ return bless {}, $class;
+
+}
+
+package MyTestSub;
+
+use strict;
+use Module::Pluggable search_path => "MyTest::Plugin";
+
+
+sub new {
+ my $class = shift;
+ my $self = bless {}, $class;
+
+ $self->except(["MyTest::Plugin::Foo"]);
+
+ return $self;
+}
+1;
+
--- /dev/null
+#!perl -wT
+
+use strict;
+use FindBin;
+use lib (($FindBin::Bin."/lib")=~/^(.*)$/);
+use Test::More tests => 10;
+
+{
+ my $foo;
+ ok($foo = MyTest->new());
+
+ my @plugins;
+ my @expected = qw(MyTest::Plugin::Bar MyTest::Plugin::Quux::Foo);
+ ok(@plugins = sort $foo->plugins);
+
+ is_deeply(\@plugins, \@expected);
+
+ @plugins = ();
+
+ ok(@plugins = sort MyTest->plugins);
+ is_deeply(\@plugins, \@expected);
+}
+
+{
+ my $foo;
+ ok($foo = MyTestSub->new());
+
+ my @plugins;
+ my @expected = qw(MyTest::Plugin::Bar MyTest::Plugin::Quux::Foo);
+ ok(@plugins = sort $foo->plugins);
+
+ is_deeply(\@plugins, \@expected);
+
+ @plugins = ();
+
+ ok(@plugins = sort MyTestSub->plugins);
+ is_deeply(\@plugins, \@expected);
+}
+
+package MyTest;
+
+use strict;
+use Module::Pluggable except => qr/MyTest::Plugin::Foo/;
+
+
+
+sub new {
+ my $class = shift;
+ return bless {}, $class;
+
+}
+
+package MyTestSub;
+
+use strict;
+use Module::Pluggable search_path => "MyTest::Plugin";
+
+
+sub new {
+ my $class = shift;
+ my $self = bless {}, $class;
+
+ $self->except(qr/MyTest::Plugin::Foo/);
+
+ return $self;
+}
+1;
+
--- /dev/null
+#!perl -w
+
+use strict;
+use FindBin;
+use lib (($FindBin::Bin."/lib")=~/^(.*)$/);
+use Test::More tests => 5;
+
+my $foo;
+ok($foo = MyTest->new());
+
+my @plugins;
+my @expected = qw(MyTest::Plugin::Bar MyTest::Plugin::Foo MyTest::Plugin::Quux::Foo);
+ok(@plugins = sort $foo->plugins);
+is_deeply(\@plugins, \@expected);
+
+@plugins = ();
+
+ok(@plugins = sort MyTest->plugins);
+is_deeply(\@plugins, \@expected);
+
+
+
+package MyTest;
+use strict;
+sub new { return bless {}, $_[0] }
+
+package MyOtherTest;
+use strict;
+use Module::Pluggable ( package => "MyTest" );
+sub new { return bless {}, $_[0] }
+
+
+1;
+
--- /dev/null
+#!perl -w
+
+use strict;
+use FindBin;
+use lib (($FindBin::Bin."/lib")=~/^(.*)$/);
+use Test::More 'no_plan';
+
+use Module::Pluggable search_path => 'Acme::MyTest';
+
+my $topic = "topic";
+
+for ($topic) {
+ main->plugins;
+}
+
+is($topic, 'topic', "we've got the right topic");
--- /dev/null
+#!perl -w
+
+use strict;
+use FindBin;
+use lib (($FindBin::Bin."/lib")=~/^(.*)$/);
+use Test::More tests => 5;
+
+my $foo;
+ok($foo = ExtTest->new());
+
+my @plugins;
+my @expected = qw(ExtTest::Plugin::Bar ExtTest::Plugin::Foo ExtTest::Plugin::Quux::Foo);
+ok(@plugins = sort $foo->plugins);
+
+
+
+is_deeply(\@plugins, \@expected, "is deeply");
+
+@plugins = ();
+
+ok(@plugins = sort ExtTest->plugins);
+
+
+
+
+is_deeply(\@plugins, \@expected, "is deeply class");
+
+
+
+package ExtTest;
+
+use strict;
+use Module::Pluggable file_regex => qr/\.plugin$/;
+
+
+sub new {
+ my $class = shift;
+ return bless {}, $class;
+
+}
+1;
+
--- /dev/null
+#!perl -w
+use Test::More tests => 3;
+
+use Devel::InnerPackage qw(list_packages);
+use FindBin;
+use lib (($FindBin::Bin."/lib")=~/^(.*)$/);
+
+my @packages;
+
+use_ok("TA::C::A::I");
+ok(@packages = list_packages("TA::C::A::I"));
+
+is_deeply([sort @packages], [qw(TA::C::A::I::A TA::C::A::I::A::B)]);
+
+
--- /dev/null
+#!perl -w
+
+use Test::More tests => 1;
+use FindBin;
+use lib (($FindBin::Bin."/lib")=~/^(.*)$/);
+
+use Devel::InnerPackage qw(list_packages);
+use No::Middle;
+
+my @p = list_packages("No::Middle");
+is_deeply([ sort @p ], [ qw(No::Middle::Package::A No::Middle::Package::B) ]);
--- /dev/null
+#!/usr/bin/perl
+use strict;
+use warnings;
+use Data::Dumper;
+use FindBin;
+use lib (($FindBin::Bin."/lib")=~/^(.*)$/);
+
+use Test::More tests=>5;
+
+#use_ok( 'MyTest' );
+#diag "Module::Pluggable::VERSION $Module::Pluggable::VERSION";
+
+my @plugins = MyTest->plugins;
+my @plugins_after;
+
+use_ok( 'MyTest::Plugin::Foo' );
+ok( my $foo = MyTest::Plugin::Foo->new() );
+
+@plugins_after = MyTest->plugins;
+is_deeply(
+ \@plugins_after,
+ \@plugins,
+ "plugins haven't been clobbered",
+);
+
+can_ok ($foo, 'frobnitz');
+
+@plugins_after = MyTest->plugins;
+is_deeply(
+ \@plugins_after,
+ \@plugins,
+ "plugins haven't been clobbered",
+) or diag Dumper ;
+
+
+
+package MyTest;
+
+use strict;
+use Module::Pluggable;
+
+
+sub new {
+ my $class = shift;
+ return bless {}, $class;
+
+}
+1;
+
+
--- /dev/null
+#!perl -w
+
+BEGIN {
+ if ($^O eq 'VMS' || $^O eq 'VOS') {
+ print "1..0 # Skip: can't handle misspelled plugin names\n";
+ exit;
+ }
+}
+
+use strict;
+use FindBin;
+use Test::More;
+use lib (($FindBin::Bin."/lib")=~/^(.*)$/);
+use File::Spec::Functions qw(catfile);
+
+
+my ($dodgy_file) = (catfile($FindBin::Bin, "lib", "OddTest", "Plugin", "-Dodgy.pm")=~/^(.*)$/);
+unless (-f $dodgy_file) {
+ plan skip_all => "Can't handle misspelled plugin names\n";
+} else {
+ plan tests => 5;
+}
+
+
+my $foo;
+ok($foo = OddTest->new());
+
+my @plugins;
+my @expected = ('OddTest::Plugin::-Dodgy', 'OddTest::Plugin::Foo');
+ok(@plugins = sort $foo->plugins);
+is_deeply(\@plugins, \@expected, "is deeply");
+
+my @odd_plugins;
+my @odd_expected = qw(OddTest::Plugin::Foo);
+ok(@odd_plugins = sort $foo->odd_plugins);
+is_deeply(\@odd_plugins, \@odd_expected, "is deeply");
+
+
+package OddTest::Pluggable;
+
+use Data::Dumper;
+use base qw(Module::Pluggable::Object);
+
+
+sub find_files {
+ my $self = shift;
+ my @files = $self->SUPER::find_files(@_);
+ return grep { !/(^|\/)-/ } $self->SUPER::find_files(@_) ;
+}
+
+package OddTest;
+
+use strict;
+use Module::Pluggable;
+
+
+sub new {
+ my $class = shift;
+ return bless {}, $class;
+
+}
+
+sub odd_plugins {
+ my $self = shift;
+ my %opts;
+ my ($pkg, $file) = caller;
+ # the default name for the method is 'plugins'
+ my $sub = $opts{'sub_name'} || 'plugins';
+ # get our package
+ my ($package) = $opts{'package'} || "OddTest";
+ $opts{filename} = $file;
+ $opts{package} = $package;
+
+
+
+ my $op = OddTest::Pluggable->new( package => ref($self) );
+ return $op->plugins(@_);
+
+
+}
+
+
+1;
+
--- /dev/null
+#!perl -w
+
+use Test::More;
+use FindBin;
+use lib (($FindBin::Bin."/lib")=~/^(.*)$/);
+use Module::Pluggable::Object;
+use File::Spec::Functions qw(catfile);
+
+my ($dodgy_file) = (catfile($FindBin::Bin,"lib", "EditorJunk", "Plugin", "#Bar.pm#")=~/^(.*)$/);
+unless (-f $dodgy_file) {
+ plan skip_all => "Can't handle plugin names with octothorpes\n";
+} else {
+ plan tests => 4;
+}
+
+
+
+my $foo;
+ok($foo = EditorJunk->new());
+
+my @plugins;
+my @expected = qw(EditorJunk::Plugin::Bar EditorJunk::Plugin::Foo);
+ok(@plugins = sort $foo->plugins);
+
+is_deeply(\@plugins, \@expected, "is deeply");
+
+
+my $mpo = Module::Pluggable::Object->new(
+ package => 'EditorJunk',
+ filename => __FILE__,
+ include_editor_junk => 1,
+);
+
+@expected = ('EditorJunk::Plugin::.#Bar', 'EditorJunk::Plugin::Bar', 'EditorJunk::Plugin::Foo');
+@plugins = sort $mpo->plugins();
+is_deeply(\@plugins, \@expected, "is deeply");
+
+
+
+package EditorJunk;
+
+use strict;
+use Module::Pluggable;
+
+
+sub new {
+ my $class = shift;
+ return bless {}, $class;
+
+}
+1;
+
+
--- /dev/null
+package Acme::MyTest::Plugin::Foo;
+
+
+use strict;
+
+
+1;
+
+
--- /dev/null
+package Acme::MyTest::Plugin::Foo;
+
+
+use strict;
+
+
+1;
+
+
--- /dev/null
+package EditorJunk::Bar;
+
+
+use strict;
+
+
+1;
+
+
--- /dev/null
+package EditorJunk::Bar;
+
+
+use strict;
+
+
+1;
+
+
--- /dev/null
+package EditorJunk::Bar;
+
+
+use strict;
+
+
+1;
+
+
--- /dev/null
+package EditorJunk::Bar;
+
+
+use strict;
+
+
+1;
+
+
--- /dev/null
+package EditorJunk::Foo;
+
+
+use strict;
+
+
+1;
+
+
--- /dev/null
+package MyTest::Plugin::Bar;
+
+
+use strict;
+
+
+1;
+
+
--- /dev/null
+package MyTest::Plugin::Foo;
+
+
+use strict;
+
+
+1;
+
+
--- /dev/null
+package MyTest::Plugin::Quux::Foo;
+
+
+use strict;
+
+
+1;
+
+
--- /dev/null
+package InnerTest::Plugin::Foo;
+use strict;
+
+our $FOO = 1;
+
+package InnerTest::Plugin::Bar;
+use strict;
+
+sub bar {}
+
+package InnerTest::Plugin::Quux;
+use strict;
+use base qw(InnerTest::Plugin::Bar);
+
+
+
+1;
--- /dev/null
+package MyOtherTest::Plugin::Bar;
+use strict;
+1;
+
+
--- /dev/null
+package MyOtherTest::Plugin::Foo;
+use strict;
+1;
+
+
--- /dev/null
+package MyOtherTest::Plugin::Quux;
+use strict;
+1;
+
+
--- /dev/null
+package MyOtherTest::Plugin::Quux::Foo;
+use strict;
+1;
+
+
--- /dev/null
+package MyTest::Extend::Plugin::Bar;
+use strict;
+
+sub new {
+ my $class = shift;
+ my %self = @_;
+
+ return bless \%self, $class;
+}
+
+
+sub nork {
+ return $_[0]->{'nork'};
+}
+1;
+
+
--- /dev/null
+package MyTest::Plugin::Bar;
+
+
+use strict;
+
+
+1;
+
+
--- /dev/null
+package MyTest::Plugin::Foo;
+
+
+use strict;
+
+sub new { return bless {}, $_[0]; }
+sub frobnitz {}
+1;
+
+
--- /dev/null
+package MyTest::Plugin::Quux::Foo;
+
+
+use strict;
+
+
+1;
+
+
--- /dev/null
+package No::Middle;
+
+sub foo {}
+
+package No::Middle::Package::A;
+
+sub foo {}
+
+
+package No::Middle::Package::B;
+
+sub foo {}
+
+1;
--- /dev/null
+package OddFiles/Plugin/Foo.pm
+
+sub new {}
+
+1;
--- /dev/null
+package TA::C::A::I;
+
+sub foo { }
+
+package TA::C::A::I::A;
+
+sub foo { }
+
+package TA::C::A::I::A::B;
+
+sub foo { }
+
+1;
--- /dev/null
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA1
+
+Format: 1.0
+Source: libmodule-pluggable-perl
+Binary: libmodule-pluggable-perl
+Architecture: all
+Version: 3.8-1
+Maintainer: Debian Perl Group <pkg-perl-maintainers@lists.alioth.debian.org>
+Uploaders: Niko Tyni <ntyni@iki.fi>, Krzysztof Krzyzaniak (eloy) <eloy@debian.org>, gregor herrmann <gregor+debian@comodo.priv.at>
+Homepage: http://search.cpan.org/dist/Module-Pluggable/
+Standards-Version: 3.7.3
+Vcs-Browser: http://svn.debian.org/wsvn/pkg-perl/trunk/libmodule-pluggable-perl/
+Vcs-Svn: svn://svn.debian.org/pkg-perl/trunk/libmodule-pluggable-perl/
+Build-Depends: debhelper (>= 5)
+Build-Depends-Indep: perl (>= 5.6.0-16), perl-modules
+Files:
+ 661e2c71c824419c37775998c63b0f85 16889 libmodule-pluggable-perl_3.8.orig.tar.gz
+ 0bb3ae07a75d1ed467ba87f9dfbf8f24 3002 libmodule-pluggable-perl_3.8-1.diff.gz
+
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.6 (GNU/Linux)
+
+iD8DBQFH3tTcHqjlqpcl9jsRAmGpAJ0c1TIaUyBSuc+EVg4Ansj8OF2PbACcDlnv
+wVlKvV13Gdp0B43UGrxp374=
+=N5AC
+-----END PGP SIGNATURE-----
--- /dev/null
+Format: 1.0
+Source: libmodule-pluggable-perl
+Version: 3.8-1maemo1
+Binary: libmodule-pluggable-perl
+Maintainer: Debian Perl Group <pkg-perl-maintainers@lists.alioth.debian.org>
+Architecture: all
+Standards-Version: 3.7.3
+Build-Depends: debhelper (>= 5)
+Build-Depends-Indep: perl (>= 5.6.0-16), perl-modules
+Uploaders: Niko Tyni <ntyni@iki.fi>, Krzysztof Krzyzaniak (eloy) <eloy@debian.org>, gregor herrmann <gregor+debian@comodo.priv.at>
+Files:
+ 661e2c71c824419c37775998c63b0f85 16889 libmodule-pluggable-perl_3.8.orig.tar.gz
+ 484109f05cb7a0dcb9cbaf47ce3ccae8 3043 libmodule-pluggable-perl_3.8-1maemo1.diff.gz
--- /dev/null
+Format: 1.7
+Date: Fri, 16 Apr 2010 06:45:02 +0100
+Source: libmodule-pluggable-perl
+Binary: libmodule-pluggable-perl
+Architecture: source all
+Version: 3.8-1maemo1
+Distribution: fremantle
+Urgency: low
+Maintainer: Debian Perl Group <pkg-perl-maintainers@lists.alioth.debian.org>
+Changed-By: Nito Martinez <Nito@Qindel.ES>
+Description:
+ libmodule-pluggable-perl - Automatically provide your module the ability to accept plugins
+Changes:
+ libmodule-pluggable-perl (3.8-1maemo1) fremantle; urgency=low
+ .
+ * New Maemo packaging
+Files:
+ 41e6ad5b4063082d7f058d44f70f380a 609 perl optional libmodule-pluggable-perl_3.8-1maemo1.dsc
+ 484109f05cb7a0dcb9cbaf47ce3ccae8 3043 perl optional libmodule-pluggable-perl_3.8-1maemo1.diff.gz
+ 9b27b2c85e412b79f6b1790f6a34b400 23308 perl optional libmodule-pluggable-perl_3.8-1maemo1_all.deb
* New Maemo packaging
EOF
- print " -- Nito Martinez <Nito\@Qindel.ES> $date\n\nl";
+ print " -- Nito Martinez <Nito\@Qindel.ES> $date\n\n";
print "$_";
$begin=0;
} else {