Merge branch 'master' into renames-and-deprecations
Dave Rolsky [Sun, 5 Apr 2009 16:20:37 +0000 (11:20 -0500)]
Conflicts:
xt/pod_coverage.t

20 files changed:
Changes
Makefile.PL
README
lib/Class/MOP.pm
lib/Class/MOP/Attribute.pm
lib/Class/MOP/Class.pm
lib/Class/MOP/Immutable.pm
lib/Class/MOP/Instance.pm
lib/Class/MOP/Method.pm
lib/Class/MOP/Method/Accessor.pm
lib/Class/MOP/Method/Constructor.pm
lib/Class/MOP/Method/Generated.pm
lib/Class/MOP/Method/Wrapped.pm
lib/Class/MOP/Module.pm
lib/Class/MOP/Object.pm
lib/Class/MOP/Package.pm
lib/metaclass.pm
t/083_load_class.t
xt/pod_coverage.t
xt/pod_spell.t

diff --git a/Changes b/Changes
index 37bd252..85c130d 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,5 +1,39 @@
 Revision history for Perl extension Class-MOP.
 
+0.81
+    * Makefile.PL
+      - Make sure to preserve any compiler flags already defined in
+        Config.pm. Patch by Vincent Pit. RT #44739.
+
+0.80 Wed, April 1, 2009
+    * Class::MOP::*
+      - Call user_class->meta in fewer places, with the eventual goal
+        of allowing the user to rename or exclude ->meta
+        altogether. Instead uses Class::MOP::class_of. (Sartak)
+
+    * Class::MOP
+      - New class_of function that should be used to retrieve a
+        metaclass. This is unlike get_metaclass_by_name in that it
+        accepts instances, not just class names. (Sartak)
+
+    * Class::MOP
+      - load_first_existing_class didn't actually load the first
+        existing class; instead, it loaded the first existing and
+        compiling class.  It now throws an error if a class exists (in
+        @INC) but fails to compile.  (hdp)
+
+    * Class::MOP
+    * Class::MOP::Class
+      - we had some semi-buggy code that purported to provide a
+        HAS_ISAREV based on whether mro had get_isarev (due to an
+        oversight, it always returned 1). Since mro and MRO::Compat
+        have always had get_isarev, HAS_ISAREV was pointless. This
+        insight simplified the subclasses method by deleting the
+        pure-perl fallback. HAS_ISAREV is now deprecated. (Sartak)
+
+0.79 Fri, March 29, 2009
+    * No changes from 0.78_02.
+
 0.78_02 Thu, March 26, 2009
     * Class::MOP::Class
     * Class::MOP::Immutable
index 6cc4507..ef1680f 100644 (file)
@@ -10,7 +10,8 @@ perl_version '5.008001';
 all_from 'lib/Class/MOP.pm';
 license 'perl';
 
-my $ccflags = ' -I.';
+require Config;
+my $ccflags = ( $Config::Config{ccflags} || '' ) . ' -I.';
 $ccflags .= ' -Wall' if -d '.svn' || -d '.git' || $ENV{MAINTAINER_MODE};
 
 requires 'Carp';
diff --git a/README b/README
index a27f42d..d78a9a5 100644 (file)
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-Class::MOP version 0.78_02
+Class::MOP version 0.80
 ===========================
 
 See the individual module documentation for more information
index 3385712..2f144ba 100644 (file)
@@ -10,7 +10,7 @@ use MRO::Compat;
 
 use Carp          'confess';
 use Devel::GlobalDestruction qw( in_global_destruction );
-use Scalar::Util  'weaken', 'reftype';
+use Scalar::Util  'weaken', 'reftype', 'blessed';
 use Sub::Name qw( subname );
 
 use Class::MOP::Class;
@@ -24,15 +24,16 @@ BEGIN {
         ? sub () { 0 }
         : sub () { 1 };    
 
-    *HAVE_ISAREV = defined(&mro::get_isarev)
-        ? sub () { 1 }
-        : sub () { 1 };
+    sub HAVE_ISAREV () {
+        warn "Class::MOP::HAVE_ISAREV is deprecated and will be removed in a future release. It has always returned 1 anyway.";
+        return 1;
+    }
 
     # this is either part of core or set up appropriately by MRO::Compat
     *check_package_cache_flag = \&mro::get_pkg_gen;
 }
 
-our $VERSION   = '0.78_02';
+our $VERSION   = '0.80';
 our $XS_VERSION = $VERSION;
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';    
@@ -59,6 +60,12 @@ XSLoader::load( __PACKAGE__, $XS_VERSION );
     sub does_metaclass_exist        { exists $METAS{$_[0]} && defined $METAS{$_[0]} }
     sub remove_metaclass_by_name    { $METAS{$_[0]} = undef }
 
