From: Stevan Little Date: Tue, 4 Sep 2007 15:47:58 +0000 (+0000) Subject: start of the TC refactor X-Git-Tag: 0_26~29 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=d67145edcc2653d4936d9395e5d63405332b4c1b;p=gitmo%2FMoose.git start of the TC refactor --- diff --git a/Changes b/Changes index dc179e0..a5fa13b 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,22 @@ Revision history for Perl extension Moose +0.26 + * Moose + - added all the meta classes to the immutable list and + set it to inline the accessors + + * Moose::Meta::TypeConstraint + - some minor adjustments to make subclassing easier + + * Moose::Meta::TypeConstraint::Union + - this is not a subclass of Moose::Meta::TypeConstraint + which is more correct + + * Moose::Meta::TypeConstraint::Container + - added this module (taken from MooseX::AttributeHelpers) + to help construct nested collection types + - added tests for this + 0.25 Mon. Aug. 13, 2007 * Moose - Documentation update to reference Moose::Util::TypeConstraints diff --git a/PLANS b/PLANS new file mode 100644 index 0000000..e009272 --- /dev/null +++ b/PLANS @@ -0,0 +1,57 @@ +----------------------------------------------------------- +-- Type Constraints refactor +----------------------------------------------------------- + +- move the details of TC construction that are in Moose.pm and + Moose::Util::TypeConstraints into the Moose::Meta::TypeConstraint module + +This will make it much easier to generate TCs on their own, without +having to use the sugar layer. This should also clean up their APIs +as well, which will make it easier to subclass them. + +- create an official TC registry API + +Right now the registration of the TC is a by-product of creation in the sugar +layer, this is bad and make extension of TCs difficult. I am not sure if this +registry API should exist as part of Moose::Util::TypeConstraints, or of we +should create a complete registry object itself. + +This registry should be a singleton, but M::U::TC should enforce that lifecycle +choice so that you can use your own registry if you really want too. + +I mean parent of the registry. So that I can create my own registry +object for a given class, and any retrieval of a type constraint from +this object would automatically search parent registries as well. + +- refactor the various TC internals to make it more subclassing friendly + +This also includes the coercion stuff as well. This should give you what you +need to make your object/class bound stuff. + +- move the container TCs from MooseX::AttributeHelpers into Moose core + +These have proven so useful for me in the latest $work project that I think +they should really be core. + +- allow a switch of some kind to optionally turn TC checking off at runtime + +The type checks can get expensive and some people have suggested that allowing +the checks to be turned off would be helpful for deploying into performance +intensive systems. Perhaps this can actually be done as an option to make_immutable? + +- misc. minor bits + +* make the errors for TCs use ->message +* look into localizing the messages too +* make ANON TCs be lazy, so they can possibly be subsituted for the real thing later +* make ANON TCs more introspectable + + +----------------------------------------------------------- +-- Roles refactor +----------------------------------------------------------- + + +----------------------------------------------------------- +-- Immutable refactor +----------------------------------------------------------- \ No newline at end of file diff --git a/lib/Moose.pm b/lib/Moose.pm index 0201714..7aa481d 100644 --- a/lib/Moose.pm +++ b/lib/Moose.pm @@ -4,7 +4,7 @@ package Moose; use strict; use warnings; -our $VERSION = '0.25'; +our $VERSION = '0.26'; our $AUTHORITY = 'cpan:STEVAN'; use Scalar::Util 'blessed', 'reftype'; @@ -22,6 +22,8 @@ use Moose::Meta::TypeCoercion; use Moose::Meta::Attribute; use Moose::Meta::Instance; +use Moose::Meta::Role; + use Moose::Object; use Moose::Util::TypeConstraints; @@ -234,7 +236,7 @@ use Moose::Util::TypeConstraints; $_->meta->make_immutable( inline_constructor => 0, - inline_accessors => 0, + inline_accessors => 1, ) for ( 'Moose::Meta::Attribute', 'Moose::Meta::Class', @@ -242,12 +244,18 @@ $_->meta->make_immutable( 'Moose::Meta::TypeConstraint', 'Moose::Meta::TypeConstraint::Union', + 'Moose::Meta::TypeConstraint::Container', 'Moose::Meta::TypeCoercion', 'Moose::Meta::Method', 'Moose::Meta::Method::Accessor', 'Moose::Meta::Method::Constructor', + 'Moose::Meta::Method::Destructor', 'Moose::Meta::Method::Overriden', + + 'Moose::Meta::Role', + 'Moose::Meta::Role::Method', + 'Moose::Meta::Role::Method::Required', ); 1; diff --git a/lib/Moose/Meta/Role.pm b/lib/Moose/Meta/Role.pm index 0609cee..cf74e9b 100644 --- a/lib/Moose/Meta/Role.pm +++ b/lib/Moose/Meta/Role.pm @@ -14,6 +14,7 @@ our $AUTHORITY = 'cpan:STEVAN'; use Moose::Meta::Class; use Moose::Meta::Role::Method; +use Moose::Meta::Role::Method::Required; use base 'Class::MOP::Module'; diff --git a/lib/Moose/Meta/Role/Method/Required.pm b/lib/Moose/Meta/Role/Method/Required.pm index 18d5f56..38271c2 100644 --- a/lib/Moose/Meta/Role/Method/Required.pm +++ b/lib/Moose/Meta/Role/Method/Required.pm @@ -7,6 +7,8 @@ use warnings; our $VERSION = '0.01'; our $AUTHORITY = 'cpan:STEVAN'; +use base 'Moose::Meta::Role::Method'; + 1; __END__ diff --git a/lib/Moose/Meta/TypeConstraint.pm b/lib/Moose/Meta/TypeConstraint.pm index 8295230..7a7cddf 100644 --- a/lib/Moose/Meta/TypeConstraint.pm +++ b/lib/Moose/Meta/TypeConstraint.pm @@ -12,14 +12,18 @@ use Sub::Name 'subname'; use Carp 'confess'; use Scalar::Util 'blessed'; -our $VERSION = '0.08'; +our $VERSION = '0.09'; our $AUTHORITY = 'cpan:STEVAN'; use Moose::Meta::TypeConstraint::Union; +use Moose::Meta::TypeConstraint::Container; __PACKAGE__->meta->add_attribute('name' => (reader => 'name' )); __PACKAGE__->meta->add_attribute('parent' => (reader => 'parent' )); -__PACKAGE__->meta->add_attribute('constraint' => (reader => 'constraint')); +__PACKAGE__->meta->add_attribute('constraint' => ( + reader => 'constraint', + writer => '_set_constraint', +)); __PACKAGE__->meta->add_attribute('message' => ( accessor => 'message', predicate => 'has_message' diff --git a/lib/Moose/Meta/TypeConstraint/Container.pm b/lib/Moose/Meta/TypeConstraint/Container.pm new file mode 100644 index 0000000..d68859d --- /dev/null +++ b/lib/Moose/Meta/TypeConstraint/Container.pm @@ -0,0 +1,104 @@ +package Moose::Meta::TypeConstraint::Container; + +use strict; +use warnings; +use metaclass; + +use Scalar::Util 'blessed'; +use Carp 'confess'; + +our $VERSION = '0.01'; +our $AUTHORITY = 'cpan:STEVAN'; + +use base 'Moose::Meta::TypeConstraint'; + +__PACKAGE__->meta->add_attribute('container_type' => ( + accessor => 'container_type', + predicate => 'has_container_type', +)); + +sub compile_type_constraint { + my $self = shift; + + my $parent_name = $self->parent->name; + + ($self->has_container_type) + || confess "You cannot create a Container type without one"; + + my $container_type = $self->container_type; + + (blessed $container_type && $container_type->isa('Moose::Meta::TypeConstraint')) + || confess "The container type must be a Moose meta type"; + + my $constraint; + + if ($parent_name eq 'ArrayRef') { + $constraint = sub { + foreach my $x (@$_) { + ($container_type->check($x)) || return + } 1; + }; + } + elsif ($parent_name eq 'HashRef') { + $constraint = sub { + foreach my $x (values %$_) { + ($container_type->check($x)) || return + } 1; + }; + } + else { + confess "Your isa must be either ArrayRef or HashRef (sorry no subtype support yet)"; + } + + $self->_set_constraint($constraint); + + $self->SUPER::compile_type_constraint; +} + +1; + +__END__ + + +=pod + +=head1 NAME + +Moose::Meta::TypeConstraint::Container + +=head1 DESCRIPTION + +=head1 METHODS + +=over 4 + +=item B + +=item B + +=item B + +=item B + +=back + +=head1 BUGS + +All complex software has bugs lurking in it, and this module is no +exception. If you find a bug please either email me, or add the bug +to cpan-RT. + +=head1 AUTHOR + +Stevan Little Estevan@iinteractive.comE + +=head1 COPYRIGHT AND LICENSE + +Copyright 2006, 2007 by Infinity Interactive, Inc. + +L + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself. + +=cut diff --git a/lib/Moose/Meta/TypeConstraint/Union.pm b/lib/Moose/Meta/TypeConstraint/Union.pm index 03d7f8f..25fe9e6 100644 --- a/lib/Moose/Meta/TypeConstraint/Union.pm +++ b/lib/Moose/Meta/TypeConstraint/Union.pm @@ -5,9 +5,18 @@ use strict; use warnings; use metaclass; -our $VERSION = '0.05'; +our $VERSION = '0.06'; our $AUTHORITY = 'cpan:STEVAN'; +# NOTE: +# this is not really correct, but +# I think it shoul be here anyway. +# In truth, this should implement +# the same abstract base/interface +# as the TC moule. +# - SL +use base 'Moose::Meta::TypeConstraint'; + __PACKAGE__->meta->add_attribute('type_constraints' => ( accessor => 'type_constraints', default => sub { [] } diff --git a/t/061_container_type_constraint.t b/t/061_container_type_constraint.t new file mode 100644 index 0000000..ea3be87 --- /dev/null +++ b/t/061_container_type_constraint.t @@ -0,0 +1,67 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use Test::More no_plan => 1; +use Test::Exception; + +BEGIN { + use_ok('Moose'); + use_ok('Moose::Util::TypeConstraints'); + use_ok('Moose::Meta::TypeConstraint::Container'); +} + +# Array of Ints + +my $array_of_ints = Moose::Meta::TypeConstraint::Container->new( + name => 'ArrayRef[Int]', + parent => find_type_constraint('ArrayRef'), + container_type => find_type_constraint('Int'), +); +isa_ok($array_of_ints, 'Moose::Meta::TypeConstraint::Container'); +isa_ok($array_of_ints, 'Moose::Meta::TypeConstraint'); + +ok($array_of_ints->check([ 1, 2, 3, 4 ]), '... [ 1, 2, 3, 4 ] passed successfully'); +ok(!$array_of_ints->check([qw/foo bar baz/]), '... [qw/foo bar baz/] failed successfully'); +ok(!$array_of_ints->check([ 1, 2, 3, qw/foo bar/]), '... [ 1, 2, 3, qw/foo bar/] failed successfully'); + +ok(!$array_of_ints->check(1), '... 1 failed successfully'); +ok(!$array_of_ints->check({}), '... {} failed successfully'); +ok(!$array_of_ints->check(sub { () }), '... sub { () } failed successfully'); + +# Hash of Ints + +my $hash_of_ints = Moose::Meta::TypeConstraint::Container->new( + name => 'HashRef[Int]', + parent => find_type_constraint('HashRef'), + container_type => find_type_constraint('Int'), +); +isa_ok($hash_of_ints, 'Moose::Meta::TypeConstraint::Container'); +isa_ok($hash_of_ints, 'Moose::Meta::TypeConstraint'); + +ok($hash_of_ints->check({ one => 1, two => 2, three => 3 }), '... { one => 1, two => 2, three => 3 } passed successfully'); +ok(!$hash_of_ints->check({ 1 => 'one', 2 => 'two', 3 => 'three' }), '... { 1 => one, 2 => two, 3 => three } failed successfully'); +ok(!$hash_of_ints->check({ 1 => 'one', 2 => 'two', three => 3 }), '... { 1 => one, 2 => two, three => 3 } failed successfully'); + +ok(!$hash_of_ints->check(1), '... 1 failed successfully'); +ok(!$hash_of_ints->check([]), '... [] failed successfully'); +ok(!$hash_of_ints->check(sub { () }), '... sub { () } failed successfully'); + +# Array of Array of Ints + +my $array_of_array_of_ints = Moose::Meta::TypeConstraint::Container->new( + name => 'ArrayRef[ArrayRef[Int]]', + parent => find_type_constraint('ArrayRef'), + container_type => $array_of_ints, +); +isa_ok($array_of_array_of_ints, 'Moose::Meta::TypeConstraint::Container'); +isa_ok($array_of_array_of_ints, 'Moose::Meta::TypeConstraint'); + +ok($array_of_array_of_ints->check( + [[ 1, 2, 3 ], [ 4, 5, 6 ]] +), '... [[ 1, 2, 3 ], [ 4, 5, 6 ]] passed successfully'); +ok(!$array_of_array_of_ints->check( + [[ 1, 2, 3 ], [ qw/foo bar/ ]] +), '... [[ 1, 2, 3 ], [ qw/foo bar/ ]] failed successfully'); +