Merge branch 'master' into topic/more-compatible
gfx [Sun, 20 Sep 2009 03:06:58 +0000 (12:06 +0900)]
Conflicts:
Changes

18 files changed:
Changes
Makefile.PL
lib/Mouse.pm
lib/Mouse/Meta/Attribute.pm
lib/Mouse/Meta/Class.pm
lib/Mouse/Meta/Method/Accessor.pm [deleted file]
lib/Mouse/Meta/Role.pm
lib/Mouse/Meta/TypeConstraint.pm
lib/Mouse/Object.pm
lib/Mouse/Util/TypeConstraints.pm
t/000-recipes/001_point.t
t/007-attributes.t
t/010-required.t
t/025-more-isa.t
t/029-new.t
t/030_roles/002_role.t
t/400-define-role.t
t/402-attribute-application.t

diff --git a/Changes b/Changes
index cb2f29f..fbf45aa 100644 (file)
--- a/Changes
+++ b/Changes
@@ -2,10 +2,13 @@ Revision history for Mouse
 
 0.30
 
-0.29 Thu Sep 17 11:49:49 2009
+    * Support is => 'bare', and you must pass the 'is' option (gfx)
+
+    * Make generator methods private (gfx)
 
-    * role class has ->meta in method_list, because it does in Moose since 0.90
+0.29 Thu Sep 17 11:49:49 2009
 
+    * role class has ->meta in method_list, because it does in Moose since 0.9
 0.28 Wed Sep  8 20:00:06 2009
     * Alter Makefile.PL so in author mode we generate lib/Mouse/Tiny.pm on
       every run so that 'make dist' actually does what it's meant to (mst)
