Cleanup C3 handling, require updated Class::C3::Componentised
Peter Rabbitson [Mon, 31 Jan 2011 12:29:53 +0000 (13:29 +0100)]
Changes
Makefile.PL
lib/DBIx/Class.pm
lib/DBIx/Class/Admin/Usage.pm
lib/DBIx/Class/Manual/Component.pod
lib/DBIx/Class/Schema.pm
lib/DBIx/Class/Storage/DBI.pm
lib/DBIx/Class/Storage/DBI/Sybase/MSSQL.pm
lib/DBIx/Class/Storage/DBI/Sybase/Microsoft_SQL_Server.pm
t/04_c3_mro.t [moved from t/04dont_break_c3.t with 68% similarity]
t/storage/txn_scope_guard.t

diff --git a/Changes b/Changes
index 079159b..1d06025 100644 (file)
--- a/Changes
+++ b/Changes
@@ -9,6 +9,7 @@ Revision history for DBIx::Class
           plain ::Storage::DBI
 
     * Fixes
+        - Fix ::Storage::DBI::* MRO problems on 5.8.x perls
         - Disable mysql_auto_reconnect for MySQL - depending on the ENV
           it sometimes defaults to on and causes major borkage on older
           DBD::mysql versions
@@ -21,6 +22,9 @@ Revision history for DBIx::Class
         - Fix reverse_relationship_info on prototypical result sources
           (sources not yet registered with a schema)
 
+    * Misc
+        - Only load Class::C3 and friends if necessary ($] < 5.010)
+
 0.08127 2011-01-19 16:40 (UTC)
     * New Features / Changes
         - Schema/resultsource instances are now crossreferenced via a new
