From: John Napiorkowski Date: Fri, 25 Jun 2010 01:25:21 +0000 (-0400) Subject: more docs, test fixes and prep for release X-Git-Tag: 0.02 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=gitmo%2FMooseX-Dependent.git;a=commitdiff_plain;h=c9ecd5066a4cf4e7124372ba0efbd89841553084 more docs, test fixes and prep for release --- diff --git a/Changes b/Changes index 3cfe1e2..4924661 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,13 @@ Revision history for MooseX-Types-Parameterized - -0.01 24 June 2010 + +0.02 24 June 2010 + - numerous documentation and code formatting fixes + - fixed coercions + - better custom error messages + - more tests + - fixed missing dependency + +0.01 23 June 2010 - Completed basic requirements, documentation and tests. - - sending this out from YAPC::NA, while in a talk on extending - Moose :) + - sending this out from YAPC::NA, while in a talk on extending + Moose :) diff --git a/lib/MooseX/Types/Parameterizable.pm b/lib/MooseX/Types/Parameterizable.pm index b75924b..d62d7fe 100644 --- a/lib/MooseX/Types/Parameterizable.pm +++ b/lib/MooseX/Types/Parameterizable.pm @@ -2,7 +2,7 @@ package MooseX::Types::Parameterizable; use 5.008; -our $VERSION = '0.01'; +our $VERSION = '0.02'; $VERSION = eval $VERSION; use Moose::Util::TypeConstraints; @@ -26,7 +26,7 @@ The follow is example usage. ## Create a type constraint that is a string but parameterizes an integer ## that is used as a maximum length constraint on that string, similar to - ## an SQL Varchar type. + ## a SQL Varchar database type. subtype Varchar, as Parameterizable[Str,Int], @@ -54,13 +54,13 @@ The follow is example usage. ## Dies with an invalid constraint for 'varchar_five' my $object2 = __PACKAGE__->new( - varchar_five => '12345678', + varchar_five => '12345678', ## too long! varchar_ten => '123456789', ); ## varchar_five coerces as expected my $object3 = __PACKAGE__->new( - varchar_five => [qw/aa bb/], + varchar_five => [qw/aa bb/], ## coerces to "aabb" varchar_ten => '123456789', ); @@ -68,14 +68,20 @@ See t/05-pod-examples.t for runnable versions of all POD code =head1 DESCRIPTION -A L library for creating parameterizable types. A parameterizable type -constraint for all intents and uses is a subclass of a parent type, but adds a -secondary type parameter which is available to constraint callbacks (such as -inside the 'where' clause) or in the coercions. +A L library for creating parameterizable types. A parameterizable +type constraint for all intents and uses is a subclass of a parent type, but +adds additional type parameters which are available to constraint callbacks +(such as inside the 'where' clause of a type constraint definition) or in the +coercions. -This allows you to create a type that has additional runtime advice, such as a -set of numbers within which another number must be unique, or allowable ranges -for a integer, such as in: +If you have L experience, you probably are familiar with the builtin +parameterizable type constraints 'ArrayRef' and 'HashRef'. This type constraint +lets you generate your own versions of parameterized constraints that work +similarly. See L for more. + +Using this type constraint, you can generate new type constraints that have +additional runtime advice, such as being able to specify maximum and minimum +values for an Int (integer) type constraint: subtype Range, as Dict[max=>Int, min=>Int], @@ -94,9 +100,11 @@ for a integer, such as in: RangedInt([{min=>10,max=>100}])->check(50); ## OK RangedInt([{min=>50, max=>75}])->check(99); ## Not OK, 99 exceeds max - -This throws a hard Moose exception. You'll need to capture it in an eval or -related exception catching system (see L or .) + +The type parameter must be valid against the type constraint given. If you pass +an invalid value this throws a hard Moose exception. You'll need to capture it +in an eval or related exception catching system (see L or .) +For example the following would throw a hard error (and not just return false) RangedInt([{min=>99, max=>10}])->check(10); ## Not OK, not a valid Range! @@ -261,7 +269,7 @@ it is available to the constraint. =head2 Recursion - TBD + TBD - Need more tests. =head1 TYPE CONSTRAINTS diff --git a/t/02-types-parameterizable-extended.t b/t/02-types-parameterizable-extended.t index 3c87820..7e94410 100644 --- a/t/02-types-parameterizable-extended.t +++ b/t/02-types-parameterizable-extended.t @@ -1,10 +1,9 @@ - -use Test::More; { - +BEGIN { use strict; use warnings; - - eval "use MooseX::Types::Structured"; if($@) { + + use Test::More; + eval "use MooseX::Types::Structured qw(Tuple Dict slurpy)"; if($@) { plan skip_all => "MooseX::Types:Structured Required for advanced Tests"; } else { eval "use Set::Scalar"; if($@) { @@ -13,160 +12,160 @@ use Test::More; { plan tests => 37; } } +} - use MooseX::Types::Structured qw(Tuple Dict slurpy); - use MooseX::Types::Parameterizable qw(Parameterizable); - use MooseX::Types::Moose qw(Int Str); - use Moose::Util::TypeConstraints; - - use MooseX::Types -declare=>[qw( - Set UniqueInt UniqueInSet Range RangedInt PositiveRangedInt1 - PositiveRangedInt2 PositiveInt PositiveRange NameAge NameBetween18and35Age - )]; - - ok class_type("Set::Scalar"), 'Created Set::Scalar class_type'; - ok subtype( Set, as "Set::Scalar"), 'Created Set subtype'; - - ok subtype( UniqueInt, - as Parameterizable[Int, Set], - where { - my ($int, $set) = @_; - return !$set->has($int); - }), 'Created UniqueInt Parameterizable Type'; - - ok( (my $set_obj = Set::Scalar->new(1,2,3,4,5)), 'Create Set Object'); - - ok !UniqueInt([$set_obj])->check(1), "Not OK, since one isn't unique in $set_obj"; - ok !UniqueInt([$set_obj])->check('AAA'), "Not OK, since AAA is not an Int"; - ok UniqueInt([$set_obj])->check(100), "OK, since 100 isn't in the set"; +use MooseX::Types::Parameterizable qw(Parameterizable); +use MooseX::Types::Moose qw(Int Str); +use Moose::Util::TypeConstraints; + +use MooseX::Types -declare=>[qw( + Set UniqueInt UniqueInSet Range RangedInt PositiveRangedInt1 + PositiveRangedInt2 PositiveInt PositiveRange NameAge NameBetween18and35Age +)]; + +ok class_type("Set::Scalar"), 'Created Set::Scalar class_type'; +ok subtype( Set, as "Set::Scalar"), 'Created Set subtype'; + +ok subtype( UniqueInt, + as Parameterizable[Int, Set], + where { + my ($int, $set) = @_; + return !$set->has($int); + }), 'Created UniqueInt Parameterizable Type'; + +ok( (my $set_obj = Set::Scalar->new(1,2,3,4,5)), 'Create Set Object'); + +ok !UniqueInt([$set_obj])->check(1), "Not OK, since one isn't unique in $set_obj"; +ok !UniqueInt([$set_obj])->check('AAA'), "Not OK, since AAA is not an Int"; +ok UniqueInt([$set_obj])->check(100), "OK, since 100 isn't in the set"; + +ok( (my $unique = UniqueInt[$set_obj]), 'Created Anonymous typeconstraint'); +ok $unique->check(10), "OK, 10 is unique"; +ok !$unique->check(2), "Not OK, '2' is already in the set"; + +ok( subtype(UniqueInSet, as UniqueInt[$set_obj]), 'Created Subtype'); +ok UniqueInSet->check(99), '99 is unique'; +ok !UniqueInSet->check(3), 'Not OK, 3 is already in the set'; + +CHECKHARDEXCEPTION: { + eval { UniqueInt->check(1000) }; + like $@, + qr/Validation failed for 'main::Set' with value undef/, + 'Got Expected Error'; + + eval { UniqueInt->validate(1000) }; + like $@, + qr/Validation failed for 'main::Set' with value undef/, + 'Got Expected Error'; +} + +subtype Range, + as Dict[max=>Int, min=>Int], + where { + my ($range) = @_; + return $range->{max} > $range->{min}; + }; + +subtype RangedInt, + as Parameterizable[Int, Range], + where { + my ($value, $range) = @_; + return ($value >= $range->{min} && + $value <= $range->{max}); + }; - ok( (my $unique = UniqueInt[$set_obj]), 'Created Anonymous typeconstraint'); - ok $unique->check(10), "OK, 10 is unique"; - ok !$unique->check(2), "Not OK, '2' is already in the set"; +ok RangedInt([{min=>10,max=>100}])->check(50), '50 in the range'; +ok !RangedInt([{min=>50, max=>75}])->check(99),'99 exceeds max'; +ok !RangedInt([{min=>50, max=>75}])->check('aa'), '"aa" not even an Int'; + +CHECKRANGEDINT: { + eval { + RangedInt([{min=>99, max=>10}])->check(10); ## Not OK, not a valid Range! + }; - ok( subtype(UniqueInSet, as UniqueInt[$set_obj]), 'Created Subtype'); - ok UniqueInSet->check(99), '99 is unique'; - ok !UniqueInSet->check(3), 'Not OK, 3 is already in the set'; + like $@, + qr/Validation failed for 'main::Range'/, + 'Got Expected Error'; +} + +ok RangedInt([min=>10,max=>100])->check(50), '50 in the range'; +ok !RangedInt([min=>50, max=>75])->check(99),'99 exceeds max'; +ok !RangedInt([min=>50, max=>75])->check('aa'), '"aa" not even an Int'; + +CHECKRANGEDINT2: { + eval { + RangedInt([min=>99, max=>10])->check(10); ## Not OK, not a valid Range! + }; - CHECKHARDEXCEPTION: { - eval { UniqueInt->check(1000) }; - like $@, - qr/Validation failed for 'main::Set' with value undef/, - 'Got Expected Error'; - - eval { UniqueInt->validate(1000) }; - like $@, - qr/Validation failed for 'main::Set' with value undef/, - 'Got Expected Error'; - } + like $@, + qr/Validation failed for 'main::Range'/, + 'Got Expected Error'; +} + +subtype PositiveRangedInt1, + as RangedInt, + where { + shift >= 0; + }; + +ok PositiveRangedInt1([min=>10,max=>100])->check(50), '50 in the range'; +ok !PositiveRangedInt1([min=>50, max=>75])->check(99),'99 exceeds max'; +ok !PositiveRangedInt1([min=>50, max=>75])->check('aa'), '"aa" not even an Int'; + +CHECKRANGEDINT2: { + eval { + PositiveRangedInt1([min=>99, max=>10])->check(10); ## Not OK, not a valid Range! + }; - subtype Range, - as Dict[max=>Int, min=>Int], - where { - my ($range) = @_; - return $range->{max} > $range->{min}; - }; - - subtype RangedInt, - as Parameterizable[Int, Range], - where { - my ($value, $range) = @_; - return ($value >= $range->{min} && - $value <= $range->{max}); - }; - - ok RangedInt([{min=>10,max=>100}])->check(50), '50 in the range'; - ok !RangedInt([{min=>50, max=>75}])->check(99),'99 exceeds max'; - ok !RangedInt([{min=>50, max=>75}])->check('aa'), '"aa" not even an Int'; - - CHECKRANGEDINT: { - eval { - RangedInt([{min=>99, max=>10}])->check(10); ## Not OK, not a valid Range! - }; - - like $@, - qr/Validation failed for 'main::Range'/, - 'Got Expected Error'; - } + like $@, + qr/Validation failed for 'main::Range'/, + 'Got Expected Error'; +} - ok RangedInt([min=>10,max=>100])->check(50), '50 in the range'; - ok !RangedInt([min=>50, max=>75])->check(99),'99 exceeds max'; - ok !RangedInt([min=>50, max=>75])->check('aa'), '"aa" not even an Int'; - - CHECKRANGEDINT2: { - eval { - RangedInt([min=>99, max=>10])->check(10); ## Not OK, not a valid Range! - }; - - like $@, - qr/Validation failed for 'main::Range'/, - 'Got Expected Error'; - } +ok !PositiveRangedInt1([min=>-100,max=>100])->check(-10), '-10 is not positive'; - subtype PositiveRangedInt1, - as RangedInt, - where { - shift >= 0; - }; - - ok PositiveRangedInt1([min=>10,max=>100])->check(50), '50 in the range'; - ok !PositiveRangedInt1([min=>50, max=>75])->check(99),'99 exceeds max'; - ok !PositiveRangedInt1([min=>50, max=>75])->check('aa'), '"aa" not even an Int'; - - CHECKRANGEDINT2: { - eval { - PositiveRangedInt1([min=>99, max=>10])->check(10); ## Not OK, not a valid Range! - }; - - like $@, - qr/Validation failed for 'main::Range'/, - 'Got Expected Error'; - } +subtype PositiveInt, + as Int, + where { + my ($value, $range) = @_; + return $value >= 0; + }; - ok !PositiveRangedInt1([min=>-100,max=>100])->check(-10), '-10 is not positive'; +## subtype Range to re-parameterize Range with subtypes +subtype PositiveRange, + as Range[max=>PositiveInt, min=>PositiveInt]; - subtype PositiveInt, - as Int, - where { - my ($value, $range) = @_; - return $value >= 0; - }; +## create subtype via reparameterizing +subtype PositiveRangedInt2, + as RangedInt[PositiveRange]; - ## subtype Range to re-parameterize Range with subtypes - subtype PositiveRange, - as Range[max=>PositiveInt, min=>PositiveInt]; - - ## create subtype via reparameterizing - subtype PositiveRangedInt2, - as RangedInt[PositiveRange]; - - ok PositiveRangedInt2([min=>10,max=>100])->check(50), '50 in the range'; - ok !PositiveRangedInt2([min=>50, max=>75])->check(99),'99 exceeds max'; - ok !PositiveRangedInt2([min=>50, max=>75])->check('aa'), '"aa" not even an Int'; - - CHECKRANGEDINT2: { - eval { - PositiveRangedInt2([min=>-100,max=>100])->check(-10); ## Not OK, not a valid Range! - }; - - like $@, - qr/Validation failed for 'main::PositiveRange'/, - 'Got Expected Error'; - } +ok PositiveRangedInt2([min=>10,max=>100])->check(50), '50 in the range'; +ok !PositiveRangedInt2([min=>50, max=>75])->check(99),'99 exceeds max'; +ok !PositiveRangedInt2([min=>50, max=>75])->check('aa'), '"aa" not even an Int'; - subtype NameAge, - as Tuple[Str, Int]; - - ok NameAge->check(['John',28]), 'Good NameAge'; - ok !NameAge->check(['John','Napiorkowski']), 'Bad NameAge'; +CHECKRANGEDINT2: { + eval { + PositiveRangedInt2([min=>-100,max=>100])->check(-10); ## Not OK, not a valid Range! + }; - subtype NameBetween18and35Age, - as NameAge[ - Str, - PositiveRangedInt2[min=>18,max=>35], - ]; - - ok NameBetween18and35Age->check(['John',28]), 'Good NameBetween18and35Age'; - ok !NameBetween18and35Age->check(['John','Napiorkowski']), 'Bad NameBetween18and35Age'; - ok !NameBetween18and35Age->check(['John',99]), 'Bad NameBetween18and35Age'; + like $@, + qr/Validation failed for 'main::PositiveRange'/, + 'Got Expected Error'; } + +subtype NameAge, + as Tuple[Str, Int]; + +ok NameAge->check(['John',28]), 'Good NameAge'; +ok !NameAge->check(['John','Napiorkowski']), 'Bad NameAge'; + +subtype NameBetween18and35Age, + as NameAge[ + Str, + PositiveRangedInt2[min=>18,max=>35], + ]; + +ok NameBetween18and35Age->check(['John',28]), 'Good NameBetween18and35Age'; +ok !NameBetween18and35Age->check(['John','Napiorkowski']), 'Bad NameBetween18and35Age'; +ok !NameBetween18and35Age->check(['John',99]), 'Bad NameBetween18and35Age'; + diff --git a/t/05-pod-examples.t b/t/05-pod-examples.t index e5ded22..1810599 100644 --- a/t/05-pod-examples.t +++ b/t/05-pod-examples.t @@ -11,10 +11,6 @@ use Test::More; use MooseX::Types::Moose qw(Str Int ArrayRef); use MooseX::Types -declare=>[qw(Varchar)]; - ## Create a type constraint that is a string but parameterizes an integer - ## that is used as a maximum length constraint on that string, similar to - ## an SQL Varchar type. - subtype Varchar, as Parameterizable[Str,Int], where { @@ -67,6 +63,55 @@ use Test::More; 'coercion as expected'; } +{ + package Test::MooseX::Types::Parameterizable::Description; + + use Moose; + use MooseX::Types::Parameterizable qw(Parameterizable); + use MooseX::Types::Moose qw(HashRef Int); + use MooseX::Types -declare=>[qw(Range RangedInt)]; + + ## Minor change from docs to avoid additional test dependencies + subtype Range, + as HashRef[Int], + where { + my ($range) = @_; + return $range->{max} > $range->{min}; + }, + message { "Not a Valid range [ $_->{max} not > $_->{min} ] " }; + + subtype RangedInt, + as Parameterizable[Int, Range], + where { + my ($value, $range) = @_; + return ($value >= $range->{min} && + $value <= $range->{max}); + }; + + Test::More::ok RangedInt([{min=>10,max=>100}])->check(50); + Test::More::ok !RangedInt([{min=>50, max=>75}])->check(99); + + eval { + Test::More::ok !RangedInt([{min=>99, max=>10}])->check(10); + }; + + Test::More::ok $@, 'There was an error'; + Test::More::like $@, qr(Not a Valid range), 'Correct custom error'; + + Test::More::ok RangedInt([min=>10,max=>100])->check(50); + Test::More::ok ! RangedInt([min=>50, max=>75])->check(99); + + eval { + RangedInt([min=>99, max=>10])->check(10); + }; + + Test::More::ok $@, 'There was an error'; + Test::More::like $@, qr(Not a Valid range), 'Correct custom error'; + + +} + + done_testing;