← Index
NYTProf Performance Profile   « line view »
For /Users/timbo/perl5/perlbrew/perls/perl-5.18.2/bin/perlcritic
  Run on Sat Mar 19 22:12:22 2016
Reported on Sat Mar 19 22:14:11 2016

Filename/Users/timbo/perl5/perlbrew/perls/perl-5.18.2/lib/site_perl/5.18.2/Module/Pluggable.pm
StatementsExecuted 34 statements in 766µs
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
1111.84ms11.7msModule::Pluggable::::BEGIN@5Module::Pluggable::BEGIN@5
11133µs38µsModule::Pluggable::::importModule::Pluggable::import
11117µs35µsModule::Pluggable::::BEGIN@3Module::Pluggable::BEGIN@3
11115µs113µsModule::Pluggable::::BEGIN@7Module::Pluggable::BEGIN@7
11111µs22µsModule::Pluggable::::BEGIN@66Module::Pluggable::BEGIN@66
11110µs55µsModule::Pluggable::::BEGIN@4Module::Pluggable::BEGIN@4
1119µs20µsModule::Pluggable::::BEGIN@67Module::Pluggable::BEGIN@67
1118µs1.29sModule::Pluggable::::__ANON__[:32]Module::Pluggable::__ANON__[:32]
0000s0sModule::Pluggable::::__ANON__[:42]Module::Pluggable::__ANON__[:42]
0000s0sModule::Pluggable::::__ANON__[:53]Module::Pluggable::__ANON__[:53]
0000s0sModule::Pluggable::::__ANON__[:63]Module::Pluggable::__ANON__[:63]
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1package Module::Pluggable;
2
3232µs252µs
# spent 35µs (17+18) within Module::Pluggable::BEGIN@3 which was called: # once (17µs+18µs) by Perl::Critic::PolicyFactory::import at line 3
use strict;
# spent 35µs making 1 call to Module::Pluggable::BEGIN@3 # spent 18µs making 1 call to strict::import
4234µs299µs
# spent 55µs (10+44) within Module::Pluggable::BEGIN@4 which was called: # once (10µs+44µs) by Perl::Critic::PolicyFactory::import at line 4
use vars qw($VERSION $FORCE_SEARCH_ALL_PATHS);
# spent 55µs making 1 call to Module::Pluggable::BEGIN@4 # spent 44µs making 1 call to vars::import
52119µs111.7ms
# spent 11.7ms (1.84+9.83) within Module::Pluggable::BEGIN@5 which was called: # once (1.84ms+9.83ms) by Perl::Critic::PolicyFactory::import at line 5
use Module::Pluggable::Object;
# spent 11.7ms making 1 call to Module::Pluggable::BEGIN@5
6
72341µs2116µs
# spent 113µs (15+98) within Module::Pluggable::BEGIN@7 which was called: # once (15µs+98µs) by Perl::Critic::PolicyFactory::import at line 7
use if $] > 5.017, 'deprecate';
# spent 113µs making 1 call to Module::Pluggable::BEGIN@7 # spent 3µs making 1 call to if::import
8
9# ObQuote:
10# Bob Porter: Looks like you've been missing a lot of work lately.
11# Peter Gibbons: I wouldn't say I've been missing it, Bob!
12
13
141700ns$VERSION = '5.1';
151100ns$FORCE_SEARCH_ALL_PATHS = 0;
16
17
# spent 38µs (33+6) within Module::Pluggable::import which was called: # once (33µs+6µs) by Perl::Critic::PolicyFactory::import at line 59 of Perl/Critic/PolicyFactory.pm
sub import {
181400ns my $class = shift;
1914µs12µs my %opts = @_;
# spent 2µs making 1 call to Readonly::Scalar::FETCH
20
2111µs my ($pkg, $file) = caller;
22 # the default name for the method is 'plugins'
231600ns my $sub = $opts{'sub_name'} || 'plugins';
24 # get our package
251300ns my ($package) = $opts{'package'} || $pkg;
261400ns $opts{filename} = $file;
271100ns $opts{package} = $package;
281500ns $opts{force_search_all_paths} = $FORCE_SEARCH_ALL_PATHS unless exists $opts{force_search_all_paths};
29
30
3113µs14µs my $finder = Module::Pluggable::Object->new(%opts);
# spent 4µs making 1 call to Module::Pluggable::Object::new
3238µs11.29s
# spent 1.29s (8µs+1.29) within Module::Pluggable::__ANON__[/Users/timbo/perl5/perlbrew/perls/perl-5.18.2/lib/site_perl/5.18.2/Module/Pluggable.pm:32] which was called: # once (8µs+1.29s) by Perl::Critic::PolicyFactory::import at line 61 of Perl/Critic/PolicyFactory.pm
my $subroutine = sub { my $self = shift; return $finder->plugins(@_) };
# spent 1.29s making 1 call to Module::Pluggable::Object::plugins
33
34 my $searchsub = sub {
35 my $self = shift;
36 my ($action,@paths) = @_;
37
38 $finder->{'search_path'} = ["${package}::Plugin"] if ($action eq 'add' and not $finder->{'search_path'} );
39 push @{$finder->{'search_path'}}, @paths if ($action eq 'add');
40 $finder->{'search_path'} = \@paths if ($action eq 'new');
41 return $finder->{'search_path'};
4212µs };
43
44
45 my $onlysub = sub {
46 my ($self, $only) = @_;
47
48 if (defined $only) {
49 $finder->{'only'} = $only;
50 };
51
52 return $finder->{'only'};
5311µs };
54
55 my $exceptsub = sub {
56 my ($self, $except) = @_;
57
58 if (defined $except) {
59 $finder->{'except'} = $except;
60 };
61
62 return $finder->{'except'};
631800ns };
64
65
66223µs232µs
# spent 22µs (11+11) within Module::Pluggable::BEGIN@66 which was called: # once (11µs+11µs) by Perl::Critic::PolicyFactory::import at line 66
no strict 'refs';
# spent 22µs making 1 call to Module::Pluggable::BEGIN@66 # spent 10µs making 1 call to strict::unimport
672180µs232µs
# spent 20µs (9+12) within Module::Pluggable::BEGIN@67 which was called: # once (9µs+12µs) by Perl::Critic::PolicyFactory::import at line 67
no warnings qw(redefine prototype);
# spent 20µs making 1 call to Module::Pluggable::BEGIN@67 # spent 12µs making 1 call to warnings::unimport
68
6912µs *{"$package\::$sub"} = $subroutine;
7012µs *{"$package\::search_path"} = $searchsub;
7111µs *{"$package\::only"} = $onlysub;
7216µs *{"$package\::except"} = $exceptsub;
73
74}
75
7612µs1;
77
78=pod
79
80=head1 NAME
81
82Module::Pluggable - automatically give your module the ability to have plugins
83
84=head1 SYNOPSIS
85
86
87Simple use Module::Pluggable -
88
89 package MyClass;
90 use Module::Pluggable;
91
92
93and then later ...
94
95 use MyClass;
96 my $mc = MyClass->new();
97 # returns the names of all plugins installed under MyClass::Plugin::*
98 my @plugins = $mc->plugins();
99
100=head1 EXAMPLE
101
102Why would you want to do this? Say you have something that wants to pass an
103object to a number of different plugins in turn. For example you may
104want to extract meta-data from every email you get sent and do something
105with it. Plugins make sense here because then you can keep adding new
106meta data parsers and all the logic and docs for each one will be
107self contained and new handlers are easy to add without changing the
108core code. For that, you might do something like ...
109
110 package Email::Examiner;
111
112 use strict;
113 use Email::Simple;
114 use Module::Pluggable require => 1;
115
116 sub handle_email {
117 my $self = shift;
118 my $email = shift;
119
120 foreach my $plugin ($self->plugins) {
121 $plugin->examine($email);
122 }
123
124 return 1;
125 }
126
- -
129.. and all the plugins will get a chance in turn to look at it.
130
131This can be trivially extended so that plugins could save the email
132somewhere and then no other plugin should try and do that.
133Simply have it so that the C<examine> method returns C<1> if
134it has saved the email somewhere. You might also want to be paranoid
135and check to see if the plugin has an C<examine> method.
136
137 foreach my $plugin ($self->plugins) {
138 next unless $plugin->can('examine');
139 last if $plugin->examine($email);
140 }
141
142
143And so on. The sky's the limit.
144
145
146=head1 DESCRIPTION
147
148Provides a simple but, hopefully, extensible way of having 'plugins' for
149your module. Obviously this isn't going to be the be all and end all of
150solutions but it works for me.
151
152Essentially all it does is export a method into your namespace that
153looks through a search path for .pm files and turn those into class names.
154
155Optionally it instantiates those classes for you.
156
157=head1 ADVANCED USAGE
158
159Alternatively, if you don't want to use 'plugins' as the method ...
160
161 package MyClass;
162 use Module::Pluggable sub_name => 'foo';
163
164
165and then later ...
166
167 my @plugins = $mc->foo();
168
169
170Or if you want to look in another namespace
171
172 package MyClass;
173 use Module::Pluggable search_path => ['Acme::MyClass::Plugin', 'MyClass::Extend'];
174
175or directory
176
177 use Module::Pluggable search_dirs => ['mylibs/Foo'];
178
179
180Or if you want to instantiate each plugin rather than just return the name
181
182 package MyClass;
183 use Module::Pluggable instantiate => 'new';
184
185and then
186
187 # whatever is passed to 'plugins' will be passed
188 # to 'new' for each plugin
189 my @plugins = $mc->plugins(@options);
190
191
192alternatively you can just require the module without instantiating it
193
194 package MyClass;
195 use Module::Pluggable require => 1;
196
197since requiring automatically searches inner packages, which may not be desirable, you can turn this off
198
199
200 package MyClass;
201 use Module::Pluggable require => 1, inner => 0;
202
203
204You can limit the plugins loaded using the except option, either as a string,
205array ref or regex
206
207 package MyClass;
208 use Module::Pluggable except => 'MyClass::Plugin::Foo';
209
210or
211
212 package MyClass;
213 use Module::Pluggable except => ['MyClass::Plugin::Foo', 'MyClass::Plugin::Bar'];
214
215or
216
217 package MyClass;
218 use Module::Pluggable except => qr/^MyClass::Plugin::(Foo|Bar)$/;
219
220
221and similarly for only which will only load plugins which match.
222
223Remember you can use the module more than once
224
225 package MyClass;
226 use Module::Pluggable search_path => 'MyClass::Filters' sub_name => 'filters';
227 use Module::Pluggable search_path => 'MyClass::Plugins' sub_name => 'plugins';
228
229and then later ...
230
231 my @filters = $self->filters;
232 my @plugins = $self->plugins;
233
234=head1 PLUGIN SEARCHING
235
236Every time you call 'plugins' the whole search path is walked again. This allows
237for dynamically loading plugins even at run time. However this can get expensive
238and so if you don't expect to want to add new plugins at run time you could do
239
240
241 package Foo;
242 use strict;
243 use Module::Pluggable sub_name => '_plugins';
244
245 our @PLUGINS;
246 sub plugins { @PLUGINS ||= shift->_plugins }
247 1;
248
249=head1 INNER PACKAGES
250
251If you have, for example, a file B<lib/Something/Plugin/Foo.pm> that
252contains package definitions for both C<Something::Plugin::Foo> and
253C<Something::Plugin::Bar> then as long as you either have either
254the B<require> or B<instantiate> option set then we'll also find
255C<Something::Plugin::Bar>. Nifty!
256
257=head1 OPTIONS
258
259You can pass a hash of options when importing this module.
260
261The options can be ...
262
263=head2 sub_name
264
265The name of the subroutine to create in your namespace.
266
267By default this is 'plugins'
268
269=head2 search_path
270
271An array ref of namespaces to look in.
272
273=head2 search_dirs
274
275An array ref of directories to look in before @INC.
276
277=head2 instantiate
278
279Call this method on the class. In general this will probably be 'new'
280but it can be whatever you want. Whatever arguments are passed to 'plugins'
281will be passed to the method.
282
283The default is 'undef' i.e just return the class name.
284
285=head2 require
286
287Just require the class, don't instantiate (overrides 'instantiate');
288
289=head2 inner
290
291If set to 0 will B<not> search inner packages.
292If set to 1 will override C<require>.
293
294=head2 only
295
296Takes a string, array ref or regex describing the names of the only plugins to
297return. Whilst this may seem perverse ... well, it is. But it also
298makes sense. Trust me.
299
300=head2 except
301
302Similar to C<only> it takes a description of plugins to exclude
303from returning. This is slightly less perverse.
304
305=head2 package
306
307This is for use by extension modules which build on C<Module::Pluggable>:
308passing a C<package> option allows you to place the plugin method in a
309different package other than your own.
310
311=head2 file_regex
312
313By default C<Module::Pluggable> only looks for I<.pm> files.
314
315By supplying a new C<file_regex> then you can change this behaviour e.g
316
317 file_regex => qr/\.plugin$/
318
319=head2 include_editor_junk
320
321By default C<Module::Pluggable> ignores files that look like they were
322left behind by editors. Currently this means files ending in F<~> (~),
323the extensions F<.swp> or F<.swo>, or files beginning with F<.#>.
324
325Setting C<include_editor_junk> changes C<Module::Pluggable> so it does
326not ignore any files it finds.
327
328=head2 follow_symlinks
329
330Whether, when searching directories, to follow symlinks.
331
332Defaults to 1 i.e do follow symlinks.
333
334=head2 min_depth, max_depth
335
336This will allow you to set what 'depth' of plugin will be allowed.
337
338So, for example, C<MyClass::Plugin::Foo> will have a depth of 3 and
339C<MyClass::Plugin::Foo::Bar> will have a depth of 4 so to only get the former
340(i.e C<MyClass::Plugin::Foo>) do
341
342 package MyClass;
343 use Module::Pluggable max_depth => 3;
344
345and to only get the latter (i.e C<MyClass::Plugin::Foo::Bar>)
346
347 package MyClass;
348 use Module::Pluggable min_depth => 4;
349
350
351=head1 TRIGGERS
352
353Various triggers can also be passed in to the options.
354
355If any of these triggers return 0 then the plugin will not be returned.
356
357=head2 before_require <plugin>
358
359Gets passed the plugin name.
360
361If 0 is returned then this plugin will not be required either.
362
363=head2 on_require_error <plugin> <err>
364
365Gets called when there's an error on requiring the plugin.
366
367Gets passed the plugin name and the error.
368
369The default on_require_error handler is to C<carp> the error and return 0.
370
371=head2 on_instantiate_error <plugin> <err>
372
373Gets called when there's an error on instantiating the plugin.
374
375Gets passed the plugin name and the error.
376
377The default on_instantiate_error handler is to C<carp> the error and return 0.
378
379=head2 after_require <plugin>
380
381Gets passed the plugin name.
382
383If 0 is returned then this plugin will be required but not returned as a plugin.
384
385=head1 METHODs
386
387=head2 search_path
388
389The method C<search_path> is exported into you namespace as well.
390You can call that at any time to change or replace the
391search_path.
392
393 $self->search_path( add => "New::Path" ); # add
394 $self->search_path( new => "New::Path" ); # replace
395
396=head1 BEHAVIOUR UNDER TEST ENVIRONMENT
397
398In order to make testing reliable we exclude anything not from blib if blib.pm is
399in %INC.
400
401However if the module being tested used another module that itself used C<Module::Pluggable>
402then the second module would fail. This was fixed by checking to see if the caller
403had (^|/)blib/ in their filename.
404
405There's an argument that this is the wrong behaviour and that modules should explicitly
406trigger this behaviour but that particular code has been around for 7 years now and I'm
407reluctant to change the default behaviour.
408
409You can now (as of version 4.1) force Module::Pluggable to look outside blib in a test environment by doing either
410
411 require Module::Pluggable;
412 $Module::Pluggable::FORCE_SEARCH_ALL_PATHS = 1;
413 import Module::Pluggable;
414
415or
416
417 use Module::Pluggable force_search_all_paths => 1;
418
419=head1 @INC hooks and App::FatPacker
420
421If a module's @INC has a hook and that hook is an object which has a C<files()> method then we will
422try and require those files too. See C<t/26inc_hook.t> for an example.
423
424This has allowed L<App::FatPacker> (as of version 0.10.0) to provide support for Module::Pluggable.
425
426This should also, theoretically, allow someone to modify PAR to do the same thing.
427
428=head1 FUTURE PLANS
429
430This does everything I need and I can't really think of any other
431features I want to add. Famous last words of course (not least
432because we're up to version 5.0 at the time of writing).
433
434However suggestions (and patches) are always welcome.
435
436=head1 DEVELOPMENT
437
438The master repo for this module is at
439
440https://github.com/simonwistow/Module-Pluggable
441
442=head1 AUTHOR
443
444Simon Wistow <simon@thegestalt.org>
445
446=head1 COPYING
447
448Copyright, 2006 Simon Wistow
449
450Distributed under the same terms as Perl itself.
451
452=head1 BUGS
453
454None known.
455
456=head1 SEE ALSO
457
458L<File::Spec>, L<File::Find>, L<File::Basename>, L<Class::Factory::Util>, L<Module::Pluggable::Ordered>
459
460=cut
461
462