From: Graham Knop Date: Mon, 20 Jan 2014 12:58:52 +0000 (-0500) Subject: build variants in eval 'BEGIN { }' to allow namespace::clean to work seamlessly X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=refs%2Fheads%2Fcleanable;hp=39c3689bf807c7cd7a25e67d52658d27efb47e70;p=p5sagit%2FPackage-Variant.git build variants in eval 'BEGIN { }' to allow namespace::clean to work seamlessly --- diff --git a/lib/Package/Variant.pm b/lib/Package/Variant.pm index df1739c..688185b 100644 --- a/lib/Package/Variant.pm +++ b/lib/Package/Variant.pm @@ -1,8 +1,7 @@ package Package::Variant; use strictures 1; -use Import::Into; -use Module::Runtime qw(require_module); +use Module::Runtime qw(require_module module_notional_filename); use Carp qw(croak); our $VERSION = '1.002000'; # 1.2.0 @@ -97,23 +96,28 @@ sub import { sub build_variant_of { my ($me, $variable, @args) = @_; my $variant_name = "${variable}::_Variant_".++$Variable{$variable}{anon}; - foreach my $to_import (@{$Variable{$variable}{args}{importing}}) { - my ($pkg, $args) = @$to_import; - require_module $pkg; - eval q{ BEGIN { $pkg->import::into($variant_name, @{$args}) }; 1; } - or die $@; + my $build = "package $variant_name;\n"; + my $importing = $Variable{$variable}{args}{importing}; + foreach my $i (0 .. $#$importing) { + my $pkg = $importing->[$i][0]; + $build .= "use $pkg \@{\$importing->[$i][1]};\n"; } my $subs = $Variable{$variable}{subs}; - local @{$subs}{keys %$subs} = map $variant_name->can($_), keys %$subs; - local $Variable{$variable}{install} = sub { - my $full_name = "${variant_name}::".shift; + my $builder = sub { + local @{$subs}{keys %$subs} = map $variant_name->can($_), keys %$subs; + local $Variable{$variable}{install} = sub { + my $full_name = "${variant_name}::".shift; - my $ref = $sub_namer->($full_name, @_); - - no strict 'refs'; - *$full_name = $ref; + my $ref = $sub_namer->($full_name, @_); + + no strict 'refs'; + *$full_name = $ref; + }; + $variable->make_variant($variant_name, @args); }; - $variable->make_variant($variant_name, @args); + $build .= "BEGIN { \$builder->() }\n1;\n"; + eval $build or die $@; + $INC{module_notional_filename($variant_name)} = '(built by Package::Variant)'; return $variant_name; } diff --git a/t/40-namespace-clean.t b/t/40-namespace-clean.t new file mode 100644 index 0000000..23ded83 --- /dev/null +++ b/t/40-namespace-clean.t @@ -0,0 +1,21 @@ +use strictures 1; +use Test::More eval { require namespace::clean } ? () + : (skip_all => 'namespace::clean needed for test'); +{ + package CleanVariant; + use Package::Variant + importing => [ + 'Carp' => ['croak'], + 'namespace::clean', + ], + ; + + sub make_variant { + my ($class, $target_package, %arguments) = @_; + my $croak = $target_package->can('croak'); + ::is $croak, \&Carp::croak, 'sub exists while building'; + } +} +my $variant = CleanVariant->build_variant; +is $variant->can('croak'), undef, 'sub cleaned after building'; +done_testing;