index 1c3fdf6..71b477f 100644 (file)
@@ -58,7 +58,7 @@ my $test_requires = {
 my $runtime_requires = {
   'Carp::Clan'               => '6.0',
   'Class::Accessor::Grouped' => '0.10002',
-  'Class::C3::Componentised' => '1.0005',
+  'Class::C3::Componentised' => '1.0008',
   'Class::Inspector'         => '1.24',
   'Config::Any'              => '0.20',
   'Context::Preserve'        => '0.01',
index 0b11c0b..c8681b7 100644 (file)
@@ -3,7 +3,17 @@ package DBIx::Class;
 use strict;
 use warnings;
 
-use MRO::Compat;
+BEGIN {
+  if ($] < 5.009_005) {
+    require MRO::Compat;
+    *DBIx::Class::_ENV_::OLD_MRO = sub () { 1 };
+  }
+  else {
+    require mro;
+    *DBIx::Class::_ENV_::OLD_MRO = sub () { 0 };
+  }
+}
+
 use mro 'c3';
 
 use DBIx::Class::Optional::Dependencies;
index ddd925a..ce41a56 100644 (file)
@@ -6,8 +6,6 @@ use base 'Getopt::Long::Descriptive::Usage';
 
 use base 'Class::Accessor::Grouped';
 
-use Class::C3;
-
 __PACKAGE__->mk_group_accessors('simple', 'synopsis', 'short_description');
 
 sub prog_name {
index dfa9f94..46170f9 100644 (file)
@@ -69,11 +69,9 @@ that are loaded first are the first ones in the inheritance stack.  So, if
 you override insert() but the DBIx::Class::Row component is loaded first
 then your insert() will never be called, since the DBIx::Class::Row insert()
 will be called first.  If you are unsure as to why a given method is not
-being called try printing out the Class::C3 inheritance stack.
+being called try printing out the current linearized MRO.
 
-  print join ', ' => Class::C3::calculateMRO('YourClass::Name');
-
-Check out the L<Class::C3> docs for more information about inheritance.
+  print join ', ' => mro::get_linear_isa('YourClass::Name');
 
 =head1 EXISTING COMPONENTS
 
index 4dbe059..fbfd15b 100644 (file)
@@ -240,9 +240,9 @@ sub load_namespaces {
 
   my @to_register;
   {
-    no warnings 'redefine';
-    local *Class::C3::reinitialize = sub { };
-    use warnings 'redefine';
+    no warnings qw/redefine/;
+    local *Class::C3::reinitialize = sub { } if DBIx::Class::_ENV_::OLD_MRO;
+    use warnings qw/redefine/;
 
     # ensure classes are loaded and attached in inheritance order
     for my $res (values %results) {
@@ -295,7 +295,8 @@ sub load_namespaces {
       . 'corresponding Result class';
   }
 
-  Class::C3->reinitialize;
+  Class::C3->reinitialize if DBIx::Class::_ENV_::OLD_MRO;
+
   $class->register_class(@$_) for (@to_register);
 
   return;
@@ -378,7 +379,9 @@ sub load_classes {
   my @to_register;
   {
     no warnings qw/redefine/;
-    local *Class::C3::reinitialize = sub { };
+    local *Class::C3::reinitialize = sub { } if DBIx::Class::_ENV_::OLD_MRO;
+    use warnings qw/redefine/;
+
     foreach my $prefix (keys %comps_for) {
       foreach my $comp (@{$comps_for{$prefix}||[]}) {
         my $comp_class = "${prefix}::${comp}";
@@ -395,7 +398,7 @@ sub load_classes {
       }
     }
   }
-  Class::C3->reinitialize;
+  Class::C3->reinitialize if DBIx::Class::_ENV_::OLD_MRO;
 
   foreach my $to (@to_register) {
     $class->register_class(@$to);
@@ -907,8 +910,10 @@ sub compose_namespace {
   my $schema = $self->clone;
   {
     no warnings qw/redefine/;
+    local *Class::C3::reinitialize = sub { } if DBIx::Class::_ENV_::OLD_MRO;
+    use warnings qw/redefine/;
+
     no strict qw/refs/;
-#    local *Class::C3::reinitialize = sub { };
     foreach my $moniker ($schema->sources) {
       my $source = $schema->source($moniker);
       my $target_class = "${target}::${moniker}";
@@ -927,7 +932,7 @@ sub compose_namespace {
      $schema->register_source($moniker, $source);
     }
   }
-#  Class::C3->reinitialize();
+  Class::C3->reinitialize() if DBIx::Class::_ENV_::OLD_MRO;
   {
     no strict 'refs';
     no warnings 'redefine';
index 6278956..99befac 100644 (file)
@@ -1211,6 +1211,8 @@ sub _determine_driver {
 
     $self->_driver_determined(1);
 
+    Class::C3->reinitialize() if DBIx::Class::_ENV_::OLD_MRO;
+
     $self->_init; # run driver-specific initializations
 
     $self->_run_connection_actions
index bd833df..04eda45 100644 (file)
@@ -37,11 +37,6 @@ This subclass supports MSSQL connected via L<DBD::Sybase>.
   $schema->storage_type('::DBI::Sybase::MSSQL');
   $schema->connect_info('dbi:Sybase:....', ...);
 
-=head1 BUGS
-
-Currently, this doesn't work right unless you call C<Class::C3::reinitialize()>
-after connecting.
-
 =head1 AUTHORS
 
 Brandon L Black <blblack@gmail.com>
index 5f904d8..4b55929 100644 (file)
@@ -10,9 +10,6 @@ use base qw/
 use mro 'c3';
 use Carp::Clan qw/^DBIx::Class/;
 
-# Temporary fix for mysterious MRO fail on 5.8 perls
-Class::C3::reinitialize if $] < '5.01';
-
 sub _rebless {
   my $self = shift;
   my $dbh  = $self->_get_dbh;
similarity index 68%
rename from t/04dont_break_c3.t
rename to t/04_c3_mro.t
index 6a8496d..3224b5b 100644 (file)
@@ -2,10 +2,9 @@ use warnings;
 use strict;
 
 use Test::More;
-use MRO::Compat;
 
 use lib qw(t/lib);
-use DBICTest; # do not remove even though it is not used
+use DBICTest; # do not remove even though it is not used (pulls in MRO::Compat if needed)
 
 {
   package AAA;
@@ -38,7 +37,6 @@ eval { mro::get_linear_isa('CCC'); };
 ok (! $@, "Correctly skipped injecting an indirect parent of class BBB");
 
 use DBIx::Class::Storage::DBI::Sybase::Microsoft_SQL_Server;
-use B;
 
 is_deeply (
   mro::get_linear_isa('DBIx::Class::Storage::DBI::Sybase::Microsoft_SQL_Server'),
@@ -58,11 +56,20 @@ is_deeply (
   'Correctly ordered ISA of DBIx::Class::Storage::DBI::Sybase::Microsoft_SQL_Server'
 );
 
-my $dialect_ref = DBIx::Class::Storage::DBI::Sybase::Microsoft_SQL_Server->can('sql_limit_dialect');
+my $storage = DBIx::Class::Storage::DBI::Sybase::Microsoft_SQL_Server->new;
+$storage->_determine_driver;
 is (
-  B::svref_2object($dialect_ref)->GV->STASH->NAME,
-  'DBIx::Class::Storage::DBI::MSSQL',
+  $storage->can('sql_limit_dialect'),
+  'DBIx::Class::Storage::DBI::MSSQL'->can('sql_limit_dialect'),
   'Correct method picked'
 );
 
+if ($] >= 5.010) {
+  ok (! $INC{'Class/C3.pm'}, 'No Class::C3 loaded on perl 5.10+');
+
+  # Class::C3::Componentised loads MRO::Compat unconditionally to satisfy
+  # the assumption that once Class::C3::X is loaded, so is Class::C3
+  #ok (! $INC{'MRO/Compat.pm'}, 'No MRO::Compat loaded on perl 5.10+');
+}
+
 done_testing;
index f79ff8d..03985b3 100644 (file)
@@ -92,7 +92,9 @@ use DBICTest;
 
   no strict 'refs';
   no warnings 'redefine';
+
   local *{DBIx::Class::Storage::DBI::txn_rollback} = sub { die 'die die my darling' };
+  Class::C3->reinitialize() if DBIx::Class::_ENV_::OLD_MRO;
 
   throws_ok (sub {
     my $guard = $schema->txn_scope_guard;
@@ -120,6 +122,7 @@ use DBICTest;
   no strict 'refs';
   no warnings 'redefine';
   local *{DBIx::Class::Storage::DBI::txn_rollback} = sub { die 'die die my darling' };
+  Class::C3->reinitialize() if DBIx::Class::_ENV_::OLD_MRO;
 
 #The warn from within a DESTROY callback freaks out Test::Warn, do it old-school
 =begin