Репозиторий Sisyphus
Последнее обновление: 1 октября 2023 | Пакетов: 18631 | Посещений: 37569955
en ru br
Репозитории ALT

Группа :: Разработка/Perl
Пакет: perl-MooX-Types-MooseLike

 Главная   Изменения   Спек   Патчи   Исходники   Загрузить   Gear   Bugs and FR  Repocop 

MooX-Types-MooseLike-0.25/000075500000000000000000000000001217715246600153225ustar00rootroot00000000000000MooX-Types-MooseLike-0.25/.gitignore000064400000000000000000000003271217715246600173140ustar00rootroot00000000000000.includepath
.project
.build
MooX-Types-MooseLike-*
MANIFEST
MANIFEST.bak
META.*
MYMETA.*
Makefile
Makefile.old
README
blib/
pm_to_blib
Distar/
.tidyall.d/

# yes that's right, distar makes it for us
MANIFEST.SKIP

MooX-Types-MooseLike-0.25/Changes000064400000000000000000000076521217715246600166270ustar00rootroot000000000000000.25 - 2013-07-29
- Don't trigger bool overrides when checking for object instance type
[RT#87382] (Mithaldu)
- Make Moo a build dep. instead of run dep.

0.24 - 2013-07-10
- Upgrade Num test, keep in sync w/ Moose (autarch)
- Improve documentation

0.23 - 2013-03-07
- Fix regression in subtypes defined with a string (for the parent test)

0.22 - 2013-03-04
- Allow subtyping of parameterized types (haarg)
- Extract SetObject and Numeric types into their own distributions

0.21 - 2013-02-16
- Allow type libraries more control over inflation to Moose types (tobyink)

0.20 - 2013-02-11
- Improve documentation

0.19 - 2013-02-10
- New type: Enum

0.18 - 2013-02-09
- AnyOf now supports parameterized types
API CHANGE: AnyOf no longer takes types in a string
This means you should write: AnyOf[Int, CodeRef]
instead of: AnyOf['Int', 'CodeRef']
- New type: AllOf (intersection of defined types)
- Simplify new make_type() code (haarg)

0.17 - 2013-02-08
- New type: AnyOf (union of defined types)

0.16 - 2012-10-11
- Handle undef with grace (github issues 13 and 14)
- Improve POD for: InstanceOf, ConsumerOf, HasMethods
- Restrict ConsumerOf and HasMethods to something blessed (i.e. an instance)
- Bump Moo requirements (better role composition and isa builder check)

0.15 - 2012-09-28
- Relax InstanceOf definition to use isa()

0.14 - 2012-09-19
- Remove pesky Set::Object from build requirements

0.13 - 2012-09-18
- Only test SetObject when Set::Object is already installed

0.12 - 2012-09-11
Release Name: Independence for Catalunya
- Improve POD
- Add testing dependency
- Correct SetObject
- Enable ConsumerOf to accept multiple roles

0.11 - 2012-09-10
- Generalize parameterizable (fREW)
- Rework type string arguments to follow ['Str'] pattern (mattp)
- New types: InstanceOf, ConsumerOf and HasMethods

0.10 - 2012-08-26
- Allow Type() arguments (mattp)
- Improve error handling for parameterized types (mattp)
- Improve documentation

0.09 - 2012-07-23
- Preserve attribute properties defined after 'isa'
[github issue #7]
Failing tests (xsawyerx)

0.08 - 2012-07-03
- Support for parameterized type: Maybe
For example, isa => Maybe[Int]

0.07 - 2012-06-29
- Support for parameterized types: ArrayRef, HashRef, ScalarRef
This means one can now write: isa => ArrayRef[HashRef]

0.06 - 2012-06-27
- Make subtype use full test [RT#78074] (SineSwiper)
- Correct SingleDigit type definition [RT#78074] (SineSwiper)
- Add Stack Trace on Exception [RT#77583] (Mithaldu)

0.05 - 2012-05-16
- Add Deps [RT#77225] (SymKat)
- Add META (SineSwiper)

0.04 - 2012-04-27
ADDITIONS:
* Add support for Moo type inflation to Moose (mst)

API CHANGE:
* Numeric types equivalent to MooseX::Type::Common::Numeric

0.03 - 2012-03-19
IMPROVEMENTS:
* Bunches of POD [RT#73519]
* Simplified Exporter usage [RT#75209] (dolmen)
* Removed Data::Dumper::Concise dependency [RT#73469] (rsimoes)

ADDITIONS:
* Numeric Types
* Experimental type building API

API CHANGE:
* Basic types are now found in MooX::Types::MooseLike::Base
instead of MooX::Types::MooseLike


0.02 - 2011-10-21
ADDITIONS:
* Most non-parameterized types of the basic Moose type hierarchy
are now supported. Exceptions are ClassName and RoleName
* Ability to re-use the type tests to build new ones via is_$type()

IMPROVEMENTS:
* Refactored generation of assert_Foo() to use a dispatch table
and captures for quote_sub.

FIXES:
* Add AutoPrereq to dist.ini so Makefile.PL gets dependencies generated

0.01 - 2011-09-15
Initial Release
MooX-Types-MooseLike-0.25/Makefile.PL000064400000000000000000000013641217715246600173000ustar00rootroot00000000000000use strict;
use warnings FATAL => 'all';
use 5.008001;
use ExtUtils::MakeMaker;
(do 'maint/Makefile.PL.include' or die $@) unless -f 'META.yml';

my %RUN_DEPS = (
'Module::Runtime' => 0.012,
);
my %BUILD_DEPS = (
'Moo' => 0.091010,
'Test::More' => 0.96,
'Test::Fatal' => 0.003,
);

WriteMakefile(
NAME => 'MooX::Types::MooseLike',
VERSION_FROM => 'lib/MooX/Types/MooseLike.pm',
PREREQ_PM => {
%RUN_DEPS,
},
BUILD_REQUIRES => {
%BUILD_DEPS,
},
META_ADD => {
resources => {
repository => 'git://github.com/mateu/MooX-Types-MooseLike.git',
bugtracker => 'http://rt.cpan.org/NoAuth/Bugs.html?Dist=MooX-Types-MooseLike',
IRC => 'irc://irc.perl.org/#web-simple',
},
},
LICENSE => 'perl',
);
MooX-Types-MooseLike-0.25/lib/000075500000000000000000000000001217715246600160705ustar00rootroot00000000000000MooX-Types-MooseLike-0.25/lib/MooX/000075500000000000000000000000001217715246600167525ustar00rootroot00000000000000MooX-Types-MooseLike-0.25/lib/MooX/Types/000075500000000000000000000000001217715246600200565ustar00rootroot00000000000000MooX-Types-MooseLike-0.25/lib/MooX/Types/MooseLike.pm000064400000000000000000000157331217715246600223140ustar00rootroot00000000000000package MooX::Types::MooseLike;
use strict;
use warnings FATAL => 'all';
use Exporter 5.57 'import';
our @EXPORT_OK;
push @EXPORT_OK, qw( exception_message inflate_type );
use Module::Runtime qw(require_module);
use Carp qw(confess croak);
use List::Util qw(first);

our $VERSION = '0.25';

sub register_types {
my ($type_definitions, $into, $moose_namespace) = @_;
foreach my $type_def (@{$type_definitions}) {
my $coderefs = make_type($type_def, $moose_namespace);
install_type($type_def->{name}, $coderefs, $into);
}
return;
}

sub install_type {
my ($type_name, $coderefs, $namespace) = @_;
my $is_type_name = 'is_' . $type_name;
my $type_full_name = $namespace . '::' . $type_name;
my $is_type_full_name = $namespace . '::' . $is_type_name;

{
no strict 'refs'; ## no critic qw(TestingAndDebugging::ProhibitNoStrict)
*{$type_full_name} = $coderefs->{type};
*{$is_type_full_name} = $coderefs->{is_type};
push @{"${namespace}::EXPORT_OK"}, $type_name, $is_type_name;
}
return;
}

sub make_type {
my ($type_definition, $moose_namespace) = @_;
my $test = $type_definition->{test};

if (my $subtype_of = $type_definition->{subtype_of}) {
if (!ref $subtype_of) {
my $from = $type_definition->{from}
|| croak "Must define a 'from' namespace for the parent type: $subtype_of when defining type: $type_definition->{name}";
$subtype_of = do {
no strict 'refs';
&{$from . '::' . $subtype_of}();
};
}
# Assume a (base) test always exists even if you must write: test => sub {1}
my $base_test = $test;
$test = sub {
my $value = shift;
local $@;
eval { $subtype_of->($value); 1 } or return;
# TODO implement: eval { $base_test->($value); 1 } paradigm
if ($base_test) {
$base_test->($value) or return;
}
return 1;
};
}

my $isa = sub {
return if $test->(@_);
local $Carp::Internal{"MooX::Types::MooseLike"} = 1; ## no critic qw(Variables::ProhibitPackageVars)
confess $type_definition->{message}->(@_) ; ## no critic qw(ErrorHandling::RequireUseOfExceptions)
};

if (ref $type_definition->{inflate}) {
$Moo::HandleMoose::TYPE_MAP{$isa} = $type_definition->{inflate};
}
elsif (exists $type_definition->{inflate} and not $type_definition->{inflate}) {
# no-op
}
else {
my $full_name =
defined $moose_namespace
? "${moose_namespace}::" . $type_definition->{name}
: $type_definition->{name};

$Moo::HandleMoose::TYPE_MAP{$isa} = sub {
require_module($moose_namespace) if $moose_namespace;
Moose::Util::TypeConstraints::find_type_constraint($full_name);
};
}

return {
type => sub {

# If we have a parameterized type then we want to check its values
if (ref($_[0]) eq 'ARRAY') {
my @params = @{$_[0]};
my $parameterized_isa = sub {

# Types that take other types as a parameter have a parameterizable
# part with the one exception: 'AnyOf'
if (my $parameterizer = $type_definition->{parameterizable}) {

# Can we assume @params is a list of coderefs?
if(my $culprit = first { (ref($_) ne 'CODE') } @params) {
croak "Expect all parameters to be coderefs, but found: $culprit";
}

# Check the containing type. We could pass @_, but it is such that:
# scalar @_ = 1 always in this context. In other words,
# an $isa only type checks one thing at a time.
$isa->($_[0]);

# Run the nested type coderefs on each value
foreach my $coderef (@params) {
foreach my $value ($parameterizer->($_[0])) {
$coderef->($value);
}
}
}
else {
# Note that while $isa only checks on value at a time
# We can pass it additional parameters as we do here.
# These additional parameters are then used in the type definition
# For example, see InstanceOf
$isa->($_[0], @params);
}
};

if (ref $type_definition->{inflate}) {
my $inflation = $type_definition->{inflate};
$Moo::HandleMoose::TYPE_MAP{$parameterized_isa} = sub { $inflation->(\@params) };
}

# Remove old $isa, but return the rest of the arguments
# so any specs defined after 'isa' don't get lost
shift;
return ($parameterized_isa, @_);
}
else {
return $isa;
}
},
is_type => sub { $test->(@_) },
};
}

sub exception_message {
my ($attribute_value, $type) = @_;
$attribute_value = defined $attribute_value ? $attribute_value : 'undef';
return "${attribute_value} is not ${type}!";
}

sub inflate_type {
my $coderef = shift;
if (my $inflator = $Moo::HandleMoose::TYPE_MAP{$coderef}) {
return $inflator->();
}
return Moose::Meta::TypeConstraint->new(
constraint => sub { eval { &$coderef; 1 } }
);
}

1;
__END__

=head1 NAME

MooX::Types::MooseLike - some Moosish types and a type builder

=head1 SYNOPSIS

package MyApp::Types;
use MooX::Types::MooseLike;
use base qw(Exporter);
our @EXPORT_OK = ();

# Define some types
my $defs = [{
name => 'MyType',
test => sub { predicate($_[0]) },
message => sub { "$_[0] is not the type we want!" }
},
{
name => 'VarChar',
test => sub {
my ($value, $param) = @_;
length($value) <= $param;
},
message => sub { "$_[0] is too large! It should be less than or equal to $_[1]." }
}];

# Make the types available - this adds them to @EXPORT_OK automatically.
MooX::Types::MooseLike::register_types($defs, __PACKAGE__);

...

# Somewhere in code that uses the type
package MyApp::Foo;
use Moo;
use MyApp::Types qw(MyType VarChar);
has attribute => (
is => 'ro',
isa => MyType,
);

has string => (
is => 'ro',
isa => VarChar[25]
);

=head1 DESCRIPTION

See L<MooX::Types::MooseLike::Base> for a list of available base types.
Its source also provides an example of how to build base types, along
with both parameterizable and non-parameterizable.

See L<MooX::Types::MooseLike::Numeric> for an example of how to build subtypes.

See L<MooX::Types::SetObject> for an example of how to build parameterized types.

=head1 AUTHOR

mateu - Mateu X. Hunter (cpan:MATEU) <hunter@missoula.org>

=head1 CONTRIBUTORS

mst - Matt S. Trout (cpan:MSTROUT) <mst@shadowcat.co.uk>

Mithaldu - Christian Walde (cpan:MITHALDU) <walde.christian@googlemail.com>

Matt Phillips (cpan:MATTP) <mattp@cpan.org>

Arthur Axel fREW Schmidt (cpan:FREW) <frioux@gmail.com>

Toby Inkster (cpan:TOBYINK) <tobyink@cpan.org>

Graham Knop (cpan:HAARG) <haarg@cpan.org>

=head1 COPYRIGHT

Copyright (c) 2011-2013 the MooX::Types::MooseLike L</AUTHOR> and
L</CONTRIBUTORS> as listed above.

=head1 LICENSE

This library is free software and may be distributed under the same terms
as perl itself.

=cut
MooX-Types-MooseLike-0.25/lib/MooX/Types/MooseLike/000075500000000000000000000000001217715246600217455ustar00rootroot00000000000000MooX-Types-MooseLike-0.25/lib/MooX/Types/MooseLike/Base.pm000064400000000000000000000411511217715246600231570ustar00rootroot00000000000000package MooX::Types::MooseLike::Base;
use strict;
use warnings FATAL => 'all';
use Scalar::Util qw(blessed);
use List::Util;
use MooX::Types::MooseLike qw( exception_message inflate_type );
use Exporter 5.57 'import';
our @EXPORT_OK = ();

our $VERSION = 0.25;

# These types act like those found in Moose::Util::TypeConstraints.
# Generally speaking, the same test is used.
sub some_basic_type_definitions {
return
(
{
name => 'Any',
test => sub { 1 },
message =>
sub { "If you get here you've achieved the impossible, congrats." }
},
{
name => 'Item',
test => sub { 1 },
message =>
sub { "If you get here you've achieved the impossible, congrats" }
},
{
name => 'Bool',

# test => sub { $_[0] == 0 || $_[0] == 1 },
test => sub {
!defined($_[0]) || $_[0] eq "" || "$_[0]" eq '1' || "$_[0]" eq '0';
},
message => sub { return exception_message($_[0], 'a Boolean') },
},

# Maybe has no test for itself, rather only the parameter type does
{
name => 'Maybe',
test => sub { 1 },
message => sub { 'Maybe only uses its parameterized type message' },
parameterizable => sub { return if (not defined $_[0]); $_[0] },
},
{
name => 'Undef',
test => sub { !defined($_[0]) },
message => sub { return exception_message($_[0], 'undef') },
},
);
}

sub defined_type_definitions {
return
({
name => 'Defined',
test => sub { defined($_[0]) },
message => sub { return exception_message($_[0], 'defined') },
},
{
name => 'Value',
test => sub { defined $_[0] and not ref($_[0]) },
message => sub { return exception_message($_[0], 'a value') },
},
{
name => 'Str',
test => sub { defined $_[0] and (ref(\$_[0]) eq 'SCALAR') },
message => sub { return exception_message($_[0], 'a string') },
},
{
name => 'Num',
test => sub {
my $val = $_[0];
defined $val and
($val =~ /\A[+-]?[0-9]+\z/) ||
( $val =~ /\A(?:[+-]?) # matches optional +- in the beginning
(?=[0-9]|\.[0-9]) # matches previous +- only if there is something like 3 or .3
[0-9]* # matches 0-9 zero or more times
(?:\.[0-9]+)? # matches optional .89 or nothing
(?:[Ee](?:[+-]?[0-9]+))? # matches E1 or e1 or e-1 or e+1 etc
\z/x );
},
message => sub {
my $nbr = shift;
if (not defined $nbr) {
$nbr = 'undef';
}
elsif (not (length $nbr)) {
$nbr = 'The empty string';
}
return exception_message($nbr, 'a number');
},
},
{
name => 'Int',
test => sub { defined $_[0] and ("$_[0]" =~ /^-?[0-9]+$/x) },
message => sub {
my $nbr = shift;
if (not defined $nbr) {
$nbr = 'undef';
}
elsif (not (length $nbr)) {
$nbr = 'The empty string';
}
return exception_message($nbr, 'an integer');
},
},
);
}

sub ref_type_definitions {
return
(
{
name => 'Ref',
test => sub { defined $_[0] and ref($_[0]) },
message => sub { return exception_message($_[0], 'a reference') },
},

{
name => 'ScalarRef',
test => sub { defined $_[0] and ref($_[0]) eq 'SCALAR' },
message => sub { return exception_message($_[0], 'a ScalarRef') },
parameterizable => sub { ${ $_[0] } },
inflate => sub {
require Moose::Util::TypeConstraints;
if (my $params = shift) {
return Moose::Util::TypeConstraints::_create_parameterized_type_constraint(
Moose::Util::TypeConstraints::find_type_constraint('ScalarRef'),
inflate_type(@$params),
);
}
return Moose::Util::TypeConstraints::find_type_constraint('ScalarRef');
},
},
{
name => 'ArrayRef',
test => sub { defined $_[0] and ref($_[0]) eq 'ARRAY' },
message => sub { return exception_message($_[0], 'an ArrayRef') },
parameterizable => sub { @{ $_[0] } },
inflate => sub {
require Moose::Util::TypeConstraints;
if (my $params = shift) {
return Moose::Util::TypeConstraints::_create_parameterized_type_constraint(
Moose::Util::TypeConstraints::find_type_constraint('ArrayRef'),
inflate_type(@$params),
);
}
return Moose::Util::TypeConstraints::find_type_constraint('ArrayRef');
},
},
{
name => 'HashRef',
test => sub { defined $_[0] and ref($_[0]) eq 'HASH' },
message => sub { return exception_message($_[0], 'a HashRef') },
parameterizable => sub { values %{ $_[0] } },
inflate => sub {
require Moose::Util::TypeConstraints;
if (my $params = shift) {
return Moose::Util::TypeConstraints::_create_parameterized_type_constraint(
Moose::Util::TypeConstraints::find_type_constraint('HashRef'),
inflate_type(@$params),
);
}
return Moose::Util::TypeConstraints::find_type_constraint('HashRef');
},
},
{
name => 'CodeRef',
test => sub { defined $_[0] and ref($_[0]) eq 'CODE' },
message => sub { return exception_message($_[0], 'a CodeRef') },
},
{
name => 'RegexpRef',
test => sub { defined $_[0] and ref($_[0]) eq 'Regexp' },
message => sub { return exception_message($_[0], 'a RegexpRef') },
},
{
name => 'GlobRef',
test => sub { defined $_[0] and ref($_[0]) eq 'GLOB' },
message => sub { return exception_message($_[0], 'a GlobRef') },
},
);
}

sub filehandle_type_definitions {
return
(
{
name => 'FileHandle',
test => sub {
defined $_[0]
and Scalar::Util::openhandle($_[0])
or (blessed($_[0]) && $_[0]->isa("IO::Handle"));
},
message => sub { return exception_message($_[0], 'a FileHandle') },
},
);
}

sub blessed_type_definitions {## no critic qw(Subroutines::ProhibitExcessComplexity)
return
(
{
name => 'Object',
test => sub { defined $_[0] and blessed($_[0]) and blessed($_[0]) ne 'Regexp' },
message => sub { return exception_message($_[0], 'an Object') },
},
{
name => 'InstanceOf',
test => sub {
my ($instance, @classes) = (shift, @_);
return if not defined $instance;
return if not blessed($instance);
my @missing_classes = grep { !$instance->isa($_) } @classes;
return (scalar @missing_classes ? 0 : 1);
},
message => sub {
my $instance = shift;
return "No instance given" if not defined $instance;
return "$instance is not blessed" if not blessed($instance);
my @missing_classes = grep { !$instance->isa($_) } @_;
my $s = (scalar @missing_classes) > 1 ? 'es' : '';
my $missing_classes = join ' ', @missing_classes;
return "$instance is not an instance of the class${s}: $missing_classes";
},
inflate => sub {
require Moose::Meta::TypeConstraint::Class;
if (my $classes = shift) {
if (@$classes == 1) {
return Moose::Meta::TypeConstraint::Class->new(class => @$classes);
}
elsif (@$classes > 1) {
return Moose::Meta::TypeConstraint->new(
parent => Moose::Util::TypeConstraints::find_type_constraint('Object'),
constraint => sub {
my $instance = shift;
my @missing_classes = grep { !$instance->isa($_) } @$classes;
return (scalar @missing_classes ? 0 : 1);
},
);
}
}
return Moose::Util::TypeConstraints::find_type_constraint('Object');
},
},
{
name => 'ConsumerOf',
test => sub {
my ($instance, @roles) = (shift, @_);
return if not defined $instance;
return if not blessed($instance);
return if (!$instance->can('does'));
my @missing_roles = grep { !$instance->does($_) } @roles;
return (scalar @missing_roles ? 0 : 1);
},
message => sub {
my $instance = shift;
return "No instance given" if not defined $instance;
return "$instance is not blessed" if not blessed($instance);
return "$instance is not a consumer of roles" if (!$instance->can('does'));
my @missing_roles = grep { !$instance->does($_) } @_;
my $s = (scalar @missing_roles) > 1 ? 's' : '';
my $missing_roles = join ' ', @missing_roles;
return "$instance does not consume the required role${s}: $missing_roles";
},
inflate => sub {
require Moose::Meta::TypeConstraint::Role;
if (my $roles = shift) {
if (@$roles == 1) {
return Moose::Meta::TypeConstraint::Role->new(role => @$roles);
}
elsif (@$roles > 1) {
return Moose::Meta::TypeConstraint->new(
parent => Moose::Util::TypeConstraints::find_type_constraint('Object'),
constraint => sub {
my $instance = shift;
return if (!$instance->can('does'));
my @missing_roles = grep { !$instance->does($_) } @$roles;
return (scalar @missing_roles ? 0 : 1);
},
);
}
}
return Moose::Util::TypeConstraints::find_type_constraint('Object');
},
},
{
name => 'HasMethods',
test => sub {
my ($instance, @methods) = (shift, @_);
return if not defined $instance;
return if not blessed($instance);
my @missing_methods = grep { !$instance->can($_) } @methods;
return (scalar @missing_methods ? 0 : 1);
},
message => sub {
my $instance = shift;
return "No instance given" if not defined $instance;
return "$instance is not blessed" if not blessed($instance);
my @missing_methods = grep { !$instance->can($_) } @_;
my $s = (scalar @missing_methods) > 1 ? 's' : '';
my $missing_methods = join ' ', @missing_methods;
return "$instance does not have the required method${s}: $missing_methods";
},
inflate => sub {
require Moose::Meta::TypeConstraint::DuckType;
if (my $methods = shift) {
return Moose::Meta::TypeConstraint::DuckType->new(methods => $methods);
}
return Moose::Util::TypeConstraints::find_type_constraint('Object');
},
},
{
name => 'Enum',
test => sub {
my ($value, @possible_values) = @_;
return if not defined $value;
return List::Util::first { $value eq $_ } @possible_values;
},
message => sub {
my ($value, @possible_values) = @_;
my $possible_values = join(', ', @possible_values);
return exception_message($value, "any of the possible values: ${possible_values}");
},
inflate => sub {
require Moose::Meta::TypeConstraint::Enum;
if (my $possible_values = shift) {
return Moose::Meta::TypeConstraint::Enum->new(values => $possible_values);
}
die "Enum cannot be inflated to a Moose type without any possible values";
},
},
);
}

sub logic_type_definitions {
return
(
{
name => 'AnyOf',
test => sub {
my ($value, @types) = @_;
foreach my $type (@types) {
return 1 if (eval {$type->($value); 1;});
}
return;
},
message => sub { return exception_message($_[0], 'any of the types') },
inflate => sub {
require Moose::Meta::TypeConstraint::Union;
if (my $types = shift) {
return Moose::Meta::TypeConstraint::Union->new(
type_constraints => [ map inflate_type($_), @$types ],
);
}
die "AnyOf cannot be inflated to a Moose type without any possible types";
},
},
{
name => 'AllOf',
test => sub { return 1; },
message => sub { 'AllOf only uses its parameterized type messages' },
parameterizable => sub { $_[0] },
inflate => 0,
},
);
}
sub type_definitions {
return
[
some_basic_type_definitions()
,defined_type_definitions()
,ref_type_definitions()
,filehandle_type_definitions()
,blessed_type_definitions()
,logic_type_definitions()
];
}

MooX::Types::MooseLike::register_types(type_definitions(), __PACKAGE__);

# Export an 'all' tag so one can easily import all types like so:
# use MooX::Types::MooseLike::Base qw(:all)
our %EXPORT_TAGS = ('all' => \@EXPORT_OK);

1;

__END__

=head1 NAME

MooX::Types::MooseLike::Base - Moose like types for Moo

=head1 SYNOPSIS

package MyPackage;
use Moo;
use MooX::Types::MooseLike::Base qw(:all);

has "beers_by_day_of_week" => (
isa => HashRef
);
has "current_BAC" => (
isa => Num
);

# Also supporting is_$type. For example, is_Int() can be used as follows
has 'legal_age' => (
is => 'ro',
isa => sub { die "$_[0] is not of legal age"
unless (is_Int($_[0]) && $_[0] > 17) },
);

=head1 DESCRIPTION

Moo attributes (like Moose) have an 'isa' property.
This module provides some basic types for this property.
One can import all types with ':all' tag or import
a list of types like:

use MooX::Types::MooseLike::Base qw/HashRef ArrayRef/;

so one could then declare some attributtes like:

has 'contact' => (
is => 'ro',
isa => HashRef,
);
has 'guest_list' => (
is => 'ro',
isa => ArrayRef[HashRef],
);

These types provide a check that the I<contact> attribute is a C<hash> reference,
and that the I<guest_list> is an C<array of hash> references.

=head1 TYPES (1st class functions - return a coderef)

=head2 Any

Any type (test is always true)

=head2 Item

Synonymous with Any type

=head2 Undef

A type that is not defined

=head2 Defined

A type that is defined

=head2 Bool

A boolean 1|0 type

=head2 Value

A non-reference type

=head2 Ref

A reference type

=head2 Str

A non-reference type where a reference to it is a SCALAR

=head2 Num

A number type

=head2 Int

An integer type

=head2 ArrayRef

An ArrayRef (ARRAY) type

=head2 HashRef

A HashRef (HASH) type

=head2 CodeRef

A CodeRef (CODE) type

=head2 RegexpRef

A regular expression reference type

=head2 GlobRef

A glob reference type

=head2 FileHandle

A type that is either a builtin perl filehandle or an IO::Handle object

=head2 Object

A type that is an object (think blessed)

=head1 PARAMETERIZED TYPES

=head2 Parameterizing Types With a Single Type

The following types can be parameterized with other types.

=head3 ArrayRef

For example, ArrayRef[HashRef]

=head3 HashRef

=head3 ScalarRef

=head3 Maybe

For example, Maybe[Int] would be an integer or undef

=head2 Parameterizing Types With Multiple Types

=head3 AnyOf

Check if the attribute is any of the listed types (think union).
Takes a list of types as the argument, for example:

isa => AnyOf[Int, ArrayRef[Int], HashRef[Int]]

Note: AnyOf is passed an ArrayRef[CodeRef]

=head3 AllOf

Check if the attribute is all of the listed types (think intersection)
Takes a list of types as the argument. For example:

isa => AllOf[
InstanceOf['Human'],
ConsumerOf['Air'],
HasMethods['breath', 'dance']
],


=head2 Parameterizing Types With (Multiple) Strings

In addition, we have some parameterized types that take string arguments.

=head3 InstanceOf

Check if the attribute is an object instance of one or more classes.
Uses C<blessed> and C<isa> to do so.
Takes a list of class names as the argument. For example:

isa => InstanceOf['MyClass','MyOtherClass']

Note: InstanceOf is passed an ArrayRef[Str]

=head3 ConsumerOf

Check if the attribute is blessed and consumes one or more roles.
Uses C<blessed> and C<does> to do so.
Takes a list of role names as the arguments. For example:

isa => ConsumerOf['My::Role', 'My::AnotherRole']

=head3 HasMethods

Check if the attribute is blessed and has one or more methods.
Uses C<blessed> and C<can> to do so.
Takes a list of method names as the arguments. For example:

isa => HasMethods[qw/postulate contemplate liberate/]

=head3 Enum

Check if the attribute is one of the enumerated strings.
Takes a list of possible string values. For example:

isa => Enum['rock', 'spock', 'paper', 'lizard', 'scissors']

=head1 AUTHOR

Mateu Hunter C<hunter@missoula.org>

=head1 THANKS

mst has provided critical guidance on the design

=head1 COPYRIGHT

Copyright 2011-2013 Mateu Hunter

=head1 LICENSE

You may distribute this code under the same terms as Perl itself.

=cut
MooX-Types-MooseLike-0.25/maint/000075500000000000000000000000001217715246600164325ustar00rootroot00000000000000MooX-Types-MooseLike-0.25/maint/Makefile.PL.include000064400000000000000000000003061217715246600220250ustar00rootroot00000000000000BEGIN { -e 'Distar' or system("git clone git://git.shadowcat.co.uk/p5sagit/Distar.git") }
use lib 'Distar/lib';
use Distar;

author 'mateu - Mateu X. Hunter (cpan:MATEU) <hunter@missoula.org>';

1;
MooX-Types-MooseLike-0.25/t/000075500000000000000000000000001217715246600155655ustar00rootroot00000000000000MooX-Types-MooseLike-0.25/t/basic.t000064400000000000000000000222641217715246600170410ustar00rootroot00000000000000package MooX::Types::MooseLike::Test;
use strict;
use warnings FATAL => 'all';
use Moo;
use MooX::Types::MooseLike::Base qw(:all);

has 'a_bool' => (
is => 'ro',
isa => Bool,
);
has 'an_undef' => (
is => 'ro',
isa => Undef,
);
has 'a_defined' => (
is => 'ro',
isa => Defined,
);
has 'a_value' => (
is => 'ro',
isa => Value,
);
has 'a_string' => (
is => 'ro',
isa => Str,
);
has 'a_number' => (
is => 'ro',
isa => Num,
);
has 'an_integer' => (
is => 'ro',
isa => Int,
);
has 'a_ref' => (
is => 'ro',
isa => Ref,
);
has 'an_array' => (
is => 'ro',
isa => ArrayRef,
);
has 'a_hash' => (
is => 'ro',
isa => HashRef,
);
has 'a_code' => (
is => 'ro',
isa => CodeRef,
);
has 'a_regex' => (
is => 'ro',
isa => RegexpRef,
);
has 'a_glob' => (
is => 'ro',
isa => GlobRef,
);
has 'a_filehandle' => (
is => 'ro',
isa => FileHandle,
);
has 'an_object' => (
is => 'ro',
isa => Object,
);
has 'legal_age' => (
is => 'ro',
isa => sub {
die "$_[0] is not of legal age"
unless (is_Int($_[0]) && $_[0] > 17);
},
);

package main;
use strict;
use warnings FATAL => 'all';
use Test::More;
use Test::Fatal;
use IO::Handle;
use MooX::Types::MooseLike::Base qw(:all);

ok(is_Str('x'), 'is_Str');
ok(!is_Str([]), 'is_Str fails on ArrayRef');
ok(is_Num(3.142), 'is_Num');
ok(is_Num('9'), 'is_Num');
ok(!is_Num('xxx'), 'is_Num fails on a non-numeric string');
ok(is_Int(-3), 'is_Int');
ok(!is_Int(3.142), 'is_Int fails on a Float');
ok(is_Bool('0'), '0 is_Bool');
ok(is_Bool(''), 'empty string is_Bool');
ok(is_Bool(), 'undef is_Bool');
ok(is_Bool(1), '1 is_Bool');
ok(!is_Bool(-1), 'is_Bool fails on -1');
ok(is_ArrayRef([]), 'is_ArrayRef');
ok(!is_ArrayRef('1'), 'is_ArrayRef fails on 1');
ok(is_HashRef({}), 'is_HashRef');
ok(!is_HashRef([]), 'is_HashRef fails on []');
ok(is_CodeRef(sub { }), 'is_CodeRef');
ok(!is_CodeRef({}), 'is_CodeRef fails on {}');
ok(is_Object(IO::Handle->new), 'Object');
ok(!is_Object({}), 'is_Object fails on HashRef');

# Test Bool
ok(MooX::Types::MooseLike::Test->new(a_bool => undef), 'undef is a Bool');
ok(MooX::Types::MooseLike::Test->new(a_bool => 0), '0 is a Bool');
my $false_boolean_value = 0.001;
like(
exception {
MooX::Types::MooseLike::Test->new(a_bool => $false_boolean_value);
},
qr/$false_boolean_value is not a Boolean/,
'a non-boolean is an exception when we want a Bool'
);

# Undef
ok(MooX::Types::MooseLike::Test->new(an_undef => undef), 'Undef');
like(
exception { MooX::Types::MooseLike::Test->new(an_undef => '') },
qr/is not undef/,
'empty string is an exception when we want an Undef type'
);

# Defined
ok(MooX::Types::MooseLike::Test->new(a_defined => ''), 'Defined');
like(
exception { MooX::Types::MooseLike::Test->new(a_defined => undef) },
qr/is not defined/,
'undef is an exception when we want a Defined type'
);

# Test Value
ok(MooX::Types::MooseLike::Test->new(a_value => ''), 'empty string Value');
ok(MooX::Types::MooseLike::Test->new(a_value => 0), 'zero Value');
ok(MooX::Types::MooseLike::Test->new(a_value => 'yarn'), 'word Value');
like(
exception { MooX::Types::MooseLike::Test->new(a_value => undef) },
qr/undef is not a value/,
'undef is an exception when we want a Value'
);
like(
exception { MooX::Types::MooseLike::Test->new(a_value => []) },
qr/ARRAY.*?is not a value/,
'an ArrayRef is an exception when we want a Value'
);

# Test Str
ok(MooX::Types::MooseLike::Test->new(a_string => ''), 'Empty string');
ok(MooX::Types::MooseLike::Test->new(a_string => '0'), 'Zero as a string');
ok(MooX::Types::MooseLike::Test->new(a_string => 'barn'), 'Word string');
like(
exception { MooX::Types::MooseLike::Test->new(a_string => undef) },
qr/undef is not a string/,
'undef is an exception when we want a Str'
);
like(
exception { MooX::Types::MooseLike::Test->new(a_string => []) },
qr/ARRAY.*?is not a string/,
'an ArrayRef is an exception when we want a Str'
);

# Test Num
ok(MooX::Types::MooseLike::Test->new(a_number => 0), 'Num zero');
ok(MooX::Types::MooseLike::Test->new(a_number => 3.14), 'Num');
like(
exception { MooX::Types::MooseLike::Test->new(a_number => undef) },
qr/undef is not a number/,
'undef is an exception when we want a number'
);
like(
exception { MooX::Types::MooseLike::Test->new(a_number => '') },
qr/The empty string is not a number/,
'The empty string is an exception when we want a number'
);
like(
exception { MooX::Types::MooseLike::Test->new(a_number => '5x5') },
qr/is not a number/,
'a non number is an exception when we want a number'
);

# Test Int
ok(MooX::Types::MooseLike::Test->new(an_integer => -1), 'Int');
like(
exception { MooX::Types::MooseLike::Test->new(an_integer => undef) },
qr/undef is not an integer/,
'undef is an exception when we want an Integer'
);
like(
exception { MooX::Types::MooseLike::Test->new(an_integer => '') },
qr/The empty string is not an integer/,
'The empty string is an exception when we want an Integer'
);
like(
exception { MooX::Types::MooseLike::Test->new(an_integer => 1.01) },
qr/is not an integer/,
'a non-integer is an exception when we want an Integer'
);

# Test Ref
ok(MooX::Types::MooseLike::Test->new(a_ref => []), 'Ref: ArrayRef');
like(
exception { MooX::Types::MooseLike::Test->new(a_ref => undef) },
qr/is not a reference/,
'undef is an exception when we want a reference'
);
like(
exception { MooX::Types::MooseLike::Test->new(a_ref => '') },
qr/is not a reference/,
'The empty string is an exception when we want a reference'
);
like(
exception { MooX::Types::MooseLike::Test->new(a_ref => 0) },
qr/is not a reference/,
'zero is an exception when we want an reference'
);

# Test ArrayRef
ok(MooX::Types::MooseLike::Test->new(an_array => []), 'ArrayRef');
like(
exception { MooX::Types::MooseLike::Test->new(an_array => undef) },
qr/is not an ArrayRef/,
'undef is an exception when we want an ArrayRef'
);
like(
exception { MooX::Types::MooseLike::Test->new(an_array => '') },
qr/is not an ArrayRef/,
'The empty string is an exception when we want an ArrayRef'
);
like(
exception { MooX::Types::MooseLike::Test->new(an_array => 0) },
qr/is not an ArrayRef/,
'zero is an exception when we want an ArrayRef'
);
like(
exception { MooX::Types::MooseLike::Test->new(an_array => {}) },
qr/HASH.*?is not an ArrayRef/,
'a HashRef is an exception when we want an ArrayRef'
);
like(
exception { MooX::Types::MooseLike::Test->new(an_array => 'string') },
qr/string is not an ArrayRef/,
'a String is an exception when we want an ArrayRef'
);

# Test HashRef
ok(MooX::Types::MooseLike::Test->new(a_hash => {}), 'HashRef');
like(
exception { MooX::Types::MooseLike::Test->new(a_hash => undef) },
qr/is not a HashRef/,
'undef is an exception when we want a HashRef'
);
like(
exception { MooX::Types::MooseLike::Test->new(a_hash => '') },
qr/is not a HashRef/,
'The empty string is an exception when we want a HashRef'
);
like(
exception { MooX::Types::MooseLike::Test->new(a_hash => []) },
qr/ARRAY.*?is not a HashRef/,
'an ArrayRef is an exception when we want a HashRef'
);
like(
exception { MooX::Types::MooseLike::Test->new(a_hash => 'string') },
qr/string is not a HashRef/,
'a String is an exception when we want a HashRef'
);

# Test CodeRef
ok(MooX::Types::MooseLike::Test->new(a_code => sub { }), 'CodeRef');
like(
exception { MooX::Types::MooseLike::Test->new(a_code => []) },
qr/ARRAY.*?is not a CodeRef/,
'an ArrayRef is an exception when we want a CodeRef'
);

# Test RegexpRef
ok(MooX::Types::MooseLike::Test->new(a_regex => qr{}), 'RegexpRef');
like(
exception { MooX::Types::MooseLike::Test->new(a_regex => []) },
qr/ARRAY.*?is not a RegexpRef/,
'an ArrayRef is an exception when we want a RegexpRef'
);

# Test GlobRef
# avoid warning for using FOO only once
no warnings 'once';
ok(MooX::Types::MooseLike::Test->new(a_glob => \*FOO), 'GlobRef');
like(
exception { MooX::Types::MooseLike::Test->new(a_glob => []) },
qr/ARRAY.*?is not a GlobRef/,
'an ArrayRef is an exception when we want a GlobRef'
);

# Test FileHandle
ok(MooX::Types::MooseLike::Test->new(a_filehandle => IO::Handle->new),
'FileHandle');
like(
exception { MooX::Types::MooseLike::Test->new(a_filehandle => []) },
qr/ARRAY.*?is not a FileHandle/,
'an ArrayRef is an exception when we want a FileHandle'
);

# Test Object
ok(MooX::Types::MooseLike::Test->new(an_object => IO::Handle->new), 'Object');
like(
exception { MooX::Types::MooseLike::Test->new(an_object => []) },
qr/ARRAY.*?is not an Object/,
'an ArrayRef is an exception when we want an Object'
);

# Test legal_age attribute which has an 'isa' that uses 'is_Int'
ok(MooX::Types::MooseLike::Test->new(legal_age => 18), 'Legal Age');
my $minor_age = 17;
like(
exception { MooX::Types::MooseLike::Test->new(legal_age => $minor_age) },
qr/$minor_age is not of legal age/,
'an integer less than 18 is an exception when we want a legal age'
);

like(
exception { MooX::Types::MooseLike::Test->new(an_undef => '') },
qr/is not undef.*\n.*MooX::Types::MooseLike::Test::new.*basic\.t/,
'The error looks like a useful stacktrace'
);

done_testing;
MooX-Types-MooseLike-0.25/t/builder.t000064400000000000000000000007101217715246600173760ustar00rootroot00000000000000{

package MyObject;
use Moo;
use MooX::Types::MooseLike::Base qw<ArrayRef CodeRef>;
has attribute_with_a_builder => (
is => 'ro',
isa => ArrayRef [CodeRef],
builder => '_build_attribute_properties',
);

sub _build_attribute_properties {
[ sub { 'pie' } ];
}
}

use Test::More;
my $object = MyObject->new;
is($object->attribute_with_a_builder->[0]->(),
'pie', 'Parameterized type with a builder');

done_testing;
MooX-Types-MooseLike-0.25/t/default.t000064400000000000000000000006051217715246600173770ustar00rootroot00000000000000{

package MyObject;
use Moo;
use MooX::Types::MooseLike::Base qw<ArrayRef Int>;
has attribute_with_a_default => (
is => 'ro',
isa => ArrayRef [Int],
default => sub { [ 52, 27, 108 ] },
);
}
use Test::More;
use Test::Fatal;

is_deeply(
MyObject->new->attribute_with_a_default,
[ 52, 27, 108 ],
'Parameterized type with a default'
);

done_testing;
MooX-Types-MooseLike-0.25/t/inflate_0.t000064400000000000000000000034721217715246600176210ustar00rootroot00000000000000use strict;
use warnings;
use Test::More;
use Test::Fatal;

eval q{
package Local::TypeLibrary;
use Exporter 'import';
use MooX::Types::MooseLike ();
MooX::Types::MooseLike::register_types([{
name => 'Flibble',
test => sub { $_[0] =~ /^flibble$/i },
message => sub { 'Unflibble' },
inflate => 0,
}], __PACKAGE__);
$INC{'Local/TypeLibrary.pm'} = __FILE__;
1;
} or die $@;

eval q{
package Local::TestClass;
use Moo;
use Local::TypeLibrary 'Flibble';
has flibble => (is => 'ro', isa => Flibble);
1;
} or die $@;

is(
exception { Local::TestClass->new(flibble => 'fliBBle') },
undef,
'value which should not violate type constraint',
);

like(
exception { Local::TestClass->new(flibble => 'monkey') },
qr{^isa check for "flibble" failed: Unflibble},
'value which should violate type constraint',
);

eval q{ require Moose } or do {
note "Moose not available; skipping actual inflation tests";
done_testing;
exit;
};

is(
exception { Local::TestClass->new(flibble => 'fliBBle') },
undef,
'Moose loaded; value which should not violate type constraint',
);

like(
exception { Local::TestClass->new(flibble => 'monkey') },
qr{^isa check for "flibble" failed: Unflibble},
'Moose loaded; value which should violate type constraint',
);

my $tc = do {

# Suppress distracting warnings from within Moose
local $SIG{__WARN__} = sub { 0 };
Local::TestClass->meta->get_attribute('flibble')->type_constraint;
};

is(
$tc->name,
'__ANON__',
'type constraint inflation results in an anonymous type',
);

ok($tc->check('Flibble'), 'Moose::Meta::TypeConstraint works (1)');
ok($tc->check('FLIBBLE'), 'Moose::Meta::TypeConstraint works (2)');
ok(!$tc->check('Monkey'), 'Moose::Meta::TypeConstraint works (3)');
ok(!$tc->check([]), 'Moose::Meta::TypeConstraint works (4)');

done_testing;
MooX-Types-MooseLike-0.25/t/inflate_name.t000064400000000000000000000033261217715246600204000ustar00rootroot00000000000000use strict;
use warnings;
use Test::More;
use Test::Fatal;

eval q{
package Local::TypeLibrary;
use Exporter 'import';
use MooX::Types::MooseLike ();
MooX::Types::MooseLike::register_types([{
name => 'Defined',
test => sub { defined $_[0] },
message => sub { 'Not defined' },
}], __PACKAGE__);
$INC{'Local/TypeLibrary.pm'} = __FILE__;
1;
} or die $@;

eval q{
package Local::TestClass;
use Moo;
use Local::TypeLibrary 'Defined';
has flibble => (is => 'ro', isa => Defined);
1;
} or die $@;

is(
exception { Local::TestClass->new(flibble => 'fliBBle') },
undef,
'value which should not violate type constraint',
);

like(
exception { Local::TestClass->new(flibble => undef) },
qr{^isa check for "flibble" failed: Not defined},
'value which should violate type constraint',
);

eval q{ require Moose } or do {
note "Moose not available; skipping actual inflation tests";
done_testing;
exit;
};

is(
exception { Local::TestClass->new(flibble => 'fliBBle') },
undef,
'Moose loaded; value which should not violate type constraint',
);

like(
exception { Local::TestClass->new(flibble => undef) },
qr{^isa check for "flibble" failed: Not defined},
'Moose loaded; value which should violate type constraint',
);

my $tc = do {

# Suppress distracting warnings from within Moose
local $SIG{__WARN__} = sub { 0 };
Local::TestClass->meta->get_attribute('flibble')->type_constraint;
};

is(
$tc->name,
'Defined',
'type constraint inflation results in built in Defined type',
);

ok($tc->check('Flibble'), 'Moose::Meta::TypeConstraint works (1)');
ok(!$tc->check(undef), 'Moose::Meta::TypeConstraint works (2)');

done_testing;
MooX-Types-MooseLike-0.25/t/inflate_sub.t000064400000000000000000000037051217715246600202520ustar00rootroot00000000000000use strict;
use warnings;
use Test::More;
use Test::Fatal;

eval q{
package Local::TypeLibrary;
use Exporter 'import';
use MooX::Types::MooseLike ();
MooX::Types::MooseLike::register_types([{
name => 'Flibble',
test => sub { $_[0] =~ /^flibble$/i },
message => sub { 'Unflibble' },
inflate => sub {
return Moose::Meta::TypeConstraint->new(
name => 'MooseFlibble',
constraint => sub { $_[0] =~ /^flibble$/i },
);
},
}], __PACKAGE__);
$INC{'Local/TypeLibrary.pm'} = __FILE__;
1;
} or die $@;

eval q{
package Local::TestClass;
use Moo;
use Local::TypeLibrary 'Flibble';
has flibble => (is => 'ro', isa => Flibble);
1;
} or die $@;

is(
exception { Local::TestClass->new(flibble => 'fliBBle') },
undef,
'value which should not violate type constraint',
);

like(
exception { Local::TestClass->new(flibble => 'monkey') },
qr{^isa check for "flibble" failed: Unflibble},
'value which should violate type constraint',
);

eval q{ require Moose } or do {
note "Moose not available; skipping actual inflation tests";
done_testing;
exit;
};

is(
exception { Local::TestClass->new(flibble => 'fliBBle') },
undef,
'Moose loaded; value which should not violate type constraint',
);

like(
exception { Local::TestClass->new(flibble => 'monkey') },
qr{^isa check for "flibble" failed: Unflibble},
'Moose loaded; value which should violate type constraint',
);

my $tc = do {

# Suppress distracting warnings from within Moose
local $SIG{__WARN__} = sub { 0 };
Local::TestClass->meta->get_attribute('flibble')->type_constraint;
};

is(
$tc->name,
'MooseFlibble',
'type constraint inflation results in custom type',
);

ok($tc->check('Flibble'), 'Moose::Meta::TypeConstraint works (1)');
ok($tc->check('FLIBBLE'), 'Moose::Meta::TypeConstraint works (2)');
ok(!$tc->check('Monkey'), 'Moose::Meta::TypeConstraint works (3)');
ok(!$tc->check([]), 'Moose::Meta::TypeConstraint works (4)');

done_testing;
MooX-Types-MooseLike-0.25/t/parameterized.t000064400000000000000000000125531217715246600206140ustar00rootroot00000000000000{
package A;
use Moo;
has fun => (is => 'ro');
1;
}
{
package B;
use Moo;
extends 'A';
has funner => (is => 'ro');
1;
}
{
package MooX::Types::MooseLike::Test;
use strict;
use warnings FATAL => 'all';
use Moo;
use MooX::Types::MooseLike::Base qw/
ArrayRef Int HashRef Str ScalarRef Maybe AnyOf Undef
/;

has an_array_of_integers => (
is => 'ro',
isa => ArrayRef [Int],
);
has an_array_of_hash => (
is => 'ro',
isa => ArrayRef [HashRef],
);
has a_hash_of_strings => (
is => 'ro',
isa => HashRef [Str],
);
has an_array_of_hash_of_int => (
is => 'ro',
isa => ArrayRef [ HashRef [Int] ],
);
has a_scalar_ref_of_int => (
is => 'ro',
isa => ScalarRef [Int],
);
has maybe_an_int => (
is => 'ro',
isa => Maybe [Int],
);
has array_maybe_a_hash => (
is => 'ro',
isa => ArrayRef [ Maybe [HashRef] ],
);
has array_maybe_a_hash_of_int => (
is => 'ro',
isa => ArrayRef [ Maybe [ HashRef [Int] ] ],
);
has maybe_an_int_or_hash => (
is => 'ro',
isa => AnyOf[Int, HashRef, Undef],
);
}

package main;
use strict;
use warnings FATAL => 'all';
use Test::More;
use Test::Fatal;
use IO::Handle;

# ArrayRef[Int]
ok(MooX::Types::MooseLike::Test->new(an_array_of_integers => [ 6, 7, 10, -1 ]),
'ArrayRef[Int]');
like(
exception {
MooX::Types::MooseLike::Test->new(an_array_of_integers => [ 1.5, 2 ]);
},
qr/is not an integer/,
'an ArrayRef of Floats is an exception when we want an ArrayRef[Int]'
);

# ArrayRef[HashRef]
ok(
MooX::Types::MooseLike::Test->new(
an_array_of_hash => [ { a => 1 }, { b => 2 } ]
),
'ArrayRef[HashRef]'
);
ok(
MooX::Types::MooseLike::Test->new(
an_array_of_hash => [ { a => 1 }, { b => undef } ]
),
'ArrayRef[HashRef] with undef'
);
like(
exception {
MooX::Types::MooseLike::Test->new(
an_array_of_hash => [ { x => 1 }, [ 1, 2, 3 ] ]);
},
qr/is not a HashRef/,
'an ArrayRef of integers is an exception when we want an ArrayRef[HashRef]'
);

# HashRef[Str]
ok(MooX::Types::MooseLike::Test->new(a_hash_of_strings => { a => 1, b => 'x' }),
'HashRef[Str]');
ok(MooX::Types::MooseLike::Test->new(a_hash_of_strings => {}),
'Empty HashRef');
like(
exception {
MooX::Types::MooseLike::Test->new(a_hash_of_strings =>
{ a => MooX::Types::MooseLike::Test->new(), b => 'x' });
},
qr/is not a string/,
'an HashRef with Objects is an exception when we want an HashRef[Str]'
);

# ArrayRef[HashRef[Int]]
ok(
MooX::Types::MooseLike::Test->new(
an_array_of_hash_of_int => [ { a => 1 }, { b => 2 } ]
),
'ArrayRef[HashRef[Int]]'
);
like(
exception {
MooX::Types::MooseLike::Test->new(
an_array_of_hash_of_int => [ { x => 1 }, { x => 1.1 } ]);
},
qr/is not an integer/,
'an ArrayRef of HashRef of Floats is an exception when we want an ArrayRef[HashRef[Int]]'
);

# ScalarRef[Int]
ok(MooX::Types::MooseLike::Test->new(a_scalar_ref_of_int => \1),
'ScalarRef[Int]');
like(
exception { MooX::Types::MooseLike::Test->new(a_scalar_ref_of_int => \'x') },
qr/is not an integer/,
'a ScalarRef of Str is an exception when we want an ScalarRef[Int]'
);

# Maybe[Int]
ok(MooX::Types::MooseLike::Test->new(maybe_an_int => 41),
'Maybe[Int] as an integer');
ok(MooX::Types::MooseLike::Test->new(maybe_an_int => undef),
'Maybe[Int] as undef');
ok(MooX::Types::MooseLike::Test->new(maybe_an_int => -24),
'Maybe[Int] as undef');
like(
exception { MooX::Types::MooseLike::Test->new(maybe_an_int => 'x') },
qr/is not an integer/,
'a Str is an exception when we want a Maybe[Int]'
);

# AnyOf[Int, HashRef, Undef] - a stand in for Maybe[Int, HashRef]
ok(MooX::Types::MooseLike::Test->new(maybe_an_int_or_hash => {nbr => 41} ),
'Maybe[Int, HahsRef, Undef] as a HashRef');
ok(MooX::Types::MooseLike::Test->new(maybe_an_int_or_hash => 41 ),
'Maybe[Int, HahsRef, Undef] as an integer');
ok(MooX::Types::MooseLike::Test->new(maybe_an_int_or_hash => undef ),
'Maybe[Int, HahsRef, Undef] as an undef');
like(
exception { MooX::Types::MooseLike::Test->new(maybe_an_int_or_hash => [] ) },
qr/is not any of/,
'an ArrayRef is an exception when we want a AnyOf[Int, HashRef, Undef]'
);
like(
exception { MooX::Types::MooseLike::Test->new(maybe_an_int_or_hash => sub {} ) },
qr/is not any of/,
'a CodeRef is an exception when we want a AnyOf[Int, HashRef, Undef]'
);

# ArrayRef[Maybe[HashRef]]
ok(MooX::Types::MooseLike::Test->new(array_maybe_a_hash => [ { a => 41 } ]),
'ArrayRef[Maybe[HashRef]] as an HashRef');
ok(
MooX::Types::MooseLike::Test->new(
array_maybe_a_hash => [ undef, { a => 41 } ]
),
'ArrayRef[Maybe[HashRef]] with an undef'
);
like(
exception { MooX::Types::MooseLike::Test->new(array_maybe_a_hash => ['x']) },
qr/is not a HashRef/,
'a Str is an exception when we want a Maybe[HashRef]'
);

# ArrayRef[Maybe[HashRef[Int]]]
ok(
MooX::Types::MooseLike::Test->new(
array_maybe_a_hash_of_int => [ { a => 41 } ]
),
'ArrayRef[Maybe[HashRef]] as a HashRef[Int]'
);
ok(
MooX::Types::MooseLike::Test->new(
array_maybe_a_hash_of_int => [ undef, { a => -1 } ]
),
'ArrayRef[Maybe[HashRef]] with an undef'
);
like(
exception {
MooX::Types::MooseLike::Test->new(
array_maybe_a_hash_of_int => [ { b => 'x' } ]);
},
qr/is not an integer/,
'a Str is an exception when we want a Maybe[HashRef[Int]]'
);

done_testing;
MooX-Types-MooseLike-0.25/t/parameterized_inflate.t000064400000000000000000000047211217715246600223140ustar00rootroot00000000000000use strict;
use warnings;
use Test::More;
use Test::Fatal;

eval q{
package Local::TestClass;
use Moo;
use MooX::Types::MooseLike::Base qw( Enum AnyOf Str ArrayRef ScalarRef HashRef HasMethods );
has chipmunk => (is => 'ro', isa => Enum[qw(Alvin Simon Theodore)]);
has songs => (is => 'ro', isa => AnyOf[ Str, ArrayRef[Str] ]);
has complex => (is => 'ro', isa => HashRef[ArrayRef[ScalarRef[HasMethods[qw/foo bar/]]]]);
1;
} or die $@;

is(
exception { Local::TestClass->new(chipmunk => 'Simon', songs => []) },
undef,
'values which should not violate type constraints',
);

like(
exception { Local::TestClass->new(chipmunk => 'Romeo') },
qr{^isa check for "chipmunk" failed: Romeo is not any of the possible values},
'value which should violate Enum type constraint',
);

like(
exception { Local::TestClass->new(songs => {}) },
qr{^isa check for "songs" failed: HASH\(.+?\) is not any of the types},
'value which should violate AnyOf type constraint',
);

eval q{ require Moose } or do {
note "Moose not available; skipping actual inflation tests";
done_testing;
exit;
};

my $tc = do {
$SIG{__WARN__} = sub { 0 };
Local::TestClass->meta->get_attribute('chipmunk')->type_constraint;
};

is(
exception { Local::TestClass->new(chipmunk => 'Simon') },
undef,
'Moose loaded; value which should not violate type constraint',
);

like(
exception { Local::TestClass->new(chipmunk => 'Romeo') },
qr{^isa check for "chipmunk" failed: Romeo is not any of the possible values},
'Moose loaded; value which should violate type constraint',
);

isa_ok($tc, 'Moose::Meta::TypeConstraint::Enum');
is_deeply($tc->values, [qw/Alvin Simon Theodore/], '$tc->values');

my $tc2 = do {
$SIG{__WARN__} = sub { 0 };
Local::TestClass->meta->get_attribute('songs')->type_constraint;
};

ok(
$tc2->name eq 'ArrayRef[Str]|Str' || $tc2->name eq 'Str|ArrayRef[Str]',
'complex type constraint (union of Str and ArrayRef[Str]) correctly inflated',
);

my $tc3 = do {
$SIG{__WARN__} = sub { 0 };
Local::TestClass->meta->get_attribute('complex')->type_constraint;
};

is(
$tc3->name,
'HashRef[ArrayRef[ScalarRef[__ANON__]]]',
'very complex type constraint correctly inflated',
);

isa_ok(
$tc3->type_parameter->type_parameter->type_parameter,
'Moose::Meta::TypeConstraint::DuckType',
);

is_deeply(
[sort @{$tc3->type_parameter->type_parameter->type_parameter->methods}],
[sort qw/foo bar/],
'duck type has correct methods'
);

done_testing;
MooX-Types-MooseLike-0.25/t/parameterized_subtype.t000064400000000000000000000030631217715246600223630ustar00rootroot00000000000000use strict;
use warnings;
use Test::More;
use Test::Fatal;

BEGIN {
package Local::TypeLibrary;
use MooX::Types::MooseLike qw/ exception_message /;
use MooX::Types::MooseLike::Base qw/ Object AllOf InstanceOf ConsumerOf HasMethods /;
use Exporter 5.57 'import';
MooX::Types::MooseLike::register_types([{
name => 'Douche',
subtype_of => AllOf[InstanceOf['Man'], ConsumerOf['Role::Dick'], HasMethods['thought', 'testosterone']],
from => 'MooX::Types::MooseLike::Base',
test => sub { ($_[0]->testosterone =~ /beaucou/) and ($_[0]->thought < 0.5) },
message => sub { return exception_message($_[0], 'a douche') },
}], __PACKAGE__);
$INC{'Local/TypeLibrary.pm'} = __FILE__;
}
{
package Human;
use Moo;
use MooX::Types::MooseLike::Base qw/ Num /;
has thought => (is => 'ro', isa => Num);
}
{ package Woman; use Moo; extends 'Human'; sub sings {}; }
{ package Man; use Moo; extends 'Human'; sub hunts {}; }
{
package Role::Dick;
use Moo::Role;
sub testosterone { 'beaucoupe' };
}
{
package Brogrammer;
use Moo;
extends 'Man';
with ('Role::Dick');
}
{
package MooX::Types::MooseLike::Test;
use Moo;
use Local::TypeLibrary qw/Douche/;
has brogrammer => (
is => 'ro',
isa => Douche,
);
}

ok(MooX::Types::MooseLike::Test->new(brogrammer => Brogrammer->new(thought => 0)), 'A brogrammer is a douche');
like(
exception {
MooX::Types::MooseLike::Test->new(brogrammer => bless {}, 'Elkman');
},
qr/is not a douche/,
'Elk man is not a douche',
);

done_testing();
MooX-Types-MooseLike-0.25/t/parameterized_with_coderefs.t000064400000000000000000000044061217715246600235170ustar00rootroot00000000000000{
package MooX::Types::MooseLike::Test;
use strict;
use warnings FATAL => 'all';
use Moo;
use MooX::Types::MooseLike::Base qw/ AnyOf AllOf Object Int ArrayRef HashRef InstanceOf HasMethods /;

has any_of => (
is => 'ro',
isa => AnyOf[Int, HashRef[Int], Object],
);
has all_of => (
is => 'ro',
isa => AllOf[InstanceOf['IO::Handle'], HasMethods['print']],
);
}
package main;
use strict;
use warnings FATAL => 'all';
use Test::More;
use Test::Fatal;
use IO::Handle;

# AnyOf
ok(MooX::Types::MooseLike::Test->new(any_of => IO::Handle->new ), 'value is AnyOf[Int, ArrayRef[Int], HashRef[Int], Object]');
ok(MooX::Types::MooseLike::Test->new(any_of => 108 ), 'Int is AnyOf[Int, ArrayRef[Int], HashRef[Int], Object]');
ok(MooX::Types::MooseLike::Test->new(any_of => {auspicious_number => 108} ), 'HashRef[Int] is AnyOf[Int, ArrayRef[Int], HashRef[Int], Object]');
ok(MooX::Types::MooseLike::Test->new(any_of => {} ), 'HashRef is AnyOf[Int, ArrayRef[Int], HashRef[Int], Object]');
my $false_value;
like(
exception {
MooX::Types::MooseLike::Test->new(any_of => $false_value);
},
qr/is not any of/,
'undef is not an any of the types given"'
);
$false_value = { nada => undef };
like(
exception {
MooX::Types::MooseLike::Test->new(any_of => $false_value);
},
qr/is not any of/,
'A HashRef with an undefined value is not an any of the types given'
);
$false_value = [];
like(
exception {
MooX::Types::MooseLike::Test->new(any_of => $false_value);
},
qr/is not any of/,
'ArrayRef is not an any of the types given'
);
$false_value = 'peace_treaty';
like(
exception {
MooX::Types::MooseLike::Test->new(any_of => $false_value);
},
qr/is not any of/,
'a string is not any of the types given'
);

# AllOf
ok(MooX::Types::MooseLike::Test->new(all_of => IO::Handle->new ),
"value is AllOf[InstanceOf('IO::Handle'), HasMethods['print']]");
$false_value = undef;
like(
exception {
MooX::Types::MooseLike::Test->new(all_of => $false_value);
},
qr/No instance given/,
'undef is not an instance of IO::Handle"'
);
$false_value = 'peace_treaty';
like(
exception {
MooX::Types::MooseLike::Test->new(all_of => $false_value);
},
qr/is not blessed/,
'a string is not an instance of IO::Handle'
);

done_testing;
MooX-Types-MooseLike-0.25/t/parameterized_with_string.t000064400000000000000000000121061217715246600232270ustar00rootroot00000000000000{
package NoBool;
use Moo;
use overload ('bool' => sub { die });
}
{
package MooX::Types::MooseLike::Test::Role;
use Role::Tiny;
sub foo { 'ja' };
sub bar { 'ara' };
}
{
package MooX::Types::MooseLike::Test::AnotherRole;
use Role::Tiny;
sub que { 'dius' };
sub quoi { 'dieu' };
}
{
package A;
use Moo;
has fun => (is => 'ro');
1;
}
{
package B;
use Moo;
extends 'A';
has funner => (is => 'ro');
1;
}

{
package MooX::Types::MooseLike::Test;
use strict;
use warnings FATAL => 'all';
use Moo;
use MooX::Types::MooseLike::Base qw/
InstanceOf ConsumerOf HasMethods Enum
/;
with (
'MooX::Types::MooseLike::Test::Role',
'MooX::Types::MooseLike::Test::AnotherRole'
);

has instance_of_IO_Handle => (
is => 'ro',
isa => InstanceOf['IO::Handle'],
);
has instance_of_A_and_B => (
is => 'ro',
isa => InstanceOf['A', 'B'],
);
has instance_of_NoBool => (
is => 'ro',
isa => InstanceOf['NoBool'],
);
has consumer_of => (
is => 'ro',
isa => ConsumerOf[
'MooX::Types::MooseLike::Test::Role',
'MooX::Types::MooseLike::Test::AnotherRole'
],
);
has has_methods => (
is => 'ro',
isa => HasMethods['foo', 'bar'],
);
has enum_type => (
is => 'ro',
isa => Enum['estrella', 'lluna', 'deessa'],
);
}
package main;
use strict;
use warnings FATAL => 'all';
use Test::More;
use Test::Fatal;
use IO::Handle;

# InstanceOf
ok(MooX::Types::MooseLike::Test->new(instance_of_IO_Handle => IO::Handle->new ), 'instance of IO::Handle');
my $false_instance;
like(
exception {
MooX::Types::MooseLike::Test->new(instance_of_IO_Handle => $false_instance);
},
qr/No instance given/,
'undef is not an instance of IO::Handle'
);
$false_instance = {};
like(
exception {
MooX::Types::MooseLike::Test->new(instance_of_IO_Handle => $false_instance);
},
qr/is not blessed/,
'a hashref is not an instance of IO::Handle'
);
$false_instance = bless {}, 'Foo';
like(
exception {
MooX::Types::MooseLike::Test->new(instance_of_IO_Handle => $false_instance);
},
qr/is not an instance of the class.*IO::Handle/,
'a Foo instance is not an instance of IO::Handle'
);
ok(MooX::Types::MooseLike::Test->new(instance_of_A_and_B => B->new ), 'instance of A and B');
ok(MooX::Types::MooseLike::Test->new(instance_of_NoBool => NoBool->new ), 'instance of NoBool');

# ConsumerOf
ok(MooX::Types::MooseLike::Test->new(consumer_of => MooX::Types::MooseLike::Test->new ), 'consumer of a some roles');
my $false_consumer;
like(
exception {
MooX::Types::MooseLike::Test->new(consumer_of => $false_consumer);
},
qr/No instance given/,
'undef is not a consumer of roles'
);
$false_consumer = IO::Handle->new;
like(
exception {
MooX::Types::MooseLike::Test->new(consumer_of => $false_consumer);
},
qr/is not a consumer of roles/,
'an IO::Handle instance is not a consumer of roles'
);
like(
exception {
MooX::Types::MooseLike::Test->new(consumer_of => 'MooX::Types::MooseLike::Test');
},
qr/is not blessed/,
'a class name is not a consumer of roles'
);

# HasMethods
ok(MooX::Types::MooseLike::Test->new(has_methods => MooX::Types::MooseLike::Test->new ), 'has methods of madness');
my $false_has_methods;
like(
exception {
MooX::Types::MooseLike::Test->new(has_methods => $false_has_methods);
},
qr/No instance given/,
'undef does not have the required methods'
);
$false_has_methods = IO::Handle->new;
like(
exception {
MooX::Types::MooseLike::Test->new(has_methods => $false_has_methods);
},
qr/does not have the required methods/,
'an object instance does not have the required methods'
);
like(
exception {
MooX::Types::MooseLike::Test->new(has_methods => 'MooX::Types::MooseLike::Test');
},
qr/is not blessed/,
'a class name is does not have methods'
);

# Enum
ok(MooX::Types::MooseLike::Test->new(enum_type => 'estrella' ), 'has one of the possible values (enum)');
ok(MooX::Types::MooseLike::Test->new(enum_type => 'deessa' ), 'has one of the possible values (enum)');
my $false_enum = undef;
like(
exception {
MooX::Types::MooseLike::Test->new(enum_type => $false_enum);
},
qr/is not any of the possible values/,
'undef is not one of the enumerated values'
);
$false_enum = IO::Handle->new;
like(
exception {
MooX::Types::MooseLike::Test->new(enum_type => $false_enum);
},
qr/is not any of the possible values/,
'an object is not one of the enumerated values'
);
$false_enum = {};
like(
exception {
MooX::Types::MooseLike::Test->new(enum_type => $false_enum);
},
qr/is not any of the possible values/,
'a HashRef is not one of the enumerated values'
);
$false_enum = '';
like(
exception {
MooX::Types::MooseLike::Test->new(enum_type => $false_enum);
},
qr/is not any of the possible values/,
'an empty string is not one of the enumerated values'
);
$false_enum = 'Tot es possible';
like(
exception {
MooX::Types::MooseLike::Test->new(enum_type => $false_enum);
},
qr/is not any of the possible values/,
'a different string is not one of the enumerated values'
);

done_testing;
MooX-Types-MooseLike-0.25/t/required.t000064400000000000000000000007361217715246600176000ustar00rootroot00000000000000{

package MyObject;
use Moo;
use MooX::Types::MooseLike::Base qw<HashRef>;

has required_parameterized_hashref => (
is => "ro",
isa => HashRef [HashRef],
required => 1,
);
}
use Test::More;
use Test::Fatal;
ok(MyObject->new(required_parameterized_hashref => { a => {} }),
'Required parameterized type');
like(
exception { MyObject->new },
qr/Missing required arguments/,
'A required parameterized type must exist'
);

done_testing;
MooX-Types-MooseLike-0.25/t/subtype.t000064400000000000000000000041011217715246600174410ustar00rootroot00000000000000use strict;
use warnings;
use Test::More;
use Test::Fatal;

BEGIN {
package Local::TypeLibrary;
use MooX::Types::MooseLike;
use Exporter 5.57 'import';
MooX::Types::MooseLike::register_types([{
name => 'BaseType',
test => sub { defined $_[0] && !ref $_[0] },
message => sub { 'not a simple string' },
}], __PACKAGE__);
MooX::Types::MooseLike::register_types([{
name => 'SubType',
subtype_of => 'BaseType',
from => __PACKAGE__,
test => sub { length $_[0] },
message => sub { 'not a string length > 0' },
}], __PACKAGE__);
MooX::Types::MooseLike::register_types([{
name => 'SubSubType',
subtype_of => SubType(),
test => sub { $_[0] },
message => sub { 'not a true value' },
}], __PACKAGE__);
$INC{'Local/TypeLibrary.pm'} = __FILE__;
}

{
package MooX::Types::MooseLike::Test;
use strict;
use warnings FATAL => 'all';
use Moo;
use Local::TypeLibrary qw/BaseType SubType SubSubType/;

has string => (
is => 'ro',
isa => BaseType,
);
has string_w_length => (
is => 'ro',
isa => SubType,
);
has true_string => (
is => 'ro',
isa => SubSubType,
);
}

ok(MooX::Types::MooseLike::Test->new(string => ''), 'empty string is a string');
ok(MooX::Types::MooseLike::Test->new(string_w_length => '0'), '0 is a string with length');
ok(MooX::Types::MooseLike::Test->new(true_string => '1'), '1 is true string');
like(
exception {
MooX::Types::MooseLike::Test->new(string => undef);
},
qr/not a simple string/,
'undef is not a simple string',
);
like(
exception {
MooX::Types::MooseLike::Test->new(string_w_length => '');
},
qr/not a string length > 0/,
'empty string has no length',
);
like(
exception {
MooX::Types::MooseLike::Test->new(string_w_length => {});
},
qr/not a string length > 0/,
'hashref is not a simple string',
);
like(
exception {
MooX::Types::MooseLike::Test->new(true_string => '0');
},
qr/not a true value/,
'0 is not a true value',
);

done_testing;
MooX-Types-MooseLike-0.25/t/version.t000064400000000000000000000003571217715246600174440ustar00rootroot00000000000000use strict;
use warnings FATAL => 'all';
use Test::More;
use MooX::Types::MooseLike;
use MooX::Types::MooseLike::Base;

ok(($MooX::Types::MooseLike::Base::VERSION == $MooX::Types::MooseLike::VERSION), 'versions are equal');

done_testing;
MooX-Types-MooseLike-0.25/tidyall.ini000064400000000000000000000001521217715246600174630ustar00rootroot00000000000000[PerlTidy]
select = **/*.{pl,pm,t}
argv = -io -i=2

[PerlCritic]
select = lib/**/*.pm
argv = -severity 3
 
дизайн и разработка: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
текущий майнтейнер: Michael Shigorin