X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2F_Util.pm;h=31f038f377f5c6f8fb5e9ed40253f56960bd5f2e;hb=2ff0298236251060746c44fad5bec5ece455c35c;hp=09fdfe95ab7e25bbec0727bf058c2115b5041191;hpb=4b1b44c16347a9f7a404a390983782cc5625e355;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/_Util.pm b/lib/DBIx/Class/_Util.pm index 09fdfe9..31f038f 100644 --- a/lib/DBIx/Class/_Util.pm +++ b/lib/DBIx/Class/_Util.pm @@ -1,6 +1,8 @@ package # hide from PAUSE DBIx::Class::_Util; +use DBIx::Class::StartupCheck; # load es early as we can, usually a noop + use warnings; use strict; @@ -80,8 +82,8 @@ use B (); use Carp 'croak'; use Storable 'nfreeze'; use Scalar::Util qw(weaken blessed reftype refaddr); -use List::Util qw(first); -use Sub::Quote qw(qsub quote_sub); +use Sub::Quote qw(qsub); +use Sub::Name (); # Already correctly prototyped: perlbrew exec perl -MStorable -e 'warn prototype \&Storable::dclone' BEGIN { *deep_clone = \&Storable::dclone } @@ -90,7 +92,7 @@ use base 'Exporter'; our @EXPORT_OK = qw( sigwarn_silencer modver_gt_or_eq modver_gt_or_eq_and_lt fail_on_internal_wantarray fail_on_internal_call - refdesc refcount hrefaddr + refdesc refcount hrefaddr set_subname scope_guard detected_reinvoked_destructor is_exception dbic_internal_try quote_sub qsub perlstring serialize deep_clone dump_value @@ -100,6 +102,70 @@ our @EXPORT_OK = qw( use constant UNRESOLVABLE_CONDITION => \ '1 = 0'; +BEGIN { + # add preliminary attribute support + # FIXME FIXME FIXME + # To be revisited when Moo with proper attr support ships + Sub::Quote->VERSION(2.002); + require attributes; +} +# Override forcing no_defer, and adding naming consistency checks +sub quote_sub { + Carp::confess( "Anonymous quoting not supported by the DBIC sub_quote override - supply a sub name" ) if + @_ < 2 + or + ! defined $_[1] + or + length ref $_[1] + ; + + Carp::confess( "The DBIC sub_quote override expects sub name '$_[0]' to be fully qualified" ) + unless $_[0] =~ /::/; + + Carp::confess( "The DBIC sub_quote override expects the sub name '$_[0]' to match the supplied 'package' argument" ) if + $_[3] + and + defined $_[3]->{package} + and + index( $_[0], $_[3]->{package} ) != 0 + ; + + my @caller = caller(0); + my $sq_opts = { + package => $caller[0], + hints => $caller[8], + warning_bits => $caller[9], + hintshash => $caller[10], + %{ $_[3] || {} }, + + # explicitly forced for everything + no_defer => 1, + }; + + my $cref = Sub::Quote::quote_sub( $_[0], $_[1], $_[2]||{}, $sq_opts ); + + # FIXME FIXME FIXME + # To be revisited when Moo with proper attr support ships + if( + # external application does not work on things like :prototype(...), :lvalue, etc + my @attrs = grep { + $_ !~ /^[a-z]/ + or + Carp::confess( "The DBIC sub_quote override does not support applying of reserved attribute '$_'" ) + } @{ $sq_opts->{attributes} || []} + ) { + Carp::confess( "The DBIC sub_quote override does not allow mixing 'attributes' with 'no_install'" ) + if $sq_opts->{no_install}; + + # might be different from $sq_opts->{package}; + my ($install_into) = $_[0] =~ /(.+)::[^:]+$/; + + attributes->import( $install_into, $cref, @attrs ); + } + + $cref; +} + sub sigwarn_silencer ($) { my $pattern = shift; @@ -134,6 +200,16 @@ sub refcount ($) { B::svref_2object($_[0])->REFCNT; } +# FIXME In another life switch this to a polyfill like the one in namespace::clean +sub set_subname ($$) { + + # fully qualify name + splice @_, 0, 1, caller(0) . "::$_[0]" + if $_[0] !~ /::|'/; + + &Sub::Name::subname; +} + sub serialize ($) { local $Storable::canonical = 1; nfreeze($_[0]); @@ -362,10 +438,13 @@ sub is_exception ($) { my $destruction_registry = {}; sub CLONE { - $destruction_registry = { map - { defined $_ ? ( refaddr($_) => $_ ) : () } - values %$destruction_registry - }; + %$destruction_registry = map { + (defined $_) + ? ( refaddr($_) => $_ ) + : () + } values %$destruction_registry; + + weaken($_) for values %$destruction_registry; # Dummy NEXTSTATE ensuring the all temporaries on the stack are garbage # collected before leaving this scope. Depending on the code above, this @@ -551,8 +630,8 @@ sub mkdir_p ($) { ), 'with_stacktrace'); } - my $mark = []; - weaken ( $list_ctx_ok_stack_marker = $mark ); + weaken( $list_ctx_ok_stack_marker = my $mark = [] ); + $mark; } } @@ -564,7 +643,7 @@ sub fail_on_internal_call { $fr = [ CORE::caller(1) ]; $argdesc = ref $DB::args[0] ? DBIx::Class::_Util::refdesc($DB::args[0]) - : undef + : ( $DB::args[0] . '' ) ; }; @@ -576,7 +655,7 @@ sub fail_on_internal_call { $fr->[1] !~ /\b(?:CDBICompat|ResultSetProxy)\b/ # no point touching there ) { DBIx::Class::Exception->throw( sprintf ( - "Illegal internal call of indirect proxy-method %s() with argument %s: examine the last lines of the proxy method deparse below to determine what to call directly instead at %s on line %d\n\n%s\n\n Stacktrace starts", + "Illegal internal call of indirect proxy-method %s() with argument '%s': examine the last lines of the proxy method deparse below to determine what to call directly instead at %s on line %d\n\n%s\n\n Stacktrace starts", $fr->[3], $argdesc, @{$fr}[1,2], ( $fr->[6] || do { require B::Deparse; no strict 'refs';