[Pdx-pm] too late to run INIT (Class::Trait)

Eric Wilhelm scratchcomputing at gmail.com
Sun Jun 3 02:04:02 PDT 2007


Hi all,

Is there any reliable way to tell if it is "Too late to run INIT"?  All 
I can think of is $^S, but that doesn't seem to be any use.  The 
warning appears to come from op.c, but AFAICT it is playing with some 
"do not touch" bits.

We could all do the local $SIG{__WARN__} dance, but I'm thinking there 
has to be a better way for Class::Trait to make the compile-time 
checking optional.  There's "no warnings 'void'", but it wouldn't be 
able to be conditional.  Can't put the $SIG{__WARN__} in Class::Trait 
because local won't work there.

Could put just the INIT block in Class::Trait::Strict, but that wouldn't 
default to compile-time checking the integrity (though it could maybe 
be made to die (thus being actually strict) but now we're back to the 
same question of whether or not compile-time is done.)

hmm...

  BEGIN {
      our $shutup;
      local $SIG{__WARN__} = sub {
          warn "we had a warning @_\n";
      };
      require Class::Trait::Init unless($shutup);
  }
  sub _do_init {
      initialize() if scalar keys %TRAITS_TO_CHECK;
  }

  # Class::Trait::Strict
  use warnings;
  use strict;
  INIT {
      Class::Trait::_do_init();
  }
  1;

...
  $ perl -e '$Class::Trait::shutup = 1;
  require Class::Trait; print "yay\n"'
  yay
  $ perl -e 'require Class::Trait;'
  we had a warning Too late to run INIT block at Class/Trait/Init.pm
  line 5.

So, we can catch the warning and use qr/^Too late to run INIT/ as a 
flag, possibly then using Class::Trait::Strict::import() (or caller()) 
as an indicator of whether strict trait-checking was explicitly 
requested (thus making runtime use of a trait-bearing class an optional 
fatal error (for the real sticklers))  but still be able to set the 
no-noise variable.  Err, probably just be quiet by default and die if 
anyone explicitly requested that we *must* do compile-time checks.  
OTOH, could we just do the init bit when the SIG{__WARN__} fires?  :-D

Thoughts?   e.g. we have to re-juggle the $SIG{__WARN__} in case some 
warning happens during the _do_init() :-/

Thanks,
Eric

# from Ovid
# on Thursday 31 May 2007 08:57 am:

>You mentioned that you don't use Class::Trait due to the "too late to
> run INIT" warning.  It's an unfortunate problem, but it's one which
> is virtually impossible to avoid due to the way that Perl works.
>  Unfortunately, due to the nature of traits, moving it into
> Class::Trait::Strict isn't an option (the compile-time safety is
> something I need to guarantee).  However, I have the following
> snippet of code in my Test::Class base class and it should give you
> an idea of one way to deal with the problem:
>
>  sub startup : Test(startup) {
>      my $test = shift;
>
>      # If there are any tests in this class using the db, set it up:
>      if($test->_pkg_has_attribute('DB')) {
>          $test->_database( TEST::Database->new );
>      }
>
>      {
>          my $using_traits = 0;
>
>          # Because of how traits work, they need to be loaded at
> compile time # or else their integrity checks fail.  This skips their
> warning and # runs the integrity checks manually if traits are used.
> local $SIG{__WARN__} = sub {
>              my $warning = shift;
>              if ( $warning =~ /Too late to run INIT
> block.*Class\/Trait.pm/ ) { $using_traits = 1;
>                  return;
>              }
>              CORE::warn($warning);
>          };
>          my $class = $test->_class;
>          $class->require or $test->FAIL_ALL("Could not require
> $class: $@"); Class::Trait->initialize if $using_traits;
>      }
>  }
>----- Original Message ----
>From: Eric Wilhelm <scratchcomputing at gmail.com>
>To: Ovid <curtis_ovid_poe at yahoo.com>
>Sent: Friday, October 27, 2006 11:16:10 PM
>Subject: Class::Trait INIT thingy
>
>Hi Ovid,
>
>I have to admit that I ended up not using traits mainly because of the
>"too late to run INIT" warning.  I know it's a nit, but it makes my
>"silence" tests fail :-(  So, I'm using the *idea* of traits, but
> doing it with Exporter.
>
>The unfortunate thing about INIT is that once you mention it, there is
>no way to ignore it.
>
>I wonder if it would be better to put just that INIT block in
>Class::Trait::Strict or something?

-- 
Turns out the optimal technique is to put it in reverse and gun it.
--Steven Squyres (on challenges in interplanetary robot navigation)
---------------------------------------------------
    http://scratchcomputing.com
---------------------------------------------------


More information about the Pdx-pm-list mailing list