0_04
Stevan Little [Mon, 17 Apr 2006 02:55:23 +0000 (02:55 +0000)]
Changes
MANIFEST
README
lib/Moose/Meta/Attribute.pm
lib/Moose/Meta/Class.pm
lib/Moose/Meta/Role.pm
lib/Moose/Object.pm
lib/Moose/Role.pm
lib/Moose/Util/TypeConstraints.pm
t/034_does_attribute_option.t [new file with mode: 0644]
t/052_util_std_type_constraints.t

diff --git a/Changes b/Changes
index 411f6a5..c6de4f8 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,6 +1,6 @@
 Revision history for Perl extension Moose
 
-0.04
+0.04 Sun. April 16th, 2006
     * Moose::Role
       - Roles can now consume other roles
         - added tests for this
@@ -21,6 +21,8 @@ Revision history for Perl extension Moose
     * Moose::Meta::Attribute
       - added support for triggers on attributes
         - added tests for this
+      - added support for does option on an attribute 
+        - added tests for this
         
     * Moose::Meta::Class
       - added support for attribute triggers in the 
index 3740e43..4024218 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -28,6 +28,7 @@ t/003_basic.t
 t/004_basic.t
 t/005_basic.t
 t/006_basic.t
+t/007_basic.t
 t/010_basic_class_setup.t
 t/011_require_superclasses.t
 t/012_super_and_override.t
@@ -38,9 +39,12 @@ t/020_foreign_inheritence.t
 t/030_attribute_reader_generation.t
 t/031_attribute_writer_generation.t
 t/032_attribute_accessor_generation.t
+t/033_attribute_triggers.t
+t/034_does_attribute_option.t
 t/040_meta_role.t
 t/041_role.t
 t/042_apply_role.t
+t/043_role_composition_errors.t
 t/050_util_type_constraints.t
 t/051_util_type_constraints_export.t
 t/052_util_std_type_constraints.t
@@ -49,7 +53,12 @@ t/054_util_type_coercion.t
 t/055_util_type_reloading.t
 t/056_util_more_type_coercion.t
 t/100_subtype_quote_bug.t
+t/101_subtype_conflict_bug.t
+t/102_Moose_Object_error.t
 t/pod.t
 t/pod_coverage.t
 t/lib/Bar.pm
 t/lib/Foo.pm
+t/lib/MyMooseA.pm
+t/lib/MyMooseB.pm
+t/lib/MyMooseObject.pm
diff --git a/README b/README
index 3d47cd7..e4af674 100644 (file)
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-Moose version 0.03_02
+Moose version 0.04
 ===========================
 
 See the individual module documentation for more information
