Class-C3-Componentised-1.001002/0000755000000000000000000000000013244015227016171 5ustar00rootwheel00000000000000Class-C3-Componentised-1.001002/Changes0000644000000000000000000000420013244015207017456 0ustar00rootwheel00000000000000Revision history for Class-C3-Componentised 1.001002 - 2018-02-23 - fixed author metadata - added x_static_install and dynamic_config=0 to metadata - added x_authority to metadata 1.001_001 - 2018-02-15 - list test prerequisites as test prerequisites rather than runtime prerequisites. (RT#100637) - correctly list Test::More 0.96 as a test prerequisite (RT#77611) - stop using Class::C3 in tests. it is still listed as a prerequisite. because some things expect it to be available once this module is installed. - convert packaging from using Module::Install to plain ExtUtils::MakeMaker, with Distar for releasing. This fixes issues when the current directory is not in @INC (perl 5.26). Fixes RT#121696, RT#120826 - fixed typo in documentation. (RT#85355) - fixed module abstracts. - increase Class::Inspector prereq to 1.32 to fix ensure_class_found on modules provided by @INC hooks, such as PAR. (RT#42845) 1.001000 08 Aug 2011 - Add Class::C3::Componentised::ApplyHooks features 1.0009 20 Mar 2011 - Stop importing Carp functions (and thus polluting the inheritor namespaces) - Make sure $_ is properly preserved even if the loaded module is negligent enough to change it (RT#66661) - Added missing copyright statement 1.0008 24 Feb 2011 Fix inject_base regression introduced during optimizations in 1.0007 1.0007 23 Feb 2011 Throw a readable exception when load_optional_class is given an invalid class name 1.0006 08 Sep 2009 Allow derived classes without component_base_class(), given all arguments to load_components are absolute class names (+Classname) 1.0005 22 Apr 2009 Add load_optional_class method 1.0004 18 Mar 2009 Port to use MRO::Compat (rafl) 1.0003 5 Mar 2008 Fix tests on perl 5.10.0 1.0002 4 Mar 2008 Make tests more resilient 1.0001 11 Aug 2007 Add missing dep on Test::Exception 1.0000 31 Jul 2007 First version, based on DBIx::Class::Componentised r3634 Class-C3-Componentised-1.001002/lib/0000755000000000000000000000000013244015226016736 5ustar00rootwheel00000000000000Class-C3-Componentised-1.001002/lib/Class/0000755000000000000000000000000013244015226020003 5ustar00rootwheel00000000000000Class-C3-Componentised-1.001002/lib/Class/C3/0000755000000000000000000000000013244015226020250 5ustar00rootwheel00000000000000Class-C3-Componentised-1.001002/lib/Class/C3/Componentised/0000755000000000000000000000000013244015226023057 5ustar00rootwheel00000000000000Class-C3-Componentised-1.001002/lib/Class/C3/Componentised/ApplyHooks.pm0000644000000000000000000000706513241316232025514 0ustar00rootwheel00000000000000package Class::C3::Componentised::ApplyHooks; use strict; use warnings; our %Before; our %After; sub BEFORE_APPLY (&) { push @{$Before{scalar caller}}, $_[0]; $Class::C3::Componentised::APPLICATOR_FOR{scalar caller} = __PACKAGE__; } sub AFTER_APPLY (&) { push @{$After {scalar caller}}, $_[0]; $Class::C3::Componentised::APPLICATOR_FOR{scalar caller} = __PACKAGE__; } sub _apply_component_to_class { my ($me, $comp, $target, $apply) = @_; my @heritage = @{mro::get_linear_isa($comp)}; my @before = map { my $to_run = $Before{$_}; ($to_run?[$_,$to_run]:()) } @heritage; for my $todo (@before) { my ($parent, $fn) = @$todo; for my $f (reverse @$fn) { $target->$f($parent) } } $apply->(); my @after = map { my $to_run = $After{$_}; ($to_run?[$_,$to_run]:()) } @heritage; for my $todo (reverse @after) { my ($parent, $fn) = @$todo; for my $f (@$fn) { $target->$f($parent) } } } { no strict 'refs'; sub import { my ($from, @args) = @_; my $to = caller; my $default = 1; my $i = 0; my $skip = 0; my @import; for my $arg (@args) { if ($skip) { $skip--; $i++; next } if ($arg eq '-before_apply') { $default = 0; $skip = 1; push @{$Before{$to}}, $args[$i + 1]; $Class::C3::Componentised::APPLICATOR_FOR{$to} = $from; } elsif ($arg eq '-after_apply') { $default = 0; $skip = 1; push @{$After{$to}}, $args[$i + 1]; $Class::C3::Componentised::APPLICATOR_FOR{$to} = $from; } elsif ($arg =~ /^BEFORE_APPLY|AFTER_APPLY$/) { $default = 0; push @import, $arg } $i++; } @import = qw(BEFORE_APPLY AFTER_APPLY) if $default; *{"$to\::$_"} = \&{"$from\::$_"} for @import } } 1; =head1 NAME Class::C3::Componentised::ApplyHooks - Run methods before or after components are injected =head1 SYNOPSIS package MyComponent; our %statistics; use Class::C3::Componentised::ApplyHooks -before_apply => sub { my ($class, $component) = @_; push @{$statistics{$class}}, '-before_apply'; }, -after_apply => sub { my ($class, $component) = @_; push @{$statistics{$class}}, '-after_apply'; }, qw(BEFORE_APPLY AFTER_APPLY); BEFORE_APPLY { push @{$statistics{$class}}, 'BEFORE_APPLY' }; AFTER_APPLY { push @{$statistics{$class}}, 'AFTER_APPLY' }; AFTER_APPLY { use Devel::Dwarn; Dwarn %statistics }; 1; =head1 DESCRIPTION This package allows a given component to run methods on the class that is being injected into before or after the component is injected. Note from the L that all C may be run more than once. =head1 IMPORT ACTION Both import actions simply run a list of coderefs that will be passed the class that is being acted upon and the component that is being added to the class. =head1 IMPORT OPTIONS =head2 -before_apply Adds a before apply action for the current component without importing any subroutines into your namespace. =head2 -after_apply Adds an after apply action for the current component without importing any subroutines into your namespace. =head1 EXPORTED SUBROUTINES =head2 BEFORE_APPLY BEFORE_APPLY { warn "about to apply $_[1] to class $_[0]" }; Adds a before apply action for the current component. =head2 AFTER_APPLY AFTER_APPLY { warn "just applied $_[1] to class $_[0]" }; Adds an after apply action for the current component. =cut Class-C3-Componentised-1.001002/lib/Class/C3/Componentised.pm0000644000000000000000000001346513244014767023437 0ustar00rootwheel00000000000000package Class::C3::Componentised; =head1 NAME Class::C3::Componentised - Load mix-ins or components to your C3-based class =head1 SYNOPSIS package MyModule; use strict; use warnings; use base 'Class::C3::Componentised'; sub component_base_class { "MyModule::Component" } package main; MyModule->load_components( qw/Foo Bar/ ); # Will load MyModule::Component::Foo and MyModule::Component::Bar =head1 DESCRIPTION This will inject base classes to your module using the L method resolution order. Please note: these are not plugins that can take precedence over methods declared in MyModule. If you want something like that, consider L. =head1 METHODS =cut use strict; use warnings; # This will prime the Class::C3 namespace (either by loading it proper on 5.8 # or by installing compat shims on 5.10+). A user might have a reasonable # expectation that using Class::C3:: will give him access to # Class::C3 itself, and this module has been providing this historically. # Therefore leaving it in indefinitely. use MRO::Compat; use Carp (); use List::Util (); our $VERSION = '1.001002'; $VERSION =~ tr/_//d; my $invalid_class = qr/(?: \b:\b | \:{3,} | \:\:$ )/x; =head2 load_components( @comps ) Loads the given components into the current module. If a module begins with a C<+> character, it is taken to be a fully qualified class name, otherwise C<< $class->component_base_class >> is prepended to it. Calling this will call C. =cut sub load_components { my $class = shift; $class->_load_components( map { /^\+(.*)$/ ? $1 : join ('::', $class->component_base_class, $_) } grep { $_ !~ /^#/ } @_ ); } =head2 load_own_components( @comps ) Similar to L, but assumes every class is C<"$class::$comp">. =cut sub load_own_components { my $class = shift; $class->_load_components( map { "${class}::$_" } grep { $_ !~ /^#/ } @_ ); } sub _load_components { my $class = shift; return unless @_; $class->ensure_class_loaded($_) for @_; $class->inject_base($class => @_); Class::C3::reinitialize(); } =head2 load_optional_components As L, but will silently ignore any components that cannot be found. =cut sub load_optional_components { my $class = shift; $class->_load_components( grep { $class->load_optional_class( $_ ) } ( map { /^\+(.*)$/ ? $1 : join ('::', $class->component_base_class, $_) } grep { $_ !~ /^#/ } @_ ) ); } =head2 ensure_class_loaded Given a class name, tests to see if it is already loaded or otherwise defined. If it is not yet loaded, the package is require'd, and an exception is thrown if the class is still not loaded. BUG: For some reason, packages with syntax errors are added to %INC on require =cut sub ensure_class_loaded { my ($class, $f_class) = @_; no strict 'refs'; # ripped from Class::Inspector for speed # note that the order is important (faster items are first) return if ${"${f_class}::VERSION"}; return if @{"${f_class}::ISA"}; my $file = (join ('/', split ('::', $f_class) ) ) . '.pm'; return if $INC{$file}; for ( keys %{"${f_class}::"} ) { return if ( *{"${f_class}::$_"}{CODE} ); } # require always returns true on success # ill-behaved modules might very well obliterate $_ eval { local $_; require($file) } or do { $@ = "Invalid class name '$f_class'" if $f_class =~ $invalid_class; if ($class->can('throw_exception')) { $class->throw_exception($@); } else { Carp::croak $@; } }; return; } =head2 ensure_class_found Returns true if the specified class is installed or already loaded, false otherwise. =cut sub ensure_class_found { #my ($class, $f_class) = @_; require Class::Inspector; return Class::Inspector->loaded($_[1]) || Class::Inspector->installed($_[1]); } =head2 inject_base Does the actual magic of adjusting C<@ISA> on the target module. =cut sub inject_base { my $class = shift; my $target = shift; mro::set_mro($target, 'c3'); for my $comp (reverse @_) { my $apply = do { no strict 'refs'; sub { unshift ( @{"${target}::ISA"}, $comp ) }; }; unless ($target eq $comp || $target->isa($comp)) { our %APPLICATOR_FOR; if (my $apply_class = List::Util::first { $APPLICATOR_FOR{$_} } @{mro::get_linear_isa($comp)} ) { $APPLICATOR_FOR{$apply_class}->_apply_component_to_class($comp,$target,$apply); } else { $apply->(); } } } } =head2 load_optional_class Returns a true value if the specified class is installed and loaded successfully, throws an exception if the class is found but not loaded successfully, and false if the class is not installed =cut sub load_optional_class { my ($class, $f_class) = @_; # ensure_class_loaded either returns a () (*not* true) or throws eval { $class->ensure_class_loaded($f_class); 1; } && return 1; my $err = $@; # so we don't lose it if ($f_class =~ $invalid_class) { $err = "Invalid class name '$f_class'"; } else { my $fn = quotemeta( (join ('/', split ('::', $f_class) ) ) . '.pm' ); return 0 if ($err =~ /Can't locate ${fn} in \@INC/ ); } if ($class->can('throw_exception')) { $class->throw_exception($err); } else { die $err; } } =head1 AUTHORS Matt S. Trout and the L Pulled out into separate module by Ash Berlin C<< >> Optimizations and overall bolt-tightening by Peter "ribasushi" Rabbitson C<< >> =head1 COPYRIGHT Copyright (c) 2006 - 2011 the Class::C3::Componentised L as listed above. =head1 LICENSE You may distribute this code under the same terms as Perl itself. =cut 1; Class-C3-Componentised-1.001002/Makefile.PL0000644000000000000000000000637713244014310020150 0ustar00rootwheel00000000000000use strict; use warnings FATAL => 'all'; use 5.006002; my %META = ( name => 'Class-C3-Componentised', license => 'perl_5', prereqs => { configure => { requires => { 'ExtUtils::MakeMaker' => 0, } }, build => { requires => { } }, test => { requires => { 'Test::Exception' => '0.31', 'Test::More' => '0.96', }, }, runtime => { requires => { 'perl' => '5.006002', 'MRO::Compat' => '0.09', 'Class::Inspector' => '1.32', # we don't actually need Class::C3. MRO::Compat loads it on 5.8. On 5.10 # it isn't needed. However, some existing code relies on us loading # Class::C3. We don't want to break it just yet. Therefore we depend # directly on Class::C3 as well. 'Class::C3' => '0.20', }, }, develop => { requires => { 'Test::Pod' => '1.14', 'Test::Pod::Coverage' => '1.04', }, }, }, resources => { repository => { url => 'git://git.shadowcat.co.uk/p5sagit/Class-C3-Componentised.git', web => 'https://github.com/p5sagit/Class-C3-Componentised', type => 'git', }, bugtracker => { web => 'https://rt.cpan.org/Public/Dist/Display.html?Name=Class-C3-Componentised', mailto => 'bug-Class-C3-Componentised@rt.cpan.org', }, license => [ 'http://dev.perl.org/licenses/' ], }, no_index => { directory => [ 't', 'xt' ] }, x_authority => "cpan:FREW", dynamic_config => 0, x_static_install => 1, ); my %MM_ARGS = (); ## BOILERPLATE ############################################################### require ExtUtils::MakeMaker; (do './maint/Makefile.PL.include' or die $@) unless -f 'META.yml'; # have to do this since old EUMM dev releases miss the eval $VERSION line my $eumm_version = eval $ExtUtils::MakeMaker::VERSION; my $mymeta = $eumm_version >= 6.57_02; my $mymeta_broken = $mymeta && $eumm_version < 6.57_07; ($MM_ARGS{NAME} = $META{name}) =~ s/-/::/g; ($MM_ARGS{VERSION_FROM} = "lib/$MM_ARGS{NAME}.pm") =~ s{::}{/}g; $META{license} = [ $META{license} ] if $META{license} && !ref $META{license}; $MM_ARGS{LICENSE} = $META{license}[0] if $META{license} && $eumm_version >= 6.30; $MM_ARGS{NO_MYMETA} = 1 if $mymeta_broken; $MM_ARGS{META_ADD} = { 'meta-spec' => { version => 2 }, %META } unless -f 'META.yml'; $MM_ARGS{PL_FILES} ||= {}; $MM_ARGS{NORECURS} = 1 if not exists $MM_ARGS{NORECURS}; for (qw(configure build test runtime)) { my $key = $_ eq 'runtime' ? 'PREREQ_PM' : uc $_.'_REQUIRES'; my $r = $MM_ARGS{$key} = { %{$META{prereqs}{$_}{requires} || {}}, %{delete $MM_ARGS{$key} || {}}, }; defined $r->{$_} or delete $r->{$_} for keys %$r; } $MM_ARGS{MIN_PERL_VERSION} = delete $MM_ARGS{PREREQ_PM}{perl} || 0; delete $MM_ARGS{MIN_PERL_VERSION} if $eumm_version < 6.47_01; $MM_ARGS{BUILD_REQUIRES} = {%{$MM_ARGS{BUILD_REQUIRES}}, %{delete $MM_ARGS{TEST_REQUIRES}}} if $eumm_version < 6.63_03; $MM_ARGS{PREREQ_PM} = {%{$MM_ARGS{PREREQ_PM}}, %{delete $MM_ARGS{BUILD_REQUIRES}}} if $eumm_version < 6.55_01; delete $MM_ARGS{CONFIGURE_REQUIRES} if $eumm_version < 6.51_03; ExtUtils::MakeMaker::WriteMakefile(%MM_ARGS); ## END BOILERPLATE ########################################################### Class-C3-Componentised-1.001002/MANIFEST0000644000000000000000000000126613244015227017327 0ustar00rootwheel00000000000000Changes lib/Class/C3/Componentised.pm lib/Class/C3/Componentised/ApplyHooks.pm Makefile.PL MANIFEST This list of files t/00-load.t t/01-basic.t t/02-explicit.t t/03-on-apply.t t/03-unstable_dollar_underscore.t t/04-on-apply-use-base.t t/lib/AnotherModule.pm t/lib/DestroyDollarUnderscore.pm t/lib/MyModule.pm t/lib/MyModule/ErrorComponent.pm t/lib/MyModule/OwnComponent.pm t/lib/MyModule/Plugin/Foo.pm t/lib/MyModuleNoBase.pm xt/pod-coverage.t xt/pod.t META.yml Module YAML meta-data (added by MakeMaker) META.json Module JSON meta-data (added by MakeMaker) README README file (added by Distar) Class-C3-Componentised-1.001002/META.json0000644000000000000000000000346313244015227017620 0ustar00rootwheel00000000000000{ "abstract" : "Load mix-ins or components to your C3-based class", "author" : [ "Ash Berlin " ], "dynamic_config" : 0, "generated_by" : "ExtUtils::MakeMaker version 7.3, CPAN::Meta::Converter version 2.150010", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "Class-C3-Componentised", "no_index" : { "directory" : [ "t", "xt" ] }, "prereqs" : { "build" : { "requires" : {} }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "develop" : { "requires" : { "Test::Pod" : "1.14", "Test::Pod::Coverage" : "1.04" } }, "runtime" : { "requires" : { "Class::C3" : "0.20", "Class::Inspector" : "1.32", "MRO::Compat" : "0.09", "perl" : "5.006002" } }, "test" : { "requires" : { "Test::Exception" : "0.31", "Test::More" : "0.96" } } }, "release_status" : "stable", "resources" : { "bugtracker" : { "mailto" : "bug-Class-C3-Componentised@rt.cpan.org", "web" : "https://rt.cpan.org/Public/Dist/Display.html?Name=Class-C3-Componentised" }, "license" : [ "http://dev.perl.org/licenses/" ], "repository" : { "type" : "git", "url" : "git://git.shadowcat.co.uk/p5sagit/Class-C3-Componentised.git", "web" : "https://github.com/p5sagit/Class-C3-Componentised" } }, "version" : "1.001002", "x_authority" : "cpan:FREW", "x_serialization_backend" : "JSON::PP version 2.97001", "x_static_install" : 1 } Class-C3-Componentised-1.001002/META.yml0000644000000000000000000000164113244015227017444 0ustar00rootwheel00000000000000--- abstract: 'Load mix-ins or components to your C3-based class' author: - 'Ash Berlin ' build_requires: Test::Exception: '0.31' Test::More: '0.96' configure_requires: ExtUtils::MakeMaker: '0' dynamic_config: 0 generated_by: 'ExtUtils::MakeMaker version 7.3, CPAN::Meta::Converter version 2.150010' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: Class-C3-Componentised no_index: directory: - t - xt requires: Class::C3: '0.20' Class::Inspector: '1.32' MRO::Compat: '0.09' perl: '5.006002' resources: bugtracker: https://rt.cpan.org/Public/Dist/Display.html?Name=Class-C3-Componentised license: http://dev.perl.org/licenses/ repository: git://git.shadowcat.co.uk/p5sagit/Class-C3-Componentised.git version: '1.001002' x_authority: cpan:FREW x_serialization_backend: 'CPAN::Meta::YAML version 0.018' x_static_install: 1 Class-C3-Componentised-1.001002/README0000644000000000000000000000451313244015227017054 0ustar00rootwheel00000000000000NAME Class::C3::Componentised - Load mix-ins or components to your C3-based class SYNOPSIS package MyModule; use strict; use warnings; use base 'Class::C3::Componentised'; sub component_base_class { "MyModule::Component" } package main; MyModule->load_components( qw/Foo Bar/ ); # Will load MyModule::Component::Foo and MyModule::Component::Bar DESCRIPTION This will inject base classes to your module using the Class::C3 method resolution order. Please note: these are not plugins that can take precedence over methods declared in MyModule. If you want something like that, consider MooseX::Object::Pluggable. METHODS load_components( @comps ) Loads the given components into the current module. If a module begins with a "+" character, it is taken to be a fully qualified class name, otherwise "$class->component_base_class" is prepended to it. Calling this will call "Class::C3::reinitialize". load_own_components( @comps ) Similar to load_components, but assumes every class is "$class::$comp". load_optional_components As load_components, but will silently ignore any components that cannot be found. ensure_class_loaded Given a class name, tests to see if it is already loaded or otherwise defined. If it is not yet loaded, the package is require'd, and an exception is thrown if the class is still not loaded. BUG: For some reason, packages with syntax errors are added to %INC on require ensure_class_found Returns true if the specified class is installed or already loaded, false otherwise. inject_base Does the actual magic of adjusting @ISA on the target module. load_optional_class Returns a true value if the specified class is installed and loaded successfully, throws an exception if the class is found but not loaded successfully, and false if the class is not installed AUTHORS Matt S. Trout and the DBIx::Class team Pulled out into separate module by Ash Berlin "" Optimizations and overall bolt-tightening by Peter "ribasushi" Rabbitson "" COPYRIGHT Copyright (c) 2006 - 2011 the Class::C3::Componentised "AUTHORS" as listed above. LICENSE You may distribute this code under the same terms as Perl itself. Class-C3-Componentised-1.001002/t/0000755000000000000000000000000013244015226016433 5ustar00rootwheel00000000000000Class-C3-Componentised-1.001002/t/00-load.t0000644000000000000000000000031013241316232017744 0ustar00rootwheel00000000000000use strict; use warnings; use Test::More tests => 1; BEGIN { use_ok( 'Class::C3::Componentised' ); } diag( "Testing Class::C3::Componentised $Class::C3::Componentised::VERSION, Perl $], $^X" ); Class-C3-Componentised-1.001002/t/01-basic.t0000644000000000000000000000676713241316232020135 0ustar00rootwheel00000000000000use strict; use warnings; use FindBin; use Test::More; use Test::Exception; use Class::Inspector; use lib "$FindBin::Bin/lib"; plan tests => 25; BEGIN { package TestPackage::A; sub some_method {} } use_ok('MyModule'); MyModule->load_components('Foo'); # Clear down inc so ppl dont mess us up with installing modules that we # expect not to exist #@INC = (); # This breaks Carp1.08/perl 5.10.0; bah throws_ok { MyModule->load_components('+ClassC3ComponentFooThatShouldntExist'); } qr/^Can't locate ClassC3ComponentFooThatShouldntExist.pm in \@INC/; is(MyModule->new->message, "Foo MyModule", "it worked"); ok( MyModule->ensure_class_found('MyModule::Plugin::Foo'), 'loaded package MyModule::Plugin::Foo was found' ); ok( !Class::Inspector->loaded('MyModule::OwnComponent'), 'MyModule::OwnComponent not loaded yet' ); ok( MyModule->ensure_class_found('MyModule::OwnComponent'), 'package MyModule::OwnComponent was found' ); ok( !Class::Inspector->loaded('MyModule::OwnComponent'), 'MyModule::OwnComponent not loaded by ensure_class_found()' ); ok( MyModule->ensure_class_found('TestPackage::A'), 'anonymous package TestPackage::A found' ); ok( !MyModule->ensure_class_found('FAKE::WONT::BE::FOUND'), 'fake package not found' ); # Test load_optional_class my $retval = eval { MyModule->load_optional_class('ANOTHER::FAKE::PACKAGE') }; ok( !$@, 'load_optional_class on a nonexistent class did not throw' ); ok( !$retval, 'nonexistent package not loaded' ); $retval = eval { MyModule->load_optional_class('MyModule::OwnComponent') }; ok( !$@, 'load_optional_class on an existing class did not throw' ); ok( $retval, 'MyModule::OwnComponent loaded' ); throws_ok ( sub { MyModule->load_optional_class('MyModule::ErrorComponent') }, qr/did not return a true value/, 'MyModule::ErrorComponent threw ok' ); eval { MyModule->load_optional_class('ENDS::WITH::COLONS::') }; like( $@, qr/Invalid class name 'ENDS::WITH::COLONS::'/, 'Throw on Class::' ); # Simulate a PAR environment { my @code; local @INC = @INC; unshift @INC, sub { if ($_[1] =~ m{^VIRTUAL/PAR/PACKAGE[0-9]*\.pm$}) { return (sub { return 0 unless @code; $_ = shift @code; 1; } ); } else { return (); } }; $retval = eval { MyModule->load_optional_class('FAKE::PAR::PACKAGE') }; ok( !$@, 'load_optional_class on a nonexistent PAR class did not throw' ); ok( !$retval, 'nonexistent PAR package not loaded' ); # simulate a class which does load but does not return true @code = ( q/package VIRTUAL::PAR::PACKAGE1;/, q/0;/, ); $retval = eval { MyModule->load_optional_class('VIRTUAL::PAR::PACKAGE1') }; ok( $@, 'load_optional_class of a no-true-returning PAR module did throw' ); ok( !$retval, 'no-true-returning PAR package not loaded' ); # simulate a normal class @code = ( q/package VIRTUAL::PAR::PACKAGE2;/, q/1;/, ); $retval = eval { MyModule->load_optional_class('VIRTUAL::PAR::PACKAGE2') }; ok( !$@, 'load_optional_class of a PAR module did not throw' ); ok( $retval, 'PAR package "loaded"' ); # see if we can still load stuff with the coderef present $retval = eval { MyModule->load_optional_class('AnotherModule') }; ok( !$@, 'load_optional_class did not throw' ) || diag $@; ok( $retval, 'AnotherModule loaded' ); @code = ( q/package VIRTUAL::PAR::PACKAGE3;/, q/1;/, ); $retval = eval { MyModule->ensure_class_found('VIRTUAL::PAR::PACKAGE3') }; ok( !$@, 'ensure_class_found of a PAR module did not throw' ); ok( $retval, 'PAR package "found"' ); } Class-C3-Componentised-1.001002/t/02-explicit.t0000644000000000000000000000207413241041202020651 0ustar00rootwheel00000000000000use strict; use warnings; use FindBin; use Test::More; use Test::Exception; use lib "$FindBin::Bin/lib"; plan tests => 7; use_ok('MyModuleNoBase'); is(MyModuleNoBase->new->message, " MyModuleNoBase", "initial message matches"); lives_ok ( sub { MyModuleNoBase->load_components('+MyModule::Plugin::Foo') }, 'explicit load_components does not throw', ); is(MyModuleNoBase->new->message, "Foo MyModuleNoBase", "component works"); throws_ok ( sub { MyModuleNoBase->load_components('ClassC3ComponentFooThatShouldntExist') }, qr/Can't locate object method "component_base_class"/, 'non-explicit component specification fails without component_base_class()', ); throws_ok ( sub { MyModuleNoBase->load_optional_components('ClassC3ComponentFooThatShouldntExist') }, qr/Can't locate object method "component_base_class"/, 'non-explicit component specification fails without component_base_class()', ); lives_ok ( sub { MyModuleNoBase->load_optional_components('+ClassC3ComponentFooThatShouldntExist') }, 'explicit optional component specification does not throw', ); Class-C3-Componentised-1.001002/t/03-on-apply.t0000644000000000000000000000255413241041202020573 0ustar00rootwheel00000000000000use strict; use warnings; use FindBin; use Test::More; use Test::Exception; use lib "$FindBin::Bin/lib"; my $awesome_robot = 0; my $first = 0; my $last = 0; BEGIN { package MyModule::Plugin::TestActions; use Class::C3::Componentised::ApplyHooks; BEFORE_APPLY { $awesome_robot++; $first = $awesome_robot }; BEFORE_APPLY { $awesome_robot++; $first = $awesome_robot }; AFTER_APPLY { $awesome_robot++; $last = $awesome_robot }; 1; } BEGIN { package MyModule::Plugin::TestActionDie; use Class::C3::Componentised::ApplyHooks -before_apply => sub { die 'this component is not applicable (yuk yuk yuk)' }; 1; } BEGIN { package MyModule::Plugin::TestActionLoadFrew; use Class::C3::Componentised::ApplyHooks; BEFORE_APPLY { $_[0]->load_components('TestActionFrew') }; 1; } BEGIN { package MyModule::Plugin::TestActionFrew; sub frew { 1 } 1; } use_ok('MyModule'); is( $first, 0, 'first starts at zero' ); is( $last, 0, 'last starts at zero' ); MyModule->load_components('TestActions'); is( $first, 2, 'first gets value of 1 (it runs first)' ); is( $last, 3, 'last gets value of 2 (it runs last)' ); dies_ok { MyModule->load_components('TestActionDie') } 'die from BEFORE_APPLY works'; dies_ok { MyModule->frew } 'fREW is not loaded'; MyModule->load_components('TestActionLoadFrew'); is( MyModule->frew, 1, 'fREW is loaded' ); done_testing; Class-C3-Componentised-1.001002/t/03-unstable_dollar_underscore.t0000644000000000000000000000046313241041202024434 0ustar00rootwheel00000000000000use strict; use warnings; use Class::C3::Componentised; use Test::More; use FindBin; use lib "$FindBin::Bin/lib"; my @mods = 'DestroyDollarUnderscore'; for (@mods) { Class::C3::Componentised->ensure_class_loaded($_); } is_deeply(\@mods, [ 'DestroyDollarUnderscore' ], '$_ untouched'); done_testing; Class-C3-Componentised-1.001002/t/04-on-apply-use-base.t0000644000000000000000000000354413241041202022276 0ustar00rootwheel00000000000000use strict; use warnings; use FindBin; use Test::More; use Test::Exception; use lib "$FindBin::Bin/lib"; BEGIN { package A::First; use Class::C3::Componentised::ApplyHooks; AFTER_APPLY { $_[0]->after("a $_[1]") }; AFTER_APPLY { $_[0]->after("b $_[1]") }; BEFORE_APPLY { $_[0]->before("a $_[1]") }; BEFORE_APPLY { $_[0]->before("b $_[1]") }; 1; } BEGIN { package A::Second; use base 'A::First'; use Class::C3::Componentised::ApplyHooks -after_apply => sub { $_[0]->after("a $_[1]") }, -before_apply => sub { $_[0]->before("a $_[1]") }, qw(BEFORE_APPLY AFTER_APPLY); AFTER_APPLY { $_[0]->after("b $_[1]") }; BEFORE_APPLY { $_[0]->before("b $_[1]") }; 1; } BEGIN { package A::Third; use base 'A::Second'; 1; } BEGIN { package A::Class::Second; use base 'Class::C3::Componentised'; use Test::More; our @before; our @after; sub component_base_class { 'A' } __PACKAGE__->load_components('Second'); sub before { push @before, $_[1] } sub after { push @after, $_[1] } is_deeply(\@before, [ 'b A::Second', 'a A::Second', 'b A::First', 'a A::First', ], 'before runs in the correct order'); is_deeply(\@after, [ 'a A::First', 'b A::First', 'a A::Second', 'b A::Second', ], 'after runs in the correct order'); } BEGIN { package A::Class::Third; use base 'Class::C3::Componentised'; use Test::More; our @before; our @after; sub component_base_class { 'A' } __PACKAGE__->load_components('Third'); sub before { push @before, $_[1] } sub after { push @after, $_[1] } is_deeply(\@before, [ 'b A::Second', 'a A::Second', 'b A::First', 'a A::First', ], 'before runs in the correct order'); is_deeply(\@after, [ 'a A::First', 'b A::First', 'a A::Second', 'b A::Second', ], 'after runs in the correct order'); } done_testing; Class-C3-Componentised-1.001002/t/lib/0000755000000000000000000000000013244015226017201 5ustar00rootwheel00000000000000Class-C3-Componentised-1.001002/t/lib/AnotherModule.pm0000644000000000000000000000003213241316232022276 0ustar00rootwheel00000000000000package AnotherModule; 1; Class-C3-Componentised-1.001002/t/lib/DestroyDollarUnderscore.pm0000644000000000000000000000011413241316232024352 0ustar00rootwheel00000000000000package DestroyDollarUnderscore; use strict; use warnings; undef ($_); 1; Class-C3-Componentised-1.001002/t/lib/MyModule/0000755000000000000000000000000013244015226020734 5ustar00rootwheel00000000000000Class-C3-Componentised-1.001002/t/lib/MyModule/ErrorComponent.pm0000644000000000000000000000016613241316232024247 0ustar00rootwheel00000000000000package # hide from PAUSE MyModule::ErrorComponent; use strict; use warnings; # this is missing on purpose # 1; Class-C3-Componentised-1.001002/t/lib/MyModule/OwnComponent.pm0000644000000000000000000000032113241316232023712 0ustar00rootwheel00000000000000package # hide from pause MyModule::OwnComponent; use strict; use warnings; use MRO::Compat; use mro 'c3'; sub message { my $self = shift; return join(" ", "OwnComponent", $self->next::method); } 1; Class-C3-Componentised-1.001002/t/lib/MyModule/Plugin/0000755000000000000000000000000013244015226022172 5ustar00rootwheel00000000000000Class-C3-Componentised-1.001002/t/lib/MyModule/Plugin/Foo.pm0000644000000000000000000000021313241316232023245 0ustar00rootwheel00000000000000package # hide from pause MyModule::Plugin::Foo; use strict; use warnings; use MRO::Compat; use mro 'c3'; sub message { "Foo"; } 1; Class-C3-Componentised-1.001002/t/lib/MyModule.pm0000644000000000000000000000044713241316232021275 0ustar00rootwheel00000000000000package # hide from pause MyModule; use strict; use warnings; use base 'Class::C3::Componentised'; sub component_base_class { "MyModule::Plugin" } sub message { my $msg = $_[0]->maybe::next::method() || ''; return $msg . ' ' . __PACKAGE__; } sub new { return bless {}, shift; } 1; Class-C3-Componentised-1.001002/t/lib/MyModuleNoBase.pm0000644000000000000000000000037413241316232022364 0ustar00rootwheel00000000000000package # hide from pause MyModuleNoBase; use strict; use warnings; use base 'Class::C3::Componentised'; sub message { my $msg = $_[0]->maybe::next::method() || ''; return $msg . ' ' . __PACKAGE__; } sub new { return bless {}, shift; } 1; Class-C3-Componentised-1.001002/xt/0000755000000000000000000000000013244015226016623 5ustar00rootwheel00000000000000Class-C3-Componentised-1.001002/xt/pod-coverage.t0000644000000000000000000000012013241316232021352 0ustar00rootwheel00000000000000#!perl -T use Test::More; use Test::Pod::Coverage 1.04; all_pod_coverage_ok(); Class-C3-Componentised-1.001002/xt/pod.t0000644000000000000000000000010313241316232017562 0ustar00rootwheel00000000000000#!perl -T use Test::More; use Test::Pod 1.14; all_pod_files_ok();