From: Stevan Little Date: Mon, 17 Apr 2006 02:55:23 +0000 (+0000) Subject: 0_04 X-Git-Tag: 0_05~28 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=02a0fb5233657a2b8136651fe1f9bb70a272a014;p=gitmo%2FMoose.git 0_04 --- diff --git a/Changes b/Changes index 411f6a5..c6de4f8 100644 --- 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 diff --git a/MANIFEST b/MANIFEST index 3740e43..4024218 100644 --- 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 --- 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 diff --git a/lib/Moose/Meta/Attribute.pm b/lib/Moose/Meta/Attribute.pm index 41c1de4..0d154cb 100644 --- a/lib/Moose/Meta/Attribute.pm +++ b/lib/Moose/Meta/Attribute.pm @@ -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. =item B -Returns true of this meta-attribute produces a weak reference. +Returns true if this meta-attribute produces a weak reference. =item B -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 -Returns true of this meta-attribute should be initialized lazily. +Returns true if this meta-attribute should be initialized lazily. NOTE: lazy attributes, B have a C field set. =item B -Returns true of this meta-attribute should perform type coercion. +Returns true if this meta-attribute should perform type coercion. =item B +Returns true if this meta-attribute has a trigger set. + =item B +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 +bi-directional relations. + =back =head1 BUGS diff --git a/lib/Moose/Meta/Class.pm b/lib/Moose/Meta/Class.pm index 810b608..8ec469f 100644 --- a/lib/Moose/Meta/Class.pm +++ b/lib/Moose/Meta/Class.pm @@ -186,6 +186,8 @@ to the L documentation. =item B +We override this method to support the C attribute option. + =item B This provides some Moose specific extensions to this method, you @@ -203,14 +205,30 @@ methods. =item B +This will create an C method modifier for you, and install +it in the package. + =item B +This will create an C method modifier for you, and install +it in the package. + =item B +This will return an array of C instances which are +attached to this class. + =item B +This takes an instance of C in C<$role>, and adds it +to the list of associated roles. + =item B +This will test if this class C 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 diff --git a/lib/Moose/Meta/Role.pm b/lib/Moose/Meta/Role.pm index d0db84f..82d0400 100644 --- a/lib/Moose/Meta/Role.pm +++ b/lib/Moose/Meta/Role.pm @@ -330,7 +330,9 @@ Moose::Meta::Role - The Moose Role metaclass =head1 DESCRIPTION Moose's Roles are being actively developed, please see L -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 diff --git a/lib/Moose/Object.pm b/lib/Moose/Object.pm index a035523..58c373d 100644 --- a/lib/Moose/Object.pm +++ b/lib/Moose/Object.pm @@ -95,6 +95,9 @@ This will call every C method in the inheritance hierarchy. =item B +This will check if the invocant's class C a given C<$role_name>. +This is similar to C for object, but it checks the roles instead. + =back =head1 BUGS diff --git a/lib/Moose/Role.pm b/lib/Moose/Role.pm index ecc016f..6821d8f 100644 --- a/lib/Moose/Role.pm +++ b/lib/Moose/Role.pm @@ -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. - -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 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 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 diff --git a/lib/Moose/Util/TypeConstraints.pm b/lib/Moose/Util/TypeConstraints.pm index ff39e5b..2db83f4 100644 --- a/lib/Moose/Util/TypeConstraints.pm +++ b/lib/Moose/Util/TypeConstraints.pm @@ -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 index 0000000..a154f93 --- /dev/null +++ b/t/034_does_attribute_option.t @@ -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()'; +} + diff --git a/t/052_util_std_type_constraints.t b/t/052_util_std_type_constraints.t index 526a43a..3432e23 100644 --- a/t/052_util_std_type_constraints.t +++ b/t/052_util_std_type_constraints.t @@ -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'); + +