index 41c1de4..0d154cb 100644 (file)
@@ -44,6 +44,14 @@ sub new {
        }
        
        if (exists $options{isa}) {
+           
+           if (exists $options{does}) {
+               if (eval { $options{isa}->can('does') }) {
+                   ($options{isa}->does($options{does}))                   
+                       || confess "Cannot have an isa option and a does option if the isa does not do the does";
+               }
+           }       
+           
            # allow for anon-subtypes here ...
            if (blessed($options{isa}) && $options{isa}->isa('Moose::Meta::TypeConstraint')) {
                        $options{type_constraint} = $options{isa};
@@ -63,6 +71,26 @@ sub new {
             $options{type_constraint} = $constraint;
                }
        }       
+       elsif (exists $options{does}) {     
+           # allow for anon-subtypes here ...
+           if (blessed($options{does}) && $options{does}->isa('Moose::Meta::TypeConstraint')) {
+                       $options{type_constraint} = $options{isa};
+               }
+               else {
+                   # otherwise assume it is a constraint
+                   my $constraint = Moose::Util::TypeConstraints::find_type_constraint($options{does});              
+                   # if the constraing it not found ....
+                   unless (defined $constraint) {                              
+                       # assume it is a foreign class, and make 
+                       # an anon constraint for it 
+                       $constraint = Moose::Util::TypeConstraints::subtype(
+                           'Role', 
+                           Moose::Util::TypeConstraints::where { $_->does($options{does}) }
+                       );
+                   }                       
+            $options{type_constraint} = $constraint;
+               }           
+       }
        
        if (exists $options{coerce} && $options{coerce}) {
            (exists $options{type_constraint})
@@ -216,26 +244,33 @@ for L<Moose::Meta::TypeConstraint>.
 
 =item B<is_weak_ref>
 
-Returns true of this meta-attribute produces a weak reference.
+Returns true if this meta-attribute produces a weak reference.
 
 =item B<is_required>
 
-Returns true of this meta-attribute is required to have a value.
+Returns true if this meta-attribute is required to have a value.
 
 =item B<is_lazy>
 
-Returns true of this meta-attribute should be initialized lazily.
+Returns true if this meta-attribute should be initialized lazily.
 
 NOTE: lazy attributes, B<must> have a C<default> field set.
 
 =item B<should_coerce>
 
-Returns true of this meta-attribute should perform type coercion.
+Returns true if this meta-attribute should perform type coercion.
 
 =item B<has_trigger>
 
+Returns true if this meta-attribute has a trigger set.
+
 =item B<trigger>
 
+This is a CODE reference which will be executed every time the 
+value of an attribute is assigned. The CODE ref will get two values, 
+the invocant and the new value. This can be used to handle I<basic> 
+bi-directional relations.
+
 =back
 
 =head1 BUGS
index 810b608..8ec469f 100644 (file)
@@ -186,6 +186,8 @@ to the L<Class::MOP::Class> documentation.
 
 =item B<new_object>
 
+We override this method to support the C<trigger> attribute option.
+
 =item B<construct_instance>
 
 This provides some Moose specific extensions to this method, you 
@@ -203,14 +205,30 @@ methods.
 
 =item B<add_override_method_modifier ($name, $method)>
 
+This will create an C<override> method modifier for you, and install 
+it in the package.
+
 =item B<add_augment_method_modifier ($name, $method)>
 
+This will create an C<augment> method modifier for you, and install 
+it in the package.
+
 =item B<roles>
 
+This will return an array of C<Moose::Meta::Role> instances which are 
+attached to this class.
+
 =item B<add_role ($role)>
 
+This takes an instance of C<Moose::Meta::Role> in C<$role>, and adds it 
+to the list of associated roles.
+
 =item B<does_role ($role_name)>
 
+This will test if this class C<does> a given C<$role_name>. It will 
+not only check it's local roles, but ask them as well in order to 
+cascade down the role hierarchy.
+
 =back
 
 =head1 BUGS
index d0db84f..82d0400 100644 (file)
@@ -330,7 +330,9 @@ Moose::Meta::Role - The Moose Role metaclass
 =head1 DESCRIPTION
 
 Moose's Roles are being actively developed, please see L<Moose::Role> 
-for more information. 
+for more information. For the most part, this has no user-serviceable 
+parts inside. It's API is still subject to some change (although 
+probably not that much really).
 
 =head1 METHODS
 
index a035523..58c373d 100644 (file)
@@ -95,6 +95,9 @@ This will call every C<DEMOLISH> method in the inheritance hierarchy.
 
 =item B<does ($role_name)>
 
+This will check if the invocant's class C<does> a given C<$role_name>. 
+This is similar to C<isa> for object, but it checks the roles instead.
+
 =back
 
 =head1 BUGS
index ecc016f..6821d8f 100644 (file)
@@ -18,8 +18,6 @@ sub import {
        
        # we should never export to main
        return if $pkg eq 'main';
-       
-       Moose::Util::TypeConstraints->import($pkg);
 
        my $meta;
        if ($pkg->can('meta')) {
@@ -133,28 +131,28 @@ Moose::Role - The Moose Role
 =head1 DESCRIPTION
 
 This is currently a very early release of Perl 6 style Roles for 
-Moose, it should be considered experimental and incomplete.
-
-This feature is being actively developed, but $work is currently 
-preventing me from paying as much attention to it as I would like. 
-So I am releasing it in hopes people will help me on this I<hint hint>.
-
-If you are interested in helping, please come to #moose on irc.perl.org
-and we can talk. 
+Moose, it is still incomplete, but getting much closer. If you are 
+interested in helping move this feature along, please come to 
+#moose on irc.perl.org and we can talk. 
 
 =head1 CAVEATS
 
-Currently, the role support has a number of caveats. They are as follows:
+Currently, the role support has a few of caveats. They are as follows:
 
 =over 4
 
 =item *
 
-At this time classes I<can> consume more than one Role, but they are simply 
-applied one after another in the order you ask for them. This is incorrect 
-behavior, the roles should be merged first, and conflicts determined, etc. 
-However, if your roles do not have any conflicts, then things will work just 
-fine.
+At this time classes I<cannot> correctly consume more than one role. The 
+role composition process, and it's conflict detection has not been added
+yet. While this should be considered a major feature, it can easily be 
+worked around, and in many cases, is not needed at all.
+A class can actually consume multiple roles, they are just applied one 
+after another in the order you ask for them. This is incorrect behavior, 
+the roles should be merged first, and conflicts determined, etc. However, 
+if your roles do not have any conflicts, then things will work just 
+fine. This actually tends to be quite sufficient for basic roles.
 
 =item *
 
@@ -165,8 +163,6 @@ so that they can be applied to the consuming class.
 
 =back
 
-Basically thats all I can think of for now, I am sure there are more though.
-
 =head1 BUGS
 
 All complex software has bugs lurking in it, and this module is no 
index ff39e5b..2db83f4 100644 (file)
@@ -116,6 +116,8 @@ subtype 'RegexpRef' => as 'Ref' => where { ref($_) eq 'Regexp' };
 # blessed(qr/.../) returns true,.. how odd
 subtype 'Object' => as 'Ref' => where { blessed($_) && blessed($_) ne 'Regexp' };
 
+subtype 'Role' => as 'Object' => where { $_->can('does') };
+
 1;
 
 __END__
@@ -176,6 +178,7 @@ could probably use some work, but it works for me at the moment.
           CodeRef
           RegexpRef
           Object       
+            Role
 
 Suggestions for improvement are welcome.
     
diff --git a/t/034_does_attribute_option.t b/t/034_does_attribute_option.t
new file mode 100644 (file)
index 0000000..a154f93
--- /dev/null
@@ -0,0 +1,82 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 7;
+use Test::Exception;
+
+BEGIN {
+    use_ok('Moose');           
+}
+
+{
+    package Foo::Role;
+    use strict;
+    use warnings;
+    use Moose::Role;
+
+    # if does() exists on its own, then 
+    # we create a type constraint for 
+    # it, just as we do for isa()
+    has 'bar' => (is => 'rw', does => 'Bar::Role'); 
+
+    package Bar::Role;
+    use strict;
+    use warnings;
+    use Moose::Role;
+
+    # if isa and does appear together, then see if Class->does(Role)
+    # if it does work... then the does() check is actually not needed 
+    # since the isa() check will imply the does() check    
+    has 'foo' => (is => 'rw', isa => 'Foo::Class', does => 'Foo::Role');    
+    
+    package Foo::Class;
+    use strict;
+    use warnings;
+    use Moose;
+    
+    with 'Foo::Role';
+
+    package Bar::Class;
+    use strict;
+    use warnings;
+    use Moose;
+
+    with 'Bar::Role';
+
+}
+
+my $foo = Foo::Class->new;
+isa_ok($foo, 'Foo::Class');
+
+my $bar = Bar::Class->new;
+isa_ok($bar, 'Bar::Class');
+
+lives_ok {
+    $foo->bar($bar);
+} '... bar passed the type constraint okay';
+
+dies_ok {
+    $foo->bar($foo);
+} '... foo did not pass the type constraint okay';
+
+lives_ok {
+    $bar->foo($foo);
+} '... foo passed the type constraint okay';    
+
+# some error conditions
+
+{
+    package Baz::Class;
+    use strict;
+    use warnings;
+    use Moose;
+
+    # if isa and does appear together, then see if Class->does(Role)
+    # if it does not,.. we have a conflict... so we die loudly
+    ::dies_ok {
+        has 'foo' => (isa => 'Foo::Class', does => 'Bar::Class');
+    } '... cannot have a does() which is not done by the isa()';
+}    
+    
index 526a43a..3432e23 100644 (file)
@@ -3,7 +3,7 @@
 use strict;
 use warnings;
 
-use Test::More tests => 111;
+use Test::More tests => 122;
 use Test::Exception;
 
 use Scalar::Util ();
@@ -136,3 +136,22 @@ ok(!defined Object(sub {}),           '... Object rejects anything which is not
 ok(!defined Object($SCALAR_REF),      '... Object rejects anything which is not blessed');
 ok(!defined Object(qr/../),           '... Object rejects anything which is not blessed');
 ok(defined Object(bless {}, 'Foo'),   '... Object accepts anything which is blessed');
+
+{
+    package My::Role;
+    sub does { 'fake' }
+}
+
+ok(!defined Role(0),                '... Role rejects anything which is not a Role');
+ok(!defined Role(100),              '... Role rejects anything which is not a Role');
+ok(!defined Role(''),               '... Role rejects anything which is not a Role');
+ok(!defined Role('Foo'),            '... Role rejects anything which is not a Role');
+ok(!defined Role([]),               '... Role rejects anything which is not a Role');
+ok(!defined Role({}),               '... Role rejects anything which is not a Role');
+ok(!defined Role(sub {}),           '... Role rejects anything which is not a Role');
+ok(!defined Role($SCALAR_REF),      '... Role rejects anything which is not a Role');
+ok(!defined Role(qr/../),           '... Role rejects anything which is not a Role');
+ok(!defined Role(bless {}, 'Foo'),  '... Role accepts anything which is not a Role');
+ok(defined Role(bless {}, 'My::Role'),  '... Role accepts anything which is not a Role');
+
+