index 5f13219..aa7620c 100755 (executable)
@@ -65,7 +65,7 @@ sub create_moose_compatibility_test {
                 my $dirname = File::Basename::dirname($_);
 
                 my $tmpdir = File::Spec->catfile('xt', 'compatibility', $dirname);
-                File::Path::make_path($tmpdir);
+                File::Path::mkpath($tmpdir);
 
                 my $tmpfile = File::Spec->catfile($tmpdir, $basename);
                 open my $wfh, '>', $tmpfile or die $!;
index 264f32c..7ca9997 100644 (file)
@@ -122,7 +122,9 @@ sub init_meta {
     {
         no strict 'refs';
         no warnings 'redefine';
-        *{$class.'::meta'} = sub { $meta };
+        *{$class.'::meta'} = sub {
+            return Mouse::Meta::Class->initialize(ref($_[0]) || $_[0]);
+        };
     }
 
     return $meta;
index dfae8b2..8abdd14 100644 (file)
@@ -1,12 +1,10 @@
 package Mouse::Meta::Attribute;
 use strict;
 use warnings;
-require overload;
 
 use Carp 'confess';
 use Scalar::Util ();
 use Mouse::Meta::TypeConstraint;
-use Mouse::Meta::Method::Accessor;
 
 sub new {
     my ($class, $name, %options) = @_;
@@ -56,16 +54,119 @@ sub _create_args {
     $_[0]->{_create_args}
 }
 
-sub inlined_name {
+sub _inlined_name {
     my $self = shift;
-    my $name = $self->name;
-    my $key   = "'" . $name . "'";
-    return $key;
+    return sprintf '"%s"', quotemeta $self->name;
 }
 
-sub generate_predicate {
+sub _generate_accessor{
+    my ($attribute) = @_;
+
+    my $name          = $attribute->name;
+    my $default       = $attribute->default;
+    my $constraint    = $attribute->type_constraint;
+    my $builder       = $attribute->builder;
+    my $trigger       = $attribute->trigger;
+    my $is_weak       = $attribute->is_weak_ref;
+    my $should_deref  = $attribute->should_auto_deref;
+    my $should_coerce = $attribute->should_coerce;
+
+    my $compiled_type_constraint    = $constraint ? $constraint->{_compiled_type_constraint} : undef;
+
+    my $self  = '$_[0]';
+    my $key   = $attribute->_inlined_name;
+
+    my $accessor = 
+        '#line ' . __LINE__ . ' "' . __FILE__ . "\"\n" .
+        "sub {\n";
+    if ($attribute->_is_metadata eq 'rw') {
+        $accessor .= 
+            '#line ' . __LINE__ . ' "' . __FILE__ . "\"\n" .
+            'if (scalar(@_) >= 2) {' . "\n";
+
+        my $value = '$_[1]';
+
+        if ($constraint) {
+            if ($should_coerce) {
+                $accessor .=
+                    "\n".
+                    '#line ' . __LINE__ . ' "' . __FILE__ . "\"\n" .
+                    'my $val = Mouse::Util::TypeConstraints->typecast_constraints("'.$attribute->associated_class->name.'", $attribute->{type_constraint}, '.$value.');';
+                $value = '$val';
+            }
+            if ($compiled_type_constraint) {
+                $accessor .= 
+                    "\n".
+                    '#line ' . __LINE__ . ' "' . __FILE__ . "\"\n" .
+                    'unless ($compiled_type_constraint->('.$value.')) {
+                        $attribute->verify_type_constraint_error($name, '.$value.', $attribute->{type_constraint});
+                    }' . "\n";
+            } else {
+                $accessor .= 
+                    "\n".
+                    '#line ' . __LINE__ . ' "' . __FILE__ . "\"\n" .
+                    'unless ($constraint->check('.$value.')) {
+                        $attribute->verify_type_constraint_error($name, '.$value.', $attribute->{type_constraint});
+                    }' . "\n";
+            }
+        }
+
+        # if there's nothing left to do for the attribute we can return during
+        # this setter
+        $accessor .= 'return ' if !$is_weak && !$trigger && !$should_deref;
+
+        $accessor .= $self.'->{'.$key.'} = '.$value.';' . "\n";
+
+        if ($is_weak) {
+            $accessor .= 'Scalar::Util::weaken('.$self.'->{'.$key.'}) if ref('.$self.'->{'.$key.'});' . "\n";
+        }
+
+        if ($trigger) {
+            $accessor .= '$trigger->('.$self.', '.$value.');' . "\n";
+        }
+
+        $accessor .= "}\n";
+    }
+    else {
+        $accessor .= 'Carp::confess("Cannot assign a value to a read-only accessor") if scalar(@_) >= 2;' . "\n";
+    }
+
+    if ($attribute->is_lazy) {
+        $accessor .= $self.'->{'.$key.'} = ';
+
+        $accessor .= $attribute->has_builder
+                ? $self.'->$builder'
+                    : ref($default) eq 'CODE'
+                    ? '$default->('.$self.')'
+                    : '$default';
+        $accessor .= ' if !exists '.$self.'->{'.$key.'};' . "\n";
+    }
+
+    if ($should_deref) {
+        if (ref($constraint) && $constraint->name =~ '^ArrayRef\b') {
+            $accessor .= 'if (wantarray) {
+                return @{ '.$self.'->{'.$key.'} || [] };
+            }';
+        }
+        else {
+            $accessor .= 'if (wantarray) {
+                return %{ '.$self.'->{'.$key.'} || {} };
+            }';
+        }
+    }
+
+    $accessor .= 'return '.$self.'->{'.$key.'};
+    }';
+
+    my $sub = eval $accessor;
+    Carp::confess($@) if $@;
+    return $sub;
+}
+
+
+sub _generate_predicate {
     my $attribute = shift;
-    my $key = $attribute->inlined_name;
+    my $key = $attribute->_inlined_name;
 
     my $predicate = 'sub { exists($_[0]->{'.$key.'}) }';
 
@@ -74,9 +175,9 @@ sub generate_predicate {
     return $sub;
 }
 
-sub generate_clearer {
+sub _generate_clearer {
     my $attribute = shift;
-    my $key = $attribute->inlined_name;
+    my $key = $attribute->_inlined_name;
 
     my $clearer = 'sub { delete($_[0]->{'.$key.'}) }';
 
@@ -85,7 +186,7 @@ sub generate_clearer {
     return $sub;
 }
 
-sub generate_handles {
+sub _generate_handles {
     my $attribute = shift;
     my $reader = $attribute->name;
     my %handles = $attribute->_canonicalize_handles($attribute->handles);
@@ -120,13 +221,6 @@ sub create {
         if exists $args{coerce};
 
     if (exists $args{isa}) {
-        confess "Got isa => $args{isa}, but Mouse does not yet support parameterized types for containers other than ArrayRef and HashRef (rt.cpan.org #39795)"
-            if $args{isa} =~ /^([^\[]+)\[.+\]$/ &&
-               $1 ne 'ArrayRef' &&
-               $1 ne 'HashRef'  &&
-               $1 ne 'Maybe'
-        ;
-
         my $type_constraint = delete $args{isa};
         $args{type_constraint}= Mouse::Util::TypeConstraints::find_or_create_isa_type_constraint($type_constraint);
     }
@@ -137,30 +231,40 @@ sub create {
 
     $class->add_attribute($attribute);
 
+    my $associated_methods = 0;
+
+    my $is_metadata = $attribute->_is_metadata || '';
+
     # install an accessor
-    if ($attribute->_is_metadata eq 'rw' || $attribute->_is_metadata eq 'ro') {
-        my $code = Mouse::Meta::Method::Accessor->generate_accessor_method_inline(
-            $attribute,
-        );
+    if ($is_metadata eq 'rw' || $is_metadata eq 'ro') {
+        my $code = $attribute->_generate_accessor();
         $class->add_method($name => $code);
+        $associated_methods++;
     }
 
     for my $method (qw/predicate clearer/) {
         my $predicate = "has_$method";
         if ($attribute->$predicate) {
-            my $generator = "generate_$method";
+            my $generator = "_generate_$method";
             my $coderef = $attribute->$generator;
             $class->add_method($attribute->$method => $coderef);
+            $associated_methods++;
         }
     }
 
     if ($attribute->has_handles) {
-        my $method_map = $attribute->generate_handles;
+        my $method_map = $attribute->_generate_handles;
         for my $method_name (keys %$method_map) {
             $class->add_method($method_name => $method_map->{$method_name});
+            $associated_methods++;
         }
     }
 
+    if($associated_methods == 0 && $is_metadata ne 'bare'){
+        Carp::cluck(qq{Attribute ($name) of class }.$class->name.qq{ has no associated methods (did you mean to provide an "is" argument?)});
+
+    }
+
     return $attribute;
 }
 
@@ -348,22 +452,6 @@ installed. Some error checking is done.
 
 Informational methods.
 
-=head2 generate_accessor -> CODE
-
-Creates a new code reference for the attribute's accessor.
-
-=head2 generate_predicate -> CODE
-
-Creates a new code reference for the attribute's predicate.
-
-=head2 generate_clearer -> CODE
-
-Creates a new code reference for the attribute's clearer.
-
-=head2 generate_handles -> { MethodName => CODE }
-
-Creates a new code reference for each of the attribute's handles methods.
-
 =head2 verify_against_type_constraint Item -> 1 | ERROR
 
 Checks that the given value passes this attribute's type constraint. Returns 1
index 4761e5d..7ba5692 100644 (file)
@@ -20,12 +20,13 @@ do {
     }
 
     sub initialize {
-        my $class = blessed($_[0]) || $_[0];
-        my $name  = $_[1];
+        my($class, $package_name, @args) = @_;
 
-        $METACLASS_CACHE{$name} = $class->new(name => $name)
-            if !exists($METACLASS_CACHE{$name});
-        return $METACLASS_CACHE{$name};
+        ($package_name && !ref($package_name))\r
+            || confess("You must pass a package name and it cannot be blessed");\r
+
+        return $METACLASS_CACHE{$package_name}
+            ||= $class->_construct_class_instance(package => $package_name, @args);
     }
 
     # Means of accessing all the metaclasses that have
@@ -40,21 +41,20 @@ do {
     sub remove_metaclass_by_name    { $METACLASS_CACHE{$_[0]} = undef }
 };
 
-sub new {
-    my $class = shift;
-    my %args  = @_;
+sub _construct_class_instance {
+    my($class, %args) = @_;
 
-    $args{attributes} = {};
+    $args{attributes}   = {};
     $args{superclasses} = do {
         no strict 'refs';
-        \@{ $args{name} . '::ISA' };
+        \@{ $args{package} . '::ISA' };
     };
     $args{roles} ||= [];
 
     bless \%args, $class;
 }
 
-sub name { $_[0]->{name} }
+sub name { $_[0]->{package} }
 
 sub superclasses {
     my $self = shift;
@@ -319,7 +319,7 @@ sub does_role {
 }
 
 sub create {
-    my ($self, $package_name, %options) = @_;
+    my ($class, $package_name, %options) = @_;
 
     (ref $options{superclasses} eq 'ARRAY')
         || confess "You must pass an ARRAY ref of superclasses"
@@ -356,11 +356,11 @@ sub create {
         version
         authority
     )};
-    my $meta = $self->initialize( $package_name => %initialize_options );
+    my $meta = $class->initialize( $package_name => %initialize_options );
 
     # FIXME totally lame
     $meta->add_method('meta' => sub {
-        $self->initialize(ref($_[0]) || $_[0]);
+        Mouse::Meta::Class->initialize(ref($_[0]) || $_[0]);
     });
 
     $meta->superclasses(@{$options{superclasses}})
diff --git a/lib/Mouse/Meta/Method/Accessor.pm b/lib/Mouse/Meta/Method/Accessor.pm
deleted file mode 100644 (file)
index 38531bc..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-package Mouse::Meta::Method::Accessor;
-use strict;
-use warnings;
-use Carp ();
-
-# internal use only. do not call directly
-sub generate_accessor_method_inline {
-    my ($class, $attribute) = @_;
-
-    my $name          = $attribute->name;
-    my $default       = $attribute->default;
-    my $constraint    = $attribute->type_constraint;
-    my $builder       = $attribute->builder;
-    my $trigger       = $attribute->trigger;
-    my $is_weak       = $attribute->is_weak_ref;
-    my $should_deref  = $attribute->should_auto_deref;
-    my $should_coerce = $attribute->should_coerce;
-
-    my $compiled_type_constraint    = $constraint ? $constraint->{_compiled_type_constraint} : undef;
-
-    my $self  = '$_[0]';
-    my $key   = $attribute->inlined_name;
-
-    my $accessor = 
-        '#line ' . __LINE__ . ' "' . __FILE__ . "\"\n" .
-        "sub {\n";
-    if ($attribute->_is_metadata eq 'rw') {
-        $accessor .= 
-            '#line ' . __LINE__ . ' "' . __FILE__ . "\"\n" .
-            'if (scalar(@_) >= 2) {' . "\n";
-
-        my $value = '$_[1]';
-
-        if ($constraint) {
-            if ($should_coerce) {
-                $accessor .=
-                    "\n".
-                    '#line ' . __LINE__ . ' "' . __FILE__ . "\"\n" .
-                    'my $val = Mouse::Util::TypeConstraints->typecast_constraints("'.$attribute->associated_class->name.'", $attribute->{type_constraint}, '.$value.');';
-                $value = '$val';
-            }
-            if ($compiled_type_constraint) {
-                $accessor .= 
-                    "\n".
-                    '#line ' . __LINE__ . ' "' . __FILE__ . "\"\n" .
-                    'unless ($compiled_type_constraint->('.$value.')) {
-                        $attribute->verify_type_constraint_error($name, '.$value.', $attribute->{type_constraint});
-                    }' . "\n";
-            } else {
-                $accessor .= 
-                    "\n".
-                    '#line ' . __LINE__ . ' "' . __FILE__ . "\"\n" .
-                    'unless ($constraint->check('.$value.')) {
-                        $attribute->verify_type_constraint_error($name, '.$value.', $attribute->{type_constraint});
-                    }' . "\n";
-            }
-        }
-
-        # if there's nothing left to do for the attribute we can return during
-        # this setter
-        $accessor .= 'return ' if !$is_weak && !$trigger && !$should_deref;
-
-        $accessor .= $self.'->{'.$key.'} = '.$value.';' . "\n";
-
-        if ($is_weak) {
-            $accessor .= 'Scalar::Util::weaken('.$self.'->{'.$key.'}) if ref('.$self.'->{'.$key.'});' . "\n";
-        }
-
-        if ($trigger) {
-            $accessor .= '$trigger->('.$self.', '.$value.');' . "\n";
-        }
-
-        $accessor .= "}\n";
-    }
-    else {
-        $accessor .= 'Carp::confess("Cannot assign a value to a read-only accessor") if scalar(@_) >= 2;' . "\n";
-    }
-
-    if ($attribute->is_lazy) {
-        $accessor .= $self.'->{'.$key.'} = ';
-
-        $accessor .= $attribute->has_builder
-                ? $self.'->$builder'
-                    : ref($default) eq 'CODE'
-                    ? '$default->('.$self.')'
-                    : '$default';
-        $accessor .= ' if !exists '.$self.'->{'.$key.'};' . "\n";
-    }
-
-    if ($should_deref) {
-        if (ref($constraint) && $constraint->name =~ '^ArrayRef\b') {
-            $accessor .= 'if (wantarray) {
-                return @{ '.$self.'->{'.$key.'} || [] };
-            }';
-        }
-        else {
-            $accessor .= 'if (wantarray) {
-                return %{ '.$self.'->{'.$key.'} || {} };
-            }';
-        }
-    }
-
-    $accessor .= 'return '.$self.'->{'.$key.'};
-    }';
-
-    my $sub = eval $accessor;
-    Carp::confess($@) if $@;
-    return $sub;
-}
-
-1;
index 13daeaf..4910f72 100644 (file)
@@ -2,6 +2,7 @@ package Mouse::Meta::Role;
 use strict;
 use warnings;
 use Carp 'confess';
+
 use Mouse::Util qw(version authority identifier);
 
 do {
index 538e3b2..51b0867 100644 (file)
@@ -1,6 +1,8 @@
 package Mouse::Meta::TypeConstraint;
 use strict;
 use warnings;
+use Carp ();
+
 use overload '""'     => sub { shift->{name} },   # stringify to tc name
              fallback => 1;
 
@@ -28,6 +30,26 @@ sub check {
     $self->{_compiled_type_constraint}->(@_);
 }
 
+sub validate {
+    my ($self, $value) = @_;\r
+    if ($self->{_compiled_type_constraint}->($value)) {\r
+        return undef;\r
+    }\r
+    else {\r
+        $self->get_message($value);\r
+    }\r
+}
+
+sub assert_valid {\r
+    my ($self, $value) = @_;\r
+\r
+    my $error = $self->validate($value);\r
+    return 1 if ! defined $error;\r
+
+    Carp::confess($error);\r
+}\r
+
+
 sub message {
     return $_[0]->{message};
 }
index ddcf41f..745d1f2 100644 (file)
@@ -136,7 +136,7 @@ sub does {
         || confess "You must supply a role name to does()";
     my $meta = $self->meta;
     foreach my $class ($meta->linearized_isa) {
-        my $m = $meta->initialize($class);
+        my $m = ref($meta)->initialize($class);
         return 1 
             if $m->can('does_role') && $m->does_role($role_name);            
     }
index 4f77130..993e8e0 100644 (file)
@@ -308,6 +308,13 @@ sub find_type_constraint {
 sub find_or_create_isa_type_constraint {
     my $type_constraint = shift;
 
+    Carp::confess("Got isa => type_constraints, but Mouse does not yet support parameterized types for containers other than ArrayRef and HashRef and Maybe (rt.cpan.org #39795)")
+        if $type_constraint =~ /\A ( [^\[]+ ) \[\.+\] \z/xms &&
+           $1 ne 'ArrayRef' &&
+           $1 ne 'HashRef'  &&
+           $1 ne 'Maybe'
+    ;
+
     my $code;
 
     $type_constraint =~ s/\s+//g;
index 1f52f0f..90b989b 100644 (file)
@@ -36,7 +36,7 @@ use Test::Exception;
        
        extends 'Point';
        
-       has 'z' => (isa => 'Int');
+       has 'z' => (isa => 'Int', is => 'bare');
        
        after 'clear' => sub {
            my $self = shift;
index 4316e25..fdb3ed3 100644 (file)
@@ -8,7 +8,9 @@ do {
     package Class;
     use Mouse;
 
-    has 'x';
+    has 'x' => (
+        is => 'bare',
+    );
 
     has 'y' => (
         is => 'ro',
index 161717c..e6a6990 100644 (file)
@@ -9,15 +9,18 @@ do {
     use Mouse;
 
     has foo => (
+        is => 'bare',
         required => 1,
     );
 
     has bar => (
+        is => 'bare',
         required => 1,
         default => 50,
     );
 
     has baz => (
+        is => 'bare',
         required => 1,
         default => sub { 10 },
     );
index 576d5e1..022c89c 100755 (executable)
@@ -54,6 +54,7 @@ do {
     use Mouse;
 
     has oops => (
+        is      => 'bare',
         isa     => 'Int',
         default => "yikes",
     );
index 4e642eb..fe660a1 100644 (file)
@@ -8,7 +8,9 @@ do {
     package Class;
     use Mouse;
 
-    has 'x';
+    has x => (
+        is => 'bare',
+    );
 
     has y => (
         is => 'ro',
index 2dfe39b..448d492 100755 (executable)
@@ -85,16 +85,13 @@ is_deeply(
 
 ok($foo_role->has_attribute('bar'), '... FooRole does have the bar attribute');
 
-is_deeply(
-    $foo_role->get_attribute('bar'),
-    { is => 'rw', isa => 'Foo' },
-    '... got the correct description of the bar attribute');
+is $foo_role->get_attribute('bar')->{is}, 'rw', '... got the correct description of the bar attribute';
 
 ok($foo_role->has_attribute('baz'), '... FooRole does have the baz attribute');
 
-is_deeply(
-    $foo_role->get_attribute('baz'),
-    { is => 'ro' },
+is(
+    $foo_role->get_attribute('baz')->{is},
+    'ro',
     '... got the correct description of the baz attribute');
 
 # method modifiers
index 7202797..1441463 100644 (file)
@@ -44,7 +44,7 @@ lives_ok {
     package Role;
     use Mouse::Role;
 
-    has 'foo';
+    has 'foo' => (is => 'bare');
 
     no Mouse::Role;
 };
index fbb400d..e4745c5 100644 (file)
@@ -9,13 +9,14 @@ do {
     use Mouse::Role;
 
     has 'attr' => (
+        is      => 'bare',
         default => 'Role',
     );
 
     no Mouse::Role;
 };
 
-is_deeply(Role->meta->get_attribute('attr'), {default => 'Role'});
+is(Role->meta->get_attribute('attr')->{default}, 'Role');
 
 do {
     package Class;
@@ -33,6 +34,7 @@ do {
     use Mouse::Role;
 
     has 'attr' => (
+        is      => 'bare',
         default => 'Role2',
     );
 
@@ -55,6 +57,7 @@ lives_ok {
     with 'Role';
 
     has attr => (
+        is      => 'bare',
         default => 'Class3',
     );
 };
@@ -66,6 +69,7 @@ lives_ok {
     use Mouse;
 
     has attr => (
+        is      => 'bare',
         default => 'Class::Parent',
     );
 };