+    # This handles instances as well as class names
+    sub class_of {
+        my $class = blessed($_[0]) || $_[0];
+        return $METAS{$class};
+    }
+
     # NOTE:
     # We only cache metaclasses, meaning instances of
     # Class::MOP::Class. We do not cache instance of
@@ -66,6 +73,15 @@ XSLoader::load( __PACKAGE__, $XS_VERSION );
     # because I don't yet see a good reason to do so.
 }
 
+sub _class_to_pmfile {
+    my $class = shift;
+
+    my $file = $class . '.pm';
+    $file =~ s{::}{/}g;
+
+    return $file;
+}
+
 sub load_first_existing_class {
     my @classes = @_
         or return;
@@ -80,10 +96,12 @@ sub load_first_existing_class {
     my $found;
     my %exceptions;
     for my $class (@classes) {
+        my $pmfile = _class_to_pmfile($class);
         my $e = _try_load_one_class($class);
 
         if ($e) {
             $exceptions{$class} = $e;
+            last if $e !~ /^Can't locate \Q$pmfile\E in \@INC/;
         }
         else {
             $found = $class;
@@ -100,6 +118,9 @@ sub load_first_existing_class {
                 "Could not load class (%s) because : %s", $_,
                 $exceptions{$_}
                 )
+            }
+        grep {
+            exists $exceptions{$_}
             } @classes
     );
 }
@@ -109,8 +130,7 @@ sub _try_load_one_class {
 
     return if is_class_loaded($class);
 
-    my $file = $class . '.pm';
-    $file =~ s{::}{/}g;
+    my $file = _class_to_pmfile($class);
 
     return do {
         local $@;
@@ -842,11 +862,6 @@ We set this constant depending on what version perl we are on, this
 allows us to take advantage of new 5.10 features and stay backwards
 compatible.
 
-=item I<Class::MOP::HAVE_ISAREV>
-
-Whether or not the L<mro> pragma provides C<get_isarev>, a much faster
-way to get all the subclasses of a certain class.
-
 =back
 
 =head2 Utility functions
@@ -859,7 +874,7 @@ Note that these are all called as B<functions, not methods>.
 
 This will load the specified C<$class_name>. This function can be used
 in place of tricks like C<eval "use $module"> or using C<require>
-unconditionally.
+unconditionally. This will return the metaclass of C<$class_name>.
 
 =item B<Class::MOP::is_class_loaded($class_name)>
 
@@ -878,6 +893,12 @@ is from and the name of the C<$code> itself. This is used by several
 elements of the MOP to determine where a given C<$code> reference is
 from.
 
+=item B<Class::MOP::class_of($instance_or_class_name)>
+
+This will return the metaclass of the given instance or class name.
+Even if the class lacks a metaclass, no metaclass will be initialized
+and C<undef> will be returned.
+
 =item B<Class::MOP::check_package_cache_flag($pkg)>
 
 B<NOTE: DO NOT USE THIS FUNCTION, IT IS FOR INTERNAL USE ONLY!>
index 802d4d0..9579d7a 100644 (file)
@@ -9,7 +9,7 @@ use Class::MOP::Method::Accessor;
 use Carp         'confess';
 use Scalar::Util 'blessed', 'weaken';
 
-our $VERSION   = '0.78_02';
+our $VERSION   = '0.80';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index 11f51db..eaa838d 100644 (file)
@@ -11,7 +11,7 @@ use Class::MOP::Method::Wrapped;
 use Carp         'confess';
 use Scalar::Util 'blessed', 'weaken';
 
-our $VERSION   = '0.78_02';
+our $VERSION   = '0.80';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
@@ -182,16 +182,17 @@ sub _check_metaclass_compatibility {
             : ref($super_meta);
 
         ($self->isa($super_meta_type))
-            || confess $self->name . "->meta => (" . (ref($self)) . ")" .
-                       " is not compatible with the " .
-                       $superclass_name . "->meta => (" . ($super_meta_type)     . ")";
+            || confess "Class::MOP::class_of(" . $self->name . ") => ("
+                       . (ref($self)) . ")" .  " is not compatible with the " .
+                       "Class::MOP::class_of(".$superclass_name . ") => ("
+                       . ($super_meta_type) . ")";
         # NOTE:
         # we also need to check that instance metaclasses
         # are compatibile in the same the class.
         ($self->instance_metaclass->isa($super_meta->instance_metaclass))
-            || confess $self->name . "->meta->instance_metaclass => (" . ($self->instance_metaclass) . ")" .
+            || confess "Class::MOP::class_of(" . $self->name . ")->instance_metaclass => (" . ($self->instance_metaclass) . ")" .
                        " is not compatible with the " .
-                       $superclass_name . "->meta->instance_metaclass => (" . ($super_meta->instance_metaclass) . ")";
+                       "Class::MOP::class_of(" . $superclass_name . ")->instance_metaclass => (" . ($super_meta->instance_metaclass) . ")";
     }
 }
 
@@ -435,22 +436,16 @@ sub _clone_instance {
 sub rebless_instance {
     my ($self, $instance, %params) = @_;
 
-    my $old_metaclass;
-    if ($instance->can('meta')) {
-        ($instance->meta->isa('Class::MOP::Class'))
-            || confess 'Cannot rebless instance if ->meta is not an instance of Class::MOP::Class';
-        $old_metaclass = $instance->meta;
-    }
-    else {
-        $old_metaclass = $self->initialize(blessed($instance));
-    }
+    my $old_metaclass = Class::MOP::class_of($instance);
 
-    $old_metaclass->rebless_instance_away($instance, $self, %params);
+    my $old_class = $old_metaclass ? $old_metaclass->name : blessed($instance);
+    $self->name->isa($old_class)
+        || confess "You may rebless only into a subclass of ($old_class), of which (". $self->name .") isn't.";
 
-    my $meta_instance = $self->get_meta_instance();
+    $old_metaclass->rebless_instance_away($instance, $self, %params)
+        if $old_metaclass;
 
-    $self->name->isa($old_metaclass->name)
-        || confess "You may rebless only into a subclass of (". $old_metaclass->name ."), of which (". $self->name .") isn't.";
+    my $meta_instance = $self->get_meta_instance();
 
     # rebless!
     # we use $_[1] here because of t/306_rebless_overload.t regressions on 5.8.8
@@ -510,51 +505,9 @@ sub superclasses {
 
 sub subclasses {
     my $self = shift;
-
     my $super_class = $self->name;
 
-    if ( Class::MOP::HAVE_ISAREV() ) {
-        return @{ $super_class->mro::get_isarev() };
-    } else {
-        my @derived_classes;
-
-        my $find_derived_classes;
-        $find_derived_classes = sub {
-            my ($outer_class) = @_;
-
-            my $symbol_table_hashref = do { no strict 'refs'; \%{"${outer_class}::"} };
-
-            SYMBOL:
-            for my $symbol ( keys %$symbol_table_hashref ) {
-                next SYMBOL if $symbol !~ /\A (\w+):: \z/x;
-                my $inner_class = $1;
-
-                next SYMBOL if $inner_class eq 'SUPER';    # skip '*::SUPER'
-
-                my $class =
-                $outer_class
-                ? "${outer_class}::$inner_class"
-                : $inner_class;
-
-                if ( $class->isa($super_class) and $class ne $super_class ) {
-                    push @derived_classes, $class;
-                }
-
-                next SYMBOL if $class eq 'main';           # skip 'main::*'
-
-                $find_derived_classes->($class);
-            }
-        };
-
-        my $root_class = q{};
-        $find_derived_classes->($root_class);
-
-        undef $find_derived_classes;
-
-        @derived_classes = sort { $a->isa($b) ? 1 : $b->isa($a) ? -1 : 0 } @derived_classes;
-
-        return @derived_classes;
-    }
+    return @{ $super_class->mro::get_isarev() };
 }
 
 
index b050685..9b96087 100644 (file)
@@ -9,7 +9,7 @@ use Class::MOP::Method::Constructor;
 use Carp         'confess';
 use Scalar::Util 'blessed';
 
-our $VERSION   = '0.78_02';
+our $VERSION   = '0.80';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
@@ -169,7 +169,7 @@ my %DEFAULT_METHODS = (
         # that has been made immutable and for that we need 
         # to dig a bit ...
         if ($self->isa('Class::MOP::Class')) {
-            return $self->{'___original_class'}->meta;
+            return Class::MOP::class_of($self->{'___original_class'});
         }
         else {
             return $self;
@@ -184,7 +184,7 @@ sub _create_methods_for_immutable_metaclass {
     my $self = shift;
 
     my $metaclass = $self->metaclass;
-    my $meta      = $metaclass->meta;
+    my $meta      = Class::MOP::class_of($metaclass);
 
     return {
         %DEFAULT_METHODS,
@@ -200,7 +200,7 @@ sub _create_methods_for_immutable_metaclass {
 sub _make_read_only_methods {
     my $self = shift;
 
-    my $metameta = $self->metaclass->meta;
+    my $metameta = Class::MOP::class_of($self->metaclass);
 
     my %methods;
     foreach my $read_only_method ( @{ $self->options->{read_only} } ) {
@@ -238,7 +238,7 @@ sub _make_memoized_methods {
 
     my %methods;
 
-    my $metameta = $self->metaclass->meta;
+    my $metameta = Class::MOP::class_of($self->metaclass);
 
     my $memoized_methods = $self->options->{memoize};
     foreach my $method_name ( keys %{$memoized_methods} ) {
@@ -279,7 +279,7 @@ sub _make_wrapped_methods {
 
     my $wrapped_methods = $self->options->{wrapped};
 
-    my $metameta = $self->metaclass->meta;
+    my $metameta = Class::MOP::class_of($self->metaclass);
 
     foreach my $method_name ( keys %{$wrapped_methods} ) {
         my $method = $metameta->find_method_by_name($method_name);
index 546ffbf..3683dcf 100644 (file)
@@ -6,7 +6,7 @@ use warnings;
 
 use Scalar::Util 'weaken', 'blessed';
 
-our $VERSION   = '0.78_02';
+our $VERSION   = '0.80';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index 836273b..dfc0f29 100644 (file)
@@ -7,7 +7,7 @@ use warnings;
 use Carp         'confess';
 use Scalar::Util 'weaken';
 
-our $VERSION   = '0.78_02';
+our $VERSION   = '0.80';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index 6e40217..7b99469 100644 (file)
@@ -7,7 +7,7 @@ use warnings;
 use Carp         'confess';
 use Scalar::Util 'blessed', 'weaken';
 
-our $VERSION   = '0.78_02';
+our $VERSION   = '0.80';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index 8de6706..4358de9 100644 (file)
@@ -7,7 +7,7 @@ use warnings;
 use Carp         'confess';
 use Scalar::Util 'blessed', 'weaken', 'looks_like_number';
 
-our $VERSION   = '0.78_02';
+our $VERSION   = '0.80';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index 9c00836..bc70dd3 100644 (file)
@@ -6,7 +6,7 @@ use warnings;
 
 use Carp 'confess';
 
-our $VERSION   = '0.78_02';
+our $VERSION   = '0.80';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index 0568a01..2cf2197 100644 (file)
@@ -7,7 +7,7 @@ use warnings;
 use Carp         'confess';
 use Scalar::Util 'blessed';
 
-our $VERSION   = '0.78_02';
+our $VERSION   = '0.80';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index 35294b1..579fbd4 100644 (file)
@@ -7,7 +7,7 @@ use warnings;
 use Carp         'confess';
 use Scalar::Util 'blessed';
 
-our $VERSION   = '0.78_02';
+our $VERSION   = '0.80';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index b6b0445..99d5c02 100644 (file)
@@ -6,7 +6,7 @@ use warnings;
 
 use Scalar::Util 'blessed';
 
-our $VERSION   = '0.78_02';
+our $VERSION   = '0.80';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
@@ -18,7 +18,7 @@ sub meta {
 }
 
 sub _new {
-    shift->meta->new_object(@_);
+    Class::MOP::class_of(shift)->new_object(@_);
 }
 
 # RANT:
index 4a70e89..d1b1b68 100644 (file)
@@ -8,7 +8,7 @@ use B;
 use Scalar::Util 'blessed';
 use Carp         'confess';
 
-our $VERSION   = '0.78_02';
+our $VERSION   = '0.80';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index b3f66b8..6740e14 100644 (file)
@@ -7,7 +7,7 @@ use warnings;
 use Carp         'confess';
 use Scalar::Util 'blessed';
 
-our $VERSION   = '0.78_02';
+our $VERSION   = '0.80';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index e93c427..22a10af 100644 (file)
@@ -1,6 +1,6 @@
 use strict;
 use warnings;
-use Test::More tests => 33;
+use Test::More tests => 34;
 use Test::Exception;
 
 require Class::MOP;
@@ -51,6 +51,15 @@ throws_ok {
 qr/Missing right curly/;
 
 throws_ok {
+    delete $INC{'SyntaxError.pm'};
+    Class::MOP::load_first_existing_class(
+        'FakeClassOhNo', 'SyntaxError', 'Class'
+    );
+}
+qr/Missing right curly/,
+    'load_first_existing_class does not pass over an existing (bad) module';
+
+throws_ok {
     Class::MOP::load_class('This::Does::Not::Exist');
 }
 qr/Could not load class \(This::Does::Not::Exist\) because :/,
index 2918767..0897f59 100644 (file)
@@ -14,6 +14,7 @@ my @modules = all_modules();
 plan tests => scalar @modules;
 
 my %trustme = (
+    'Class::MOP'            => ['HAVE_ISAREV'],
     'Class::MOP::Attribute' => ['process_accessors'],
     'Class::MOP::Class'     => [
         # deprecated
@@ -42,6 +43,8 @@ my %trustme = (
         'update_package_cache_flag',
         'wrap_method_body',
 
+        # doc'd with rebless_instance
+        'rebless_instance_away',
     ],
 
     'Class::MOP::Instance' => [
index 52327ee..7568046 100644 (file)
@@ -128,6 +128,7 @@ pluggable
 prechecking
 prepends
 rebless
+reblessing
 runtime
 sigil
 sigils