COPYRIGHT000664001750001750 2347712422772317 13737 0ustar00taitai000000000000Type-Tiny-1.000005Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: Type-Tiny Upstream-Contact: Toby Inkster (TOBYINK) Source: https://metacpan.org/release/Type-Tiny Files: examples/benchmark-coercions.pl examples/benchmark-constraints.pl lib/Devel/TypeTiny/Perl56Compat.pm lib/Devel/TypeTiny/Perl58Compat.pm lib/Error/TypeTiny.pm lib/Error/TypeTiny/Assertion.pm lib/Error/TypeTiny/Compilation.pm lib/Error/TypeTiny/WrongNumberOfParameters.pm lib/Eval/TypeTiny.pm lib/Reply/Plugin/TypeTiny.pm lib/Test/TypeTiny.pm lib/Type/Coercion.pm lib/Type/Coercion/FromMoose.pm lib/Type/Coercion/Union.pm lib/Type/Library.pm lib/Type/Params.pm lib/Type/Parser.pm lib/Type/Registry.pm lib/Type/Tiny.pm lib/Type/Tiny/Class.pm lib/Type/Tiny/Duck.pm lib/Type/Tiny/Enum.pm lib/Type/Tiny/Intersection.pm lib/Type/Tiny/Manual.pod lib/Type/Tiny/Manual/Coercions.pod lib/Type/Tiny/Manual/Libraries.pod lib/Type/Tiny/Manual/Optimization.pod lib/Type/Tiny/Manual/Params.pod lib/Type/Tiny/Manual/Policies.pod lib/Type/Tiny/Manual/UsingWithMoo.pod lib/Type/Tiny/Manual/UsingWithMoose.pod lib/Type/Tiny/Manual/UsingWithMouse.pod lib/Type/Tiny/Manual/UsingWithOther.pod lib/Type/Tiny/Role.pm lib/Type/Tiny/Union.pm lib/Type/Utils.pm lib/Types/Common/Numeric.pm lib/Types/Common/String.pm lib/Types/Standard.pm lib/Types/Standard/ArrayRef.pm lib/Types/Standard/Dict.pm lib/Types/Standard/HashRef.pm lib/Types/Standard/Map.pm lib/Types/Standard/ScalarRef.pm lib/Types/Standard/Tuple.pm lib/Types/TypeTiny.pm t/00-begin.t t/01-compile.t t/02-api.t t/03-leak.t t/20-unit/Error-TypeTiny-Assertion/basic.t t/20-unit/Error-TypeTiny-Compilation/basic.t t/20-unit/Error-TypeTiny-WrongNumberOfParameters/basic.t t/20-unit/Error-TypeTiny/basic.t t/20-unit/Error-TypeTiny/stacktrace.t t/20-unit/Eval-TypeTiny/basic.t t/20-unit/Eval-TypeTiny/fallback-aliases.t t/20-unit/Eval-TypeTiny/lexical-subs.t t/20-unit/Type-Coercion-Union/basic.t t/20-unit/Type-Coercion/basic.t t/20-unit/Type-Coercion/frozen.t t/20-unit/Type-Coercion/inlining.t t/20-unit/Type-Coercion/parameterized.t t/20-unit/Type-Library/assert.t t/20-unit/Type-Library/errors.t t/20-unit/Type-Library/inheritance.t t/20-unit/Type-Library/is.t t/20-unit/Type-Library/to.t t/20-unit/Type-Library/types.t t/20-unit/Type-Params/badsigs.t t/20-unit/Type-Params/carping.t t/20-unit/Type-Params/coerce.t t/20-unit/Type-Params/methods.t t/20-unit/Type-Params/mixednamed.t t/20-unit/Type-Params/multisig.t t/20-unit/Type-Params/named.t t/20-unit/Type-Params/noninline.t t/20-unit/Type-Params/optional.t t/20-unit/Type-Params/positional.t t/20-unit/Type-Params/slurpy.t t/20-unit/Type-Parser/basic.t t/20-unit/Type-Parser/moosextypes.t t/20-unit/Type-Registry/basic.t t/20-unit/Type-Registry/moosextypes.t t/20-unit/Type-Registry/mousextypes.t t/20-unit/Type-Tiny-Class/basic.t t/20-unit/Type-Tiny-Class/errors.t t/20-unit/Type-Tiny-Class/plus-constructors.t t/20-unit/Type-Tiny-Duck/basic.t t/20-unit/Type-Tiny-Enum/basic.t t/20-unit/Type-Tiny-Intersection/basic.t t/20-unit/Type-Tiny-Role/basic.t t/20-unit/Type-Tiny-Role/errors.t t/20-unit/Type-Tiny-Union/basic.t t/20-unit/Type-Tiny/arithmetic.t t/20-unit/Type-Tiny/basic.t t/20-unit/Type-Tiny/coercion-modifiers.t t/20-unit/Type-Tiny/parameterization.t t/20-unit/Type-Tiny/syntax.t t/20-unit/Type-Utils/dwim-moose.t t/20-unit/Type-Utils/dwim-mouse.t t/20-unit/Type-Utils/match-on-type.t t/20-unit/Types-Standard/basic.t t/20-unit/Types-Standard/deep-coercions.t t/20-unit/Types-Standard/mxtmlb-alike.t t/20-unit/Types-Standard/optlist.t t/20-unit/Types-Standard/overload.t t/20-unit/Types-Standard/strmatch.t t/20-unit/Types-Standard/structured.t t/20-unit/Types-Standard/tied.t t/30-integration/Exporter-Tiny/basic.t t/30-integration/Exporter-Tiny/installer.t t/30-integration/Exporter-Tiny/role-conflict.t t/30-integration/Function-Parameters/basic.t t/30-integration/Moo/basic.t t/30-integration/Moo/coercion.t t/30-integration/Moo/exceptions.t t/30-integration/Moo/inflation.t t/30-integration/Moo/inflation2.t t/30-integration/Moops/basic.t t/30-integration/Moops/library-keyword.t t/30-integration/Moose/accept-moose-types.t t/30-integration/Moose/basic.t t/30-integration/Moose/coercion.t t/30-integration/Moose/native-attribute-traits.t t/30-integration/MooseX-Types/basic.t t/30-integration/MooseX-Types/extending.t t/30-integration/MooseX-Types/more.t t/30-integration/Mouse/basic.t t/30-integration/Mouse/coercion.t t/30-integration/MouseX-Types/basic.t t/30-integration/MouseX-Types/extending.t t/30-integration/Object-Accessor/basic.t t/30-integration/Sub-Quote/basic.t t/30-integration/Validation-Class-Simple/archaic.t t/30-integration/Validation-Class-Simple/basic.t t/lib/BiggerLib.pm t/lib/DemoLib.pm Copyright: This software is copyright (c) 2013-2014 by Toby Inkster. License: GPL-1.0+ or Artistic-1.0 Files: t/20-unit/Devel-TypeTiny-Perl56Compat/basic.t t/20-unit/Devel-TypeTiny-Perl58Compat/basic.t t/20-unit/Test-TypeTiny/basic.t t/20-unit/Test-TypeTiny/extended.t t/20-unit/Test-TypeTiny/matchfor.t t/20-unit/Type-Coercion-FromMoose/basic.t t/20-unit/Type-Coercion-FromMoose/errors.t t/20-unit/Type-Coercion/esoteric.t t/20-unit/Type-Coercion/smartmatch.t t/20-unit/Type-Coercion/typetiny-constructor.t t/20-unit/Type-Registry/automagic.t t/20-unit/Type-Registry/methods.t t/20-unit/Type-Tiny-Duck/errors.t t/20-unit/Type-Tiny-Enum/errors.t t/20-unit/Type-Tiny-Intersection/errors.t t/20-unit/Type-Tiny-Union/errors.t t/20-unit/Type-Tiny/esoteric.t t/20-unit/Type-Tiny/my-methods.t t/20-unit/Type-Tiny/shortcuts.t t/20-unit/Type-Tiny/smartmatch.t t/20-unit/Type-Tiny/to-moose.t t/20-unit/Type-Tiny/to-mouse.t t/20-unit/Type-Utils/classifier.t t/20-unit/Type-Utils/dwim-both.t t/20-unit/Type-Utils/warnings.t t/20-unit/Types-Standard/lockdown.t t/20-unit/Types-TypeTiny/basic.t t/20-unit/Types-TypeTiny/coercion.t t/20-unit/Types-TypeTiny/meta.t t/30-integration/Kavorka/basic.t t/30-integration/Moo/coercion-inlining-avoidance.t t/30-integration/Moose/inflate-then-inline.t t/30-integration/Return-Type/basic.t t/30-integration/Sub-Quote/unquote-coercions.t t/30-integration/Sub-Quote/unquote-constraints.t t/30-integration/Switcheroo/basic.t t/30-integration/Type-Tie/basic.t t/30-integration/match-simple/basic.t Copyright: This software is copyright (c) 2014 by Toby Inkster. License: GPL-1.0+ or Artistic-1.0 Files: META.json META.yml NEWS TODO dist.ini doap.ttl examples/benchmark-param-validation.pl Copyright: Copyright 2014 Toby Inkster. License: GPL-1.0+ or Artistic-1.0 Files: INSTALL examples/versus-scalar-validation.pl t/README t/TODO t/mk-test-manifest.pl t/not-covered.pl Copyright: Unknown License: Unknown Files: CREDITS Changes LICENSE Makefile.PL README Copyright: Copyright 1970 Toby Inkster. License: GPL-1.0+ or Artistic-1.0 Files: t/40-regression/rt92571-2.t t/40-regression/rt92571.t t/40-regression/rt92591.t t/40-regression/rt94196.t t/40-regression/rt97684.t Copyright: This software is copyright (c) 2014 by Diab Jerius. License: GPL-1.0+ or Artistic-1.0 Files: t/20-unit/Types-Common-Numeric/basic.t t/20-unit/Types-Common-String/basic.t t/20-unit/Types-Common-String/coerce.t t/20-unit/Types-Common-String/unicode.t Copyright: This software is copyright (c) 2013-2014 by Matt S Trout - mst (at) shadowcatsystems.co.uk (L). License: GPL-1.0+ or Artistic-1.0 Files: lib/Type/Tiny/_HalfOp.pm t/20-unit/Type-Tiny-_HalfOp/overload-precedence.t t/40-regression/73f51e2d.pl t/40-regression/73f51e2d.t Copyright: This software is copyright (c) 2014 by Graham Knop. License: GPL-1.0+ or Artistic-1.0 Files: t/40-regression/rt85911.t t/40-regression/rt86004.t t/40-regression/rt90096-2.t Copyright: This software is copyright (c) 2013-2014 by Diab Jerius. License: GPL-1.0+ or Artistic-1.0 Files: COPYRIGHT SIGNATURE Copyright: None License: public-domain Files: t/40-regression/rt86233.t t/40-regression/rt86239.t Copyright: This software is copyright (c) 2013-2014 by Vyacheslav Matyukhin. License: GPL-1.0+ or Artistic-1.0 Files: t/40-regression/gh1.t Copyright: This software is copyright (c) 2013-2014 by Richard Simões. License: GPL-1.0+ or Artistic-1.0 Files: t/99-moose-std-types-test.t Copyright: This software is copyright (c) 2013-2014 by Infinity Interactive, Inc.. License: GPL-1.0+ or Artistic-1.0 Files: t/40-regression/rt90096.t Copyright: This software is copyright (c) 2013-2014 by Samuel Kaufman. License: GPL-1.0+ or Artistic-1.0 Files: inc/Try/Tiny.pm Copyright: Copyright 2014 Yuval Kogman. License: GPL-1.0+ or Artistic-1.0 Files: t/30-integration/Class-InsideOut/basic.t Copyright: This software is copyright (c) 2013-2014 by David Golden, Toby Inkster. License: GPL-1.0+ or Artistic-1.0 Files: t/40-regression/ttxs-gh1.t Copyright: This software is copyright (c) 2014 by Jed Lund. License: GPL-1.0+ or Artistic-1.0 Files: examples/datetime-coercions.pl Copyright: This software is copyright (c) 2013 by Toby Inkster. License: GPL-1.0+ or Artistic-1.0 Files: t/30-integration/MooseX-Getopt/coercion.t Copyright: This software is copyright (c) 2014 by Alexander Hartmaier. License: GPL-1.0+ or Artistic-1.0 Files: inc/Test/Fatal.pm Copyright: Copyright 2014 Ricardo Signes. License: GPL-1.0+ or Artistic-1.0 Files: inc/Test/Requires.pm Copyright: Copyright 2014 MATSUNO Tokuhiro. License: GPL-1.0+ or Artistic-1.0 Files: t/40-regression/rt98113.t Copyright: This software is copyright (c) 2014 by Dagfinn Ilmari MannsÃ¥ker. License: GPL-1.0+ or Artistic-1.0 License: Artistic-1.0 This software is Copyright (c) 2014 by the copyright holder(s). This is free software, licensed under: The Artistic License 1.0 License: GPL-1.0 This software is Copyright (c) 2014 by the copyright holder(s). This is free software, licensed under: The GNU General Public License, Version 1, February 1989 CREDITS000664001750001750 244212422772214 13425 0ustar00taitai000000000000Type-Tiny-1.000005Maintainer: - Toby Inkster (TOBYINK) Contributor: - Alexander Hartmaier (ABRAXXA) - Dagfinn Ilmari Mannsåker (ILMARI) - David Steinbrunner - Diab Jerius (DJERIUS) - Gianni Ceccarelli (DAKKAR) - Graham Knop (HAARG) - Mark Stosberg (MARKSTOS) - Peter Flanigan (PJFL) - Peter Karman (KARMAN) - Pierre Masci - Samuel Kaufman (SKAUFMAN) - Vyacheslav Matyukhin (MMCLERIC) Thanks: - Benct Philip Jonsson - Brendan Byrd (BBYRD) - Caleb Cushing (XENO) - David Golden (DAGOLDEN) - Jason R Mash (JRMASH) - Kevin Dawson (BOWTIE) - Marcel Montes (SPICEMAN) - Marcel Timmerman (MARTIMM) - Matt Phillips (MATTP) - Matt S Trout (MSTROUT) - Michael G Schwern (MSCHWERN) - OMEGA - Peter Rabbitson (RIBASUSHI) - Richard Simões (RSIMOES) - Shlomi Fish (SHLOMIF) - Steven Lee (STEVENL) - Tim Bunce (TIMB) Changes000664001750001750 17007012422772214 13743 0ustar00taitai000000000000Type-Tiny-1.000005Type-Tiny ========= Created: 2013-03-23 Home page: Bug tracker: Maintainer: Toby Inkster (TOBYINK) 1.000005 2014-10-25 [ Bug Fixes ] - Fix short-circuiting optimizations for parameterized HashRef, ArrayRef, ScalarRef, and Map type constraints. Fixes RT#99312. Marcel Timmerman++ [ Test Suite ] - Fix annoying warning message in test suite with recent versions of Exporter::Tiny. 1.000004 2014-09-02 [ Bug Fixes ] - Fix for Type::Registry::DWIM. Fixes RT#98458. Marcel Montes++ - Fix issues with coercions and native attribute traits with some oldish versions of Moose on oldish versions of Perl. Fixes RT#98159. Peter Flanigan++ 1.000003 2014-08-28 [ Bug Fixes ] - Fix for coercions to parameterized Dict including a mixture of inlineable and non-inlineable optional values. Fixes RT#98362. Gianni Ceccarelli++ 1.000002 2014-08-18 [ Bug Fixes ] - Fix for overloaded operation fallback on Perl 5.10.x. Fixes RT#98113. Dagfinn Ilmari Mannsåker++ Peter Flanigan++ 1.000001 2014-08-18 [ Bug Fixes ] - Changes to dwim_type() in 0.047_09 broke the fallback to creating class types in some circumstances. This broke the MooX::late test suite, and some usages of MooX::late. Shlomi Fish++ 1.000000 2014-08-16 Happy CPAN Day! [ Documentation ] - Document the Type::Tiny versioning policy. - Updated NEWS file. - Updated TODO file. 0.047_09 2014-08-12 [ Bug Fixes ] - Fix documentation typo. Benct Philip Jonsson++ [ Documentation ] - Improvements and clarifications to Type::Coercion documentation. [ Test Suite ] - Add tests for Error::TypeTiny::Assertion's predicate methods. - Add tests for Type::Coercion's i_really_want_to_unfreeze method. [ Other ] - Better integration between Type::Library and Type::Registry. If you import a type constraint from a Type::Library-based module, it will automatically be inserted into your modules' type registry. - The to_Foo functions exported by Type::Library-based modules are now significantly faster. (But only if the type's coercion is frozen.) - Type::Utils::dwim_type now takes into account what OO framework the caller is using (Moose or Mouse) if it needs to fall back to asking the OO framework about a type constraint. 0.047_08 2014-08-05 Sanity++ [ Bug Fixes ] - Fix non-inlined version of NegativeOrZeroInt. [ Documentation ] - Document the remaining RT#93345-related issues - see "Deep Caveat" in Type::Tiny::Manual::Coercions. [ Test Suite ] - Alter the Types::Common::* test cases to use Test::TypeTiny. - Test to avoid the "too few arguments for type constraint check functions" error. Diab Jerius++ - Update t/30-integration/Moose/coercion.t to Moose 2.1200 which throws an exception rather than printing a warning when coerce=>1 is used on a type constraint with no coercions. [ Other ] - Prevent inlining of coercions if they've not been frozen. 0.047_07 2014-08-04 [ Bug Fixes ] - The extract_type function was missing from Type::Parser's @EXPORT_OK list. [ Test Suite ] - Test cases for Type::Parser::extract_type. [ Other ] - Parameterized Maybe constraints are now XS-accelerated. 0.047_06 2014-07-31 What made the Queen go all ice crazy? [ Bug Fixes ] - Bugfix in coercion inheritance where the child's type_coercion_map arrayref would end up as a reference to the parent's type_coercion_map. (Which was not good.) [ Test Suite ] - More Type::Registry test cases. [ Other ] - Added: Type::Coercion now has a i_really_want_to_unfreeze method. - Added: Type::Library now has a make_immutable method. - Coercions for the types defined in Types::Common::Numeric are now frozen. - Coercions for the types defined in Types::Common::String are now frozen. - Coercions for the types defined in Types::Standard are now frozen. - Parameterized types now have their coercions frozen automatically, so you can no longer add coercions to, say, ArrayRef[Int]. However, you can create a subtype of ArrayRef[Int] and add coercions to that. Michael G Schwern++ - Type::Registry now has methods for creating union/intersection/class/role type constraints. Type::Parser delegates to these, making it potentially reusable outside Type::Tiny by simply passing it an alternative type registry object. - Type::Registry/Type::Parser will now auto-load MouseX::Types libraries. 0.047_05 2014-07-29 Sanity++ [ REGRESSIONS ] - Introduced bug concerning coercions to parameterized Dicts with a mixture of inlineable and non-inlineable optional values. [ Documentation ] - Improve the documentation of Optional[] and slurpy. [ Other ] - A far saner implementation of Optional[]. - A slightly saner implementation of Types::TypeTiny's meta methods. - Optimizations for slurpy Any. - When slurping the tail of a Tuple into a hashref, check it's an even number of elements. 0.047_04 2014-07-28 The 98% Coverage Release [ Documentation ] - Type::Utils does not export english_list() and classifier() by default. [ Test Suite ] - Check that Mouse type converted to Type::Tiny objects keep their original error messages. - Improve test coverage for Type::Registry. - Improve test coverage for Type::Utils' match_on_type and compile_match_on_type. - Test code from SYNOPSIS sections (only in xt). - Test exceptions thrown by Types::Standard::ScalarRef. - Test that Sub::Quote-enabled coderefs generated by Type::Tiny and Type::Coercion can actually be retrieved by Sub::Quote. - Test the Type::Coercion overloading of ~~. - Test warnings raised by Type::Utils::declare(). - Tests for Test::TypeTiny::matchfor(). - Tests for dynamically delegated Type::Tiny an Type::Coercion methods. - Tests for introspection methods of Type::Coercion. - Tests for introspection methods of Types::TypeTiny. [ Other ] - Straighten out the relationships between Type::Coercion and its subclasses. - Type:Utils::match_on_type no longer automatically loads Types::Standard. 0.047_03 2014-07-26 The 96% Coverage Release [ Bug Fixes ] - Fix for slurpy Map within a Tuple. - Types::TypeTiny->has_type was incorrectly returning whether Types::TypeTiny contained the named *coercion* instead of a named *type*. [ Test Suite ] - Check Type::Library-based type libraries can extend MouseX::Types-based type libraries. - Check that Type::Registry works in conjunction with MouseX::Types. (There's some TODO stuff there.) - Checks for more Error::TypeTiny::Assertion explanations (Tuple, Duck, Intersection, Union, Dicts containing slurpy things). - Checks non-inlineable deep coercions for Tuple. - Fake a very old Validation::Class::Simple for a certain test by overriding $Validation::Class::Simple::VERSION. - Improved type constraint constructor tests (exceptions thrown for bad parameters, coercion=>ARRAY|CODE parameter). - Improved type introspection method tests (find_parent/is_supertype_of/is_subtype_of/is_strictly_supertype_of/is_s trictly_subtype_of). - Test the immutability of Type::Coercion::Union. - Tests for `isa`. - Tests for non-inlineable type constraints in `match_on_type` and `compile_match_on_type`. - Tests for various little methods which were added for Moose/Mouse-compatibility. [ Packaging ] - Bundle my TODO file. [ Other ] - Better `isa` faking - returns true to Class::MOP::Object. 0.047_02 2014-07-23 The 92% Coverage Release [ Documentation ] - Type::Tiny::Manual no longer says that Perl 5.6.x support is at risk. [ Test Suite ] - Add tests explicitly testing Type::Tiny objects conversion to Moose::Meta::TypeConstraint and Mouse::Meta::TypeConstraint objects. - Include test case relating to Type::Tiny::XS GitHub issue #1. - Stop using base.pm. - Test exceptions thrown by Type::Tiny::Class. - Test exceptions thrown by Type::Tiny::Enum. - Test exceptions thrown by Type::Tiny::Role. - Test the Error::TypeTiny::Compilation exception class. - Test the Error::TypeTiny::WrongNumberOfParameters exception class. [ Other ] - Allow Enums containing hyphens to be accelerated by Type::Tiny::XS. - Type::Tiny::Class should stop using Class::ISA. Instead, if mro.pm is not available, use a private sub stolen from MRO::Compat. - Type::Tiny::Intersection is now XS-accelerated. - Type::Tiny::Union is now XS-accelerated. 0.047_01 2014-07-21 The 87% Coverage Release [ Bug Fixes ] - Fix a silly test case that was relying on Exporter::Tiny to always load B.pm. (Current versions of Exporter::Tiny do load B.pm, but future versions might not.) [ Documentation ] - Better document which type constraints will be accelerated by Type::Tiny::XS and Mouse. [ Other ] - Type::Tiny::Enum is now XS-accelerated. - Types::Common::Numeric::PositiveInt is now XS-accelerated. - Types::Common::Numeric::PositiveOrZeroInt is now XS-accelerated. - Types::Common::String::NonEmptyStr is now XS-accelerated. - Types::Standard::Map is now XS-accelerated. - Types::Standard::Tuple is now XS-accelerated. - Unify _USE_XS/_USE_MOUSE logic in Type::Tiny. (It was previously scattered across Types::Standard and various other modules.) 0.046 2014-07-18 [ Bug Fixes ] - Fix for Types::TypeTiny::to_TypeTiny($coderef) when Sub::Quote is loaded but not used. - Undef no longer passes the Types::TypeTiny::StringLike type constraint. [ Test Suite ] - Add test cases for Types::TypeTiny (the library of type constraints used internally by Type::Tiny). [ Other ] - Minor optimizations to Types::TypeTiny::to_TypeTiny. 0.045_05 2014-07-18 [ Bug Fixes ] - More sensible use of Sub::Name in Type::Library. [ Documentation ] - Added a Type::Tiny::Manual::Optimization perldoc page. [ Other ] - Added: Type::Tiny now has a `where` method which is a shortcut for creating a child type with a constraint coderef. - Added: Type::Tiny now has an `of` method which is a shortcut for `parameterize` which I can never spell properly. - Restore and improve Mouse XS stuff dropped in Type-Tiny 0.045_03. 0.045_04 2014-07-15 [ Bug Fixes ] - Type::Params was warning about additional arguments passed to sprintf under Perl blead. The additional argument has been removed. [ Documentation ] - Updated NEWS file. [ Test Suite ] - Cope with changes to Type::Tie error messages introduced in Type::Tie 0.008. - Fix warnings in 30-integration/Moose/native-attribute-traits.t when run under perl -w. Peter Karman++ - Generally stop testing the contents of error messages produced by external modules! 0.045_03 2014-07-11 [ REGRESSIONS ] - The Mouse XS stuff introduced in Type-Tiny 0.003_09 has been partially removed. (I do plan on restoring it, and improving it.) [ Documentation ] - Update benchmark scripts, showing results with/without Type::Tiny::XS. [ Test Suite ] - When testing equivalence between Types::Standard types and core Moose types, don't test `Num` because Types::Standard provides two different implementations for it. [ Other ] - Type::Tiny::XS is now used (if available) to speed up some of the Types::Standard type constraints, plus Type::Tiny::Class and Type::Tiny::Duck. 0.045_02 2014-07-10 [ Bug Fixes ] - Remove outdated references to the overloaded + operator from Types::Standard documentation. Fixes RT#96379. Diab Jerius++ [ Documentation ] - Include benchmark/example of Type::Params versus Scalar::Validation. 0.045_01 2014-06-30 [ Bug Fixes ] - Ensure that when a Type::Tiny object is inflated into a Moose::Meta::TypeConstraint, inlining still happens via Type::Tiny. omega++ - Workaround strange behaviour of exists() function when applied to @_ on Perl older than 5.20 which caused some uses of Optional[Foo] to accept an explicit undef. Caleb Cushing++ 0.044 2014-06-03 [ Documentation ] - Updated NEWS file. 0.043_05 2014-05-21 [ Bug Fixes ] - Fix inflation of Type::Coercion objects to Moose::Meta::TypeCoercion when some of the coercion routines are given as strings. [ Documentation ] - Document the is_*, to_*, and assert_* functions in Type::Tiny::Manual::Libraries. Alexander Hartmaier++ - Mention coercion=>1 and why it is useful in Type::Tiny::Manual::Coercions. Alexander Hartmaier++ [ Test Suite ] - Integration tests for MooseX::Getopt. Alexander Hartmaier++ [ Other ] - Detect missing comma in declaration of type constraints using Type::Utils a la `declare Foo as Bar`, and print a warning. Tim Bunce++ - No longer need to inflate a Type::Tiny object to Moose::Meta::TypeConstraint in order to give an answer to $type->isa('Moose::Meta::TypeConstraint::Union'). 0.043_04 2014-05-21 [ Test Suite ] - Improve test cases for integration with Moose native attribute traits. 0.043_03 2014-05-06 [ Documentation ] - Rename Types::Datetime to Example::Types because there is now really a Types::DateTime on CPAN. - Type::Tiny::Manual::Libraries add example of using the custom types library. Peter Karman++ [ Test Suite ] - Add some test cases for the Error::TypeTiny class. - Improve Eval::TypeTiny test cases. - Tests for Type::Library error messages. [ Packaging ] - Updated bundled version of Try::Tiny. [ Other ] - Added: Extremely experimental and mostly undocumented my_method stuff. - Added: Type::Utils::classifier 0.043_02 2014-04-11 - Added: Experimental my_methods attribute so that type constraints can offer additional methods. - Added: Type::Tiny now has a find_parent method. 0.043_01 2014-04-06 - Sub::Quote quoted coderefs passed to to_TypeTiny() now result in inlinable type constraints. 0.042 2014-04-02 [ Documentation ] - Include more recent results in benchmarking example scripts. - List currently unstable/experimental parts of the distribution in Type::Tiny::Manual::Policies. 0.041_04 2014-03-31 [ Test Suite ] - Add tests for given/when matching against type constraints. 0.041_03 2014-03-28 [ Documentation ] - Improve documentation for the Type::Coercion class; especially its constructors, attributes and methods. - Improve documentation for the Type::Tiny class; especially its constructor, attributes and methods. 0.041_02 2014-03-26 [ Bug Fixes ] - Fix Type::Tiny::Duck's inlining of code when given the variable name `$_`. Fixes RT#94196. Diab Jerius++ [ Documentation ] - Type::Tiny::Manual links to various parts of the test suite to document concepts. These links had grown stale and have now been updated. - Updated NEWS file. [ Test Suite ] - Prevent 20-unit/Type-Registry/moosextypes.t from failing due to too old MooseX::Types::Common - just skip the test script if MXTC is older than 0.001004. 0.041_01 2014-03-17 [ BACK COMPAT ] - Type::Tiny and Type::Coercion no longer overload addition. This feature never really worked very well with regard to precendence, requiring lot of parentheses to use. The overload also made solving the parameterizable type coercion problem very difficult. [ Other ] - Parameterizable coercions are now passed a reference to the type constraint they should target. 0.040 2014-03-17 [ Documentation ] - Refreshed SEE ALSO section of Type::Tiny::Manual::Libraries. - Updated NEWS file. 0.039_13 2014-03-15 [ Bug Fixes ] - Fix occasional segfaults on threaded Perl 5.18.x. Graham Knop++ [ Test Suite ] - Test for occasional segfaults on threaded Perl 5.18.x. Graham Knop++ 0.039_12 2014-03-12 [ Bug Fixes ] - Various Type::Utils functions were trying to dereference undef as a hash or array in certain circumstances. Matt Phillips++ [ Other ] - Type::Utils' class_type and role_type functions will $name =~ s/:://g. Matt Phillips++ 0.039_11 2014-03-11 [ Test Suite ] - Because of changes to Data::Dumper in Perl 5.19.x, the test suite was previously skipping some Dumper-based test cases depending on Perl version. However, Dumper is dual-lifed, so older versions of Perl may have shiny, new Dumpers. Skip test cases based on Data::Dumper version instead. 0.039_10 2014-03-10 [ Documentation ] - Document the benefits of freezing coercions, and of defining coercions either within the type library, or via $type->plus_coercions. [ Other ] - $type->plus_coercions and friends now return objects with frozen coercions. 0.039_09 2014-02-25 [ Documentation ] - Update Type::Tiny::Manual::Params to mention Kavorka, and newer features of Function::Parameters. [ Test Suite ] - Test integration with Moops. - Test integration with Switcheroo. - Test that coercions attached to Moose type constraints get inherited by Type::Tiny when they are inhaled. - Unit tests for Devel::TypeTiny::Perl56Compat. - Unit tests for Devel::TypeTiny::Perl58Compat. 0.039_08 2014-02-24 [ Test Suite ] - Test integration with Kavorka. 0.039_07 2014-02-17 [ Bug Fixes ] - Fix hash ordering bug in Return::Type integration tests. 0.039_06 2014-02-17 [ Bug Fixes ] - Type::Tiny's SUPPORT_SMARTMATCH constant was broken; fixed now. - Type::Tiny's TIEARRAY and TIEHASH methods were broken; fixed now. [ Test Suite ] - Enable some old tests that had been disabled as not-yet-implemented for parameterized type constraints; the feature they test was implemented ages ago. - Test integration with Return::Type. - Test integration with Type::Tie. - Test integration with match::simple. 0.039_05 2014-02-15 - Apply the Type::Tiny::_HalfOp trick to overloaded addition too. 0.039_04 2014-02-05 - Make overloaded ops on parameterized type constraints work more consistently between Perl above and below 5.14, reducing the need for parenthesizing complex type constraint expresssions. Graham Knop++ 0.039_03 2014-02-05 [ Bug Fixes ] - Make Type::Utils::declare_coercion work outside type libraries. Fixes RT#92591. Diab Jerius++ - Weak reference from Type::Coercion objects to target type constraint caused bad behaviour in some cases. This has been fixed by retaining enough information within the Type::Coercion to be able to reconstruct its type constraint if it disappears due to the reference count falling to zero. Fixes RT#92571. Diab Jerius++ 0.039_02 2014-01-25 [ Test Suite ] - Add tests for Test::TypeTiny. 0.039_01 2014-01-21 [ Documentation ] - The preferred IRC channel for support is now #moops. [ Test Suite ] - Restructure the 't' directory. [ Other ] - Removed: Exporter::TypeTiny. 0.038 2014-01-01 [ Documentation ] - Copyright 2014. - Updated NEWS file. 0.037_03 2013-12-30 [ Bug Fixes ] - Fix problems with Moo::HandleMoose integration on threaded Perls. Graham Knop++ Kevin Dawson++ Matt S Trout++ [ Test Suite ] - Skip leak.t on threaded Perls (for now). 0.037_02 2013-12-29 [ Documentation ] - Link to the Type::Tiny stability policy from the pod of each module it covers. 0.037_01 2013-12-24 [ Bug Fixes ] - Fix a Type::Params/B problem on Perl 5.6.x. 0.036 2013-12-21 [ Documentation ] - Updated NEWS file. 0.035_01 2013-12-17 - Make Type::Parser work with newer versions of MooseX::Types::Common which uses namespace::autoclean. Fixes RT#91468. David Steinbrunner++ - Make parameterized Dict and Map type constraints work with Moose native hash attribute trait. Jason R Mash++ 0.034 2013-12-09 [ Documentation ] - Updated NEWS file. 0.033_04 2013-12-06 [ Test Suite ] - Further tests related to RT#90096. Diab Jerius++ [ Other ] - Implement coercion_names, get_coercion, has_coercion, and has_type methods for Types::TypeTiny, to make it more like a real Type::Library type library. - The `extends` function from Type::Utils now allows inheritance of coercions, not just types. Fixes RT#91153. Jason R Mash++ 0.033_03 2013-11-26 [ Bug Fixes ] - Fix bug in Type::Params::multisig with regard to slurpy parameters. Fixes RT#90865. Diab Jerius++ [ Documentation ] - Make Error::TypeTiny::Assertion's explain method act more according to documentation. Fixes RT#90867. Diab Jerius++ [ Packaging ] - Recommend Sub::Name in META.json. 0.033_02 2013-11-26 - Split out some of the longer parts of Types::Standard into other modules that will be loaded on demand; this shaves about 20% off the load time of Types::Standard. 0.033_01 2013-11-07 [ Bug Fixes ] - Type::Params now localizes $_ before trying to assign anything to it. Fixes RT#90096. Samuel Kaufman++ [ Test Suite ] - Test case using a Type::Params compiled check within the scope of a read-only $_ variable. Samuel Kaufman++ [ Other ] - Added: Types::Common::Numeric - Added: Types::Common::String 0.032 2013-11-05 Remember, remember the fifth of November [ Bug Fixes ] - Eliminate a warning under Perl 5.6.x. [ Documentation ] - Updated NEWS file. 0.031_05 2013-11-04 [ Documentation ] - Fix minor typo. David Steinbrunner++ [ Other ] - Allow Dict to take a slurpy parameter - a la Dict[foo => Int, slurpy HashRef[Num]]. Matt S Trout++ 0.031_04 2013-11-03 [ Bug Fixes ] - Type::Parser 0.031_02 introduced a bug under Perl 5.6.x where we relied on the existence (or not) of a hash item being affected by `local`; this was implemented in Perl 5.8.0. Work around this problem by checking definedness instead. 0.031_03 2013-11-03 - Added: Deep coercions for Maybe[`a]. Fixes RT#89936. Brendan Byrd++ 0.031_02 2013-11-03 - Type::Parser now differentiates between Tuple[] and Tuple too. - Type::Parser only treats a comma as an operator within a parameterization now, and is thus now able to parse types from the head of a string which is a comma-separated list of types. 0.031_01 2013-10-28 [ Bug Fixes ] - Differentiate Tuple[] vs Tuple, and Dict[] vs Dict. Fixes RT#89696. Benct Philip Jonsson++ [ Documentation ] - Improved documentation for Types::TypeTiny. [ Test Suite ] - Adjustments to cope with newer Moose is-class-loaded heuristics. - Check Moose exception objects with isa rather than regexp matching. 0.030 2013-10-18 [ Documentation ] - Updated NEWS file. [ Test Suite ] - Skip leak.t on Perl < 5.10.1. Type-Tiny does have some memory leaks in particular older versions of Perl: 5.8.8 and 5.10.0 are known to be problematic, but 5.8.9 seems fine. Ultimately it would be nice to get these fixed, but in the mean time skipping the test case makes the distribution easier to install. 0.029_04 2013-10-17 [ Bug Fixes ] - Fix inlining of type checks in Moo which was broken around about version 0.027_09. - Fix validate_explain error messages in Type::Tiny::Union. Fixes RT#89279. Brendan Byrd++ [ Other ] - $Type::Tiny::DD can be set numerically. Fixes RT#89251. Tim Bunce++ - Improve error messages under Moo. Fixes RT#89234. Graham Knop++ 0.029_03 2013-10-17 [ Bug Fixes ] - Fix segfault on Perl 5.8.1 to 5.8.3. (And possibly some other 5.8.x Perls.) Caused by the combination of eval and goto. Dagfinn Ilmari Mannsåker++ Graham Knop++ Peter Rabbitson++ - Older versions of Scalar::Util::looks_like_number return true for undef; work around them. 0.029_02 2013-10-11 [ BACK COMPAT ] - Renamed the Type::Exception modules to Error::TypeTiny. Fixes RT#89280. Brendan Byrd++ [ Documentation ] - Fix typos in documentation of Error::TypeTiny package variables. [ Other ] - $Type::Tiny::DD package variable can now be used for a pluggable data dumper coderef. Fixes RT#89251. Tim Bunce++ - Type::Tiny::Enum type constraints are now subtypes of Types::Standard::Str; not Types::Standard::Defined. David Golden++ - Types::Standard::Item is now a subtype of not Types::Standard::Any. David Golden++ 0.029_01 2013-09-26 - Replace Exporter::TypeTiny with Exporter::Tiny (an external dependency). 0.028 2013-09-26 [ Documentation ] - Note in documentation for Type::Tiny::Union, etc that constraint/inlining coderefs not only should not be provided to the constructor, but cannot! Fixes RT#88655. Brendan Byrd++ - Updated NEWS file. 0.027_09 2013-09-20 [ REGRESSIONS ] - Inlining of type checks in Moo broken in this release, or hereabouts. Fixed in 0.029_04. [ Bug Fixes ] - Fix whitespace in error messages. [ Test Suite ] - Skip leak.t on Perl 5.10.0. 0.027_08 2013-09-19 [ Bug Fixes ] - Fix typo in Type::Utils for coerce=>1 --> coercion=>1. Fixes RT#88798. Diab Jerius++ - Fix typo in changelog for previous developer release. - Type::Exception::Assertion changes from 0.027_05 are now conditional upon Perl version; only take effect on Perl 5.8+; they just weren't working on Perl 5.6. [ Test Suite ] - More changes to version numbers reported by 00-begin.t. [ Other ] - Explicitly overload boolification (always true!) in Type::Exception. 0.027_07 2013-09-18 [ Bug Fixes ] - Fix missing version number in Type::Coercion::FromMoose [ Test Suite ] - Changes to version numbers reported by 00-begin.t. [ Other ] - Also ensure Mouse type constraints converted to Type::Tiny constraints retain their coercions. 0.027_06 2013-09-18 [ Documentation ] - Add a draft Stability Policy to Type::Tiny::Manual. [ Other ] - Added: Override `validate_explain` in all the bundled subclasses of Type::Tiny. - Added: Type::Coercion::FromMoose - Added: Type::Tiny::Union now provides a `find_type_for` method which should be compatible with Moose's equivalent method. - Added: Type::Utils now provides an `english_list` function like Moose::Util does. This was useful internally for implementing `validate_explain` methods. - Loosen the rules for Type::Tiny and Type::Coercion name attributes; allow them to begin with one or two leading underscores. - Memoize Types::TypeTiny::to_TypeTiny. - Stop using base.pm. - Type::Tiny::Union's compiled checks no longer close over the type constraints which are in the union. - Types::TypeTiny::to_TypeTiny now uses Type::Coercion::FromMoose to ensure Moose type constraints converted to Type::Tiny constraints retain their coercions. 0.027_05 2013-09-15 - Added: Provide a `validate_explain` method as part of Type::Tiny's public API. - Include a detailed explanation in the stringification of Type::Exception::Assertion. - Refactor the explanation generation mechanism. 0.027_04 2013-09-09 [ Test Suite ] - The file t/moose-coercion.t was checking a particular Moose warning message. In Moose 2.1100, this warning has been upgraded to an exception. For now, disable that particular check. 0.027_03 2013-09-09 [ Bug Fixes ] - Prevent Eval::TypeTiny from leaking stashes by recycling the sandbox. [ Test Suite ] - Fix the ultra-finicky t/02-api.t to cope with changes to Moose::Meta::TypeConstraint API in Moose 2.1100. 0.027_02 2013-09-08 [ Bug Fixes ] - Restore Type::Tiny -> Moose -> Type::Tiny round-tripping broken in previous release. [ Documentation ] - In Type::Tiny::Manual::Coercions, explain how to chain coercions. 0.027_01 2013-09-07 [ REGRESSIONS ] - Weakening various references to fix memory leaks led to breaking Type::Tiny -> Moose -> Type::Tiny round-tripping via Types::TypeTiny::to_TypeTiny. Test cases for this marked TODO. [ Bug Fixes ] - Fixed some memory leaks. Still some work to do in this area. [ Other ] - Added `coercibles` method to Type::Tiny. Diab Jerius++ 0.026 2013-09-05 [ Documentation ] - Updated NEWS file. 0.025_03 2013-09-04 [ Documentation ] - Document that multisig() accepts coderefs. [ Packaging ] - Use a newer version of RDF::DOAP to process this changelog. 0.025_02 2013-09-02 [ Bug Fixes ] - functionparameters.t now requires Moo or Moose and is skipped otherwise. [ Other ] - Added: Type::Params now provides a multisig() function, allowing you to define multiple function signatures, and attempt to validate @_ against them each in turn. Fixes RT#88291. Diab Jerius++ 0.025_01 2013-09-02 [ Bug Fixes ] - The Tuple structured type was treating arrays with missing required elements as if they were present but undef. Fixes RT#88277. Steven Lee++ [ Documentation ] - Document the internals of Exporter::TypeTiny. [ Packaging ] - Take advantage of dynamic_config to ask automated testers to test Type::Tiny with Moose present, but only if the Type::Tiny version number includes an underscore. - use Dist-Inkt [ Other ] - Exporter::TypeTiny will now use method-style resolution when searching for a sub to export. - Make Exporter::TypeTiny support generators with less internals-hacking. 0.024 2013-08-27 [ Documentation ] - Updated NEWS file. 0.023_03 2013-08-23 [ Bug Fixes ] - Constructors for some subclasses of Type::Tiny rejected hashrefs of paramaters. Fixes RT#88064. Brendan Byrd++ - Stop considering the empty string to be a valid package name. [ Test Suite ] - Include additional test cases stolen from Moose. [ Other ] - Implementation of RegexpRef in Types::Standard is now closer to Moose's implementation (accepts blessed Regexps). 0.023_02 2013-08-23 [ Bug Fixes ] - Fix quoting in error messages which caused Type::Params to be unable to compile some coderefs. Fixes RT#87846. Tim Bunce++ - Improve ugly type assertion failure messages when given structures of nested references. Fixes RT#87999. Tim Bunce++ [ Other ] - Added: Type::Registry now has an `add_type` method, for adding a single type constraint to a registry. - Type::Registry's `add_types` method now supports importing MooseX::Types and MouseX::Types libraries. - Type::Utils' `extend` function now supports extending MooseX::Types and MouseX::Types libraries. 0.023_01 2013-08-16 [ Bug Fixes ] - Fix Moo -> Moose type inflation issue. Matt Phillips++ 0.022 2013-08-06 [ Documentation ] - Updated NEWS file. [ Other ] - Improved implementations of is_subtype_of/is_strictly_subtype_of; better for subclassing. - In Devel::TypeTiny::Perl56Compat, `use strict` and `use warnings`. 0.021_04 2013-07-30 [ Bug Fixes ] - Fix Type::Parser's handling of numeric parameters; they shouldn't need quoting. - Fix Types::Standard::Dict differentiating between undef and not exists. Fixes RT#87443. Tim Bunce++ [ Packaging ] - Add dependency on Exporter 5.57 for older versions of Perl. 0.021_03 2013-07-30 - Improve compatibility between Type::Tiny and Moose attribute native traits. - Restore Eval::TypeTiny's pre-0.019_01 behaviour re closing over lexicals, but enable the 0.021_02 behaviour if alias=>1 option is passed in. 0.021_02 2013-07-26 - Use real lexicals again for Eval::TypeTiny; this requires Devel::LexAlias, but there's a fallback to using tied variables. 0.021_01 2013-07-24 - Added: Type::Tiny is_strictly_a_type_of method. - Added: Type::Tiny is_strictly_subtype_of method. - Added: Type::Tiny is_strictly_supertype_of method. - Added: Type::Tiny strictly_equals method. 0.020 2013-07-23 [ Documentation ] - Updated NEWS file. 0.019_01 2013-07-23 [ Bug Fixes ] - Eval::TypeTiny now closes over variables properly. - Work around lack of B::perlstring() function in Perl 5.6.x in test suite. 0.018 2013-07-21 [ Documentation ] - Updated NEWS file. 0.017_02 2013-07-20 [ Bug Fixes ] - Further changes for Perl 5.6.x support. [ Other ] - Hopefully improved workaround for missing B::perlstring() using Data::Dumper instead of quotemeta(). Peter Rabbitson++ 0.017_01 2013-07-19 [ Bug Fixes ] - Work around lack of B::perlstring() function in Perl 5.6.x. [ Documentation ] - Fix typo in Types::Standard 'regular exception' -> 'regular expression'. Mark Stosberg++ - Give an example of the default error messages thrown by Type::Tiny. - Improve examples of custom type constraint error message in Type::Utils and Type::Tiny::Manual::Libraries. Fixes RT#86892. Tim Bunce++ [ Other ] - Updated: Eval::TypeTiny now supports lexical subs under Perl 5.18. 0.016 2013-07-16 [ Documentation ] - Add some pod links. - Updated NEWS file. 0.015_05 2013-07-15 [ Packaging ] - Experimentally drop required version of Perl from 5.8.1 to 5.6.1. I've not been able to extensively test Type-Tiny on Perl 5.6.x, but I believe it should mostly work. (The only feature that seems unlikely to work is non-ASCII names for type constraints and coercions.) [ Other ] - Stop monkey-patching Moose::Meta::TypeContraint; it's not necessary and has never been documented. 0.015_04 2013-07-13 [ Documentation ] - Clarify when inlining via Sub::Quote may be less efficient than hand-written inlining. Fixes RT#86893. Tim Bunce++ - Mention in Type::Tiny::Manual::Libraries that the `extends` function is no longer exported by default; update example code. Fixes RT#86813. Pierre Masci++ [ Other ] - Allow an inline_as block to return a list of strings (which are implictly joined with &&); allow the first item on the list to be undef, which is treated as the inlined parent type constraint. Fixes RT#86891. Tim Bunce++ 0.015_03 2013-07-08 - Added: Implement TIESCALAR, TIEARRAY and TIEHASH methods for Type::Tiny; this improves Type::Tie integration. - Slight speed improvements for `compile_match_on_type`. - The `dwim_type` function now prioritizes lookups within the caller class' type registry over Types::Standard's built-in types. 0.015_02 2013-07-06 - Better test cases for `dwim_type`. - Improvements to DWIMness of Type::Parser for the benefit of `dwim_type`. 0.015_01 2013-07-05 - Added: Type::Utils now provides a `dwim_type` function; this is powered by a hidden Type::Registry::DWIM package. - Type::Parser can now pull in types from MooseX::Types libraries properly. 0.014 2013-06-28 [ Documentation ] - Updated NEWS file. 0.013_01 2013-06-27 [ BACK COMPAT ] - Type::Parser functions no longer accept an arrayref of tokens, as they expect to pull tokens from a stream as required. - Type::Parser no longer provides a `tokens` function as it no longer pre-emptively tokenizes the whole string it is given. [ Other ] - Added: Type::Parser now provides a `extract_type` function which parses a type constraint expression from the head of a string and returns a Type::Tiny object, plus the tail of the string. (This is designed to make it easier to use Type::Parser to parse things like function signatures.) - Type::Parser's tokenization is now done on a pull basis, allowing one-pass building of the AST. 0.012 2013-06-25 [ Documentation ] - Updated NEWS file. 0.011_03 2013-06-25 [ Bug Fixes ] - Type::Tiny now overloads `cmp`. Necessary because Mouse does a sort on type constraints in a union, and overload's fallback doesn't seem to cover `cmp` on Perl prior to 5.12. 0.011_02 2013-06-25 [ Bug Fixes ] - Types::Standard 0.009_02 stopped including 'library' attribute in its types, and thus broke MooX::late. Type::Library modified to make 'library' attribute more automatic, and less reliant on Type::Utils to do the right thing. Graham Knop++ 0.011_01 2013-06-25 [ Bug Fixes ] - B::SPECIAL-related fix. Fixes RT#86383. Peter Flanigan++ - Unions of Type::Tiny and Mouse::Meta::TypeConstraints now work properly. This makes Type::Tiny and MouseX::Types play nice together (much like Type::Tiny already plays nice with MooseX::Types). [ Other ] - Cleanups within Type::Coercion. Necessary because in some places the entire type_coercion_map (including conversion coderefs) was passed through Types::Standard::to_TypeTiny, when really only the type constraints should have been. - Types::Standard::to_TypeTiny now accepts any object implementing the Type::API::Constraint or Type::API::Constraint::Coercion interfaces. As Mouse::Meta::TypeConstraint implements this interface, specific support for importing Mouse types has been dropped; the generic Type::API import 'just works' for Mouse types. - Types::Standard::to_TypeTiny now accepts unblessed coderefs and converts them to type constraints. This allows things like `Int & sub { $_ < 10 }` to work. 0.010 2013-06-24 [ Documentation ] - Updated NEWS file. 0.009_07 2013-06-24 [ Test Suite ] - Make rt86172.t an 'xt' test case because it's causing random CPAN testers failures unrelated to the feature it's supposed to be testing. - More test cases for interacting with MooseX::Types type constraints. [ Other ] - If a Type::Tiny object is instantiated with a Sub::Quote quoted constraint coderef, and no inlined coderef, then Type::Tiny will use Sub::Quote to make an inlined coderef. - Subclasses of Type::Tiny reject 'inlined' coderef, just like they already reject 'constraint' coderef. - Type::Params no longer uses Type::Utils. - Types::Standard::to_TypeTiny now sets 'display_name' instead of 'name' on generated type constraints. 0.009_06 2013-06-23 [ Bug Fixes ] - Careful calling the DOES method (it doesn't exist in Perl 5.8). 0.009_05 2013-06-23 [ Bug Fixes ] - Type::Registry does the AUTOLOAD thing, so ought to provide a DESTROY method. 0.009_04 2013-06-23 [ Bug Fixes ] - Type::Tiny::Class shouldn't completely trust @ISA when establishing parent class heirarchies. [ Other ] - Constructors for Type::Tiny subclasses no longer accept the 'constraint' parameter; it doesn't make sense. - Updated: Support Type::API interfaces. 0.009_03 2013-06-22 [ Bug Fixes ] - Fix Types::Standard compilation errors under Perl 5.8.x. 0.009_02 2013-06-22 [ REGRESSIONS ] - Types::Standard types no longer have 'library' attribute set; this subtly breaks Moo type inflation, and breaks the MooX::late test suite which relies on type inflation working correctly. [ Bug Fixes ] - Fix for compiled_checks for type constraints inheriting from Type::Tiny::Class, etc. Richard Simões++ [ Other ] - Types::Standard no longer uses Type::Utils. - Various minor optimizations for Eval::TypeTiny, Type::Tiny, etc. 0.009_01 2013-06-21 [ Bug Fixes ] - Fix error messages from type constraints with null constraint coderefs. [ Other ] - Added: Reply::Plugin::TypeTiny. 0.008 2013-06-21 [ Documentation ] - Updated NEWS file. 0.007_10 2013-06-21 [ Bug Fixes ] - Fixed many small parsing bugs in Type::Parser. - MooseX::Types objects used in Type::Tiny::Union, Type::Tiny::Intersection and parameterized Type::Tiny type constraints would break in some circumstances, as Types::TypeTiny::to_TypeTiny was failing to convert them to native Type::Tiny type constraints. Fixes RT#86303. [ Documentation ] - Document status of Type::Registry. [ Test Suite ] - Add test cases for Type::Parser. - Better test cases for Type::Registry. [ Other ] - Added: Type::Parser now exports a _std_eval function useful for testing. - Improved error messages from Type::Parser. - Type::Parser now supports parentheses in its DSL. 0.007_09 2013-06-18 [ Bug Fixes ] - Fix problems inlining Dict deep coercions where the target constraint could not be inlined. Fixes RT#86233. Vyacheslav Matyukhin++ - Fix unintuitive Dict deep coercions. Fixes RT#86239. Vyacheslav Matyukhin++ [ Test Suite ] - Bundle various tests for deep Dict coercions. Vyacheslav Matyukhin++ 0.007_08 2013-06-17 [ Bug Fixes ] - Fix problem with interaction between constraints, coercions, and Moose classes that inherit from Moo classes. Fixes RT#86172. Peter Flanigan++ [ Test Suite ] - Bundle test for interaction between constraints, coercions, and Moose classes that inherit from Moo classes. Peter Flanigan++ 0.007_07 2013-06-16 [ Bug Fixes ] - Partly roll back prototype changes. Now we use `;$` for Perl since 5.14, but `;@`, for older Perls that don't support `;$` so well. 0.007_06 2013-06-16 [ BACK COMPAT ] - Better prototypes (was `;@`, now `;$`) for parameterizable type 'constants' exported by type libraries. Matt S Trout++ - Type::Utils no longer exports 'extends' by default. [ Documentation ] - Document the evaluation environment used by Eval::TypeTiny. - Rearranged documentation for Type::Utils, avoiding previous split into Moose-like and non-Moose-like functions. [ Other ] - Added: Type::Exception is now capable of supplying stack traces (requires Devel::StackTrace). - Exceptions thrown for Moo isa/coerce now indicate which attribute was involved. 0.007_05 2013-06-12 [ Documentation ] - Mention Scalar::Does and Type::Tie in manual. - Vastly improved documentation for Type::Utils. - Vastly improved documentation for Types::Standard. [ Test Suite ] - Added test cases for InstanceOf, ConsumerOf, HasMethods and Enum types defined by Types::Standard. [ Other ] - Added: Add match_on_type and compile_match_on_type to Type::Utils. - Support '0' and '1' as shortcuts for Optional[Any] and Any in Type::Params. (Not documented yet.) 0.007_04 2013-06-09 [ Bug Fixes ] - Overloading of `$type eq $type` now works in Perl 5.8. Fixes RT#85895. Vyacheslav Matyukhin++ - The combination of Dict, Optional and coercions seems to have been broken in certain circumstances. Fixes RT#86001. Diab Jerius++ 0.007_03 2013-06-08 [ Bug Fixes ] - Inlining of certain deep Dict, Tuple and Map coercions was broken, but Type::Params attempted to inline them anyway, leading to death. Fixes RT#85911. Diab Jerius++ [ Documentation ] - Better document Type::Tiny's 'parents' method which differs from the Moose method of the same name. 0.007_02 2013-06-04 [ Documentation ] - Improvements to Type::Tiny::Manual. - Improvements to Type::Tiny::Manual::Params, including rewritten manual processing section, and processing type constraints in function signatures via Function::Parameters/Attribute::Constract. [ Test Suite ] - Test cases for usage with Function::Parameters. [ Other ] - Added: New constraints added to Types::Standard: InstanceOf, ConsumerOf, HasMethods and Enum. Graham Knop++ - Allow constraint_generators (for parameterizable type constraints) to return full Type::Tiny objects instead of plain coderefs. - Drop use of Carp in Type::Parser. - Type::Tiny::Class types now have an automatically calculated parent type constraint based on @ISA. - Type::Tiny::Duck types now have a parent type constraint of Types::Standard::Object. - Type::Tiny::Enum types now have a parent type constraint of Types::Standard::Str. - Type::Tiny::Intersection types now have an arbitrary parent type constraint. - Type::Tiny::Role types now have a parent type constraint of Types::Standard::Object. - Type::Tiny::Union types now have an automatically calculated parent type constraint based on the most specific common parent type constraint. 0.007_01 2013-06-01 Happy birthday to me... [ BACK COMPAT ] - Types::Standard's Num constraint is now a subtype of either LaxNum and StrictNum (depending on environment). [ Bug Fixes ] - Fix $VERSION defined in Type::Library. [ Packaging ] - Generate README from Type::Tiny::Manual instead of Type::Tiny. [ Other ] - Added: Type::Parser. - Added: Types::Standard now has LaxNum/StrictNum type constraints. - Implemented Types::TypeTiny->meta->get_type. - Re-introduce Type::Registry, with improved parsing thanks to Type::Parser. 0.006 2013-05-28 [ Bug Fixes ] - Exporter::TypeTiny::mkopt_hash now works. 0.005_08 2013-05-28 [ Test Suite ] - Add 00-begin.t. - Rearrange test cases - Use JSON::PP instead of JSON in test cases, because JSON::PP is a core module since Perl 5.14. 0.005_07 2013-05-28 [ Bug Fixes ] - Assertions using the assert_return pattern were triggering FATAL warnings when inlined with Sub::Quote. Inlined assertions are now prefixed with 'no warnings "void";'. [ Documentation ] - Add pure-Perl Mouse to examples/benchmark-constraints.pl. 0.005_06 2013-05-26 [ Bug Fixes ] - Fix StrMatch to properly support regexps containing slashes. [ Other ] - Fold Types::Standard::DeepCoercion into Types::Standard. 0.005_05 2013-05-24 [ Documentation ] - Suggest newer version of Validation::Class. [ Other ] - Added: Type::Tiny now has an assert_return method, which is used in most places in preference to assert_valid. - Fix warnings under Perl 5.18. - Removed: Removed Type::Registry from the release; it will return at a later date. 0.005_04 2013-05-17 [ Bug Fixes ] - Fixed bug in non-inlined code for Types::Standard::MkOpt. [ Other ] - Added: Type::Exception::Compilation. - All error conditions now throw exception objects instead of string error messages. - Allow the slurpy tail of a Types::Standard::Tuple to be a treated as a hashref rather than an arrayref. - Deep explanations for Types::Standard::{Map,Maybe,Ref,Dict,Tuple} type constraint assertion failures. - Improved deep explanations for Types::Standard::{ArrayRef,HashRef,ScalarRef}. - Test::TypeTiny performs more thorough testing if EXTENDED_TESTING environment variable is set. - Throw exception if people attempt to set parent types for Type::Tiny::{Class,Role,Duck,Enum,Union,Intersection}. 0.005_03 2013-05-14 - Many error conditions now throw exception objects instead of string error messages. - Removed: Bytes and Chars type constraints removed from Types::Standard. - Removed: Decode and Encode coercions removed from Types::Standard. 0.005_02 2013-05-14 [ Documentation ] - Fix a typo in declare_coercion in Type::Tiny::Manual::Coercions. Vyacheslav Matyukhin++ - Link to Type::Tiny::Manual::Libraries instead of non-existing Type::Tiny::Intro. Vyacheslav Matyukhin++ 0.005_01 2013-05-07 [ Bug Fixes ] - Type::Library should require Perl 5.8.1, not 5.8.3. [ Other ] - Added: ArrayLike type added to Types::TypeTiny. - Added: Type::Registry. 0.004 2013-05-06 [ Bug Fixes ] - Eval::Closure now strips line breaks and other unsavoury characters from descriptions. [ Other ] - Minor updates to to_TypeTiny following Validation::Class 7.900048 release. 0.003_16 2013-05-05 [ Documentation ] - Document that Map[`k,`v] has a deep coercion. - Improve Type::Coercion documentation. [ Other ] - Minor updates to coderef overloading following Moo 1.002000 release. - Rename Types::Standard::AutomaticCoercion -> Types::Standard::DeepCoercion. - Type::Params produces nicer error messages. 0.003_15 2013-05-03 - Improvements to to_TypeTiny function, including accepting Validation::Class::Simple objects. 0.003_14 2013-05-03 0.003_13 2013-05-03 [ Bug Fixes ] - Don't crash in old versions of Moose that have no Class::MOP::_definition_context() function. [ Documentation ] - Fix typo in Type::Params documentation. Diab Jerius++ [ Test Suite ] - BAIL_OUT in test suite if 00-compile.t or 01-api.t fail. [ Other ] - Better documentation and tests of Moose/Mouse-compatible API. 0.003_12 2013-05-01 [ Bug Fixes ] - Sane behaviour for Types::Standard's 'slurpy' function when it appears mid-list. [ Other ] - Allow people to use Carp::{confess,cluck,carp} with Type::Params validators; default is still croak. - Improved Type::Params documentation. - Type::Params validators now explicitly check the number of arguments passed to them. Vyacheslav Matyukhin++ 0.003_11 2013-04-30 [ Test Suite ] - Test cases for Eval::TypeTiny. [ Other ] - Automatic coercion for parameterized Dict will no longer drop key/value pairs to force a coercion. Vyacheslav Matyukhin++ - Automatic coercion for parameterized Tuple will no longer drop values to force a coercion. Vyacheslav Matyukhin++ 0.003_10 2013-04-29 [ Documentation ] - Improve Exporter::TypeTiny documentation. - Improve advice on inlining type constraints and coercions. [ Packaging ] - Bump version of Test::More dependency fom 0.88 to 0.96. [ Other ] - Added: Bundle Type::Params, which had previously appeared on CPAN in a separate developer release. - Added: New module, Eval::TypeTiny - Added: Type::Tiny::SUPPORT_SMARTMATCH constant. - General code tidy-up. - Much of the stringy eval stuff has been factored out into Eval::TypeTiny. 0.003_09 2013-04-28 [ Documentation ] - Document usage with Params::Check and Object::Accessor. [ Other ] - Added: 'Tied' type constraint added to Types::Standard. - If Mouse is already in memory, Type::Tiny will use its super-fast XS subs to validate values when possible. 0.003_08 2013-04-26 [ Documentation ] - More Exporter::TypeTiny docs, including usage with Sub::Exporter::Lexical. [ Test Suite ] - Add test case using Exporter::TypeTiny with Sub::Exporter::Lexical. [ Other ] - ASCII-only strings are now accepted by the Chars constraint in Types::Standard. - Type::Tiny, Type::Coercion and their subclasses no longer call Types::TypeTiny->import method. - Types::TypeTiny lazily loads Exporter::TypeTiny - i.e. it loads Exporter::TypeTiny when Types::TypeTiny->import is first called. 0.003_07 2013-04-26 [ Bug Fixes ] - Fix method conflicts when exporting type constraints to roles. Kevin Dawson++ [ Documentation ] - Document usage with Class::InsideOut. - Minor improvements to manual. 0.003_06 2013-04-25 [ Documentation ] - Add lots of stuff to Type::Tiny::Manual::UsingWithMouse. - Document deep coercions (feature added in 0.003_01). [ Other ] - Add a bunch of stub methods to Type::Tiny and Type::Coercion in order to make it less necessary to inflate to Moose/Mouse meta objects. - No longer need to add '-mouse' when importing types into Mouse libraries. (Same change as what we did for Moose in 0.000_11.) - Types::TypeTiny::to_TypeTiny can now coerce from a Mouse::Meta::TypeConstraint. - Various minor changes to Exporter::TypeTiny to make it more Sub::Exporter compatible. 0.003_05 2013-04-19 [ Bug Fixes ] - Prevent warnings (about 'my $val' masking a previously declared variable) when several Str checks are being inlined in close proximity, such as Tuple[Str,Str] [ Documentation ] - Create a new manual page Type::Tiny::Manual::Coercions. - Document Exporter::TypeTiny. [ Other ] - Added: Chars and Bytes types added to Types::Standard. - Added: Encode, Decode, Join and Split coercions added to Types::Standard. - Added: Type::Tiny::Class now has a plus_constructors method. - Allow coercions to accept parameters. 0.003_04 2013-04-18 - Factor out the sub exporting code scattered around (in Type::Utils, Types::TypeTiny and Type::Library) into a single module, Exporter::TypeTiny. 0.003_03 2013-04-17 - Added: Add OptList data type to Types::Standard, plus MkOpt coercion. - Make Type::Tiny's has_coercion method more DWIM. - When inflating Moo type constraints to Moose, don't unnecessarily call 'moose_type' method. 0.003_02 2013-04-16 [ Documentation ] - Document how to process sub parameters with Type::Tiny, and point people towards Type::Params. [ Other ] - Avoid unnecessarily regenerating parameterized type constraints. 0.003_01 2013-04-16 [ Documentation ] - Link from Test::TypeTiny to Test::Deep::Type. [ Other ] - Allow a Type::Tiny object to "freeze" its coercions. This prevents a Type::Tiny object from becoming out of sync with its equivalent Mouse or Moose constraint objects. - Allow subtypes to inherit coercions from their parent type constraint. (They do not by default.) - Build coercions automatically for certain type parameterized constraints. Say there's a Num->Int coercion defined; then we should be able to coerce ArrayRef[Num]->ArrayRef[Int]. - Overload "+" operator for Type::Coercion and Type::Tiny allows coercions to be added to each other, and added to type constraints. - Type::Library packages can now include "standalone" Type::Coercion objects, not attached to a type constraint. These can be exported on request. 0.002 2013-04-26 [ Bug Fixes ] - Fix method conflicts when exporting type constraints to roles. Kevin Dawson++ - Prevent warnings (about 'my $val' masking a previously declared variable) when several Str checks are being inlined in close proximity, such as Tuple[Str,Str] [ Documentation ] - Link from Test::TypeTiny to Test::Deep::Type. [ Other ] - Added: Chars and Bytes types added to Types::Standard. - Avoid unnecessarily regenerating parameterized type constraints. - Make Type::Tiny's has_coercion method more DWIM. 0.001 2013-04-15 First public release [ Bug Fixes ] - Some inline code assumed that it would be compiled in a package that had 'blessed' imported. - Some inline code wasn't wrapped in parentheses. [ Documentation ] - Minor improvements. [ Test Suite ] - More test cases for Optional[`a] within Dict[`a]. [ Other ] - Improve test names generated by Test::TypeTiny; allow test scripts to provide test names. - Parameterized type constraints in Types::Standard now do some sanity checking on their arguments. - Weaken the reference from a Moose::Meta::TypeConstraint object to its Type::Tiny origin. 0.000_12 2013-04-12 [ Documentation ] - Fix minor typo. 0.000_11 2013-04-11 [ Bug Fixes ] - Fix prototype for Type::Utils::as. [ Other ] - No longer need to pass '-moose' parameter when importing a library into a Moose class; only Mouse needs that treatment now. 0.000_10 2013-04-09 [ Bug Fixes ] - Fix incorrect Test::Requires line in 'mouse-coercion.t'. [ Other ] - Improvements to has_coercion_for_{type,value} from Type::Coercion. 0.000_09 2013-04-08 [ Documentation ] - Bundle benchmarking scripts. - Fill in the Usage with Moose section of the fine manual. [ Packaging ] - Tidy up the 'examples' directory. [ Other ] - When generating Moose/Mouse constraints from Type::Tiny objects, prefer to generate anonymous ones. 0.000_08 2013-04-07 - Most parts of the API that accept Type::Tiny objects (e.g. Type::Utils::from()) now also accept Moose::Meta::TypeConstraint objects. - Rewrite most of the functions exported by Type::Library-based type libraries to cope better with being used mid-list. - Types::TypeTiny::to_TypeTiny can be used to coerce a Moose type constraint object to Type::Tiny. 0.000_07 2013-04-06 [ Bug Fixes ] - Fix inlining for Type::Tiny::Intersection. - Fix inlining of certain conditionals into coercion code. - Types within libraries, if accessed directly rather than exported, did not accept parameters. [ Documentation ] - Document constructor for Type::Tiny::Class. [ Test Suite ] - More test cases. [ Other ] - Added: New module Type::Coercion::Union automatically handles coercion to union types. 0.000_06 2013-04-05 [ Documentation ] - Improved documentation of parameterization attributes. - Section in manual comparing Type::Tiny with various other type library frameworks. - Using Type::Tiny with Moo added to manual. [ Test Suite ] - More test cases. [ Other ] - Added: Type::Tiny now has an 'inline_assert' function. - Footprint reduction: Type::Tiny and Type::Coercion no longer use if.pm. - Footprint reduction: Type::Tiny no longer triggers Perl to load its Unicode tables (unless you create a type constraint with a non-ASCII type name). - Footprint reduction: Type::Tiny, Type::Library and Type::Coerce no longer automatically load Types::Standard and Type::Utils. - In Moo, type assertions and coercions are now inlined. Matt S Trout++ - Monkey patch Moose::Meta::TypeConstraint to be able to retrieve Type::Tiny constraints from inflated Moose constraints. 0.000_05 2013-04-04 [ BACK COMPAT ] - Rename Type::Standard module to Types::Standard. [ Bug Fixes ] - Fix is_parameterized method. - Get Mouse coercions working. [ Test Suite ] - Factor out some functions from test suite into a new module: Test::TypeTiny. - Rearrange test suite slightly. [ Other ] - Allow null type constraints with no parent type (e.g. 'Any' in Types::Standard) to be inlined. - Don't die with full stack trace. - Sanity checks for type constraint names. - Types::TypeTiny bootstrapping library now takes care of vaious internal type checking requirements. 0.000_04 2013-04-03 - Added: Finally implement Type::Coercion's has_coercion_for_type method. - Added: Type::Tiny equals/is_subtype_of/is_supertype_of/is_a_type_of methods for type constraint comparisons. - Added: Type::Tiny plus_coercions/minus_coercions/no_coercions methods for creating subtypes with different sets of coercions. - Allow coercion code to be expressed as a string; quite a bit faster. - Create and use compiled coercions; somewhat faster. 0.000_03 2013-04-03 [ Bug Fixes ] - Fix the crashing t/moo-inflation.t test case. [ Documentation ] - Document Type::Coercion's overloading. [ Test Suite ] - Add test cases for ScalarRef[`a]. [ Other ] - All of Type::Standard cannow be inlined. - Create and use compiled type constraint checks; much faster! - Make sure Type::Standard's Moose-like built-ins get inflated to real Moose built-in types. - Use more unique stringification for %Moo::HandleMoose::TYPE_MAP keys. 0.000_02 2013-04-02 [ Bug Fixes ] - Anchor enum regexps to beginning and end of string. [ Documentation ] - Beginnings of Type::Tiny::Manual. [ Other ] - Added: StrMatch added to Type::Standard. - use Type::Library -base - use Type::Library -declare 0.000_01 2013-04-02 Developer preview INSTALL000664001750001750 165312422772210 13435 0ustar00taitai000000000000Type-Tiny-1.000005 Installing Type-Tiny should be straightforward. INSTALLATION WITH CPANMINUS If you have cpanm, you only need one line: % cpanm Type::Tiny If you are installing into a system-wide directory, you may need to pass the "-S" flag to cpanm, which uses sudo to install the module: % cpanm -S Type::Tiny INSTALLATION WITH THE CPAN SHELL Alternatively, if your CPAN shell is set up, you should just be able to do: % cpan Type::Tiny MANUAL INSTALLATION As a last resort, you can manually install it. Download the tarball and unpack it. Consult the file META.json for a list of pre-requisites. Install these first. To build Type-Tiny: % perl Makefile.PL % make && make test Then install it: % make install If you are installing into a system-wide directory, you may need to run: % sudo make install LICENSE000664001750001750 4365512422772210 13441 0ustar00taitai000000000000Type-Tiny-1.000005This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. Terms of the Perl programming language system itself a) the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version, or b) the "Artistic License" --- The GNU General Public License, Version 1, February 1989 --- This software is Copyright (c) 2014 by Toby Inkster. This is free software, licensed under: The GNU General Public License, Version 1, February 1989 GNU GENERAL PUBLIC LICENSE Version 1, February 1989 Copyright (C) 1989 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The license agreements of most software companies try to keep users at the mercy of those companies. By contrast, our General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. The General Public License applies to the Free Software Foundation's software and to any other program whose authors commit to using it. You can use it for your programs, too. When we speak of free software, we are referring to freedom, not price. Specifically, the General Public License is designed to make sure that you have the freedom to give away or sell copies of free software, that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of a such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must tell them their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any work containing the Program or a portion of it, either verbatim or with modifications. Each licensee is addressed as "you". 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this General Public License and to the absence of any warranty; and give any other recipients of the Program a copy of this General Public License along with the Program. You may charge a fee for the physical act of transferring a copy. 2. You may modify your copy or copies of the Program or any portion of it, and copy and distribute such modifications under the terms of Paragraph 1 above, provided that you also do the following: a) cause the modified files to carry prominent notices stating that you changed the files and the date of any change; and b) cause the whole of any work that you distribute or publish, that in whole or in part contains the Program or any part thereof, either with or without modifications, to be licensed at no charge to all third parties under the terms of this General Public License (except that you may choose to grant warranty protection to some or all third parties, at your option). c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the simplest and most usual way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this General Public License. d) You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. Mere aggregation of another independent work with the Program (or its derivative) on a volume of a storage or distribution medium does not bring the other work under the scope of these terms. 3. You may copy and distribute the Program (or a portion or derivative of it, under Paragraph 2) in object code or executable form under the terms of Paragraphs 1 and 2 above provided that you also do one of the following: a) accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Paragraphs 1 and 2 above; or, b) accompany it with a written offer, valid for at least three years, to give any third party free (except for a nominal charge for the cost of distribution) a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Paragraphs 1 and 2 above; or, c) accompany it with the information you received as to where the corresponding source code may be obtained. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form alone.) Source code for a work means the preferred form of the work for making modifications to it. For an executable file, complete source code means all the source code for all modules it contains; but, as a special exception, it need not include source code for modules which are standard libraries that accompany the operating system on which the executable file runs, or for standard header files or definitions files that accompany that operating system. 4. You may not copy, modify, sublicense, distribute or transfer the Program except as expressly provided under this General Public License. Any attempt otherwise to copy, modify, sublicense, distribute or transfer the Program is void, and will automatically terminate your rights to use the Program under this License. However, parties who have received copies, or rights to use copies, from you under this General Public License will not have their licenses terminated so long as such parties remain in full compliance. 5. By copying, distributing or modifying the Program (or any work based on the Program) you indicate your acceptance of this license to do so, and all its terms and conditions. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. 7. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of the license which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the license, you may choose any version ever published by the Free Software Foundation. 8. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to humanity, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19xx name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (a program to direct compilers to make passes at assemblers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice That's all there is to it! --- The Artistic License 1.0 --- This software is Copyright (c) 2014 by Toby Inkster. This is free software, licensed under: The Artistic License 1.0 The Artistic License Preamble The intent of this document is to state the conditions under which a Package may be copied, such that the Copyright Holder maintains some semblance of artistic control over the development of the package, while giving the users of the package the right to use and distribute the Package in a more-or-less customary fashion, plus the right to make reasonable modifications. Definitions: - "Package" refers to the collection of files distributed by the Copyright Holder, and derivatives of that collection of files created through textual modification. - "Standard Version" refers to such a Package if it has not been modified, or has been modified in accordance with the wishes of the Copyright Holder. - "Copyright Holder" is whoever is named in the copyright or copyrights for the package. - "You" is you, if you're thinking about copying or distributing this Package. - "Reasonable copying fee" is whatever you can justify on the basis of media cost, duplication charges, time of people involved, and so on. (You will not be required to justify it to the Copyright Holder, but only to the computing community at large as a market that must bear the fee.) - "Freely Available" means that no fee is charged for the item itself, though there may be fees involved in handling the item. It also means that recipients of the item may redistribute it under the same conditions they received it. 1. You may make and give away verbatim copies of the source form of the Standard Version of this Package without restriction, provided that you duplicate all of the original copyright notices and associated disclaimers. 2. You may apply bug fixes, portability fixes and other modifications derived from the Public Domain or from the Copyright Holder. A Package modified in such a way shall still be considered the Standard Version. 3. You may otherwise modify your copy of this Package in any way, provided that you insert a prominent notice in each changed file stating how and when you changed that file, and provided that you do at least ONE of the following: a) place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or placing the modifications on a major archive site such as ftp.uu.net, or by allowing the Copyright Holder to include your modifications in the Standard Version of the Package. b) use the modified Package only within your corporation or organization. c) rename any non-standard executables so the names do not conflict with standard executables, which must also be provided, and provide a separate manual page for each non-standard executable that clearly documents how it differs from the Standard Version. d) make other distribution arrangements with the Copyright Holder. 4. You may distribute the programs of this Package in object code or executable form, provided that you do at least ONE of the following: a) distribute a Standard Version of the executables and library files, together with instructions (in the manual page or equivalent) on where to get the Standard Version. b) accompany the distribution with the machine-readable source of the Package with your modifications. c) accompany any non-standard executables with their corresponding Standard Version executables, giving the non-standard executables non-standard names, and clearly documenting the differences in manual pages (or equivalent), together with instructions on where to get the Standard Version. d) make other distribution arrangements with the Copyright Holder. 5. You may charge a reasonable copying fee for any distribution of this Package. You may charge any fee you choose for support of this Package. You may not charge a fee for this Package itself. However, you may distribute this Package in aggregate with other (possibly commercial) programs as part of a larger (possibly commercial) software distribution provided that you do not advertise this Package as a product of your own. 6. The scripts and library files supplied as input to or produced as output from the programs of this Package do not automatically fall under the copyright of this Package, but belong to whomever generated them, and may be sold commercially, and may be aggregated with this Package. 7. C or perl subroutines supplied by you and linked into this Package shall not be considered part of this Package. 8. The name of the Copyright Holder may not be used to endorse or promote products derived from this software without specific prior written permission. 9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. The End MANIFEST000664001750001750 1556712422772317 13576 0ustar00taitai000000000000Type-Tiny-1.000005COPYRIGHT CREDITS Changes INSTALL LICENSE MANIFEST META.json META.yml Makefile.PL NEWS README SIGNATURE TODO dist.ini doap.ttl examples/benchmark-coercions.pl examples/benchmark-constraints.pl examples/benchmark-param-validation.pl examples/datetime-coercions.pl examples/versus-scalar-validation.pl inc/Test/Fatal.pm inc/Test/Requires.pm inc/Try/Tiny.pm lib/Devel/TypeTiny/Perl56Compat.pm lib/Devel/TypeTiny/Perl58Compat.pm lib/Error/TypeTiny.pm lib/Error/TypeTiny/Assertion.pm lib/Error/TypeTiny/Compilation.pm lib/Error/TypeTiny/WrongNumberOfParameters.pm lib/Eval/TypeTiny.pm lib/Reply/Plugin/TypeTiny.pm lib/Test/TypeTiny.pm lib/Type/Coercion.pm lib/Type/Coercion/FromMoose.pm lib/Type/Coercion/Union.pm lib/Type/Library.pm lib/Type/Params.pm lib/Type/Parser.pm lib/Type/Registry.pm lib/Type/Tiny.pm lib/Type/Tiny/Class.pm lib/Type/Tiny/Duck.pm lib/Type/Tiny/Enum.pm lib/Type/Tiny/Intersection.pm lib/Type/Tiny/Manual.pod lib/Type/Tiny/Manual/Coercions.pod lib/Type/Tiny/Manual/Libraries.pod lib/Type/Tiny/Manual/Optimization.pod lib/Type/Tiny/Manual/Params.pod lib/Type/Tiny/Manual/Policies.pod lib/Type/Tiny/Manual/UsingWithMoo.pod lib/Type/Tiny/Manual/UsingWithMoose.pod lib/Type/Tiny/Manual/UsingWithMouse.pod lib/Type/Tiny/Manual/UsingWithOther.pod lib/Type/Tiny/Role.pm lib/Type/Tiny/Union.pm lib/Type/Tiny/_HalfOp.pm lib/Type/Utils.pm lib/Types/Common/Numeric.pm lib/Types/Common/String.pm lib/Types/Standard.pm lib/Types/Standard/ArrayRef.pm lib/Types/Standard/Dict.pm lib/Types/Standard/HashRef.pm lib/Types/Standard/Map.pm lib/Types/Standard/ScalarRef.pm lib/Types/Standard/Tuple.pm lib/Types/TypeTiny.pm t/00-begin.t t/01-compile.t t/02-api.t t/03-leak.t t/20-unit/Devel-TypeTiny-Perl56Compat/basic.t t/20-unit/Devel-TypeTiny-Perl58Compat/basic.t t/20-unit/Error-TypeTiny-Assertion/basic.t t/20-unit/Error-TypeTiny-Compilation/basic.t t/20-unit/Error-TypeTiny-WrongNumberOfParameters/basic.t t/20-unit/Error-TypeTiny/basic.t t/20-unit/Error-TypeTiny/stacktrace.t t/20-unit/Eval-TypeTiny/basic.t t/20-unit/Eval-TypeTiny/fallback-aliases.t t/20-unit/Eval-TypeTiny/lexical-subs.t t/20-unit/Test-TypeTiny/basic.t t/20-unit/Test-TypeTiny/extended.t t/20-unit/Test-TypeTiny/matchfor.t t/20-unit/Type-Coercion-FromMoose/basic.t t/20-unit/Type-Coercion-FromMoose/errors.t t/20-unit/Type-Coercion-Union/basic.t t/20-unit/Type-Coercion/basic.t t/20-unit/Type-Coercion/esoteric.t t/20-unit/Type-Coercion/frozen.t t/20-unit/Type-Coercion/inlining.t t/20-unit/Type-Coercion/parameterized.t t/20-unit/Type-Coercion/smartmatch.t t/20-unit/Type-Coercion/typetiny-constructor.t t/20-unit/Type-Library/assert.t t/20-unit/Type-Library/errors.t t/20-unit/Type-Library/inheritance.t t/20-unit/Type-Library/is.t t/20-unit/Type-Library/to.t t/20-unit/Type-Library/types.t t/20-unit/Type-Params/badsigs.t t/20-unit/Type-Params/carping.t t/20-unit/Type-Params/coerce.t t/20-unit/Type-Params/methods.t t/20-unit/Type-Params/mixednamed.t t/20-unit/Type-Params/multisig.t t/20-unit/Type-Params/named.t t/20-unit/Type-Params/noninline.t t/20-unit/Type-Params/optional.t t/20-unit/Type-Params/positional.t t/20-unit/Type-Params/slurpy.t t/20-unit/Type-Parser/basic.t t/20-unit/Type-Parser/moosextypes.t t/20-unit/Type-Registry/automagic.t t/20-unit/Type-Registry/basic.t t/20-unit/Type-Registry/methods.t t/20-unit/Type-Registry/moosextypes.t t/20-unit/Type-Registry/mousextypes.t t/20-unit/Type-Tiny-Class/basic.t t/20-unit/Type-Tiny-Class/errors.t t/20-unit/Type-Tiny-Class/plus-constructors.t t/20-unit/Type-Tiny-Duck/basic.t t/20-unit/Type-Tiny-Duck/errors.t t/20-unit/Type-Tiny-Enum/basic.t t/20-unit/Type-Tiny-Enum/errors.t t/20-unit/Type-Tiny-Intersection/basic.t t/20-unit/Type-Tiny-Intersection/errors.t t/20-unit/Type-Tiny-Role/basic.t t/20-unit/Type-Tiny-Role/errors.t t/20-unit/Type-Tiny-Union/basic.t t/20-unit/Type-Tiny-Union/errors.t t/20-unit/Type-Tiny-_HalfOp/overload-precedence.t t/20-unit/Type-Tiny/arithmetic.t t/20-unit/Type-Tiny/basic.t t/20-unit/Type-Tiny/coercion-modifiers.t t/20-unit/Type-Tiny/esoteric.t t/20-unit/Type-Tiny/my-methods.t t/20-unit/Type-Tiny/parameterization.t t/20-unit/Type-Tiny/shortcuts.t t/20-unit/Type-Tiny/smartmatch.t t/20-unit/Type-Tiny/syntax.t t/20-unit/Type-Tiny/to-moose.t t/20-unit/Type-Tiny/to-mouse.t t/20-unit/Type-Utils/classifier.t t/20-unit/Type-Utils/dwim-both.t t/20-unit/Type-Utils/dwim-moose.t t/20-unit/Type-Utils/dwim-mouse.t t/20-unit/Type-Utils/match-on-type.t t/20-unit/Type-Utils/warnings.t t/20-unit/Types-Common-Numeric/basic.t t/20-unit/Types-Common-String/basic.t t/20-unit/Types-Common-String/coerce.t t/20-unit/Types-Common-String/unicode.t t/20-unit/Types-Standard/basic.t t/20-unit/Types-Standard/deep-coercions.t t/20-unit/Types-Standard/lockdown.t t/20-unit/Types-Standard/mxtmlb-alike.t t/20-unit/Types-Standard/optlist.t t/20-unit/Types-Standard/overload.t t/20-unit/Types-Standard/strmatch.t t/20-unit/Types-Standard/structured.t t/20-unit/Types-Standard/tied.t t/20-unit/Types-TypeTiny/basic.t t/20-unit/Types-TypeTiny/coercion.t t/20-unit/Types-TypeTiny/meta.t t/30-integration/Class-InsideOut/basic.t t/30-integration/Exporter-Tiny/basic.t t/30-integration/Exporter-Tiny/installer.t t/30-integration/Exporter-Tiny/role-conflict.t t/30-integration/Function-Parameters/basic.t t/30-integration/Kavorka/basic.t t/30-integration/Moo/basic.t t/30-integration/Moo/coercion-inlining-avoidance.t t/30-integration/Moo/coercion.t t/30-integration/Moo/exceptions.t t/30-integration/Moo/inflation.t t/30-integration/Moo/inflation2.t t/30-integration/Moops/basic.t t/30-integration/Moops/library-keyword.t t/30-integration/Moose/accept-moose-types.t t/30-integration/Moose/basic.t t/30-integration/Moose/coercion.t t/30-integration/Moose/inflate-then-inline.t t/30-integration/Moose/native-attribute-traits.t t/30-integration/MooseX-Getopt/coercion.t t/30-integration/MooseX-Types/basic.t t/30-integration/MooseX-Types/extending.t t/30-integration/MooseX-Types/more.t t/30-integration/Mouse/basic.t t/30-integration/Mouse/coercion.t t/30-integration/MouseX-Types/basic.t t/30-integration/MouseX-Types/extending.t t/30-integration/Object-Accessor/basic.t t/30-integration/Return-Type/basic.t t/30-integration/Sub-Quote/basic.t t/30-integration/Sub-Quote/unquote-coercions.t t/30-integration/Sub-Quote/unquote-constraints.t t/30-integration/Switcheroo/basic.t t/30-integration/Type-Tie/basic.t t/30-integration/Validation-Class-Simple/archaic.t t/30-integration/Validation-Class-Simple/basic.t t/30-integration/match-simple/basic.t t/40-regression/73f51e2d.pl t/40-regression/73f51e2d.t t/40-regression/gh1.t t/40-regression/rt85911.t t/40-regression/rt86004.t t/40-regression/rt86233.t t/40-regression/rt86239.t t/40-regression/rt90096-2.t t/40-regression/rt90096.t t/40-regression/rt92571-2.t t/40-regression/rt92571.t t/40-regression/rt92591.t t/40-regression/rt94196.t t/40-regression/rt97684.t t/40-regression/rt98113.t t/40-regression/ttxs-gh1.t t/99-moose-std-types-test.t t/README t/TODO t/lib/BiggerLib.pm t/lib/DemoLib.pm t/mk-test-manifest.pl t/not-covered.pl META.json000664001750001750 1653712422772317 14064 0ustar00taitai000000000000Type-Tiny-1.000005{ "abstract" : "tiny, yet Moo(se)-compatible type constraint", "author" : [ "Toby Inkster (TOBYINK) " ], "dynamic_config" : 1, "generated_by" : "Dist::Inkt::Profile::TOBYINK version 0.023, CPAN::Meta::Converter version 2.142690", "keywords" : [ "Argument Checking", "Argument Validation", "Moo", "Moose", "Mouse", "Parameter Checking", "Parameter Validation", "Schema", "Type Coercion", "Type Constraint", "Type Library", "Validation" ], "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "Type-Tiny", "no_index" : { "directory" : [ "eg", "examples", "inc", "t", "xt" ] }, "optional_features" : {}, "prereqs" : { "configure" : { "recommends" : { "CPAN::Meta::Requirements" : "2.000" }, "requires" : { "ExtUtils::MakeMaker" : "6.17" } }, "develop" : { "suggests" : { "Dist::Inkt::Profile::TOBYINK" : "0" } }, "runtime" : { "conflicts" : { "Kavorka" : "<= 0.013", "Types::ReadOnly" : "<= 0.001" }, "recommends" : { "Devel::LexAlias" : "0.05", "Devel::StackTrace" : "0", "Sub::Name" : "0", "Type::Tie" : "0", "Type::Tiny::XS" : "0.010", "perl" : "5.010001" }, "requires" : { "Exporter::Tiny" : "0.026", "perl" : "5.006001" }, "suggests" : { "Moo" : "1.000000", "Moose" : "2.0400", "Mouse" : "1.00", "Reply" : "0" } }, "test" : { "recommends" : { "Test::Tester" : "0.109", "Test::Warnings" : "0" }, "requires" : { "Test::More" : "0.96" } } }, "provides" : { "Devel::TypeTiny::Perl56Compat" : { "file" : "lib/Devel/TypeTiny/Perl56Compat.pm", "version" : "1.000005" }, "Devel::TypeTiny::Perl58Compat" : { "file" : "lib/Devel/TypeTiny/Perl58Compat.pm", "version" : "1.000005" }, "Error::TypeTiny" : { "file" : "lib/Error/TypeTiny.pm", "version" : "1.000005" }, "Error::TypeTiny::Assertion" : { "file" : "lib/Error/TypeTiny/Assertion.pm", "version" : "1.000005" }, "Error::TypeTiny::Compilation" : { "file" : "lib/Error/TypeTiny/Compilation.pm", "version" : "1.000005" }, "Error::TypeTiny::WrongNumberOfParameters" : { "file" : "lib/Error/TypeTiny/WrongNumberOfParameters.pm", "version" : "1.000005" }, "Eval::TypeTiny" : { "file" : "lib/Eval/TypeTiny.pm", "version" : "1.000005" }, "Reply::Plugin::TypeTiny" : { "file" : "lib/Reply/Plugin/TypeTiny.pm", "version" : "1.000005" }, "Test::TypeTiny" : { "file" : "lib/Test/TypeTiny.pm", "version" : "1.000005" }, "Type::Coercion" : { "file" : "lib/Type/Coercion.pm", "version" : "1.000005" }, "Type::Coercion::FromMoose" : { "file" : "lib/Type/Coercion/FromMoose.pm", "version" : "1.000005" }, "Type::Coercion::Union" : { "file" : "lib/Type/Coercion/Union.pm", "version" : "1.000005" }, "Type::Library" : { "file" : "lib/Type/Library.pm", "version" : "1.000005" }, "Type::Params" : { "file" : "lib/Type/Params.pm", "version" : "1.000005" }, "Type::Parser" : { "file" : "lib/Type/Parser.pm", "version" : "1.000005" }, "Type::Registry" : { "file" : "lib/Type/Registry.pm", "version" : "1.000005" }, "Type::Tiny" : { "file" : "lib/Type/Tiny.pm", "version" : "1.000005" }, "Type::Tiny::Class" : { "file" : "lib/Type/Tiny/Class.pm", "version" : "1.000005" }, "Type::Tiny::Duck" : { "file" : "lib/Type/Tiny/Duck.pm", "version" : "1.000005" }, "Type::Tiny::Enum" : { "file" : "lib/Type/Tiny/Enum.pm", "version" : "1.000005" }, "Type::Tiny::Intersection" : { "file" : "lib/Type/Tiny/Intersection.pm", "version" : "1.000005" }, "Type::Tiny::Role" : { "file" : "lib/Type/Tiny/Role.pm", "version" : "1.000005" }, "Type::Tiny::Union" : { "file" : "lib/Type/Tiny/Union.pm", "version" : "1.000005" }, "Type::Utils" : { "file" : "lib/Type/Utils.pm", "version" : "1.000005" }, "Types::Common::Numeric" : { "file" : "lib/Types/Common/Numeric.pm", "version" : "1.000005" }, "Types::Common::String" : { "file" : "lib/Types/Common/String.pm", "version" : "1.000005" }, "Types::Standard" : { "file" : "lib/Types/Standard.pm", "version" : "1.000005" }, "Types::Standard::ArrayRef" : { "file" : "lib/Types/Standard/ArrayRef.pm", "version" : "1.000005" }, "Types::Standard::Dict" : { "file" : "lib/Types/Standard/Dict.pm", "version" : "1.000005" }, "Types::Standard::HashRef" : { "file" : "lib/Types/Standard/HashRef.pm", "version" : "1.000005" }, "Types::Standard::Map" : { "file" : "lib/Types/Standard/Map.pm", "version" : "1.000005" }, "Types::Standard::ScalarRef" : { "file" : "lib/Types/Standard/ScalarRef.pm", "version" : "1.000005" }, "Types::Standard::Tuple" : { "file" : "lib/Types/Standard/Tuple.pm", "version" : "1.000005" }, "Types::TypeTiny" : { "file" : "lib/Types/TypeTiny.pm", "version" : "1.000005" } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny" }, "homepage" : "https://metacpan.org/release/Type-Tiny", "license" : [ "http://dev.perl.org/licenses/" ], "repository" : { "type" : "git", "url" : "git://github.com/tobyink/p5-type-tiny.git", "web" : "https://github.com/tobyink/p5-type-tiny" }, "x_identifier" : "http://purl.org/NET/cpan-uri/dist/Type-Tiny/project" }, "version" : "1.000005", "x_breaks" : { "Kavorka" : "<= 0.013", "Types::ReadOnly" : "<= 0.001" }, "x_contributors" : [ "Diab Jerius (DJERIUS) ", "Vyacheslav Matyukhin (MMCLERIC) ", "Peter Flanigan (PJFL) ", "Pierre Masci", "Mark Stosberg (MARKSTOS) ", "David Steinbrunner ", "Samuel Kaufman (SKAUFMAN) ", "Graham Knop (HAARG) ", "Peter Karman (KARMAN) ", "Alexander Hartmaier (ABRAXXA) ", "Dagfinn Ilmari Mannsåker (ILMARI) ", "Gianni Ceccarelli (DAKKAR) " ] } META.yml000664001750001750 1135312422772317 13703 0ustar00taitai000000000000Type-Tiny-1.000005--- abstract: 'tiny, yet Moo(se)-compatible type constraint' author: - 'Toby Inkster (TOBYINK) ' build_requires: Test::More: '0.96' configure_requires: ExtUtils::MakeMaker: '6.17' conflicts: Kavorka: '<= 0.013' Types::ReadOnly: '<= 0.001' dynamic_config: 1 generated_by: 'Dist::Inkt::Profile::TOBYINK version 0.023, CPAN::Meta::Converter version 2.142690' keywords: - 'Argument Checking' - 'Argument Validation' - Moo - Moose - Mouse - 'Parameter Checking' - 'Parameter Validation' - Schema - 'Type Coercion' - 'Type Constraint' - 'Type Library' - Validation license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: Type-Tiny no_index: directory: - eg - examples - inc - t - xt optional_features: {} provides: Devel::TypeTiny::Perl56Compat: file: lib/Devel/TypeTiny/Perl56Compat.pm version: '1.000005' Devel::TypeTiny::Perl58Compat: file: lib/Devel/TypeTiny/Perl58Compat.pm version: '1.000005' Error::TypeTiny: file: lib/Error/TypeTiny.pm version: '1.000005' Error::TypeTiny::Assertion: file: lib/Error/TypeTiny/Assertion.pm version: '1.000005' Error::TypeTiny::Compilation: file: lib/Error/TypeTiny/Compilation.pm version: '1.000005' Error::TypeTiny::WrongNumberOfParameters: file: lib/Error/TypeTiny/WrongNumberOfParameters.pm version: '1.000005' Eval::TypeTiny: file: lib/Eval/TypeTiny.pm version: '1.000005' Reply::Plugin::TypeTiny: file: lib/Reply/Plugin/TypeTiny.pm version: '1.000005' Test::TypeTiny: file: lib/Test/TypeTiny.pm version: '1.000005' Type::Coercion: file: lib/Type/Coercion.pm version: '1.000005' Type::Coercion::FromMoose: file: lib/Type/Coercion/FromMoose.pm version: '1.000005' Type::Coercion::Union: file: lib/Type/Coercion/Union.pm version: '1.000005' Type::Library: file: lib/Type/Library.pm version: '1.000005' Type::Params: file: lib/Type/Params.pm version: '1.000005' Type::Parser: file: lib/Type/Parser.pm version: '1.000005' Type::Registry: file: lib/Type/Registry.pm version: '1.000005' Type::Tiny: file: lib/Type/Tiny.pm version: '1.000005' Type::Tiny::Class: file: lib/Type/Tiny/Class.pm version: '1.000005' Type::Tiny::Duck: file: lib/Type/Tiny/Duck.pm version: '1.000005' Type::Tiny::Enum: file: lib/Type/Tiny/Enum.pm version: '1.000005' Type::Tiny::Intersection: file: lib/Type/Tiny/Intersection.pm version: '1.000005' Type::Tiny::Role: file: lib/Type/Tiny/Role.pm version: '1.000005' Type::Tiny::Union: file: lib/Type/Tiny/Union.pm version: '1.000005' Type::Utils: file: lib/Type/Utils.pm version: '1.000005' Types::Common::Numeric: file: lib/Types/Common/Numeric.pm version: '1.000005' Types::Common::String: file: lib/Types/Common/String.pm version: '1.000005' Types::Standard: file: lib/Types/Standard.pm version: '1.000005' Types::Standard::ArrayRef: file: lib/Types/Standard/ArrayRef.pm version: '1.000005' Types::Standard::Dict: file: lib/Types/Standard/Dict.pm version: '1.000005' Types::Standard::HashRef: file: lib/Types/Standard/HashRef.pm version: '1.000005' Types::Standard::Map: file: lib/Types/Standard/Map.pm version: '1.000005' Types::Standard::ScalarRef: file: lib/Types/Standard/ScalarRef.pm version: '1.000005' Types::Standard::Tuple: file: lib/Types/Standard/Tuple.pm version: '1.000005' Types::TypeTiny: file: lib/Types/TypeTiny.pm version: '1.000005' recommends: Devel::LexAlias: '0.05' Devel::StackTrace: '0' Sub::Name: '0' Type::Tie: '0' Type::Tiny::XS: '0.010' perl: '5.010001' requires: Exporter::Tiny: '0.026' perl: '5.006001' resources: Identifier: http://purl.org/NET/cpan-uri/dist/Type-Tiny/project bugtracker: http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny homepage: https://metacpan.org/release/Type-Tiny license: http://dev.perl.org/licenses/ repository: git://github.com/tobyink/p5-type-tiny.git version: '1.000005' x_breaks: Kavorka: '<= 0.013' Types::ReadOnly: '<= 0.001' x_contributors: - 'Diab Jerius (DJERIUS) ' - 'Vyacheslav Matyukhin (MMCLERIC) ' - 'Peter Flanigan (PJFL) ' - 'Pierre Masci' - 'Mark Stosberg (MARKSTOS) ' - 'David Steinbrunner ' - 'Samuel Kaufman (SKAUFMAN) ' - 'Graham Knop (HAARG) ' - 'Peter Karman (KARMAN) ' - 'Alexander Hartmaier (ABRAXXA) ' - 'Dagfinn Ilmari Mannsåker (ILMARI) ' - 'Gianni Ceccarelli (DAKKAR) ' Makefile.PL000664001750001750 3513312422772317 14406 0ustar00taitai000000000000Type-Tiny-1.000005use strict; use ExtUtils::MakeMaker 6.17; my $EUMM = eval( $ExtUtils::MakeMaker::VERSION ); my $meta = { "abstract" => "tiny, yet Moo(se)-compatible type constraint", "author" => ["Toby Inkster (TOBYINK) "], "dynamic_config" => 1, "generated_by" => "Dist::Inkt::Profile::TOBYINK version 0.023, CPAN::Meta::Converter version 2.142690", "keywords" => [ "Argument Checking", "Argument Validation", "Moo", "Moose", "Mouse", "Parameter Checking", "Parameter Validation", "Schema", "Type Coercion", "Type Constraint", "Type Library", "Validation", ], "license" => ["perl_5"], "meta-spec" => { url => "http://search.cpan.org/perldoc?CPAN::Meta::Spec", version => 2, }, "name" => "Type-Tiny", "no_index" => { directory => ["eg", "examples", "inc", "t", "xt"] }, "prereqs" => { configure => { recommends => { "CPAN::Meta::Requirements" => "2.000" }, requires => { "ExtUtils::MakeMaker" => 6.17 }, }, develop => { suggests => { "Dist::Inkt::Profile::TOBYINK" => 0 } }, runtime => { conflicts => { "Kavorka" => "<= 0.013", "Types::ReadOnly" => "<= 0.001" }, recommends => { "Devel::LexAlias" => 0.05, "Devel::StackTrace" => 0, "perl" => 5.010001, "Sub::Name" => 0, "Type::Tie" => 0, "Type::Tiny::XS" => "0.010", }, requires => { "Exporter::Tiny" => 0.026, "perl" => 5.006001 }, suggests => { Moo => "1.000000", Moose => "2.0400", Mouse => "1.00", Reply => 0 }, }, test => { recommends => { "Test::Tester" => 0.109, "Test::Warnings" => 0 }, requires => { "Test::More" => 0.96 }, }, }, "provides" => { "Devel::TypeTiny::Perl56Compat" => { file => "lib/Devel/TypeTiny/Perl56Compat.pm", version => 1.000005 }, "Devel::TypeTiny::Perl58Compat" => { file => "lib/Devel/TypeTiny/Perl58Compat.pm", version => 1.000005 }, "Error::TypeTiny" => { file => "lib/Error/TypeTiny.pm", version => 1.000005 }, "Error::TypeTiny::Assertion" => { file => "lib/Error/TypeTiny/Assertion.pm", version => 1.000005 }, "Error::TypeTiny::Compilation" => { file => "lib/Error/TypeTiny/Compilation.pm", version => 1.000005 }, "Error::TypeTiny::WrongNumberOfParameters" => { file => "lib/Error/TypeTiny/WrongNumberOfParameters.pm", version => 1.000005, }, "Eval::TypeTiny" => { file => "lib/Eval/TypeTiny.pm", version => 1.000005 }, "Reply::Plugin::TypeTiny" => { file => "lib/Reply/Plugin/TypeTiny.pm", version => 1.000005 }, "Test::TypeTiny" => { file => "lib/Test/TypeTiny.pm", version => 1.000005 }, "Type::Coercion" => { file => "lib/Type/Coercion.pm", version => 1.000005 }, "Type::Coercion::FromMoose" => { file => "lib/Type/Coercion/FromMoose.pm", version => 1.000005 }, "Type::Coercion::Union" => { file => "lib/Type/Coercion/Union.pm", version => 1.000005 }, "Type::Library" => { file => "lib/Type/Library.pm", version => 1.000005 }, "Type::Params" => { file => "lib/Type/Params.pm", version => 1.000005 }, "Type::Parser" => { file => "lib/Type/Parser.pm", version => 1.000005 }, "Type::Registry" => { file => "lib/Type/Registry.pm", version => 1.000005 }, "Type::Tiny" => { file => "lib/Type/Tiny.pm", version => 1.000005 }, "Type::Tiny::Class" => { file => "lib/Type/Tiny/Class.pm", version => 1.000005 }, "Type::Tiny::Duck" => { file => "lib/Type/Tiny/Duck.pm", version => 1.000005 }, "Type::Tiny::Enum" => { file => "lib/Type/Tiny/Enum.pm", version => 1.000005 }, "Type::Tiny::Intersection" => { file => "lib/Type/Tiny/Intersection.pm", version => 1.000005 }, "Type::Tiny::Role" => { file => "lib/Type/Tiny/Role.pm", version => 1.000005 }, "Type::Tiny::Union" => { file => "lib/Type/Tiny/Union.pm", version => 1.000005 }, "Type::Utils" => { file => "lib/Type/Utils.pm", version => 1.000005 }, "Types::Common::Numeric" => { file => "lib/Types/Common/Numeric.pm", version => 1.000005 }, "Types::Common::String" => { file => "lib/Types/Common/String.pm", version => 1.000005 }, "Types::Standard" => { file => "lib/Types/Standard.pm", version => 1.000005 }, "Types::Standard::ArrayRef" => { file => "lib/Types/Standard/ArrayRef.pm", version => 1.000005 }, "Types::Standard::Dict" => { file => "lib/Types/Standard/Dict.pm", version => 1.000005 }, "Types::Standard::HashRef" => { file => "lib/Types/Standard/HashRef.pm", version => 1.000005 }, "Types::Standard::Map" => { file => "lib/Types/Standard/Map.pm", version => 1.000005 }, "Types::Standard::ScalarRef" => { file => "lib/Types/Standard/ScalarRef.pm", version => 1.000005 }, "Types::Standard::Tuple" => { file => "lib/Types/Standard/Tuple.pm", version => 1.000005 }, "Types::TypeTiny" => { file => "lib/Types/TypeTiny.pm", version => 1.000005 }, }, "release_status" => "stable", "resources" => { bugtracker => { web => "http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny" }, homepage => "https://metacpan.org/release/Type-Tiny", license => ["http://dev.perl.org/licenses/"], repository => { type => "git", url => "git://github.com/tobyink/p5-type-tiny.git", web => "https://github.com/tobyink/p5-type-tiny", }, x_identifier => "http://purl.org/NET/cpan-uri/dist/Type-Tiny/project", }, "version" => 1.000005, "x_breaks" => { "Kavorka" => "<= 0.013", "Types::ReadOnly" => "<= 0.001" }, "x_contributors" => [ "Diab Jerius (DJERIUS) ", "Vyacheslav Matyukhin (MMCLERIC) ", "Peter Flanigan (PJFL) ", "Pierre Masci", "Mark Stosberg (MARKSTOS) ", "David Steinbrunner ", "Samuel Kaufman (SKAUFMAN) ", "Graham Knop (HAARG) ", "Peter Karman (KARMAN) ", "Alexander Hartmaier (ABRAXXA) ", "Dagfinn Ilmari Manns\xE5ker (ILMARI) ", "Gianni Ceccarelli (DAKKAR) ", ], }; my %dynamic_config; do { $meta->{prereqs}{runtime}{requires}{'Scalar::Util'} = '1.13' if $] < 5.007003; $meta->{prereqs}{runtime}{requires}{'Data::Dumper'} = '1.121' if $] < 5.008001; $meta->{prereqs}{runtime}{requires}{'Text::Balanced'} = '1.95' if $] < 5.007003; $meta->{prereqs}{runtime}{requires}{'Exporter'} = '5.57' if $] < 5.009001; if ($ENV{EXTENDED_TESTING} and $meta->{version} =~ /_/) { $meta->{prereqs}{test}{requires}{'Moose'} = '2.0600'; } }; for my $stage (keys %{$meta->{prereqs}}) { my $conflicts = $meta->{prereqs}{$stage}{conflicts} or next; eval { require CPAN::Meta::Requirements } or last; $conflicts = 'CPAN::Meta::Requirements'->from_string_hash($conflicts); for my $module ($conflicts->required_modules) { eval "require $module" or next; my $installed = eval(sprintf('$%s::VERSION', $module)); $conflicts->accepts_module($module, $installed) or next; my $message = "\n". "** This version of $meta->{name} conflicts with the version of\n". "** module $module ($installed) you have installed.\n"; die($message . "\n" . "Bailing out") if $stage eq 'build' || $stage eq 'configure'; $message .= "**\n". "** It's strongly recommended that you update it after\n". "** installing this version of $meta->{name}.\n"; warn("$message\n"); } } my %WriteMakefileArgs = ( ABSTRACT => $meta->{abstract}, AUTHOR => ($EUMM >= 6.5702 ? $meta->{author} : $meta->{author}[0]), DISTNAME => $meta->{name}, VERSION => $meta->{version}, EXE_FILES => [ map $_->{file}, values %{ $meta->{x_provides_scripts} || {} } ], NAME => do { my $n = $meta->{name}; $n =~ s/-/::/g; $n }, test => { TESTS => "t/*.t t/20-unit/Devel-TypeTiny-Perl56Compat/*.t t/20-unit/Devel-TypeTiny-Perl58Compat/*.t t/20-unit/Error-TypeTiny-Assertion/*.t t/20-unit/Error-TypeTiny-Compilation/*.t t/20-unit/Error-TypeTiny-WrongNumberOfParameters/*.t t/20-unit/Error-TypeTiny/*.t t/20-unit/Eval-TypeTiny/*.t t/20-unit/Test-TypeTiny/*.t t/20-unit/Type-Coercion-FromMoose/*.t t/20-unit/Type-Coercion-Union/*.t t/20-unit/Type-Coercion/*.t t/20-unit/Type-Library/*.t t/20-unit/Type-Params/*.t t/20-unit/Type-Parser/*.t t/20-unit/Type-Registry/*.t t/20-unit/Type-Tiny-Class/*.t t/20-unit/Type-Tiny-Duck/*.t t/20-unit/Type-Tiny-Enum/*.t t/20-unit/Type-Tiny-Intersection/*.t t/20-unit/Type-Tiny-Role/*.t t/20-unit/Type-Tiny-Union/*.t t/20-unit/Type-Tiny-_HalfOp/*.t t/20-unit/Type-Tiny/*.t t/20-unit/Type-Utils/*.t t/20-unit/Types-Common-Numeric/*.t t/20-unit/Types-Common-String/*.t t/20-unit/Types-Standard/*.t t/20-unit/Types-TypeTiny/*.t t/30-integration/Class-InsideOut/*.t t/30-integration/Exporter-Tiny/*.t t/30-integration/Function-Parameters/*.t t/30-integration/Kavorka/*.t t/30-integration/Moo/*.t t/30-integration/Moops/*.t t/30-integration/Moose/*.t t/30-integration/MooseX-Getopt/*.t t/30-integration/MooseX-Types/*.t t/30-integration/Mouse/*.t t/30-integration/MouseX-Types/*.t t/30-integration/Object-Accessor/*.t t/30-integration/Return-Type/*.t t/30-integration/Sub-Quote/*.t t/30-integration/Switcheroo/*.t t/30-integration/Type-Tie/*.t t/30-integration/Validation-Class-Simple/*.t t/30-integration/match-simple/*.t t/40-regression/*.t" }, %dynamic_config, ); $WriteMakefileArgs{LICENSE} = $meta->{license}[0] if $EUMM >= 6.3001; sub deps { my %r; for my $stage (@_) { for my $dep (keys %{$meta->{prereqs}{$stage}{requires}}) { next if $dep eq 'perl'; my $ver = $meta->{prereqs}{$stage}{requires}{$dep}; $r{$dep} = $ver if !exists($r{$dep}) || $ver >= $r{$dep}; } } \%r; } my ($build_requires, $configure_requires, $runtime_requires, $test_requires); if ($EUMM >= 6.6303) { $WriteMakefileArgs{BUILD_REQUIRES} ||= deps('build'); $WriteMakefileArgs{CONFIGURE_REQUIRES} ||= deps('configure'); $WriteMakefileArgs{TEST_REQUIRES} ||= deps('test'); $WriteMakefileArgs{PREREQ_PM} ||= deps('runtime'); } elsif ($EUMM >= 6.5503) { $WriteMakefileArgs{BUILD_REQUIRES} ||= deps('build', 'test'); $WriteMakefileArgs{CONFIGURE_REQUIRES} ||= deps('configure'); $WriteMakefileArgs{PREREQ_PM} ||= deps('runtime'); } elsif ($EUMM >= 6.52) { $WriteMakefileArgs{CONFIGURE_REQUIRES} ||= deps('configure'); $WriteMakefileArgs{PREREQ_PM} ||= deps('runtime', 'build', 'test'); } else { $WriteMakefileArgs{PREREQ_PM} ||= deps('configure', 'build', 'test', 'runtime'); } { my ($minperl) = reverse sort( grep defined && /^[0-9]+(\.[0-9]+)?$/, map $meta->{prereqs}{$_}{requires}{perl}, qw( configure build runtime ) ); if (defined($minperl)) { die "Installing $meta->{name} requires Perl >= $minperl" unless $] >= $minperl; $WriteMakefileArgs{MIN_PERL_VERSION} ||= $minperl if $EUMM >= 6.48; } } sub FixMakefile { return unless -d 'inc'; my $file = shift; local *MAKEFILE; open MAKEFILE, "< $file" or die "FixMakefile: Couldn't open $file: $!; bailing out"; my $makefile = do { local $/; }; close MAKEFILE or die $!; $makefile =~ s/\b(test_harness\(\$\(TEST_VERBOSE\), )/$1'inc', /; $makefile =~ s/( -I\$\(INST_ARCHLIB\))/ -Iinc$1/g; $makefile =~ s/( "-I\$\(INST_LIB\)")/ "-Iinc"$1/g; $makefile =~ s/^(FULLPERL = .*)/$1 "-Iinc"/m; $makefile =~ s/^(PERL = .*)/$1 "-Iinc"/m; open MAKEFILE, "> $file" or die "FixMakefile: Couldn't open $file: $!; bailing out"; print MAKEFILE $makefile or die $!; close MAKEFILE or die $!; } my $mm = WriteMakefile(%WriteMakefileArgs); FixMakefile($mm->{FIRST_MAKEFILE} || 'Makefile'); exit(0); NEWS000664001750001750 261212422772210 13077 0ustar00taitai000000000000Type-Tiny-1.000005======================================================================= This file contains a high-level summary of changes between recent stable releases of Type-Tiny. For a more detailed list, including changes in development releases, see the "Changes" file instead. ======================================================================= 2014-03-17 Type-Tiny version 0.040 released! - Deprecated module Exporter::TypeTiny is now gone. - Restructure and expand test suite. - Coercion bugfixes. - Improvements to overloaded operations on parameterized types. - Fix problems with threaded Perl 5.18.x. 2014-04-02 Type-Tiny version 0.042 released! - One year since Type-Tiny 0.000_01 was uploaded to CPAN. - No more overloaded addition operator on Type::Tiny/Type::Coercion. 2014-06-03 Type-Tiny version 0.044 released! - Lots of bugfixes, tests, and documentation improvements. 2014-07-18 Type-Tiny version 0.046 released! - Support for Type::Tiny::XS. - Test case improvements. 2014-08-16 Type-Tiny version 1.000000 released! - Enhanced support for Type::Tiny::XS. - More test case improvements. - Saner implementations of slurpy and Optional within Tuples and Dicts. - More aggressive at freezing coercions. - Better behaviour of non-frozen coercions. (For example, they are no longer considered to be inlineable.) - Better integration between Type::Library and Type::Registry. README000664001750001750 1356512422772210 13311 0ustar00taitai000000000000Type-Tiny-1.000005NAME Type::Tiny::Manual - an overview of Type::Tiny SYNOPSIS Type::Tiny is a small class for writing type constraints, inspired by Moose's type constraint API. It has only one non-core dependency (and even that is simply a module that was previously distributed as part of Type::Tiny but has since been spun off), and can be used with Moose, Mouse and Moo (or none of the above). Type::Tiny is bundled with Type::Library a framework for organizing type constraints into collections. Also bundled is Types::Standard, a Moose-inspired library of useful type constraints. Type::Params is also provided, to allow very fast checking and coercion of function and method parameters. SEE ALSO * Libraries - how to build a type library with Type::Tiny, Type::Library and Type::Utils * Coercions - adding coercions to type constraints * Using with Moose - how to use Type::Tiny and Type::Library with Moose * Using with Mouse - how to use Type::Tiny and Type::Library with Mouse * Using with Moo - how to use Type::Tiny and Type::Library with Moo * Using with Other OO Frameworks - how to use Type::Tiny and Type::Library with other OO frameworks * Type::Tiny and friends don't need to be used within an OO framework. See FreeMind::Node for an example that does not. * Processing arguments to subs - coerce and validate arguments to functions and methods. * Other modules using Type::Tiny in interesting ways: Type::Tie, Test::Mocha, Scalar::Does, Set::Equivalence... * Optimization - squeeze the most out of your CPU. * Type::Tiny maintenance policies - the stability policy. DEPENDENCIES Type::Tiny requires at least Perl 5.6.1, though certain Unicode-related features (e.g. non-ASCII type constraint names) may work better in newer versions of Perl. Type::Tiny requires Exporter::Tiny, a module that was previously bundled in this distribution, but has since been spun off as a separate distribution. Don't worry - it's quick and easy to install. At run-time, Type::Tiny also requires the following modules: B, B::Deparse, Carp, Data::Dumper, Scalar::Util, Text::Balanced, overload, strict and warnings. All of these come bundled with Perl itself. Prior to Perl 5.8, Scalar::Util and Text::Balanced do not come bundled with Perl and will need installing separately from the CPAN. Certain features require additional modules. Tying a variable to a type constraint (e.g. `tie my $count, Int`) requires Type::Tie; stack traces on exceptions require Devel::StackTrace. The Reply::Plugin::TypeTiny plugin for Reply requires Reply (obviously). Devel::LexAlias may *slightly* increase the speed of some of Type::Tiny's compiled coderefs. Type::Tiny::XS is not required, but if available provides a speed boost for some type checks. (Setting the environment variable `PERL_TYPE_TINY_XS` to false, or setting `PERL_ONLY` to true will suppress the use of Type::Tiny::XS, even if it is available.) The test suite additionally requires Test::More, Test::Fatal and Test::Requires. Test::More comes bundled with Perl, but if you are using a version of Perl older than 5.14, you will need to upgrade to at least Test::More version 0.96. Test::Requires and Test::Fatal (plus Try::Tiny which Test::Fatal depends on) are bundled with Type::Tiny in the `inc` directory, so you do not need to install them separately. If using Type::Tiny in conjunction with Moo, then at least Moo 1.001000 is recommended. If using Type::Tiny with Moose, then at least Moose 2.0600 is recommended. If using Type::Tiny with Mouse, then at least Mouse 1.00 is recommended. Type::Tiny is mostly untested against older versions of these packages. TYPE::TINY VERSUS X Specio Type::Tiny is similar in aim to Specio. The major differences are * Type::Tiny is "tiny" (Specio will eventually have fewer dependencies than it currently does, but is unlikely to ever have as few as Type::Tiny); * Specio has a somewhat nicer API (better method names; less duplication), and its API is likely to improve further. Type::Tiny's aims at complete compatibility with current versions of Moose and Mouse, so there is a limit to how much I can deviate from the existing APIs of (Moose|Mouse)::Meta::TypeConstraint. MooseX::Types Type::Tiny libraries expose a similar interface to MooseX::Types libraries. In most cases you should be able to rewrite a MooseX::Types library to use Type::Tiny pretty easily. MooX::Types::MooseLike Type::Tiny is faster and supports coercions. Scalar::Does Scalar::Does is somewhat of a precursor to Type::Tiny, but has now been rewritten to use Type::Tiny internally. It gives you a `does($value, $type)` function that is roughly equivalent to `$type->check($value)` except that $type may be one of a list of pre-defined strings (instead of a Type::Tiny type constraint); or may be a package name in which case it will be assumed to be a role and checked with `$value->DOES($type)`. BUGS Please report any bugs to . SUPPORT IRC: support is available through in the *#moops* channel on irc.perl.org . AUTHOR Toby Inkster . COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. SIGNATURE000664001750001750 4324612422772317 13724 0ustar00taitai000000000000Type-Tiny-1.000005This file contains message digests of all files listed in MANIFEST, signed via the Module::Signature module, version 0.73. To verify the content in this distribution, first make sure you have Module::Signature installed, then type: % cpansign -v It will check each file's integrity, as well as the signature's validity. If "==> Signature verified OK! <==" is not displayed, the distribution may already have been compromised, and you should not run its Makefile.PL or Build.PL. -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 SHA1 f2f783878895905728904e8097c1771d3443a9c6 COPYRIGHT SHA1 b1f67a8983d34d3cfe1bfa5a5aeae93db92deb67 CREDITS SHA1 93b828d8c702b14e42e7fc5e31c2f7809c40e890 Changes SHA1 ad40a11542937daa751b38225d43868322a073cc INSTALL SHA1 34f5e12514b91055de4b164a1f2327ef5c30ba53 LICENSE SHA1 e578c72b89156a593ab399c43fbc74afa2061f50 MANIFEST SHA1 2f3a5432e3c2ca383d575740ce33c15563055383 META.json SHA1 95fc2af08abf8b8c5d400dccdbf4f7332ff4791c META.yml SHA1 41bf88907a6f932920cd3035317e041ad8dd8bfb Makefile.PL SHA1 6a37e192c7f990678cfac5902bdc4c0ab22bcabb NEWS SHA1 618818969d163bfaff6515c6d8bfca8b208ef4f3 README SHA1 dfcf31f0d8a975af5299a3e869bbb983edf2605d TODO SHA1 eeed84a123dd7a29ae3be4700cd6d1daeb6c1c68 dist.ini SHA1 4fdedc492703d62c38835dfbc9f969564e5b2484 doap.ttl SHA1 8287b47d25816131e3cc423250538c5565f89407 examples/benchmark-coercions.pl SHA1 e9b329c6285d83681bff3e4c2ecbb56089999d57 examples/benchmark-constraints.pl SHA1 83ba80a1a71b01fa18933c1e0f97de9eba965247 examples/benchmark-param-validation.pl SHA1 f25058eef51dac107e9aa72ec62272aec62f7e94 examples/datetime-coercions.pl SHA1 2aacb4150fc74604496079f9ac21968325ac5f3b examples/versus-scalar-validation.pl SHA1 8b3c5d366a0a716096617c9e14a100c1948fd159 inc/Test/Fatal.pm SHA1 95d4da14025622f3a45f5e9b75b7b6860148f415 inc/Test/Requires.pm SHA1 e7088f7483bdffb64be359be205927c3d6639ffe inc/Try/Tiny.pm SHA1 317b9ea61e77bcfaa28aee83007c7ee6d249c522 lib/Devel/TypeTiny/Perl56Compat.pm SHA1 e27f0bef509e8ff334d363fa6477191edb6762e0 lib/Devel/TypeTiny/Perl58Compat.pm SHA1 24a7137a39d0939ff6f9fdd7a354820e28dd98a5 lib/Error/TypeTiny.pm SHA1 de936bd37a482b7613f8e6a8c1f94b1fc2da4185 lib/Error/TypeTiny/Assertion.pm SHA1 0fd914169c6fc08447c5596184f37fad44c3d1aa lib/Error/TypeTiny/Compilation.pm SHA1 25b741c4a7f35bc84cd699f99515fbf91388e025 lib/Error/TypeTiny/WrongNumberOfParameters.pm SHA1 694252b371e4f6cfecd9824a311a6d1b7edaa98d lib/Eval/TypeTiny.pm SHA1 edd3438c5e8fdfb5a13b16ef7366ccde7c5e1fd5 lib/Reply/Plugin/TypeTiny.pm SHA1 907d5257aee4897a4d21088294904309f3ff8c52 lib/Test/TypeTiny.pm SHA1 dc85e56b27c642c1e0f02e8e8f9962038d631688 lib/Type/Coercion.pm SHA1 07038e3e1c14fe81937b45e67ddc8a171b890b8d lib/Type/Coercion/FromMoose.pm SHA1 f0b9223ebf65f7bf528b9802b1572531677f6655 lib/Type/Coercion/Union.pm SHA1 0daabb70400507205fa1903783ae3e89a3bf3a53 lib/Type/Library.pm SHA1 d2d0cb5c7d203f8d40c13fbde5157a9d83cea7eb lib/Type/Params.pm SHA1 254b60dd36c491a6ec8af38d1bc9cf15146ef736 lib/Type/Parser.pm SHA1 21d54221104ce5312b60b307678081e4ea086a80 lib/Type/Registry.pm SHA1 4375dead71e85090b639b6575fb79f8833654c4e lib/Type/Tiny.pm SHA1 3636ba8cc2f660b543a12c34ddc2598b2113729e lib/Type/Tiny/Class.pm SHA1 9696df09017ece318ed0506d768cce128b26d3bc lib/Type/Tiny/Duck.pm SHA1 1196a079b5a57a37e0177ce4e3138e15f62da02b lib/Type/Tiny/Enum.pm SHA1 fc2bbe65a71c3c1eeeb5327ebdef44a6a1977cc2 lib/Type/Tiny/Intersection.pm SHA1 76f16ec3fba03876fc35d6dcb2ffc57891e22ec9 lib/Type/Tiny/Manual.pod SHA1 1ee6304527dbb89bb7e5ba1312ea36ffe5a6dc83 lib/Type/Tiny/Manual/Coercions.pod SHA1 aa6d56fb6fc50a9293948ea4f03995f017ece254 lib/Type/Tiny/Manual/Libraries.pod SHA1 4008a036c434a8bf07c9e360e8db37d244b8cab6 lib/Type/Tiny/Manual/Optimization.pod SHA1 89f7da04e7b2d1c8363df659e063eab69ee55200 lib/Type/Tiny/Manual/Params.pod SHA1 097bf4e31a8241107ee4f11993788728f243ecfa lib/Type/Tiny/Manual/Policies.pod SHA1 ef827a774088d9cb5b0cb0543ce932ef11f369dd lib/Type/Tiny/Manual/UsingWithMoo.pod SHA1 6bd074644a4d5e67c9fed91f9e24283ae1416c06 lib/Type/Tiny/Manual/UsingWithMoose.pod SHA1 e96e186ad4afcd2f980282bd510b42a9bca9a863 lib/Type/Tiny/Manual/UsingWithMouse.pod SHA1 ba5d7e9bcd7cffc7708f272be40a229bdbc8e19b lib/Type/Tiny/Manual/UsingWithOther.pod SHA1 db9094f4277e20cc3964ecdf14c1210d5c3c5bee lib/Type/Tiny/Role.pm SHA1 ae802e9082fbfe35066ed4019b9281e7f58f6510 lib/Type/Tiny/Union.pm SHA1 5c26ae1a7d22f23a6b9d60efb9e5698427efe2f0 lib/Type/Tiny/_HalfOp.pm SHA1 6c5c1323cbf9090a3ac494d49ca3692e14023637 lib/Type/Utils.pm SHA1 91452b00b186cadfcf55c37b78be9df3cabfd0e4 lib/Types/Common/Numeric.pm SHA1 0ea04e398aa159f4b6ea0696f0aa6310df810eb6 lib/Types/Common/String.pm SHA1 01ab4e6fc9203d63978c72f67a2ec1c40946f239 lib/Types/Standard.pm SHA1 1917a2e95b9862ceea9776f89cc8a5ef1afeac17 lib/Types/Standard/ArrayRef.pm SHA1 a635df2a2641347a757282ae9fe480b40a3be3e4 lib/Types/Standard/Dict.pm SHA1 7a1d9e696fc0dad748b3df3dfb666233df6cb999 lib/Types/Standard/HashRef.pm SHA1 505ded4a9c7e4b6bdf6b8d1f50cffe37f92b51b2 lib/Types/Standard/Map.pm SHA1 a1d581409e8cf465588f7507e7ca79d8cd652ffc lib/Types/Standard/ScalarRef.pm SHA1 0c2a779edb986172bd2d820fc270482fdd872d2c lib/Types/Standard/Tuple.pm SHA1 bc2ad3c807c11b3f11974312b574880243271ee4 lib/Types/TypeTiny.pm SHA1 b9af35d9d0a3328fedc80c5824da06ca69409589 t/00-begin.t SHA1 d3f403cf1bde842588e66107eeae2c34290dab72 t/01-compile.t SHA1 6424dbcb52e79c715b37ccc836fea197525f057e t/02-api.t SHA1 d515317dbf547309e22a09ecca20065daa0c90f1 t/03-leak.t SHA1 f28068b49527681dc4e147b3bd2ca7a163545e40 t/20-unit/Devel-TypeTiny-Perl56Compat/basic.t SHA1 15d9987525dbb2c590d66323ef2e9ad4a999574f t/20-unit/Devel-TypeTiny-Perl58Compat/basic.t SHA1 29486c881392c8490d490e26bcfb7a6b4eb1604e t/20-unit/Error-TypeTiny-Assertion/basic.t SHA1 39f0f71c9be77b40f1174c0ae6257bc6a60d6874 t/20-unit/Error-TypeTiny-Compilation/basic.t SHA1 1eeb57ce0471f659c8b90d9e2eb8c3d0f538593b t/20-unit/Error-TypeTiny-WrongNumberOfParameters/basic.t SHA1 bb0ae0fd87fc2a2ec8aca23567e495eb986b9b9f t/20-unit/Error-TypeTiny/basic.t SHA1 192e65901959094b96beb2731c60923c2544e914 t/20-unit/Error-TypeTiny/stacktrace.t SHA1 602d3df196ea4cdc237bf89213b15548e4c639b1 t/20-unit/Eval-TypeTiny/basic.t SHA1 fffe0d31c3eb71550a4ba560fcbb90fccad2bcb3 t/20-unit/Eval-TypeTiny/fallback-aliases.t SHA1 bf9eddf28b323a1e232ea5622ece38874ed89770 t/20-unit/Eval-TypeTiny/lexical-subs.t SHA1 0d8906c13806cca3440c8d11722684395cfeb1d7 t/20-unit/Test-TypeTiny/basic.t SHA1 d44c2c0b0ed1d69aaba0436b1a67a44844628015 t/20-unit/Test-TypeTiny/extended.t SHA1 b3f07e91d85e8d2d684d9ebb53e512476003db0f t/20-unit/Test-TypeTiny/matchfor.t SHA1 1a78fcc51393c259dde6eaf249bc57389330e25c t/20-unit/Type-Coercion-FromMoose/basic.t SHA1 7a0614fbc420168e74d45f5934367713dc9c9db1 t/20-unit/Type-Coercion-FromMoose/errors.t SHA1 be157f6de3fccb8e3fe0cb43e367f78cb15506c8 t/20-unit/Type-Coercion-Union/basic.t SHA1 f1732e8387b6bee8b3dd67715e2fec5a5ed9680b t/20-unit/Type-Coercion/basic.t SHA1 2b3cddf2d148e9ec07c68cf50bfc2cece7910d09 t/20-unit/Type-Coercion/esoteric.t SHA1 f3565174f11f4215e3810df27cab2b8b2b1d721f t/20-unit/Type-Coercion/frozen.t SHA1 c9f55d2a715fabff47b460843c5b619d1001f389 t/20-unit/Type-Coercion/inlining.t SHA1 672c7389629fa0594eabdf12e837466f1d96cdcf t/20-unit/Type-Coercion/parameterized.t SHA1 e37cb0ada698107dbf9f8d759118e09e463df60d t/20-unit/Type-Coercion/smartmatch.t SHA1 0879a2be4fb9874357da7d0aa089f1d09296d976 t/20-unit/Type-Coercion/typetiny-constructor.t SHA1 6759ca9e9deb9e8ac8715335fae7f51e7c8c2abd t/20-unit/Type-Library/assert.t SHA1 886da2841b0caf78935d0e2a571265021b5b83db t/20-unit/Type-Library/errors.t SHA1 886f03eb374a0bc88c992ddabd47e0ab9af90937 t/20-unit/Type-Library/inheritance.t SHA1 50e5ea609b05e8952dfe6aaa2dd6809280e742a3 t/20-unit/Type-Library/is.t SHA1 87442dc6543236325ba1faae9eeaea485f36c709 t/20-unit/Type-Library/to.t SHA1 dc29b410e47a63cde1963cc348d8ac8369a9d196 t/20-unit/Type-Library/types.t SHA1 11acc7e236d64cca8a9ac7ab910570ed38fabee5 t/20-unit/Type-Params/badsigs.t SHA1 899c98198fbf752ddeeccb373637da17a60a60d8 t/20-unit/Type-Params/carping.t SHA1 b2c905090b590861050061b46f2b9c920dba342b t/20-unit/Type-Params/coerce.t SHA1 16314f96dcabec21727864b82016e2581bd970fd t/20-unit/Type-Params/methods.t SHA1 2a8a9b74440c74b53391ba5b4e7854bd1738321e t/20-unit/Type-Params/mixednamed.t SHA1 327c1e582d30793ff3393f518d135efc33156522 t/20-unit/Type-Params/multisig.t SHA1 426ee447807557dad96cad50742db68ba4919881 t/20-unit/Type-Params/named.t SHA1 dde47da443721ff3de875f54caf3d28ba65a175b t/20-unit/Type-Params/noninline.t SHA1 c9448d6a10b48482190b539654a99c045f5a78b0 t/20-unit/Type-Params/optional.t SHA1 c8e9a92b55d3736b30b1d4047e09f5aea6643004 t/20-unit/Type-Params/positional.t SHA1 50a6fd10075064da20c3c005e8d3fc6c40f4c240 t/20-unit/Type-Params/slurpy.t SHA1 bbd2de4c0d54ace67af445284ad4dedd6b58e885 t/20-unit/Type-Parser/basic.t SHA1 01c99c359538df250677906ec24fd931b82dcbd1 t/20-unit/Type-Parser/moosextypes.t SHA1 54d85a0f70376b9e3a33c082761bec19899cedf2 t/20-unit/Type-Registry/automagic.t SHA1 9dad0a098f5a4cb7aca03635ee433879e059a0cd t/20-unit/Type-Registry/basic.t SHA1 e9acc3dd2f3725aae2f6e1a595cf539e3859e6d9 t/20-unit/Type-Registry/methods.t SHA1 68718858d922cf4a29b336b62deac4dc633a8c56 t/20-unit/Type-Registry/moosextypes.t SHA1 b73f649e5c0d8f2f04cdde86b773c7c5a9032ccd t/20-unit/Type-Registry/mousextypes.t SHA1 66efbf7eca5461b0095c666dfd4eac176f59635b t/20-unit/Type-Tiny-Class/basic.t SHA1 1a002c09cfd1caeca119f27eecd3b2bfa6879964 t/20-unit/Type-Tiny-Class/errors.t SHA1 0a98e4346d8b9a1a5d14af125993b3f736f7c867 t/20-unit/Type-Tiny-Class/plus-constructors.t SHA1 b88ba9eb584600968e619a44a65c18a4d1b20e8a t/20-unit/Type-Tiny-Duck/basic.t SHA1 3cc021195613ebfce2cfcc32a3743424e8a02a5c t/20-unit/Type-Tiny-Duck/errors.t SHA1 bfffdecee9d0a12409bea19ce9507b9b8d854b11 t/20-unit/Type-Tiny-Enum/basic.t SHA1 7f1bb58f8a5e88cad2a523bddf204caca49885a9 t/20-unit/Type-Tiny-Enum/errors.t SHA1 45c500be061cd42c4c02dfac61c2383b987f40f4 t/20-unit/Type-Tiny-Intersection/basic.t SHA1 8ed66d9acd422a938871961c2a6fd1eafab7b669 t/20-unit/Type-Tiny-Intersection/errors.t SHA1 f623b85e99fc36c7c283fa14ad41d8118919370c t/20-unit/Type-Tiny-Role/basic.t SHA1 628ddc8d8e93268d3c1854caf98ca211d4ad0cd9 t/20-unit/Type-Tiny-Role/errors.t SHA1 03410ff163c28be50b95ba9325c7440f56d7adff t/20-unit/Type-Tiny-Union/basic.t SHA1 6f69c07f5b99a38f1e9088380d58a69fb6fc984a t/20-unit/Type-Tiny-Union/errors.t SHA1 b0705b77cfe293525446e9aa79144ac84f3f04c3 t/20-unit/Type-Tiny-_HalfOp/overload-precedence.t SHA1 df16fe134295effc5036420bdc407d80d0a6403c t/20-unit/Type-Tiny/arithmetic.t SHA1 1d56dc5b4112e2de4f128ca045d2f3886774be70 t/20-unit/Type-Tiny/basic.t SHA1 eb3bfba613971feca8d1f30585595c2fad99e560 t/20-unit/Type-Tiny/coercion-modifiers.t SHA1 4ddded9517e95ecb5eea6e5a8e2c0ed8f3dda3ce t/20-unit/Type-Tiny/esoteric.t SHA1 2c1f75c14004e3ffae61ef294be1d20ba9c91cfc t/20-unit/Type-Tiny/my-methods.t SHA1 927a852aaa2e1c80afd5d03ee6edb23b0e1eb5e8 t/20-unit/Type-Tiny/parameterization.t SHA1 c01cf834a245e606a7569bdec8f51e17b54e6eba t/20-unit/Type-Tiny/shortcuts.t SHA1 a56a1abe29695eb063ad482dddd29818f1748d94 t/20-unit/Type-Tiny/smartmatch.t SHA1 32a791e182958f527ae9384355b381a491022986 t/20-unit/Type-Tiny/syntax.t SHA1 b3b6d756f3888455aacd3a4ad1b27cd5a0045e8d t/20-unit/Type-Tiny/to-moose.t SHA1 1004f06ab52204fa69b2c684dc6d93525222d608 t/20-unit/Type-Tiny/to-mouse.t SHA1 37075ba176c4c90ae099c132e59d3fa7219f8f46 t/20-unit/Type-Utils/classifier.t SHA1 61c6207df4de8e5d6aa026820a97869705235b22 t/20-unit/Type-Utils/dwim-both.t SHA1 eed7bdd2e497d6285318ce375205b03260c3028d t/20-unit/Type-Utils/dwim-moose.t SHA1 dbaa2fe138a7c91a374db618460c0003c18ff9e6 t/20-unit/Type-Utils/dwim-mouse.t SHA1 9f312fa1e087e47f3dc192bde67292d4b0b66f9c t/20-unit/Type-Utils/match-on-type.t SHA1 1178864691872ccabfd32e45882eeb03b1c09d0d t/20-unit/Type-Utils/warnings.t SHA1 092fba41d4a128243f1da35230cd63c46c31de87 t/20-unit/Types-Common-Numeric/basic.t SHA1 9db6707d3d6247034aa5d96ba63a0ce2041ac410 t/20-unit/Types-Common-String/basic.t SHA1 5a1d2ef80a0cb1c559e1d86a563accdefb1daa58 t/20-unit/Types-Common-String/coerce.t SHA1 60f0d8924f3556227c07f024b5ea3526c46d2bf3 t/20-unit/Types-Common-String/unicode.t SHA1 027d9dfecffac07c9e6eb69319db284f49245557 t/20-unit/Types-Standard/basic.t SHA1 236ad778e85654668486ab2070a0c4f7b7c26b2f t/20-unit/Types-Standard/deep-coercions.t SHA1 0947699d805cd4a131b49f38bce5131bb4e27704 t/20-unit/Types-Standard/lockdown.t SHA1 f4b67b87104d6514cf85c7018ca4451e8c35accf t/20-unit/Types-Standard/mxtmlb-alike.t SHA1 03eb0e84983981fc9698771a8e6d963090681a1e t/20-unit/Types-Standard/optlist.t SHA1 8a438f687b9e8d6c3f122d36f445a66b324ac83b t/20-unit/Types-Standard/overload.t SHA1 218c975320897284ad68d0b6306de0ad74bb8b1b t/20-unit/Types-Standard/strmatch.t SHA1 5f97f99204d0c83648eb6b85d6698da1bec184ab t/20-unit/Types-Standard/structured.t SHA1 04702d1353ffc8bdd1f8ac0e3dc59f634164f9f0 t/20-unit/Types-Standard/tied.t SHA1 dd68680d4e149181579832b05218ad2aa314f462 t/20-unit/Types-TypeTiny/basic.t SHA1 531a4458fafc17a527b1ff3d10b5a31d6c87b78e t/20-unit/Types-TypeTiny/coercion.t SHA1 72236fa1570495cec069673674af7908f3ab8b60 t/20-unit/Types-TypeTiny/meta.t SHA1 413782c8873d62d6e45da8e62624cbd345cfefbb t/30-integration/Class-InsideOut/basic.t SHA1 cfd04b3ad67cfda0758e1ec3ecb676c3c42938a3 t/30-integration/Exporter-Tiny/basic.t SHA1 14ccfb84a3c2c395d5a58183911dfde5be6ad2ef t/30-integration/Exporter-Tiny/installer.t SHA1 606f48474abc21958b2fa5e32c967785d25bafc6 t/30-integration/Exporter-Tiny/role-conflict.t SHA1 39722c2c0a8ce312becc65445be4d28f6a261f8f t/30-integration/Function-Parameters/basic.t SHA1 ff1a7204d6f1fb93b01d499e0c6866b812617a9e t/30-integration/Kavorka/basic.t SHA1 14573cd911424f9711f9fdb2858b563e00f55137 t/30-integration/Moo/basic.t SHA1 64219d6e017330e6547f1a7fb51295b74b51564e t/30-integration/Moo/coercion-inlining-avoidance.t SHA1 0a55f5788d5ce6a16008b158c9dbb4e1f0ce6bf5 t/30-integration/Moo/coercion.t SHA1 202cfb5c7a76e96636c952e337a9dc5b338ead30 t/30-integration/Moo/exceptions.t SHA1 b72ff074358e50986a2d1e7f5d26ca0dbda1ba1c t/30-integration/Moo/inflation.t SHA1 df69edc34cd4df6ea0e104253b21c8d513fcda0c t/30-integration/Moo/inflation2.t SHA1 6e067c04404fbebac67fa17a6e7f124422875abb t/30-integration/Moops/basic.t SHA1 8a6d2bd6f88e623ee3a8097225ba3188a91a1c89 t/30-integration/Moops/library-keyword.t SHA1 951474159fd17f57ddcab49d41ee9f3c3dc61911 t/30-integration/Moose/accept-moose-types.t SHA1 b94d883181d5e2a8dd008410ab173ef018d53400 t/30-integration/Moose/basic.t SHA1 251dd8e32e97e0ed0bc8a0b2249a09ba6b91be48 t/30-integration/Moose/coercion.t SHA1 5bd0d931433a4722cefdb925aeade6a52d0262f9 t/30-integration/Moose/inflate-then-inline.t SHA1 29707d7c79ba1b14cc806229366ba481e8e83b4c t/30-integration/Moose/native-attribute-traits.t SHA1 39f4c0ef1a0317b301380fd3ba9cf067f157b15c t/30-integration/MooseX-Getopt/coercion.t SHA1 ce9128d67dd493d8a098b43a79d621a68ef44690 t/30-integration/MooseX-Types/basic.t SHA1 4e8cc262d34fa2512765d5583ce714c9e4e60ccd t/30-integration/MooseX-Types/extending.t SHA1 b793a8fe0ba551eb6edce4371e7e09d2f06434b0 t/30-integration/MooseX-Types/more.t SHA1 9fed63a8e9a7ea72157a6501c48ba469503da774 t/30-integration/Mouse/basic.t SHA1 cf8dcebdda2a29f747d7c979ef1ef2f97f2830d3 t/30-integration/Mouse/coercion.t SHA1 9d2e7e9da13a8e8dbf128ca87c895dbf45cdb6e8 t/30-integration/MouseX-Types/basic.t SHA1 c9d06d12b6a935049aac9024177170691c5ad1cf t/30-integration/MouseX-Types/extending.t SHA1 2d52fab2ca400eca0bdae8d10fd16285ca7c30d6 t/30-integration/Object-Accessor/basic.t SHA1 3b3749e2f00dfce5376b07b20029f172050ba755 t/30-integration/Return-Type/basic.t SHA1 eec7ea7d3ce9cfc49063685d669418a200174048 t/30-integration/Sub-Quote/basic.t SHA1 be5d3c59c8d3b53a87aff8299851699755d6a476 t/30-integration/Sub-Quote/unquote-coercions.t SHA1 13db0be12e9af963331ea7057342012cde749726 t/30-integration/Sub-Quote/unquote-constraints.t SHA1 b410fb9dfcfaa6c5999484e00553ec11360bd2f0 t/30-integration/Switcheroo/basic.t SHA1 0d2e5f7cd72335c0688784f8dfc11084c268872c t/30-integration/Type-Tie/basic.t SHA1 cc1d3f967bb3478579cc8de38446bc8feb01d06b t/30-integration/Validation-Class-Simple/archaic.t SHA1 d04fc6f2c2e585a4f7cc2b2459f4e03d13d89226 t/30-integration/Validation-Class-Simple/basic.t SHA1 352549247763ed90c90fb194530e2682641e3aa2 t/30-integration/match-simple/basic.t SHA1 ca18e0558abf6d9313a0ebd18be6ca579d64cfde t/40-regression/73f51e2d.pl SHA1 80ba6d01ea1bac1f28417f999f91749b664a8723 t/40-regression/73f51e2d.t SHA1 fec03ab3152c2865970ba2a19a4e4edbd178f8cc t/40-regression/gh1.t SHA1 cc6257770c25469f0016cde3473844e08890e27d t/40-regression/rt85911.t SHA1 f258801a42bc55bd396500255a3a41b44fa5a57d t/40-regression/rt86004.t SHA1 0831ca9eec77f6e7e80b98ff5aa59c0f25d50eac t/40-regression/rt86233.t SHA1 87c998cd74ca53ad8279b122dc4b172854945f18 t/40-regression/rt86239.t SHA1 480a150a01bb6fdd1a46841abb6f5ac4a7e3f27e t/40-regression/rt90096-2.t SHA1 6f876719e9482078f55b3a2eeb3f189cf93ad2c5 t/40-regression/rt90096.t SHA1 9791a5aa341784fc57dcc7dfc2533ae9cfbe94d5 t/40-regression/rt92571-2.t SHA1 20bb1229a9a799a7318512fa3a36deb5556c6164 t/40-regression/rt92571.t SHA1 e4ee707028a14d165f76ef59ab4fd4e88ab363f1 t/40-regression/rt92591.t SHA1 003f455af6a50189c396b50471c7a5ab39428936 t/40-regression/rt94196.t SHA1 f7bcc3760616e86c777ea05335546294b1e2c340 t/40-regression/rt97684.t SHA1 bd8073cd5c11cc68d3564d078f0e46bdd044f4c5 t/40-regression/rt98113.t SHA1 a4e1390ef920c38e1b5e48ae589d77b34b0075c8 t/40-regression/ttxs-gh1.t SHA1 d23515f31e91fe975cca99e82458feceaa80e065 t/99-moose-std-types-test.t SHA1 f765f14abcbe280da09d0d3aacca0337760b0683 t/README SHA1 83c445cac3ab13ffe427ec7bf21287ef2824ff8f t/TODO SHA1 14e9cbe972a219046ba8eca18f6b7730714d5078 t/lib/BiggerLib.pm SHA1 620f21a99269ade5cc91c73a7f9df97ee9cbb8e2 t/lib/DemoLib.pm SHA1 3eb4a7ac4357ce37ee83611ecccd32dab0a6d5a1 t/mk-test-manifest.pl SHA1 f846fa57aa90c0c55aeee735368cb9dd4015b77a t/not-covered.pl -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iEYEARECAAYFAlRL9M8ACgkQzr+BKGoqfTm6PQCgq78tji2x+TeelGnUgZsYel/k mSoAnRMTFMm89evDz90q5SNJC1j8S5xO =PpjE -----END PGP SIGNATURE----- TODO000664001750001750 243212422772210 13070 0ustar00taitai000000000000Type-Tiny-1.000005Post-1.000000 Changes ===================== * Type::Params should provide compile_named/validate_named functions tailored for named parameters rather than using the slurpy Dict hack. * Try to make inlining for ClassName, RoleName, StrMatch, etc more suitable for things like Mite. * Inform Type::Coercion when it *should have* been frozen (for example, the parameterized ArrayRef, HashRef, Dict, and Tuple coercion generators). After that, $coercion->add_type_coercions can issue a warning about that bad things are happening. On Perl 5.10, this can be done with warnings::warnif. On earlier Perls that mechanism is unreliable, so just use plain old warn. * Investigate popular type constraints defined outside Type-Tiny, and consider which can be added to Types::Standard/Types::Common::*. These would need to be constraints that can be implemented with no non-core dependencies. * Possibly add a NonEmpty type constraint, allowing NonEmpty[Str], NonEmpty[HashRef[Int]], NonEmpty[ArrayRef], etc. This would be an interesting one for optimizing. * CycleTuple[Int,Str,HashRef] should allow [1,foo=>{},2,bar=>{}]. * Perhaps allow Type::Coercion::FromMoose's implementation of add_type_coercions to succeed? * to_TypeTiny's _TypeTinyFromGeneric could support inlining? dist.ini000664001750001750 16212422772210 14022 0ustar00taitai000000000000Type-Tiny-1.000005;; class = 'Dist::Inkt::Profile::TOBYINK' ;; name = 'Type-Tiny' ;; source_for_readme = 'lib/Type/Tiny/Manual.pod' doap.ttl000664001750001750 105753612422772317 14160 0ustar00taitai000000000000Type-Tiny-1.000005@prefix cpan-uri: . @prefix dc: . @prefix doap: . @prefix doap-bugs: . @prefix doap-changeset: . @prefix doap-deps: . @prefix doap-tests: . @prefix foaf: . @prefix nfo: . @prefix rdfs: . @prefix xsd: . dc:title "the same terms as the perl 5 programming language system itself". a doap:Project; dc:contributor ; doap-bugs:issue , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ; doap-deps:develop-suggestion [ doap-deps:on "Dist::Inkt::Profile::TOBYINK"^^doap-deps:CpanId; rdfs:comment "This is used for building the release tarball."@en; ]; doap-deps:runtime-conflict [ doap-deps:on "Kavorka <= 0.013"^^doap-deps:CpanId; rdfs:comment "Theoretically broken by changes to parameterization of Dict to allow it to accept a slurpy."@en; ], [ doap-deps:on "Types::ReadOnly <= 0.001"^^doap-deps:CpanId; rdfs:comment "Theoretically broken by changes to parameterization of Dict to allow it to accept a slurpy."@en; ]; doap-deps:runtime-recommendation [ doap-deps:on "perl 5.010001"^^doap-deps:CpanId; rdfs:comment "For smartmatch operator overloading; and to avoid some pre-5.10 hacks."@en; ], [ doap-deps:on "Devel::LexAlias 0.05"^^doap-deps:CpanId; rdfs:comment "Devel::LexAlias is useful for some Eval::TypeTiny features."@en; ], [ doap-deps:on "Type::Tiny::XS 0.010"^^doap-deps:CpanId; rdfs:comment "Make stuff faster (I think)."@en; ], [ doap-deps:on "Sub::Name"^^doap-deps:CpanId; rdfs:comment "This allows Type::Library to name subs nicely."@en; ], [ doap-deps:on "Type::Tie"^^doap-deps:CpanId; rdfs:comment "Type::Tie is needed if you want to constrain the type of a scalar, array or hash variable."@en; ], [ doap-deps:on "Devel::StackTrace"^^doap-deps:CpanId; rdfs:comment "Type::Exception can use Devel::StackTrace for stack traces."@en; ]; doap-deps:runtime-requirement [ doap-deps:on "perl 5.006001"^^doap-deps:CpanId ], [ doap-deps:on "Exporter::Tiny 0.026"^^doap-deps:CpanId; rdfs:comment "This module was spun off from the Type-Tiny distribution."@en; ]; doap-deps:runtime-suggestion [ doap-deps:on "Moose 2.0400"^^doap-deps:CpanId; rdfs:comment "Type::Tiny works nicely with Moose."@en; ], [ doap-deps:on "Mouse 1.00"^^doap-deps:CpanId; rdfs:comment "Type::Tiny works nicely with Mouse."@en; ], [ doap-deps:on "Moo 1.000000"^^doap-deps:CpanId; rdfs:comment "Type::Tiny works nicely with Moo."@en; ], [ doap-deps:on "Reply"^^doap-deps:CpanId; rdfs:comment "Type::Tiny bundles a plugin for Reply."@en; ]; doap-deps:test-recommendation [ doap-deps:on "Test::Tester 0.109"^^doap-deps:CpanId; rdfs:comment "For testing Test::TypeTiny."@en; ], [ doap-deps:on "Test::Warnings"^^doap-deps:CpanId; rdfs:comment "For testing Type::Utils."@en; ]; doap-deps:test-requirement [ doap-deps:on "Test::More 0.96"^^doap-deps:CpanId; rdfs:comment "I don't have the patience to maintain a test suite that runs on ancient versions of Test::More."@en; ]; doap:bug-database ; doap:category [ rdfs:label "Moo" ], [ rdfs:label "Argument Validation" ], [ rdfs:label "Argument Checking" ], [ rdfs:label "Validation" ], [ rdfs:label "Moose" ], [ rdfs:label "Mouse" ], [ rdfs:label "Type Constraint" ], [ rdfs:label "Type Coercion" ], [ rdfs:label "Type Library" ], [ rdfs:label "Schema" ], [ rdfs:label "Parameter Validation" ], [ rdfs:label "Parameter Checking" ]; doap:created "2013-03-23"^^xsd:date; doap:developer ; doap:download-page ; doap:homepage ; doap:license ; doap:maintainer ; doap:name "Type-Tiny"; doap:programming-language "Perl"; doap:release , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ; doap:repository [ a doap:GitRepository; doap:browse ; ]; doap:shortdesc "tiny, yet Moo(se)-compatible type constraint". a cpan-uri:DeveloperRelease, doap:Version; rdfs:label "Developer preview"; dc:identifier "Type-Tiny-0.000_01"^^xsd:string; dc:issued "2013-04-02"^^xsd:date; doap-changeset:released-by ; doap:file-release ; doap:revision "0.000_01"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.000_02"^^xsd:string; dc:issued "2013-04-02"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Beginnings of Type::Tiny::Manual."; ], [ a doap-changeset:Bugfix; rdfs:label "Anchor enum regexps to beginning and end of string."; ], [ a doap-changeset:Addition; rdfs:label "StrMatch added to Type::Standard."; ], [ a doap-changeset:Change; rdfs:label "use Type::Library -base"; ], [ a doap-changeset:Change; rdfs:label "use Type::Library -declare"; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.000_02"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.000_03"^^xsd:string; dc:issued "2013-04-03"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Document Type::Coercion's overloading."; ], [ a doap-changeset:Change; rdfs:label "Create and use compiled type constraint checks; much faster!"; ], [ a doap-changeset:Change; rdfs:label "All of Type::Standard cannow be inlined."; ], [ a doap-changeset:Tests; rdfs:label "Add test cases for ScalarRef[`a]."; ], [ a doap-changeset:Change; rdfs:label "Use more unique stringification for %Moo::HandleMoose::TYPE_MAP keys."; ], [ a doap-changeset:Change; rdfs:label "Make sure Type::Standard's Moose-like built-ins get inflated to real Moose built-in types."; ], [ a doap-changeset:Bugfix, doap-changeset:Tests; rdfs:label "Fix the crashing t/moo-inflation.t test case."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.000_03"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.000_04"^^xsd:string; dc:issued "2013-04-03"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Create and use compiled coercions; somewhat faster."; ], [ a doap-changeset:Addition; rdfs:label "Type::Tiny plus_coercions/minus_coercions/no_coercions methods for creating subtypes with different sets of coercions."; ], [ a doap-changeset:Addition; rdfs:label "Type::Tiny equals/is_subtype_of/is_supertype_of/is_a_type_of methods for type constraint comparisons."; ], [ a doap-changeset:Addition; rdfs:label "Finally implement Type::Coercion's has_coercion_for_type method."; ], [ a doap-changeset:Change; rdfs:label "Allow coercion code to be expressed as a string; quite a bit faster."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.000_04"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.000_05"^^xsd:string; dc:issued "2013-04-04"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Tests; rdfs:label "Factor out some functions from test suite into a new module: Test::TypeTiny."; ], [ a doap-changeset:Tests; rdfs:label "Rearrange test suite slightly."; ], [ a doap-changeset:BackCompat; rdfs:label "Rename Type::Standard module to Types::Standard."; ], [ a doap-changeset:Change; rdfs:label "Types::TypeTiny bootstrapping library now takes care of vaious internal type checking requirements."; ], [ a doap-changeset:Change; rdfs:label "Sanity checks for type constraint names."; ], [ a doap-changeset:Bugfix; rdfs:label "Fix is_parameterized method."; ], [ a doap-changeset:Change; rdfs:label "Allow null type constraints with no parent type (e.g. 'Any' in Types::Standard) to be inlined."; ], [ a doap-changeset:Change; rdfs:label "Don't die with full stack trace."; ], [ a doap-changeset:Bugfix; rdfs:label "Get Mouse coercions working."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.000_05"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.000_06"^^xsd:string; dc:issued "2013-04-05"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Monkey patch Moose::Meta::TypeConstraint to be able to retrieve Type::Tiny constraints from inflated Moose constraints."; ], [ a doap-changeset:Tests; rdfs:label "More test cases."; ], [ a doap-changeset:Documentation; rdfs:label "Improved documentation of parameterization attributes."; ], [ a doap-changeset:Change; rdfs:label "Footprint reduction: Type::Tiny, Type::Library and Type::Coerce no longer automatically load Types::Standard and Type::Utils."; ], [ a doap-changeset:Change; rdfs:label "Footprint reduction: Type::Tiny and Type::Coercion no longer use if.pm."; ], [ a doap-changeset:Change; rdfs:label "Footprint reduction: Type::Tiny no longer triggers Perl to load its Unicode tables (unless you create a type constraint with a non-ASCII type name)."; ], [ a doap-changeset:Addition; rdfs:label "Type::Tiny now has an 'inline_assert' function."; ], [ a doap-changeset:Documentation; rdfs:label "Using Type::Tiny with Moo added to manual."; ], [ a doap-changeset:Documentation; rdfs:label "Section in manual comparing Type::Tiny with various other type library frameworks."; ], [ a doap-changeset:Change; rdfs:label "In Moo, type assertions and coercions are now inlined."; doap-changeset:thanks ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.000_06"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.000_07"^^xsd:string; dc:issued "2013-04-06"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Tests; rdfs:label "More test cases."; ], [ a doap-changeset:Documentation; rdfs:label "Document constructor for Type::Tiny::Class."; ], [ a doap-changeset:Bugfix; rdfs:label "Fix inlining for Type::Tiny::Intersection."; ], [ a doap-changeset:Bugfix; rdfs:label "Types within libraries, if accessed directly rather than exported, did not accept parameters."; ], [ a doap-changeset:Addition; rdfs:label "New module Type::Coercion::Union automatically handles coercion to union types."; ], [ a doap-changeset:Bugfix; rdfs:label "Fix inlining of certain conditionals into coercion code."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.000_07"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.000_08"^^xsd:string; dc:issued "2013-04-07"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Rewrite most of the functions exported by Type::Library-based type libraries to cope better with being used mid-list."; ], [ a doap-changeset:Change; rdfs:label "Most parts of the API that accept Type::Tiny objects (e.g. Type::Utils::from()) now also accept Moose::Meta::TypeConstraint objects."; ], [ a doap-changeset:Change; rdfs:label "Types::TypeTiny::to_TypeTiny can be used to coerce a Moose type constraint object to Type::Tiny."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.000_08"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.000_09"^^xsd:string; dc:issued "2013-04-08"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Bundle benchmarking scripts."; ], [ a doap-changeset:Packaging; rdfs:label "Tidy up the 'examples' directory."; ], [ a doap-changeset:Change; rdfs:label "When generating Moose/Mouse constraints from Type::Tiny objects, prefer to generate anonymous ones."; ], [ a doap-changeset:Documentation; rdfs:label "Fill in the Usage with Moose section of the fine manual."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.000_09"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.000_10"^^xsd:string; dc:issued "2013-04-09"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Improvements to has_coercion_for_{type,value} from Type::Coercion."; ], [ a doap-changeset:Bugfix, doap-changeset:Tests; rdfs:label "Fix incorrect Test::Requires line in 'mouse-coercion.t'."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.000_10"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.000_11"^^xsd:string; dc:issued "2013-04-11"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "Fix prototype for Type::Utils::as."; ], [ a doap-changeset:Change; rdfs:label "No longer need to pass '-moose' parameter when importing a library into a Moose class; only Mouse needs that treatment now."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.000_11"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.000_12"^^xsd:string; dc:issued "2013-04-12"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Fix minor typo."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.000_12"^^xsd:string. a doap:Version; rdfs:label "First public release"; dc:identifier "Type-Tiny-0.001"^^xsd:string; dc:issued "2013-04-15"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Minor improvements."; ], [ a doap-changeset:Bugfix; rdfs:label "Some inline code assumed that it would be compiled in a package that had 'blessed' imported."; ], [ a doap-changeset:Bugfix; rdfs:label "Some inline code wasn't wrapped in parentheses."; ], [ a doap-changeset:Tests; rdfs:label "More test cases for Optional[`a] within Dict[`a]."; ], [ a doap-changeset:Change; rdfs:label "Weaken the reference from a Moose::Meta::TypeConstraint object to its Type::Tiny origin."; ], [ a doap-changeset:Change; rdfs:label "Parameterized type constraints in Types::Standard now do some sanity checking on their arguments."; ], [ a doap-changeset:Change; rdfs:label "Improve test names generated by Test::TypeTiny; allow test scripts to provide test names."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.001"^^xsd:string. a doap:Version; dc:identifier "Type-Tiny-0.002"^^xsd:string; dc:issued "2013-04-26"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Link from Test::TypeTiny to Test::Deep::Type."; ], [ a doap-changeset:Change; rdfs:label "Avoid unnecessarily regenerating parameterized type constraints."; ], [ a doap-changeset:Change; rdfs:label "Make Type::Tiny's has_coercion method more DWIM."; ], [ a doap-changeset:Addition; rdfs:label "Chars and Bytes types added to Types::Standard."; ], [ a doap-changeset:Bugfix; rdfs:label "Prevent warnings (about 'my $val' masking a previously declared variable) when several Str checks are being inlined in close proximity, such as Tuple[Str,Str]"; ], [ a doap-changeset:Bugfix; rdfs:label "Fix method conflicts when exporting type constraints to roles."; doap-changeset:fixes [ doap-bugs:reporter ; ]; doap-changeset:thanks ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.002"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.003_01"^^xsd:string; dc:issued "2013-04-16"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Link from Test::TypeTiny to Test::Deep::Type."; ], [ a doap-changeset:Change; rdfs:label "Allow a Type::Tiny object to \"freeze\" its coercions. This prevents a Type::Tiny object from becoming out of sync with its equivalent Mouse or Moose constraint objects."; ], [ a doap-changeset:Change; rdfs:label "Type::Library packages can now include \"standalone\" Type::Coercion objects, not attached to a type constraint. These can be exported on request."; ], [ a doap-changeset:Change; rdfs:label "Overload \"+\" operator for Type::Coercion and Type::Tiny allows coercions to be added to each other, and added to type constraints."; ], [ a doap-changeset:Change; rdfs:label "Build coercions automatically for certain type parameterized constraints. Say there's a Num->Int coercion defined; then we should be able to coerce ArrayRef[Num]->ArrayRef[Int]."; ], [ a doap-changeset:Change; rdfs:label "Allow subtypes to inherit coercions from their parent type constraint. (They do not by default.)"; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.003_01"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.003_02"^^xsd:string; dc:issued "2013-04-16"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Document how to process sub parameters with Type::Tiny, and point people towards Type::Params."; ], [ a doap-changeset:Change; rdfs:label "Avoid unnecessarily regenerating parameterized type constraints."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.003_02"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.003_03"^^xsd:string; dc:issued "2013-04-17"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "When inflating Moo type constraints to Moose, don't unnecessarily call 'moose_type' method."; ], [ a doap-changeset:Change; rdfs:label "Make Type::Tiny's has_coercion method more DWIM."; ], [ a doap-changeset:Addition; rdfs:label "Add OptList data type to Types::Standard, plus MkOpt coercion."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.003_03"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.003_04"^^xsd:string; dc:issued "2013-04-18"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Factor out the sub exporting code scattered around (in Type::Utils, Types::TypeTiny and Type::Library) into a single module, Exporter::TypeTiny."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.003_04"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.003_05"^^xsd:string; dc:issued "2013-04-19"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Addition; rdfs:label "Chars and Bytes types added to Types::Standard."; ], [ a doap-changeset:Change; rdfs:label "Allow coercions to accept parameters."; ], [ a doap-changeset:Addition; rdfs:label "Encode, Decode, Join and Split coercions added to Types::Standard."; ], [ a doap-changeset:Bugfix; rdfs:label "Prevent warnings (about 'my $val' masking a previously declared variable) when several Str checks are being inlined in close proximity, such as Tuple[Str,Str]"; ], [ a doap-changeset:Addition; rdfs:label "Type::Tiny::Class now has a plus_constructors method."; ], [ a doap-changeset:Documentation; rdfs:label "Create a new manual page Type::Tiny::Manual::Coercions."; ], [ a doap-changeset:Documentation; rdfs:label "Document Exporter::TypeTiny."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.003_05"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.003_06"^^xsd:string; dc:issued "2013-04-25"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "No longer need to add '-mouse' when importing types into Mouse libraries. (Same change as what we did for Moose in 0.000_11.)"; ], [ a doap-changeset:Documentation; rdfs:label "Add lots of stuff to Type::Tiny::Manual::UsingWithMouse."; ], [ a doap-changeset:Documentation; rdfs:label "Document deep coercions (feature added in 0.003_01)."; ], [ a doap-changeset:Change; rdfs:label "Add a bunch of stub methods to Type::Tiny and Type::Coercion in order to make it less necessary to inflate to Moose/Mouse meta objects."; ], [ a doap-changeset:Change; rdfs:label "Various minor changes to Exporter::TypeTiny to make it more Sub::Exporter compatible."; ], [ a doap-changeset:Change; rdfs:label "Types::TypeTiny::to_TypeTiny can now coerce from a Mouse::Meta::TypeConstraint."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.003_06"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.003_07"^^xsd:string; dc:issued "2013-04-26"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Document usage with Class::InsideOut."; ], [ a doap-changeset:Documentation; rdfs:label "Minor improvements to manual."; ], [ a doap-changeset:Bugfix; rdfs:label "Fix method conflicts when exporting type constraints to roles."; doap-changeset:fixes [ doap-bugs:reporter ; ]; doap-changeset:thanks ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.003_07"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.003_08"^^xsd:string; dc:issued "2013-04-26"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "ASCII-only strings are now accepted by the Chars constraint in Types::Standard."; ], [ a doap-changeset:Documentation; rdfs:label "More Exporter::TypeTiny docs, including usage with Sub::Exporter::Lexical."; ], [ a doap-changeset:Tests; rdfs:label "Add test case using Exporter::TypeTiny with Sub::Exporter::Lexical."; ], [ a doap-changeset:Change; rdfs:label "Type::Tiny, Type::Coercion and their subclasses no longer call Types::TypeTiny->import method."; ], [ a doap-changeset:Change; rdfs:label "Types::TypeTiny lazily loads Exporter::TypeTiny - i.e. it loads Exporter::TypeTiny when Types::TypeTiny->import is first called."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.003_08"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.003_09"^^xsd:string; dc:issued "2013-04-28"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Document usage with Params::Check and Object::Accessor."; ], [ a doap-changeset:Addition; rdfs:label "'Tied' type constraint added to Types::Standard."; ], [ a doap-changeset:Change; rdfs:label "If Mouse is already in memory, Type::Tiny will use its super-fast XS subs to validate values when possible."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.003_09"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.003_10"^^xsd:string; dc:issued "2013-04-29"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Improve Exporter::TypeTiny documentation."; ], [ a doap-changeset:Documentation; rdfs:label "Improve advice on inlining type constraints and coercions."; ], [ a doap-changeset:Packaging; rdfs:label "Bump version of Test::More dependency fom 0.88 to 0.96."; ], [ a doap-changeset:Change; rdfs:label "General code tidy-up."; ], [ a doap-changeset:Addition; rdfs:label "Type::Tiny::SUPPORT_SMARTMATCH constant."; ], [ a doap-changeset:Addition; rdfs:label "New module, Eval::TypeTiny"; ], [ a doap-changeset:Change; rdfs:label "Much of the stringy eval stuff has been factored out into Eval::TypeTiny."; ], [ a doap-changeset:Addition; rdfs:label "Bundle Type::Params, which had previously appeared on CPAN in a separate developer release."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.003_10"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.003_11"^^xsd:string; dc:issued "2013-04-30"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Tests; rdfs:label "Test cases for Eval::TypeTiny."; ], [ rdfs:label "Automatic coercion for parameterized Dict will no longer drop key/value pairs to force a coercion."; doap-changeset:thanks ; rdfs:seeAlso ; ], [ rdfs:label "Automatic coercion for parameterized Tuple will no longer drop values to force a coercion."; doap-changeset:thanks ; rdfs:seeAlso ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.003_11"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.003_12"^^xsd:string; dc:issued "2013-05-01"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Allow people to use Carp::{confess,cluck,carp} with Type::Params validators; default is still croak."; ], [ a doap-changeset:Change; rdfs:label "Improved Type::Params documentation."; ], [ a doap-changeset:Bugfix; rdfs:label "Sane behaviour for Types::Standard's 'slurpy' function when it appears mid-list."; ], [ rdfs:label "Type::Params validators now explicitly check the number of arguments passed to them."; doap-changeset:thanks ; rdfs:seeAlso ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.003_12"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.003_13"^^xsd:string; dc:issued "2013-05-03"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "Don't crash in old versions of Moose that have no Class::MOP::_definition_context() function."; ], [ a doap-changeset:Change; rdfs:label "Better documentation and tests of Moose/Mouse-compatible API."; ], [ a doap-changeset:Tests; rdfs:label "BAIL_OUT in test suite if 00-compile.t or 01-api.t fail."; ], [ a doap-changeset:Documentation; rdfs:label "Fix typo in Type::Params documentation."; doap-changeset:blame ; rdfs:seeAlso ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.003_13"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.003_14"^^xsd:string; dc:issued "2013-05-03"^^xsd:date; doap-changeset:released-by ; doap:file-release ; doap:revision "0.003_14"^^xsd:string; rdfs:comment "No functional changes.". a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.003_15"^^xsd:string; dc:issued "2013-05-03"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Improvements to to_TypeTiny function, including accepting Validation::Class::Simple objects."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.003_15"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.003_16"^^xsd:string; dc:issued "2013-05-05"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Rename Types::Standard::AutomaticCoercion -> Types::Standard::DeepCoercion."; ], [ a doap-changeset:Change; rdfs:label "Type::Params produces nicer error messages."; ], [ a doap-changeset:Documentation; rdfs:label "Document that Map[`k,`v] has a deep coercion."; ], [ a doap-changeset:Documentation; rdfs:label "Improve Type::Coercion documentation."; ], [ a doap-changeset:Change; rdfs:label "Minor updates to coderef overloading following Moo 1.002000 release."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.003_16"^^xsd:string. a doap:Version; dc:identifier "Type-Tiny-0.004"^^xsd:string; dc:issued "2013-05-06"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Minor updates to to_TypeTiny following Validation::Class 7.900048 release."; ], [ a doap-changeset:Bugfix; rdfs:label "Eval::Closure now strips line breaks and other unsavoury characters from descriptions."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.004"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.005_01"^^xsd:string; dc:issued "2013-05-07"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "Type::Library should require Perl 5.8.1, not 5.8.3."; ], [ a doap-changeset:Addition; rdfs:label "ArrayLike type added to Types::TypeTiny."; ], [ a doap-changeset:Addition; rdfs:label "Type::Registry."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.005_01"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.005_02"^^xsd:string; dc:issued "2013-05-14"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Fix a typo in declare_coercion in Type::Tiny::Manual::Coercions."; doap-changeset:blame ; ], [ a doap-changeset:Documentation; rdfs:label "Link to Type::Tiny::Manual::Libraries instead of non-existing Type::Tiny::Intro."; doap-changeset:blame ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.005_02"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.005_03"^^xsd:string; dc:issued "2013-05-14"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Many error conditions now throw exception objects instead of string error messages."; ], [ a doap-changeset:Removal; rdfs:label "Bytes and Chars type constraints removed from Types::Standard."; ], [ a doap-changeset:Removal; rdfs:label "Decode and Encode coercions removed from Types::Standard."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.005_03"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.005_04"^^xsd:string; dc:issued "2013-05-17"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "All error conditions now throw exception objects instead of string error messages."; ], [ a doap-changeset:Change; rdfs:label "Deep explanations for Types::Standard::{Map,Maybe,Ref,Dict,Tuple} type constraint assertion failures."; ], [ a doap-changeset:Change; rdfs:label "Test::TypeTiny performs more thorough testing if EXTENDED_TESTING environment variable is set."; ], [ a doap-changeset:Bugfix; rdfs:label "Fixed bug in non-inlined code for Types::Standard::MkOpt."; ], [ a doap-changeset:Change; rdfs:label "Improved deep explanations for Types::Standard::{ArrayRef,HashRef,ScalarRef}."; ], [ a doap-changeset:Change; rdfs:label "Throw exception if people attempt to set parent types for Type::Tiny::{Class,Role,Duck,Enum,Union,Intersection}."; ], [ a doap-changeset:Addition; rdfs:label "Type::Exception::Compilation."; ], [ a doap-changeset:Change; rdfs:label "Allow the slurpy tail of a Types::Standard::Tuple to be a treated as a hashref rather than an arrayref."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.005_04"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.005_05"^^xsd:string; dc:issued "2013-05-24"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Fix warnings under Perl 5.18."; ], [ a doap-changeset:Documentation; rdfs:label "Suggest newer version of Validation::Class."; ], [ a doap-changeset:Addition; rdfs:label "Type::Tiny now has an assert_return method, which is used in most places in preference to assert_valid."; ], [ a doap-changeset:Removal; rdfs:label "Removed Type::Registry from the release; it will return at a later date."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.005_05"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.005_06"^^xsd:string; dc:issued "2013-05-26"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Fold Types::Standard::DeepCoercion into Types::Standard."; ], [ a doap-changeset:Bugfix; rdfs:label "Fix StrMatch to properly support regexps containing slashes."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.005_06"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.005_07"^^xsd:string; dc:issued "2013-05-28"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Add pure-Perl Mouse to examples/benchmark-constraints.pl."; ], [ a doap-changeset:Bugfix; rdfs:label "Assertions using the assert_return pattern were triggering FATAL warnings when inlined with Sub::Quote. Inlined assertions are now prefixed with 'no warnings \"void\";'."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.005_07"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.005_08"^^xsd:string; dc:issued "2013-05-28"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Tests; rdfs:label "Use JSON::PP instead of JSON in test cases, because JSON::PP is a core module since Perl 5.14."; ], [ a doap-changeset:Tests; rdfs:label "Rearrange test cases"; ], [ a doap-changeset:Tests; rdfs:label "Add 00-begin.t."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.005_08"^^xsd:string. a doap:Version; dc:identifier "Type-Tiny-0.006"^^xsd:string; dc:issued "2013-05-28"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "Exporter::TypeTiny::mkopt_hash now works."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.006"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; rdfs:label "Happy birthday to me..."; dc:identifier "Type-Tiny-0.007_01"^^xsd:string; dc:issued "2013-06-01"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "Fix $VERSION defined in Type::Library."; ], [ a doap-changeset:Change; rdfs:label "Re-introduce Type::Registry, with improved parsing thanks to Type::Parser."; ], [ a doap-changeset:Addition; rdfs:label "Type::Parser."; ], [ a doap-changeset:Addition; rdfs:label "Types::Standard now has LaxNum/StrictNum type constraints."; ], [ a doap-changeset:BackCompat; rdfs:label "Types::Standard's Num constraint is now a subtype of either LaxNum and StrictNum (depending on environment)."; ], [ a doap-changeset:Change; rdfs:label "Implemented Types::TypeTiny->meta->get_type."; ], [ a doap-changeset:Packaging; rdfs:label "Generate README from Type::Tiny::Manual instead of Type::Tiny."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.007_01"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.007_02"^^xsd:string; dc:issued "2013-06-04"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Drop use of Carp in Type::Parser."; ], [ a doap-changeset:Documentation; rdfs:label "Improvements to Type::Tiny::Manual."; ], [ a doap-changeset:Documentation; rdfs:label "Improvements to Type::Tiny::Manual::Params, including rewritten manual processing section, and processing type constraints in function signatures via Function::Parameters/Attribute::Constract."; ], [ a doap-changeset:Tests; rdfs:label "Test cases for usage with Function::Parameters."; ], [ a doap-changeset:Change; rdfs:label "Allow constraint_generators (for parameterizable type constraints) to return full Type::Tiny objects instead of plain coderefs."; ], [ a doap-changeset:Change; rdfs:label "Type::Tiny::Duck types now have a parent type constraint of Types::Standard::Object."; ], [ a doap-changeset:Change; rdfs:label "Type::Tiny::Role types now have a parent type constraint of Types::Standard::Object."; ], [ a doap-changeset:Change; rdfs:label "Type::Tiny::Enum types now have a parent type constraint of Types::Standard::Str."; ], [ a doap-changeset:Change; rdfs:label "Type::Tiny::Class types now have an automatically calculated parent type constraint based on @ISA."; ], [ a doap-changeset:Change; rdfs:label "Type::Tiny::Union types now have an automatically calculated parent type constraint based on the most specific common parent type constraint."; ], [ a doap-changeset:Change; rdfs:label "Type::Tiny::Intersection types now have an arbitrary parent type constraint."; ], [ a doap-changeset:Addition; rdfs:label "New constraints added to Types::Standard: InstanceOf, ConsumerOf, HasMethods and Enum."; doap-changeset:thanks ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.007_02"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.007_03"^^xsd:string; dc:issued "2013-06-08"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Better document Type::Tiny's 'parents' method which differs from the Moose method of the same name."; ], [ a doap-changeset:Bugfix; rdfs:label "Inlining of certain deep Dict, Tuple and Map coercions was broken, but Type::Params attempted to inline them anyway, leading to death."; doap-changeset:fixes ; doap-changeset:thanks ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.007_03"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.007_04"^^xsd:string; dc:issued "2013-06-09"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "The combination of Dict, Optional and coercions seems to have been broken in certain circumstances."; doap-changeset:fixes ; doap-changeset:thanks ; ], [ a doap-changeset:Bugfix; rdfs:label "Overloading of `$type eq $type` now works in Perl 5.8."; doap-changeset:fixes ; doap-changeset:thanks ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.007_04"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.007_05"^^xsd:string; dc:issued "2013-06-12"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Addition; rdfs:label "Add match_on_type and compile_match_on_type to Type::Utils."; ], [ a doap-changeset:Documentation; rdfs:label "Vastly improved documentation for Type::Utils."; ], [ a doap-changeset:Documentation; rdfs:label "Vastly improved documentation for Types::Standard."; ], [ a doap-changeset:Documentation; rdfs:label "Mention Scalar::Does and Type::Tie in manual."; ], [ a doap-changeset:Tests; rdfs:label "Added test cases for InstanceOf, ConsumerOf, HasMethods and Enum types defined by Types::Standard."; ], [ a doap-changeset:Change; rdfs:label "Support '0' and '1' as shortcuts for Optional[Any] and Any in Type::Params. (Not documented yet.)"; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.007_05"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.007_06"^^xsd:string; dc:issued "2013-06-16"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Rearranged documentation for Type::Utils, avoiding previous split into Moose-like and non-Moose-like functions."; ], [ a doap-changeset:Documentation; rdfs:label "Document the evaluation environment used by Eval::TypeTiny."; ], [ a doap-changeset:Addition; rdfs:label "Type::Exception is now capable of supplying stack traces (requires Devel::StackTrace)."; ], [ a doap-changeset:Change; rdfs:label "Exceptions thrown for Moo isa/coerce now indicate which attribute was involved."; ], [ a doap-changeset:BackCompat; rdfs:label "Type::Utils no longer exports 'extends' by default."; ], [ a doap-changeset:BackCompat; rdfs:label "Better prototypes (was `;@`, now `;$`) for parameterizable type 'constants' exported by type libraries."; doap-changeset:thanks ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.007_06"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.007_07"^^xsd:string; dc:issued "2013-06-16"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "Partly roll back prototype changes. Now we use `;$` for Perl since 5.14, but `;@`, for older Perls that don't support `;$` so well."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.007_07"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.007_08"^^xsd:string; dc:issued "2013-06-17"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "Fix problem with interaction between constraints, coercions, and Moose classes that inherit from Moo classes."; doap-changeset:fixes ; doap-changeset:thanks ; ], [ a doap-changeset:Tests; rdfs:label "Bundle test for interaction between constraints, coercions, and Moose classes that inherit from Moo classes."; doap-changeset:blame ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.007_08"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.007_09"^^xsd:string; dc:issued "2013-06-18"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "Fix problems inlining Dict deep coercions where the target constraint could not be inlined."; doap-changeset:fixes ; doap-changeset:thanks ; ], [ a doap-changeset:Bugfix; rdfs:label "Fix unintuitive Dict deep coercions."; doap-changeset:fixes ; doap-changeset:thanks ; ], [ a doap-changeset:Tests; rdfs:label "Bundle various tests for deep Dict coercions."; doap-changeset:blame ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.007_09"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.007_10"^^xsd:string; dc:issued "2013-06-21"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Type::Parser now supports parentheses in its DSL."; ], [ a doap-changeset:Addition; rdfs:label "Type::Parser now exports a _std_eval function useful for testing."; ], [ a doap-changeset:Bugfix; rdfs:label "Fixed many small parsing bugs in Type::Parser."; ], [ a doap-changeset:Change; rdfs:label "Improved error messages from Type::Parser."; ], [ a doap-changeset:Tests; rdfs:label "Add test cases for Type::Parser."; ], [ a doap-changeset:Tests; rdfs:label "Better test cases for Type::Registry."; ], [ a doap-changeset:Documentation; rdfs:label "Document status of Type::Registry."; ], [ a doap-changeset:Bugfix; rdfs:label "MooseX::Types objects used in Type::Tiny::Union, Type::Tiny::Intersection and parameterized Type::Tiny type constraints would break in some circumstances, as Types::TypeTiny::to_TypeTiny was failing to convert them to native Type::Tiny type constraints."; doap-changeset:fixes ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.007_10"^^xsd:string. a doap:Version; dc:identifier "Type-Tiny-0.008"^^xsd:string; dc:issued "2013-06-21"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Updated NEWS file."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.008"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.009_01"^^xsd:string; dc:issued "2013-06-21"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "Fix error messages from type constraints with null constraint coderefs."; ], [ a doap-changeset:Addition; rdfs:label "Reply::Plugin::TypeTiny."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.009_01"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.009_02"^^xsd:string; dc:issued "2013-06-22"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Various minor optimizations for Eval::TypeTiny, Type::Tiny, etc."; ], [ a doap-changeset:Change; rdfs:label "Types::Standard no longer uses Type::Utils."; ], [ a doap-changeset:Bugfix; rdfs:label "Fix for compiled_checks for type constraints inheriting from Type::Tiny::Class, etc."; doap-changeset:fixes ; doap-changeset:thanks ; ], [ a doap-changeset:Regression; rdfs:label "Types::Standard types no longer have 'library' attribute set; this subtly breaks Moo type inflation, and breaks the MooX::late test suite which relies on type inflation working correctly."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.009_02"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.009_03"^^xsd:string; dc:issued "2013-06-22"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "Fix Types::Standard compilation errors under Perl 5.8.x."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.009_03"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.009_04"^^xsd:string; dc:issued "2013-06-23"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "Type::Tiny::Class shouldn't completely trust @ISA when establishing parent class heirarchies."; ], [ a doap-changeset:Change; rdfs:label "Constructors for Type::Tiny subclasses no longer accept the 'constraint' parameter; it doesn't make sense."; ], [ a doap-changeset:Update; rdfs:label "Support Type::API interfaces."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.009_04"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.009_05"^^xsd:string; dc:issued "2013-06-23"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "Type::Registry does the AUTOLOAD thing, so ought to provide a DESTROY method."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.009_05"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.009_06"^^xsd:string; dc:issued "2013-06-23"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "Careful calling the DOES method (it doesn't exist in Perl 5.8)."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.009_06"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.009_07"^^xsd:string; dc:issued "2013-06-24"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Types::Standard::to_TypeTiny now sets 'display_name' instead of 'name' on generated type constraints."; ], [ a doap-changeset:Tests; rdfs:label "More test cases for interacting with MooseX::Types type constraints."; ], [ a doap-changeset:Change; rdfs:label "Type::Params no longer uses Type::Utils."; ], [ a doap-changeset:Change; rdfs:label "Subclasses of Type::Tiny reject 'inlined' coderef, just like they already reject 'constraint' coderef."; ], [ a doap-changeset:Change; rdfs:label "If a Type::Tiny object is instantiated with a Sub::Quote quoted constraint coderef, and no inlined coderef, then Type::Tiny will use Sub::Quote to make an inlined coderef."; ], [ a doap-changeset:Tests; rdfs:label "Make rt86172.t an 'xt' test case because it's causing random CPAN testers failures unrelated to the feature it's supposed to be testing."; rdfs:seeAlso ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.009_07"^^xsd:string. a doap:Version; dc:identifier "Type-Tiny-0.010"^^xsd:string; dc:issued "2013-06-24"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Updated NEWS file."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.010"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.011_01"^^xsd:string; dc:issued "2013-06-25"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "Unions of Type::Tiny and Mouse::Meta::TypeConstraints now work properly. This makes Type::Tiny and MouseX::Types play nice together (much like Type::Tiny already plays nice with MooseX::Types)."; ], [ a doap-changeset:Change; rdfs:label "Cleanups within Type::Coercion. Necessary because in some places the entire type_coercion_map (including conversion coderefs) was passed through Types::Standard::to_TypeTiny, when really only the type constraints should have been."; ], [ a doap-changeset:Change; rdfs:label "Types::Standard::to_TypeTiny now accepts any object implementing the Type::API::Constraint or Type::API::Constraint::Coercion interfaces. As Mouse::Meta::TypeConstraint implements this interface, specific support for importing Mouse types has been dropped; the generic Type::API import 'just works' for Mouse types."; ], [ a doap-changeset:Change; rdfs:label "Types::Standard::to_TypeTiny now accepts unblessed coderefs and converts them to type constraints. This allows things like `Int & sub { $_ < 10 }` to work."; ], [ a doap-changeset:Bugfix; rdfs:label "B::SPECIAL-related fix."; doap-changeset:fixes ; doap-changeset:thanks ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.011_01"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.011_02"^^xsd:string; dc:issued "2013-06-25"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "Types::Standard 0.009_02 stopped including 'library' attribute in its types, and thus broke MooX::late. Type::Library modified to make 'library' attribute more automatic, and less reliant on Type::Utils to do the right thing."; doap-changeset:thanks ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.011_02"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.011_03"^^xsd:string; dc:issued "2013-06-25"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "Type::Tiny now overloads `cmp`. Necessary because Mouse does a sort on type constraints in a union, and overload's fallback doesn't seem to cover `cmp` on Perl prior to 5.12."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.011_03"^^xsd:string. a doap:Version; dc:identifier "Type-Tiny-0.012"^^xsd:string; dc:issued "2013-06-25"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Updated NEWS file."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.012"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.013_01"^^xsd:string; dc:issued "2013-06-27"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Type::Parser's tokenization is now done on a pull basis, allowing one-pass building of the AST."; ], [ a doap-changeset:BackCompat; rdfs:label "Type::Parser no longer provides a `tokens` function as it no longer pre-emptively tokenizes the whole string it is given."; ], [ a doap-changeset:BackCompat; rdfs:label "Type::Parser functions no longer accept an arrayref of tokens, as they expect to pull tokens from a stream as required."; ], [ a doap-changeset:Addition; rdfs:label "Type::Parser now provides a `extract_type` function which parses a type constraint expression from the head of a string and returns a Type::Tiny object, plus the tail of the string. (This is designed to make it easier to use Type::Parser to parse things like function signatures.)"; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.013_01"^^xsd:string. a doap:Version; dc:identifier "Type-Tiny-0.014"^^xsd:string; dc:issued "2013-06-28"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Updated NEWS file."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.014"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.015_01"^^xsd:string; dc:issued "2013-07-05"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Type::Parser can now pull in types from MooseX::Types libraries properly."; ], [ a doap-changeset:Addition; rdfs:label "Type::Utils now provides a `dwim_type` function; this is powered by a hidden Type::Registry::DWIM package."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.015_01"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.015_02"^^xsd:string; dc:issued "2013-07-06"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Improvements to DWIMness of Type::Parser for the benefit of `dwim_type`."; ], [ a doap-changeset:Change; rdfs:label "Better test cases for `dwim_type`."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.015_02"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.015_03"^^xsd:string; dc:issued "2013-07-08"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "The `dwim_type` function now prioritizes lookups within the caller class' type registry over Types::Standard's built-in types."; ], [ a doap-changeset:Change; rdfs:label "Slight speed improvements for `compile_match_on_type`."; ], [ a doap-changeset:Addition; rdfs:label "Implement TIESCALAR, TIEARRAY and TIEHASH methods for Type::Tiny; this improves Type::Tie integration."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.015_03"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.015_04"^^xsd:string; dc:issued "2013-07-13"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Mention in Type::Tiny::Manual::Libraries that the `extends` function is no longer exported by default; update example code."; doap-changeset:blame ; doap-changeset:fixes , ; rdfs:seeAlso ; ], [ rdfs:label "Allow an inline_as block to return a list of strings (which are implictly joined with &&); allow the first item on the list to be undef, which is treated as the inlined parent type constraint."; doap-changeset:fixes ; doap-changeset:thanks ; ], [ a doap-changeset:Documentation; rdfs:label "Clarify when inlining via Sub::Quote may be less efficient than hand-written inlining."; doap-changeset:fixes ; doap-changeset:thanks ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.015_04"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.015_05"^^xsd:string; dc:issued "2013-07-15"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Packaging; rdfs:label "Experimentally drop required version of Perl from 5.8.1 to 5.6.1. I've not been able to extensively test Type-Tiny on Perl 5.6.x, but I believe it should mostly work. (The only feature that seems unlikely to work is non-ASCII names for type constraints and coercions.)"; ], [ a doap-changeset:Change; rdfs:label "Stop monkey-patching Moose::Meta::TypeContraint; it's not necessary and has never been documented."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.015_05"^^xsd:string. a doap:Version; dc:identifier "Type-Tiny-0.016"^^xsd:string; dc:issued "2013-07-16"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Add some pod links."; ], [ a doap-changeset:Documentation; rdfs:label "Updated NEWS file."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.016"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.017_01"^^xsd:string; dc:issued "2013-07-19"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Update; rdfs:label "Eval::TypeTiny now supports lexical subs under Perl 5.18."; ], [ a doap-changeset:Documentation; rdfs:label "Give an example of the default error messages thrown by Type::Tiny."; ], [ a doap-changeset:Bugfix; rdfs:label "Work around lack of B::perlstring() function in Perl 5.6.x."; ], [ a doap-changeset:Documentation; rdfs:label "Improve examples of custom type constraint error message in Type::Utils and Type::Tiny::Manual::Libraries."; doap-changeset:fixes ; doap-changeset:thanks ; ], [ a doap-changeset:Documentation; rdfs:label "Fix typo in Types::Standard 'regular exception' -> 'regular expression'."; doap-changeset:blame ; doap-changeset:fixes ; rdfs:seeAlso ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.017_01"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.017_02"^^xsd:string; dc:issued "2013-07-20"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Hopefully improved workaround for missing B::perlstring() using Data::Dumper instead of quotemeta()."; doap-changeset:thanks ; ], [ a doap-changeset:Bugfix; rdfs:label "Further changes for Perl 5.6.x support."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.017_02"^^xsd:string. a doap:Version; dc:identifier "Type-Tiny-0.018"^^xsd:string; dc:issued "2013-07-21"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Updated NEWS file."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.018"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.019_01"^^xsd:string; dc:issued "2013-07-23"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "Work around lack of B::perlstring() function in Perl 5.6.x in test suite."; ], [ a doap-changeset:Bugfix; rdfs:label "Eval::TypeTiny now closes over variables properly."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.019_01"^^xsd:string. a doap:Version; dc:identifier "Type-Tiny-0.020"^^xsd:string; dc:issued "2013-07-23"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Updated NEWS file."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.020"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.021_01"^^xsd:string; dc:issued "2013-07-24"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Addition; rdfs:label "Type::Tiny strictly_equals method."; ], [ a doap-changeset:Addition; rdfs:label "Type::Tiny is_strictly_subtype_of method."; ], [ a doap-changeset:Addition; rdfs:label "Type::Tiny is_strictly_supertype_of method."; ], [ a doap-changeset:Addition; rdfs:label "Type::Tiny is_strictly_a_type_of method."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.021_01"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.021_02"^^xsd:string; dc:issued "2013-07-26"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Use real lexicals again for Eval::TypeTiny; this requires Devel::LexAlias, but there's a fallback to using tied variables."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.021_02"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.021_03"^^xsd:string; dc:issued "2013-07-30"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Restore Eval::TypeTiny's pre-0.019_01 behaviour re closing over lexicals, but enable the 0.021_02 behaviour if alias=>1 option is passed in."; ], [ a doap-changeset:Change; rdfs:label "Improve compatibility between Type::Tiny and Moose attribute native traits."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.021_03"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.021_04"^^xsd:string; dc:issued "2013-07-30"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "Fix Type::Parser's handling of numeric parameters; they shouldn't need quoting."; ], [ a doap-changeset:Packaging; rdfs:label "Add dependency on Exporter 5.57 for older versions of Perl."; ], [ a doap-changeset:Bugfix; rdfs:label "Fix Types::Standard::Dict differentiating between undef and not exists."; doap-changeset:fixes ; doap-changeset:thanks ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.021_04"^^xsd:string. a doap:Version; dc:identifier "Type-Tiny-0.022"^^xsd:string; dc:issued "2013-08-06"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "In Devel::TypeTiny::Perl56Compat, `use strict` and `use warnings`."; ], [ a doap-changeset:Change; rdfs:label "Improved implementations of is_subtype_of/is_strictly_subtype_of; better for subclassing."; ], [ a doap-changeset:Documentation; rdfs:label "Updated NEWS file."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.022"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.023_01"^^xsd:string; dc:issued "2013-08-16"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "Fix Moo -> Moose type inflation issue."; doap-changeset:thanks ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.023_01"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.023_02"^^xsd:string; dc:issued "2013-08-23"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Addition; rdfs:label "Type::Registry now has an `add_type` method, for adding a single type constraint to a registry."; ], [ a doap-changeset:Change; rdfs:label "Type::Registry's `add_types` method now supports importing MooseX::Types and MouseX::Types libraries."; ], [ a doap-changeset:Change; rdfs:label "Type::Utils' `extend` function now supports extending MooseX::Types and MouseX::Types libraries."; ], [ a doap-changeset:Bugfix; rdfs:label "Fix quoting in error messages which caused Type::Params to be unable to compile some coderefs."; doap-changeset:fixes ; doap-changeset:thanks ; ], [ a doap-changeset:Bugfix; rdfs:label "Improve ugly type assertion failure messages when given structures of nested references."; doap-changeset:fixes ; doap-changeset:thanks ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.023_02"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.023_03"^^xsd:string; dc:issued "2013-08-23"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "Constructors for some subclasses of Type::Tiny rejected hashrefs of paramaters."; doap-changeset:fixes ; doap-changeset:thanks ; ], [ a doap-changeset:Change; rdfs:label "Implementation of RegexpRef in Types::Standard is now closer to Moose's implementation (accepts blessed Regexps)."; ], [ a doap-changeset:Bugfix; rdfs:label "Stop considering the empty string to be a valid package name."; ], [ a doap-changeset:Tests; rdfs:label "Include additional test cases stolen from Moose."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.023_03"^^xsd:string. a doap:Version; dc:identifier "Type-Tiny-0.024"^^xsd:string; dc:issued "2013-08-27"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Updated NEWS file."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.024"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.025_01"^^xsd:string; dc:issued "2013-09-02"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "The Tuple structured type was treating arrays with missing required elements as if they were present but undef."; doap-changeset:fixes ; doap-changeset:thanks ; ], [ a doap-changeset:Change; rdfs:label "Make Exporter::TypeTiny support generators with less internals-hacking."; ], [ a doap-changeset:Documentation; rdfs:label "Document the internals of Exporter::TypeTiny."; ], [ a doap-changeset:Change; rdfs:label "Exporter::TypeTiny will now use method-style resolution when searching for a sub to export."; ], [ a doap-changeset:Packaging; rdfs:label "use Dist-Inkt"; ], [ a doap-changeset:Packaging; rdfs:label "Take advantage of dynamic_config to ask automated testers to test Type::Tiny with Moose present, but only if the Type::Tiny version number includes an underscore."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.025_01"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.025_02"^^xsd:string; dc:issued "2013-09-02"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Addition; rdfs:label "Type::Params now provides a multisig() function, allowing you to define multiple function signatures, and attempt to validate @_ against them each in turn."; doap-changeset:fixes ; doap-changeset:thanks ; ], [ a doap-changeset:Bugfix, doap-changeset:Tests; rdfs:label "functionparameters.t now requires Moo or Moose and is skipped otherwise."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.025_02"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.025_03"^^xsd:string; dc:issued "2013-09-04"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Document that multisig() accepts coderefs."; ], [ a doap-changeset:Packaging; rdfs:label "Use a newer version of RDF::DOAP to process this changelog."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.025_03"^^xsd:string. a doap:Version; dc:identifier "Type-Tiny-0.026"^^xsd:string; dc:issued "2013-09-05"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Updated NEWS file."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.026"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.027_01"^^xsd:string; dc:issued "2013-09-07"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "Fixed some memory leaks. Still some work to do in this area."; ], [ a doap-changeset:Regression; rdfs:label "Weakening various references to fix memory leaks led to breaking Type::Tiny -> Moose -> Type::Tiny round-tripping via Types::TypeTiny::to_TypeTiny. Test cases for this marked TODO."; ], [ rdfs:label "Added `coercibles` method to Type::Tiny."; doap-changeset:thanks ; rdfs:seeAlso ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.027_01"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.027_02"^^xsd:string; dc:issued "2013-09-08"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "Restore Type::Tiny -> Moose -> Type::Tiny round-tripping broken in previous release."; ], [ a doap-changeset:Documentation; rdfs:label "In Type::Tiny::Manual::Coercions, explain how to chain coercions."; rdfs:seeAlso ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.027_02"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.027_03"^^xsd:string; dc:issued "2013-09-09"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Tests, doap-changeset:Update; rdfs:label "Fix the ultra-finicky t/02-api.t to cope with changes to Moose::Meta::TypeConstraint API in Moose 2.1100."; ], [ a doap-changeset:Bugfix; rdfs:label "Prevent Eval::TypeTiny from leaking stashes by recycling the sandbox."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.027_03"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.027_04"^^xsd:string; dc:issued "2013-09-09"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Tests, doap-changeset:Update; rdfs:label "The file t/moose-coercion.t was checking a particular Moose warning message. In Moose 2.1100, this warning has been upgraded to an exception. For now, disable that particular check."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.027_04"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.027_05"^^xsd:string; dc:issued "2013-09-15"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Include a detailed explanation in the stringification of Type::Exception::Assertion."; ], [ a doap-changeset:Change; rdfs:label "Refactor the explanation generation mechanism."; ], [ a doap-changeset:Addition; rdfs:label "Provide a `validate_explain` method as part of Type::Tiny's public API."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.027_05"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.027_06"^^xsd:string; dc:issued "2013-09-18"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Addition; rdfs:label "Override `validate_explain` in all the bundled subclasses of Type::Tiny."; ], [ a doap-changeset:Change; rdfs:label "Memoize Types::TypeTiny::to_TypeTiny."; ], [ a doap-changeset:Addition; rdfs:label "Type::Tiny::Union now provides a `find_type_for` method which should be compatible with Moose's equivalent method."; ], [ a doap-changeset:Change; rdfs:label "Type::Tiny::Union's compiled checks no longer close over the type constraints which are in the union."; ], [ a doap-changeset:Addition; rdfs:label "Type::Utils now provides an `english_list` function like Moose::Util does. This was useful internally for implementing `validate_explain` methods."; ], [ a doap-changeset:Documentation; rdfs:label "Add a draft Stability Policy to Type::Tiny::Manual."; ], [ a doap-changeset:Change; rdfs:label "Loosen the rules for Type::Tiny and Type::Coercion name attributes; allow them to begin with one or two leading underscores."; ], [ a doap-changeset:Change; rdfs:label "Types::TypeTiny::to_TypeTiny now uses Type::Coercion::FromMoose to ensure Moose type constraints converted to Type::Tiny constraints retain their coercions."; ], [ a doap-changeset:Addition; rdfs:label "Type::Coercion::FromMoose"; ], [ a doap-changeset:Change; rdfs:label "Stop using base.pm."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.027_06"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.027_07"^^xsd:string; dc:issued "2013-09-18"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Also ensure Mouse type constraints converted to Type::Tiny constraints retain their coercions."; ], [ a doap-changeset:Bugfix; rdfs:label "Fix missing version number in Type::Coercion::FromMoose"; ], [ a doap-changeset:Tests; rdfs:label "Changes to version numbers reported by 00-begin.t."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.027_07"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.027_08"^^xsd:string; dc:issued "2013-09-19"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Explicitly overload boolification (always true!) in Type::Exception."; ], [ a doap-changeset:Bugfix; rdfs:label "Type::Exception::Assertion changes from 0.027_05 are now conditional upon Perl version; only take effect on Perl 5.8+; they just weren't working on Perl 5.6."; ], [ a doap-changeset:Tests; rdfs:label "More changes to version numbers reported by 00-begin.t."; ], [ a doap-changeset:Bugfix, doap-changeset:Documentation; rdfs:label "Fix typo in changelog for previous developer release."; ], [ a doap-changeset:Bugfix, doap-changeset:Documentation; rdfs:label "Fix typo in Type::Utils for coerce=>1 --> coercion=>1."; doap-changeset:fixes ; doap-changeset:thanks ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.027_08"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.027_09"^^xsd:string; dc:issued "2013-09-20"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "Fix whitespace in error messages."; ], [ a doap-changeset:Tests; rdfs:label "Skip leak.t on Perl 5.10.0."; ], [ a doap-changeset:Regression; rdfs:label "Inlining of type checks in Moo broken in this release, or hereabouts. Fixed in 0.029_04."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.027_09"^^xsd:string. a doap:Version; dc:identifier "Type-Tiny-0.028"^^xsd:string; dc:issued "2013-09-26"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Updated NEWS file."; ], [ a doap-changeset:Documentation; rdfs:label "Note in documentation for Type::Tiny::Union, etc that constraint/inlining coderefs not only should not be provided to the constructor, but cannot!"; doap-changeset:fixes ; doap-changeset:thanks ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.028"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.029_01"^^xsd:string; dc:issued "2013-09-26"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Replace Exporter::TypeTiny with Exporter::Tiny (an external dependency)."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:branch "exporter-tiny"; doap:file-release ; doap:revision "0.029_01"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.029_02"^^xsd:string; dc:issued "2013-10-11"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:BackCompat; rdfs:label "Renamed the Type::Exception modules to Error::TypeTiny."; doap-changeset:fixes ; doap-changeset:thanks ; ], [ rdfs:label "Type::Tiny::Enum type constraints are now subtypes of Types::Standard::Str; not Types::Standard::Defined."; doap-changeset:thanks ; ], [ rdfs:label "Types::Standard::Item is now a subtype of not Types::Standard::Any."; doap-changeset:thanks ; ], [ a doap-changeset:Documentation; rdfs:label "Fix typos in documentation of Error::TypeTiny package variables."; ], [ rdfs:label "$Type::Tiny::DD package variable can now be used for a pluggable data dumper coderef."; doap-changeset:fixes ; doap-changeset:thanks ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:branch "master"; doap:file-release ; doap:revision "0.029_02"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.029_03"^^xsd:string; dc:issued "2013-10-17"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "Older versions of Scalar::Util::looks_like_number return true for undef; work around them."; ], [ a doap-changeset:Bugfix; rdfs:label "Fix segfault on Perl 5.8.1 to 5.8.3. (And possibly some other 5.8.x Perls.) Caused by the combination of eval and goto."; doap-changeset:thanks , , ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.029_03"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.029_04"^^xsd:string; dc:issued "2013-10-17"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "Fix validate_explain error messages in Type::Tiny::Union."; doap-changeset:fixes ; doap-changeset:thanks ; ], [ rdfs:label "$Type::Tiny::DD can be set numerically."; doap-changeset:fixes ; doap-changeset:thanks ; ], [ a doap-changeset:Bugfix; rdfs:label "Fix inlining of type checks in Moo which was broken around about version 0.027_09."; ], [ rdfs:label "Improve error messages under Moo."; doap-changeset:fixes ; doap-changeset:thanks ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.029_04"^^xsd:string. a doap:Version; dc:identifier "Type-Tiny-0.030"^^xsd:string; dc:issued "2013-10-18"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Tests; rdfs:label "Skip leak.t on Perl < 5.10.1. Type-Tiny does have some memory leaks in particular older versions of Perl: 5.8.8 and 5.10.0 are known to be problematic, but 5.8.9 seems fine. Ultimately it would be nice to get these fixed, but in the mean time skipping the test case makes the distribution easier to install."; ], [ a doap-changeset:Documentation; rdfs:label "Updated NEWS file."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.030"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.031_01"^^xsd:string; dc:issued "2013-10-28"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Tests; rdfs:label "Adjustments to cope with newer Moose is-class-loaded heuristics."; ], [ a doap-changeset:Tests; rdfs:label "Check Moose exception objects with isa rather than regexp matching."; ], [ a doap-changeset:Documentation; rdfs:label "Improved documentation for Types::TypeTiny."; ], [ a doap-changeset:Bugfix; rdfs:label "Differentiate Tuple[] vs Tuple, and Dict[] vs Dict."; doap-changeset:fixes ; doap-changeset:thanks ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.031_01"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.031_02"^^xsd:string; dc:issued "2013-11-03"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Type::Parser now differentiates between Tuple[] and Tuple too."; ], [ a doap-changeset:Change; rdfs:label "Type::Parser only treats a comma as an operator within a parameterization now, and is thus now able to parse types from the head of a string which is a comma-separated list of types."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.031_02"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.031_03"^^xsd:string; dc:issued "2013-11-03"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Addition; rdfs:label "Deep coercions for Maybe[`a]."; doap-changeset:fixes ; doap-changeset:thanks ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.031_03"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.031_04"^^xsd:string; dc:issued "2013-11-03"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "Type::Parser 0.031_02 introduced a bug under Perl 5.6.x where we relied on the existence (or not) of a hash item being affected by `local`; this was implemented in Perl 5.8.0. Work around this problem by checking definedness instead."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.031_04"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.031_05"^^xsd:string; dc:issued "2013-11-04"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Fix minor typo."; doap-changeset:blame ; ], [ a doap-changeset:Change; rdfs:label "Allow Dict to take a slurpy parameter - a la Dict[foo => Int, slurpy HashRef[Num]]."; doap-changeset:thanks ; rdfs:comment "This was Matt S Trout's idea."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.031_05"^^xsd:string. a doap:Version; rdfs:label "Remember, remember the fifth of November"; dc:identifier "Type-Tiny-0.032"^^xsd:string; dc:issued "2013-11-05"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Updated NEWS file."; ], [ a doap-changeset:Bugfix; rdfs:label "Eliminate a warning under Perl 5.6.x."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.032"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.033_01"^^xsd:string; dc:issued "2013-11-07"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Addition; rdfs:label "Types::Common::Numeric"; ], [ a doap-changeset:Addition; rdfs:label "Types::Common::String"; ], [ a doap-changeset:Tests; rdfs:label "Test case using a Type::Params compiled check within the scope of a read-only $_ variable."; doap-changeset:blame ; ], [ a doap-changeset:Bugfix; rdfs:label "Type::Params now localizes $_ before trying to assign anything to it."; doap-changeset:fixes ; doap-changeset:thanks ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.033_01"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.033_02"^^xsd:string; dc:issued "2013-11-26"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Split out some of the longer parts of Types::Standard into other modules that will be loaded on demand; this shaves about 20% off the load time of Types::Standard."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:branch "ts-optimization"; doap:file-release ; doap:revision "0.033_02"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.033_03"^^xsd:string; dc:issued "2013-11-26"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Packaging; rdfs:label "Recommend Sub::Name in META.json."; ], [ a doap-changeset:Bugfix; rdfs:label "Fix bug in Type::Params::multisig with regard to slurpy parameters."; doap-changeset:fixes ; doap-changeset:thanks ; ], [ a doap-changeset:Documentation; rdfs:label "Make Error::TypeTiny::Assertion's explain method act more according to documentation."; doap-changeset:fixes ; doap-changeset:thanks ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.033_03"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.033_04"^^xsd:string; dc:issued "2013-12-06"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Implement coercion_names, get_coercion, has_coercion, and has_type methods for Types::TypeTiny, to make it more like a real Type::Library type library."; ], [ rdfs:label "The `extends` function from Type::Utils now allows inheritance of coercions, not just types."; doap-changeset:fixes ; doap-changeset:thanks ; ], [ a doap-changeset:Tests; rdfs:label "Further tests related to RT#90096."; doap-changeset:thanks ; rdfs:seeAlso ; ]; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.033_04"^^xsd:string. a doap:Version; dc:identifier "Type-Tiny-0.034"^^xsd:string; dc:issued "2013-12-09"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Updated NEWS file."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.034"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.035_01"^^xsd:string; dc:issued "2013-12-17"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ rdfs:label "Make parameterized Dict and Map type constraints work with Moose native hash attribute trait."; doap-changeset:thanks ; ], [ rdfs:label "Make Type::Parser work with newer versions of MooseX::Types::Common which uses namespace::autoclean."; doap-changeset:fixes ; doap-changeset:thanks ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.035_01"^^xsd:string. a doap:Version; dc:identifier "Type-Tiny-0.036"^^xsd:string; dc:issued "2013-12-21"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Updated NEWS file."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.036"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.037_01"^^xsd:string; dc:issued "2013-12-24"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "Fix a Type::Params/B problem on Perl 5.6.x."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.037_01"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.037_02"^^xsd:string; dc:issued "2013-12-29"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Link to the Type::Tiny stability policy from the pod of each module it covers."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.037_02"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.037_03"^^xsd:string; dc:issued "2013-12-30"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Tests; rdfs:label "Skip leak.t on threaded Perls (for now)."; ], [ a doap-changeset:Bugfix; rdfs:label "Fix problems with Moo::HandleMoose integration on threaded Perls."; doap-changeset:thanks , , ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.037_03"^^xsd:string. a doap:Version; dc:identifier "Type-Tiny-0.038"^^xsd:string; dc:issued "2014-01-01"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Updated NEWS file."; ], [ a doap-changeset:Documentation; rdfs:label "Copyright 2014."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.038"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.039_01"^^xsd:string; dc:issued "2014-01-21"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "The preferred IRC channel for support is now #moops."; ], [ a doap-changeset:Removal; rdfs:label "Exporter::TypeTiny."; ], [ a doap-changeset:Tests; rdfs:label "Restructure the 't' directory."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.039_01"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.039_02"^^xsd:string; dc:issued "2014-01-25"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Tests; rdfs:label "Add tests for Test::TypeTiny."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.039_02"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.039_03"^^xsd:string; dc:issued "2014-02-05"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "Make Type::Utils::declare_coercion work outside type libraries."; doap-changeset:fixes ; doap-changeset:thanks ; ], [ a doap-changeset:Bugfix; rdfs:label "Weak reference from Type::Coercion objects to target type constraint caused bad behaviour in some cases. This has been fixed by retaining enough information within the Type::Coercion to be able to reconstruct its type constraint if it disappears due to the reference count falling to zero."; doap-changeset:fixes ; doap-changeset:thanks ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.039_03"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.039_04"^^xsd:string; dc:issued "2014-02-05"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ rdfs:label "Make overloaded ops on parameterized type constraints work more consistently between Perl above and below 5.14, reducing the need for parenthesizing complex type constraint expresssions."; doap-changeset:blame ; rdfs:seeAlso ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.039_04"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.039_05"^^xsd:string; dc:issued "2014-02-15"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Apply the Type::Tiny::_HalfOp trick to overloaded addition too."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.039_05"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.039_06"^^xsd:string; dc:issued "2014-02-17"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "Type::Tiny's TIEARRAY and TIEHASH methods were broken; fixed now."; ], [ a doap-changeset:Bugfix; rdfs:label "Type::Tiny's SUPPORT_SMARTMATCH constant was broken; fixed now."; ], [ a doap-changeset:Tests; rdfs:label "Test integration with match::simple."; ], [ a doap-changeset:Tests; rdfs:label "Test integration with Type::Tie."; ], [ a doap-changeset:Tests; rdfs:label "Test integration with Return::Type."; ], [ a doap-changeset:Tests; rdfs:label "Enable some old tests that had been disabled as not-yet-implemented for parameterized type constraints; the feature they test was implemented ages ago."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.039_06"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.039_07"^^xsd:string; dc:issued "2014-02-17"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix, doap-changeset:Tests; rdfs:label "Fix hash ordering bug in Return::Type integration tests."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.039_07"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.039_08"^^xsd:string; dc:issued "2014-02-24"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Tests; rdfs:label "Test integration with Kavorka."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.039_08"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.039_09"^^xsd:string; dc:issued "2014-02-25"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Update Type::Tiny::Manual::Params to mention Kavorka, and newer features of Function::Parameters."; ], [ a doap-changeset:Tests; rdfs:label "Test integration with Moops."; ], [ a doap-changeset:Tests; rdfs:label "Test integration with Switcheroo."; ], [ a doap-changeset:Tests; rdfs:label "Test that coercions attached to Moose type constraints get inherited by Type::Tiny when they are inhaled."; ], [ a doap-changeset:Tests; rdfs:label "Unit tests for Devel::TypeTiny::Perl56Compat."; ], [ a doap-changeset:Tests; rdfs:label "Unit tests for Devel::TypeTiny::Perl58Compat."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.039_09"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.039_10"^^xsd:string; dc:issued "2014-03-10"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Document the benefits of freezing coercions, and of defining coercions either within the type library, or via $type->plus_coercions."; ], [ a doap-changeset:Change; rdfs:label "$type->plus_coercions and friends now return objects with frozen coercions."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.039_10"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.039_11"^^xsd:string; dc:issued "2014-03-11"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Tests; rdfs:label "Because of changes to Data::Dumper in Perl 5.19.x, the test suite was previously skipping some Dumper-based test cases depending on Perl version. However, Dumper is dual-lifed, so older versions of Perl may have shiny, new Dumpers. Skip test cases based on Data::Dumper version instead."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.039_11"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.039_12"^^xsd:string; dc:issued "2014-03-12"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "Various Type::Utils functions were trying to dereference undef as a hash or array in certain circumstances."; doap-changeset:thanks ; ], [ a doap-changeset:Change; rdfs:label "Type::Utils' class_type and role_type functions will $name =~ s/:://g."; doap-changeset:thanks ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.039_12"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.039_13"^^xsd:string; dc:issued "2014-03-15"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Tests; rdfs:label "Test for occasional segfaults on threaded Perl 5.18.x."; doap-changeset:blame ; ], [ a doap-changeset:Bugfix; rdfs:label "Fix occasional segfaults on threaded Perl 5.18.x."; doap-changeset:blame ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.039_13"^^xsd:string. a doap:Version; dc:identifier "Type-Tiny-0.040"^^xsd:string; dc:issued "2014-03-17"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Updated NEWS file."; ], [ a doap-changeset:Documentation; rdfs:label "Refreshed SEE ALSO section of Type::Tiny::Manual::Libraries."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.040"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.041_01"^^xsd:string; dc:issued "2014-03-17"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:BackCompat; rdfs:label "Type::Tiny and Type::Coercion no longer overload addition. This feature never really worked very well with regard to precendence, requiring lot of parentheses to use. The overload also made solving the parameterizable type coercion problem very difficult."; ], [ a doap-changeset:Change; rdfs:label "Parameterizable coercions are now passed a reference to the type constraint they should target."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.041_01"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.041_02"^^xsd:string; dc:issued "2014-03-26"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Type::Tiny::Manual links to various parts of the test suite to document concepts. These links had grown stale and have now been updated."; ], [ a doap-changeset:Tests; rdfs:label "Prevent 20-unit/Type-Registry/moosextypes.t from failing due to too old MooseX::Types::Common - just skip the test script if MXTC is older than 0.001004."; ], [ a doap-changeset:Documentation; rdfs:label "Updated NEWS file."; ], [ a doap-changeset:Bugfix; rdfs:label "Fix Type::Tiny::Duck's inlining of code when given the variable name `$_`."; doap-changeset:fixes ; doap-changeset:thanks ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.041_02"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.041_03"^^xsd:string; dc:issued "2014-03-28"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Improve documentation for the Type::Tiny class; especially its constructor, attributes and methods."; ], [ a doap-changeset:Documentation; rdfs:label "Improve documentation for the Type::Coercion class; especially its constructors, attributes and methods."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.041_03"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.041_04"^^xsd:string; dc:issued "2014-03-31"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Tests; rdfs:label "Add tests for given/when matching against type constraints."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.041_04"^^xsd:string. a doap:Version; dc:identifier "Type-Tiny-0.042"^^xsd:string; dc:issued "2014-04-02"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "List currently unstable/experimental parts of the distribution in Type::Tiny::Manual::Policies."; ], [ a doap-changeset:Documentation; rdfs:label "Include more recent results in benchmarking example scripts."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.042"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.043_01"^^xsd:string; dc:issued "2014-04-06"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Sub::Quote quoted coderefs passed to to_TypeTiny() now result in inlinable type constraints."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.043_01"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.043_02"^^xsd:string; dc:issued "2014-04-11"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Addition; rdfs:label "Experimental my_methods attribute so that type constraints can offer additional methods."; ], [ a doap-changeset:Addition; rdfs:label "Type::Tiny now has a find_parent method."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.043_02"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.043_03"^^xsd:string; dc:issued "2014-05-06"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Addition; rdfs:label "Type::Utils::classifier"; ], [ a doap-changeset:Documentation; rdfs:label "Rename Types::Datetime to Example::Types because there is now really a Types::DateTime on CPAN."; ], [ a doap-changeset:Addition; rdfs:label "Extremely experimental and mostly undocumented my_method stuff."; ], [ a doap-changeset:Tests; rdfs:label "Improve Eval::TypeTiny test cases."; ], [ a doap-changeset:Packaging; rdfs:label "Updated bundled version of Try::Tiny."; ], [ a doap-changeset:Tests; rdfs:label "Tests for Type::Library error messages."; ], [ a doap-changeset:Tests; rdfs:label "Add some test cases for the Error::TypeTiny class."; ], [ a doap-changeset:Documentation; rdfs:label "Type::Tiny::Manual::Libraries add example of using the custom types library."; doap-changeset:blame ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.043_03"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.043_04"^^xsd:string; dc:issued "2014-05-21"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Tests; rdfs:label "Improve test cases for integration with Moose native attribute traits."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.043_04"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.043_05"^^xsd:string; dc:issued "2014-05-21"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Tests; rdfs:label "Integration tests for MooseX::Getopt."; doap-changeset:blame ; ], [ a doap-changeset:Bugfix; rdfs:label "Fix inflation of Type::Coercion objects to Moose::Meta::TypeCoercion when some of the coercion routines are given as strings."; doap-changeset:fixes [ a doap-bugs:Issue; rdfs:label "Inflation of Type::Coercion objects to Moose::Meta::TypeCoercion is sometimes broken."; doap-bugs:reporter ; ]; ], [ a doap-changeset:Change; rdfs:label "No longer need to inflate a Type::Tiny object to Moose::Meta::TypeConstraint in order to give an answer to $type->isa('Moose::Meta::TypeConstraint::Union')."; rdfs:comment "Inflation to Moose::Meta::TypeConstraint is a last resort."; ], [ a doap-changeset:Change; rdfs:label "Detect missing comma in declaration of type constraints using Type::Utils a la `declare Foo as Bar`, and print a warning."; doap-changeset:thanks ; ], [ a doap-changeset:Documentation; rdfs:label "Document the is_*, to_*, and assert_* functions in Type::Tiny::Manual::Libraries."; doap-changeset:thanks ; rdfs:comment "They were already mentioned in Type::Library."; ], [ a doap-changeset:Documentation; rdfs:label "Mention coercion=>1 and why it is useful in Type::Tiny::Manual::Coercions."; doap-changeset:thanks ; rdfs:comment "It was already mentioned in Type::Tiny."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.043_05"^^xsd:string. a doap:Version; dc:identifier "Type-Tiny-0.044"^^xsd:string; dc:issued "2014-06-03"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Updated NEWS file."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.044"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.045_01"^^xsd:string; dc:issued "2014-06-30"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "Ensure that when a Type::Tiny object is inflated into a Moose::Meta::TypeConstraint, inlining still happens via Type::Tiny."; doap-changeset:thanks [ a foaf:Person; foaf:nick "omega" ]; rdfs:comment "This was causing some obscure problems with MooseX::Getopt."; ], [ a doap-changeset:Bugfix; rdfs:label "Workaround strange behaviour of exists() function when applied to @_ on Perl older than 5.20 which caused some uses of Optional[Foo] to accept an explicit undef."; doap-changeset:thanks ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.045_01"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.045_02"^^xsd:string; dc:issued "2014-07-10"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Include benchmark/example of Type::Params versus Scalar::Validation."; ], [ a doap-changeset:Bugfix, doap-changeset:Documentation; rdfs:label "Remove outdated references to the overloaded + operator from Types::Standard documentation."; doap-changeset:fixes ; doap-changeset:thanks ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.045_02"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.045_03"^^xsd:string; dc:issued "2014-07-11"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Type::Tiny::XS is now used (if available) to speed up some of the Types::Standard type constraints, plus Type::Tiny::Class and Type::Tiny::Duck."; ], [ a doap-changeset:Regression; rdfs:label "The Mouse XS stuff introduced in Type-Tiny 0.003_09 has been partially removed. (I do plan on restoring it, and improving it.)"; ], [ a doap-changeset:Tests; rdfs:label "When testing equivalence between Types::Standard types and core Moose types, don't test `Num` because Types::Standard provides two different implementations for it."; ], [ a doap-changeset:Documentation; rdfs:label "Update benchmark scripts, showing results with/without Type::Tiny::XS."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.045_03"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.045_04"^^xsd:string; dc:issued "2014-07-15"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Tests; rdfs:label "Cope with changes to Type::Tie error messages introduced in Type::Tie 0.008."; ], [ a doap-changeset:Tests; rdfs:label "Generally stop testing the contents of error messages produced by external modules!"; ], [ a doap-changeset:Bugfix; rdfs:label "Type::Params was warning about additional arguments passed to sprintf under Perl blead. The additional argument has been removed."; ], [ a doap-changeset:Documentation; rdfs:label "Updated NEWS file."; ], [ a doap-changeset:Tests; rdfs:label "Fix warnings in 30-integration/Moose/native-attribute-traits.t when run under perl -w."; doap-changeset:blame ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.045_04"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.045_05"^^xsd:string; dc:issued "2014-07-18"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Addition; rdfs:label "Type::Tiny now has an `of` method which is a shortcut for `parameterize` which I can never spell properly."; ], [ a doap-changeset:Addition; rdfs:label "Type::Tiny now has a `where` method which is a shortcut for creating a child type with a constraint coderef."; ], [ a doap-changeset:Documentation; rdfs:label "Added a Type::Tiny::Manual::Optimization perldoc page."; ], [ a doap-changeset:Bugfix; rdfs:label "More sensible use of Sub::Name in Type::Library."; ], [ a doap-changeset:Change; rdfs:label "Restore and improve Mouse XS stuff dropped in Type-Tiny 0.045_03."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.045_05"^^xsd:string. a doap:Version; dc:identifier "Type-Tiny-0.046"^^xsd:string; dc:issued "2014-07-18"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Tests; rdfs:label "Add test cases for Types::TypeTiny (the library of type constraints used internally by Type::Tiny)."; ], [ a doap-changeset:Bugfix; rdfs:label "Fix for Types::TypeTiny::to_TypeTiny($coderef) when Sub::Quote is loaded but not used."; ], [ a doap-changeset:Bugfix; rdfs:label "Undef no longer passes the Types::TypeTiny::StringLike type constraint."; ], [ a doap-changeset:Change; rdfs:label "Minor optimizations to Types::TypeTiny::to_TypeTiny."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.046"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; rdfs:label "The 87% Coverage Release"; dc:identifier "Type-Tiny-0.047_01"^^xsd:string; dc:issued "2014-07-21"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ rdfs:label "Types::Standard::Map is now XS-accelerated."; rdfs:seeAlso ; ], [ rdfs:label "Types::Standard::Tuple is now XS-accelerated."; rdfs:seeAlso ; ], [ rdfs:label "Type::Tiny::Enum is now XS-accelerated."; rdfs:seeAlso ; ], [ rdfs:label "Types::Common::Numeric::PositiveInt is now XS-accelerated."; rdfs:seeAlso ; ], [ rdfs:label "Types::Common::Numeric::PositiveOrZeroInt is now XS-accelerated."; rdfs:seeAlso ; ], [ rdfs:label "Types::Common::String::NonEmptyStr is now XS-accelerated."; rdfs:seeAlso ; ], [ rdfs:label "Unify _USE_XS/_USE_MOUSE logic in Type::Tiny. (It was previously scattered across Types::Standard and various other modules.)"; ], [ a doap-changeset:Documentation; rdfs:label "Better document which type constraints will be accelerated by Type::Tiny::XS and Mouse."; ], [ a doap-changeset:Bugfix, doap-changeset:Tests; rdfs:label "Fix a silly test case that was relying on Exporter::Tiny to always load B.pm. (Current versions of Exporter::Tiny do load B.pm, but future versions might not.)"; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.047_01"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; rdfs:label "The 92% Coverage Release"; dc:identifier "Type-Tiny-0.047_02"^^xsd:string; dc:issued "2014-07-23"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Allow Enums containing hyphens to be accelerated by Type::Tiny::XS."; ], [ a doap-changeset:Tests; rdfs:label "Test the Error::TypeTiny::Compilation exception class."; ], [ a doap-changeset:Tests; rdfs:label "Test exceptions thrown by Type::Tiny::Enum."; ], [ a doap-changeset:Tests; rdfs:label "Test the Error::TypeTiny::WrongNumberOfParameters exception class."; ], [ a doap-changeset:Tests; rdfs:label "Test exceptions thrown by Type::Tiny::Class."; ], [ a doap-changeset:Tests; rdfs:label "Test exceptions thrown by Type::Tiny::Role."; ], [ a doap-changeset:Tests; rdfs:label "Add tests explicitly testing Type::Tiny objects conversion to Moose::Meta::TypeConstraint and Mouse::Meta::TypeConstraint objects."; ], [ a doap-changeset:Change; rdfs:label "Type::Tiny::Class should stop using Class::ISA. Instead, if mro.pm is not available, use a private sub stolen from MRO::Compat."; ], [ a doap-changeset:Tests; rdfs:label "Stop using base.pm."; ], [ a doap-changeset:Documentation; rdfs:label "Type::Tiny::Manual no longer says that Perl 5.6.x support is at risk."; ], [ rdfs:label "Type::Tiny::Union is now XS-accelerated."; rdfs:seeAlso ; ], [ rdfs:label "Type::Tiny::Intersection is now XS-accelerated."; rdfs:seeAlso ; ], [ a doap-changeset:Tests; rdfs:label "Include test case relating to Type::Tiny::XS GitHub issue #1."; rdfs:seeAlso ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.047_02"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; rdfs:label "The 96% Coverage Release"; dc:identifier "Type-Tiny-0.047_03"^^xsd:string; dc:issued "2014-07-26"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Tests; rdfs:label "Improved type introspection method tests (find_parent/is_supertype_of/is_subtype_of/is_strictly_supertype_of/is_strictly_subtype_of)."; ], [ a doap-changeset:Tests; rdfs:label "Improved type constraint constructor tests (exceptions thrown for bad parameters, coercion=>ARRAY|CODE parameter)."; ], [ a doap-changeset:Tests; rdfs:label "Checks for more Error::TypeTiny::Assertion explanations (Tuple, Duck, Intersection, Union, Dicts containing slurpy things)."; ], [ a doap-changeset:Tests; rdfs:label "Checks non-inlineable deep coercions for Tuple."; ], [ a doap-changeset:Bugfix; rdfs:label "Fix for slurpy Map within a Tuple."; ], [ a doap-changeset:Bugfix; rdfs:label "Types::TypeTiny->has_type was incorrectly returning whether Types::TypeTiny contained the named *coercion* instead of a named *type*."; ], [ a doap-changeset:Tests; rdfs:label "Test the immutability of Type::Coercion::Union."; ], [ a doap-changeset:Tests; rdfs:label "Fake a very old Validation::Class::Simple for a certain test by overriding $Validation::Class::Simple::VERSION."; ], [ a doap-changeset:Tests; rdfs:label "Check that Type::Registry works in conjunction with MouseX::Types. (There's some TODO stuff there.)"; ], [ a doap-changeset:Packaging; rdfs:label "Bundle my TODO file."; ], [ a doap-changeset:Change; rdfs:label "Better `isa` faking - returns true to Class::MOP::Object."; ], [ a doap-changeset:Tests; rdfs:label "Tests for `isa`."; ], [ a doap-changeset:Tests; rdfs:label "Tests for various little methods which were added for Moose/Mouse-compatibility."; ], [ a doap-changeset:Tests; rdfs:label "Tests for non-inlineable type constraints in `match_on_type` and `compile_match_on_type`."; ], [ a doap-changeset:Tests; rdfs:label "Check Type::Library-based type libraries can extend MouseX::Types-based type libraries."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.047_03"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; rdfs:label "The 98% Coverage Release"; dc:identifier "Type-Tiny-0.047_04"^^xsd:string; dc:issued "2014-07-28"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Tests; rdfs:label "Tests for introspection methods of Types::TypeTiny."; ], [ a doap-changeset:Tests; rdfs:label "Check that Mouse type converted to Type::Tiny objects keep their original error messages."; ], [ a doap-changeset:Tests; rdfs:label "Tests for Test::TypeTiny::matchfor()."; ], [ a doap-changeset:Tests; rdfs:label "Improve test coverage for Type::Registry."; ], [ a doap-changeset:Tests; rdfs:label "Tests for dynamically delegated Type::Tiny an Type::Coercion methods."; ], [ a doap-changeset:Documentation; rdfs:label "Type::Utils does not export english_list() and classifier() by default."; ], [ a doap-changeset:Tests; rdfs:label "Test that Sub::Quote-enabled coderefs generated by Type::Tiny and Type::Coercion can actually be retrieved by Sub::Quote."; ], [ a doap-changeset:Tests; rdfs:label "Test the Type::Coercion overloading of ~~."; ], [ a doap-changeset:Change; rdfs:label "Straighten out the relationships between Type::Coercion and its subclasses."; ], [ a doap-changeset:Tests; rdfs:label "Tests for introspection methods of Type::Coercion."; ], [ a doap-changeset:Tests; rdfs:label "Test exceptions thrown by Types::Standard::ScalarRef."; ], [ a doap-changeset:Tests; rdfs:label "Improve test coverage for Type::Utils' match_on_type and compile_match_on_type."; ], [ a doap-changeset:Change; rdfs:label "Type:Utils::match_on_type no longer automatically loads Types::Standard."; ], [ a doap-changeset:Tests; rdfs:label "Test warnings raised by Type::Utils::declare()."; ], [ a doap-changeset:Tests; rdfs:label "Test code from SYNOPSIS sections (only in xt)."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.047_04"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; rdfs:label "Sanity++"; dc:identifier "Type-Tiny-0.047_05"^^xsd:string; dc:issued "2014-07-29"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "A far saner implementation of Optional[]."; ], [ a doap-changeset:Documentation; rdfs:label "Improve the documentation of Optional[] and slurpy."; ], [ a doap-changeset:Change; rdfs:label "Optimizations for slurpy Any."; ], [ a doap-changeset:Change; rdfs:label "When slurping the tail of a Tuple into a hashref, check it's an even number of elements."; ], [ a doap-changeset:Change; rdfs:label "A slightly saner implementation of Types::TypeTiny's meta methods."; ], [ a doap-changeset:Regression; rdfs:label "Introduced bug concerning coercions to parameterized Dicts with a mixture of inlineable and non-inlineable optional values."; rdfs:seeAlso ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.047_05"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; rdfs:label "What made the Queen go all ice crazy?"; dc:identifier "Type-Tiny-0.047_06"^^xsd:string; dc:issued "2014-07-31"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Type::Registry/Type::Parser will now auto-load MouseX::Types libraries."; ], [ a doap-changeset:Change; rdfs:label "Type::Registry now has methods for creating union/intersection/class/role type constraints. Type::Parser delegates to these, making it potentially reusable outside Type::Tiny by simply passing it an alternative type registry object."; ], [ a doap-changeset:Tests; rdfs:label "More Type::Registry test cases."; ], [ a doap-changeset:Bugfix; rdfs:label "Bugfix in coercion inheritance where the child's type_coercion_map arrayref would end up as a reference to the parent's type_coercion_map. (Which was not good.)"; ], [ a doap-changeset:Change; rdfs:label "Coercions for the types defined in Types::Standard are now frozen."; ], [ a doap-changeset:Change; rdfs:label "Coercions for the types defined in Types::Common::Numeric are now frozen."; ], [ a doap-changeset:Change; rdfs:label "Coercions for the types defined in Types::Common::String are now frozen."; ], [ a doap-changeset:Addition; rdfs:label "Type::Coercion now has a i_really_want_to_unfreeze method."; ], [ a doap-changeset:Addition; rdfs:label "Type::Library now has a make_immutable method."; ], [ rdfs:label "Parameterized types now have their coercions frozen automatically, so you can no longer add coercions to, say, ArrayRef[Int]. However, you can create a subtype of ArrayRef[Int] and add coercions to that."; doap-changeset:thanks ; rdfs:seeAlso ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.047_06"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.047_07"^^xsd:string; dc:issued "2014-08-04"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "The extract_type function was missing from Type::Parser's @EXPORT_OK list."; ], [ a doap-changeset:Tests; rdfs:label "Test cases for Type::Parser::extract_type."; ], [ a doap-changeset:Change; rdfs:label "Parameterized Maybe constraints are now XS-accelerated."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.047_07"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; rdfs:label "Sanity++"; dc:identifier "Type-Tiny-0.047_08"^^xsd:string; dc:issued "2014-08-05"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Tests; rdfs:label "Test to avoid the \"too few arguments for type constraint check functions\" error."; doap-changeset:thanks ; rdfs:seeAlso ; ], [ rdfs:label "Prevent inlining of coercions if they've not been frozen."; rdfs:seeAlso ; ], [ a doap-changeset:Documentation; rdfs:label "Document the remaining RT#93345-related issues - see \"Deep Caveat\" in Type::Tiny::Manual::Coercions."; rdfs:seeAlso ; ], [ a doap-changeset:Tests; rdfs:label "Update t/30-integration/Moose/coercion.t to Moose 2.1200 which throws an exception rather than printing a warning when coerce=>1 is used on a type constraint with no coercions."; ], [ a doap-changeset:Tests; rdfs:label "Alter the Types::Common::* test cases to use Test::TypeTiny."; ], [ a doap-changeset:Bugfix; rdfs:label "Fix non-inlined version of NegativeOrZeroInt."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.047_08"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-0.047_09"^^xsd:string; dc:issued "2014-08-12"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Improvements and clarifications to Type::Coercion documentation."; ], [ a doap-changeset:Change; rdfs:label "The to_Foo functions exported by Type::Library-based modules are now significantly faster. (But only if the type's coercion is frozen.)"; ], [ a doap-changeset:Tests; rdfs:label "Add tests for Error::TypeTiny::Assertion's predicate methods."; ], [ a doap-changeset:Tests; rdfs:label "Add tests for Type::Coercion's i_really_want_to_unfreeze method."; ], [ a doap-changeset:Change; rdfs:label "Better integration between Type::Library and Type::Registry. If you import a type constraint from a Type::Library-based module, it will automatically be inserted into your modules' type registry."; ], [ a doap-changeset:Change; rdfs:label "Type::Utils::dwim_type now takes into account what OO framework the caller is using (Moose or Mouse) if it needs to fall back to asking the OO framework about a type constraint."; ], [ a doap-changeset:Bugfix, doap-changeset:Documentation; rdfs:label "Fix documentation typo."; doap-changeset:fixes ; doap-changeset:thanks ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "0.047_09"^^xsd:string. a doap:Version; rdfs:label "Happy CPAN Day!"; dc:identifier "Type-Tiny-1.000000"^^xsd:string; dc:issued "2014-08-16"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Updated NEWS file."; ], [ a doap-changeset:Documentation; rdfs:label "Updated TODO file."; ], [ a doap-changeset:Documentation; rdfs:label "Document the Type::Tiny versioning policy."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "1.000000"^^xsd:string. a doap:Version; dc:identifier "Type-Tiny-1.000001"^^xsd:string; dc:issued "2014-08-18"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "Changes to dwim_type() in 0.047_09 broke the fallback to creating class types in some circumstances. This broke the MooX::late test suite, and some usages of MooX::late."; doap-changeset:thanks ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "1.000001"^^xsd:string. a doap:Version; dc:identifier "Type-Tiny-1.000002"^^xsd:string; dc:issued "2014-08-18"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "Fix for overloaded operation fallback on Perl 5.10.x."; doap-changeset:blame ; doap-changeset:fixes ; doap-changeset:thanks ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "1.000002"^^xsd:string. a doap:Version; dc:identifier "Type-Tiny-1.000003"^^xsd:string; dc:issued "2014-08-28"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "Fix for coercions to parameterized Dict including a mixture of inlineable and non-inlineable optional values."; doap-changeset:blame ; doap-changeset:fixes ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "1.000003"^^xsd:string. a doap:Version; dc:identifier "Type-Tiny-1.000004"^^xsd:string; dc:issued "2014-09-02"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "Fix issues with coercions and native attribute traits with some oldish versions of Moose on oldish versions of Perl."; doap-changeset:fixes ; doap-changeset:thanks ; rdfs:comment "Backported fix from 1.001_000."; ], [ a doap-changeset:Bugfix; rdfs:label "Fix for Type::Registry::DWIM."; doap-changeset:fixes ; doap-changeset:thanks ; rdfs:comment "Backported fix from 1.001_000."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "1.000004"^^xsd:string. a doap:Version; dc:identifier "Type-Tiny-1.000005"^^xsd:string; dc:issued "2014-10-25"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "Fix short-circuiting optimizations for parameterized HashRef, ArrayRef, ScalarRef, and Map type constraints."; doap-changeset:fixes ; doap-changeset:thanks ; ], [ a doap-changeset:Tests; rdfs:label "Fix annoying warning message in test suite with recent versions of Exporter::Tiny."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "1.000005"^^xsd:string. a foaf:Agent; foaf:mbox . a foaf:Agent; foaf:mbox . a foaf:Agent; foaf:mbox . a foaf:Agent; foaf:mbox . a foaf:Agent; foaf:mbox . a foaf:Agent; foaf:mbox . a foaf:Agent; foaf:mbox . a foaf:Person; foaf:name "Alexander Hartmaier"; foaf:nick "ABRAXXA"; foaf:page . a foaf:Person; foaf:name "Brendan Byrd"; foaf:nick "BBYRD"; foaf:page . a foaf:Person; foaf:name "Kevin Dawson"; foaf:nick "BOWTIE"; foaf:page . a foaf:Person; foaf:name "David Golden"; foaf:nick "DAGOLDEN"; foaf:page . a foaf:Person; foaf:name "Gianni Ceccarelli"; foaf:nick "DAKKAR"; foaf:page . a foaf:Agent, foaf:Person; foaf:mbox ; foaf:name "Diab Jerius"; foaf:nick "DJERIUS"; foaf:page . a foaf:Person; foaf:name "Graham Knop"; foaf:nick "HAARG"; foaf:page . a foaf:Person; foaf:name "Dagfinn Ilmari Mannsker"; foaf:nick "ILMARI"; foaf:page . a foaf:Person; foaf:name "Ingy dt Net"; foaf:nick "INGY"; foaf:page . a foaf:Person; foaf:name "Jason R Mash"; foaf:nick "JRMASH"; foaf:page . a foaf:Person; foaf:name "Peter Karman"; foaf:nick "KARMAN"; foaf:page . a foaf:Person; foaf:name "Mark Stosberg"; foaf:nick "MARKSTOS"; foaf:page . a foaf:Person; foaf:name "Marcel Timmerman"; foaf:nick "MARTIMM"; foaf:page . a foaf:Person; foaf:name "Matt Phillips"; foaf:nick "MATTP"; foaf:page . a foaf:Person; foaf:name "Vyacheslav Matyukhin"; foaf:nick "MMCLERIC"; foaf:page . a foaf:Agent, foaf:Person; foaf:mbox ; foaf:name "Michael G Schwern"; foaf:nick "MSCHWERN"; foaf:page . a foaf:Person; foaf:name "Matt S Trout"; foaf:nick "MSTROUT"; foaf:page . a foaf:Person; foaf:name "Yuval Kogman"; foaf:nick "NUFFIN"; foaf:page . a foaf:Person; foaf:name "Peter Flanigan"; foaf:nick "PJFL"; foaf:page . a foaf:Person; foaf:name "Peter Rabbitson"; foaf:nick "RIBASUSHI"; foaf:page . a foaf:Person; foaf:name "Ricardo Signes"; foaf:nick "RJBS"; foaf:page . a foaf:Person; foaf:name "Richard Simes"; foaf:nick "RSIMOES"; foaf:page . a foaf:Person; foaf:name "Shlomi Fish"; foaf:nick "SHLOMIF"; foaf:page . a foaf:Person; foaf:name "Samuel Kaufman"; foaf:nick "SKAUFMAN"; foaf:page . a foaf:Person; foaf:name "Marcel Montes"; foaf:nick "SPICEMAN"; foaf:page . a foaf:Person; foaf:name "Steven Lee"; foaf:nick "STEVENL"; foaf:page . a foaf:Person; foaf:name "Tim Bunce"; foaf:nick "TIMB"; foaf:page . a foaf:Person; foaf:mbox ; foaf:name "Toby Inkster"; foaf:nick "TOBYINK"; foaf:page . a foaf:Person; foaf:name "MATSUNO Tokuhiro"; foaf:nick "TOKUHIROM"; foaf:page . a foaf:Person; foaf:name "Caleb Cushing"; foaf:nick "XENO"; foaf:page . a doap-bugs:Issue; rdfs:label "Confusing error message if required slurpy Dict not present in parameter list"; dc:created "2013-05-05T03:35:42+01:00"^^xsd:dateTime; dc:reporter ; doap-bugs:id "85054"; doap-bugs:page ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "exception objects"; dc:created "2013-05-09T04:52:37+01:00"^^xsd:dateTime; dc:reporter _:B1; doap-bugs:id "85149"; doap-bugs:page ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "Type::Library has wrong VERSION variable"; dc:created "2013-05-30T03:53:03+01:00"^^xsd:dateTime; dc:reporter ; doap-bugs:id "85720"; doap-bugs:page ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "support for optional arguments"; dc:created "2013-05-30T14:11:03+01:00"^^xsd:dateTime; dc:reporter ; doap-bugs:id "85732"; doap-bugs:page ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "Type comparison not working on 5.8"; dc:created "2013-06-05T18:39:56+01:00"^^xsd:dateTime; dc:reporter [ a foaf:Agent; foaf:mbox ]; doap-bugs:id "85895", "85895"^^xsd:string; doap-bugs:page , ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "\"coercion cannot be inlined\" error w/ Type::Params::compile & Dict"; dc:created "2013-06-06T04:00:30+01:00"^^xsd:dateTime; dc:reporter ; doap-bugs:id "85911", "85911"^^xsd:string; doap-bugs:page , ; doap-bugs:status ; doap-tests:regression_test [ a doap-tests:RegressionTest; doap-tests:purpose "Test Type::Params with deep Dict coercion."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/40-regression/rt85911.t"; ]; ]. a doap-bugs:Issue; doap-bugs:id "86001"^^xsd:string; doap-bugs:page . a doap-bugs:Issue; rdfs:label "type constraint fails after coercion if too many elements in Dict"; dc:created "2013-06-08T23:03:45+01:00"^^xsd:dateTime; dc:reporter ; doap-bugs:id "86004", "86004"^^xsd:string; doap-bugs:page , ; doap-bugs:status ; doap-tests:regression_test [ a doap-tests:RegressionTest; doap-tests:purpose "Test Type::Params with more complex Dict coercion."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/40-regression/rt86004.t"; ]; ]. a doap-bugs:Issue; rdfs:label "Missing coercion with Moose and Type::Tiny"; dc:created "2013-06-15T22:30:28+01:00"^^xsd:dateTime; dc:reporter _:B2; doap-bugs:id "86172", "86172"^^xsd:string; doap-bugs:page , ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "\"Cannot inline type constraint check\" erro with compile and Dict"; dc:created "2013-06-18T15:23:52+01:00"^^xsd:dateTime; dc:reporter ; doap-bugs:id "86233", "86233"^^xsd:string; doap-bugs:page , ; doap-bugs:status ; doap-tests:regression_test [ a doap-tests:RegressionTest; doap-tests:purpose "Fix: \"Cannot inline type constraint check\" error with compile and Dict."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/40-regression/rt86233.t"; ]; ]. a doap-bugs:Issue; rdfs:label "Optional constraints ignored if wrapped in Dict"; dc:created "2013-06-18T16:34:37+01:00"^^xsd:dateTime; dc:reporter ; doap-bugs:id "86239", "86239"^^xsd:string; doap-bugs:page , ; doap-bugs:status ; doap-tests:regression_test [ a doap-tests:RegressionTest; doap-tests:purpose "Fix: Optional constraints ignored if wrapped in Dict."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/40-regression/rt86239.t"; ]; ]. a doap-bugs:Issue; doap-bugs:id "86303"^^xsd:string; doap-bugs:page . a doap-bugs:Issue; rdfs:label "Can't locate object method \"NAME\" via package \"B::SPECIAL\""; dc:created "2013-06-24T14:48:37+01:00"^^xsd:dateTime; dc:reporter _:B2; doap-bugs:id "86383", "86383"^^xsd:string; doap-bugs:page , ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "'extends' is not declared"; dc:created "2013-07-09T18:53:01+01:00"^^xsd:dateTime; dc:reporter [ a foaf:Agent; foaf:mbox ]; doap-bugs:id "86813", "86813"^^xsd:string; doap-bugs:page , ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "Reduce boilerplate for inline_as"; dc:created "2013-07-12T14:29:19+01:00"^^xsd:dateTime; dc:reporter ; doap-bugs:id "86891", "86891"^^xsd:string; doap-bugs:page , ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "Reduce boilerplate for message"; dc:created "2013-07-12T14:45:49+01:00"^^xsd:dateTime; dc:reporter ; doap-bugs:id "86892", "86892"^^xsd:string; doap-bugs:page , ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "Clarify \"may\" in the docs in relation to using constraint => quote_sub q{...}"; dc:created "2013-07-12T15:08:16+01:00"^^xsd:dateTime; dc:reporter ; doap-bugs:id "86893", "86893"^^xsd:string; doap-bugs:page , ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "I was bitten by equals() being looser than expected (ie structural) which impacts is_subtype_of()"; dc:created "2013-07-24T18:20:27+01:00"^^xsd:dateTime; dc:reporter ; doap-bugs:id "87264"; doap-bugs:page ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "PackageName type"; dc:created "2013-07-26T23:18:08+01:00"^^xsd:dateTime; dc:reporter _:B1; doap-bugs:id "87366"; doap-bugs:page ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "Dict type doesn't notice missing Bool elements"; dc:created "2013-07-30T15:09:13+01:00"^^xsd:dateTime; dc:reporter ; doap-bugs:id "87443", "87443"^^xsd:string; doap-bugs:page , ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "slurpy Dict[ foo => InstanceOf[\"bar\"] ] fails (due to unescaped quotes in throw?)"; dc:created "2013-08-14T11:59:43+01:00"^^xsd:dateTime; dc:reporter ; doap-bugs:id "87846", "87846"^^xsd:string; doap-bugs:page , ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "Make constraint failure errors look less like data dumps"; dc:created "2013-08-21T13:22:54+01:00"^^xsd:dateTime; dc:reporter ; doap-bugs:id "87999", "87999"^^xsd:string; doap-bugs:page , ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "Several subclasses of Type::Tiny don't accept a hashref to the constructor"; dc:created "2013-08-23T17:00:11+01:00"^^xsd:dateTime; dc:reporter _:B3; doap-bugs:id "88064", "88064"^^xsd:string; doap-bugs:page , ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "Tuple validation unexpectedly successful"; dc:created "2013-08-29T19:42:31+01:00"^^xsd:dateTime; dc:reporter ; doap-bugs:id "88277", "88277"^^xsd:string; doap-bugs:page , ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "Grouped alternatives"; dc:created "2013-08-30T18:33:23+01:00"^^xsd:dateTime; dc:reporter ; doap-bugs:id "88291", "88291"^^xsd:string; doap-bugs:page , ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "Coercion Hierarchies"; dc:created "2013-09-06T00:09:56+01:00"^^xsd:dateTime; dc:reporter ; doap-bugs:id "88452", "88452"^^xsd:string; doap-bugs:page , ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "Type::Tiny::Union could better mock Moose::Meta::TypeConstraint::Union"; dc:created "2013-09-13T09:21:08+01:00"^^xsd:dateTime; dc:reporter _:B3; doap-bugs:id "88648"; doap-bugs:page ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "Better messsages for type constraint failures"; dc:created "2013-09-13T13:52:03+01:00"^^xsd:dateTime; dc:reporter _:B3; doap-bugs:id "88655", "88655"^^xsd:string; doap-bugs:page , ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "Typo in Type::Utils documentation"; dc:created "2013-09-19T03:52:25+01:00"^^xsd:dateTime; dc:reporter ; doap-bugs:id "88798", "88798"^^xsd:string; doap-bugs:page , ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "Union and Intersection should still allow constraint/inlined attributes"; dc:created "2013-09-25T01:13:06+01:00"^^xsd:dateTime; dc:reporter ; doap-bugs:id "88951"; doap-bugs:page ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "Fwd: Union?"; dc:created "2013-09-30T17:42:42+01:00"^^xsd:dateTime; dc:reporter _:B1; doap-bugs:id "89073"; doap-bugs:page ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "Moo attribute information not included in exception messages"; dc:created "2013-10-03T17:09:02+01:00"^^xsd:dateTime; dc:reporter [ a foaf:Agent; foaf:mbox ]; doap-bugs:id "89234", "89234"^^xsd:string; doap-bugs:page , ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "Make truncation length in Type::Tiny::_dd (currently 72) configurable"; dc:created "2013-10-04T12:41:25+01:00"^^xsd:dateTime; dc:reporter ; doap-bugs:id "89251", "89251"^^xsd:string; doap-bugs:page , ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "validate_explain and Intersections"; dc:created "2013-10-06T16:21:31+01:00"^^xsd:dateTime; dc:reporter ; doap-bugs:id "89279", "89279"^^xsd:string; doap-bugs:page , ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "Types::Exception not being indexed properly"; dc:created "2013-10-06T16:24:38+01:00"^^xsd:dateTime; dc:reporter ; doap-bugs:id "89280", "89280"^^xsd:string; doap-bugs:page , ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "Item should be a subtype of Any"; dc:created "2013-10-08T01:51:05+01:00"^^xsd:dateTime; dc:reporter ; doap-bugs:id "89317"; doap-bugs:page ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "Gazetteer type constraint"; dc:created "2013-10-08T21:20:35+01:00"^^xsd:dateTime; dc:reporter _:B3; doap-bugs:id "89352"; doap-bugs:page ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "Types::Standard: please add StrLen (string with length) type"; dc:created "2013-10-22T11:42:15+01:00"^^xsd:dateTime; dc:reporter _:B4; doap-bugs:id "89691"; doap-bugs:page ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "Types::Standard: is it possible to check for an empty ArrayRef/HashRef?"; dc:created "2013-10-22T13:22:36+01:00"^^xsd:dateTime; dc:reporter _:B4; doap-bugs:id "89696", "89696"^^xsd:string; doap-bugs:page , ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "Maybe[Foo] should better emulate Foo|Undef for constraints"; dc:created "2013-11-01T00:43:36Z"^^xsd:dateTime; dc:reporter ; doap-bugs:id "89936", "89936"^^xsd:string; doap-bugs:page , ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "Modification of a read-only value attempted at parameter validation for '__ANON__'"; dc:created "2013-11-06T15:24:29Z"^^xsd:dateTime; dc:reporter ; doap-bugs:id "90096", "90096"^^xsd:string; doap-bugs:page , ; doap-bugs:status ; doap-tests:regression_test [ a doap-tests:RegressionTest; doap-tests:purpose "Additional tests related to RT#90096. Make sure that Type::Params localizes '$_'."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/40-regression/rt90096-2.t"; ]; ], [ a doap-tests:RegressionTest; doap-tests:purpose "Make sure that Type::Params localizes '$_'."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/40-regression/rt90096.t"; ]; ]. a doap-bugs:Issue; rdfs:label "Type::Params::multisig fails to validate when presented with a slurpy Dict"; dc:created "2013-11-28T00:53:07Z"^^xsd:dateTime; dc:reporter ; doap-bugs:id "90865", "90865"^^xsd:string; doap-bugs:page , ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "possible documentation error in Error::TypeTiny::Assertion"; dc:created "2013-11-28T02:25:01Z"^^xsd:dateTime; dc:reporter ; doap-bugs:id "90867", "90867"^^xsd:string; doap-bugs:page , ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "Type::Utils::extends does not handle named type coercions"; dc:created "2013-12-03T17:44:14Z"^^xsd:dateTime; dc:reporter [ a foaf:Agent; foaf:mbox ; ]; doap-bugs:id "91153", "91153"^^xsd:string; doap-bugs:page , ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "test failure"; dc:created "2013-12-17T12:39:50Z"^^xsd:dateTime; dc:reporter [ a foaf:Agent; foaf:mbox ; ]; doap-bugs:id "91468", "91468"^^xsd:string; doap-bugs:page , ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "Types::Standard: please add $class->DOES(...), $class->isa(...) and $class =~ /$valid_class_re/ constraints."; dc:created "2014-01-02T19:49:31Z"^^xsd:dateTime; dc:reporter _:B4; doap-bugs:id "91802"; doap-bugs:page ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "unexpected error from on-the-fly type union coercions, e.g. ( Str | Str )->coercion"; dc:created "2014-01-30T05:56:04Z"^^xsd:dateTime; dc:reporter ; doap-bugs:id "92571", "92571"^^xsd:string; doap-bugs:page , ; doap-bugs:status ; doap-tests:regression_test [ a doap-tests:RegressionTest; doap-tests:purpose "Make sure that the weakening of the reference from a Type::Coercion::Union object back to its \"owner\" type constraint does not break functionality."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/40-regression/rt92571-2.t"; ]; ], [ a doap-tests:RegressionTest; doap-tests:purpose "Make sure that the weakening of the reference from a Type::Coercion object back to its \"owner\" type constraint does not break functionality."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/40-regression/rt92571.t"; ]; ]. a doap-bugs:Issue; rdfs:label "anonymous coercions (via declare_coercion) ignore passed coercion maps if not in a Type::Library"; dc:created "2014-01-30T22:24:22Z"^^xsd:dateTime; dc:reporter ; doap-bugs:id "92591", "92591"^^xsd:string; doap-bugs:page , ; doap-bugs:status ; doap-tests:regression_test [ a doap-tests:RegressionTest; doap-tests:purpose "Make sure that 'declare_coercion' works outside type libraries."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/40-regression/rt92591.t"; ]; ]. a doap-bugs:Issue; rdfs:label "Inlining/compiling of coercions which haven't been frozen"; dc:created "2014-02-25T14:13:36Z"^^xsd:dateTime; dc:reporter _:B3; doap-bugs:id "93345", "93345"^^xsd:string; doap-bugs:page , ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "Type::Params; slurpy Dict breaks HasMethods"; dc:created "2014-03-26T04:18:03Z"^^xsd:dateTime; dc:reporter ; doap-bugs:id "94196", "94196"^^xsd:string; doap-bugs:page , ; doap-bugs:status ; doap-tests:regression_test [ a doap-tests:RegressionTest; doap-tests:purpose "Problematic inlining using '$_'."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/40-regression/rt94196.t"; ]; ]. a doap-bugs:Issue; rdfs:label "Type::Tiny and when()"; dc:created "2014-03-28T15:35:36Z"^^xsd:dateTime; dc:reporter ; doap-bugs:id "94286"; doap-bugs:page ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "documentation error in Types::Standard vis--vis coercions"; dc:created "2014-06-11T17:20:17+01:00"^^xsd:dateTime; dc:reporter ; doap-bugs:id "96379", "96379"^^xsd:string; doap-bugs:page , ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "5.20+ fails compile( Optional ) if passing explicit undef"; dc:created "2014-06-19T04:42:06+01:00"^^xsd:dateTime; dc:reporter _:B1; doap-bugs:id "96545"; doap-bugs:page ; doap-bugs:status . a doap-bugs:Issue; rdfs:label "InstanceOf[Class::Name] is not cached, makes declaring coercion inconsistent"; dc:created "2014-07-25T23:50:47+01:00"^^xsd:dateTime; dc:reporter ; doap-bugs:id "97516", "97516"^^xsd:string; doap-bugs:page , ; doap-bugs:status . a doap-bugs:Issue; doap-bugs:id "97684"^^xsd:string; doap-bugs:page . a doap-bugs:Issue; doap-bugs:id "98113"^^xsd:string; doap-bugs:page . a doap-bugs:Issue; doap-bugs:id "98159"^^xsd:string; doap-bugs:page . a doap-bugs:Issue; doap-bugs:id "98362"^^xsd:string; doap-bugs:page . a doap-bugs:Issue; doap-bugs:id "98458"^^xsd:string; doap-bugs:page . a doap-bugs:Issue; doap-bugs:id "99312"^^xsd:string; doap-bugs:page . foaf:mbox ; foaf:name "David Steinbrunner". foaf:name "Pierre Masci"; foaf:page . foaf:mbox ; foaf:name "Benct Philip Jonsson". _:B1 a foaf:Agent; foaf:mbox . _:B2 a foaf:Agent; foaf:mbox . _:B3 a foaf:Agent; foaf:mbox . _:B4 a foaf:Agent; foaf:mbox . _:B5 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/00-begin.t". _:B6 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/01-compile.t". _:B7 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Error-TypeTiny/basic.t". _:B8 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Utils/dwim-moose.t". _:B9 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Utils/dwim-mouse.t". _:B10 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Utils/match-on-type.t". _:B11 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Utils/warnings.t". [] a nfo:FileDataObject, nfo:SourceCode; rdfs:label "Types::Common::Numeric"; doap-tests:unit_test [ a doap-tests:UnitTest; doap-tests:purpose "Tests constraints for Types::Common::Numeric. These tests are based on tests from MooseX::Types::Common."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Types-Common-Numeric/basic.t"; ]; ]; nfo:fileName "lib/Types/Common/Numeric.pm"; nfo:programmingLanguage "Perl". [] a nfo:FileDataObject, nfo:SourceCode; rdfs:label "Types::Common::String"; doap-tests:unit_test [ a doap-tests:UnitTest; doap-tests:purpose "Tests constraints for Types::Common::String. These tests are based on tests from MooseX::Types::Common."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Types-Common-String/basic.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Tests coercions for Types::Common::String. These tests are based on tests from MooseX::Types::Common."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Types-Common-String/coerce.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Tests Unicode support for Types::Common::String. These tests are based on tests from MooseX::Types::Common."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Types-Common-String/unicode.t"; ]; ]; nfo:fileName "lib/Types/Common/String.pm"; nfo:programmingLanguage "Perl". _:B12 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Error-TypeTiny/stacktrace.t". [] a nfo:FileDataObject, nfo:SourceCode; rdfs:label "Types::Standard"; doap-tests:unit_test [ a doap-tests:UnitTest; doap-tests:purpose "Checks various values against the type constraints from Types::Standard."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Types-Standard/basic.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "If a coercion exists for type 'Foo', then Type::Tiny should be able to auto-generate a coercion for type 'ArrayRef[Foo]', etc."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Types-Standard/deep-coercions.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Test the following types from Types::Standard which were inspired by MooX::Types::MooseLike::Base. * 'InstanceOf' * 'ConsumerOf' * 'HasMethods' * 'Enum' Rather than checking they work directy, we check they are equivalent to known (and well-tested) type constraints generated using Type::Utils."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Types-Standard/mxtmlb-alike.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Checks various values against 'OptList' from Types::Standard. Checks the standalone 'MkOpt' coercion."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Types-Standard/optlist.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Checks various values against 'Overload' from Types::Standard."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Types-Standard/overload.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Checks various values against 'StrMatch' from Types::Standard."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Types-Standard/strmatch.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Checks various values against structured types from Types::Standard."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Types-Standard/structured.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Checks various values against 'Tied' from Types::Standard."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Types-Standard/tied.t"; ]; ]; nfo:fileName "lib/Types/Standard.pm"; nfo:programmingLanguage "Perl". [] a nfo:FileDataObject, nfo:SourceCode; rdfs:label "Types::TypeTiny"; doap-tests:unit_test [ a doap-tests:UnitTest; doap-tests:purpose "Test the Types::TypeTiny bootstrap library. (That is, type constraints used by Type::Tiny internally.)"; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Types-TypeTiny/basic.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Test Types::TypeTiny::to_TypeTiny pseudo-coercion."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Types-TypeTiny/coercion.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Test the Types::TypeTiny introspection methods. Types::TypeTiny doesn't inherit from Type::Library (because bootstrapping), so provides independent re-implementations of the most important introspection stuff."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Types-TypeTiny/meta.t"; ]; ]; nfo:fileName "lib/Types/TypeTiny.pm"; nfo:programmingLanguage "Perl". [] a nfo:FileDataObject, nfo:SourceCode; rdfs:label "Error::TypeTiny::Assertion"; doap-tests:unit_test [ a doap-tests:UnitTest; doap-tests:purpose "Tests Error::TypeTiny::Assertion."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Error-TypeTiny-Assertion/basic.t"; ]; ]; nfo:fileName "lib/Error/TypeTiny/Assertion.pm"; nfo:programmingLanguage "Perl". _:B13 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Class-InsideOut/basic.t". _:B14 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Exporter-Tiny/basic.t". _:B15 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Exporter-Tiny/installer.t". _:B16 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Exporter-Tiny/role-conflict.t". _:B17 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Function-Parameters/basic.t". _:B18 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Kavorka/basic.t". _:B19 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Moo/basic.t". _:B20 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Moo/coercion.t". _:B21 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Moo/exceptions.t". _:B22 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Moo/inflation.t". _:B23 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Moo/inflation2.t". _:B24 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Moops/basic.t". _:B25 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Moops/library-keyword.t". _:B26 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Moose/accept-moose-types.t". _:B27 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Moose/basic.t". _:B28 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Moose/coercion.t". _:B29 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Moose/inflate-then-inline.t". [] a nfo:FileDataObject, nfo:SourceCode; rdfs:label "Error::TypeTiny::Compilation"; doap-tests:unit_test [ a doap-tests:UnitTest; doap-tests:purpose "Tests for Error::TypeTiny::Compilation, mostly by triggering compilation errors using Eval::TypeTiny."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Error-TypeTiny-Compilation/basic.t"; ]; ]; nfo:fileName "lib/Error/TypeTiny/Compilation.pm"; nfo:programmingLanguage "Perl". [] a nfo:FileDataObject, nfo:SourceCode; rdfs:label "Error::TypeTiny::WrongNumberOfParameters"; doap-tests:unit_test [ a doap-tests:UnitTest; doap-tests:purpose "Test Error::TypeTiny::WrongNumberOfParameters."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Error-TypeTiny-WrongNumberOfParameters/basic.t"; ]; ]; nfo:fileName "lib/Error/TypeTiny/WrongNumberOfParameters.pm"; nfo:programmingLanguage "Perl". [] a nfo:FileDataObject, nfo:SourceCode; rdfs:label "Eval::TypeTiny"; doap-tests:unit_test [ a doap-tests:UnitTest; doap-tests:purpose "Tests Eval::TypeTiny."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Eval-TypeTiny/basic.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Tests Eval::TypeTiny supports alias=>1 even when Devel::LexAlias is unavailable."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Eval-TypeTiny/fallback-aliases.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Tests Eval::TypeTiny with experimental lexical subs."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Eval-TypeTiny/lexical-subs.t"; ]; ]; nfo:fileName "lib/Eval/TypeTiny.pm"; nfo:programmingLanguage "Perl". _:B30 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/02-api.t". [] a nfo:FileDataObject, nfo:SourceCode; rdfs:label "Test::TypeTiny"; doap-tests:unit_test [ a doap-tests:UnitTest; doap-tests:purpose "Tests Test::TypeTiny (which is somewhat important because Test::TypeTiny is itself used for the majority of the type constraint tests). In particular, this tests that everything works when the '$EXTENDED_TESTING' environment variable is false."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Test-TypeTiny/basic.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Tests Test::TypeTiny works when the '$EXTENDED_TESTING' environment variable is true. Note that Test::Tester appears to have issues with subtests, so currently 'should_pass' and 'should_fail' are not tested."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Test-TypeTiny/extended.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Tests Test::TypeTiny (which is somewhat important because Test::TypeTiny is itself used for the majority of the type constraint tests). In particular, this tests that everything works when the '$EXTENDED_TESTING' environment variable is false."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Test-TypeTiny/matchfor.t"; ]; ]; nfo:fileName "lib/Test/TypeTiny.pm"; nfo:programmingLanguage "Perl". [] a nfo:FileDataObject, nfo:SourceCode; rdfs:label "Type::Coercion"; doap-tests:unit_test [ a doap-tests:UnitTest; doap-tests:purpose "Checks Type::Coercion works."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Coercion/basic.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Checks various undocumented Type::Coercion methods. The fact that these are tested here should not be construed to mean tht they are any any way a stable, supported part of the Type::Coercion API."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Coercion/esoteric.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Type::Coercion objects are mutable, unlike Type::Tiny objects. However, they can be frozen, making them immutable. (And Type::Tiny will freeze them occasionally, if it feels it has to.)"; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Coercion/frozen.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Checks Type::Coercion can be inlined."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Coercion/inlining.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Checks the 'Split' and 'Join' parameterized coercions from Types::Standard."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Coercion/parameterized.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Checks Type::Coercion overload of '~~'."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Coercion/smartmatch.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Checks proper Type::Coercion objects are automatically created by the Type::Tiny constructor."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Coercion/typetiny-constructor.t"; ]; ]; nfo:fileName "lib/Type/Coercion.pm"; nfo:programmingLanguage "Perl". _:B31 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/03-leak.t". [] a nfo:FileDataObject, nfo:SourceCode; rdfs:label "Type::Coercion::FromMoose"; doap-tests:unit_test [ a doap-tests:UnitTest; doap-tests:purpose "Checks the types adopted from Moose still have a coercion which works."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Coercion-FromMoose/basic.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Checks crazy Type::Coercion::FromMoose errors."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Coercion-FromMoose/errors.t"; ]; ]; nfo:fileName "lib/Type/Coercion/FromMoose.pm"; nfo:programmingLanguage "Perl". [] a nfo:FileDataObject, nfo:SourceCode; rdfs:label "Type::Coercion::Union"; doap-tests:unit_test [ a doap-tests:UnitTest; doap-tests:purpose "Checks Type::Coercion::Union works."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Coercion-Union/basic.t"; ]; ]; nfo:fileName "lib/Type/Coercion/Union.pm"; nfo:programmingLanguage "Perl". [] a nfo:FileDataObject, nfo:SourceCode; rdfs:label "Type::Library"; doap-tests:unit_test [ a doap-tests:UnitTest; doap-tests:purpose "Checks that the assertion functions exported by a type library work as expected."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Library/assert.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Tests errors thrown by Type::Library."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Library/errors.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Checks that it's possible to extend existing type libraries."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Library/inheritance.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Checks that the check functions exported by a type library work as expected."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Library/is.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Checks that the coercion functions exported by a type library work as expected."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Library/to.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Checks that the type functions exported by a type library work as expected."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Library/types.t"; ]; ]; nfo:fileName "lib/Type/Library.pm"; nfo:programmingLanguage "Perl". _:B32 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/99-moose-std-types-test.t". [] a nfo:FileDataObject, nfo:SourceCode; rdfs:label "Type::Params"; doap-tests:unit_test [ a doap-tests:UnitTest; doap-tests:purpose "Check that people doing silly things with Test::Params get"; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Params/badsigs.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Test Type::Params' interaction with Carp: use Type::Params compile => { confess => 1 };"; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Params/carping.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Test Type::Params usage of types with coercions."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Params/coerce.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Test Type::Params usage for method calls."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Params/methods.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Test Type::Params usage with mix of positional and named parameters."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Params/mixednamed.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Test Type::Params 'multisig' function."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Params/multisig.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Test Type::Params usage with named parameters."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Params/named.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Test Type::Params with type constraints that cannot be inlined."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Params/noninline.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Test Type::Params usage with optional parameters."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Params/optional.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Test Type::Params positional parameters, a la the example in the documentation: sub nth_root { state $check = compile( Num, Num ); my ($x, $n) = $check->(@_); return $x ** (1 / $n); }"; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Params/positional.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Test Type::Params usage with slurpy parameters."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Params/slurpy.t"; ]; ]; nfo:fileName "lib/Type/Params.pm"; nfo:programmingLanguage "Perl". [] a nfo:FileDataObject, nfo:SourceCode; rdfs:label "Devel::TypeTiny::Perl56Compat"; doap-tests:unit_test [ a doap-tests:UnitTest; doap-tests:purpose "Checks 'B::perlstring()' works."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Devel-TypeTiny-Perl56Compat/basic.t"; ]; ]; nfo:fileName "lib/Devel/TypeTiny/Perl56Compat.pm"; nfo:programmingLanguage "Perl". [] a nfo:FileDataObject, nfo:SourceCode; rdfs:label "Type::Parser"; doap-tests:unit_test [ a doap-tests:UnitTest; doap-tests:purpose "Checks Type::Parser works."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Parser/basic.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Checks Type::Parser can pick up MooseX::Types type constraints."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Parser/moosextypes.t"; ]; ]; nfo:fileName "lib/Type/Parser.pm"; nfo:programmingLanguage "Perl". [] a nfo:FileDataObject, nfo:SourceCode; rdfs:label "Type::Registry"; doap-tests:unit_test [ a doap-tests:UnitTest; doap-tests:purpose "Checks Type::Registry works."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Registry/basic.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Checks Type::Registry works with MooseX::Types."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Registry/moosextypes.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Checks Type::Registry works with MouseX::Types."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Registry/mousextypes.t"; ]; ]; nfo:fileName "lib/Type/Registry.pm"; nfo:programmingLanguage "Perl". [] a nfo:FileDataObject, nfo:SourceCode; rdfs:label "Type::Tiny"; doap-tests:unit_test [ a doap-tests:UnitTest; doap-tests:purpose "Tests overloading of bitwise operators and numeric comparison operators for Type::Tiny."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Tiny/arithmetic.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Checks Type::Tiny works."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Tiny/basic.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Checks 'plus_coercions', 'minus_coercions' and 'no_coercions' methods work."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Tiny/coercion-modifiers.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Checks various undocumented Type::Tiny methods. The fact that these are tested here should not be construed to mean tht they are any any way a stable, supported part of the Type::Tiny API."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Tiny/esoteric.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Checks Type::Tiny's 'my_methods' attribute."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Tiny/my-methods.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "There are loads of tests for parameterization in 'stdlib.t', 'stdlib-overload.t', 'stdlib-strmatch.t', 'stdlib-structures.t', 'syntax.t', 'stdlib-automatic.t', etc. This file includes a handful of other parameterization-related tests that didn't fit anywhere else."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Tiny/parameterization.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Test the '->of' and '->where' shortcut methods."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Tiny/shortcuts.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Checks Type::Tiny works with the smartmatch operator."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Tiny/smartmatch.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Checks that all this Type[Param] syntactic sugar works. In particular, the following three type constraints are expected to be equivalent to each other: use Types::Standard qw( ArrayRef Int Num Str ); use Type::Utils qw( union intersection ); my $type1 = ArrayRef[Int] | ArrayRef[Num & ~Int] | ArrayRef[Str & ~Num]; my $type2 = union [ ArrayRef[Int], ArrayRef[Num & ~Int], ArrayRef[Str & ~Num], ]; my $type3 = union([ ArrayRef->parameterize(Int), ArrayRef->parameterize( intersection([ Num, Int->complementary_type, ]), ), ArrayRef->parameterize( intersection([ Str, Num->complementary_type, ]), ), ]);"; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Tiny/syntax.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Checks Type::Tiny objects can be converted to Moose type constraint objects."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Tiny/to-moose.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Checks Type::Tiny objects can be converted to Mouse type constraint objects."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Tiny/to-mouse.t"; ]; ]; nfo:fileName "lib/Type/Tiny.pm"; nfo:programmingLanguage "Perl". [] a nfo:FileDataObject, nfo:SourceCode; rdfs:label "Devel::TypeTiny::Perl58Compat"; doap-tests:unit_test [ a doap-tests:UnitTest; doap-tests:purpose "Checks 're::is_regexp()' works."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Devel-TypeTiny-Perl58Compat/basic.t"; ]; ]; nfo:fileName "lib/Devel/TypeTiny/Perl58Compat.pm"; nfo:programmingLanguage "Perl". [] a nfo:FileDataObject, nfo:SourceCode; rdfs:label "Type::Tiny::Class"; doap-tests:unit_test [ a doap-tests:UnitTest; doap-tests:purpose "Checks class type constraints work."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Tiny-Class/basic.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Checks class type constraints throw sane error messages."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Tiny-Class/errors.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Checks the 'Type::Tiny::Class''s 'plus_constructors' method."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Tiny-Class/plus-constructors.t"; ]; ]; nfo:fileName "lib/Type/Tiny/Class.pm"; nfo:programmingLanguage "Perl". [] a nfo:FileDataObject, nfo:SourceCode; rdfs:label "Type::Tiny::Duck"; doap-tests:unit_test [ a doap-tests:UnitTest; doap-tests:purpose "Checks duck type constraints work."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Tiny-Duck/basic.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Checks duck type constraints throw sane error messages."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Tiny-Duck/errors.t"; ]; ]; nfo:fileName "lib/Type/Tiny/Duck.pm"; nfo:programmingLanguage "Perl". [] a nfo:FileDataObject, nfo:SourceCode; rdfs:label "Type::Tiny::Enum"; doap-tests:unit_test [ a doap-tests:UnitTest; doap-tests:purpose "Checks enum type constraints work."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Tiny-Enum/basic.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Checks enum type constraints throw sane error messages."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Tiny-Enum/errors.t"; ]; ]; nfo:fileName "lib/Type/Tiny/Enum.pm"; nfo:programmingLanguage "Perl". [] a nfo:FileDataObject, nfo:SourceCode; rdfs:label "Type::Tiny::Intersection"; doap-tests:unit_test [ a doap-tests:UnitTest; doap-tests:purpose "Checks intersection type constraints work."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Tiny-Intersection/basic.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Checks intersection type constraints throw sane error messages."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Tiny-Intersection/errors.t"; ]; ]; nfo:fileName "lib/Type/Tiny/Intersection.pm"; nfo:programmingLanguage "Perl". [] a nfo:FileDataObject, nfo:SourceCode; rdfs:label "Error::TypeTiny"; doap-tests:unit_test [ a doap-tests:UnitTest; doap-tests:purpose "Tests for basic Error::TypeTiny functionality."; doap-tests:test_script _:B7; ], [ a doap-tests:UnitTest; doap-tests:purpose "Tests that Error::TypeTiny is capable of providing stack traces."; doap-tests:test_script _:B12; ]; nfo:fileName "lib/Error/TypeTiny.pm"; nfo:programmingLanguage "Perl". [] a nfo:FileDataObject, nfo:SourceCode; rdfs:label "Type::Tiny::Role"; doap-tests:unit_test [ a doap-tests:UnitTest; doap-tests:purpose "Checks role type constraints work."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Tiny-Role/basic.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Checks role type constraints throw sane error messages."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Tiny-Role/errors.t"; ]; ]; nfo:fileName "lib/Type/Tiny/Role.pm"; nfo:programmingLanguage "Perl". [] a nfo:FileDataObject, nfo:SourceCode; rdfs:label "Type::Tiny::Union"; doap-tests:unit_test [ a doap-tests:UnitTest; doap-tests:purpose "Checks union type constraints work."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Tiny-Union/basic.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Checks union type constraints throw sane error messages."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Tiny-Union/errors.t"; ]; ]; nfo:fileName "lib/Type/Tiny/Union.pm"; nfo:programmingLanguage "Perl". [] a nfo:FileDataObject, nfo:SourceCode; rdfs:label "Type::Tiny::_HalfOp"; doap-tests:unit_test [ a doap-tests:UnitTest; doap-tests:purpose "Ensure that the following works consistently on all supported Perls: ArrayRef[Int] | HashRef[Int]"; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Tiny-_HalfOp/overload-precedence.t"; ]; ]; nfo:fileName "lib/Type/Tiny/_HalfOp.pm"; nfo:programmingLanguage "Perl". [] a nfo:FileDataObject, nfo:SourceCode; rdfs:label "Type::Utils"; doap-tests:unit_test [ a doap-tests:UnitTest; doap-tests:purpose "Test Type::Utils 'classifier' function."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Utils/classifier.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Checks Moose type constraints, and MooseX::Types type constraints are picked up by 'dwim_type' from Type::Utils."; doap-tests:test_script _:B8; ], [ a doap-tests:UnitTest; doap-tests:purpose "Checks Mouse type constraints, and MouseX::Types type constraints are picked up by 'dwim_type' from Type::Utils."; doap-tests:test_script _:B9; ], [ a doap-tests:UnitTest; doap-tests:purpose "Test Type::Utils 'match_on_type' and 'compile_match_on_type' functions."; doap-tests:test_script _:B10; ], [ a doap-tests:UnitTest; doap-tests:purpose "Tests warnings raised by Type::Utils."; doap-tests:test_script _:B11; ]; nfo:fileName "lib/Type/Utils.pm"; nfo:programmingLanguage "Perl". _:B33 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Moose/native-attribute-traits.t". _:B34 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/MooseX-Getopt/coercion.t". _:B35 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/MooseX-Types/basic.t". _:B36 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/MooseX-Types/extending.t". _:B37 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/MooseX-Types/more.t". _:B38 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Mouse/basic.t". _:B39 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Mouse/coercion.t". _:B40 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/MouseX-Types/basic.t". _:B41 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/MouseX-Types/extending.t". _:B42 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Object-Accessor/basic.t". _:B43 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Return-Type/basic.t". _:B44 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Sub-Quote/basic.t". _:B45 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Sub-Quote/unquote-coercions.t". _:B46 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Sub-Quote/unquote-constraints.t". _:B47 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Switcheroo/basic.t". _:B48 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Type-Tie/basic.t". _:B49 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Validation-Class-Simple/archaic.t". _:B50 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Validation-Class-Simple/basic.t". _:B51 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/match-simple/basic.t". _:B52 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/40-regression/73f51e2d.t". _:B53 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/40-regression/gh1.t". _:B54 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/40-regression/ttxs-gh1.t". [] a nfo:FileDataObject; dc:license ; dc:rightsHolder ; nfo:fileName "CONTRIBUTING". [] a nfo:FileDataObject; dc:license ; dc:rightsHolder ; nfo:fileName "CREDITS". [] a nfo:FileDataObject, nfo:TextDocument; dc:license ; dc:rightsHolder ; nfo:fileName "Changes". [] a nfo:FileDataObject, nfo:TextDocument; dc:license ; dc:rightsHolder ; nfo:fileName "LICENSE". [] a nfo:FileDataObject; dc:license ; dc:rightsHolder ; nfo:fileName "META.ttl". [] a nfo:FileDataObject, nfo:SourceCode; dc:license ; dc:rightsHolder ; nfo:fileName "Makefile.PL"; nfo:programmingLanguage "Perl". [] a nfo:FileDataObject, nfo:TextDocument; dc:license ; dc:rightsHolder ; nfo:fileName "NEWS". [] a nfo:FileDataObject, nfo:TextDocument; dc:license ; dc:rightsHolder ; nfo:fileName "README". [] a nfo:FileDataObject, nfo:TextDocument; dc:license ; dc:rightsHolder ; nfo:fileName "TODO". [] a nfo:FileDataObject; dc:license ; dc:rightsHolder ; nfo:fileName "TODO.mm". [] a nfo:FileDataObject, nfo:SourceCode; dc:license ; dc:rightsHolder ; nfo:fileName "examples/benchmark-mkopt.pl"; nfo:programmingLanguage "Perl". [] a nfo:FileDataObject, nfo:SourceCode; dc:license ; dc:rightsHolder ; nfo:fileName "examples/benchmark-param-validation.pl"; nfo:programmingLanguage "Perl". [] a nfo:FileDataObject; dc:license ; dc:rightsHolder ; nfo:fileName "meta/changes.pret". [] a nfo:FileDataObject; dc:license ; dc:rightsHolder ; nfo:fileName "meta/doap.pret". [] a nfo:FileDataObject; dc:license ; dc:rightsHolder ; nfo:fileName "meta/makefile.pret". [] a nfo:FileDataObject; dc:license ; dc:rightsHolder ; nfo:fileName "meta/people.pret". [] a nfo:FileDataObject; dc:license ; dc:rightsHolder ; nfo:fileName "meta/rights.pret". [] a nfo:FileDataObject, nfo:SourceCode; dc:license ; dc:rightsHolder ; nfo:fileName "inc/Test/Fatal.pm"; nfo:programmingLanguage "Perl". [] a nfo:FileDataObject, nfo:SourceCode; dc:license ; dc:rightsHolder ; nfo:fileName "inc/Test/Requires.pm"; nfo:programmingLanguage "Perl". [] a nfo:FileDataObject, nfo:SourceCode; dc:license ; dc:rightsHolder ; nfo:fileName "inc/Try/Tiny.pm"; nfo:programmingLanguage "Perl". [] a nfo:FileDataObject; dc:license ; dc:rightsHolder ; nfo:fileName "MANIFEST.SKIP". [] a doap-tests:Test; doap-tests:purpose "Print some standard diagnostics before beginning testing."; doap-tests:test_script _:B5. [] a doap-tests:Test; doap-tests:purpose "Test that Type::Tiny, Type::Library, etc compile."; doap-tests:test_script _:B6. [] a doap-tests:IntegrationTest; doap-tests:purpose "Checks Type::Tiny works with Kavorka."; doap-tests:test_script _:B18. [] a doap-tests:IntegrationTest; doap-tests:purpose "Check type constraints work with Moo. Checks values that should pass and should fail; checks error messages."; doap-tests:test_script _:B19. [] a doap-tests:IntegrationTest; doap-tests:purpose "Check coercions work with Moo."; doap-tests:test_script _:B20. [] a doap-tests:IntegrationTest; doap-tests:purpose "Tests Error::TypeTiny interaction with Moo."; doap-tests:test_script _:B21. [] a doap-tests:IntegrationTest; doap-tests:purpose "Checks that type constraints continue to work when a Moo class is inflated to a Moose class. Checks that Moo::HandleMoose correctly calls back to Type::Tiny to build Moose type constraints."; doap-tests:test_script _:B22. [] a doap-tests:IntegrationTest; doap-tests:purpose "A test for type constraint inflation from Moo to Moose."; doap-tests:test_script _:B23. [] a doap-tests:IntegrationTest; doap-tests:purpose "Check that type constraints work in Moops. This file is borrowed from the Moops test suite, where it is called '31types.t'."; doap-tests:test_script _:B24. [] a doap-tests:IntegrationTest; doap-tests:purpose "Check that type libraries can be declared with Moops. This file is borrowed from the Moops test suite, where it is called '71library.t'."; doap-tests:test_script _:B25. [] a doap-tests:IntegrationTest; doap-tests:purpose "Check that Moose type constraints can be passed into the Type::Tiny API where a Type::Tiny constraint might usually be expected."; doap-tests:test_script _:B26. [] a doap-tests:IntegrationTest; doap-tests:purpose "Check type constraints work with Moose. Checks values that should pass and should fail; checks error messages."; doap-tests:test_script _:B27. [] a doap-tests:IntegrationTest; doap-tests:purpose "Check coercions work with Moose; both mutable and immutable classes."; doap-tests:test_script _:B28. [] a doap-tests:IntegrationTest; doap-tests:purpose "Check type constraint inlining works with Moose in strange edge cases where we need to inflate Type::Tiny constraints into full Moose::Meta::TypeConstraint objects."; doap-tests:test_script _:B29. [] a doap-tests:IntegrationTest; doap-tests:purpose "Check type constraints and coercions work with Moose native attibute traits."; doap-tests:test_script _:B33. [] a doap-tests:IntegrationTest; doap-tests:purpose "Check coercions work with MooseX::Getopt; both mutable and immutable classes."; doap-tests:test_script _:B34. [] a doap-tests:IntegrationTest; doap-tests:purpose "Complex checks between Type::Tiny and MooseX::Types."; doap-tests:test_script _:B35. [] a doap-tests:IntegrationTest; doap-tests:purpose "Check that Type::Library can extend an existing MooseX::Types type constraint library."; doap-tests:test_script _:B36. [] a doap-tests:IntegrationTest; doap-tests:purpose "More checks between Type::Tiny and MooseX::Types. This started out as an example of making a parameterized 'Not[]' type constraint, but worked out as a nice test case."; doap-tests:test_script _:B37. [] a doap-tests:IntegrationTest; doap-tests:purpose "Check type constraints work with Mouse. Checks values that should pass and should fail; checks error messages."; doap-tests:test_script _:B38. [] a doap-tests:IntegrationTest; doap-tests:purpose "Check coercions work with Mouse; both mutable and immutable classes."; doap-tests:test_script _:B39. [] a doap-tests:IntegrationTest; doap-tests:purpose "Complex checks between Type::Tiny and MouseX::Types."; doap-tests:test_script _:B40. [] a doap-tests:IntegrationTest; doap-tests:purpose "Check that Type::Library can extend an existing MooseX::Types type constraint library."; doap-tests:test_script _:B41. [] a doap-tests:IntegrationTest; doap-tests:purpose "Check type constraints work with Object::Accessor."; doap-tests:test_script _:B42. [] a doap-tests:IntegrationTest; doap-tests:purpose "Test that this sort of thing works: sub foo :ReturnType(Int) { ...; }"; doap-tests:test_script _:B43. [] a doap-tests:IntegrationTest; doap-tests:purpose "Check type constraints can be made inlinable using Sub::Quote."; doap-tests:test_script _:B44. [] a doap-tests:IntegrationTest; doap-tests:purpose "Check type coercions can be unquoted Sub::Quote."; doap-tests:test_script _:B45. [] a doap-tests:IntegrationTest; doap-tests:purpose "Check type constraints can be unquoted Sub::Quote."; doap-tests:test_script _:B46. [] a doap-tests:IntegrationTest; doap-tests:purpose "Checks Type::Tiny works with Switcheroo."; doap-tests:test_script _:B47. [] a doap-tests:IntegrationTest; doap-tests:purpose "Test that this sort of thing works: tie my $var, Int;"; doap-tests:test_script _:B48. [] a doap-tests:IntegrationTest; doap-tests:purpose "Fake Validation::Class::Simple 7.900017 by overriding '$VERSION' variable. (There is a reason for this... 'Types::TypeTiny::to_TypeTiny' follows two different code paths depending on the version of the Validation::Class::Simple object passed to it.)"; doap-tests:test_script _:B49. [] a doap-tests:IntegrationTest; doap-tests:purpose "Check type constraints Validation::Class::Simple objects can be used as type constraints."; doap-tests:test_script _:B50. [] a doap-tests:IntegrationTest; doap-tests:purpose "Checks Type::Tiny works with match::simple."; doap-tests:test_script _:B51. [] a doap-tests:RegressionTest; doap-tests:purpose "Possible issue causing segfaults on threaded Perl 5.18.x."; doap-tests:test_script _:B52. [] a doap-tests:RegressionTest; doap-tests:purpose "Test that subtypes of Type::Tiny::Class work."; doap-tests:test_script _:B53. [] a doap-tests:RegressionTest; doap-tests:purpose "Test that was failing with Type::Tiny::XS prior to 0.009."; doap-tests:test_script _:B54. [] a doap-tests:Test; doap-tests:purpose "Test that Type::Tiny and Type::Coercion provide a Moose/Mouse-compatible API."; doap-tests:test_script _:B30. [] a doap-tests:Test; doap-tests:purpose "Check for memory leaks. These tests are not comprehensive; chances are that there are still memory leaks lurking somewhere in Type::Tiny. If you have any concrete suggestions for things to test, or fixes for identified memory leaks, please file a bug report. https://rt.cpan.org/Ticket/Create.html?Queue=Type-Tiny."; doap-tests:test_script _:B31. [] a doap-tests:Test; doap-tests:purpose "Type constraint tests pilfered from the Moose test suite."; doap-tests:test_script _:B32. [] a doap-tests:IntegrationTest; doap-tests:purpose "Check type constraints work with Class::InsideOut."; doap-tests:test_script _:B13. [] a doap-tests:IntegrationTest; doap-tests:purpose "Tests Exporter::Tiny has the features Type::Tiny needs."; doap-tests:test_script _:B14. [] a doap-tests:IntegrationTest; doap-tests:purpose "Tests Type::Library libraries work with Sub::Exporter plugins."; doap-tests:test_script _:B15. [] a doap-tests:IntegrationTest; doap-tests:purpose "Tests exporting to two roles; tries to avoid reporting conflicts."; doap-tests:test_script _:B16. [] a doap-tests:IntegrationTest; doap-tests:purpose "Check type constraints work with Function::Parameters."; doap-tests:test_script _:B17. benchmark-coercions.pl000664001750001750 673212422772210 20476 0ustar00taitai000000000000Type-Tiny-1.000005/examples=pod =encoding utf-8 =head1 PURPOSE Compares the speed of the constructor in four equivalent classes built using different tools: =over =item B L with L types and non-L coderef coercions. =item B L with L types and coercions. =item B L with L type constraints and coderef coercions. Class is made immutable. =item B L with L type constraints and coercions. Class is made immutable. =back =head1 RESULTS For both Moose and Moo, L type constraints are clearly faster than the conventional approach. B<< With Type::Tiny::XS: >> Rate Moo_MXTML Moose Moo_TT Moose_TT Moo_MXTML 3040/s -- -44% -64% -83% Moose 5463/s 80% -- -35% -69% Moo_TT 8373/s 175% 53% -- -52% Moose_TT 17612/s 479% 222% 110% -- B<< Without Type::Tiny::XS: >> Rate Moo_MXTML Moo_TT Moose Moose_TT Moo_MXTML 3140/s -- -41% -50% -63% Moo_TT 5288/s 68% -- -16% -38% Moose 6305/s 101% 19% -- -26% Moose_TT 8574/s 173% 62% 36% -- (Tested versions: Type::Tiny 0.045_03, Type::Tiny::XS 0.004, Moose 2.1207, Moo 1.005000, and MooX::Types::MooseLike 0.25.) =head1 DEPENDENCIES To run this script, you will need: L, L, L, L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Benchmark ':all'; { package Local::Moo_MXTML; use Moo; use MooX::Types::MooseLike::Base qw(HashRef ArrayRef Int is_Int); has attr1 => ( is => "ro", isa => ArrayRef[Int], coerce => sub { is_Int($_[0]) ? [ $_[0] ] : $_[0] }, ); has attr2 => ( is => "ro", isa => HashRef[ArrayRef[Int]], ); } { package Local::Moo_TT; use Moo; use Types::Standard qw(HashRef ArrayRef Int); my $AofI = (ArrayRef[Int])->plus_coercions(Int, '[$_]'); has attr1 => ( is => "ro", isa => $AofI, coerce => $AofI->coercion, ); has attr2 => ( is => "ro", isa => HashRef[ArrayRef[Int]], ); } { package Local::Moose; use Moose; use Moose::Util::TypeConstraints qw(subtype as coerce from via); subtype "AofI", as "ArrayRef[Int]"; coerce "AofI", from "Int", via { [$_] }; has attr1 => ( is => "ro", isa => "AofI", coerce => 1, ); has attr2 => ( is => "ro", isa => "HashRef[ArrayRef[Int]]", ); __PACKAGE__->meta->make_immutable; } { package Local::Moose_TT; use Moose; use Types::Standard qw(HashRef ArrayRef Int); use Sub::Quote; my $AofI = (ArrayRef[Int])->plus_coercions(Int, '[$_]'); has attr1 => ( is => "ro", isa => $AofI, coerce => 1, ); has attr2 => ( is => "ro", isa => HashRef[ArrayRef[Int]], ); __PACKAGE__->meta->make_immutable; } our %data = ( attr1 => 4, attr2 => { one => [0 .. 1], two => [0 .. 2], three => [0 .. 3], }, ); cmpthese(-1, { Moo_MXTML => q{ Local::Moo_MXTML->new(%::data) }, Moo_TT => q{ Local::Moo_TT->new(%::data) }, Moose_TT => q{ Local::Moose_TT->new(%::data) }, Moose => q{ Local::Moose->new(%::data) }, }); benchmark-constraints.pl000664001750001750 1144012422772210 21071 0ustar00taitai000000000000Type-Tiny-1.000005/examples=pod =encoding utf-8 =head1 PURPOSE Compares the speed of the constructor in six equivalent classes built using different tools: =over =item B L with L types. =item B L with L types. =item B L with L type constraints. Class is made immutable. =item B L with L type constraints. Class is made immutable. =item B L with L type constraints. Class is made immutable. B<< XS is switched off using C environment variable. >> =item B L with L type constraints. Class is made immutable. B<< XS is switched off using C environment variable. >> =back Each tool is used to define a class like the following: { package Local::Class; use Whatever::Tool; use Types::Standard qw(HashRef ArrayRef Int); has attr1 => (is => "ro", isa => ArrayRef[Int]); has attr2 => (is => "ro", isa => HashRef[ArrayRef[Int]]); } Then we benchmark the following object instantiation: Local::Class->new( attr1 => [1..10], attr2 => { one => [0 .. 1], two => [0 .. 2], three => [0 .. 3], }, ); =head1 RESULTS In all cases, L type constraints are clearly faster than the conventional approach. B<< With Type::Tiny::XS: >> Rate Moo_MXTML Mouse Moose Moo_TT Moose_TT Mouse_TT Moo_MXTML 2428/s -- -35% -57% -82% -90% -91% Mouse 3759/s 55% -- -33% -72% -85% -86% Moose 5607/s 131% 49% -- -58% -78% -79% Moo_TT 13274/s 447% 253% 137% -- -48% -51% Moose_TT 25358/s 945% 575% 352% 91% -- -7% Mouse_TT 27306/s 1025% 626% 387% 106% 8% -- B<< Without Type::Tiny::XS: >> Rate Moo_MXTML Mouse Moo_TT Moose Moose_TT Mouse_TT Moo_MXTML 2610/s -- -31% -56% -56% -67% -67% Mouse 3759/s 44% -- -36% -37% -52% -52% Moo_TT 5894/s 126% 57% -- -1% -24% -25% Moose 5925/s 127% 58% 1% -- -24% -25% Moose_TT 7802/s 199% 108% 32% 32% -- -1% Mouse_TT 7876/s 202% 110% 34% 33% 1% -- (Tested versions: Type::Tiny 0.045_03, Type::Tiny::XS 0.004, Moose 2.1207, Moo 1.005000, MooX::Types::MooseLike 0.25, and Mouse 2.3.0) =head1 DEPENDENCIES To run this script, you will need: L, L, L, L, L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Benchmark ':all'; BEGIN { $ENV{MOUSE_PUREPERL} = 1 }; { package Local::Moo_MXTML; use Moo; use MooX::Types::MooseLike::Base qw(HashRef ArrayRef Int); has attr1 => (is => "ro", isa => ArrayRef[Int]); has attr2 => (is => "ro", isa => HashRef[ArrayRef[Int]]); } { package Local::Moo_TT; use Moo; use Types::Standard qw(HashRef ArrayRef Int); has attr1 => (is => "ro", isa => ArrayRef[Int]); has attr2 => (is => "ro", isa => HashRef[ArrayRef[Int]]); } { package Local::Moose; use Moose; has attr1 => (is => "ro", isa => "ArrayRef[Int]"); has attr2 => (is => "ro", isa => "HashRef[ArrayRef[Int]]"); __PACKAGE__->meta->make_immutable; } { package Local::Moose_TT; use Moose; use Types::Standard qw(HashRef ArrayRef Int); has attr1 => (is => "ro", isa => ArrayRef[Int]); has attr2 => (is => "ro", isa => HashRef[ArrayRef[Int]]); __PACKAGE__->meta->make_immutable; } { package Local::Mouse; use Mouse; has attr1 => (is => "ro", isa => "ArrayRef[Int]"); has attr2 => (is => "ro", isa => "HashRef[ArrayRef[Int]]"); __PACKAGE__->meta->make_immutable; } { package Local::Mouse_TT; use Mouse; use Types::Standard qw(HashRef ArrayRef Int); has attr1 => (is => "ro", isa => ArrayRef[Int]); has attr2 => (is => "ro", isa => HashRef[ArrayRef[Int]]); __PACKAGE__->meta->make_immutable; } our %data = ( attr1 => [1..10], attr2 => { one => [0 .. 1], two => [0 .. 2], three => [0 .. 3], }, ); cmpthese(-1, { Moo_MXTML => q{ Local::Moo_MXTML->new(%::data) }, Moose => q{ Local::Moose->new(%::data) }, Mouse => q{ Local::Mouse->new(%::data) }, Moo_TT => q{ Local::Moo_TT->new(%::data) }, Moose_TT => q{ Local::Moose_TT->new(%::data) }, Mouse_TT => q{ Local::Mouse_TT->new(%::data) }, }); benchmark-param-validation.pl000664001750001750 1366112422772210 21761 0ustar00taitai000000000000Type-Tiny-1.000005/examples=pod =encoding utf-8 =head1 TEST 1: COMPLEX PARAMETER CHECKING Compares the run-time speed of five parameter validators for validating a fairly complex function signature. The function accepts an arrayref, followed by an object providing C and C methods, followed by an integer less than 90. The validators tested were: =over =item B (shown as B in results table) Using the C trait. =item B (shown as B in results table) C given the following spec: state $spec = [ { type => ARRAYREF, }, { can => ["print", "say"], }, { type => SCALAR, regex => qr{^\d+$}, callbacks => { 'less than 90' => sub { shift() < 90 }, }, }, ]; =item B (shown as B in results table) Given three coderefs to validate parameters. =item B<< Type::Params::validate() >> (shown as B<< T:P v >> in results table) Called as: validate(\@_, ArrayRef, $PrintAndSay, $SmallInt); Where C<< $PrintAndSay >> is a duck type, and C<< $SmallInt >> is a subtype of C<< Int >>, with inlining defined. =item B<< Type::Params::compile() >> (shown as B<< T:P c >> in results table) Using the same type constraints as C<< validate() >> =back =head2 Results B<< With Type::Tiny::XS: >> Rate [D:V] [P:V] [P:C] [T:P v] [T:P c] [D:V] 10324/s -- -8% -35% -48% -81% [P:V] 11247/s 9% -- -29% -43% -80% [P:C] 15941/s 54% 42% -- -19% -71% [T:P v] 19685/s 91% 75% 23% -- -64% [T:P c] 55304/s 436% 392% 247% 181% -- B<< Without Type::Tiny::XS: >> Rate [P:V] [D:V] [P:C] [T:P v] [T:P c] [P:V] 9800/s -- -7% -8% -41% -72% [D:V] 10500/s 7% -- -1% -37% -71% [P:C] 10609/s 8% 1% -- -36% -70% [T:P v] 16638/s 70% 58% 57% -- -53% [T:P c] 35628/s 264% 239% 236% 114% -- (Tested versions: Data::Validator 1.04 with Mouse 2.3.0, Params::Validate 1.10, Params::Check 0.38, and Type::Params 0.045_03 with Type::Tiny::XS 0.004.) =head1 TEST B: SIMPLE PARAMETER CHECKING Based on the idea that I was playing to Type::Params' strengths, I decided on something I thought would be more of a challenge: a simpler function signature which takes two required and one optional parameters. This is purely a test of parameter count; no type checking is involved! This is a face off between Type::Params and Params::Validate. =head2 Results Because no type checks are involved, it doesn't matter whether Type::Tiny::XS is available or not. (The results are similar either way.) Rate [P:V] [T:P c] [P:V] 73643/s -- -70% [T:P c] 241917/s 228% -- =head1 DEPENDENCIES To run this script, you will need: L, L, L, L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use feature qw(state); use Benchmark qw(cmpthese); # In today's contest, we'll be comparing Type::Params... # use Type::Params qw( compile validate ); use Type::Utils; use Types::Standard qw( -types ); # ... with Params::Validate... # BEGIN { $ENV{PARAMS_VALIDATE_IMPLEMENTATION} = 'XS' }; # ... which we'll give a fighting chance use Params::Validate qw( validate_pos ARRAYREF SCALAR ); # ... and Data::Validator... use Data::Validator (); use Mouse::Util::TypeConstraints (); # ... and Params::Check... use Params::Check (); # Define custom type constraints... my $PrintAndSay = duck_type PrintAndSay => ["print", "say"]; my $SmallInt = declare SmallInt => as Int, where { $_ < 90 }, inline_as { $_[0]->parent->inline_check($_)." and $_ < 90" }; # ... and for Mouse... my $PrintAndSay2 = Mouse::Util::TypeConstraints::duck_type(PrintAndSay => ["print", "say"]); my $SmallInt2 = Mouse::Util::TypeConstraints::subtype( "SmallInt", Mouse::Util::TypeConstraints::as("Int"), Mouse::Util::TypeConstraints::where(sub { $_ < 90 }), ); sub TypeParams_validate { my @in = validate(\@_, ArrayRef, $PrintAndSay, $SmallInt); } sub TypeParams_compile { state $spec = compile(ArrayRef, $PrintAndSay, $SmallInt); my @in = $spec->(@_); } sub ParamsValidate { state $spec = [ { type => ARRAYREF }, { can => ["print", "say"] }, { type => SCALAR, regex => qr{^\d+$}, callbacks => { 'less than 90' => sub { shift() < 90 } } }, ]; my @in = validate_pos(@_, @$spec); } sub ParamsCheck { state $spec = [ [sub { ref $_[0] eq 'ARRAY' }], [sub { Scalar::Util::blessed($_[0]) and $_[0]->can("print") and $_[0]->can("say") }], [sub { !ref($_[0]) and $_[0] =~ m{^\d+$} and $_[0] < 90 }], ]; # Params::Check::check doesn't support positional parameters. # Params::Check::allow fakery instead. my @in = map { Params::Check::allow($_[$_], $spec->[$_]) ? $_[$_] : die } 0..$#$spec; } sub DataValidator { state $spec = "Data::Validator"->new( first => "ArrayRef", second => $PrintAndSay2, third => $SmallInt2, )->with("StrictSequenced"); my @in = $spec->validate(@_); } # Actually run the benchmarks... # use IO::Handle (); our @data = ( [1, 2, 3], IO::Handle->new, 50, ); cmpthese(-3, { '[D:V]' => q{ DataValidator(@::data) }, '[P:V]' => q{ ParamsValidate(@::data) }, '[P:C]' => q{ ParamsCheck(@::data) }, '[T:P v]' => q{ TypeParams_validate(@::data) }, '[T:P c]' => q{ TypeParams_compile(@::data) }, }); # Now we'll just do a simple check of argument count; not checking any types! print "\n----\n\n"; our $CHK = compile(1, 1, 0); our @ARGS = 1..2; cmpthese(-3, { '[T:P c]' => q { $::CHK->(@::ARGS) }, '[P:V]' => q { validate_pos(@::ARGS, 1, 1, 0) }, }); datetime-coercions.pl000664001750001750 525112422772210 20333 0ustar00taitai000000000000Type-Tiny-1.000005/examples=pod =encoding utf-8 =head1 PURPOSE This example expands upon the Example::Types library defined in L. It defines class types for L and L and some structured types for hashes that can be used to instantiate DateTime objects. It defines some coercions for the C class type. A simple L class is provided using some of these types and coercions. The class also defines a couple of extra coercions inline. See the source code of this file for the actual example code. =head1 DEPENDENCIES L, L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib "lib", "../lib"; BEGIN { package Example::Types; use Type::Library -base, -declare => qw( Datetime DatetimeHash Duration EpochHash ); use Type::Utils; use Types::Standard -types; require DateTime; require DateTime::Duration; class_type Datetime, { class => "DateTime" }; class_type Duration, { class => "DateTime::Duration" }; declare DatetimeHash, as Dict[ year => Int, month => Optional[ Int ], day => Optional[ Int ], hour => Optional[ Int ], minute => Optional[ Int ], second => Optional[ Int ], nanosecond => Optional[ Int ], time_zone => Optional[ Str ], ]; declare EpochHash, as Dict[ epoch => Int, time_zone => Optional[ Str ], ]; coerce Datetime, from Int, via { "DateTime"->from_epoch(epoch => $_) }, from Undef, via { "DateTime"->now }, from DatetimeHash, via { "DateTime"->new(%$_) }, from EpochHash, via { "DateTime"->from_epoch(%$_) }; $INC{"Example/Types.pm"} = __FILE__; }; BEGIN { package Person; use Moose; use Types::Standard qw( Str Int Num ); use Example::Types qw( Datetime Duration ); has name => ( is => "ro", isa => Str, required => 1, ); has age => ( is => "ro", isa => Int->plus_coercions(Num, 'int($_)', Duration, '$_->years'), coerce => 1, init_arg => undef, lazy => 1, builder => "_build_age", ); has date_of_birth => ( is => "ro", isa => Datetime, coerce => 1, required => 1, ); sub _build_age { my $self = shift; return Datetime->class->now - $self->date_of_birth; } }; my $me = Person->new( name => "Toby Inkster", date_of_birth => { epoch => 328646500, time_zone => "Asia/Tokyo" }, ); printf("%s is %d years old.\n", $me->name, $me->age); versus-scalar-validation.pl000664001750001750 400312422772210 21471 0ustar00taitai000000000000Type-Tiny-1.000005/examplesuse strict; use warnings; use Test::More; use Test::Fatal; use Test::Benchmark; use Benchmark qw(timethis); $Test::Benchmark::VERBOSE = 1; { package UseSV; use Scalar::Validation qw(:all); sub test { my $p_bool = par p_bool => -Enum => [0 => '1'] => shift; my $p_123 = par p_123 => -Enum => {1 => 1, 2 => 1, 3 => 1} => shift; my $p_free = par p_free => sub { $_ > 5 } => shift, sub { "$_ is not larger than 5" }; p_end \@_; return $p_bool + $p_123 + $p_free; } } { package UseTP; use Type::Params qw(compile); use Types::Standard qw(Enum); use Types::XSD::Lite qw(Integer); my $_check = compile Enum[0,1], Enum[1..3], Integer[minExclusive => 5]; sub test { my ($p_bool, $p_123, $p_free) = $_check->(@_); return $p_bool + $p_123 + $p_free; } } subtest "Scalar::Validation works ok" => sub { is( UseSV::test(1,2,7), 10 ); like( exception { UseSV::test(2,2,2) }, qr/^Error/, ); }; subtest "Type::Params works ok" => sub { is( UseTP::test(1,2,7), 10 ); like( exception { UseTP::test(2,2,2) }, qr/did not pass type constraint/, ); }; is_fastest('TP', -1, { SV => q[ UseSV::test(1,2,7) ], TP => q[ UseTP::test(1,2,7) ], }, 'Type::Params is fastest at passing validations'); is_fastest('TP', -1, { SV => q[ eval { UseSV::test(1,2,3) } ], TP => q[ eval { UseTP::test(1,2,3) } ], }, 'Type::Params is fastest at failing validations'); done_testing; __END__ # Subtest: Scalar::Validation works ok ok 1 ok 2 1..2 ok 1 - Scalar::Validation works ok # Subtest: Type::Params works ok ok 1 ok 2 1..2 ok 2 - Type::Params works ok ok 3 - Type::Params is fastest at passing validations # TP - 2 wallclock secs ( 1.17 usr + 0.00 sys = 1.17 CPU) @ 6564.10/s (n=7680) # SV - 1 wallclock secs ( 1.03 usr + 0.00 sys = 1.03 CPU) @ 4744.66/s (n=4887) ok 4 - Type::Params is fastest at failing validations # TP - 1 wallclock secs ( 1.05 usr + 0.00 sys = 1.05 CPU) @ 3412.38/s (n=3583) # SV - 1 wallclock secs ( 1.07 usr + 0.03 sys = 1.10 CPU) @ 1285.45/s (n=1414) 1..4 00-begin.t000664001750001750 317112422772210 14332 0ustar00taitai000000000000Type-Tiny-1.000005/t=pod =encoding utf-8 =head1 PURPOSE Print some standard diagnostics before beginning testing. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; sub diag_version { my ($module, $version) = @_; $version = eval "require $module; $module->VERSION" unless defined $version; return diag sprintf(' %-30s undef', $module) unless defined $version; my ($major, $rest) = split /\./, $version; return diag sprintf(' %-30s % 4d.%s', $module, $major, $rest); } sub diag_env { require B; require Devel::TypeTiny::Perl56Compat; my $var = shift; return diag sprintf(' $%-30s %s', $var, exists $ENV{$var} ? B::perlstring($ENV{$var}) : "undef"); } while () { chomp; if (/^#\s*(.*)$/ or /^$/) { diag($1 || ""); next; } if (/^\$(.+)$/) { diag_env($1); next; } if (/^perl$/) { diag_version("Perl", $]); next; } diag_version($_) if /\S/; } require Types::Standard; diag(""); diag( !Types::Standard::Str()->_has_xsub ? ">>>> Type::Tiny is not using XS" : $INC{'Type/Tiny/XS.pm'} ? ">>>> Type::Tiny is using Type::Tiny::XS" : ">>>> Type::Tiny is using Mouse::XS" ); diag(""); ok 1; done_testing; __END__ perl Exporter::Tiny Type::Tie Type::Tiny::XS Moo Moose Mouse $AUTOMATED_TESTING $NONINTERACTIVE_TESTING $EXTENDED_TESTING $AUTHOR_TESTING $RELEASE_TESTING $PERL_TYPE_TINY_XS $PERL_TYPES_STANDARD_STRICTNUM $PERL_ONLY 01-compile.t000664001750001750 215312422772210 14676 0ustar00taitai000000000000Type-Tiny-1.000005/t=pod =encoding utf-8 =head1 PURPOSE Test that Type::Tiny, Type::Library, etc compile. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; use_ok("Eval::TypeTiny"); use_ok("Test::TypeTiny"); use_ok("Type::Coercion"); use_ok("Type::Coercion::Union"); use_ok("Error::TypeTiny"); use_ok("Error::TypeTiny::Assertion"); use_ok("Error::TypeTiny::Compilation"); use_ok("Error::TypeTiny::WrongNumberOfParameters"); use_ok("Type::Library"); use_ok("Types::Standard"); use_ok("Types::TypeTiny"); use_ok("Type::Tiny"); use_ok("Type::Tiny::Class"); use_ok("Type::Tiny::Duck"); use_ok("Type::Tiny::Enum"); use_ok("Type::Tiny::Intersection"); use_ok("Type::Tiny::Role"); use_ok("Type::Tiny::Union"); use_ok("Type::Utils"); use_ok("Type::Params"); BAIL_OUT("Further tests rely on all modules compiling.") unless "Test::Builder"->new->is_passing; done_testing; 02-api.t000664001750001750 472612422772210 14030 0ustar00taitai000000000000Type-Tiny-1.000005/t=pod =encoding utf-8 =head1 PURPOSE Test that Type::Tiny and Type::Coercion provide a Moose/Mouse-compatible API. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; my $HAVE_MOOSE = eval { require Moose }; my @MOOSE_WANTS = qw( _actually_compile_type_constraint _collect_all_parents _compile_subtype _compile_type _compiled_type_constraint _default_message _has_compiled_type_constraint _has_inlined_type_constraint _inline_check _inline_environment _new _package_defined_in _set_constraint assert_coerce assert_valid can_be_inlined check coerce coercion compile_type_constraint constraint create_child_type equals get_message has_coercion has_message has_parent inline_environment inlined is_a_type_of is_subtype_of message meta name new parent parents validate ); my $HAVE_MOUSE = eval { require Mouse }; my @MOUSE_WANTS = qw( __is_parameterized _add_type_coercions _as_string _compiled_type_coercion _compiled_type_constraint _identity _unite assert_valid check coerce compile_type_constraint create_child_type get_message has_coercion is_a_type_of message name new parameterize parent type_parameter ); require Type::Tiny; my $type = "Type::Tiny"->new(name => "TestType"); for (@MOOSE_WANTS) { SKIP: { skip "Moose::Meta::TypeConstraint PRIVATE API: '$_'", 1 if /^_/ && !$HAVE_MOOSE; ok($type->can($_), "Moose::Meta::TypeConstraint API: $type->can('$_')"); } } for (@MOUSE_WANTS) { SKIP: { skip "Mouse::Meta::TypeConstraint PRIVATE API: '$_'", 1 if /^_/ && !$HAVE_MOUSE; ok($type->can($_), "Mouse::Meta::TypeConstraint API: $type->can('$_')"); } } my @MOOSE_WANTS_COERCE = qw( _compiled_type_coercion _new add_type_coercions coerce compile_type_coercion has_coercion_for_type meta new type_coercion_map type_constraint ); require Type::Coercion; my $coerce = "Type::Coercion"->new(name => "TestCoercion"); for (@MOOSE_WANTS_COERCE) { SKIP: { skip "Moose::Meta::TypeCoercion PRIVATE API: '$_'", 1 if /^_/ && !$HAVE_MOOSE; ok($coerce->can($_), "Moose::Meta::TypeCoercion API: $coerce->can('$_')"); } } BAIL_OUT("Further tests rely on the Type::Tiny and Type::Coercion APIs.") unless "Test::Builder"->new->is_passing; done_testing; 03-leak.t000664001750001750 416212422772210 14166 0ustar00taitai000000000000Type-Tiny-1.000005/t=pod =encoding utf-8 =head1 PURPOSE Check for memory leaks. These tests are not comprehensive; chances are that there are still memory leaks lurking somewhere in Type::Tiny. If you have any concrete suggestions for things to test, or fixes for identified memory leaks, please file a bug report. L. =head1 DEPENDENCIES L. This test is skipped on Perl < 5.10.1 because I'm not interested in jumping through hoops for ancient versions of Perl. =head1 MISC ATTRIBUTE DECORATION If Perl has been compiled with Misc Attribute Decoration (MAD) enabled, then this test may fail. If you don't know what MAD is, then don't worry: you probably don't have it enabled. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Config; BEGIN { plan skip_all => 'Devel::Cover' if $INC{'Devel/Cover.pm'} }; BEGIN { plan skip_all => 'Perl < 5.10.1' if $] < 5.010001 }; BEGIN { plan skip_all => 'useithreads' if $Config{'useithreads'} }; use Test::Requires 'Test::LeakTrace'; use Test::LeakTrace; use Types::Standard qw( ArrayRef HashRef ); eval { require Moo }; no_leaks_ok { my $x = Type::Tiny->new; undef($x); } 'Type::Tiny->new'; no_leaks_ok { my $x = Type::Tiny->new->coercibles; undef($x); } 'Type::Tiny->new->coercible'; no_leaks_ok { my $x = ArrayRef | HashRef; my $y = HashRef | ArrayRef; undef($_) for $x, $y; } 'ArrayRef | HashRef'; no_leaks_ok { my $x = ArrayRef[HashRef]; my $y = HashRef[ArrayRef]; undef($_) for $x, $y; } 'ArrayRef[HashRef]'; no_leaks_ok { my $x = Type::Tiny->new; $x->check(1); undef($x); } 'Type::Tiny->new->check'; no_leaks_ok { my $x = ArrayRef->plus_coercions(HashRef, sub { [sort keys %$_] }); my $a = $x->coerce({bar => 1, baz => 2}); undef($_) for $x, $a; } 'ArrayRef->plus_coercions->coerce'; done_testing; 99-moose-std-types-test.t000664001750001750 4666312422772210 17356 0ustar00taitai000000000000Type-Tiny-1.000005/t=pod =encoding utf-8 =head1 PURPOSE Type constraint tests pilfered from the L test suite. =head1 DEPENDENCIES Test is skipped if Moose 2.0600 is not available. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE, but largely derived from the Moose test suite. Moose is maintained by the Moose Cabal, along with the help of many contributors. See "CABAL" in Moose and "CONTRIBUTORS" in Moose for details. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Infinity Interactive, Inc.. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut #!/usr/bin/perl use Test::More; BEGIN { $ENV{PERL_TYPES_STANDARD_STRICTNUM} = 1; }; BEGIN { $ENV{AUTOMATED_TESTING} or $ENV{EXTENDED_TESTING} or $ENV{AUTHOR_TESTING} or $ENV{RELEASE_TESTING} or plan skip_all => 'set EXTENDED_TESTING to true if you want to run this test' }; use strict; use warnings; use Test::Fatal; use Test::Requires { 'Moose' => '2.0600' }; use Eval::TypeTiny; use IO::File; use Scalar::Util qw( blessed openhandle ); use Type::Utils { replace => 1 }, -all; use Types::Standard; my $ZERO = 0; my $ONE = 1; my $INT = 100; my $NEG_INT = -100; my $NUM = 42.42; my $NEG_NUM = -42.42; my $EMPTY_STRING = q{}; my $STRING = 'foo'; my $NUM_IN_STRING = 'has 42 in it'; my $INT_WITH_NL1 = "1\n"; my $INT_WITH_NL2 = "\n1"; my $SCALAR_REF = \( my $var ); my $SCALAR_REF_REF = \$SCALAR_REF; my $ARRAY_REF = []; my $HASH_REF = {}; my $CODE_REF = sub { }; my $GLOB = do { no warnings 'once'; *GLOB_REF }; my $GLOB_REF = \$GLOB; open my $FH, '<', $0 or die "Could not open $0 for the test"; my $FH_OBJECT = IO::File->new( $0, 'r' ) or die "Could not open $0 for the test"; my $REGEX = qr/../; my $REGEX_OBJ = bless qr/../, 'BlessedQR'; my $FAKE_REGEX = bless {}, 'Regexp'; my $OBJECT = bless {}, 'Foo'; my $UNDEF = undef; { package Thing; sub new { } sub foo { } } my $CLASS_NAME = 'Thing'; { package Role; use Moose::Role; sub foo { } } my $ROLE_NAME = 'Role'; my %tests = ( Any => { accept => [ $ZERO, $ONE, $INT, $NEG_INT, $NUM, $NEG_NUM, $EMPTY_STRING, $STRING, $NUM_IN_STRING, $INT_WITH_NL1, $INT_WITH_NL2, $SCALAR_REF, $SCALAR_REF_REF, $ARRAY_REF, $HASH_REF, $CODE_REF, $GLOB, $GLOB_REF, $FH, $FH_OBJECT, $REGEX, $REGEX_OBJ, $FAKE_REGEX, $OBJECT, $UNDEF, ], }, Item => { accept => [ $ZERO, $ONE, $INT, $NEG_INT, $NUM, $NEG_NUM, $EMPTY_STRING, $STRING, $NUM_IN_STRING, $INT_WITH_NL1, $INT_WITH_NL2, $SCALAR_REF, $SCALAR_REF_REF, $ARRAY_REF, $HASH_REF, $CODE_REF, $GLOB, $GLOB_REF, $FH, $FH_OBJECT, $REGEX, $REGEX_OBJ, $FAKE_REGEX, $OBJECT, $UNDEF, ], }, Defined => { accept => [ $ZERO, $ONE, $INT, $NEG_INT, $NUM, $NEG_NUM, $EMPTY_STRING, $STRING, $NUM_IN_STRING, $INT_WITH_NL1, $INT_WITH_NL2, $SCALAR_REF, $SCALAR_REF_REF, $ARRAY_REF, $HASH_REF, $CODE_REF, $GLOB, $GLOB_REF, $FH, $FH_OBJECT, $REGEX, $REGEX_OBJ, $FAKE_REGEX, $OBJECT, ], reject => [ $UNDEF, ], }, Undef => { accept => [ $UNDEF, ], reject => [ $ZERO, $ONE, $INT, $NEG_INT, $NUM, $NEG_NUM, $EMPTY_STRING, $STRING, $NUM_IN_STRING, $INT_WITH_NL1, $INT_WITH_NL2, $SCALAR_REF, $SCALAR_REF_REF, $ARRAY_REF, $HASH_REF, $CODE_REF, $GLOB, $GLOB_REF, $FH, $FH_OBJECT, $REGEX, $REGEX_OBJ, $FAKE_REGEX, $OBJECT, ], }, Bool => { accept => [ $ZERO, $ONE, $EMPTY_STRING, $UNDEF, ], reject => [ $INT, $NEG_INT, $NUM, $NEG_NUM, $STRING, $NUM_IN_STRING, $INT_WITH_NL1, $INT_WITH_NL2, $SCALAR_REF, $SCALAR_REF_REF, $ARRAY_REF, $HASH_REF, $CODE_REF, $GLOB, $GLOB_REF, $FH, $FH_OBJECT, $REGEX, $REGEX_OBJ, $FAKE_REGEX, $OBJECT, ], }, Maybe => { accept => [ $ZERO, $ONE, $INT, $NEG_INT, $NUM, $NEG_NUM, $EMPTY_STRING, $STRING, $NUM_IN_STRING, $INT_WITH_NL1, $INT_WITH_NL2, $SCALAR_REF, $SCALAR_REF_REF, $ARRAY_REF, $HASH_REF, $CODE_REF, $GLOB, $GLOB_REF, $FH, $FH_OBJECT, $REGEX, $REGEX_OBJ, $FAKE_REGEX, $OBJECT, $UNDEF, ], }, Value => { accept => [ $ZERO, $ONE, $INT, $NEG_INT, $NUM, $NEG_NUM, $EMPTY_STRING, $STRING, $NUM_IN_STRING, $INT_WITH_NL1, $INT_WITH_NL2, $GLOB, ], reject => [ $SCALAR_REF, $SCALAR_REF_REF, $ARRAY_REF, $HASH_REF, $CODE_REF, $GLOB_REF, $FH, $FH_OBJECT, $REGEX, $REGEX_OBJ, $FAKE_REGEX, $OBJECT, $UNDEF, ], }, Ref => { accept => [ $SCALAR_REF, $SCALAR_REF_REF, $ARRAY_REF, $HASH_REF, $CODE_REF, $GLOB_REF, $FH, $FH_OBJECT, $REGEX, $REGEX_OBJ, $FAKE_REGEX, $OBJECT, ], reject => [ $ZERO, $ONE, $INT, $NEG_INT, $NUM, $NEG_NUM, $EMPTY_STRING, $STRING, $NUM_IN_STRING, $INT_WITH_NL1, $INT_WITH_NL2, $GLOB, $UNDEF, ], }, Num => { accept => [ $ZERO, $ONE, $INT, $NEG_INT, $NUM, $NEG_NUM, ], reject => [ $EMPTY_STRING, $STRING, $NUM_IN_STRING, $SCALAR_REF, $SCALAR_REF_REF, $ARRAY_REF, $HASH_REF, $CODE_REF, $GLOB, $GLOB_REF, $FH, $FH_OBJECT, $REGEX, $REGEX_OBJ, $FAKE_REGEX, $OBJECT, $UNDEF, $INT_WITH_NL1, $INT_WITH_NL2, ], }, Int => { accept => [ $ZERO, $ONE, $INT, $NEG_INT, ], reject => [ $NUM, $NEG_NUM, $EMPTY_STRING, $STRING, $NUM_IN_STRING, $INT_WITH_NL1, $INT_WITH_NL2, $SCALAR_REF, $SCALAR_REF_REF, $ARRAY_REF, $HASH_REF, $CODE_REF, $GLOB, $GLOB_REF, $FH, $FH_OBJECT, $REGEX, $REGEX_OBJ, $FAKE_REGEX, $OBJECT, $UNDEF, ], }, Str => { accept => [ $ZERO, $ONE, $INT, $NEG_INT, $NUM, $NEG_NUM, $EMPTY_STRING, $STRING, $NUM_IN_STRING, $INT_WITH_NL1, $INT_WITH_NL2, ], reject => [ $SCALAR_REF, $SCALAR_REF_REF, $ARRAY_REF, $HASH_REF, $CODE_REF, $GLOB, $GLOB_REF, $FH, $FH_OBJECT, $REGEX, $REGEX_OBJ, $FAKE_REGEX, $OBJECT, $UNDEF, ], }, ScalarRef => { accept => [ $SCALAR_REF, $SCALAR_REF_REF, ], reject => [ $ZERO, $ONE, $INT, $NEG_INT, $NUM, $NEG_NUM, $EMPTY_STRING, $STRING, $NUM_IN_STRING, $INT_WITH_NL1, $INT_WITH_NL2, $ARRAY_REF, $HASH_REF, $CODE_REF, $GLOB, $GLOB_REF, $FH, $FH_OBJECT, $REGEX, $REGEX_OBJ, $FAKE_REGEX, $OBJECT, $UNDEF, ], }, ArrayRef => { accept => [ $ARRAY_REF, ], reject => [ $ZERO, $ONE, $INT, $NEG_INT, $NUM, $NEG_NUM, $EMPTY_STRING, $STRING, $NUM_IN_STRING, $INT_WITH_NL1, $INT_WITH_NL2, $SCALAR_REF, $SCALAR_REF_REF, $HASH_REF, $CODE_REF, $GLOB, $GLOB_REF, $FH, $FH_OBJECT, $REGEX, $REGEX_OBJ, $FAKE_REGEX, $OBJECT, $UNDEF, ], }, HashRef => { accept => [ $HASH_REF, ], reject => [ $ZERO, $ONE, $INT, $NEG_INT, $NUM, $NEG_NUM, $EMPTY_STRING, $STRING, $NUM_IN_STRING, $INT_WITH_NL1, $INT_WITH_NL2, $SCALAR_REF, $SCALAR_REF_REF, $ARRAY_REF, $CODE_REF, $GLOB, $GLOB_REF, $FH, $FH_OBJECT, $REGEX, $REGEX_OBJ, $FAKE_REGEX, $OBJECT, $UNDEF, ], }, CodeRef => { accept => [ $CODE_REF, ], reject => [ $ZERO, $ONE, $INT, $NEG_INT, $NUM, $NEG_NUM, $EMPTY_STRING, $STRING, $NUM_IN_STRING, $INT_WITH_NL1, $INT_WITH_NL2, $SCALAR_REF, $SCALAR_REF_REF, $ARRAY_REF, $HASH_REF, $GLOB, $GLOB_REF, $FH, $FH_OBJECT, $REGEX, $REGEX_OBJ, $FAKE_REGEX, $OBJECT, $UNDEF, ], }, RegexpRef => { accept => [ $REGEX, $REGEX_OBJ, ], reject => [ $ZERO, $ONE, $INT, $NEG_INT, $NUM, $NEG_NUM, $EMPTY_STRING, $STRING, $NUM_IN_STRING, $INT_WITH_NL1, $INT_WITH_NL2, $SCALAR_REF, $SCALAR_REF_REF, $ARRAY_REF, $HASH_REF, $CODE_REF, $GLOB, $GLOB_REF, $FH, $FH_OBJECT, $OBJECT, $UNDEF, $FAKE_REGEX, ], }, GlobRef => { accept => [ $GLOB_REF, $FH, ], reject => [ $ZERO, $ONE, $INT, $NEG_INT, $NUM, $NEG_NUM, $EMPTY_STRING, $STRING, $NUM_IN_STRING, $INT_WITH_NL1, $INT_WITH_NL2, $SCALAR_REF, $SCALAR_REF_REF, $ARRAY_REF, $HASH_REF, $CODE_REF, $GLOB, $FH_OBJECT, $OBJECT, $REGEX, $REGEX_OBJ, $FAKE_REGEX, $UNDEF, ], }, FileHandle => { accept => [ $FH, $FH_OBJECT, ], reject => [ $ZERO, $ONE, $INT, $NEG_INT, $NUM, $NEG_NUM, $EMPTY_STRING, $STRING, $NUM_IN_STRING, $INT_WITH_NL1, $INT_WITH_NL2, $SCALAR_REF, $SCALAR_REF_REF, $ARRAY_REF, $HASH_REF, $CODE_REF, $GLOB, $GLOB_REF, $OBJECT, $REGEX, $REGEX_OBJ, $FAKE_REGEX, $UNDEF, ], }, Object => { accept => [ $FH_OBJECT, $REGEX, $REGEX_OBJ, $FAKE_REGEX, $OBJECT, ], reject => [ $ZERO, $ONE, $INT, $NEG_INT, $NUM, $NEG_NUM, $EMPTY_STRING, $STRING, $NUM_IN_STRING, $INT_WITH_NL1, $INT_WITH_NL2, $SCALAR_REF, $SCALAR_REF_REF, $ARRAY_REF, $HASH_REF, $CODE_REF, $GLOB, $GLOB_REF, $FH, $UNDEF, ], }, ClassName => { accept => [ $CLASS_NAME, $ROLE_NAME, ], reject => [ $ZERO, $ONE, $INT, $NEG_INT, $NUM, $NEG_NUM, $EMPTY_STRING, $STRING, $NUM_IN_STRING, $INT_WITH_NL1, $INT_WITH_NL2, $SCALAR_REF, $SCALAR_REF_REF, $ARRAY_REF, $HASH_REF, $CODE_REF, $GLOB, $GLOB_REF, $FH, $FH_OBJECT, $REGEX, $REGEX_OBJ, $FAKE_REGEX, $OBJECT, $UNDEF, ], }, RoleName => { accept => [ $ROLE_NAME, ], reject => [ $CLASS_NAME, $ZERO, $ONE, $INT, $NEG_INT, $NUM, $NEG_NUM, $EMPTY_STRING, $STRING, $NUM_IN_STRING, $INT_WITH_NL1, $INT_WITH_NL2, $SCALAR_REF, $SCALAR_REF_REF, $ARRAY_REF, $HASH_REF, $CODE_REF, $GLOB, $GLOB_REF, $FH, $FH_OBJECT, $REGEX, $REGEX_OBJ, $FAKE_REGEX, $OBJECT, $UNDEF, ], }, ); for my $name ( sort keys %tests ) { test_constraint( 'Types::Standard'->get_type($name), $tests{$name} ); test_constraint( dwim_type("$name|$name"), $tests{$name} ); } my %substr_test_str = ( ClassName => 'x' . $CLASS_NAME, RoleName => 'x' . $ROLE_NAME, ); # We need to test that the Str constraint (and types that derive from it) # accept the return val of substr() - which means passing that return val # directly to the checking code foreach my $type_name (qw(Str Num Int ClassName RoleName)) { my $str = $substr_test_str{$type_name} || '123456789'; my $type = 'Types::Standard'->get_type($type_name); my $unoptimized = $type->parent->create_child_type(constraint => $type->constraint)->compiled_check; my $inlined; { $inlined = eval_closure( source => 'sub { ( ' . $type->_inline_check('$_[0]') . ' ) }', ); } ok( $type->check( substr( $str, 1, 5 ) ), $type_name . ' accepts return val from substr using ->check' ); ok( $unoptimized->( substr( $str, 1, 5 ) ), $type_name . ' accepts return val from substr using unoptimized constraint' ); ok( $inlined->( substr( $str, 1, 5 ) ), $type_name . ' accepts return val from substr using inlined constraint' ); # only Str accepts empty strings. next unless $type_name eq 'Str'; ok( $type->check( substr( $str, 0, 0 ) ), $type_name . ' accepts empty return val from substr using ->check' ); ok( $unoptimized->( substr( $str, 0, 0 ) ), $type_name . ' accepts empty return val from substr using unoptimized constraint' ); ok( $inlined->( substr( $str, 0, 0 ) ), $type_name . ' accepts empty return val from substr using inlined constraint' ); } { my $class_tc = class_type {class => 'Thing'}; test_constraint( $class_tc, { accept => [ ( bless {}, 'Thing' ), ], reject => [ 'Thing', $ZERO, $ONE, $INT, $NEG_INT, $NUM, $NEG_NUM, $EMPTY_STRING, $STRING, $NUM_IN_STRING, $INT_WITH_NL1, $INT_WITH_NL2, $SCALAR_REF, $SCALAR_REF_REF, $ARRAY_REF, $HASH_REF, $CODE_REF, $GLOB, $GLOB_REF, $FH, $FH_OBJECT, $REGEX, $REGEX_OBJ, $FAKE_REGEX, $OBJECT, $UNDEF, ], } ); } { package Duck; sub new { } sub quack { } sub flap { } } { package DuckLike; sub new { } sub quack { } sub flap { } } { package Bird; sub new { } sub flap { } } { my @methods = qw( quack flap ); my $duck = duck_type 'Duck' => [@methods]; test_constraint( $duck, { accept => [ ( bless {}, 'Duck' ), ( bless {}, 'DuckLike' ), ], reject => [ $ZERO, $ONE, $INT, $NEG_INT, $NUM, $NEG_NUM, $EMPTY_STRING, $STRING, $NUM_IN_STRING, $INT_WITH_NL1, $INT_WITH_NL2, $SCALAR_REF, $SCALAR_REF_REF, $ARRAY_REF, $HASH_REF, $CODE_REF, $GLOB, $GLOB_REF, $FH, $FH_OBJECT, $REGEX, $REGEX_OBJ, $FAKE_REGEX, $OBJECT, ( bless {}, 'Bird' ), $UNDEF, ], } ); } { my @allowed = qw( bar baz quux ); my $enum = enum 'Enumerated' => [@allowed]; test_constraint( $enum, { accept => \@allowed, reject => [ $ZERO, $ONE, $INT, $NEG_INT, $NUM, $NEG_NUM, $EMPTY_STRING, $STRING, $NUM_IN_STRING, $INT_WITH_NL1, $INT_WITH_NL2, $SCALAR_REF, $SCALAR_REF_REF, $ARRAY_REF, $HASH_REF, $CODE_REF, $GLOB, $GLOB_REF, $FH, $FH_OBJECT, $REGEX, $REGEX_OBJ, $FAKE_REGEX, $OBJECT, $UNDEF, ], } ); } { require Type::Tiny::Union; my $union = 'Type::Tiny::Union'->new( type_constraints => [ Types::Standard::Int, Types::Standard::Object, ], ); test_constraint( $union, { accept => [ $ZERO, $ONE, $INT, $NEG_INT, $FH_OBJECT, $REGEX, $REGEX_OBJ, $FAKE_REGEX, $OBJECT, ], reject => [ $NUM, $NEG_NUM, $EMPTY_STRING, $STRING, $NUM_IN_STRING, $INT_WITH_NL1, $INT_WITH_NL2, $SCALAR_REF, $SCALAR_REF_REF, $ARRAY_REF, $HASH_REF, $CODE_REF, $GLOB, $GLOB_REF, $FH, $UNDEF, ], } ); } { note 'Anonymous Union Test'; my $union = union[ Types::Standard::Int, Types::Standard::Object ]; test_constraint( $union, { accept => [ $ZERO, $ONE, $INT, $NEG_INT, $FH_OBJECT, $REGEX, $REGEX_OBJ, $FAKE_REGEX, $OBJECT, ], reject => [ $NUM, $NEG_NUM, $EMPTY_STRING, $STRING, $NUM_IN_STRING, $INT_WITH_NL1, $INT_WITH_NL2, $SCALAR_REF, $SCALAR_REF_REF, $ARRAY_REF, $HASH_REF, $CODE_REF, $GLOB, $GLOB_REF, $FH, $UNDEF, ], } ); } { note 'Named Union Test'; my $union = union 'NamedUnion' => [ Types::Standard::Int, Types::Standard::Object ]; test_constraint( $union, { accept => [ $ZERO, $ONE, $INT, $NEG_INT, $FH_OBJECT, $REGEX, $REGEX_OBJ, $FAKE_REGEX, $OBJECT, ], reject => [ $NUM, $NEG_NUM, $EMPTY_STRING, $STRING, $NUM_IN_STRING, $INT_WITH_NL1, $INT_WITH_NL2, $SCALAR_REF, $SCALAR_REF_REF, $ARRAY_REF, $HASH_REF, $CODE_REF, $GLOB, $GLOB_REF, $FH, $UNDEF, ], } ); } { note 'Combined Union Test'; my $union = union( [ Types::Standard::Int, enum [qw[ red green blue ]] ] ); test_constraint( $union, { accept => [ $ZERO, $ONE, $INT, $NEG_INT, 'red', 'green', 'blue', ], reject => [ 'yellow', 'pink', $FH_OBJECT, $REGEX, $REGEX_OBJ, $FAKE_REGEX, $OBJECT, $NUM, $NEG_NUM, $EMPTY_STRING, $STRING, $NUM_IN_STRING, $INT_WITH_NL1, $INT_WITH_NL2, $SCALAR_REF, $SCALAR_REF_REF, $ARRAY_REF, $HASH_REF, $CODE_REF, $GLOB, $GLOB_REF, $FH, $UNDEF, ], } ); } { my $enum1 = enum 'Enum1' => ['a', 'b']; my $enum2 = enum 'Enum2' => ['x', 'y']; my $union = subtype 'EnumUnion', as ($enum1|$enum2); test_constraint( $union, { accept => [qw( a b x y )], reject => [ $ZERO, $ONE, $INT, $NEG_INT, $NUM, $NEG_NUM, $EMPTY_STRING, $STRING, $NUM_IN_STRING, $INT_WITH_NL1, $INT_WITH_NL2, $SCALAR_REF, $SCALAR_REF_REF, $ARRAY_REF, $HASH_REF, $CODE_REF, $GLOB, $GLOB_REF, $FH, $FH_OBJECT, $REGEX, $REGEX_OBJ, $FAKE_REGEX, $OBJECT, $UNDEF, ], } ); } { package DoesRole; use Moose; with 'Role'; } close $FH or warn "Could not close the filehandle $0 for test"; $FH_OBJECT->close or warn "Could not close the filehandle $0 for test"; done_testing; sub test_constraint { my $type = shift; my $tests = shift; local $Test::Builder::Level = $Test::Builder::Level + 1; unless ( blessed $type ) { BAIL_OUT("TYPE STRING!!! $type!"); } my $name = $type->name; note "TYPE: $name"; my $unoptimized = $type->has_parent ? $type->parent->create_child_type(constraint => $type->constraint)->compiled_check : 'Type::Tiny'->new( constraint => $type->constraint )->compiled_check; my $inlined; if ( $type->can_be_inlined ) { $inlined = eval_closure( source => 'sub { ( ' . $type->_inline_check('$_[0]') . ' ) }', environment => $type->inline_environment, ); } require Moose; my $class = Moose::Meta::Class->create_anon( superclasses => ['Moose::Object'], ); $class->add_attribute( simple => ( is => 'ro', isa => $type, ) ); $class->add_attribute( collection => ( traits => ['Array'], isa => Types::Standard::ArrayRef()->parameterize($type), default => sub { [] }, handles => { add_to_collection => 'push' }, ) ); my $anon_class = $class->name; for my $accept ( @{ $tests->{accept} || [] } ) { my $described = describe($accept); ok( $type->check($accept), "$name accepts $described using ->check" ); ok( $unoptimized->($accept), "$name accepts $described using unoptimized constraint" ); if ($inlined) { ok( $inlined->($accept), "$name accepts $described using inlined constraint" ); } is( exception { $anon_class->new( simple => $accept ); }, undef, "no exception passing $described to constructor with $name" ); is( exception { $anon_class->new()->add_to_collection($accept); }, undef, "no exception passing $described to native trait push method with $name" ); } for my $reject ( @{ $tests->{reject} || [] } ) { my $described = describe($reject); ok( !$type->check($reject), "$name rejects $described using ->check" ); ok( !$unoptimized->($reject), "$name rejects $described using unoptimized constraint" ); if ($inlined) { ok( !$inlined->($reject), "$name rejects $described using inlined constraint" ); } ok( exception { $anon_class->new( simple => $reject ); }, "got exception passing $described to constructor with $name" ); ok( exception { $anon_class->new()->add_to_collection($reject); }, "got exception passing $described to native trait push method with $name" ); } } sub describe { my $val = shift; return 'undef' unless defined $val; if ( !ref $val ) { return q{''} if $val eq q{}; $val =~ s/\n/\\n/g; return $val; } return 'open filehandle' if openhandle $val && !blessed $val; return blessed $val ? ( ref $val ) . ' object' : ( ref $val ) . ' reference'; } README000664001750001750 124412422772210 13523 0ustar00taitai000000000000Type-Tiny-1.000005/tRunning the test suite ====================== In the main directory for the distribution (i.e. the directory containing dist.ini), run the following command: prove -lr "t" Test suite structure ==================== Each test should contain its own documentation in pod format. t/20-unit/ - unit tests for each module in the distribution t/30-integration/ - integration tests for using Type-Tiny with other software - these should be skipped if the other software is not available t/40-regression/ - tests related to specific bug reports t/lib/ - support files for test cases. t/*.t - miscellaneous other tests t/*.pl - support files for managing test cases TODO000664001750001750 6512422772210 13273 0ustar00taitai000000000000Type-Tiny-1.000005/t- full module coverage (according to not-covered.pl) mk-test-manifest.pl000664001750001750 515412422772210 16374 0ustar00taitai000000000000Type-Tiny-1.000005/t#!/usr/bin/env perl use v5.014; use Path::Tiny; use Path::Iterator::Rule; use Pod::POM; use constant PROJ_NAME => 'Type-Tiny'; use constant PROJ_DIR => path(path(__FILE__)->absolute->dirname)->parent; use constant LIB_DIR => PROJ_DIR->child('lib'); use constant TEST_DIR => PROJ_DIR->child('t'); my $rule = Path::Iterator::Rule->new->file->name('*.t'); package Local::View { use parent 'Pod::POM::View::Text'; sub view_seq_link { my ($self, $link) = @_; $link =~ s/^.*?\|//; return $link; } } sub podpurpose { my $pod = Pod::POM->new->parse_file($_[0]->openr_raw); my ($purpose) = grep $_->title eq 'PURPOSE', $pod->head1; my $content = eval { $purpose->content->present('Local::View') } || "(Unknown.)"; my $trimmed = ($content =~ s/(\A\s+)|(\s+\z)//rms); $trimmed =~ s/\s+/ /g; $trimmed =~ s/"/\\"/g if $_[1]; return $trimmed; } say '@prefix : .'; MISC_TESTS: { my $iter = $rule->clone->max_depth(1)->iter( TEST_DIR ); while (my $file = $iter->()) { my $test = path($file); say "[] a :Test; :test_script f`${\ $test->relative(PROJ_DIR) } ${\ PROJ_NAME }`; :purpose \"${\ podpurpose($test,1) }\"."; } } UNIT_TESTS: { my $iter = $rule->iter( TEST_DIR->child('20-unit') ); my %mods; while (my $file = $iter->()) { my $test = path($file); my ($module) = ($test =~ m(t/20-unit/([^/]+)/)); $module =~ s{-}{::}g; push @{ $mods{$module} ||= [] }, $test; } for my $mod (sort keys %mods) { say "m`$mod ${\ PROJ_NAME }`"; for my $test (sort @{ $mods{$mod} }) { say "\t:unit_test [ a :UnitTest; :test_script f`${\ $test->relative(PROJ_DIR) } ${\ PROJ_NAME }`; :purpose \"${\ podpurpose($test,1) }\" ];"; } say "\t."; } } INTEGRATION_TESTS: { my $iter = $rule->iter( TEST_DIR->child('30-integration') ); while (my $file = $iter->()) { my $test = path($file); say "[] a :IntegrationTest; :test_script f`${\ $test->relative(PROJ_DIR) } ${\ PROJ_NAME }`; :purpose \"${\ podpurpose($test,1) }\"."; } } REGRESSION_TESTS: { my $iter = $rule->iter( TEST_DIR->child('40-regression') ); my %bugs; while (my $file = $iter->()) { my $test = path($file); if ($test =~ m/rt([0-9]+)/) { push @{ $bugs{$1} ||= [] }, $test; next; } say "[] a :RegressionTest; :test_script f`${\ $test->relative(PROJ_DIR) } ${\ PROJ_NAME }`; :purpose \"${\ podpurpose($test,1) }\"."; } for my $rt (sort { $a <=> $b } keys %bugs) { say "RT#$rt"; for my $test (@{$bugs{$rt}}) { say "\t:regression_test [ a :RegressionTest; :test_script f`${\ $test->relative(PROJ_DIR) } ${\ PROJ_NAME }`; :purpose \"${\ podpurpose($test,1) }\"];"; } say "\t."; } } not-covered.pl000664001750001750 113012422772210 15417 0ustar00taitai000000000000Type-Tiny-1.000005/t#!/usr/bin/env perl use v5.014; use Path::Tiny; use Path::Iterator::Rule; use constant LIB_DIR => path(path(__FILE__)->absolute->dirname)->parent->child('lib'); use constant TEST_DIR => path(path(__FILE__)->absolute->dirname)->parent->child('t/20-unit'); my $rule = Path::Iterator::Rule->new->file->perl_module; my $iter = $rule->iter( LIB_DIR ); while (my $file = $iter->()) { my $module = path($file)->relative(LIB_DIR); $module =~ s{.pm$}{}; $module =~ s{/}{::}g; TEST_DIR->child($module =~ s/::/-/gr)->exists or ($module =~ /^Types::Standard::/) # helper module or say $module; } Fatal.pm000664001750001750 245512422772210 15462 0ustar00taitai000000000000Type-Tiny-1.000005/inc/Test#line 1 use strict; use warnings; package Test::Fatal; { $Test::Fatal::VERSION = '0.010'; } # ABSTRACT: incredibly simple helpers for testing code with exceptions use Carp (); use Try::Tiny 0.07; use base 'Exporter'; our @EXPORT = qw(exception); our @EXPORT_OK = qw(exception success dies_ok lives_ok); sub exception (&) { my $code = shift; return try { $code->(); return undef; } catch { return $_ if $_; my $problem = defined $_ ? 'false' : 'undef'; Carp::confess("$problem exception caught by Test::Fatal::exception"); }; } sub success (&;@) { my $code = shift; return finally( sub { return if @_; # <-- only run on success $code->(); }, @_ ); } my $Tester; # Signature should match that of Test::Exception sub dies_ok (&;$) { my $code = shift; my $name = shift; require Test::Builder; $Tester ||= Test::Builder->new; my $ok = $Tester->ok( exception( \&$code ), $name ); $ok or $Tester->diag( "expected an exception but none was raised" ); return $ok; } sub lives_ok (&;$) { my $code = shift; my $name = shift; require Test::Builder; $Tester ||= Test::Builder->new; my $ok = $Tester->ok( !exception( \&$code ), $name ); $ok or $Tester->diag( "expected return but an exception was raised" ); return $ok; } 1; __END__ #line 212 Requires.pm000664001750001750 343312422772210 16227 0ustar00taitai000000000000Type-Tiny-1.000005/inc/Test#line 1 package Test::Requires; use strict; use warnings; our $VERSION = '0.06'; use base 'Test::Builder::Module'; use 5.006000; sub import { my $class = shift; my $caller = caller(0); # export methods { no strict 'refs'; *{"$caller\::test_requires"} = \&test_requires; } # test arguments if (@_ == 1 && ref $_[0] && ref $_[0] eq 'HASH') { while (my ($mod, $ver) = each %{$_[0]}) { test_requires($mod, $ver, $caller); } } else { for my $mod (@_) { test_requires($mod, undef, $caller); } } } sub test_requires { my ( $mod, $ver, $caller ) = @_; return if $mod eq __PACKAGE__; if (@_ != 3) { $caller = caller(0); } $ver ||= ''; eval qq{package $caller; use $mod $ver}; ## no critic. if (my $e = $@) { my $skip_all = sub { my $builder = __PACKAGE__->builder; if (not defined $builder->has_plan) { $builder->skip_all(@_); } elsif ($builder->has_plan eq 'no_plan') { $builder->skip(@_); if ( $builder->can('parent') && $builder->parent ) { die bless {} => 'Test::Builder::Exception'; } exit 0; } else { for (1..$builder->has_plan) { $builder->skip(@_); } if ( $builder->can('parent') && $builder->parent ) { die bless {} => 'Test::Builder::Exception'; } exit 0; } }; if ( $e =~ /^Can't locate/ ) { $skip_all->("Test requires module '$mod' but it's not found"); } else { $skip_all->("$e"); } } } 1; __END__ #line 128 Tiny.pm000664001750001750 4332512422772210 15236 0ustar00taitai000000000000Type-Tiny-1.000005/inc/Trypackage Try::Tiny; BEGIN { $Try::Tiny::AUTHORITY = 'cpan:NUFFIN'; } $Try::Tiny::VERSION = '0.21'; use 5.006; # ABSTRACT: minimal try/catch with proper preservation of $@ use strict; use warnings; use Exporter (); our @ISA = qw( Exporter ); our @EXPORT = our @EXPORT_OK = qw(try catch finally); use Carp; $Carp::Internal{+__PACKAGE__}++; BEGIN { eval "use Sub::Name; 1" or *{subname} = sub {1} } # Need to prototype as @ not $$ because of the way Perl evaluates the prototype. # Keeping it at $$ means you only ever get 1 sub because we need to eval in a list # context & not a scalar one sub try (&;@) { my ( $try, @code_refs ) = @_; # we need to save this here, the eval block will be in scalar context due # to $failed my $wantarray = wantarray; # work around perl bug by explicitly initializing these, due to the likelyhood # this will be used in global destruction (perl rt#119311) my ( $catch, @finally ) = (); # find labeled blocks in the argument list. # catch and finally tag the blocks by blessing a scalar reference to them. foreach my $code_ref (@code_refs) { if ( ref($code_ref) eq 'Try::Tiny::Catch' ) { croak 'A try() may not be followed by multiple catch() blocks' if $catch; $catch = ${$code_ref}; } elsif ( ref($code_ref) eq 'Try::Tiny::Finally' ) { push @finally, ${$code_ref}; } else { croak( 'try() encountered an unexpected argument (' . ( defined $code_ref ? $code_ref : 'undef' ) . ') - perhaps a missing semi-colon before or' ); } } # FIXME consider using local $SIG{__DIE__} to accumulate all errors. It's # not perfect, but we could provide a list of additional errors for # $catch->(); # name the blocks if we have Sub::Name installed my $caller = caller; subname("${caller}::try {...} " => $try); subname("${caller}::catch {...} " => $catch) if $catch; subname("${caller}::finally {...} " => $_) foreach @finally; # save the value of $@ so we can set $@ back to it in the beginning of the eval # and restore $@ after the eval finishes my $prev_error = $@; my ( @ret, $error ); # failed will be true if the eval dies, because 1 will not be returned # from the eval body my $failed = not eval { $@ = $prev_error; # evaluate the try block in the correct context if ( $wantarray ) { @ret = $try->(); } elsif ( defined $wantarray ) { $ret[0] = $try->(); } else { $try->(); }; return 1; # properly set $fail to false }; # preserve the current error and reset the original value of $@ $error = $@; $@ = $prev_error; # set up a scope guard to invoke the finally block at the end my @guards = map { Try::Tiny::ScopeGuard->_new($_, $failed ? $error : ()) } @finally; # at this point $failed contains a true value if the eval died, even if some # destructor overwrote $@ as the eval was unwinding. if ( $failed ) { # if we got an error, invoke the catch block. if ( $catch ) { # This works like given($error), but is backwards compatible and # sets $_ in the dynamic scope for the body of C<$catch> for ($error) { return $catch->($error); } # in case when() was used without an explicit return, the C # loop will be aborted and there's no useful return value } return; } else { # no failure, $@ is back to what it was, everything is fine return $wantarray ? @ret : $ret[0]; } } sub catch (&;@) { my ( $block, @rest ) = @_; croak 'Useless bare catch()' unless wantarray; return ( bless(\$block, 'Try::Tiny::Catch'), @rest, ); } sub finally (&;@) { my ( $block, @rest ) = @_; croak 'Useless bare finally()' unless wantarray; return ( bless(\$block, 'Try::Tiny::Finally'), @rest, ); } { package # hide from PAUSE Try::Tiny::ScopeGuard; use constant UNSTABLE_DOLLARAT => ($] < '5.013002') ? 1 : 0; sub _new { shift; bless [ @_ ]; } sub DESTROY { my ($code, @args) = @{ $_[0] }; local $@ if UNSTABLE_DOLLARAT; eval { $code->(@args); 1; } or do { warn "Execution of finally() block $code resulted in an exception, which " . '*CAN NOT BE PROPAGATED* due to fundamental limitations of Perl. ' . 'Your program will continue as if this event never took place. ' . "Original exception text follows:\n\n" . (defined $@ ? $@ : '$@ left undefined...') . "\n" ; } } } __PACKAGE__ __END__ =pod =encoding UTF-8 =head1 NAME Try::Tiny - minimal try/catch with proper preservation of $@ =head1 VERSION version 0.21 =head1 SYNOPSIS You can use Try::Tiny's C and C to expect and handle exceptional conditions, avoiding quirks in Perl and common mistakes: # handle errors with a catch handler try { die "foo"; } catch { warn "caught error: $_"; # not $@ }; You can also use it like a standalone C to catch and ignore any error conditions. Obviously, this is an extreme measure not to be undertaken lightly: # just silence errors try { die "foo"; }; =head1 DESCRIPTION This module provides bare bones C/C/C statements that are designed to minimize common mistakes with eval blocks, and NOTHING else. This is unlike L which provides a nice syntax and avoids adding another call stack layer, and supports calling C from the C block to return from the parent subroutine. These extra features come at a cost of a few dependencies, namely L and L which are occasionally problematic, and the additional catch filtering uses L type constraints which may not be desirable either. The main focus of this module is to provide simple and reliable error handling for those having a hard time installing L, but who still want to write correct C blocks without 5 lines of boilerplate each time. It's designed to work as correctly as possible in light of the various pathological edge cases (see L) and to be compatible with any style of error values (simple strings, references, objects, overloaded objects, etc). If the C block dies, it returns the value of the last statement executed in the C block, if there is one. Otherwise, it returns C in scalar context or the empty list in list context. The following examples all assign C<"bar"> to C<$x>: my $x = try { die "foo" } catch { "bar" }; my $x = try { die "foo" } || { "bar" }; my $x = (try { die "foo" }) // { "bar" }; my $x = eval { die "foo" } || "bar"; You can add C blocks, yielding the following: my $x; try { die 'foo' } finally { $x = 'bar' }; try { die 'foo' } catch { warn "Got a die: $_" } finally { $x = 'bar' }; C blocks are always executed making them suitable for cleanup code which cannot be handled using local. You can add as many C blocks to a given C block as you like. Note that adding a C block without a preceding C block suppresses any errors. This behaviour is consistent with using a standalone C, but it is not consistent with C/C patterns found in other programming languages, such as Java, Python, Javascript or C#. If you learnt the C/C pattern from one of these languages, watch out for this. =head1 EXPORTS All functions are exported by default using L. If you need to rename the C, C or C keyword consider using L to get L's flexibility. =over 4 =item try (&;@) Takes one mandatory C subroutine, an optional C subroutine and C subroutine. The mandatory subroutine is evaluated in the context of an C block. If no error occurred the value from the first block is returned, preserving list/scalar context. If there was an error and the second subroutine was given it will be invoked with the error in C<$_> (localized) and as that block's first and only argument. C<$@> does B contain the error. Inside the C block it has the same value it had before the C block was executed. Note that the error may be false, but if that happens the C block will still be invoked. Once all execution is finished then the C block, if given, will execute. =item catch (&;@) Intended to be used in the second argument position of C. Returns a reference to the subroutine it was given but blessed as C which allows try to decode correctly what to do with this code reference. catch { ... } Inside the C block the caught error is stored in C<$_>, while previous value of C<$@> is still available for use. This value may or may not be meaningful depending on what happened before the C, but it might be a good idea to preserve it in an error stack. For code that captures C<$@> when throwing new errors (i.e. L), you'll need to do: local $@ = $_; =item finally (&;@) try { ... } catch { ... } finally { ... }; Or try { ... } finally { ... }; Or even try { ... } finally { ... } catch { ... }; Intended to be the second or third element of C. C blocks are always executed in the event of a successful C or if C is run. This allows you to locate cleanup code which cannot be done via C e.g. closing a file handle. When invoked, the C block is passed the error that was caught. If no error was caught, it is passed nothing. (Note that the C block does not localize C<$_> with the error, since unlike in a C block, there is no way to know if C<$_ == undef> implies that there were no errors.) In other words, the following code does just what you would expect: try { die_sometimes(); } catch { # ...code run in case of error } finally { if (@_) { print "The try block died with: @_\n"; } else { print "The try block ran without error.\n"; } }; B block>. C will not do anything about handling possible errors coming from code located in these blocks. Furthermore B blocks are not trappable and are unable to influence the execution of your program>. This is due to limitation of C-based scope guards, which C is implemented on top of. This may change in a future version of Try::Tiny. In the same way C blesses the code reference this subroutine does the same except it bless them as C. =back =head1 BACKGROUND There are a number of issues with C. =head2 Clobbering $@ When you run an C block and it succeeds, C<$@> will be cleared, potentially clobbering an error that is currently being caught. This causes action at a distance, clearing previous errors your caller may have not yet handled. C<$@> must be properly localized before invoking C in order to avoid this issue. More specifically, C<$@> is clobbered at the beginning of the C, which also makes it impossible to capture the previous error before you die (for instance when making exception objects with error stacks). For this reason C will actually set C<$@> to its previous value (the one available before entering the C block) in the beginning of the C block. =head2 Localizing $@ silently masks errors Inside an C block, C behaves sort of like: sub die { $@ = $_[0]; return_undef_from_eval(); } This means that if you were polite and localized C<$@> you can't die in that scope, or your error will be discarded (printing "Something's wrong" instead). The workaround is very ugly: my $error = do { local $@; eval { ... }; $@; }; ... die $error; =head2 $@ might not be a true value This code is wrong: if ( $@ ) { ... } because due to the previous caveats it may have been unset. C<$@> could also be an overloaded error object that evaluates to false, but that's asking for trouble anyway. The classic failure mode is: sub Object::DESTROY { eval { ... } } eval { my $obj = Object->new; die "foo"; }; if ( $@ ) { } In this case since C is not localizing C<$@> but still uses C, it will set C<$@> to C<"">. The destructor is called when the stack is unwound, after C sets C<$@> to C<"foo at Foo.pm line 42\n">, so by the time C is evaluated it has been cleared by C in the destructor. The workaround for this is even uglier than the previous ones. Even though we can't save the value of C<$@> from code that doesn't localize, we can at least be sure the C was aborted due to an error: my $failed = not eval { ... return 1; }; This is because an C that caught a C will always return a false value. =head1 SHINY SYNTAX Using Perl 5.10 you can use L. The C block is invoked in a topicalizer context (like a C block), but note that you can't return a useful value from C using the C blocks without an explicit C. This is somewhat similar to Perl 6's C blocks. You can use it to concisely match errors: try { require Foo; } catch { when (/^Can't locate .*?\.pm in \@INC/) { } # ignore default { die $_ } }; =head1 CAVEATS =over 4 =item * C<@_> is not available within the C block, so you need to copy your arglist. In case you want to work with argument values directly via C<@_> aliasing (i.e. allow C<$_[1] = "foo">), you need to pass C<@_> by reference: sub foo { my ( $self, @args ) = @_; try { $self->bar(@args) } } or sub bar_in_place { my $self = shift; my $args = \@_; try { $_ = $self->bar($_) for @$args } } =item * C returns from the C block, not from the parent sub (note that this is also how C works, but not how L works): sub parent_sub { try { die; } catch { return; }; say "this text WILL be displayed, even though an exception is thrown"; } Instead, you should capture the return value: sub parent_sub { my $success = try { die; 1; }; return unless $success; say "This text WILL NEVER appear!"; } # OR sub parent_sub_with_catch { my $success = try { die; 1; } catch { # do something with $_ return undef; #see note }; return unless $success; say "This text WILL NEVER appear!"; } Note that if you have a C block, it must return C for this to work, since if a C block exists, its return value is returned in place of C when an exception is thrown. =item * C introduces another caller stack frame. L is not used. L will not report this when using full stack traces, though, because C<%Carp::Internal> is used. This lack of magic is considered a feature. =item * The value of C<$_> in the C block is not guaranteed to be the value of the exception thrown (C<$@>) in the C block. There is no safe way to ensure this, since C may be used unhygenically in destructors. The only guarantee is that the C will be called if an exception is thrown. =item * The return value of the C block is not ignored, so if testing the result of the expression for truth on success, be sure to return a false value from the C block: my $obj = try { MightFail->new; } catch { ... return; # avoid returning a true value; }; return unless $obj; =item * C<$SIG{__DIE__}> is still in effect. Though it can be argued that C<$SIG{__DIE__}> should be disabled inside of C blocks, since it isn't people have grown to rely on it. Therefore in the interests of compatibility, C does not disable C<$SIG{__DIE__}> for the scope of the error throwing code. =item * Lexical C<$_> may override the one set by C. For example Perl 5.10's C form uses a lexical C<$_>, creating some confusing behavior: given ($foo) { when (...) { try { ... } catch { warn $_; # will print $foo, not the error warn $_[0]; # instead, get the error like this } } } Note that this behavior was changed once again in L. However, since the entirety of lexical C<$_> is now L, it is unclear whether the new version 18 behavior is final. =back =head1 SEE ALSO =over 4 =item L Much more feature complete, more convenient semantics, but at the cost of implementation complexity. =item L Automatic error throwing for builtin functions and more. Also designed to work well with C/C. =item L A lightweight role for rolling your own exception classes. =item L Exception object implementation with a C statement. Does not localize C<$@>. =item L Provides a C statement, but properly calling C is your responsibility. The C keyword pushes C<$@> onto an error stack, avoiding some of the issues with C<$@>, but you still need to localize to prevent clobbering. =back =head1 LIGHTNING TALK I gave a lightning talk about this module, you can see the slides (Firefox only): L Or read the source: L =head1 VERSION CONTROL L =head1 AUTHORS =over 4 =item * Yuval Kogman =item * Jesse Luehrs =back =head1 COPYRIGHT AND LICENSE This software is Copyright (c) 2014 by Yuval Kogman. This is free software, licensed under: The MIT (X11) License =cut TypeTiny.pm000664001750001750 1230012422772210 16375 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Errorpackage Error::TypeTiny; use 5.006001; use strict; use warnings; BEGIN { $Error::TypeTiny::AUTHORITY = 'cpan:TOBYINK'; $Error::TypeTiny::VERSION = '1.000005'; } use overload q[""] => sub { $_[0]->to_string }, q[bool] => sub { 1 }, fallback => 1, ; our %CarpInternal; $CarpInternal{$_}++ for qw( Eval::TypeTiny Eval::TypeTiny::Sandbox Exporter::Tiny Test::TypeTiny Type::Coercion Type::Coercion::Union Error::TypeTiny Type::Library Type::Params Type::Registry Types::Standard Types::Standard::_Stringable Types::TypeTiny Type::Tiny Type::Tiny::Class Type::Tiny::Duck Type::Tiny::Enum Type::Tiny::Intersection Type::Tiny::Role Type::Tiny::Union Type::Utils ); sub new { my $class = shift; my %params = (@_==1) ? %{$_[0]} : @_; return bless \%params, $class; } sub throw { my $class = shift; my ($level, @caller, %ctxt) = 0; while ( defined scalar caller($level) and $CarpInternal{scalar caller($level)} ) { $level++ }; if ( ((caller($level - 1))[1]||"") =~ /^parameter validation for '(.+?)'$/ ) { my ($pkg, $func) = ($1 =~ m{^(.+)::(\w+)$}); $level++ if caller($level) eq ($pkg||""); } @ctxt{qw/ package file line /} = caller($level); my $stack = undef; if (our $StackTrace) { require Devel::StackTrace; $stack = "Devel::StackTrace"->new( ignore_package => [ keys %CarpInternal ], ); } die( our $LastError = $class->new( context => \%ctxt, stack_trace => $stack, @_, ) ); } sub message { $_[0]{message} ||= $_[0]->_build_message }; sub context { $_[0]{context} }; sub stack_trace { $_[0]{stack_trace} }; sub to_string { my $e = shift; my $c = $e->context; my $m = $e->message; $m =~ /\n\z/s ? $m : $c ? sprintf("%s at %s line %s.\n", $m, $c->{file}||'file?', $c->{line}||'NaN') : sprintf("%s\n", $m); } sub _build_message { return 'An exception has occurred'; } sub croak { my ($fmt, @args) = @_; @_ = ( __PACKAGE__, message => sprintf($fmt, @args), ); goto \&throw; } 1; __END__ =pod =encoding utf-8 =head1 NAME Error::TypeTiny - exceptions for Type::Tiny and friends =head1 SYNOPSIS use Data::Dumper; use Try::Tiny; use Types::Standard qw(Str); try { Str->assert_valid(undef); } catch { my $exception = shift; warn "Encountered Error: $exception"; warn Dumper($exception->explain) if $exception->isa("Error::TypeTiny::Assertion"); }; =head1 STATUS This module is covered by the L. =head1 DESCRIPTION When Type::Tiny and its related modules encounter an error, they throw an exception object. These exception objects inherit from Error::TypeTiny. =head2 Constructors =over =item C<< new(%attributes) >> Moose-style constructor function. =item C<< throw(%attributes) >> Constructs an exception and passes it to C. Automatically populates C and C if appropriate. =back =head2 Attributes =over =item C The error message. =item C Hashref containing the package, file and line that generated the error. =item C A more complete stack trace. This feature requires L; use the C<< $StackTrace >> package variable to switch it on. =back =head2 Methods =over =item C Returns the message, followed by the context if it is set. =back =head2 Functions =over =item C<< Error::TypeTiny::croak($format, @args) >> Functional-style shortcut to C method. Takes an C-style format string and optional arguments to construct the C. =back =head2 Overloading =over =item * Stringification is overloaded to call C. =back =head2 Package Variables =over =item C<< %Error::TypeTiny::CarpInternal >> Serves a similar purpose to C<< %Carp::CarpInternal >>. =item C<< $Error::TypeTiny::StackTrace >> Boolean to toggle stack trace generation. =item C<< $Error::TypeTiny::LastError >> A reference to the last exception object thrown. =back =head1 CAVEATS Although Error::TypeTiny objects are thrown for errors produced by Type::Tiny, that doesn't mean every time you use Type::Tiny you'll get Error::TypeTinys whenever you want. For example, if you use a Type::Tiny type constraint in a Moose attribute, Moose will not call the constraint's C method (which throws an exception). Instead it will call C and C (which do not), and will C an error message of its own. (The C<< $LastError >> package variable may save your bacon.) =head1 BUGS Please report any bugs to L. =head1 SEE ALSO L, L. L, L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. TypeTiny.pm000664001750001750 2033312422772210 16200 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Evalpackage Eval::TypeTiny; use strict; BEGIN { *HAS_LEXICAL_SUBS = ($] >= 5.018) ? sub(){!!1} : sub(){!!0}; }; { my $hlv; sub HAS_LEXICAL_VARS () { $hlv = !! eval { require Devel::LexAlias; exists(&Devel::LexAlias::lexalias); } unless defined $hlv; $hlv; } } sub _clean_eval { local $@; local $SIG{__DIE__}; my $r = eval $_[0]; my $e = $@; return ($r, $e); } our $AUTHORITY = 'cpan:TOBYINK'; our $VERSION = '1.000005'; our @EXPORT = qw( eval_closure ); our @EXPORT_OK = qw( HAS_LEXICAL_SUBS HAS_LEXICAL_VARS ); sub import { # do the shuffle! no warnings "redefine"; our @ISA = qw( Exporter::Tiny ); require Exporter::Tiny; my $next = \&Exporter::Tiny::import; *import = $next; my $class = shift; my $opts = { ref($_[0]) ? %{+shift} : () }; $opts->{into} ||= scalar(caller); return $class->$next($opts, @_); } use warnings; sub eval_closure { my (%args) = @_; my $src = ref $args{source} eq "ARRAY" ? join("\n", @{$args{source}}) : $args{source}; $args{alias} = 0 unless defined $args{alias}; $args{line} = 1 unless defined $args{line}; $args{description} =~ s/[^\w .:-\[\]\(\)\{\}\']//g if defined $args{description}; $src = qq{#line $args{line} "$args{description}"\n$src} if defined $args{description} && !($^P & 0x10); $args{environment} ||= {}; # for my $k (sort keys %{$args{environment}}) # { # next if $k =~ /^\$/ && ref($args{environment}{$k}) =~ /^(SCALAR|REF)$/; # next if $k =~ /^\@/ && ref($args{environment}{$k}) eq q(ARRAY); # next if $k =~ /^\%/ && ref($args{environment}{$k}) eq q(HASH); # # require Error::TypeTiny; # Error::TypeTiny::croak("Expected a variable name and ref; got %s => %s", $k, $args{environment}{$k}); # } my $sandpkg = 'Eval::TypeTiny::Sandbox'; my $alias = exists($args{alias}) ? $args{alias} : 0; my @keys = sort keys %{$args{environment}}; my $i = 0; my $source = join "\n" => ( "package $sandpkg;", "sub {", map(_make_lexical_assignment($_, $i++, $alias), @keys), $src, "}", ); _manufacture_ties() if $alias && !HAS_LEXICAL_VARS; my ($compiler, $e) = _clean_eval($source); if ($e) { chomp $e; require Error::TypeTiny::Compilation; "Error::TypeTiny::Compilation"->throw( code => (ref $args{source} eq "ARRAY" ? join("\n", @{$args{source}}) : $args{source}), errstr => $e, environment => $args{environment}, ); } my $code = $compiler->(@{$args{environment}}{@keys}); undef($compiler); if ($alias && HAS_LEXICAL_VARS) { Devel::LexAlias::lexalias($code, $_, $args{environment}{$_}) for grep !/^\&/, @keys; } return $code; } my $tmp; sub _make_lexical_assignment { my ($key, $index, $alias) = @_; my $name = substr($key, 1); if (HAS_LEXICAL_SUBS and $key =~ /^\&/) { $tmp++; my $tmpname = '$__LEXICAL_SUB__'.$tmp; return "no warnings 'experimental::lexical_subs';". "use feature 'lexical_subs';". "my $tmpname = \$_[$index];". "my sub $name { goto $tmpname };"; } if (!$alias) { my $sigil = substr($key, 0, 1); return "my $key = $sigil\{ \$_[$index] };"; } elsif (HAS_LEXICAL_VARS) { return "my $key;"; } else { my $tieclass = { '@' => 'Eval::TypeTiny::_TieArray', '%' => 'Eval::TypeTiny::_TieHash', '$' => 'Eval::TypeTiny::_TieScalar', }->{ substr($key, 0, 1) }; return sprintf( 'tie(my(%s), "%s", $_[%d]);', $key, $tieclass, $index, ); } } { my $tie; sub _manufacture_ties { $tie ||= eval <<'FALLBACK'; } } no warnings qw(void once uninitialized numeric); { package # Eval::TypeTiny::_TieArray; require Tie::Array; our @ISA = qw( Tie::StdArray ); sub TIEARRAY { my $class = shift; bless $_[0] => $class; } sub AUTOLOAD { my $self = shift; my ($method) = (our $AUTOLOAD =~ /(\w+)$/); defined tied(@$self) and return tied(@$self)->$method(@_); require Carp; Carp::croak(qq[Can't call method "$method" on an undefined value]); } sub can { my $self = shift; my $code = $self->SUPER::can(@_) || (defined tied(@$self) and tied(@$self)->can(@_)); return $code; } use overload q[bool] => sub { !! tied @{$_[0]} }, q[""] => sub { '' . tied @{$_[0]} }, q[0+] => sub { 0 + tied @{$_[0]} }, fallback => 1, ; } { package # Eval::TypeTiny::_TieHash; require Tie::Hash; our @ISA = qw( Tie::StdHash ); sub TIEHASH { my $class = shift; bless $_[0] => $class; } sub AUTOLOAD { my $self = shift; my ($method) = (our $AUTOLOAD =~ /(\w+)$/); defined tied(%$self) and return tied(%$self)->$method(@_); require Carp; Carp::croak(qq[Can't call method "$method" on an undefined value]); } sub can { my $self = shift; my $code = $self->SUPER::can(@_) || (defined tied(%$self) and tied(%$self)->can(@_)); return $code; } use overload q[bool] => sub { !! tied %{$_[0]} }, q[""] => sub { '' . tied %{$_[0]} }, q[0+] => sub { 0 + tied %{$_[0]} }, fallback => 1, ; } { package # Eval::TypeTiny::_TieScalar; require Tie::Scalar; our @ISA = qw( Tie::StdScalar ); sub TIESCALAR { my $class = shift; bless $_[0] => $class; } sub AUTOLOAD { my $self = shift; my ($method) = (our $AUTOLOAD =~ /(\w+)$/); defined tied($$self) and return tied($$self)->$method(@_); require Carp; Carp::croak(qq[Can't call method "$method" on an undefined value]); } sub can { my $self = shift; my $code = $self->SUPER::can(@_) || (defined tied($$self) and tied($$self)->can(@_)); return $code; } use overload q[bool] => sub { !! tied ${$_[0]} }, q[""] => sub { '' . tied ${$_[0]} }, q[0+] => sub { 0 + tied ${$_[0]} }, fallback => 1, ; } 1; FALLBACK 1; __END__ =pod =encoding utf-8 =for stopwords pragmas coderefs =head1 NAME Eval::TypeTiny - utility to evaluate a string of Perl code in a clean environment =head1 STATUS This module is considered part of Type-Tiny's internals. It is not covered by the L. =head1 DESCRIPTION This module is used by Type::Tiny to compile coderefs from strings of Perl code, and hashrefs of variables to close over. =head2 Functions This module exports one function, which works much like the similarly named function from L: =over =item C<< eval_closure(source => $source, environment => \%env, %opt) >> =back =head2 Constants The following constants may be exported, but are not by default. =over =item C<< HAS_LEXICAL_SUBS >> Boolean indicating whether Eval::TypeTiny has support for lexical subs. (This feature requires Perl 5.18.) =item C<< HAS_LEXICAL_VARS >> Don't worry; closing over lexical variables in the closures is always supported! However, if this constant is true, it means that L is available, which makes them slightly faster than the fallback solution which uses tied variables. (This only makes any difference when the C<< alias => 1 >> option is used.) =back =head1 EVALUATION ENVIRONMENT The evaluation is performed in the presence of L, but the absence of L. (This is different to L which enables warnings for compiled closures.) The L pragma is not active in the evaluation environment, so the following will not work: use feature qw(say); use Eval::TypeTiny qw(eval_closure); my $say_all = eval_closure( source => 'sub { say for @_ }', ); $say_all->("Hello", "World"); The L pragma does not "carry over" into the stringy eval. It is of course possible to import pragmas into the evaluated string as part of the string itself: use Eval::TypeTiny qw(eval_closure); my $say_all = eval_closure( source => 'sub { use feature qw(say); say for @_ }', ); $say_all->("Hello", "World"); =head1 BUGS Please report any bugs to L. =head1 SEE ALSO L, L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. TypeTiny.pm000664001750001750 1260712422772210 16235 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Testpackage Test::TypeTiny; use strict; use warnings; use Test::More qw(); use Scalar::Util qw(blessed); use Types::TypeTiny qw(to_TypeTiny); require Exporter::Tiny; our @ISA = 'Exporter::Tiny'; BEGIN { *EXTENDED_TESTING = $ENV{EXTENDED_TESTING} ? sub(){!!1} : sub(){!!0}; }; our $AUTHORITY = 'cpan:TOBYINK'; our $VERSION = '1.000005'; our @EXPORT = qw( should_pass should_fail ok_subtype ); our @EXPORT_OK = qw( EXTENDED_TESTING matchfor ); sub matchfor { my @matchers = @_; bless \@matchers, do { package # Test::TypeTiny::Internal::MATCHFOR; use overload q[==] => 'match', q[eq] => 'match', q[""] => 'to_string', fallback => 1; sub to_string { $_[0][0] } sub match { my ($self, $e) = @_; my $does = Scalar::Util::blessed($e) ? ($e->can('DOES') || $e->can('isa')) : undef; for my $s (@$self) { return 1 if ref($s) && $e =~ $s; return 1 if !ref($s) && $does && $e->$does($s); } return; } __PACKAGE__; }; } sub _mk_message { require Type::Tiny; my ($template, $value) = @_; sprintf($template, Type::Tiny::_dd($value)); } sub ok_subtype { my ($type, @s) = @_; @_ = ( not(scalar grep !$_->is_subtype_of($type), @s), sprintf("%s subtype: %s", $type, join q[, ], @s), ); goto \&Test::More::ok; } eval(EXTENDED_TESTING ? <<'SLOW' : <<'FAST'); sub should_pass { my ($value, $type, $message) = @_; local $Test::Builder::Level = $Test::Builder::Level + 1; $type = to_TypeTiny($type) unless blessed($type) && $type->can("check"); my $strictures = $type->can("_strict_check"); my $test = "Test::Builder"->new->child( $message || _mk_message("%s passes type constraint $type", $value), ); $test->plan(tests => ($strictures ? 2 : 1)); $test->ok(!!$type->check($value), '->check'); $test->ok(!!$type->_strict_check($value), '->_strict_check') if $strictures; $test->finalize; return $test->is_passing; } sub should_fail { my ($value, $type, $message) = @_; $type = to_TypeTiny($type) unless blessed($type) && $type->can("check"); local $Test::Builder::Level = $Test::Builder::Level + 1; my $strictures = $type->can("_strict_check"); my $test = "Test::Builder"->new->child( $message || _mk_message("%s fails type constraint $type", $value), ); $test->plan(tests => ($strictures ? 2 : 1)); $test->ok(!$type->check($value), '->check'); $test->ok(!$type->_strict_check($value), '->_strict_check') if $strictures; $test->finalize; return $test->is_passing; } SLOW sub should_pass { my ($value, $type, $message) = @_; $type = to_TypeTiny($type) unless blessed($type) && $type->can("check"); @_ = ( !!$type->check($value), $message || _mk_message("%s passes type constraint $type", $value), ); goto \&Test::More::ok; } sub should_fail { my ($value, $type, $message) = @_; $type = to_TypeTiny($type) unless blessed($type) && $type->can("check"); @_ = ( !$type->check($value), $message || _mk_message("%s fails type constraint $type", $value), ); goto \&Test::More::ok; } FAST 1; __END__ =pod =encoding utf-8 =head1 NAME Test::TypeTiny - useful functions for testing the efficacy of type constraints =head1 SYNOPSIS =for test_synopsis BEGIN { die "SKIP: uses a module that doesn't exist as an example" }; use strict; use warnings; use Test::More; use Test::TypeTiny; use Types::Mine qw(Integer Number); should_pass(1, Integer); should_pass(-1, Integer); should_pass(0, Integer); should_fail(2.5, Integer); ok_subtype(Number, Integer); done_testing; =head1 STATUS This module is covered by the L. =head1 DESCRIPTION L provides a few handy functions for testing type constraints. =head2 Functions =over =item C<< should_pass($value, $type, $test_name) >> =item C<< should_pass($value, $type) >> Test that passes iff C<< $value >> passes C<< $type->check >>. =item C<< should_fail($value, $type, $test_name) >> =item C<< should_fail($value, $type) >> Test that passes iff C<< $value >> fails C<< $type->check >>. =item C<< ok_subtype($type, @subtypes) >> Test that passes iff all C<< @subtypes >> are subtypes of C<< $type >>. =item C<< EXTENDED_TESTING >> Exportable boolean constant. =item C<< matchfor(@things) >> Assistant for matching exceptions. Not exported by default. See also L. =back =head1 ENVIRONMENT If the C environment variable is set to true, this module will promote each C or C test into a subtest block and test the type constraint in both an inlined and non-inlined manner. This variable must be set at compile time (i.e. before this module is loaded). =head1 BUGS Please report any bugs to L. =head1 SEE ALSO L. For an alternative to C, see L which will happily accept a Type::Tiny type constraint instead of a MooseX::Types one. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. Coercion.pm000664001750001750 5325712422772210 16221 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Typepackage Type::Coercion; use 5.006001; use strict; use warnings; BEGIN { $Type::Coercion::AUTHORITY = 'cpan:TOBYINK'; $Type::Coercion::VERSION = '1.000005'; } use Eval::TypeTiny qw<>; use Scalar::Util qw< blessed >; use Types::TypeTiny qw<>; sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak } use overload q("") => sub { caller =~ m{^(Moo::HandleMoose|Sub::Quote)} ? overload::StrVal($_[0]) : $_[0]->display_name }, q(bool) => sub { 1 }, q(&{}) => "_overload_coderef", fallback => 1, ; BEGIN { require Type::Tiny; overload->import( q(~~) => sub { $_[0]->has_coercion_for_value($_[1]) }, fallback => 1, # 5.10 loses the fallback otherwise ) if Type::Tiny::SUPPORT_SMARTMATCH(); } sub _overload_coderef { my $self = shift; if ("Sub::Quote"->can("quote_sub") && $self->can_be_inlined) { $self->{_overload_coderef} = Sub::Quote::quote_sub($self->inline_coercion('$_[0]')) if !$self->{_overload_coderef} || !$self->{_sub_quoted}++; } else { $self->{_overload_coderef} ||= sub { $self->coerce(@_) }; } $self->{_overload_coderef}; } sub new { my $class = shift; my %params = (@_==1) ? %{$_[0]} : @_; $params{name} = '__ANON__' unless exists($params{name}); my $C = delete($params{type_coercion_map}) || []; my $F = delete($params{frozen}); my $self = bless \%params, $class; $self->add_type_coercions(@$C) if @$C; $self->_preserve_type_constraint; Scalar::Util::weaken($self->{type_constraint}); # break ref cycle $self->{frozen} = $F if $F; unless ($self->is_anon) { # First try a fast ASCII-only expression, but fall back to Unicode $self->name =~ /^_{0,2}[A-Z][A-Za-z0-9_]+$/sm or eval q( use 5.008; $self->name =~ /^_{0,2}\p{Lu}[\p{L}0-9_]+$/sm ) or _croak '"%s" is not a valid coercion name', $self->name; } return $self; } sub name { $_[0]{name} } sub display_name { $_[0]{display_name} ||= $_[0]->_build_display_name } sub library { $_[0]{library} } sub type_constraint { $_[0]{type_constraint} ||= $_[0]->_maybe_restore_type_constraint } sub type_coercion_map { $_[0]{type_coercion_map} ||= [] } sub moose_coercion { $_[0]{moose_coercion} ||= $_[0]->_build_moose_coercion } sub compiled_coercion { $_[0]{compiled_coercion} ||= $_[0]->_build_compiled_coercion } sub frozen { $_[0]{frozen} ||= 0 } sub coercion_generator { $_[0]{coercion_generator} } sub parameters { $_[0]{parameters} } sub parameterized_from { $_[0]{parameterized_from} } sub has_library { exists $_[0]{library} } sub has_type_constraint { defined $_[0]->type_constraint } # sic sub has_coercion_generator { exists $_[0]{coercion_generator} } sub has_parameters { exists $_[0]{parameters} } sub _preserve_type_constraint { my $self = shift; $self->{_compiled_type_constraint_check} = $self->{type_constraint}->compiled_check if $self->{type_constraint}; } sub _maybe_restore_type_constraint { my $self = shift; if ( my $check = $self->{_compiled_type_constraint_check} ) { return Type::Tiny->new(constraint => $check); } return; } sub add { my $class = shift; my ($x, $y, $swap) = @_; Types::TypeTiny::TypeTiny->check($x) and return $x->plus_fallback_coercions($y); Types::TypeTiny::TypeTiny->check($y) and return $y->plus_coercions($x); _croak "Attempt to add $class to something that is not a $class" unless blessed($x) && blessed($y) && $x->isa($class) && $y->isa($class); ($y, $x) = ($x, $y) if $swap; my %opts; if ($x->has_type_constraint and $y->has_type_constraint and $x->type_constraint == $y->type_constraint) { $opts{type_constraint} = $x->type_constraint; } elsif ($x->has_type_constraint and $y->has_type_constraint) { # require Type::Tiny::Union; # $opts{type_constraint} = "Type::Tiny::Union"->new( # type_constraints => [ $x->type_constraint, $y->type_constraint ], # ); } $opts{display_name} ||= "$x+$y"; delete $opts{display_name} if $opts{display_name} eq '__ANON__+__ANON__'; my $new = $class->new(%opts); $new->add_type_coercions( @{$x->type_coercion_map} ); $new->add_type_coercions( @{$y->type_coercion_map} ); return $new; } sub _build_display_name { shift->name; } sub qualified_name { my $self = shift; if ($self->has_library and not $self->is_anon) { return sprintf("%s::%s", $self->library, $self->name); } return $self->name; } sub is_anon { my $self = shift; $self->name eq "__ANON__"; } sub _clear_compiled_coercion { delete $_[0]{_overload_coderef}; delete $_[0]{compiled_coercion}; } sub freeze { $_[0]{frozen} = 1; $_[0] } sub i_really_want_to_unfreeze { $_[0]{frozen} = 0; $_[0] } sub coerce { my $self = shift; return $self->compiled_coercion->(@_); } sub assert_coerce { my $self = shift; my $r = $self->coerce(@_); $self->type_constraint->assert_valid($r) if $self->has_type_constraint; return $r; } sub has_coercion_for_type { my $self = shift; my $type = Types::TypeTiny::to_TypeTiny($_[0]); return "0 but true" if $self->has_type_constraint && $type->is_a_type_of($self->type_constraint); my $c = $self->type_coercion_map; for (my $i = 0; $i <= $#$c; $i += 2) { return !!1 if $type->is_a_type_of($c->[$i]); } return; } sub has_coercion_for_value { my $self = shift; local $_ = $_[0]; return "0 but true" if $self->has_type_constraint && $self->type_constraint->check(@_); my $c = $self->type_coercion_map; for (my $i = 0; $i <= $#$c; $i += 2) { return !!1 if $c->[$i]->check(@_); } return; } sub add_type_coercions { my $self = shift; my @args = @_; _croak "Attempt to add coercion code to a Type::Coercion which has been frozen" if $self->frozen; while (@args) { my $type = Types::TypeTiny::to_TypeTiny(shift @args); my $coercion = shift @args; _croak "Types must be blessed Type::Tiny objects" unless Types::TypeTiny::TypeTiny->check($type); _croak "Coercions must be code references or strings" unless Types::TypeTiny::StringLike->check($coercion) || Types::TypeTiny::CodeLike->check($coercion); push @{$self->type_coercion_map}, $type, $coercion; } $self->_clear_compiled_coercion; return $self; } sub _build_compiled_coercion { my $self = shift; my @mishmash = @{$self->type_coercion_map}; return sub { $_[0] } unless @mishmash; if ($self->can_be_inlined) { return Eval::TypeTiny::eval_closure( source => sprintf('sub ($) { %s }', $self->inline_coercion('$_[0]')), description => sprintf("compiled coercion '%s'", $self), ); } # These arrays will be closed over. my (@types, @codes); while (@mishmash) { push @types, shift @mishmash; push @codes, shift @mishmash; } if ($self->has_type_constraint) { unshift @types, $self->type_constraint; unshift @codes, undef; } my @sub; for my $i (0..$#types) { push @sub, $types[$i]->can_be_inlined ? sprintf('if (%s)', $types[$i]->inline_check('$_[0]')) : sprintf('if ($checks[%d]->(@_))', $i); push @sub, !defined($codes[$i]) ? sprintf(' { return $_[0] }') : Types::TypeTiny::StringLike->check($codes[$i]) ? sprintf(' { local $_ = $_[0]; return scalar(%s); }', $codes[$i]) : sprintf(' { local $_ = $_[0]; return scalar($codes[%d]->(@_)) }', $i); } push @sub, 'return $_[0];'; return Eval::TypeTiny::eval_closure( source => sprintf('sub ($) { %s }', join qq[\n], @sub), description => sprintf("compiled coercion '%s'", $self), environment => { '@checks' => [ map $_->compiled_check, @types ], '@codes' => \@codes, }, ); } sub can_be_inlined { my $self = shift; return unless $self->frozen; return if $self->has_type_constraint && !$self->type_constraint->can_be_inlined; my @mishmash = @{$self->type_coercion_map}; while (@mishmash) { my ($type, $converter) = splice(@mishmash, 0, 2); return unless $type->can_be_inlined; return unless Types::TypeTiny::StringLike->check($converter); } return !!1; } sub _source_type_union { my $self = shift; my @r; push @r, $self->type_constraint if $self->has_type_constraint; my @mishmash = @{$self->type_coercion_map}; while (@mishmash) { my ($type) = splice(@mishmash, 0, 2); push @r, $type; } require Type::Tiny::Union; return "Type::Tiny::Union"->new(type_constraints => \@r, tmp => 1); } sub inline_coercion { my $self = shift; my $varname = $_[0]; _croak "This coercion cannot be inlined" unless $self->can_be_inlined; my @mishmash = @{$self->type_coercion_map}; return "($varname)" unless @mishmash; my (@types, @codes); while (@mishmash) { push @types, shift @mishmash; push @codes, shift @mishmash; } if ($self->has_type_constraint) { unshift @types, $self->type_constraint; unshift @codes, undef; } my @sub; for my $i (0..$#types) { push @sub, sprintf('(%s) ?', $types[$i]->inline_check($varname)); push @sub, (defined($codes[$i]) && ($varname eq '$_')) ? sprintf('scalar(do { %s }) :', $codes[$i]) : defined($codes[$i]) ? sprintf('scalar(do { local $_ = %s; %s }) :', $varname, $codes[$i]) : sprintf('%s :', $varname); } push @sub, "$varname"; "@sub"; } sub _build_moose_coercion { my $self = shift; my %options = (); $options{type_coercion_map} = [ $self->freeze->_codelike_type_coercion_map('moose_type') ]; $options{type_constraint} = $self->type_constraint if $self->has_type_constraint; require Moose::Meta::TypeCoercion; my $r = "Moose::Meta::TypeCoercion"->new(%options); return $r; } sub _codelike_type_coercion_map { my $self = shift; my $modifier = $_[0]; my @orig = @{ $self->type_coercion_map }; my @new; while (@orig) { my ($type, $converter) = splice(@orig, 0, 2); push @new, $modifier ? $type->$modifier : $type; if (Types::TypeTiny::CodeLike->check($converter)) { push @new, $converter; } else { push @new, Eval::TypeTiny::eval_closure( source => sprintf('sub { local $_ = $_[0]; %s }', $converter), description => sprintf("temporary compiled converter from '%s'", $type), ); } } return @new; } sub is_parameterizable { shift->has_coercion_generator; } sub is_parameterized { shift->has_parameters; } sub parameterize { my $self = shift; return $self unless @_; $self->is_parameterizable or _croak "Constraint '%s' does not accept parameters", "$self"; @_ = map Types::TypeTiny::to_TypeTiny($_), @_; return ref($self)->new( type_constraint => $self->type_constraint, type_coercion_map => [ $self->coercion_generator->($self, $self->type_constraint, @_) ], parameters => \@_, frozen => 1, parameterized_from => $self, ); } sub _reparameterize { my $self = shift; my ($target_type) = @_; $self->is_parameterized or return $self; my $parent = $self->parameterized_from; return ref($self)->new( type_constraint => $target_type, type_coercion_map => [ $parent->coercion_generator->($parent, $target_type, @{$self->parameters}) ], parameters => \@_, frozen => 1, parameterized_from => $parent, ); } sub isa { my $self = shift; if ($INC{"Moose.pm"} and blessed($self) and $_[0] eq 'Moose::Meta::TypeCoercion') { return !!1; } if ($INC{"Moose.pm"} and blessed($self) and $_[0] =~ /^(Class::MOP|MooseX?)::/) { my $r = $self->moose_coercion->isa(@_); return $r if $r; } $self->SUPER::isa(@_); } sub can { my $self = shift; my $can = $self->SUPER::can(@_); return $can if $can; if ($INC{"Moose.pm"} and blessed($self) and my $method = $self->moose_coercion->can(@_)) { return sub { $method->(shift->moose_coercion, @_) }; } return; } sub AUTOLOAD { my $self = shift; my ($m) = (our $AUTOLOAD =~ /::(\w+)$/); return if $m eq 'DESTROY'; if ($INC{"Moose.pm"} and blessed($self) and my $method = $self->moose_coercion->can($m)) { return $method->($self->moose_coercion, @_); } _croak q[Can't locate object method "%s" via package "%s"], $m, ref($self)||$self; } # Private Moose method, but Moo uses this... sub _compiled_type_coercion { my $self = shift; if (@_) { my $thing = $_[0]; if (blessed($thing) and $thing->isa("Type::Coercion")) { $self->add_type_coercions(@{$thing->type_coercion_map}); } elsif (Types::TypeTiny::CodeLike->check($thing)) { require Types::Standard; $self->add_type_coercions(Types::Standard::Any(), $thing); } } $self->compiled_coercion; } *compile_type_coercion = \&compiled_coercion; sub meta { _croak("Not really a Moose::Meta::TypeCoercion. Sorry!") } 1; __END__ =pod =encoding utf-8 =head1 NAME Type::Coercion - a set of coercions to a particular target type constraint =head1 STATUS This module is covered by the L. =head1 DESCRIPTION =head2 Constructors =over =item C<< new(%attributes) >> Moose-style constructor function. =item C<< add($c1, $c2) >> Create a Type::Coercion from two existing Type::Coercion objects. =back =head2 Attributes Attributes are named values that may be passed to the constructor. For each attribute, there is a corresponding reader method. For example: my $c = Type::Coercion->new( type_constraint => Int ); my $t = $c->type_constraint; # Int =head3 Important attributes These are the attributes you are likely to be most interested in providing when creating your own type coercions, and most interested in reading when dealing with coercion objects. =over =item C Weak reference to the target type constraint (i.e. the type constraint which the output of coercion coderefs is expected to conform to). =item C Arrayref of source-type/code pairs. =item C Boolean; default false. A frozen coercion cannot have C called upon it. =item C A name for the coercion. These need to conform to certain naming rules (they must begin with an uppercase letter and continue using only letters, digits 0-9 and underscores). Optional; if not supplied will be an anonymous coercion. =item C A name to display for the coercion when stringified. These don't have to conform to any naming rules. Optional; a default name will be calculated from the C. =item C The package name of the type library this coercion is associated with. Optional. Informational only: setting this attribute does not install the coercion into the package. =back =head3 Attributes related to parameterizable and parameterized coercions The following attributes are used for parameterized coercions, but are not fully documented because they may change in the near future: =over =item C<< coercion_generator >> =item C<< parameters >> =item C<< parameterized_from >> =back =head3 Lazy generated attributes The following attributes should not be usually passed to the constructor; unless you're doing something especially unusual, you should rely on the default lazily-built return values. =over =item C<< compiled_coercion >> Coderef to coerce a value (C<< $_[0] >>). The general point of this attribute is that you should not set it, but rely on the lazily-built default. Type::Coerce will usually generate a pretty fast coderef, inlining all type constraint checks, etc. =item C A L object equivalent to this one. Don't set this manually; rely on the default built one. =back =head2 Methods =head3 Predicate methods These methods return booleans indicating information about the coercion. They are each tightly associated with a particular attribute. (See L.) =over =item C, C Simple Moose-style predicate methods indicating the presence or absence of an attribute. =item C Returns true iff the coercion does not have a C. =back The following predicates are used for parameterized coercions, but are not fully documented because they may change in the near future: =over =item C<< has_coercion_generator >> =item C<< has_parameters >> =item C<< is_parameterizable >> =item C<< is_parameterized >> =back =head3 Coercion The following methods are used for coercing values to a type constraint: =over =item C<< coerce($value) >> Coerce the value to the target type. Returns the coerced value, or the original value if no coercion was possible. =item C<< assert_coerce($value) >> Coerce the value to the target type, and throw an exception if the result does not validate against the target type constraint. Returns the coerced value. =back =head3 Coercion code definition methods These methods all return C<< $self >> so are suitable for chaining. =over =item C<< add_type_coercions($type1, $code1, ...) >> Takes one or more pairs of L constraints and coercion code, creating an ordered list of source types and coercion codes. Coercion codes can be expressed as either a string of Perl code (this includes objects which overload stringification), or a coderef (or object that overloads coderefification). In either case, the value to be coerced is C<< $_ >>. C<< add_type_coercions($coercion_object) >> also works, and can be used to copy coercions from another type constraint: $type->coercion->add_type_coercions($othertype->coercion)->freeze; =item C<< freeze >> Sets the C attribute to true. Called automatically by L sometimes. =item C<< i_really_want_to_unfreeze >> If you really want to unfreeze a coercion, call this method. Don't call this method. It will potentially lead to subtle bugs. This method is considered unstable; future versions of Type::Tiny may alter its behaviour (e.g. to throw an exception if it has been detected that unfreezing this particular coercion will cause bugs). =back =head3 Parameterization The following method is used for parameterized coercions, but is not fully documented because it may change in the near future: =over =item C<< parameterize(@params) >> =back =head3 Type coercion introspection methods These methods allow you to determine a coercion's relationship to type constraints: =over =item C<< has_coercion_for_type($source_type) >> Returns true iff this coercion has a coercion from the source type. Returns the special string C<< "0 but true" >> if no coercion should actually be necessary for this type. (For example, if a coercion coerces to a theoretical "Number" type, there is probably no coercion necessary for values that already conform to the "Integer" type.) =item C<< has_coercion_for_value($value) >> Returns true iff the value could be coerced by this coercion. Returns the special string C<< "0 but true" >> if no coercion would be actually be necessary for this value (due to it already meeting the target type constraint). =back The C attribute provides a type constraint object for the target type constraint of the coercion. See L. =head3 Inlining methods =for stopwords uated The following methods are used to generate strings of Perl code which may be pasted into stringy Cuated subs to perform type coercions: =over =item C<< can_be_inlined >> Returns true iff the coercion can be inlined. =item C<< inline_coercion($varname) >> Much like C from L. =back =head3 Other methods =over =item C<< qualified_name >> For non-anonymous coercions that have a library, returns a qualified C<< "MyLib::MyCoercion" >> sort of name. Otherwise, returns the same as C. =item C<< isa($class) >>, C<< can($method) >>, C<< AUTOLOAD(@args) >> If Moose is loaded, then the combination of these methods is used to mock a Moose::Meta::TypeCoercion. =back The following methods exist for Moose/Mouse compatibility, but do not do anything useful. =over =item C<< compile_type_coercion >> =item C<< meta >> =back =head2 Overloading =over =item * Boolification is overloaded to always return true. =item * Coderefification is overloaded to call C. =item * On Perl 5.10.1 and above, smart match is overloaded to call C. =back Previous versions of Type::Coercion would overload the C<< + >> operator to call C. Support for this was dropped after 0.040. =head1 DIAGNOSTICS =over =item B<< Attempt to add coercion code to a Type::Coercion which has been frozen >> Type::Tiny type constraints are designed as immutable objects. Once you've created a constraint, rather than modifying it you generally create child constraints to do what you need. Type::Coercion objects, on the other hand, are mutable. Coercion routines can be added at any time during the object's lifetime. Sometimes Type::Tiny needs to freeze a Type::Coercion object to prevent this. In L and L code this is likely to happen as soon as you use a type constraint in an attribute. Workarounds: =over =item * Define as many of your coercions as possible within type libraries, not within the code that uses the type libraries. The type library will be evaluated relatively early, likely before there is any reason to freeze a coercion. =item * If you do need to add coercions to a type within application code outside the type library, instead create a subtype and add coercions to that. The C method provided by L should make this simple. =back =back =head1 BUGS Please report any bugs to L. =head1 SEE ALSO L. L, L, L, L. L. L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. Library.pm000664001750001750 3314712422772210 16060 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Typepackage Type::Library; use 5.006001; use strict; use warnings; BEGIN { $Type::Library::AUTHORITY = 'cpan:TOBYINK'; $Type::Library::VERSION = '1.000005'; } use Eval::TypeTiny qw< eval_closure >; use Scalar::Util qw< blessed refaddr >; use Type::Tiny; use Types::TypeTiny qw< TypeTiny to_TypeTiny >; require Exporter::Tiny; our @ISA = 'Exporter::Tiny'; BEGIN { *NICE_PROTOTYPES = ($] >= 5.014) ? sub () { !!1 } : sub () { !!0 } }; sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak } { my $got_subname; my %already; # prevent renaming established functions sub _subname ($$) { ($got_subname or eval "require Sub::Name") and ($got_subname = 1) and !$already{refaddr($_[1])}++ and return(Sub::Name::subname(@_)); return $_[1]; } } sub _exporter_validate_opts { my $class = shift; no strict "refs"; my $into = $_[0]{into}; push @{"$into\::ISA"}, $class if $_[0]{base}; return $class->SUPER::_exporter_validate_opts(@_); } sub _exporter_expand_tag { my $class = shift; my ($name, $value, $globals) = @_; $name eq 'types' and return map [ "$_" => $value ], $class->type_names; $name eq 'is' and return map [ "is_$_" => $value ], $class->type_names; $name eq 'assert' and return map [ "assert_$_" => $value ], $class->type_names; $name eq 'to' and return map [ "to_$_" => $value ], $class->type_names; $name eq 'coercions' and return map [ "$_" => $value ], $class->coercion_names; if ($name eq 'all') { no strict "refs"; return ( map( [ "+$_" => $value ], $class->type_names, ), map( [ $_ => $value ], $class->coercion_names, @{"$class\::EXPORT"}, @{"$class\::EXPORT_OK"}, ), ); } return $class->SUPER::_exporter_expand_tag(@_); } sub _mksub { my $class = shift; my ($type, $post_method) = @_; $post_method ||= q(); my $source = $type->is_parameterizable ? sprintf( q{ sub (%s) { return $_[0]->complete($type) if ref($_[0]) eq 'Type::Tiny::_HalfOp'; my $params; $params = shift if ref($_[0]) eq q(ARRAY); my $t = $params ? $type->parameterize(@$params) : $type; @_ && wantarray ? return($t%s, @_) : return $t%s; } }, NICE_PROTOTYPES ? q(;$) : q(;@), $post_method, $post_method, ) : sprintf( q{ sub () { $type%s if $] } }, $post_method, ); return _subname( $type->qualified_name, eval_closure( source => $source, description => sprintf("exportable function '%s'", $type), environment => {'$type' => \$type}, ), ); } sub _exporter_permitted_regexp { my $class = shift; my $inherited = $class->SUPER::_exporter_permitted_regexp(@_); my $types = join "|", map quotemeta, sort { length($b) <=> length($a) or $a cmp $b } $class->type_names; my $coercions = join "|", map quotemeta, sort { length($b) <=> length($a) or $a cmp $b } $class->coercion_names; qr{^(?: $inherited | (?: (?:is_|to_|assert_)? (?:$types) ) | (?:$coercions) )$}xms; } sub _exporter_expand_sub { my $class = shift; my ($name, $value, $globals) = @_; if ($name =~ /^\+(.+)/ and $class->has_type($1)) { my $type = $1; my $value2 = +{%{$value||{}}}; return map $class->_exporter_expand_sub($_, $value2, $globals), $type, "is_$type", "assert_$type", "to_$type"; } if (my $type = $class->get_type($name)) { my $post_method = q(); $post_method = '->mouse_type' if $globals->{mouse}; $post_method = '->moose_type' if $globals->{moose}; return ($name => $class->_mksub($type, $post_method)) if $post_method; } return $class->SUPER::_exporter_expand_sub(@_); } sub _exporter_install_sub { my $class = shift; my ($name, $value, $globals, $sym) = @_; my $package = $globals->{into}; if (!ref $package and my $type = $class->get_type($name)) { my ($prefix) = grep defined, $value->{-prefix}, $globals->{prefix}, q(); my ($suffix) = grep defined, $value->{-suffix}, $globals->{suffix}, q(); my $as = $prefix . ($value->{-as} || $name) . $suffix; $INC{'Type/Registry.pm'} ? 'Type::Registry'->for_class($package)->add_type($type, $as) : ($Type::Registry::DELAYED{$package}{$as} = $type); } $class->SUPER::_exporter_install_sub(@_); } sub _exporter_fail { my $class = shift; my ($name, $value, $globals) = @_; my $into = $globals->{into} or _croak("Parameter 'into' not supplied"); if ($globals->{declare}) { my $declared = sub (;$) { my $params; $params = shift if ref($_[0]) eq "ARRAY"; my $type = $into->get_type($name); unless ($type) { _croak "Cannot parameterize a non-existant type" if $params; $type = $name; } my $t = $params ? $type->parameterize(@$params) : $type; @_ && wantarray ? return($t, @_) : return $t; }; return( $name, _subname( "$class\::$name", NICE_PROTOTYPES ? sub (;$) { goto $declared } : sub (;@) { goto $declared }, ), ); } return $class->SUPER::_exporter_fail(@_); } sub meta { no strict "refs"; no warnings "once"; return $_[0] if blessed $_[0]; ${"$_[0]\::META"} ||= bless {}, $_[0]; } sub add_type { my $meta = shift->meta; my $class = blessed($meta); my $type = ref($_[0]) =~ /^Type::Tiny\b/ ? $_[0] : blessed($_[0]) ? to_TypeTiny($_[0]) : ref($_[0]) eq q(HASH) ? "Type::Tiny"->new(library => $class, %{$_[0]}) : "Type::Tiny"->new(library => $class, @_); my $name = $type->{name}; $meta->{types} ||= {}; _croak 'Type %s already exists in this library', $name if $meta->has_type($name); _croak 'Type %s conflicts with coercion of same name', $name if $meta->has_coercion($name); _croak 'Cannot add anonymous type to a library' if $type->is_anon; $meta->{types}{$name} = $type; no strict "refs"; no warnings "redefine", "prototype"; my $to_type = $type->has_coercion && $type->coercion->frozen ? $type->coercion->compiled_coercion : sub ($) { $type->coerce($_[0]) }; *{"$class\::$name"} = $class->_mksub($type); *{"$class\::is_$name"} = _subname "$class\::is_$name", $type->compiled_check; *{"$class\::to_$name"} = _subname "$class\::to_$name", $to_type; *{"$class\::assert_$name"} = _subname "$class\::assert_$name", $type->_overload_coderef; return $type; } sub get_type { my $meta = shift->meta; $meta->{types}{$_[0]}; } sub has_type { my $meta = shift->meta; exists $meta->{types}{$_[0]}; } sub type_names { my $meta = shift->meta; keys %{ $meta->{types} }; } sub add_coercion { require Type::Coercion; my $meta = shift->meta; my $c = blessed($_[0]) ? $_[0] : "Type::Coercion"->new(@_); my $name = $c->name; $meta->{coercions} ||= {}; _croak 'Coercion %s already exists in this library', $name if $meta->has_coercion($name); _croak 'Coercion %s conflicts with type of same name', $name if $meta->has_type($name); _croak 'Cannot add anonymous type to a library' if $c->is_anon; $meta->{coercions}{$name} = $c; no strict "refs"; no warnings "redefine", "prototype"; my $class = blessed($meta); *{"$class\::$name"} = $class->_mksub($c); return $c; } sub get_coercion { my $meta = shift->meta; $meta->{coercions}{$_[0]}; } sub has_coercion { my $meta = shift->meta; exists $meta->{coercions}{$_[0]}; } sub coercion_names { my $meta = shift->meta; keys %{ $meta->{coercions} }; } sub make_immutable { my $meta = shift->meta; my $class = ref($meta); for my $type (values %{$meta->{types}}) { $type->coercion->freeze; no strict "refs"; no warnings "redefine", "prototype"; my $to_type = $type->has_coercion && $type->coercion->frozen ? $type->coercion->compiled_coercion : sub ($) { $type->coerce($_[0]) }; my $name = $type->name; *{"$class\::to_$name"} = _subname "$class\::to_$name", $to_type; } 1; } 1; __END__ =pod =encoding utf-8 =for stopwords Moo(se)-compatible MooseX::Types-like =head1 NAME Type::Library - tiny, yet Moo(se)-compatible type libraries =head1 SYNOPSIS =for test_synopsis BEGIN { die "SKIP: crams multiple modules into single example" }; package Types::Mine { use Scalar::Util qw(looks_like_number); use Type::Library -base; use Type::Tiny; my $NUM = "Type::Tiny"->new( name => "Number", constraint => sub { looks_like_number($_) }, message => sub { "$_ ain't a number" }, ); __PACKAGE__->meta->add_type($NUM); __PACKAGE__->meta->make_immutable; } package Ermintrude { use Moo; use Types::Mine qw(Number); has favourite_number => (is => "ro", isa => Number); } package Bullwinkle { use Moose; use Types::Mine qw(Number); has favourite_number => (is => "ro", isa => Number); } package Maisy { use Mouse; use Types::Mine qw(Number); has favourite_number => (is => "ro", isa => Number); } =head1 STATUS This module is covered by the L. =head1 DESCRIPTION L is a tiny class for creating MooseX::Types-like type libraries which are compatible with Moo, Moose and Mouse. If you're reading this because you want to create a type library, then you're probably better off reading L. =head2 Methods A type library is a singleton class. Use the C method to get a blessed object which other methods can get called on. For example: Types::Mine->meta->add_type($foo); =begin trustme =item meta =end trustme =over =item C<< add_type($type) >> or C<< add_type(%opts) >> Add a type to the library. If C<< %opts >> is given, then this method calls C<< Type::Tiny->new(%opts) >> first, and adds the resultant type. Adding a type named "Foo" to the library will automatically define four functions in the library's namespace: =over =item C<< Foo >> Returns the Type::Tiny object. =item C<< is_Foo($value) >> Returns true iff $value passes the type constraint. =item C<< assert_Foo($value) >> Returns $value iff $value passes the type constraint. Dies otherwise. =item C<< to_Foo($value) >> Coerces the value to the type. =back =item C<< get_type($name) >> Gets the C object corresponding to the name. =item C<< has_type($name) >> Boolean; returns true if the type exists in the library. =item C<< type_names >> List all types defined by the library. =item C<< add_coercion($c) >> or C<< add_coercion(%opts) >> Add a standalone coercion to the library. If C<< %opts >> is given, then this method calls C<< Type::Coercion->new(%opts) >> first, and adds the resultant coercion. Adding a coercion named "FooFromBar" to the library will automatically define a function in the library's namespace: =over =item C<< FooFromBar >> Returns the Type::Coercion object. =back =item C<< get_coercion($name) >> Gets the C object corresponding to the name. =item C<< has_coercion($name) >> Boolean; returns true if the coercion exists in the library. =item C<< coercion_names >> List all standalone coercions defined by the library. =item C<< import(@args) >> Type::Library-based libraries are exporters. =item C<< make_immutable >> A shortcut for calling C<< $type->coercion->freeze >> on every type constraint in the library. =back =head2 Constants =over =item C<< NICE_PROTOTYPES >> If this is true, then Type::Library will give parameterizable type constraints slightly the nicer prototype of C<< (;$) >> instead of the default C<< (;@) >>. This allows constructs like: ArrayRef[Int] | HashRef[Int] ... to "just work". =back =head2 Export Type libraries are exporters. For the purposes of the following examples, assume that the C library defines types C and C. # Exports nothing. # use Types::Mine; # Exports a function "String" which is a constant returning # the String type constraint. # use Types::Mine qw( String ); # Exports both String and Number as above. # use Types::Mine qw( String Number ); # Same. # use Types::Mine qw( :types ); # Exports a sub "is_String" so that "is_String($foo)" is equivalent # to "String->check($foo)". # use Types::Mine qw( is_String ); # Exports "is_String" and "is_Number". # use Types::Mine qw( :is ); # Exports a sub "assert_String" so that "assert_String($foo)" is # equivalent to "String->assert_return($foo)". # use Types::Mine qw( assert_String ); # Exports "assert_String" and "assert_Number". # use Types::Mine qw( :assert ); # Exports a sub "to_String" so that "to_String($foo)" is equivalent # to "String->coerce($foo)". # use Types::Mine qw( to_String ); # Exports "to_String" and "to_Number". # use Types::Mine qw( :to ); # Exports "String", "is_String", "assert_String" and "coerce_String". # use Types::Mine qw( +String ); # Exports everything. # use Types::Mine qw( :all ); Type libraries automatically inherit from L; see the documentation of that module for tips and tricks importing from libraries. =head1 BUGS Please report any bugs to L. =head1 SEE ALSO L. L, L, L, L. L, L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. Params.pm000664001750001750 4340412422772210 15674 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Typepackage Type::Params; use 5.006001; use strict; use warnings; BEGIN { if ($] < 5.008) { require Devel::TypeTiny::Perl56Compat }; } BEGIN { $Type::Params::AUTHORITY = 'cpan:TOBYINK'; $Type::Params::VERSION = '1.000005'; } use B qw(); use Eval::TypeTiny; use Scalar::Util qw(refaddr); use Error::TypeTiny; use Error::TypeTiny::Assertion; use Error::TypeTiny::WrongNumberOfParameters; use Type::Tiny::Union; use Types::Standard -types; use Types::TypeTiny qw(CodeLike ArrayLike to_TypeTiny); require Exporter::Tiny; our @ISA = 'Exporter::Tiny'; our @EXPORT = qw( compile ); our @EXPORT_OK = qw( multisig validate Invocant ); BEGIN { my $Invocant = 'Type::Tiny::Union'->new( name => 'Invocant', type_constraints => [Object, ClassName], ); sub Invocant () { $Invocant }; }; sub _mkslurpy { my ($name, $type, $tc, $i) = @_; $name = 'local $_' if $name eq '$_'; $type eq '@' ? sprintf( '%s = [ @_[%d..$#_] ];', $name, $i, ) : sprintf( '%s = (($#_-%d)%%2)==0 ? "Error::TypeTiny::WrongNumberOfParameters"->throw(message => sprintf("Odd number of elements in %%s", %s)) : +{ @_[%d..$#_] };', $name, $i, B::perlstring("$tc"), $i, ); } sub compile { my (@code, %env); @code = 'my (@R, %tmp, $tmp);'; push @code, '#placeholder'; # $code[1] my %options = (ref($_[0]) eq "HASH" && !$_[0]{slurpy}) ? %{+shift} : (); my $arg = -1; my $saw_slurpy = 0; my $min_args = 0; my $max_args = 0; my $saw_opt = 0; while (@_) { ++$arg; my $constraint = shift; my $is_optional; my $really_optional; my $is_slurpy; my $varname; if (Bool->check($constraint)) { $constraint = $constraint ? Any : Optional[Any]; } if (HashRef->check($constraint)) { $constraint = to_TypeTiny($constraint->{slurpy}); push @code, $constraint->is_a_type_of(Dict) ? _mkslurpy('$_', '%', $constraint => $arg) : $constraint->is_a_type_of(Map) ? _mkslurpy('$_', '%', $constraint => $arg) : $constraint->is_a_type_of(Tuple) ? _mkslurpy('$_', '@', $constraint => $arg) : $constraint->is_a_type_of(HashRef) ? _mkslurpy('$_', '%', $constraint => $arg) : $constraint->is_a_type_of(ArrayRef) ? _mkslurpy('$_', '@', $constraint => $arg) : Error::TypeTiny::croak("Slurpy parameter not of type HashRef or ArrayRef"); $varname = '$_'; $is_slurpy++; $saw_slurpy++; } else { Error::TypeTiny::croak("Parameter following slurpy parameter") if $saw_slurpy; $is_optional = grep $_->{uniq} == Optional->{uniq}, $constraint->parents; $really_optional = $is_optional && $constraint->parent->{uniq} eq Optional->{uniq} && $constraint->type_parameter; if ($is_optional) { push @code, sprintf 'return @R if $#_ < %d;', $arg; $saw_opt++; $max_args++; } else { Error::TypeTiny::croak("Non-Optional parameter following Optional parameter") if $saw_opt; $min_args++; $max_args++; } $varname = sprintf '$_[%d]', $arg; } if ($constraint->has_coercion and $constraint->coercion->can_be_inlined) { push @code, sprintf( '$tmp%s = %s;', ($is_optional ? '{x}' : ''), $constraint->coercion->inline_coercion($varname) ); $varname = '$tmp'.($is_optional ? '{x}' : ''); } elsif ($constraint->has_coercion) { $env{'@coerce'}[$arg] = $constraint->coercion->compiled_coercion; push @code, sprintf( '$tmp%s = $coerce[%d]->(%s);', ($is_optional ? '{x}' : ''), $arg, $varname, ); $varname = '$tmp'.($is_optional ? '{x}' : ''); } if ($constraint->can_be_inlined) { push @code, sprintf( '(%s) or Type::Tiny::_failed_check(%d, %s, %s, varname => %s);', $really_optional ? $constraint->type_parameter->inline_check($varname) : $constraint->inline_check($varname), $constraint->{uniq}, B::perlstring($constraint), $varname, $is_slurpy ? 'q{$SLURPY}' : sprintf('q{$_[%d]}', $arg), ); } else { $env{'@check'}[$arg] = $really_optional ? $constraint->type_parameter->compiled_check : $constraint->compiled_check; push @code, sprintf( '%s or Type::Tiny::_failed_check(%d, %s, %s, varname => %s);', sprintf(sprintf '$check[%d]->(%s)', $arg, $varname), $constraint->{uniq}, B::perlstring($constraint), $varname, $is_slurpy ? 'q{$SLURPY}' : sprintf('q{$_[%d]}', $arg), ); } push @code, sprintf 'push @R, %s;', $varname; } if ($min_args == $max_args and not $saw_slurpy) { $code[1] = sprintf( '"Error::TypeTiny::WrongNumberOfParameters"->throw(got => scalar(@_), minimum => %d, maximum => %d) if @_ != %d;', $min_args, $max_args, $min_args, ); } elsif ($min_args < $max_args and not $saw_slurpy) { $code[1] = sprintf( '"Error::TypeTiny::WrongNumberOfParameters"->throw(got => scalar(@_), minimum => %d, maximum => %d) if @_ < %d || @_ > %d;', $min_args, $max_args, $min_args, $max_args, ); } elsif ($min_args and $saw_slurpy) { $code[1] = sprintf( '"Error::TypeTiny::WrongNumberOfParameters"->throw(got => scalar(@_), minimum => %d) if @_ < %d;', $min_args, $min_args, ); } push @code, '@R;'; my $source = "sub { no warnings; ".join("\n", @code)." };"; return $source if $options{want_source}; my $closure = eval_closure( source => $source, description => sprintf("parameter validation for '%s'", [caller(1+($options{caller_level}||0))]->[3] || '__ANON__'), environment => \%env, ); return { min_args => $min_args, max_args => $saw_slurpy ? undef : $max_args, closure => $closure, } if $options{want_details}; return $closure; } my %compiled; sub validate { my $arr = shift; my $sub = $compiled{ join ":", map($_->{uniq}||"\@$_->{slurpy}", @_) } ||= compile({ caller_level => 1 }, @_); @_ = @$arr; goto $sub; } sub multisig { my %options = (ref($_[0]) eq "HASH" && !$_[0]{slurpy}) ? %{+shift} : (); my @multi = map { CodeLike->check($_) ? { closure => $_ } : ArrayLike->check($_) ? compile({ want_details => 1 }, @$_) : $_; } @_; my @code = 'sub { my $r; '; for my $i (0 .. $#multi) { my $sig = $multi[$i]; my @cond; push @cond, sprintf('@_ >= %s', $sig->{min_args}) if defined $sig->{min_args}; push @cond, sprintf('@_ <= %s', $sig->{max_args}) if defined $sig->{max_args}; push @code, sprintf('if (%s){', join(' and ', @cond)) if @cond; push @code, sprintf('eval { $r = [ $multi[%d]{closure}->(@_) ] };', $i); push @code, 'return(@$r) if $r;'; push @code, '}' if @cond; } push @code, '"Error::TypeTiny"->throw(message => "Parameter validation failed");'; push @code, '}'; eval_closure( source => \@code, description => sprintf("parameter validation for '%s'", [caller(1+($options{caller_level}||0))]->[3] || '__ANON__'), environment => { '@multi' => \@multi }, ); } 1; __END__ =pod =encoding utf-8 =for stopwords evals =head1 NAME Type::Params - Params::Validate-like parameter validation using Type::Tiny type constraints and coercions =head1 SYNOPSIS use v5.10; use strict; use warnings; use Type::Params qw( compile ); use Types::Standard qw( slurpy Str ArrayRef Num ); sub deposit_monies { state $check = compile( Str, Str, slurpy ArrayRef[Num] ); my ($sort_code, $account_number, $monies) = $check->(@_); my $account = Local::BankAccount->new($sort_code, $account_number); $account->deposit($_) for @$monies; } deposit_monies("12-34-56", "11223344", 1.2, 3, 99.99); =head1 STATUS This module is covered by the L. =head1 DESCRIPTION Type::Params uses L constraints to validate the parameters to a sub. It takes the slightly unorthodox approach of separating validation into two stages: =over =item 1. Compiling the parameter specification into a coderef; then =item 2. Using the coderef to validate parameters. =back The first stage is slow (it might take a couple of milliseconds), but you only need to do it the first time the sub is called. The second stage is fast; according to my benchmarks faster even than the XS version of L. If you're using a modern version of Perl, you can use the C keyword which was a feature added to Perl in 5.10. If you're stuck on Perl 5.8, the example from the SYNOPSIS could be rewritten as: my $deposit_monies_check; sub deposit_monies { $deposit_monies_check ||= compile( Str, Str, slurpy ArrayRef[Num] ); my ($sort_code, $account_number, $monies) = $check->(@_); ...; } Not quite as neat, but not awful either. There's a shortcut reducing it to one step: use Type::Params qw( validate ); sub deposit_monies { my ($sort_code, $account_number, $monies) = validate( \@_, Str, Str, slurpy ArrayRef[Num] ); ...; } Type::Params has a few tricks up its sleeve to make sure performance doesn't suffer too much with the shortcut, but it's never going to be as fast as the two stage compile/execute. =begin trustme Dude, these functions are documented! =item compile =item validate =item Invocant =item multisig =end trustme =head1 COOKBOOK =head2 Positional Parameters sub nth_root { state $check = compile( Num, Num ); my ($x, $n) = $check->(@_); return $x ** (1 / $n); } =head2 Method Calls Type::Params exports an additional keyword C on request. This is a type constraint accepting blessed objects and also class names. use Types::Standard qw( ClassName Object Str Int ); use Type::Params qw( compile Invocant ); # a class method sub new_from_json { state $check = compile( ClassName, Str ); my ($class, $json) = $check->(@_); $class->new( from_json($json) ); } # an object method sub dump { state $check = compile( Object, Int ); my ($self, $limit) = $check->(@_); local $Data::Dumper::Maxdepth = $limit; print Data::Dumper::Dumper($self); } # can be called as either and object or class method sub run { state $check = compile( Invocant ); my ($proto) = $check->(@_); my $self = ref($proto) ? $proto : $default_instance; $self->_run; } =head2 Optional Parameters use Types::Standard qw( Object Optional Int ); sub dump { state $check = compile( Object, Optional[Int] ); my ($self, $limit) = $check->(@_); $limit //= 0; local $Data::Dumper::Maxdepth = $limit; print Data::Dumper::Dumper($self); } $obj->dump(1); # ok $obj->dump(); # ok $obj->dump(undef); # dies =head2 Slurpy Parameters use Types::Standard qw( slurpy ClassName HashRef ); sub new { state $check = compile( ClassName, slurpy HashRef ); my ($class, $ref) = $check->(@_); bless $ref => $class; } __PACKAGE__->new(foo => 1, bar => 2); The following types from L can be made slurpy: C, C, C, C, C. Hash-like types will die if an odd number of elements are slurped in. A check may only have one slurpy parameter, and it must be the last parameter. =head2 Named Parameters Just use a slurpy C: use Types::Standard qw( slurpy Dict Ref Optional Int ); sub dump { state $check = compile( slurpy Dict[ var => Ref, limit => Optional[Int], ], ); my ($arg) = $check->(@_); local $Data::Dumper::Maxdepth = $arg->{limit}; print Data::Dumper::Dumper($arg->{var}); } dump(var => $foo, limit => 1); # ok dump(var => $foo); # ok dump(limit => 1); # dies =head2 Mixed Positional and Named Parameters use Types::Standard qw( slurpy Dict Ref Optional Int ); sub my_print { state $check = compile( Str, slurpy Dict[ colour => Optional[Str], size => Optional[Int], ], ); my ($string, $arg) = $check->(@_); } my_print("Hello World", colour => "blue"); =head2 Coercions Coercions will automatically be applied for I type constraints that have a coercion associated. use Type::Utils; use Types::Standard qw( Int Num ); my $RoundedInt = declare as Int; coerce $RoundedInt, from Num, q{ int($_) }; sub set_age { state $check = compile( Object, $RoundedInt ); my ($self, $age) = $check->(@_); $self->{age} = $age; } $obj->set_age(32.5); # ok; coerced to "32". Coercions carry over into structured types such as C automatically: sub delete_articles { state $check = compile( Object, slurpy ArrayRef[$RoundedInt] ); my ($db, $articles) = $check->(@_); $db->select_article($_)->delete for @$articles; } # delete articles 1, 2 and 3 delete_articles($my_db, 1.1, 2.2, 3.3); If type C has coercions from C and C and you want to B coercion, then use: state $check = compile( Foo->no_coercions ); Or if you just want to prevent coercion from C, use: state $check = compile( Foo->minus_coercions(Str) ); Or maybe add an extra coercion: state $check = compile( Foo->plus_coercions(Int, q{ Foo->new_from_number($_) }), ); Note that the coercion is specified as a string of Perl code. This is usually the fastest way to do it, but a coderef is also accepted. Either way, the value to be coerced is C<< $_ >>. =head2 Alternatives Type::Params can export a C function that compiles multiple alternative signatures into one, and uses the first one that works: state $check = multisig( [ Int, ArrayRef ], [ HashRef, Num ], [ CodeRef ], ); my ($int, $arrayref) = $check->( 1, [] ); my ($hashref, $num) = $check->( {}, 1.1 ); my ($code) = $check->( sub { 1 } ); $check->( sub { 1 }, 1.1 ); # throws an exception Coercions, slurpy parameters, etc still work. There's currently no indication of which of the multiple signatures succeeded. The present implementation involves compiling each signature independently, and trying them each (in their given order!) in an C block. The only slightly intelligent part is that it checks if C<< scalar(@_) >> fits into the signature properly (taking into account optional and slurpy parameters), and skips evals which couldn't possibly succeed. It's also possible to list coderefs as alternatives in C: state $check = multisig( [ Int, ArrayRef ], sub { ... }, [ HashRef, Num ], [ CodeRef ], ); The coderef is expected to die if that alternative should be abandoned (and the next alternative tried), or return the list of accepted parameters. Here's a full example: sub get_from { state $check = multisig( [ Int, ArrayRef ], [ Str, HashRef ], sub { my ($meth, $obj); die unless is_Object($obj); die unless $obj->can($meth); return ($meth, $obj); }, ); my ($needle, $haystack) = $check->(@_); is_HashRef($haystack) ? $haystack->{$needle} : is_ArrayRef($haystack) ? $haystack->[$needle] : is_Object($haystack) ? $haystack->$needle : die; } get_from(0, \@array); # returns $array[0] get_from('foo', \%hash); # returns $hash{foo} get_from('foo', $obj); # returns $obj->foo =head1 COMPARISON WITH PARAMS::VALIDATE L is not really a drop-in replacement for L; the API differs far too much to claim that. Yet it performs a similar task, so it makes sense to compare them. =over =item * Type::Params will tend to be faster if you've got a sub which is called repeatedly, but may be a little slower than Params::Validate for subs that are only called a few times. This is because it does a bunch of work the first time your sub is called to make subsequent calls a lot faster. =item * Type::Params is mostly geared towards positional parameters, while Params::Validate seems to be primarily aimed at named parameters. (Though either works for either.) Params::Validate doesn't appear to have a particularly natural way of validating a mix of positional and named parameters. =item * Type::Utils allows you to coerce parameters. For example, if you expect a L object, you could coerce it from a string. =item * Params::Validate allows you to supply defaults for missing parameters; Type::Params does not, but you may be able to use coercion from Undef. =item * If you are primarily writing object-oriented code, using Moose or similar, and you are using Type::Tiny type constraints for your attributes, then using Type::Params allows you to use the same constraints for method calls. =item * Type::Params comes bundled with Types::Standard, which provides a much richer vocabulary of types than the type validation constants that come with Params::Validate. For example, Types::Standard provides constraints like C<< ArrayRef[Int] >> (an arrayref of integers), while the closest from Params::Validate is C<< ARRAYREF >>, which you'd need to supplement with additional callbacks if you wanted to check that the arrayref contained integers. Whatsmore, Type::Params doesn't just work with Types::Standard, but also any other Type::Tiny type constraints. =back =head1 BUGS Please report any bugs to L. =head1 SEE ALSO L, L, L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. Parser.pm000664001750001750 3220112422772210 15676 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Typepackage Type::Parser; use strict; use warnings; sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak } our $AUTHORITY = 'cpan:TOBYINK'; our $VERSION = '1.000005'; # Token types # sub TYPE () { "TYPE" }; sub QUOTELIKE () { "QUOTELIKE" }; sub STRING () { "STRING" }; sub CLASS () { "CLASS" }; sub L_BRACKET () { "L_BRACKET" }; sub R_BRACKET () { "R_BRACKET" }; sub COMMA () { "COMMA" }; sub SLURPY () { "SLURPY" }; sub UNION () { "UNION" }; sub INTERSECT () { "INTERSECT" }; sub NOT () { "NOT" }; sub L_PAREN () { "L_PAREN" }; sub R_PAREN () { "R_PAREN" }; sub MYSTERY () { "MYSTERY" }; our @EXPORT_OK = qw( eval_type _std_eval parse extract_type ); require Exporter::Tiny; our @ISA = 'Exporter::Tiny'; Evaluate: { sub parse { my $str = $_[0]; my $parser = "Type::Parser::AstBuilder"->new(input => $str); $parser->build; wantarray ? ($parser->ast, $parser->remainder) : $parser->ast; } sub extract_type { my ($str, $reg) = @_; my ($parsed, $tail) = parse($str); wantarray ? (_eval_type($parsed, $reg), $tail) : _eval_type($parsed, $reg); } sub eval_type { my ($str, $reg) = @_; my ($parsed, $tail) = parse($str); _croak("Unexpected tail on type expression: $tail") if $tail =~ /\S/sm; return _eval_type($parsed, $reg); } my $std; sub _std_eval { require Type::Registry; unless ($std) { $std = "Type::Registry"->new; $std->add_types(-Standard); } eval_type($_[0], $std); } sub _eval_type { my ($node, $reg) = @_; $node = _simplify_expression($node); if ($node->{type} eq "list") { return map _eval_type($_, $reg), @{$node->{list}}; } if ($node->{type} eq "union") { return $reg->make_union( map _eval_type($_, $reg), @{$node->{union}} ); } if ($node->{type} eq "intersect") { return $reg->make_intersection( map _eval_type($_, $reg), @{$node->{intersect}} ); } if ($node->{type} eq "slurpy") { return +{ slurpy => _eval_type($node->{of}, $reg) }; } if ($node->{type} eq "complement") { return _eval_type($node->{of}, $reg)->complementary_type; } if ($node->{type} eq "parameterized") { my $base = _eval_type($node->{base}, $reg); return $base unless $base->is_parameterizable || $node->{params}; return $base->parameterize($node->{params} ? _eval_type($node->{params}, $reg) : ()); } if ($node->{type} eq "primary" and $node->{token}->type eq CLASS) { my $class = substr( $node->{token}->spelling, 0, length($node->{token}->spelling) - 2 ); return $reg->make_class_type($class); } if ($node->{type} eq "primary" and $node->{token}->type eq QUOTELIKE) { return eval($node->{token}->spelling); #ARGH } if ($node->{type} eq "primary" and $node->{token}->type eq STRING) { return $node->{token}->spelling; } if ($node->{type} eq "primary" and $node->{token}->type eq TYPE) { my $t = $node->{token}->spelling; my $r = ($t =~ /^(.+)::(\w+)$/) ? $reg->foreign_lookup($t, 1) : $reg->simple_lookup($t, 1); $r or _croak("%s is not a known type constraint", $node->{token}->spelling); return $r; } } sub _simplify_expression { my $expr = shift; if ($expr->{type} eq "expression" and $expr->{op}[0] eq COMMA) { return _simplify("list", COMMA, $expr); } if ($expr->{type} eq "expression" and $expr->{op}[0] eq UNION) { return _simplify("union", UNION, $expr); } if ($expr->{type} eq "expression" and $expr->{op}[0] eq INTERSECT) { return _simplify("intersect", INTERSECT, $expr); } return $expr; } sub _simplify { my $type = shift; my $op = shift; my @list; for my $expr ($_[0]{lhs}, $_[0]{rhs}) { if ($expr->{type} eq "expression" and $expr->{op}[0] eq $op) { my $simple = _simplify($type, $op, $expr); push @list, @{ $simple->{$type} }; } else { push @list, $expr; } } return { type => $type, $type => \@list }; } } { package # hide from CPAN Type::Parser::AstBuilder; sub new { my $class = shift; bless { @_ }, $class; } our %precedence = ( # Type::Parser::COMMA() , 1 , Type::Parser::UNION() , 2 , Type::Parser::INTERSECT() , 3 , Type::Parser::NOT() , 4 , ); sub _parse_primary { my $self = shift; my $tokens = $self->{tokens}; $tokens->assert_not_empty; if ($tokens->peek(0)->type eq Type::Parser::NOT) { $tokens->eat(Type::Parser::NOT); $tokens->assert_not_empty; return { type => "complement", of => $self->_parse_primary, }; } if ($tokens->peek(0)->type eq Type::Parser::SLURPY) { $tokens->eat(Type::Parser::SLURPY); $tokens->assert_not_empty; return { type => "slurpy", of => $self->_parse_primary, }; } if ($tokens->peek(0)->type eq Type::Parser::L_PAREN) { $tokens->eat(Type::Parser::L_PAREN); my $r = $self->_parse_expression; $tokens->eat(Type::Parser::R_PAREN); return $r; } if ($tokens->peek(1) and $tokens->peek(0)->type eq Type::Parser::TYPE and $tokens->peek(1)->type eq Type::Parser::L_BRACKET) { my $base = { type => "primary", token => $tokens->eat(Type::Parser::TYPE) }; $tokens->eat(Type::Parser::L_BRACKET); $tokens->assert_not_empty; local $precedence{ Type::Parser::COMMA() } = 1; my $params = undef; if ($tokens->peek(0)->type eq Type::Parser::R_BRACKET) { $tokens->eat(Type::Parser::R_BRACKET); } else { $params = $self->_parse_expression; $params = { type => "list", list => [$params] } unless $params->{type} eq "list"; $tokens->eat(Type::Parser::R_BRACKET); } return { type => "parameterized", base => $base, params => $params, }; } my $type = $tokens->peek(0)->type; if ($type eq Type::Parser::TYPE or $type eq Type::Parser::QUOTELIKE or $type eq Type::Parser::STRING or $type eq Type::Parser::CLASS) { return { type => "primary", token => $tokens->eat }; } Type::Parser::_croak("Unexpected token in primary type expression; got '%s'", $tokens->peek(0)->spelling); } sub _parse_expression_1 { my $self = shift; my $tokens = $self->{tokens}; my ($lhs, $min_p) = @_; while (!$tokens->empty and defined($precedence{$tokens->peek(0)->type}) and $precedence{$tokens->peek(0)->type} >= $min_p) { my $op = $tokens->eat; my $rhs = $self->_parse_primary; while (!$tokens->empty and defined($precedence{$tokens->peek(0)->type}) and $precedence{$tokens->peek(0)->type} > $precedence{$op->type}) { my $lookahead = $tokens->peek(0); $rhs = $self->_parse_expression_1($rhs, $precedence{$lookahead->type}); } $lhs = { type => "expression", op => $op, lhs => $lhs, rhs => $rhs, }; } return $lhs; } sub _parse_expression { my $self = shift; my $tokens = $self->{tokens}; return $self->_parse_expression_1($self->_parse_primary, 0); } sub build { my $self = shift; $self->{tokens} = "Type::Parser::TokenStream"->new(remaining => $self->{input}); $self->{ast} = $self->_parse_expression; } sub ast { $_[0]{ast}; } sub remainder { $_[0]{tokens}->remainder; } } { package # hide from CPAN Type::Parser::Token; sub type { $_[0][0] } sub spelling { $_[0][1] } } { package # hide from CPAN Type::Parser::TokenStream; use Scalar::Util qw(looks_like_number); use Text::Balanced qw(extract_quotelike); sub new { my $class = shift; bless { stack => [], done => [], @_ }, $class; } sub peek { my $self = shift; my $ahead = $_[0]; while ($self->_stack_size <= $ahead and length $self->{remaining}) { $self->_stack_extend; } my @tokens = grep ref, @{ $self->{stack} }; return $tokens[$ahead]; } sub empty { my $self = shift; not $self->peek(0); } sub eat { my $self = shift; $self->_stack_extend unless $self->_stack_size; my $r; while (defined(my $item = shift @{$self->{stack}})) { push @{ $self->{done} }, $item; if (ref $item) { $r = $item; last; } } if (@_ and $_[0] ne $r->type) { unshift @{$self->{stack}}, pop @{$self->{done}}; Type::Parser::_croak("Expected $_[0]; got ".$r->type); } return $r; } sub assert_not_empty { my $self = shift; Type::Parser::_croak("Expected token; got empty string") if $self->empty; } sub _stack_size { my $self = shift; scalar grep ref, @{ $self->{stack} }; } sub _stack_extend { my $self = shift; push @{ $self->{stack} }, $self->_read_token; my ($space) = ($self->{remaining} =~ m/^([\s\n\r]*)/sm); return unless length $space; push @{ $self->{stack} }, $space; substr($self->{remaining}, 0, length $space) = ""; } sub remainder { my $self = shift; return join "", map { ref($_) ? $_->spelling : $_ } (@{$self->{stack}}, $self->{remaining}) } my %punctuation = ( '[' => bless([ Type::Parser::L_BRACKET, "[" ], "Type::Parser::Token"), ']' => bless([ Type::Parser::R_BRACKET, "]" ], "Type::Parser::Token"), '(' => bless([ Type::Parser::L_PAREN, "[" ], "Type::Parser::Token"), ')' => bless([ Type::Parser::R_PAREN, "]" ], "Type::Parser::Token"), ',' => bless([ Type::Parser::COMMA, "," ], "Type::Parser::Token"), '=>' => bless([ Type::Parser::COMMA, "=>" ], "Type::Parser::Token"), 'slurpy' => bless([ Type::Parser::SLURPY, "slurpy" ], "Type::Parser::Token"), '|' => bless([ Type::Parser::UNION, "|" ], "Type::Parser::Token"), '&' => bless([ Type::Parser::INTERSECT, "&" ], "Type::Parser::Token"), '~' => bless([ Type::Parser::NOT, "~" ], "Type::Parser::Token"), ); sub _read_token { my $self = shift; return if $self->{remaining} eq ""; # Punctuation # if ($self->{remaining} =~ /^( => | [()\]\[|&~,] )/xsm) { my $spelling = $1; substr($self->{remaining}, 0, length $spelling) = ""; return $punctuation{$spelling}; } if (my $quotelike = extract_quotelike $self->{remaining}) { return bless([ Type::Parser::QUOTELIKE, $quotelike ], "Type::Parser::Token"),; } if ($self->{remaining} =~ /^([+-]?[\w:.+]+)/sm) { my $spelling = $1; substr($self->{remaining}, 0, length $spelling) = ""; if ($spelling =~ /::$/sm) { return bless([ Type::Parser::CLASS, $spelling ], "Type::Parser::Token"),; } elsif (looks_like_number($spelling)) { return bless([ Type::Parser::STRING, $spelling ], "Type::Parser::Token"),; } elsif ($self->{remaining} =~ /^\s*=>/sm) # peek ahead { return bless([ Type::Parser::STRING, $spelling ], "Type::Parser::Token"),; } elsif ($spelling eq "slurpy") { return $punctuation{$spelling}; } return bless([ Type::Parser::TYPE, $spelling ], "Type::Parser::Token"); } my $rest = $self->{remaining}; $self->{remaining} = ""; return bless([ Type::Parser::MYSTERY, $rest ], "Type::Parser::Token"); } } 1; __END__ =pod =encoding utf-8 =for stopwords non-whitespace =head1 NAME Type::Parser - parse type constraint strings =head1 SYNOPSIS use v5.10; use strict; use warnings; use Type::Parser qw( eval_type ); use Type::Registry; my $reg = Type::Registry->for_me; $reg->add_types("Types::Standard"); my $type = eval_type("Int | ArrayRef[Int]", $reg); $type->check(10); # true $type->check([1..4]); # true $type->check({foo=>1}); # false =head1 STATUS This module is covered by the L. =head1 DESCRIPTION Generally speaking, you probably don't want to be using this module directly. Instead use the C<< lookup >> method from L which wraps it. =head2 Functions =over =item C<< parse($string) >> Parse the type constraint string into something like an AST. If called in list context, also returns any "tail" found on the original string. =item C<< extract_type($string, $registry) >> Compile a type constraint string into a L object. If called in list context, also returns any "tail" found on the original string. =item C<< eval_type($string, $registry) >> Compile a type constraint string into a L object. Throws an error if the "tail" contains any non-whitespace character. =back =head2 Constants The following constants correspond to values returned by C<< $token->type >>. =over =item C<< TYPE >> =item C<< QUOTELIKE >> =item C<< STRING >> =item C<< CLASS >> =item C<< L_BRACKET >> =item C<< R_BRACKET >> =item C<< COMMA >> =item C<< SLURPY >> =item C<< UNION >> =item C<< INTERSECT >> =item C<< NOT >> =item C<< L_PAREN >> =item C<< R_PAREN >> =item C<< MYSTERY >> =back =head1 BUGS Please report any bugs to L. =head1 SEE ALSO L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. Registry.pm000664001750001750 2550512422772210 16263 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Typepackage Type::Registry; use 5.006001; use strict; use warnings; BEGIN { $Type::Registry::AUTHORITY = 'cpan:TOBYINK'; $Type::Registry::VERSION = '1.000005'; } use Exporter::Tiny qw( mkopt ); use Scalar::Util qw( refaddr ); use Type::Parser qw( eval_type ); use Types::TypeTiny qw( CodeLike ArrayLike to_TypeTiny ); our @ISA = 'Exporter::Tiny'; our @EXPORT_OK = qw(t); sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak } sub _exporter_expand_sub { my $class = shift; my ($name, $value, $globals, $permitted) = @_; if ($name eq "t") { my $caller = $globals->{into}; my $reg = $class->for_class( ref($caller) ? sprintf('HASH(0x%08X)', refaddr($caller)) : $caller ); return t => sub (;$) { @_ ? $reg->lookup(@_) : $reg }; } return $class->SUPER::_exporter_expand_sub(@_); } sub new { my $class = shift; ref($class) and _croak("Not an object method"); bless {}, $class; } { my %registries; sub for_class { my $class = shift; my ($for) = @_; $registries{$for} ||= $class->new; } sub for_me { my $class = shift; my $for = caller; $registries{$for} ||= $class->new; } } sub add_types { my $self = shift; my $opts = mkopt(\@_); for my $opt (@$opts) { my ($lib, $types) = @_; $lib =~ s/^-/Types::/; eval "require $lib"; my %hash; if ($lib->isa("Type::Library") or $lib eq 'Types::TypeTiny') { $types ||= [qw/-types/]; ArrayLike->check($types) or _croak("Expected arrayref following '%s'; got %s", $lib, $types); $lib->import({into => \%hash}, @$types); $hash{$_} = &{$hash{$_}}() for keys %hash; } elsif ($lib->isa("MooseX::Types::Base")) { $types ||= []; ArrayLike->check($types) && (@$types == 0) or _croak("Library '%s' is a MooseX::Types type constraint library. No import options currently supported", $lib); require Moose::Util::TypeConstraints; my $moosextypes = $lib->type_storage; for my $name (sort keys %$moosextypes) { my $tt = to_TypeTiny( Moose::Util::TypeConstraints::find_type_constraint($moosextypes->{$name}) ); $hash{$name} = $tt; } } elsif ($lib->isa("MouseX::Types::Base")) { $types ||= []; ArrayLike->check($types) && (@$types == 0) or _croak("Library '%s' is a MouseX::Types type constraint library. No import options currently supported", $lib); require Mouse::Util::TypeConstraints; my $moosextypes = $lib->type_storage; for my $name (sort keys %$moosextypes) { my $tt = to_TypeTiny( Mouse::Util::TypeConstraints::find_type_constraint($moosextypes->{$name}) ); $hash{$name} = $tt; } } else { _croak("%s is not a type library", $lib); } for my $key (sort keys %hash) { exists($self->{$key}) and $self->{$key}{uniq} != $hash{$key}{uniq} and _croak("Duplicate type name: %s", $key); $self->{$key} = $hash{$key}; } } $self; } sub add_type { my $self = shift; my ($type, $name) = @_; $type = to_TypeTiny($type); $name ||= do { $type->is_anon and _croak("Expected named type constraint; got anonymous type constraint"); $type->name; }; exists($self->{$name}) and $self->{$name}{uniq} != $type->{uniq} and _croak("Duplicate type name: %s", $name); $self->{$name} = $type; $self; } sub alias_type { my $self = shift; my ($old, @new) = @_; my $lookup = eval { $self->lookup($old) } or _croak("Expected existing type constraint name; got '$old'"); $self->{$_} = $lookup for @new; $self; } sub simple_lookup { my $self = shift; my ($tc) = @_; $tc =~ s/(^\s+|\s+$)//g; if (exists $self->{$tc}) { return $self->{$tc}; } return; } sub foreign_lookup { my $self = shift; return $_[1] ? () : $self->simple_lookup($_[0], 1) unless $_[0] =~ /^(.+)::(\w+)$/; my $library = $1; my $typename = $2; eval "require $library;"; if ( $library->isa('MooseX::Types::Base') ) { require Moose::Util::TypeConstraints; my $type = Moose::Util::TypeConstraints::find_type_constraint( $library->get_type($typename) ) or return; return to_TypeTiny($type); } if ( $library->isa('MouseX::Types::Base') ) { require Mouse::Util::TypeConstraints; my $sub = $library->can($typename) or return; my $type = Mouse::Util::TypeConstraints::find_type_constraint($sub->()) or return; return to_TypeTiny($type); } if ( $library->can("get_type") ) { my $type = $library->get_type($typename); return to_TypeTiny($type); } return; } sub lookup { my $self = shift; $self->simple_lookup(@_) or eval_type($_[0], $self); } sub make_union { my $self = shift; my (@types) = @_; require Type::Tiny::Union; return "Type::Tiny::Union"->new(type_constraints => \@types); } sub make_intersection { my $self = shift; my (@types) = @_; require Type::Tiny::Intersection; return "Type::Tiny::Intersection"->new(type_constraints => \@types); } sub make_class_type { my $self = shift; my ($class) = @_; require Type::Tiny::Class; return "Type::Tiny::Class"->new(class => $class); } sub make_role_type { my $self = shift; my ($role) = @_; require Type::Tiny::Role; return "Type::Tiny::Role"->new(role => $role); } sub AUTOLOAD { my $self = shift; my ($method) = (our $AUTOLOAD =~ /(\w+)$/); my $type = $self->simple_lookup($method); return $type if $type; _croak(q[Can't locate object method "%s" via package "%s"], $method, ref($self)); } # Prevent AUTOLOAD being called for DESTROY! sub DESTROY { return; } DELAYED: { our %DELAYED; for my $package (sort keys %DELAYED) { my $reg = __PACKAGE__->for_class($package); my $types = $DELAYED{$package}; for my $name (sort keys %$types) { $reg->add_type($types->{$name}, $name); } } } 1; __END__ =pod =encoding utf-8 =for stopwords optlist =head1 NAME Type::Registry - a glorified hashref for looking up type constraints =head1 SYNOPSIS =for test_synopsis no warnings qw(misc); package Foo::Bar; use Type::Registry; my $reg = "Type::Registry"->for_me; # a registry for Foo::Bar # Register all types from Types::Standard $reg->add_types(-Standard); # Register just one type from Types::XSD $reg->add_types(-XSD => ["NonNegativeInteger"]); # Register all types from MyApp::Types $reg->add_types("MyApp::Types"); # Create a type alias $reg->alias_type("NonNegativeInteger" => "Count"); # Look up a type constraint my $type = $reg->lookup("ArrayRef[Count]"); $type->check([1, 2, 3.14159]); # croaks Alternatively: package Foo::Bar; use Type::Registry qw( t ); # Register all types from Types::Standard t->add_types(-Standard); # Register just one type from Types::XSD t->add_types(-XSD => ["NonNegativeInteger"]); # Register all types from MyApp::Types t->add_types("MyApp::Types"); # Create a type alias t->alias_type("NonNegativeInteger" => "Count"); # Look up a type constraint my $type = t("ArrayRef[Count]"); $type->check([1, 2, 3.14159]); # croaks =head1 STATUS This module is covered by the L. =head1 DESCRIPTION A type registry is basically just a hashref mapping type names to type constraint objects. =head2 Constructors =over =item C<< new >> Create a new glorified hashref. =item C<< for_class($class) >> Create or return the existing glorified hashref associated with the given class. Note that any type constraint you have imported from Type::Library-based type libraries will be automatically available in your class' registry. =item C<< for_me >> Create or return the existing glorified hashref associated with the caller. =back =head2 Methods =over =item C<< add_types(@libraries) >> The libraries list is treated as an "optlist" (a la L). Strings are the names of type libraries; if the first character is a hyphen, it is expanded to the "Types::" prefix. If followed by an arrayref, this is the list of types to import from that library. Otherwise, imports all types from the library. use Type::Registry qw(t); t->add_types(-Standard); # OR: t->add_types("Types::Standard"); t->add_types( -TypeTiny => ['HashLike'], -Standard => ['HashRef' => { -as => 'RealHash' }], ); L (and experimentally, L) libraries can also be added this way, but I<< cannot be followed by an arrayref of types to import >>. =item C<< add_type($type, $name) >> The long-awaited singular form of C. Given a type constraint object, adds it to the registry with a given name. The name may be omitted, in which case C<< $type->name >> is called, and Type::Registry will throw an error if C<< $type >> is anonymous. If a name is explicitly given, Type::Registry cares not one wit whether the type constraint is anonymous. This method can even add L and L type constraints; indeed anything that can be handled by L's C function. (Bear in mind that to_TypeTiny I results in an anonymous type constraint, so C<< $name >> will be required.) =item C<< alias_type($oldname, $newname) >> Create an alias for an existing type. =item C<< simple_lookup($name) >> Look up a type in the registry by name. Returns undef if not found. =item C<< foreign_lookup($name) >> Like C, but if the type name contains "::", will attempt to load it from a type library. (And will attempt to load that module.) =item C<< lookup($name) >> Look up by name, with a DSL. t->lookup("Int|ArrayRef[Int]") The DSL can be summed up as: X type from this registry My::Lib::X type from a type library ~X complementary type X | Y union X & Y intersection X[...] parameterized type slurpy X slurpy type Foo::Bar:: class type Croaks if not found. =item C<< make_union(@constraints) >>, C<< make_intersection(@constraints) >>, C<< make_class_type($class) >>, C<< make_role_type($role) >> Convenience methods for creating certain common type constraints. =item C<< AUTOLOAD >> Overloaded to call C. $registry->Str; # like $registry->lookup("Str") =back =head2 Functions =over =item C<< t >> This class can export a function C<< t >> which acts like C<< "Type::Registry"->for_class($importing_class) >>. =back =head1 BUGS Please report any bugs to L. =head1 SEE ALSO L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. Tiny.pm000664001750001750 13266712422772210 15426 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Typepackage Type::Tiny; use 5.006001; use strict; use warnings; BEGIN { if ($] < 5.008) { require Devel::TypeTiny::Perl56Compat }; } BEGIN { $Type::Tiny::AUTHORITY = 'cpan:TOBYINK'; $Type::Tiny::VERSION = '1.000005'; $Type::Tiny::XS_VERSION = '0.010'; } use Eval::TypeTiny (); use Scalar::Util qw( blessed weaken refaddr isweak ); use Types::TypeTiny (); sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak } sub _swap { $_[2] ? @_[1,0] : @_[0,1] } BEGIN { ($] < 5.010001) ? eval q{ sub SUPPORT_SMARTMATCH () { !!0 } } : eval q{ sub SUPPORT_SMARTMATCH () { !!1 } }; ($] >= 5.014) ? eval q{ sub _FIXED_PRECEDENCE () { !!1 } } : eval q{ sub _FIXED_PRECEDENCE () { !!0 } }; }; BEGIN { my $try_xs = exists($ENV{PERL_TYPE_TINY_XS}) ? !!$ENV{PERL_TYPE_TINY_XS} : exists($ENV{PERL_ONLY}) ? !$ENV{PERL_ONLY} : 1; my $use_xs = 0; $try_xs and eval { require Type::Tiny::XS; 'Type::Tiny::XS'->VERSION($Type::Tiny::XS_VERSION); $use_xs++; }; *_USE_XS = $use_xs ? sub () { !!1 } : sub () { !!0 }; *_USE_MOUSE = $try_xs ? sub () { $INC{'Mouse/Util.pm'} and Mouse::Util::MOUSE_XS() } : sub () { !!0 }; }; use overload q("") => sub { caller =~ m{^(Moo::HandleMoose|Sub::Quote)} ? overload::StrVal($_[0]) : $_[0]->display_name }, q(bool) => sub { 1 }, q(&{}) => "_overload_coderef", q(|) => sub { my @tc = _swap @_; if (!_FIXED_PRECEDENCE && !blessed $tc[0] && ref $tc[0] eq 'ARRAY') { require Type::Tiny::_HalfOp; return "Type::Tiny::_HalfOp"->new('|', @tc); } require Type::Tiny::Union; "Type::Tiny::Union"->new(type_constraints => \@tc) }, q(&) => sub { my @tc = _swap @_; if (!_FIXED_PRECEDENCE && !blessed $tc[0] && ref $tc[0] eq 'ARRAY') { require Type::Tiny::_HalfOp; return "Type::Tiny::_HalfOp"->new('&', @tc); } require Type::Tiny::Intersection; "Type::Tiny::Intersection"->new(type_constraints => \@tc) }, q(~) => sub { shift->complementary_type }, q(==) => sub { $_[0]->equals($_[1]) }, q(<) => sub { my $m = $_[0]->can('is_subtype_of'); $m->(_swap @_) }, q(>) => sub { my $m = $_[0]->can('is_subtype_of'); $m->(reverse _swap @_) }, q(<=) => sub { my $m = $_[0]->can('is_a_type_of'); $m->(_swap @_) }, q(>=) => sub { my $m = $_[0]->can('is_a_type_of'); $m->(reverse _swap @_) }, q(eq) => sub { "$_[0]" eq "$_[1]" }, q(cmp) => sub { $_[2] ? ("$_[1]" cmp "$_[0]") : ("$_[0]" cmp "$_[1]") }, fallback => 1, ; BEGIN { overload->import( q(~~) => sub { $_[0]->check($_[1]) }, fallback => 1, # 5.10 loses the fallback otherwise ) if Type::Tiny::SUPPORT_SMARTMATCH; } sub _overload_coderef { my $self = shift; $self->message unless exists $self->{message}; # if ($self->has_parent && $self->_is_null_constraint) # { # $self->{_overload_coderef} ||= $self->parent->_overload_coderef; # } # els if (!exists($self->{message}) && exists(&Sub::Quote::quote_sub) && $self->can_be_inlined) { $self->{_overload_coderef} = Sub::Quote::quote_sub($self->inline_assert('$_[0]')) if !$self->{_overload_coderef} || !$self->{_sub_quoted}++; } else { $self->{_overload_coderef} ||= sub { $self->assert_return(@_) }; } $self->{_overload_coderef}; } our %ALL_TYPES; my $QFS; my $uniq = 1; sub new { my $class = shift; my %params = (@_==1) ? %{$_[0]} : @_; if (exists $params{parent}) { $params{parent} = ref($params{parent}) =~ /^Type::Tiny\b/ ? $params{parent} : Types::TypeTiny::to_TypeTiny($params{parent}); _croak "Parent must be an instance of %s", __PACKAGE__ unless blessed($params{parent}) && $params{parent}->isa(__PACKAGE__); } $params{name} = "__ANON__" unless exists $params{name}; $params{uniq} = $uniq++; if ($params{name} ne "__ANON__") { # First try a fast ASCII-only expression, but fall back to Unicode $params{name} =~ /^_{0,2}[A-Z][A-Za-z0-9_]+$/sm or eval q( use 5.008; $params{name} =~ /^_{0,2}\p{Lu}[\p{L}0-9_]+$/sm ) or _croak '"%s" is not a valid type name', $params{name}; } if (exists $params{coercion} and !ref $params{coercion} and $params{coercion}) { $params{parent}->has_coercion or _croak "coercion => 1 requires type to have a direct parent with a coercion"; $params{coercion} = $params{parent}->coercion->type_coercion_map; } if (!exists $params{inlined} and exists $params{constraint} and ( !exists $params{parent} or $params{parent}->can_be_inlined ) and $QFS ||= "Sub::Quote"->can("quoted_from_sub")) { my (undef, $perlstring, $captures) = @{ $QFS->($params{constraint}) || [] }; $params{inlined} = sub { my ($self, $var) = @_; my $code = Sub::Quote::inlinify( $perlstring, $var, $var eq q($_) ? '' : "local \$_ = $var;", 1, ); $code = sprintf('%s and %s', $self->parent->inline_check($var), $code) if $self->has_parent; return $code; } if $perlstring && !$captures; } my $self = bless \%params, $class; unless ($params{tmp}) { my $uniq = $self->{uniq}; $ALL_TYPES{$uniq} = $self; weaken( $ALL_TYPES{$uniq} ); package # no index Moo::HandleMoose; my $tmp = $self; Scalar::Util::weaken($tmp); $Moo::HandleMoose::TYPE_MAP{$self} = sub { $tmp }; } if (ref($params{coercion}) eq q(CODE)) { require Types::Standard; my $code = delete($params{coercion}); $self->{coercion} = $self->_build_coercion; $self->coercion->add_type_coercions(Types::Standard::Any(), $code); } elsif (ref($params{coercion}) eq q(ARRAY)) { my $arr = delete($params{coercion}); $self->{coercion} = $self->_build_coercion; $self->coercion->add_type_coercions(@$arr); } if ($params{my_methods} and eval { require Sub::Name }) { for my $key (keys %{$params{my_methods}}) { Sub::Name::subname( sprintf("%s::my_%s", $self->qualified_name, $key), $params{my_methods}{$key}, ); } } return $self; } sub DESTROY { my $self = shift; delete( $ALL_TYPES{$self->{uniq}} ); package # no index Moo::HandleMoose; delete( $Moo::HandleMoose::TYPE_MAP{$self} ); return; } sub _clone { my $self = shift; my %opts; $opts{$_} = $self->{$_} for qw< name display_name message >; $self->create_child_type(%opts); } our $DD; sub _dd { @_ = $_ unless @_; my ($value) = @_; goto $DD if ref($DD) eq q(CODE); require B; !defined $value ? 'Undef' : !ref $value ? sprintf('Value %s', B::perlstring($value)) : do { my $N = 0 + (defined($DD) ? $DD : 72); require Data::Dumper; local $Data::Dumper::Indent = 0; local $Data::Dumper::Useqq = 1; local $Data::Dumper::Terse = 1; local $Data::Dumper::Sortkeys = 1; local $Data::Dumper::Maxdepth = 2; my $str = Data::Dumper::Dumper($value); $str = substr($str, 0, $N - 12).'...'.substr($str, -1, 1) if length($str) >= $N; "Reference $str"; } } sub _loose_to_TypeTiny { map +( ref($_) ? Types::TypeTiny::to_TypeTiny($_) : do { require Type::Utils; Type::Utils::dwim_type($_) } ), @_; } sub name { $_[0]{name} } sub display_name { $_[0]{display_name} ||= $_[0]->_build_display_name } sub parent { $_[0]{parent} } sub constraint { $_[0]{constraint} ||= $_[0]->_build_constraint } sub compiled_check { $_[0]{compiled_type_constraint} ||= $_[0]->_build_compiled_check } sub coercion { $_[0]{coercion} ||= $_[0]->_build_coercion } sub message { $_[0]{message} } sub library { $_[0]{library} } sub inlined { $_[0]{inlined} } sub constraint_generator { $_[0]{constraint_generator} } sub inline_generator { $_[0]{inline_generator} } sub name_generator { $_[0]{name_generator} ||= $_[0]->_build_name_generator } sub coercion_generator { $_[0]{coercion_generator} } sub parameters { $_[0]{parameters} } sub moose_type { $_[0]{moose_type} ||= $_[0]->_build_moose_type } sub mouse_type { $_[0]{mouse_type} ||= $_[0]->_build_mouse_type } sub deep_explanation { $_[0]{deep_explanation} } sub my_methods { $_[0]{my_methods} ||= $_[0]->_build_my_methods } sub has_parent { exists $_[0]{parent} } sub has_library { exists $_[0]{library} } sub has_coercion { $_[0]{coercion} and !!@{ $_[0]{coercion}->type_coercion_map } } sub has_inlined { exists $_[0]{inlined} } sub has_constraint_generator { exists $_[0]{constraint_generator} } sub has_inline_generator { exists $_[0]{inline_generator} } sub has_coercion_generator { exists $_[0]{coercion_generator} } sub has_parameters { exists $_[0]{parameters} } sub has_message { defined $_[0]{message} } sub has_deep_explanation { exists $_[0]{deep_explanation} } sub _default_message { $_[0]{_default_message} ||= $_[0]->_build_default_message } sub _assert_coercion { my $self = shift; _croak "No coercion for this type constraint" unless $self->has_coercion && @{$self->coercion->type_coercion_map}; return $self->coercion; } my $null_constraint = sub { !!1 }; sub _build_display_name { shift->name; } sub _build_constraint { return $null_constraint; } sub _is_null_constraint { shift->constraint == $null_constraint; } sub _build_coercion { require Type::Coercion; my $self = shift; my %opts = (type_constraint => $self); $opts{display_name} = "to_$self" unless $self->is_anon; return "Type::Coercion"->new(%opts); } sub _build_default_message { my $self = shift; return sub { sprintf '%s did not pass type constraint', _dd($_[0]) } if "$self" eq "__ANON__"; my $name = "$self"; return sub { sprintf '%s did not pass type constraint "%s"', _dd($_[0]), $name }; } sub _build_name_generator { my $self = shift; return sub { my ($s, @a) = @_; sprintf('%s[%s]', $s, join q[,], @a); }; } sub _build_compiled_check { my $self = shift; if ($self->_is_null_constraint and $self->has_parent) { return $self->parent->compiled_check; } return Eval::TypeTiny::eval_closure( source => sprintf('sub ($) { %s }', $self->inline_check('$_[0]')), description => sprintf("compiled check '%s'", $self), ) if $self->can_be_inlined; my @constraints; push @constraints, $self->parent->compiled_check if $self->has_parent; push @constraints, $self->constraint if !$self->_is_null_constraint; return $null_constraint unless @constraints; return sub ($) { local $_ = $_[0]; for my $c (@constraints) { return unless $c->(@_); } return !!1; }; } sub equals { my ($self, $other) = _loose_to_TypeTiny(@_); return unless blessed($self) && $self->isa("Type::Tiny"); return unless blessed($other) && $other->isa("Type::Tiny"); return !!1 if refaddr($self) == refaddr($other); return !!1 if $self->has_parent && $self->_is_null_constraint && $self->parent==$other; return !!1 if $other->has_parent && $other->_is_null_constraint && $other->parent==$self; return !!1 if refaddr($self->compiled_check) == refaddr($other->compiled_check); return $self->qualified_name eq $other->qualified_name if $self->has_library && !$self->is_anon && $other->has_library && !$other->is_anon; return $self->inline_check('$x') eq $other->inline_check('$x') if $self->can_be_inlined && $other->can_be_inlined; return; } sub is_subtype_of { my ($self, $other) = _loose_to_TypeTiny(@_); return unless blessed($self) && $self->isa("Type::Tiny"); return unless blessed($other) && $other->isa("Type::Tiny"); # my $this = $self; # while (my $parent = $this->parent) # { # return !!1 if $parent->equals($other); # $this = $parent; # } # return; return unless $self->has_parent; $self->parent->equals($other) or $self->parent->is_subtype_of($other); } sub is_supertype_of { my ($self, $other) = _loose_to_TypeTiny(@_); return unless blessed($self) && $self->isa("Type::Tiny"); return unless blessed($other) && $other->isa("Type::Tiny"); $other->is_subtype_of($self); } sub is_a_type_of { my ($self, $other) = _loose_to_TypeTiny(@_); return unless blessed($self) && $self->isa("Type::Tiny"); return unless blessed($other) && $other->isa("Type::Tiny"); $self->equals($other) or $self->is_subtype_of($other); } sub strictly_equals { my ($self, $other) = _loose_to_TypeTiny(@_); return unless blessed($self) && $self->isa("Type::Tiny"); return unless blessed($other) && $other->isa("Type::Tiny"); $self->{uniq} == $other->{uniq}; } sub is_strictly_subtype_of { my ($self, $other) = _loose_to_TypeTiny(@_); return unless blessed($self) && $self->isa("Type::Tiny"); return unless blessed($other) && $other->isa("Type::Tiny"); # my $this = $self; # while (my $parent = $this->parent) # { # return !!1 if $parent->strictly_equals($other); # $this = $parent; # } # return; return unless $self->has_parent; $self->parent->strictly_equals($other) or $self->parent->is_strictly_subtype_of($other); } sub is_strictly_supertype_of { my ($self, $other) = _loose_to_TypeTiny(@_); return unless blessed($self) && $self->isa("Type::Tiny"); return unless blessed($other) && $other->isa("Type::Tiny"); $other->is_strictly_subtype_of($self); } sub is_strictly_a_type_of { my ($self, $other) = _loose_to_TypeTiny(@_); return unless blessed($self) && $self->isa("Type::Tiny"); return unless blessed($other) && $other->isa("Type::Tiny"); $self->strictly_equals($other) or $self->is_strictly_subtype_of($other); } sub qualified_name { my $self = shift; (exists $self->{library} and $self->name ne "__ANON__") ? "$self->{library}::$self->{name}" : $self->{name}; } sub is_anon { my $self = shift; $self->name eq "__ANON__"; } sub parents { my $self = shift; return unless $self->has_parent; return ($self->parent, $self->parent->parents); } sub find_parent { my $self = shift; my ($test) = @_; local ($_, $.); my $type = $self; my $count = 0; while ($type) { if ($test->($_=$type, $.=$count)) { return wantarray ? ($type, $count) : $type; } else { $type = $type->parent; $count++; } } return; } sub check { my $self = shift; ($self->{compiled_type_constraint} ||= $self->_build_compiled_check)->(@_); } sub _strict_check { my $self = shift; local $_ = $_[0]; my @constraints = reverse map { $_->constraint } grep { not $_->_is_null_constraint } ($self, $self->parents); for my $c (@constraints) { return unless $c->(@_); } return !!1; } sub get_message { my $self = shift; local $_ = $_[0]; $self->has_message ? $self->message->(@_) : $self->_default_message->(@_); } sub validate { my $self = shift; return undef if ($self->{compiled_type_constraint} ||= $self->_build_compiled_check)->(@_); local $_ = $_[0]; return $self->get_message(@_); } sub validate_explain { my $self = shift; my ($value, $varname) = @_; $varname = '$_' unless defined $varname; return undef if $self->check($value); if ($self->has_parent) { my $parent = $self->parent->validate_explain($value, $varname); return [ sprintf('"%s" is a subtype of "%s"', $self, $self->parent), @$parent ] if $parent; } my $message = sprintf( '%s%s', $self->get_message($value), $varname eq q{$_} ? '' : sprintf(' (in %s)', $varname), ); if ($self->is_parameterized and $self->parent->has_deep_explanation) { my $deep = $self->parent->deep_explanation->($self, $value, $varname); return [ $message, @$deep ] if $deep; } return [ $message, sprintf('"%s" is defined as: %s', $self, $self->_perlcode) ]; } my $b; sub _perlcode { my $self = shift; return $self->inline_check('$_') if $self->can_be_inlined; $b ||= do { require B::Deparse; my $tmp = "B::Deparse"->new; $tmp->ambient_pragmas(strict => "all", warnings => "all") if $tmp->can('ambient_pragmas'); $tmp; }; my $code = $b->coderef2text($self->constraint); $code =~ s/\s+/ /g; return "sub $code"; } sub assert_valid { my $self = shift; return !!1 if ($self->{compiled_type_constraint} ||= $self->_build_compiled_check)->(@_); local $_ = $_[0]; $self->_failed_check("$self", $_); } sub assert_return { my $self = shift; return $_[0] if ($self->{compiled_type_constraint} ||= $self->_build_compiled_check)->(@_); local $_ = $_[0]; $self->_failed_check("$self", $_); } sub can_be_inlined { my $self = shift; return $self->parent->can_be_inlined if $self->has_parent && $self->_is_null_constraint; return !!1 if !$self->has_parent && $self->_is_null_constraint; return $self->has_inlined; } sub inline_check { my $self = shift; _croak 'Cannot inline type constraint check for "%s"', $self unless $self->can_be_inlined; return $self->parent->inline_check(@_) if $self->has_parent && $self->_is_null_constraint; return '(!!1)' if !$self->has_parent && $self->_is_null_constraint; local $_ = $_[0]; my @r = $self->inlined->($self, @_); if (@r and not defined $r[0]) { _croak 'Inlining type constraint check for "%s" returned undef!', $self unless $self->has_parent; $r[0] = $self->parent->inline_check(@_); } my $r = join " && " => map { /[;{}]/ ? "do { $_ }" : "($_)" } @r; return @r==1 ? $r : "($r)"; } sub inline_assert { require B; my $self = shift; my $varname = $_[0]; my $code = sprintf( q[do { no warnings "void"; %s ? %s : Type::Tiny::_failed_check(%d, %s, %s) };], $self->inline_check(@_), $varname, $self->{uniq}, B::perlstring("$self"), $varname, ); return $code; } sub _failed_check { require Error::TypeTiny::Assertion; my ($self, $name, $value, %attrs) = @_; $self = $ALL_TYPES{$self} unless ref $self; my $exception_class = delete($attrs{exception_class}) || "Error::TypeTiny::Assertion"; if ($self) { $exception_class->throw( message => $self->get_message($value), type => $self, value => $value, %attrs, ); } else { $exception_class->throw( message => sprintf('%s did not pass type constraint "%s"', _dd($value), $name), value => $value, %attrs, ); } } sub coerce { my $self = shift; $self->_assert_coercion->coerce(@_); } sub assert_coerce { my $self = shift; $self->_assert_coercion->assert_coerce(@_); } sub is_parameterizable { shift->has_constraint_generator; } sub is_parameterized { shift->has_parameters; } my %param_cache; sub parameterize { my $self = shift; $self->is_parameterizable or @_ ? _croak("Type '%s' does not accept parameters", "$self") : return($self); @_ = map Types::TypeTiny::to_TypeTiny($_), @_; # Generate a key for caching parameterized type constraints, # but only if all the parameters are strings or type constraints. my $key; if ( not grep(ref($_) && !Types::TypeTiny::TypeTiny->check($_), @_) ) { require B; $key = join ":", map(Types::TypeTiny::TypeTiny->check($_) ? $_->{uniq} : B::perlstring($_), $self, @_); } return $param_cache{$key} if defined $key && defined $param_cache{$key}; local $Type::Tiny::parameterize_type = $self; local $_ = $_[0]; my $P; my ($constraint, $compiled) = $self->constraint_generator->(@_); if (Types::TypeTiny::TypeTiny->check($constraint)) { $P = $constraint; } else { my %options = ( constraint => $constraint, display_name => $self->name_generator->($self, @_), parameters => [@_], ); $options{compiled_type_constraint} = $compiled if $compiled; $options{inlined} = $self->inline_generator->(@_) if $self->has_inline_generator; exists $options{$_} && !defined $options{$_} && delete $options{$_} for keys %options; $P = $self->create_child_type(%options); my $coercion; $coercion = $self->coercion_generator->($self, $P, @_) if $self->has_coercion_generator; $P->coercion->add_type_coercions( @{$coercion->type_coercion_map} ) if $coercion; } if (defined $key) { $param_cache{$key} = $P; weaken($param_cache{$key}); } $P->coercion->freeze; return $P; } sub child_type_class { __PACKAGE__; } sub create_child_type { my $self = shift; return $self->child_type_class->new(parent => $self, @_); } sub complementary_type { my $self = shift; my $r = ($self->{complementary_type} ||= $self->_build_complementary_type); weaken($self->{complementary_type}) unless isweak($self->{complementary_type}); return $r; } sub _build_complementary_type { my $self = shift; my %opts = ( constraint => sub { not $self->check($_) }, display_name => sprintf("~%s", $self), ); $opts{display_name} =~ s/^\~{2}//; $opts{inlined} = sub { shift; "not(".$self->inline_check(@_).")" } if $self->can_be_inlined; return "Type::Tiny"->new(%opts); } sub _instantiate_moose_type { my $self = shift; my %opts = @_; require Moose::Meta::TypeConstraint; return "Moose::Meta::TypeConstraint"->new(%opts); } sub _build_moose_type { my $self = shift; my $r; if ($self->{_is_core}) { require Moose::Util::TypeConstraints; $r = Moose::Util::TypeConstraints::find_type_constraint($self->name); $r->{"Types::TypeTiny::to_TypeTiny"} = $self; Scalar::Util::weaken($r->{"Types::TypeTiny::to_TypeTiny"}); } else { my $wrapped_inlined = sub { shift; $self->inline_check(@_); }; my %opts; $opts{name} = $self->qualified_name if $self->has_library && !$self->is_anon; $opts{parent} = $self->parent->moose_type if $self->has_parent; $opts{constraint} = $self->constraint unless $self->_is_null_constraint; $opts{message} = $self->message if $self->has_message; $opts{inlined} = $wrapped_inlined if $self->has_inlined; $r = $self->_instantiate_moose_type(%opts); $r->{"Types::TypeTiny::to_TypeTiny"} = $self; $self->{moose_type} = $r; # prevent recursion $r->coercion($self->coercion->moose_coercion) if $self->has_coercion; } return $r; } sub _build_mouse_type { my $self = shift; my %options; $options{name} = $self->qualified_name if $self->has_library && !$self->is_anon; $options{parent} = $self->parent->mouse_type if $self->has_parent; $options{constraint} = $self->constraint unless $self->_is_null_constraint; $options{message} = $self->message if $self->has_message; require Mouse::Meta::TypeConstraint; my $r = "Mouse::Meta::TypeConstraint"->new(%options); $self->{mouse_type} = $r; # prevent recursion $r->_add_type_coercions( $self->coercion->freeze->_codelike_type_coercion_map('mouse_type') ) if $self->has_coercion; return $r; } sub _process_coercion_list { my $self = shift; my @pairs; while (@_) { my $next = shift; if (blessed($next) and $next->isa('Type::Coercion') and $next->is_parameterized) { push @pairs => ( @{ $next->_reparameterize($self)->type_coercion_map } ); } elsif (blessed($next) and $next->can('type_coercion_map')) { push @pairs => ( @{ $next->type_coercion_map }, ); } elsif (ref($next) eq q(ARRAY)) { unshift @_, @$next; } else { push @pairs => ( Types::TypeTiny::to_TypeTiny($next), shift, ); } } return @pairs; } sub plus_coercions { my $self = shift; my $new = $self->_clone; $new->coercion->add_type_coercions( $self->_process_coercion_list(@_), @{$self->coercion->type_coercion_map}, ); $new->coercion->freeze; return $new; } sub plus_fallback_coercions { my $self = shift; my $new = $self->_clone; $new->coercion->add_type_coercions( @{$self->coercion->type_coercion_map}, $self->_process_coercion_list(@_), ); $new->coercion->freeze; return $new; } sub minus_coercions { my $self = shift; my $new = $self->_clone; my @not = grep Types::TypeTiny::TypeTiny->check($_), $self->_process_coercion_list($new, @_); my @keep; my $c = $self->coercion->type_coercion_map; for (my $i = 0; $i <= $#$c; $i += 2) { my $keep_this = 1; NOT: for my $n (@not) { if ($c->[$i] == $n) { $keep_this = 0; last NOT; } } push @keep, $c->[$i], $c->[$i+1] if $keep_this; } $new->coercion->add_type_coercions(@keep); $new->coercion->freeze; return $new; } sub no_coercions { my $new = shift->_clone; $new->coercion->freeze; $new; } sub coercibles { my $self = shift; $self->has_coercion ? $self->coercion->_source_type_union : $self; } sub isa { my $self = shift; if ($INC{"Moose.pm"} and ref($self) and $_[0] =~ /^(?:Class::MOP|MooseX?::Meta)::(.+)$/) { my $meta = $1; return !!1 if $meta eq 'TypeConstraint'; return $self->is_parameterized if $meta eq 'TypeConstraint::Parameterized'; return $self->is_parameterizable if $meta eq 'TypeConstraint::Parameterizable'; return $self->isa('Type::Tiny::Union') if $meta eq 'TypeConstraint::Union'; my $inflate = $self->moose_type; return $inflate->isa(@_); } if ($INC{"Mouse.pm"} and ref($self) and $_[0] eq 'Mouse::Meta::TypeConstraint') { return !!1; } $self->SUPER::isa(@_); } sub _build_my_methods { return {}; } sub _lookup_my_method { my $self = shift; my ($name) = @_; if ($self->my_methods->{$name}) { return $self->my_methods->{$name}; } if ($self->has_parent) { return $self->parent->_lookup_my_method(@_); } return; } sub can { my $self = shift; return !!0 if $_[0] eq 'type_parameter' && blessed($_[0]) && $_[0]->has_parameters; my $can = $self->SUPER::can(@_); return $can if $can; if (ref($self)) { if ($INC{"Moose.pm"}) { my $method = $self->moose_type->can(@_); return sub { shift->moose_type->$method(@_) } if $method; } if ($_[0] =~ /\Amy_(.+)\z/) { my $method = $self->_lookup_my_method($1); return $method if $method; } } return; } sub AUTOLOAD { my $self = shift; my ($m) = (our $AUTOLOAD =~ /::(\w+)$/); return if $m eq 'DESTROY'; if (ref($self)) { if ($INC{"Moose.pm"}) { my $method = $self->moose_type->can($m); return $self->moose_type->$method(@_) if $method; } if ($m =~ /\Amy_(.+)\z/) { my $method = $self->_lookup_my_method($1); return $self->$method(@_) if $method; } } _croak q[Can't locate object method "%s" via package "%s"], $m, ref($self)||$self; } sub DOES { my $self = shift; return !!1 if ref($self) && $_[0] =~ m{^ Type::API::Constraint (?: ::Coercible | ::Inlinable )? $}x; return !!1 if !ref($self) && $_[0] eq 'Type::API::Constraint::Constructor'; "UNIVERSAL"->can("DOES") ? $self->SUPER::DOES(@_) : $self->isa(@_); } sub _has_xsub { require B; !!B::svref_2object( shift->compiled_check )->XSUB; } sub of { shift->parameterize(@_) } sub where { shift->create_child_type(constraint => @_) } # fill out Moose-compatible API sub inline_environment { +{} } sub _inline_check { shift->inline_check(@_) } sub _compiled_type_constraint { shift->compiled_check(@_) } sub meta { _croak("Not really a Moose::Meta::TypeConstraint. Sorry!") } sub compile_type_constraint { shift->compiled_check } sub _actually_compile_type_constraint { shift->_build_compiled_check } sub hand_optimized_type_constraint { shift->{hand_optimized_type_constraint} } sub has_hand_optimized_type_constraint { exists(shift->{hand_optimized_type_constraint}) } sub type_parameter { (shift->parameters || [])->[0] } # some stuff for Mouse-compatible API sub __is_parameterized { shift->is_parameterized(@_) } sub _add_type_coercions { shift->coercion->add_type_coercions(@_) }; sub _as_string { shift->qualified_name(@_) } sub _compiled_type_coercion { shift->coercion->compiled_coercion(@_) }; sub _identity { refaddr(shift) }; sub _unite { require Type::Tiny::Union; "Type::Tiny::Union"->new(type_constraints => \@_) }; # Hooks for Type::Tie sub TIESCALAR { require Type::Tie; unshift @_, 'Type::Tie::SCALAR'; goto \&Type::Tie::SCALAR::TIESCALAR }; sub TIEARRAY { require Type::Tie; unshift @_, 'Type::Tie::ARRAY'; goto \&Type::Tie::ARRAY::TIEARRAY }; sub TIEHASH { require Type::Tie; unshift @_, 'Type::Tie::HASH'; goto \&Type::Tie::HASH::TIEHASH }; 1; __END__ =pod =encoding utf-8 =for stopwords Moo(se)-compatible MooseX MouseX MooX Moose-compat invocant =head1 NAME Type::Tiny - tiny, yet Moo(se)-compatible type constraint =head1 SYNOPSIS use Scalar::Util qw(looks_like_number); use Type::Tiny; my $NUM = "Type::Tiny"->new( name => "Number", constraint => sub { looks_like_number($_) }, message => sub { "$_ ain't a number" }, ); package Ermintrude { use Moo; has favourite_number => (is => "ro", isa => $NUM); } package Bullwinkle { use Moose; has favourite_number => (is => "ro", isa => $NUM); } package Maisy { use Mouse; has favourite_number => (is => "ro", isa => $NUM); } =head1 STATUS This module is covered by the L. =head1 DESCRIPTION L is a tiny class for creating Moose-like type constraint objects which are compatible with Moo, Moose and Mouse. Maybe now we won't need to have separate MooseX, MouseX and MooX versions of everything? We can but hope... This documents the internals of L. L is a better starting place if you're new. =head2 Constructor =over =item C<< new(%attributes) >> Moose-style constructor function. =back =head2 Attributes Attributes are named values that may be passed to the constructor. For each attribute, there is a corresponding reader method. For example: my $type = Type::Tiny->new( name => "Foo" ); print $type->name, "\n"; # says "Foo" =head3 Important attributes These are the attributes you are likely to be most interested in providing when creating your own type constraints, and most interested in reading when dealing with type constraint objects. =over =item C<< constraint >> Coderef to validate a value (C<< $_ >>) against the type constraint. The coderef will not be called unless the value is known to pass any parent type constraint (see C below). Defaults to C<< sub { 1 } >> - i.e. a coderef that passes all values. =item C<< parent >> Optional attribute; parent type constraint. For example, an "Integer" type constraint might have a parent "Number". If provided, must be a Type::Tiny object. =item C<< inlined >> A coderef which returns a string of Perl code suitable for inlining this type. Optional. If C (above) is a coderef generated via L, then Type::Tiny I be able to automatically generate C for you. =item C<< name >> The name of the type constraint. These need to conform to certain naming rules (they must begin with an uppercase letter and continue using only letters, digits 0-9 and underscores). Optional; if not supplied will be an anonymous type constraint. =item C<< display_name >> A name to display for the type constraint when stringified. These don't have to conform to any naming rules. Optional; a default name will be calculated from the C. =item C<< library >> The package name of the type library this type is associated with. Optional. Informational only: setting this attribute does not install the type into the package. =item C<< message >> Coderef that returns an error message when C<< $_ >> does not validate against the type constraint. Optional (there's a vaguely sensible default.) =item C<< coercion >> A L object associated with this type. Generally speaking this attribute should not be passed to the constructor; you should rely on the default lazily-built coercion object. You may pass C<< coercion => 1 >> to the constructor to inherit coercions from the constraint's parent. (This requires the parent constraint to have a coercion.) =item C<< my_methods >> Experimenal hashref of additional methods that can be called on the type constraint object. =back =head3 Attributes related to parameterizable and parameterized types The following additional attributes are used for parameterizable (e.g. C) and parameterized (e.g. C<< ArrayRef[Int] >>) type constraints. Unlike Moose, these aren't handled by separate subclasses. =over =item C<< constraint_generator >> Coderef that generates a new constraint coderef based on parameters. Alternatively, the constraint generator can return a fully-formed Type::Tiny object, in which case the C, C, and C attributes documented below are ignored. Optional; providing a generator makes this type into a parameterizable type constraint. =item C<< name_generator >> A coderef which generates a new display_name based on parameters. Optional; the default is reasonable. =item C<< inline_generator >> A coderef which generates a new inlining coderef based on parameters. =item C<< coercion_generator >> A coderef which generates a new L object based on parameters. =item C<< deep_explanation >> This API is not finalized. Coderef used by L to peek inside parameterized types and figure out why a value doesn't pass the constraint. =item C<< parameters >> In parameterized types, returns an arrayref of the parameters. =back =head3 Lazy generated attributes The following attributes should not be usually passed to the constructor; unless you're doing something especially unusual, you should rely on the default lazily-built return values. =over =item C<< compiled_check >> Coderef to validate a value (C<< $_[0] >>) against the type constraint. This coderef is expected to also handle all validation for the parent type constraints. =item C<< complementary_type >> A complementary type for this type. For example, the complementary type for an integer type would be all things that are not integers, including floating point numbers, but also alphabetic strings, arrayrefs, filehandles, etc. =item C<< moose_type >>, C<< mouse_type >> Objects equivalent to this type constraint, but as a L or L. It should rarely be necessary to obtain a L object from L because the L object itself should be usable pretty much anywhere a L is expected. =back =head2 Methods =head3 Predicate methods These methods return booleans indicating information about the type constraint. They are each tightly associated with a particular attribute. (See L.) =over =item C, C, C, C, C, C, C, C, C Simple Moose-style predicate methods indicating the presence or absence of an attribute. =item C Predicate method with a little extra DWIM. Returns false if the coercion is a no-op. =item C<< is_anon >> Returns true iff the type constraint does not have a C. =item C<< is_parameterized >>, C<< is_parameterizable >> Indicates whether a type has been parameterized (e.g. C<< ArrayRef[Int] >>) or could potentially be (e.g. C<< ArrayRef >>). =back =head3 Validation and coercion The following methods are used for coercing and validating values against a type constraint: =over =item C<< check($value) >> Returns true iff the value passes the type constraint. =item C<< validate($value) >> Returns the error message for the value; returns an explicit undef if the value passes the type constraint. =item C<< assert_valid($value) >> Like C<< check($value) >> but dies if the value does not pass the type constraint. Yes, that's three very similar methods. Blame L whose API I'm attempting to emulate. :-) =item C<< assert_return($value) >> Like C<< assert_valid($value) >> but returns the value if it passes the type constraint. This seems a more useful behaviour than C<< assert_valid($value) >>. I would have just changed C<< assert_valid($value) >> to do this, except that there are edge cases where it could break Moose compatibility. =item C<< get_message($value) >> Returns the error message for the value; even if the value passes the type constraint. =item C<< validate_explain($value, $varname) >> Like C but instead of a string error message, returns an arrayref of strings explaining the reasoning why the value does not meet the type constraint, examining parent types, etc. The C<< $varname >> is an optional string like C<< '$foo' >> indicating the name of the variable being checked. =item C<< coerce($value) >> Attempt to coerce C<< $value >> to this type. =item C<< assert_coerce($value) >> Attempt to coerce C<< $value >> to this type. Throws an exception if this is not possible. =back =head3 Child type constraint creation and parameterization These methods generate new type constraint objects that inherit from the constraint they are called upon: =over =item C<< create_child_type(%attributes) >> Construct a new Type::Tiny object with this object as its parent. =item C<< where($coderef) >> Shortcut for creating an anonymous child type constraint. Use it like C<< HashRef->where(sub { exists($_->{name}) }) >>. That said, you can get a similar result using overloaded C<< & >>: HashRef & sub { exists($_->{name}) } =item C<< child_type_class >> The class that create_child_type will construct by default. =item C<< parameterize(@parameters) >> Creates a new parameterized type; throws an exception if called on a non-parameterizable type. =item C<< of(@parameters) >> A cute alias for C. Use it like C<< ArrayRef->of(Int) >>. =item C<< plus_coercions($type1, $code1, ...) >> Shorthand for creating a new child type constraint with the same coercions as this one, but then adding some extra coercions (at a higher priority than the existing ones). =item C<< plus_fallback_coercions($type1, $code1, ...) >> Like C, but added at a lower priority. =item C<< minus_coercions($type1, ...) >> Shorthand for creating a new child type constraint with fewer type coercions. =item C<< no_coercions >> Shorthand for creating a new child type constraint with no coercions at all. =back =head3 Type relationship introspection methods These methods allow you to determine a type constraint's relationship to other type constraints in an organised hierarchy: =over =item C<< equals($other) >>, C<< is_subtype_of($other) >>, C<< is_supertype_of($other) >>, C<< is_a_type_of($other) >> Compare two types. See L for what these all mean. (OK, Moose doesn't define C, but you get the idea, right?) Note that these have a slightly DWIM side to them. If you create two L objects which test the same class, they're considered equal. And: my $subtype_of_Num = Types::Standard::Num->create_child_type; my $subtype_of_Int = Types::Standard::Int->create_child_type; $subtype_of_Int->is_subtype_of( $subtype_of_Num ); # true =item C<< strictly_equals($other) >>, C<< is_strictly_subtype_of($other) >>, C<< is_strictly_supertype_of($other) >>, C<< is_strictly_a_type_of($other) >> Stricter versions of the type comparison functions. These only care about explicit inheritance via C. my $subtype_of_Num = Types::Standard::Num->create_child_type; my $subtype_of_Int = Types::Standard::Int->create_child_type; $subtype_of_Int->is_strictly_subtype_of( $subtype_of_Num ); # false =item C<< parents >> Returns a list of all this type constraint's ancestor constraints. For example, if called on the C type constraint would return the list C<< (Value, Defined, Item, Any) >>. B<< Due to a historical misunderstanding, this differs from the Moose implementation of the C method. In Moose, C only returns the immediate parent type constraints, and because type constraints only have one immediate parent, this is effectively an alias for C. The extension module L is the only place where multiple type constraints are returned; and they are returned as an arrayref in violation of the base class' documentation. I'm keeping my behaviour as it seems more useful. >> =item C<< find_parent($coderef) >> Loops through the parent type constraints I<< including the invocant itself >> and returns the nearest ancestor type constraint where the coderef evaluates to true. Within the coderef the ancestor currently being checked is C<< $_ >>. Returns undef if there is no match. In list context also returns the number of type constraints which had been looped through before the matching constraint was found. =item C<< coercibles >> Return a type constraint which is the union of type constraints that can be coerced to this one (including this one). If this type constraint has no coercions, returns itself. =item C<< type_parameter >> In parameterized type constraints, returns the first item on the list of parameters; otherwise returns undef. For example: ( ArrayRef[Int] )->type_parameter; # returns Int ( ArrayRef[Int] )->parent; # returns ArrayRef Note that parameterizable type constraints can perfectly legitimately take multiple parameters (several off the parameterizable type constraints in L do). This method only returns the first such parameter. L documents the C attribute, which returns an arrayref of all the parameters. =back =head3 Inlining methods =for stopwords uated The following methods are used to generate strings of Perl code which may be pasted into stringy Cuated subs to perform type checks: =over =item C<< can_be_inlined >> Returns boolean indicating if this type can be inlined. =item C<< inline_check($varname) >> Creates a type constraint check for a particular variable as a string of Perl code. For example: print( Types::Standard::Num->inline_check('$foo') ); prints the following output: (!ref($foo) && Scalar::Util::looks_like_number($foo)) For Moose-compat, there is an alias C<< _inline_check >> for this method. =item C<< inline_assert($varname) >> Much like C but outputs a statement of the form: die ... unless ...; Note that if this type has a custom error message, the inlined code will I this custom message!! =back =head3 Other methods =over =item C<< qualified_name >> For non-anonymous type constraints that have a library, returns a qualified C<< "MyLib::MyType" >> sort of name. Otherwise, returns the same as C. =item C<< isa($class) >>, C<< can($method) >>, C<< AUTOLOAD(@args) >> If Moose is loaded, then the combination of these methods is used to mock a Moose::Meta::TypeConstraint. If Mouse is loaded, then C mocks Mouse::Meta::TypeConstraint. =item C<< DOES($role) >> Overridden to advertise support for various roles. See also L, etc. =item C<< TIESCALAR >>, C<< TIEARRAY >>, C<< TIEHASH >> These are provided as hooks that wrap L. (Type::Tie is distributed separately, and can be used with non-Type::Tiny type constraints too.) They allow the following to work: use Types::Standard qw(Int); tie my @list, Int; push @list, 123, 456; # ok push @list, "Hello"; # dies =back The following methods exist for Moose/Mouse compatibility, but do not do anything useful. =over =item C<< compile_type_constraint >> =item C<< hand_optimized_type_constraint >> =item C<< has_hand_optimized_type_constraint >> =item C<< inline_environment >> =item C<< meta >> =back =head2 Overloading =over =item * Stringification is overloaded to return the qualified name. =item * Boolification is overloaded to always return true. =item * Coderefification is overloaded to call C. =item * On Perl 5.10.1 and above, smart match is overloaded to call C. =item * The C<< == >> operator is overloaded to call C. =item * The C<< < >> and C<< > >> operators are overloaded to call C and C. =item * The C<< ~ >> operator is overloaded to call C. =item * The C<< | >> operator is overloaded to build a union of two type constraints. See L. =item * The C<< & >> operator is overloaded to build the intersection of two type constraints. See L. =back Previous versions of Type::Tiny would overload the C<< + >> operator to call C or C as appropriate. Support for this was dropped after 0.040. =head2 Constants =over =item C<< Type::Tiny::SUPPORT_SMARTMATCH >> Indicates whether the smart match overload is supported on your version of Perl. =back =head2 Package Variables =over =item C<< $Type::Tiny::DD >> This undef by default but may be set to a coderef that Type::Tiny and related modules will use to dump data structures in things like error messages. Otherwise Type::Tiny uses it's own routine to dump data structures. C<< $DD >> may then be set to a number to limit the lengths of the dumps. (Default limit is 72.) This is a package variable (rather than get/set class methods) to allow for easy localization. =back =head1 BUGS Please report any bugs to L. =head1 SUPPORT B<< IRC: >> support is available through in the I<< #moops >> channel on L. =head1 SEE ALSO L, L. L, L, L, L. L, L, L, L, L, L. L, L. L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 THANKS Thanks to Matt S Trout for advice on L integration. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. Utils.pm000664001750001750 6220712422772210 15553 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Typepackage Type::Utils; use 5.006001; use strict; use warnings; BEGIN { $Type::Utils::AUTHORITY = 'cpan:TOBYINK'; $Type::Utils::VERSION = '1.000005'; } sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak } use Scalar::Util qw< blessed >; use Type::Library; use Type::Tiny; use Types::TypeTiny qw< TypeTiny to_TypeTiny HashLike StringLike CodeLike >; our @EXPORT = qw< declare as where message inline_as class_type role_type duck_type union intersection enum coerce from via declare_coercion to_type >; our @EXPORT_OK = ( @EXPORT, qw< extends type subtype match_on_type compile_match_on_type dwim_type english_list classifier >, ); require Exporter::Tiny; our @ISA = 'Exporter::Tiny'; sub extends { _croak "Not a type library" unless caller->isa("Type::Library"); my $caller = caller->meta; foreach my $lib (@_) { eval "use $lib; 1" or _croak "Could not load library '$lib': $@"; if ($lib->isa("Type::Library") or $lib eq 'Types::TypeTiny') { $caller->add_type( $lib->get_type($_) ) for sort $lib->meta->type_names; $caller->add_coercion( $lib->get_coercion($_) ) for sort $lib->meta->coercion_names; } elsif ($lib->isa('MooseX::Types::Base')) { require Moose::Util::TypeConstraints; my $types = $lib->type_storage; for my $name (sort keys %$types) { my $moose = Moose::Util::TypeConstraints::find_type_constraint($types->{$name}); my $tt = Types::TypeTiny::to_TypeTiny($moose); $caller->add_type( $tt->create_child_type(library => $caller, name => $name, coercion => $moose->has_coercion ? 1 : 0) ); } } elsif ($lib->isa('MouseX::Types::Base')) { require Mouse::Util::TypeConstraints; my $types = $lib->type_storage; for my $name (sort keys %$types) { my $mouse = Mouse::Util::TypeConstraints::find_type_constraint($types->{$name}); my $tt = Types::TypeTiny::to_TypeTiny($mouse); $caller->add_type( $tt->create_child_type(library => $caller, name => $name, coercion => $mouse->has_coercion ? 1 : 0) ); } } else { _croak("'$lib' is not a type constraint library"); } } } sub declare { my %opts; if (@_ % 2 == 0) { %opts = @_; if (@_==2 and $_[0]=~ /^_*[A-Z]/ and $_[1] =~ /^[0-9]+$/) { require Carp; Carp::carp("Possible missing comma after 'declare $_[0]'"); } } else { (my($name), %opts) = @_; _croak "Cannot provide two names for type" if exists $opts{name}; $opts{name} = $name; } my $caller = caller($opts{_caller_level} || 0); $opts{library} = $caller; if (defined $opts{parent}) { $opts{parent} = to_TypeTiny($opts{parent}); unless (TypeTiny->check($opts{parent})) { $caller->isa("Type::Library") or _croak("Parent type cannot be a %s", ref($opts{parent})||'non-reference scalar'); $opts{parent} = $caller->meta->get_type($opts{parent}) or _croak("Could not find parent type"); } } my $type; if (defined $opts{parent}) { $type = delete($opts{parent})->create_child_type(%opts); } else { my $bless = delete($opts{bless}) || "Type::Tiny"; eval "require $bless"; $type = $bless->new(%opts); } if ($caller->isa("Type::Library")) { $caller->meta->add_type($type) unless $type->is_anon; } return $type; } *subtype = \&declare; *type = \&declare; sub as (@) { parent => @_; } sub where (&;@) { constraint => @_; } sub message (&;@) { message => @_; } sub inline_as (&;@) { inlined => @_; } sub class_type { my $name = ref($_[0]) ? undef : shift; my %opts = %{ shift or {} }; if (defined $name) { $opts{name} = $name unless exists $opts{name}; $opts{class} = $name unless exists $opts{class}; $opts{name} =~ s/:://g; } $opts{bless} = "Type::Tiny::Class"; { no warnings "numeric"; $opts{_caller_level}++ } declare(%opts); } sub role_type { my $name = ref($_[0]) ? undef : shift; my %opts = %{ shift or {} }; if (defined $name) { $opts{name} = $name unless exists $opts{name}; $opts{role} = $name unless exists $opts{role}; $opts{name} =~ s/:://g; } $opts{bless} = "Type::Tiny::Role"; { no warnings "numeric"; $opts{_caller_level}++ } declare(%opts); } sub duck_type { my $name = ref($_[0]) ? undef : shift; my @methods = @{ shift or [] }; my %opts; $opts{name} = $name if defined $name; $opts{methods} = \@methods; $opts{bless} = "Type::Tiny::Duck"; { no warnings "numeric"; $opts{_caller_level}++ } declare(%opts); } sub enum { my $name = ref($_[0]) ? undef : shift; my @values = @{ shift or [] }; my %opts; $opts{name} = $name if defined $name; $opts{values} = \@values; $opts{bless} = "Type::Tiny::Enum"; { no warnings "numeric"; $opts{_caller_level}++ } declare(%opts); } sub union { my $name = ref($_[0]) ? undef : shift; my @tcs = @{ shift or [] }; my %opts; $opts{name} = $name if defined $name; $opts{type_constraints} = \@tcs; $opts{bless} = "Type::Tiny::Union"; { no warnings "numeric"; $opts{_caller_level}++ } declare(%opts); } sub intersection { my $name = ref($_[0]) ? undef : shift; my @tcs = @{ shift or [] }; my %opts; $opts{name} = $name if defined $name; $opts{type_constraints} = \@tcs; $opts{bless} = "Type::Tiny::Intersection"; { no warnings "numeric"; $opts{_caller_level}++ } declare(%opts); } sub declare_coercion { my %opts; $opts{name} = shift if !ref($_[0]); while (HashLike->check($_[0]) and not TypeTiny->check($_[0])) { %opts = (%opts, %{+shift}); } my $caller = caller($opts{_caller_level} || 0); $opts{library} = $caller; my $bless = delete($opts{bless}) || "Type::Coercion"; eval "require $bless"; my $c = $bless->new(%opts); my @C; if ($caller->isa("Type::Library")) { my $meta = $caller->meta; $meta->add_coercion($c) unless $c->is_anon; while (@_) { push @C, map { ref($_) ? to_TypeTiny($_) : $meta->get_type($_)||$_ } shift; push @C, shift; } } else { @C = @_; } $c->add_type_coercions(@C); return $c->freeze; } sub coerce { if ((scalar caller)->isa("Type::Library")) { my $meta = (scalar caller)->meta; my ($type) = map { ref($_) ? to_TypeTiny($_) : $meta->get_type($_)||$_ } shift; my @opts; while (@_) { push @opts, map { ref($_) ? to_TypeTiny($_) : $meta->get_type($_)||$_ } shift; push @opts, shift; } return $type->coercion->add_type_coercions(@opts); } my ($type, @opts) = @_; $type = to_TypeTiny($type); return $type->coercion->add_type_coercions(@opts); } sub from (@) { return @_; } sub to_type (@) { my $type = shift; unless (TypeTiny->check($type)) { caller->isa("Type::Library") or _croak "Target type cannot be a string"; $type = caller->meta->get_type($type) or _croak "Could not find target type"; } return +{ type_constraint => $type }, @_; } sub via (&;@) { return @_; } sub match_on_type { my $value = shift; while (@_) { my $code; if (@_ == 1) { $code = shift; } else { (my($type), $code) = splice(@_, 0, 2); TypeTiny->($type)->check($value) or next; } if (StringLike->check($code)) { local $_ = $value; if (wantarray) { my @r = eval "$code"; die $@ if $@; return @r; } if (defined wantarray) { my $r = eval "$code"; die $@ if $@; return $r; } eval "$code"; die $@ if $@; return; } else { CodeLike->($code); local $_ = $value; return $code->($value); } } _croak("No cases matched for %s", Type::Tiny::_dd($value)); } sub compile_match_on_type { my @code = 'sub { local $_ = $_[0]; '; my @checks; my @actions; my $els = ''; while (@_) { my ($type, $code); if (@_ == 1) { require Types::Standard; ($type, $code) = (Types::Standard::Any(), shift); } else { ($type, $code) = splice(@_, 0, 2); TypeTiny->($type); } if ($type->can_be_inlined) { push @code, sprintf('%sif (%s)', $els, $type->inline_check('$_')); } else { push @checks, $type; push @code, sprintf('%sif ($checks[%d]->check($_))', $els, $#checks); } $els = 'els'; if (StringLike->check($code)) { push @code, sprintf(' { %s }', $code); } else { CodeLike->($code); push @actions, $code; push @code, sprintf(' { $actions[%d]->(@_) }', $#actions); } } push @code, 'else', ' { Type::Utils::_croak("No cases matched for %s", Type::Tiny::_dd($_[0])) }'; push @code, '}'; # /sub require Eval::TypeTiny; return Eval::TypeTiny::eval_closure( source => \@code, environment => { '@actions' => \@actions, '@checks' => \@checks, }, ); } sub classifier { my $i; compile_match_on_type( +( map { my $type = $_->[0]; $type => sub { $type }; } sort { $b->[1] <=> $a->[1] or $a->[2] <=> $b->[2] } map [$_, scalar(my @parents = $_->parents), ++$i], @_ ), q[ undef ], ); } { package #hide Type::Registry::DWIM; our @ISA = qw(Type::Registry); sub foreign_lookup { my $self = shift; my $r = $self->SUPER::foreign_lookup(@_); return $r if $r; if (defined($self->{"~~assume"}) and $_[0] =~ /[A-Z_a-z][0-9A-Z_a-z]*(?:::[0-9A-Z_a-z]+)*/) { my $method = $self->{"~~assume"}; return $self->$method(@_); } return; } sub simple_lookup { my $self = shift; my $r; # If the lookup is chained to a class, then the class' own # type registry gets first refusal. # if (defined $self->{"~~chained"}) { my $chained = "Type::Registry"->for_class($self->{"~~chained"}); $r = eval { $chained->simple_lookup(@_) } unless $self == $chained; return $r if defined $r; } # Fall back to types in Types::Standard. require Types::Standard; return 'Types::Standard'->get_type($_[0]) if 'Types::Standard'->has_type($_[0]); # Only continue any further if we've been called from Type::Parser. return unless $_[1]; my $moose_lookup = sub { if ($INC{'Moose.pm'}) { require Moose::Util::TypeConstraints; require Types::TypeTiny; $r = Moose::Util::TypeConstraints::find_type_constraint($_[0]); $r = Types::TypeTiny::to_TypeTiny($r) if defined $r; } defined $r; }; my $mouse_lookup = sub { if ($INC{'Mouse.pm'}) { require Mouse::Util::TypeConstraints; require Types::TypeTiny; $r = Mouse::Util::TypeConstraints::find_type_constraint($_[0]); $r = Types::TypeTiny::to_TypeTiny($r) if defined $r; } defined $r; }; my $meta; if (defined $self->{"~~chained"}) { $meta ||= Moose::Util::find_meta($self->{"~~chained"}) if $INC{'Moose.pm'}; $meta ||= Mouse::Util::find_meta($self->{"~~chained"}) if $INC{'Mouse.pm'}; } if ($meta and $meta->isa('Class::MOP::Module')) { $moose_lookup->(@_) and return $r; } elsif ($meta and $meta->isa('Mouse::Meta::Module')) { $mouse_lookup->(@_) and return $r; } else { $moose_lookup->(@_) and return $r; $mouse_lookup->(@_) and return $r; } return $self->foreign_lookup(@_); } } our $dwimmer; sub dwim_type { my ($string, %opts) = @_; $opts{for} = caller unless defined $opts{for}; $dwimmer ||= do { require Type::Registry; 'Type::Registry::DWIM'->new; }; local $dwimmer->{'~~chained'} = $opts{for}; local $dwimmer->{'~~assume'} = $opts{does} ? 'make_role_type' : 'make_class_type'; $dwimmer->lookup($string); } sub english_list { my $conjunction = ref($_[0]) eq 'SCALAR' ? ${+shift} : 'and'; my @items = sort @_; return $items[0] if @items == 1; return "$items[0] $conjunction $items[1]" if @items == 2; my $tail = pop @items; join(', ', @items, "$conjunction $tail"); } 1; __END__ =pod =encoding utf-8 =for stopwords smush smushed =head1 NAME Type::Utils - utility functions to make defining and using type constraints a little easier =head1 SYNOPSIS package Types::Mine; use Type::Library -base; use Type::Utils -all; BEGIN { extends "Types::Standard" }; declare "AllCaps", as "Str", where { uc($_) eq $_ }, inline_as { my $varname = $_[1]; "uc($varname) eq $varname" }; coerce "AllCaps", from "Str", via { uc($_) }; =head1 STATUS This module is covered by the L. =head1 DESCRIPTION This module provides utility functions to make defining and using type constraints a little easier. =head2 Type declaration functions Many of the following are similar to the similarly named functions described in L. =over =item C<< declare $name, %options >> =item C<< declare %options >> Declare a named or anonymous type constraint. Use C and C to specify the parent type (if any) and (possibly) refine its definition. declare EvenInt, as Int, where { $_ % 2 == 0 }; my $EvenInt = declare as Int, where { $_ % 2 == 0 }; B<< NOTE: >> If the caller package inherits from L then any non-anonymous types declared in the package will be automatically installed into the library. Hidden gem: if you're inheriting from a type constraint that includes some coercions, you can include C<< coercion => 1 >> in the C<< %options >> hash to inherit the coercions. =item C<< subtype $name, %options >> =item C<< subtype %options >> Declare a named or anonymous type constraint which is descended from an existing type constraint. Use C and C to specify the parent type and refine its definition. Actually, you should use C instead; this is just an alias. This function is not exported by default. =item C<< type $name, %options >> =item C<< type %options >> Declare a named or anonymous type constraint which is not descended from an existing type constraint. Use C to provide a coderef that constrains values. Actually, you should use C instead; this is just an alias. This function is not exported by default. =item C<< as $parent >> Used with C to specify a parent type constraint: declare EvenInt, as Int, where { $_ % 2 == 0 }; =item C<< where { BLOCK } >> Used with C to provide the constraint coderef: declare EvenInt, as Int, where { $_ % 2 == 0 }; The coderef operates on C<< $_ >>, which is the value being tested. =item C<< message { BLOCK } >> Generate a custom error message when a value fails validation. declare EvenInt, as Int, where { $_ % 2 == 0 }, message { Int->validate($_) or "$_ is not divisible by two"; }; Without a custom message, the messages generated by Type::Tiny are along the lines of I<< Value "33" did not pass type constraint "EvenInt" >>, which is usually reasonable. =item C<< inline_as { BLOCK } >> Generate a string of Perl code that can be used to inline the type check into other functions. If your type check is being used within a L or L constructor or accessor methods, or used by L, this can lead to significant performance improvements. declare EvenInt, as Int, where { $_ % 2 == 0 }, inline_as { my ($constraint, $varname) = @_; my $perlcode = $constraint->parent->inline_check($varname) . "&& ($varname % 2 == 0)"; return $perlcode; }; warn EvenInt->inline_check('$xxx'); # demonstration B your C block can return a list, in which case these will be smushed together with "&&". The first item on the list may be undef, in which case the undef will be replaced by the inlined parent type constraint. (And will throw an exception if there is no parent.) declare EvenInt, as Int, where { $_ % 2 == 0 }, inline_as { return (undef, "($_ % 2 == 0)"); }; Returning a list like this is considered experimental, is not tested very much, and I offer no guarantees that it will necessarily work with Moose/Mouse/Moo. =item C<< class_type $name, { class => $package, %options } >> =item C<< class_type { class => $package, %options } >> =item C<< class_type $name >> Shortcut for declaring a L type constraint. If C<< $package >> is omitted, is assumed to be the same as C<< $name >>. If C<< $name >> contains "::" (which would be an invalid name as far as L is concerned), this will be removed. So for example, C<< class_type("Foo::Bar") >> declares a L type constraint named "FooBar" which constrains values to objects blessed into the "Foo::Bar" package. =item C<< role_type $name, { role => $package, %options } >> =item C<< role_type { role => $package, %options } >> =item C<< role_type $name >> Shortcut for declaring a L type constraint. If C<< $package >> is omitted, is assumed to be the same as C<< $name >>. If C<< $name >> contains "::" (which would be an invalid name as far as L is concerned), this will be removed. =item C<< duck_type $name, \@methods >> =item C<< duck_type \@methods >> Shortcut for declaring a L type constraint. =item C<< union $name, \@constraints >> =item C<< union \@constraints >> Shortcut for declaring a L type constraint. =item C<< enum $name, \@values >> =item C<< enum \@values >> Shortcut for declaring a L type constraint. =item C<< intersection $name, \@constraints >> =item C<< intersection \@constraints >> Shortcut for declaring a L type constraint. =back =head2 Coercion declaration functions Many of the following are similar to the similarly named functions described in L. =over =item C<< coerce $target, @coercions >> Add coercions to the target type constraint. The list of coercions is a list of type constraint, conversion code pairs. Conversion code can be either a string of Perl code or a coderef; in either case the value to be converted is C<< $_ >>. =item C<< from $source >> Sugar to specify a type constraint in a list of coercions: coerce EvenInt, from Int, via { $_ * 2 }; # As a coderef... coerce EvenInt, from Int, q { $_ * 2 }; # or as a string! =item C<< via { BLOCK } >> Sugar to specify a coderef in a list of coercions. =item C<< declare_coercion $name, \%opts, $type1, $code1, ... >> =item C<< declare_coercion \%opts, $type1, $code1, ... >> Declares a coercion that is not explicitly attached to any type in the library. For example: declare_coercion "ArrayRefFromAny", from "Any", via { [$_] }; This coercion will be exportable from the library as a L object, but the ArrayRef type exported by the library won't automatically use it. Coercions declared this way are immutable (frozen). =item C<< to_type $type >> Used with C to declare the target type constraint for a coercion, but still without explicitly attaching the coercion to the type constraint: declare_coercion "ArrayRefFromAny", to_type "ArrayRef", from "Any", via { [$_] }; You should pretty much always use this when declaring an unattached coercion because it's exceedingly useful for a type coercion to know what it will coerce to - this allows it to skip coercion when no coercion is needed (e.g. avoiding coercing C<< [] >> to C<< [ [] ] >>) and allows C to work properly. =back =head2 Type library management =over =item C<< extends @libraries >> Indicates that this type library extends other type libraries, importing their type constraints. Should usually be executed in a C<< BEGIN >> block. This is not exported by default because it's not fun to export it to Moo, Moose or Mouse classes! C<< use Type::Utils -all >> can be used to import it into your type library. =back =head2 Other =over =item C<< match_on_type $value => ($type => \&action, ..., \&default?) >> Something like a C/C or C/C construct. Dispatches along different code paths depending on the type of the incoming value. Example blatantly stolen from the Moose documentation: sub to_json { my $value = shift; return match_on_type $value => ( HashRef() => sub { my $hash = shift; '{ ' . ( join ", " => map { '"' . $_ . '" : ' . to_json( $hash->{$_} ) } sort keys %$hash ) . ' }'; }, ArrayRef() => sub { my $array = shift; '[ '.( join ", " => map { to_json($_) } @$array ).' ]'; }, Num() => q {$_}, Str() => q { '"' . $_ . '"' }, Undef() => q {'null'}, => sub { die "$_ is not acceptable json type" }, ); } Note that unlike Moose, code can be specified as a string instead of a coderef. (e.g. for C, C and C above.) For improved performance, try C. This function is not exported by default. =item C<< my $coderef = compile_match_on_type($type => \&action, ..., \&default?) >> Compile a C block into a coderef. The following JSON converter is about two orders of magnitude faster than the previous example: sub to_json; *to_json = compile_match_on_type( HashRef() => sub { my $hash = shift; '{ ' . ( join ", " => map { '"' . $_ . '" : ' . to_json( $hash->{$_} ) } sort keys %$hash ) . ' }'; }, ArrayRef() => sub { my $array = shift; '[ '.( join ", " => map { to_json($_) } @$array ).' ]'; }, Num() => q {$_}, Str() => q { '"' . $_ . '"' }, Undef() => q {'null'}, => sub { die "$_ is not acceptable json type" }, ); Remember to store the coderef somewhere fairly permanent so that you don't compile it over and over. C variables (in Perl >= 5.10) are good for this. (Same sort of idea as L.) This function is not exported by default. =item C<< my $coderef = classifier(@types) >> Returns a coderef that can be used to classify values according to their type constraint. The coderef, when passed a value, returns a type constraint which the value satisfies. use feature qw( say ); use Type::Utils qw( classifier ); use Types::Standard qw( Int Num Str Any ); my $classifier = classifier(Str, Int, Num, Any); say $classifier->( "42" )->name; # Int say $classifier->( "4.2" )->name; # Num say $classifier->( [] )->name; # Any Note that, for example, "42" satisfies Int, but it would satisfy the type constraints Num, Str, and Any as well. In this case, the classifier has picked the most specific type constraint that "42" satisfies. If no type constraint is satisfied by the value, then the classifier will return undef. =item C<< dwim_type($string, %options) >> Given a string like "ArrayRef[Int|CodeRef]", turns it into a type constraint object, hopefully doing what you mean. It uses the syntax of L. Firstly the L for the caller package is consulted; if that doesn't have a match, L is consulted for type constraint names; and if there's still no match, then if a type constraint looks like a class name, a new L object is created for it. Somewhere along the way, it also checks Moose/Mouse's type constraint registries if they are loaded. You can specify an alternative for the caller using the C option. If you'd rather create a L object, set the C option to true. # An arrayref of objects, each of which must do role Foo. my $type = dwim_type("ArrayRef[Foo]", does => 1); Type::Registry->for_me->add_types("-Standard"); Type::Registry->for_me->alias_type("Int" => "Foo"); # An arrayref of integers. my $type = dwim_type("ArrayRef[Foo]", does => 1); While it's probably better overall to use the proper L interface for resolving type constraint strings, this function often does what you want. It should never die if it fails to find a type constraint (but may die if the type constraint string is syntactically malformed), preferring to return undef. This function is not exported by default. =item C<< english_list(\$conjunction, @items) >> Joins the items with commas, placing a conjunction before the final item. The conjunction is optional, defaulting to "and". english_list(qw/foo bar baz/); # "foo, bar, and baz" english_list(\"or", qw/quux quuux/); # "quux or quuux" This function is not exported by default. =back =head1 EXPORT By default, all of the functions documented above are exported, except C and C (prefer C instead), C, C, C/C, C, and C. This module uses L; see the documentation of that module for tips and tricks importing from Type::Utils. =head1 BUGS Please report any bugs to L. =head1 SEE ALSO L. L, L, L, L. L, L, L, L, L. L, L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. Standard.pm000664001750001750 11156412422772210 16417 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Typespackage Types::Standard; use 5.006001; use strict; use warnings; BEGIN { eval { require re }; if ($] < 5.008) { require Devel::TypeTiny::Perl56Compat }; if ($] < 5.010) { require Devel::TypeTiny::Perl58Compat }; } BEGIN { $Types::Standard::AUTHORITY = 'cpan:TOBYINK'; $Types::Standard::VERSION = '1.000005'; } use Type::Library -base; our @EXPORT_OK = qw( slurpy ); use Scalar::Util qw( blessed looks_like_number ); use Type::Tiny (); use Types::TypeTiny (); BEGIN { *_is_class_loaded = Type::Tiny::_USE_XS ? \&Type::Tiny::XS::Util::is_class_loaded : sub { return !!0 if ref $_[0]; return !!0 if not $_[0]; my $stash = do { no strict 'refs'; \%{"$_[0]\::"} }; return !!1 if exists $stash->{'ISA'}; return !!1 if exists $stash->{'VERSION'}; foreach my $globref (values %$stash) { return !!1 if *{$globref}{CODE}; } return !!0; }; }; my $add_core_type = sub { my $meta = shift; my ($typedef) = @_; my $name = $typedef->{name}; my ($xsub, $xsubname); # We want Map and Tuple to be XSified, even if they're not # really core. $typedef->{_is_core} = 1 unless $name eq 'Map' || $name eq 'Tuple'; if ( Type::Tiny::_USE_XS and not ($name eq 'RegexpRef') ) { $xsub = Type::Tiny::XS::get_coderef_for($name); $xsubname = Type::Tiny::XS::get_subname_for($name); } elsif ( Type::Tiny::_USE_MOUSE and not ($name eq 'RegexpRef' or $name eq 'Int' or $name eq 'Object') ) { require Mouse::Util::TypeConstraints; $xsub = "Mouse::Util::TypeConstraints"->can($name); $xsubname = "Mouse::Util::TypeConstraints::$name" if $xsub; } $typedef->{compiled_type_constraint} = $xsub if $xsub; $typedef->{inlined} = sub { "$xsubname\($_[1])" } if defined($xsubname) and ( # These should be faster than their normal inlined # equivalents $name eq 'Str' or $name eq 'Bool' or $name eq 'ClassName' or $name eq 'RegexpRef' or $name eq 'FileHandle' ); $meta->add_type($typedef); }; sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak } my $meta = __PACKAGE__->meta; # Stringable and LazyLoad are optimizations that complicate # this module somewhat, but they have led to performance # improvements. If Types::Standard wasn't such a key type # library, I wouldn't use them. I strongly discourage anybody # from using them in their own code. If you're looking for # examples of how to write a type library sanely, you're # better off looking at the code for Types::Common::Numeric # and Types::Common::String. sub Stringable (&) { package #private Types::Standard::_Stringable; use overload q[""] => sub { $_[0]{text} ||= $_[0]{code}->() }, fallback => 1; bless +{ code => $_[0] }; } sub LazyLoad ($$) { package #private Types::Standard::LazyLoad; use overload fallback => 1, q[&{}] => sub { my ($typename, $function) = @{$_[0]}; my $type = $meta->get_type($typename); my $class = "Types::Standard::$typename"; eval "require $class; 1" or die($@); # Majorly break encapsulation for Type::Tiny :-O for my $key (keys %$type) { next unless ref($type->{$key}) eq __PACKAGE__; my $f = $type->{$key}[1]; $type->{$key} = $class->can("__$f"); } return $class->can("__$function"); }; bless \@_; } no warnings; BEGIN { *STRICTNUM = $ENV{PERL_TYPES_STANDARD_STRICTNUM} ? sub(){!!1} : sub(){!!0} }; my $_any = $meta->$add_core_type({ name => "Any", inlined => sub { "!!1" }, }); my $_item = $meta->$add_core_type({ name => "Item", inlined => sub { "!!1" }, parent => $_any, }); $meta->$add_core_type({ name => "Bool", parent => $_item, constraint => sub { !defined $_ or $_ eq q() or $_ eq '0' or $_ eq '1' }, inlined => sub { "!defined $_[1] or $_[1] eq q() or $_[1] eq '0' or $_[1] eq '1'" }, }); my $_undef = $meta->$add_core_type({ name => "Undef", parent => $_item, constraint => sub { !defined $_ }, inlined => sub { "!defined($_[1])" }, }); my $_def = $meta->$add_core_type({ name => "Defined", parent => $_item, constraint => sub { defined $_ }, inlined => sub { "defined($_[1])" }, }); my $_val = $meta->$add_core_type({ name => "Value", parent => $_def, constraint => sub { not ref $_ }, inlined => sub { "defined($_[1]) and not ref($_[1])" }, }); my $_str = $meta->$add_core_type({ name => "Str", parent => $_val, constraint => sub { ref(\$_) eq 'SCALAR' or ref(\(my $val = $_)) eq 'SCALAR' }, inlined => sub { "defined($_[1]) and do { ref(\\$_[1]) eq 'SCALAR' or ref(\\(my \$val = $_[1])) eq 'SCALAR' }" }, }); my $_laxnum = $meta->add_type({ name => "LaxNum", parent => $_str, constraint => sub { looks_like_number $_ }, inlined => sub { "defined($_[1]) && !ref($_[1]) && Scalar::Util::looks_like_number($_[1])" }, }); my $_strictnum = $meta->add_type({ name => "StrictNum", parent => $_str, constraint => sub { my $val = $_; ($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 ); }, inlined => sub { 'my $val = '.$_[1].';'. Value()->inline_check('$val') .' && ( $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 ); ' }, }); my $_num = $meta->add_type({ name => "Num", parent => (STRICTNUM ? $_strictnum : $_laxnum), }); $meta->$add_core_type({ name => "Int", parent => $_num, constraint => sub { /\A-?[0-9]+\z/ }, inlined => sub { "defined $_[1] and $_[1] =~ /\\A-?[0-9]+\\z/" }, }); my $_classn = $meta->add_type({ name => "ClassName", parent => $_str, constraint => \&_is_class_loaded, inlined => sub { "Types::Standard::_is_class_loaded(do { my \$tmp = $_[1] })" }, }); $meta->add_type({ name => "RoleName", parent => $_classn, constraint => sub { not $_->can("new") }, inlined => sub { "Types::Standard::_is_class_loaded(do { my \$tmp = $_[1] }) and not $_[1]\->can('new')" }, }); my $_ref = $meta->$add_core_type({ name => "Ref", parent => $_def, constraint => sub { ref $_ }, inlined => sub { "!!ref($_[1])" }, constraint_generator => sub { return $meta->get_type('Ref') unless @_; my $reftype = shift; Types::TypeTiny::StringLike->check($reftype) or _croak("Parameter to Ref[`a] expected to be string; got $reftype"); $reftype = "$reftype"; return sub { ref($_[0]) and Scalar::Util::reftype($_[0]) eq $reftype; } }, inline_generator => sub { my $reftype = shift; return sub { my $v = $_[1]; "ref($v) and Scalar::Util::reftype($v) eq q($reftype)"; }; }, deep_explanation => sub { require B; my ($type, $value, $varname) = @_; my $param = $type->parameters->[0]; return if $type->check($value); my $reftype = Scalar::Util::reftype($value); return [ sprintf('"%s" constrains reftype(%s) to be equal to %s', $type, $varname, B::perlstring($param)), sprintf('reftype(%s) is %s', $varname, defined($reftype) ? B::perlstring($reftype) : "undef"), ]; }, }); $meta->$add_core_type({ name => "CodeRef", parent => $_ref, constraint => sub { ref $_ eq "CODE" }, inlined => sub { "ref($_[1]) eq 'CODE'" }, }); $meta->$add_core_type({ name => "RegexpRef", parent => $_ref, constraint => sub { ref($_) && !!re::is_regexp($_) }, inlined => sub { "ref($_[1]) && !!re::is_regexp($_[1])" }, }); $meta->$add_core_type({ name => "GlobRef", parent => $_ref, constraint => sub { ref $_ eq "GLOB" }, inlined => sub { "ref($_[1]) eq 'GLOB'" }, }); $meta->$add_core_type({ name => "FileHandle", parent => $_ref, constraint => sub { (ref($_) eq "GLOB" && Scalar::Util::openhandle($_)) or (blessed($_) && $_->isa("IO::Handle")) }, inlined => sub { "(ref($_[1]) eq \"GLOB\" && Scalar::Util::openhandle($_[1])) ". "or (Scalar::Util::blessed($_[1]) && $_[1]\->isa(\"IO::Handle\"))" }, }); my $_arr = $meta->$add_core_type({ name => "ArrayRef", parent => $_ref, constraint => sub { ref $_ eq "ARRAY" }, inlined => sub { "ref($_[1]) eq 'ARRAY'" }, constraint_generator => LazyLoad(ArrayRef => 'constraint_generator'), inline_generator => LazyLoad(ArrayRef => 'inline_generator'), deep_explanation => LazyLoad(ArrayRef => 'deep_explanation'), coercion_generator => LazyLoad(ArrayRef => 'coercion_generator'), }); my $_hash = $meta->$add_core_type({ name => "HashRef", parent => $_ref, constraint => sub { ref $_ eq "HASH" }, inlined => sub { "ref($_[1]) eq 'HASH'" }, constraint_generator => LazyLoad(HashRef => 'constraint_generator'), inline_generator => LazyLoad(HashRef => 'inline_generator'), deep_explanation => LazyLoad(HashRef => 'deep_explanation'), coercion_generator => LazyLoad(HashRef => 'coercion_generator'), my_methods => { hashref_allows_key => sub { my $self = shift; Str()->check($_[0]); }, hashref_allows_value => sub { my $self = shift; my ($key, $value) = @_; return !!0 unless $self->my_hashref_allows_key($key); return !!1 if $self==HashRef(); my $href = $self->find_parent(sub { $_->has_parent && $_->parent==HashRef() }); my $param = $href->type_parameter; Str()->check($key) and $param->check($value); }, }, }); $meta->$add_core_type({ name => "ScalarRef", parent => $_ref, constraint => sub { ref $_ eq "SCALAR" or ref $_ eq "REF" }, inlined => sub { "ref($_[1]) eq 'SCALAR' or ref($_[1]) eq 'REF'" }, constraint_generator => LazyLoad(ScalarRef => 'constraint_generator'), inline_generator => LazyLoad(ScalarRef => 'inline_generator'), deep_explanation => LazyLoad(ScalarRef => 'deep_explanation'), coercion_generator => LazyLoad(ScalarRef => 'coercion_generator'), }); my $_obj = $meta->$add_core_type({ name => "Object", parent => $_ref, constraint => sub { blessed $_ }, inlined => sub { "Scalar::Util::blessed($_[1])" }, }); $meta->$add_core_type({ name => "Maybe", parent => $_item, constraint_generator => sub { return $meta->get_type('Maybe') unless @_; my $param = Types::TypeTiny::to_TypeTiny(shift); Types::TypeTiny::TypeTiny->check($param) or _croak("Parameter to Maybe[`a] expected to be a type constraint; got $param"); my $param_compiled_check = $param->compiled_check; my @xsub; if (Type::Tiny::_USE_XS) { my $paramname = Type::Tiny::XS::is_known($param_compiled_check); push @xsub, Type::Tiny::XS::get_coderef_for("Maybe[$paramname]") if $paramname; } elsif (Type::Tiny::_USE_MOUSE and $param->_has_xsub) { require Mouse::Util::TypeConstraints; my $maker = "Mouse::Util::TypeConstraints"->can("_parameterize_Maybe_for"); push @xsub, $maker->($param) if $maker; } return( sub { my $value = shift; return !!1 unless defined $value; return $param->check($value); }, @xsub, ); }, inline_generator => sub { my $param = shift; my $param_compiled_check = $param->compiled_check; if (Type::Tiny::_USE_XS) { my $paramname = Type::Tiny::XS::is_known($param_compiled_check); my $xsubname = Type::Tiny::XS::get_subname_for("Maybe[$paramname]"); return sub { "$xsubname\($_[1]\)" } if $xsubname; } return unless $param->can_be_inlined; return sub { my $v = $_[1]; my $param_check = $param->inline_check($v); "!defined($v) or $param_check"; }; }, deep_explanation => sub { my ($type, $value, $varname) = @_; my $param = $type->parameters->[0]; return [ sprintf('%s is defined', Type::Tiny::_dd($value)), sprintf('"%s" constrains the value with "%s" if it is defined', $type, $param), @{ $param->validate_explain($value, $varname) }, ]; }, coercion_generator => sub { my ($parent, $child, $param) = @_; return unless $param->has_coercion; return $param->coercion; }, }); my $_map = $meta->$add_core_type({ name => "Map", parent => $_hash, constraint_generator => LazyLoad(Map => 'constraint_generator'), inline_generator => LazyLoad(Map => 'inline_generator'), deep_explanation => LazyLoad(Map => 'deep_explanation'), coercion_generator => LazyLoad(Map => 'coercion_generator'), my_methods => { hashref_allows_key => sub { my $self = shift; my ($key) = @_; return Str()->check($key) if $self==Map(); my $map = $self->find_parent(sub { $_->has_parent && $_->parent==Map() }); my ($kcheck, $vcheck) = @{ $map->parameters }; ($kcheck or Any())->check($key); }, hashref_allows_value => sub { my $self = shift; my ($key, $value) = @_; return !!0 unless $self->my_hashref_allows_key($key); return !!1 if $self==Map(); my $map = $self->find_parent(sub { $_->has_parent && $_->parent==Map() }); my ($kcheck, $vcheck) = @{ $map->parameters }; ($kcheck or Any())->check($key) and ($vcheck or Any())->check($value); }, }, }); my $_Optional = $meta->add_type({ name => "Optional", parent => $_item, constraint_generator => sub { return $meta->get_type('Optional') unless @_; my $param = Types::TypeTiny::to_TypeTiny(shift); Types::TypeTiny::TypeTiny->check($param) or _croak("Parameter to Optional[`a] expected to be a type constraint; got $param"); sub { $param->check($_[0]) } }, inline_generator => sub { my $param = shift; return unless $param->can_be_inlined; return sub { my $v = $_[1]; $param->inline_check($v); }; }, deep_explanation => sub { my ($type, $value, $varname) = @_; my $param = $type->parameters->[0]; return [ sprintf('%s exists', $varname), sprintf('"%s" constrains %s with "%s" if it exists', $type, $varname, $param), @{ $param->validate_explain($value, $varname) }, ]; }, coercion_generator => sub { my ($parent, $child, $param) = @_; return unless $param->has_coercion; return $param->coercion; }, }); sub slurpy { my $t = shift; wantarray ? (+{ slurpy => $t }, @_) : +{ slurpy => $t }; } $meta->$add_core_type({ name => "Tuple", parent => $_arr, name_generator => sub { my ($s, @a) = @_; sprintf('%s[%s]', $s, join q[,], map { ref($_) eq "HASH" ? sprintf("slurpy %s", $_->{slurpy}) : $_ } @a); }, constraint_generator => LazyLoad(Tuple => 'constraint_generator'), inline_generator => LazyLoad(Tuple => 'inline_generator'), deep_explanation => LazyLoad(Tuple => 'deep_explanation'), coercion_generator => LazyLoad(Tuple => 'coercion_generator'), }); $meta->add_type({ name => "Dict", parent => $_hash, name_generator => sub { my ($s, @p) = @_; my $l = ref($p[-1]) eq q(HASH) ? pop(@p)->{slurpy} : undef; my %a = @p; sprintf('%s[%s%s]', $s, join(q[,], map sprintf("%s=>%s", $_, $a{$_}), sort keys %a), $l ? ",slurpy $l" : ''); }, constraint_generator => LazyLoad(Dict => 'constraint_generator'), inline_generator => LazyLoad(Dict => 'inline_generator'), deep_explanation => LazyLoad(Dict => 'deep_explanation'), coercion_generator => LazyLoad(Dict => 'coercion_generator'), my_methods => { dict_is_slurpy => sub { my $self = shift; return !!0 if $self==Dict(); my $dict = $self->find_parent(sub { $_->has_parent && $_->parent==Dict() }); ref($dict->parameters->[-1]) eq q(HASH) ? $dict->parameters->[-1]{slurpy} : !!0 }, hashref_allows_key => sub { my $self = shift; my ($key) = @_; return Str()->check($key) if $self==Dict(); my $dict = $self->find_parent(sub { $_->has_parent && $_->parent==Dict() }); my %params; my $slurpy = $dict->my_dict_is_slurpy; if ($slurpy) { my @args = @{$dict->parameters}; pop @args; %params = @args; } else { %params = @{ $dict->parameters } } return !!1 if exists($params{$key}); return !!0 if !$slurpy; return Str()->check($key) if $slurpy==Any() || $slurpy==Item() || $slurpy==Defined() || $slurpy==Ref(); return $slurpy->my_hashref_allows_key($key) if $slurpy->is_a_type_of(HashRef()); return !!0; }, hashref_allows_value => sub { my $self = shift; my ($key, $value) = @_; return !!0 unless $self->my_hashref_allows_key($key); return !!1 if $self==Dict(); my $dict = $self->find_parent(sub { $_->has_parent && $_->parent==Dict() }); my %params; my $slurpy = $dict->my_dict_is_slurpy; if ($slurpy) { my @args = @{$dict->parameters}; pop @args; %params = @args; } else { %params = @{ $dict->parameters } } return !!1 if exists($params{$key}) && $params{$key}->check($value); return !!0 if !$slurpy; return !!1 if $slurpy==Any() || $slurpy==Item() || $slurpy==Defined() || $slurpy==Ref(); return $slurpy->my_hashref_allows_value($key, $value) if $slurpy->is_a_type_of(HashRef()); return !!0; }, }, }); use overload (); $meta->add_type({ name => "Overload", parent => $_obj, constraint => sub { overload::Overloaded($_) }, inlined => sub { "Scalar::Util::blessed($_[1]) and overload::Overloaded($_[1])" }, constraint_generator => sub { return $meta->get_type('Overload') unless @_; my @operations = map { Types::TypeTiny::StringLike->check($_) ? "$_" : _croak("Parameters to Overload[`a] expected to be a strings; got $_"); } @_; return sub { my $value = shift; for my $op (@operations) { return unless overload::Method($value, $op); } return !!1; } }, inline_generator => sub { my @operations = @_; return sub { my $v = $_[1]; join " and ", "Scalar::Util::blessed($v)", map "overload::Method($v, q[$_])", @operations; }; }, }); our %_StrMatch; $meta->add_type({ name => "StrMatch", parent => $_str, constraint_generator => sub { return $meta->get_type('StrMatch') unless @_; my ($regexp, $checker) = @_; ref($regexp) eq 'Regexp' or _croak("First parameter to StrMatch[`a] expected to be a Regexp; got $regexp"); if (@_ > 1) { $checker = Types::TypeTiny::to_TypeTiny($checker); Types::TypeTiny::TypeTiny->check($checker) or _croak("Second parameter to StrMatch[`a] expected to be a type constraint; got $checker") } $checker ? sub { my $value = shift; return if ref($value); my @m = ($value =~ $regexp); $checker->check(\@m); } : sub { my $value = shift; !ref($value) and $value =~ $regexp; } ; }, inline_generator => sub { require B; my ($regexp, $checker) = @_; my $regexp_string = "$regexp"; $_StrMatch{$regexp_string} = $regexp; if ($checker) { return unless $checker->can_be_inlined; return sub { my $v = $_[1]; sprintf "!ref($v) and do { my \$m = [$v =~ \$Types::Standard::_StrMatch{%s}]; %s }", B::perlstring($regexp_string), $checker->inline_check('$m'), ; }; } else { return sub { my $v = $_[1]; sprintf "!ref($v) and $v =~ \$Types::Standard::_StrMatch{%s}", B::perlstring($regexp_string), ; }; } }, }); $meta->add_type({ name => "OptList", parent => $_arr, constraint => sub { for my $inner (@$_) { return unless ref($inner) eq q(ARRAY); return unless @$inner == 2; return unless is_Str($inner->[0]); } return !!1; }, inlined => sub { my ($self, $var) = @_; my $Str_check = Str()->inline_check('$inner->[0]'); my @code = 'do { my $ok = 1; '; push @code, sprintf('for my $inner (@{%s}) { no warnings; ', $var); push @code, sprintf('($ok=0) && last unless ref($inner) eq q(ARRAY) && @$inner == 2 && (%s); ', $Str_check); push @code, '} '; push @code, '$ok }'; return (undef, join(q( ), @code)); }, }); $meta->add_type({ name => "Tied", parent => $_ref, constraint => sub { !!tied(Scalar::Util::reftype($_) eq 'HASH' ? %{$_} : Scalar::Util::reftype($_) eq 'ARRAY' ? @{$_} : ${$_}) }, inlined => sub { my ($self, $var) = @_; $self->parent->inline_check($var) . " and !!tied(Scalar::Util::reftype($var) eq 'HASH' ? \%{$var} : Scalar::Util::reftype($var) eq 'ARRAY' ? \@{$var} : \${$var})" }, name_generator => sub { my $self = shift; my $param = Types::TypeTiny::to_TypeTiny(shift); unless (Types::TypeTiny::TypeTiny->check($param)) { Types::TypeTiny::StringLike->check($param) or _croak("Parameter to Tied[`a] expected to be a class name; got $param"); require B; return sprintf("%s[%s]", $self, B::perlstring($param)); } return sprintf("%s[%s]", $self, $param); }, constraint_generator => sub { return $meta->get_type('Tied') unless @_; my $param = Types::TypeTiny::to_TypeTiny(shift); unless (Types::TypeTiny::TypeTiny->check($param)) { Types::TypeTiny::StringLike->check($param) or _croak("Parameter to Tied[`a] expected to be a class name; got $param"); require Type::Tiny::Class; $param = "Type::Tiny::Class"->new(class => "$param"); } my $check = $param->compiled_check; return sub { $check->(tied(Scalar::Util::reftype($_) eq 'HASH' ? %{$_} : Scalar::Util::reftype($_) eq 'ARRAY' ? @{$_} : ${$_})); }; }, inline_generator => sub { my $param = Types::TypeTiny::to_TypeTiny(shift); unless (Types::TypeTiny::TypeTiny->check($param)) { Types::TypeTiny::StringLike->check($param) or _croak("Parameter to Tied[`a] expected to be a class name; got $param"); require Type::Tiny::Class; $param = "Type::Tiny::Class"->new(class => "$param"); } return unless $param->can_be_inlined; return sub { require B; my $var = $_[1]; sprintf( "%s and do { my \$TIED = tied(Scalar::Util::reftype($var) eq 'HASH' ? \%{$var} : Scalar::Util::reftype($var) eq 'ARRAY' ? \@{$var} : \${$var}); %s }", Ref()->inline_check($var), $param->inline_check('$TIED') ); }; }, }); $meta->add_type({ name => "InstanceOf", parent => $_obj, constraint_generator => sub { return $meta->get_type('InstanceOf') unless @_; require Type::Tiny::Class; my @classes = map { Types::TypeTiny::TypeTiny->check($_) ? $_ : "Type::Tiny::Class"->new(class => $_, display_name => sprintf('InstanceOf[%s]', B::perlstring($_))) } @_; return $classes[0] if @classes == 1; require B; require Type::Tiny::Union; return "Type::Tiny::Union"->new( type_constraints => \@classes, display_name => sprintf('InstanceOf[%s]', join q[,], map B::perlstring($_->class), @classes), ); }, }); $meta->add_type({ name => "ConsumerOf", parent => $_obj, constraint_generator => sub { return $meta->get_type('ConsumerOf') unless @_; require B; require Type::Tiny::Role; my @roles = map { Types::TypeTiny::TypeTiny->check($_) ? $_ : "Type::Tiny::Role"->new(role => $_, display_name => sprintf('ConsumerOf[%s]', B::perlstring($_))) } @_; return $roles[0] if @roles == 1; require Type::Tiny::Intersection; return "Type::Tiny::Intersection"->new( type_constraints => \@roles, display_name => sprintf('ConsumerOf[%s]', join q[,], map B::perlstring($_->role), @roles), ); }, }); $meta->add_type({ name => "HasMethods", parent => $_obj, constraint_generator => sub { return $meta->get_type('HasMethods') unless @_; require B; require Type::Tiny::Duck; return "Type::Tiny::Duck"->new( methods => \@_, display_name => sprintf('HasMethods[%s]', join q[,], map B::perlstring($_), @_), ); }, }); $meta->add_type({ name => "Enum", parent => $_str, constraint_generator => sub { return $meta->get_type('Enum') unless @_; require B; require Type::Tiny::Enum; return "Type::Tiny::Enum"->new( values => \@_, display_name => sprintf('Enum[%s]', join q[,], map B::perlstring($_), @_), ); }, }); $meta->add_coercion({ name => "MkOpt", type_constraint => $meta->get_type("OptList"), type_coercion_map => [ $_arr, q{ Exporter::Tiny::mkopt($_) }, $_hash, q{ Exporter::Tiny::mkopt($_) }, $_undef, q{ [] }, ], }); $meta->add_coercion({ name => "Join", type_constraint => $_str, coercion_generator => sub { my ($self, $target, $sep) = @_; Types::TypeTiny::StringLike->check($sep) or _croak("Parameter to Join[`a] expected to be a string; got $sep"); require B; $sep = B::perlstring($sep); return (ArrayRef(), qq{ join($sep, \@\$_) }); }, }); $meta->add_coercion({ name => "Split", type_constraint => $_arr, coercion_generator => sub { my ($self, $target, $re) = @_; ref($re) eq q(Regexp) or _croak("Parameter to Split[`a] expected to be a regular expresssion; got $re"); my $regexp_string = "$re"; $regexp_string =~ s/\\\//\\\\\//g; # toothpicks return (Str(), qq{ [split /$regexp_string/, \$_] }); }, }); __PACKAGE__->meta->make_immutable; 1; __END__ =pod =for stopwords booleans vstrings typeglobs =encoding utf-8 =for stopwords datetimes =head1 NAME Types::Standard - bundled set of built-in types for Type::Tiny =head1 STATUS This module is covered by the L. =head1 DESCRIPTION L bundles a few types which seem to be useful. =head2 Moose-like The following types are similar to those described in L. =over =item C<< Any >> Absolutely any value passes this type constraint (even undef). =item C<< Item >> Essentially the same as C. All other type constraints in this library inherit directly or indirectly from C. =item C<< Bool >> Values that are reasonable booleans. Accepts 1, 0, the empty string and undef. =item C<< Maybe[`a] >> Given another type constraint, also accepts undef. For example, C<< Maybe[Int] >> accepts all integers plus undef. =item C<< Undef >> Only undef passes this type constraint. =item C<< Defined >> Only undef fails this type constraint. =item C<< Value >> Any defined, non-reference value. =item C<< Str >> Any string. (The only difference between C and C is that the former accepts typeglobs and vstrings.) Other customers also bought: C<< StringLike >> from L. =item C<< Num >> See C and C below. =item C<< Int >> An integer; that is a string of digits 0 to 9, optionally prefixed with a hyphen-minus character. =item C<< ClassName >> The name of a loaded package. The package must have C<< @ISA >> or C<< $VERSION >> defined, or must define at least one sub to be considered a loaded package. =item C<< RoleName >> Like C<< ClassName >>, but the package must I define a method called C. This is subtly different from Moose's type constraint of the same name; let me know if this causes you any problems. (I can't promise I'll change anything though.) =item C<< Ref[`a] >> Any defined reference value, including blessed objects. Unlike Moose, C is a parameterized type, allowing Scalar::Util::reftype checks, a la Ref["HASH"] # hashrefs, including blessed hashrefs =item C<< ScalarRef[`a] >> A value where C<< ref($value) eq "SCALAR" or ref($value) eq "REF" >>. If parameterized, the referred value must pass the additional constraint. For example, C<< ScalarRef[Int] >> must be a reference to a scalar which holds an integer value. =item C<< ArrayRef[`a] >> A value where C<< ref($value) eq "ARRAY" >>. If parameterized, the elements of the array must pass the additional constraint. For example, C<< ArrayRef[Num] >> must be a reference to an array of numbers. Other customers also bought: C<< ArrayLike >> from L. =item C<< HashRef[`a] >> A value where C<< ref($value) eq "HASH" >>. If parameterized, the values of the hash must pass the additional constraint. For example, C<< HashRef[Num] >> must be a reference to an hash where the values are numbers. The hash keys are not constrained, but Perl limits them to strings; see C below if you need to further constrain the hash values. Other customers also bought: C<< HashLike >> from L. =item C<< CodeRef >> A value where C<< ref($value) eq "CODE" >>. Other customers also bought: C<< CodeLike >> from L. =item C<< RegexpRef >> A value where C<< ref($value) eq "Regexp" >>. =item C<< GlobRef >> A value where C<< ref($value) eq "GLOB" >>. =item C<< FileHandle >> A file handle. =item C<< Object >> A blessed object. (This also accepts regexp refs.) =back =head2 Structured OK, so I stole some ideas from L. =over =item C<< Map[`k, `v] >> Similar to C but parameterized with type constraints for both the key and value. The constraint for keys would typically be a subtype of C. =item C<< Tuple[...] >> Subtype of C, accepting an list of type constraints for each slot in the array. C<< Tuple[Int, HashRef] >> would match C<< [1, {}] >> but not C<< [{}, 1] >>. =item C<< Dict[...] >> Subtype of C, accepting an list of type constraints for each slot in the hash. For example C<< Dict[name => Str, id => Int] >> allows C<< { name => "Bob", id => 42 } >>. =item C<< Optional[`a] >> Used in conjunction with C and C to specify slots that are optional and may be omitted (but not necessarily set to an explicit undef). C<< Dict[name => Str, id => Optional[Int]] >> allows C<< { name => "Bob" } >> but not C<< { name => "Bob", id => "BOB" } >>. Note that any use of C<< Optional[`a] >> outside the context of parameterized C and C type constraints makes little sense, and its behaviour is undefined. (An exception: it is used by L for a similar purpose to how it's used in C.) =back This module also exports a C function, which can be used as follows. It can cause additional trailing values in a C to be slurped into a structure and validated. For example, slurping into an ArrayRef: my $type = Tuple[Str, slurpy ArrayRef[Int]]; $type->( ["Hello"] ); # ok $type->( ["Hello", 1, 2, 3] ); # ok $type->( ["Hello", [1, 2, 3]] ); # not ok Or into a hashref: my $type2 = Tuple[Str, slurpy Map[Int, RegexpRef]]; $type2->( ["Hello"] ); # ok $type2->( ["Hello", 1, qr/one/i, 2, qr/two/] ); # ok It can cause additional values in a C to be slurped into a hashref and validated: my $type3 = Dict[ values => ArrayRef, slurpy HashRef[Str] ]; $type3->( { values => [] } ); # ok $type3->( { values => [], name => "Foo" } ); # ok $type3->( { values => [], name => [] } ); # not ok In either C or C, C<< slurpy Any >> can be used to indicate that additional values are acceptable, but should not be constrained in any way. (C<< slurpy Any >> is an optimized code path.) =begin trustme =item slurpy =end trustme =head2 Objects OK, so I stole some ideas from L. =over =item C<< InstanceOf[`a] >> Shortcut for a union of L constraints. C<< InstanceOf["Foo", "Bar"] >> allows objects blessed into the C or C classes, or subclasses of those. Given no parameters, just equivalent to C. =item C<< ConsumerOf[`a] >> Shortcut for an intersection of L constraints. C<< ConsumerOf["Foo", "Bar"] >> allows objects where C<< $o->DOES("Foo") >> and C<< $o->DOES("Bar") >> both return true. Given no parameters, just equivalent to C. =item C<< HasMethods[`a] >> Shortcut for a L constraint. C<< HasMethods["foo", "bar"] >> allows objects where C<< $o->can("foo") >> and C<< $o->can("bar") >> both return true. Given no parameters, just equivalent to C. =back =head2 More There are a few other types exported by this function: =over =item C<< Overload[`a] >> With no parameters, checks that the value is an overloaded object. Can be given one or more string parameters, which are specific operations to check are overloaded. For example, the following checks for objects which overload addition and subtraction. Overload["+", "-"] =item C<< Tied[`a] >> A reference to a tied scalar, array or hash. Can be parameterized with a type constraint which will be applied to the object returned by the C<< tied() >> function. As a convenience, can also be parameterized with a string, which will be inflated to a L. use Types::Standard qw(Tied); use Type::Utils qw(class_type); my $My_Package = class_type { class => "My::Package" }; tie my %h, "My::Package"; \%h ~~ Tied; # true \%h ~~ Tied[ $My_Package ]; # true \%h ~~ Tied["My::Package"]; # true tie my $s, "Other::Package"; \$s ~~ Tied; # true $s ~~ Tied; # false !! If you need to check that something is specifically a reference to a tied hash, use an intersection: use Types::Standard qw( Tied HashRef ); my $TiedHash = (Tied) & (HashRef); tie my %h, "My::Package"; tie my $s, "Other::Package"; \%h ~~ $TiedHash; # true \$s ~~ $TiedHash; # false =item C<< StrMatch[`a] >> A string that matches a regular expression: declare "Distance", as StrMatch[ qr{^([0-9]+)\s*(mm|cm|m|km)$} ]; You can optionally provide a type constraint for the array of subexpressions: declare "Distance", as StrMatch[ qr{^([0-9]+)\s*(.+)$}, Tuple[ Int, enum(DistanceUnit => [qw/ mm cm m km /]), ], ]; =item C<< Enum[`a] >> As per MooX::Types::MooseLike::Base: has size => (is => "ro", isa => Enum[qw( S M L XL XXL )]); =item C<< OptList >> An arrayref of arrayrefs in the style of L output. =item C<< LaxNum >>, C<< StrictNum >> In Moose 2.09, the C type constraint implementation was changed from being a wrapper around L's C function to a stricter regexp (which disallows things like "-Inf" and "Nan"). Types::Standard provides I implementations. C is measurably faster. The C type constraint is currently an alias for C unless you set the C environment variable to true before loading Types::Standard, in which case it becomes an alias for C. The constant C<< Types::Standard::STRICTNUM >> can be used to check if C is being strict. Most people should probably use C or C. Don't explicitly use C unless you specifically need an attribute which will accept things like "Inf". =back =head2 Coercions None of the types in this type library have any coercions by default. However some standalone coercions may be exported. These can be combined with type constraints using the C<< plus_coercions >> method. =over =item C<< MkOpt >> A coercion from C, C or C to C. Example usage in a Moose attribute: use Types::Standard qw( OptList MkOpt ); has options => ( is => "ro", isa => OptList->plus_coercions( MkOpt ), coerce => 1, ); =item C<< Split[`a] >> Split a string on a regexp. use Types::Standard qw( ArrayRef Str Split ); has name => ( is => "ro", isa => (ArrayRef[Str])->plus_coercions(Split[qr/\s/]), coerce => 1, ); =item C<< Join[`a] >> Join an array of strings with a delimiter. use Types::Standard qw( Str Join ); my $FileLines = Str->plus_coercions(Join["\n"]); has file_contents => ( is => "ro", isa => $FileLines, coerce => 1, ); =back =head2 Constants =over =item C<< Types::Standard::STRICTNUM >> Indicates whether C is an alias for C. (It is usually an alias for C.) =back =begin private =item Stringable =item LazyLoad =end private =head1 BUGS Please report any bugs to L. =head1 SEE ALSO L. L, L, L, L. L, L, L. L provides some type constraints based on XML Schema's data types; this includes constraints for ISO8601-formatted datetimes, integer ranges (e.g. C<< PositiveInteger[maxInclusive=>10] >> and so on. L provides C and C type constraints that were formerly found in Types::Standard. L and L provide replacements for L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. TypeTiny.pm000664001750001750 2473712422772210 16431 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Typespackage Types::TypeTiny; use strict; use warnings; our $AUTHORITY = 'cpan:TOBYINK'; our $VERSION = '1.000005'; use Scalar::Util qw< blessed refaddr weaken >; our @EXPORT_OK = ( __PACKAGE__->type_names, qw/to_TypeTiny/ ); my %cache; sub import { # do the shuffle! no warnings "redefine"; our @ISA = qw( Exporter::Tiny ); require Exporter::Tiny; my $next = \&Exporter::Tiny::import; *import = $next; my $class = shift; my $opts = { ref($_[0]) ? %{+shift} : () }; $opts->{into} ||= scalar(caller); return $class->$next($opts, @_); } sub meta { return $_[0]; } sub type_names { qw( CodeLike StringLike TypeTiny HashLike ArrayLike ); } sub has_type { my %has = map +($_ => 1), shift->type_names; !!$has{ $_[0] }; } sub get_type { my $self = shift; return unless $self->has_type(@_); no strict qw(refs); &{$_[0]}(); } sub coercion_names { qw(); } sub has_coercion { my %has = map +($_ => 1), shift->coercion_names; !!$has{ $_[0] }; } sub get_coercion { my $self = shift; return unless $self->has_coercion(@_); no strict qw(refs); &{$_[0]}(); # uncoverable statement } sub StringLike () { require Type::Tiny; $cache{StringLike} ||= "Type::Tiny"->new( name => "StringLike", constraint => sub { defined($_ ) && !ref($_ ) or Scalar::Util::blessed($_ ) && overload::Method($_ , q[""]) }, inlined => sub { qq/defined($_[1]) && !ref($_[1]) or Scalar::Util::blessed($_[1]) && overload::Method($_[1], q[""])/ }, library => __PACKAGE__, ); } sub HashLike () { require Type::Tiny; $cache{HashLike} ||= "Type::Tiny"->new( name => "HashLike", constraint => sub { ref($_ ) eq q[HASH] or Scalar::Util::blessed($_ ) && overload::Method($_ , q[%{}]) }, inlined => sub { qq/ref($_[1]) eq q[HASH] or Scalar::Util::blessed($_[1]) && overload::Method($_[1], q[\%{}])/ }, library => __PACKAGE__, ); } sub ArrayLike () { require Type::Tiny; $cache{ArrayLike} ||= "Type::Tiny"->new( name => "ArrayLike", constraint => sub { ref($_ ) eq q[ARRAY] or Scalar::Util::blessed($_ ) && overload::Method($_ , q[@{}]) }, inlined => sub { qq/ref($_[1]) eq q[ARRAY] or Scalar::Util::blessed($_[1]) && overload::Method($_[1], q[\@{}])/ }, library => __PACKAGE__, ); } sub CodeLike () { require Type::Tiny; $cache{CodeLike} ||= "Type::Tiny"->new( name => "CodeLike", constraint => sub { ref($_ ) eq q[CODE] or Scalar::Util::blessed($_ ) && overload::Method($_ , q[&{}]) }, inlined => sub { qq/ref($_[1]) eq q[CODE] or Scalar::Util::blessed($_[1]) && overload::Method($_[1], q[\&{}])/ }, library => __PACKAGE__, ); } sub TypeTiny () { require Type::Tiny; $cache{TypeTiny} ||= "Type::Tiny"->new( name => "TypeTiny", constraint => sub { Scalar::Util::blessed($_ ) && $_ ->isa(q[Type::Tiny]) }, inlined => sub { my $var = $_[1]; "Scalar::Util::blessed($var) && $var\->isa(q[Type::Tiny])" }, library => __PACKAGE__, ); } my %ttt_cache; sub to_TypeTiny { my $t = $_[0]; return $t unless (my $ref = ref $t); return $t if $ref =~ /^Type::Tiny\b/; return $ttt_cache{ refaddr($t) } if $ttt_cache{ refaddr($t) }; if (my $class = blessed $t) { return $t if $class->isa("Type::Tiny"); return _TypeTinyFromMoose($t) if $class->isa("Moose::Meta::TypeConstraint"); return _TypeTinyFromMoose($t) if $class->isa("MooseX::Types::TypeDecorator"); return _TypeTinyFromValidationClass($t) if $class->isa("Validation::Class::Simple"); return _TypeTinyFromValidationClass($t) if $class->isa("Validation::Class"); return _TypeTinyFromGeneric($t) if $t->can("check") && $t->can("get_message"); # i.e. Type::API::Constraint } return _TypeTinyFromCodeRef($t) if $ref eq q(CODE); $t; } sub _TypeTinyFromMoose { my $t = $_[0]; if (ref $t->{"Types::TypeTiny::to_TypeTiny"}) { return $t->{"Types::TypeTiny::to_TypeTiny"}; } if ($t->name ne '__ANON__') { require Types::Standard; my $ts = 'Types::Standard'->get_type($t->name); return $ts if $ts->{_is_core}; } my %opts; $opts{display_name} = $t->name; $opts{constraint} = $t->constraint; $opts{parent} = to_TypeTiny($t->parent) if $t->has_parent; $opts{inlined} = sub { shift; $t->_inline_check(@_) } if $t->can_be_inlined; $opts{message} = sub { $t->get_message($_) } if $t->has_message; $opts{moose_type} = $t; require Type::Tiny; my $new = 'Type::Tiny'->new(%opts); $ttt_cache{ refaddr($t) } = $new; weaken($ttt_cache{ refaddr($t) }); $new->{coercion} = do { require Type::Coercion::FromMoose; 'Type::Coercion::FromMoose'->new( type_constraint => $new, moose_coercion => $t->coercion, ); } if $t->has_coercion; return $new; } sub _TypeTinyFromValidationClass { my $t = $_[0]; require Type::Tiny; require Types::Standard; my %opts = ( parent => Types::Standard::HashRef(), _validation_class => $t, ); if ($t->VERSION >= "7.900048") { $opts{constraint} = sub { $t->params->clear; $t->params->add(%$_); my $f = $t->filtering; $t->filtering('off'); my $r = eval { $t->validate }; $t->filtering($f || 'pre'); return $r; }; $opts{message} = sub { $t->params->clear; $t->params->add(%$_); my $f = $t->filtering; $t->filtering('off'); my $r = (eval { $t->validate } ? "OK" : $t->errors_to_string); $t->filtering($f || 'pre'); return $r; }; } else # need to use hackish method { $opts{constraint} = sub { $t->params->clear; $t->params->add(%$_); no warnings "redefine"; local *Validation::Class::Directive::Filters::execute_filtering = sub { $_[0] }; eval { $t->validate }; }; $opts{message} = sub { $t->params->clear; $t->params->add(%$_); no warnings "redefine"; local *Validation::Class::Directive::Filters::execute_filtering = sub { $_[0] }; eval { $t->validate } ? "OK" : $t->errors_to_string; }; } require Type::Tiny; my $new = "Type::Tiny"->new(%opts); $new->coercion->add_type_coercions( Types::Standard::HashRef() => sub { my %params = %$_; for my $k (keys %params) { delete $params{$_} unless $t->get_fields($k) }; $t->params->clear; $t->params->add(%params); eval { $t->validate }; $t->get_hash; }, ); $ttt_cache{ refaddr($t) } = $new; weaken($ttt_cache{ refaddr($t) }); return $new; } sub _TypeTinyFromGeneric { my $t = $_[0]; # XXX - handle inlining?? my %opts = ( constraint => sub { $t->check(@_ ? @_ : $_) }, message => sub { $t->get_message(@_ ? @_ : $_) }, ); $opts{display_name} = $t->name if $t->can("name"); $opts{coercion} = sub { $t->coerce(@_ ? @_ : $_) } if $t->can("has_coercion") && $t->has_coercion && $t->can("coerce"); require Type::Tiny; my $new = "Type::Tiny"->new(%opts); $ttt_cache{ refaddr($t) } = $new; weaken($ttt_cache{ refaddr($t) }); return $new; } my $QFS; sub _TypeTinyFromCodeRef { my $t = $_[0]; my %opts = ( constraint => sub { return !!eval { $t->($_) }; }, message => sub { local $@; eval { $t->($_); 1 } or do { chomp $@; return $@ if $@ }; return sprintf('%s did not pass type constraint', Type::Tiny::_dd($_)); }, ); if ($QFS ||= "Sub::Quote"->can("quoted_from_sub")) { my (undef, $perlstring, $captures) = @{ $QFS->($t) || [] }; if ($perlstring) { $perlstring = "!!eval{ $perlstring }"; $opts{inlined} = sub { my $var = $_[1]; Sub::Quote::inlinify( $perlstring, $var, $var eq q($_) ? '' : "local \$_ = $var;", 1, ); } if $perlstring && !$captures; } } require Type::Tiny; my $new = "Type::Tiny"->new(%opts); $ttt_cache{ refaddr($t) } = $new; weaken($ttt_cache{ refaddr($t) }); return $new; } 1; __END__ =pod =encoding utf-8 =for stopwords arrayfication hashification =head1 NAME Types::TypeTiny - type constraints used internally by Type::Tiny =head1 STATUS This module is covered by the L. =head1 DESCRIPTION Dogfooding. This isn't a real Type::Library-based type library; that would involve too much circularity. But it exports some type constraints which, while designed for use within Type::Tiny, may be more generally useful. =head2 Types =over =item C<< StringLike >> Accepts strings and objects overloading stringification. =item C<< HashLike >> Accepts hashrefs and objects overloading hashification. =item C<< ArrayLike >> Accepts arrayrefs and objects overloading arrayfication. =item C<< CodeLike >> Accepts coderefs and objects overloading codification. =item C<< TypeTiny >> Accepts blessed L objects. =back =head2 Coercion Functions =over =item C<< to_TypeTiny($constraint) >> Promotes (or "demotes" if you prefer) a Moose::Meta::TypeConstraint object to a Type::Tiny object. Can also handle L objects. Type constraints built from Validation::Class objects deliberately I field filters when they do constraint checking (and go to great lengths to do so); using filters for coercion only. (The behaviour of C if we don't do that is just too weird!) Can also handle any object providing C and C methods. (This includes L objects.) If the object also provides C and C methods, these will be used too. Can also handle coderefs (but not blessed coderefs or objects overloading C<< &{} >>). Coderefs are expected to return true iff C<< $_ >> passes the constraint. If C<< $_ >> fails the type constraint, they may either return false, or die with a helpful error message. =back =head2 Methods These are implemented so that C<< Types::TypeTiny->meta->get_type($foo) >> works, for rough compatibility with a real L type library. =over =item C<< meta >> =item C<< type_names >> =item C<< get_type($name) >> =item C<< has_type($name) >> =item C<< coercion_names >> =item C<< get_coercion($name) >> =item C<< has_coercion($name) >> =back =head1 BUGS Please report any bugs to L. =head1 SEE ALSO L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 73f51e2d.pl000664001750001750 115012422772210 16735 0ustar00taitai000000000000Type-Tiny-1.000005/t/40-regression=pod =encoding utf-8 =head1 PURPOSE Helper file for C<< 73f51e2d.t >>. =head1 AUTHOR Graham Knop Ehaarg@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Graham Knop. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use threads; use strict; use warnings; use Type::Tiny; my $int = Type::Tiny->new( name => "Integer", constraint => sub { /^(?:-?[1-9][0-9]*|0)$|/ }, message => sub { "$_ isn't an integer" }, ); threads->create(sub { my $type = $int; 1; })->join; 73f51e2d.t000664001750001750 124212422772210 16567 0ustar00taitai000000000000Type-Tiny-1.000005/t/40-regression=pod =encoding utf-8 =head1 PURPOSE Possible issue causing segfaults on threaded Perl 5.18.x. =head1 AUTHOR Graham Knop Ehaarg@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Graham Knop. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; use Config; BEGIN { plan skip_all => "your perl does not support ithreads" unless $Config{useithreads}; }; (my $script = __FILE__) =~ s/t\z/pl/; for (1..100) { my $out = system $^X, (map {; '-I', $_ } @INC), $script; is($out, 0); } done_testing; gh1.t000664001750001750 153412422772210 16112 0ustar00taitai000000000000Type-Tiny-1.000005/t/40-regression=pod =encoding utf-8 =head1 PURPOSE Test that subtypes of Type::Tiny::Class work. =head1 SEE ALSO L, L. =head1 AUTHOR Richard Simões Ersimoes@cpan.orgE. (Minor changes by Toby Inkster Etobyink@cpan.orgE.) =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Richard Simões. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; use Test::TypeTiny; use Type::Utils; use Math::BigFloat; my $pc = declare as class_type({ class => 'Math::BigFloat' }), where { 1 }; my $value = Math::BigFloat->new(0.5); ok $pc->($value); should_pass($value, $pc); should_fail(0.5, $pc); done_testing; rt85911.t000664001750001750 220112422772210 16460 0ustar00taitai000000000000Type-Tiny-1.000005/t/40-regression=pod =encoding utf-8 =head1 PURPOSE Test L with deep Dict coercion. =head1 SEE ALSO L. =head1 AUTHOR Diab Jerius Edjerius@cpan.orgE. (Minor changes by Toby Inkster Etobyink@cpan.orgE.) =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Diab Jerius. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; BEGIN { package MyTypes; use Type::Library -base, -declare => qw[ StrList ]; use Type::Utils; use Types::Standard qw[ ArrayRef Str ]; declare StrList, as ArrayRef[Str]; coerce StrList, from Str, via { [$_] }; } use Type::Params qw[ compile ]; use Types::Standard qw[ Dict slurpy Optional ]; sub foo { my $check = compile( slurpy Dict [ foo => MyTypes::StrList ] ); return [ $check->( @_ ) ]; } sub bar { my $check = compile( MyTypes::StrList ); return [ $check->( @_ ) ]; } is_deeply( bar( 'b' ), [ ["b"] ], ); is_deeply( foo( foo => 'a' ), [ { foo=>["a"] } ], ); done_testing; rt86004.t000664001750001750 511412422772210 16460 0ustar00taitai000000000000Type-Tiny-1.000005/t/40-regression=pod =encoding utf-8 =head1 PURPOSE Test L with more complex Dict coercion. =head1 SEE ALSO L. =head1 AUTHOR Diab Jerius Edjerius@cpan.orgE. (Minor changes by Toby Inkster Etobyink@cpan.orgE.) =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Diab Jerius. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; BEGIN { package Types; use Type::Library -base, -declare => qw[ StrList ]; use Type::Utils; use Types::Standard qw[ ArrayRef Str ]; declare StrList, as ArrayRef [Str]; coerce StrList, from Str, q { [$_] }; }; use Test::More; use Test::Fatal; use Type::Params qw[ validate compile ]; use Types::Standard -all; sub a { validate( \@_, slurpy Dict [ connect => Optional [Bool], encoding => Optional [Str], hg => Optional [Types::StrList], ] ); } sub b { validate( \@_, slurpy Dict [ connect => Optional [Bool], hg => Optional [Types::StrList], ] ); } sub c { validate( \@_, slurpy Dict [ connect => Optional [Bool], encoding => Optional [Str], hg2 => Optional [Types::StrList->no_coercions->plus_coercions(Types::Standard::Str, sub {[$_]})], ] ); } my $expect = { connect => 1, hg => ['a'], }; my $expect2 = { connect => 1, hg2 => ['a'], }; # 1 { my ( $opts, $e ); $e = exception { ( $opts ) = a( connect => 1, hg => ['a'] ) } and diag $e; is_deeply( $opts, $expect, "StrList ArrayRef" ); } # 2 { my ( $opts, $e ); $e = exception { ( $opts ) = a( connect => 1, hg => 'a' ) } and diag $e; is_deeply( $opts, $expect, "StrList scalar" ); } # 3 { my ( $opts, $e ); $e = exception { ( $opts ) = b( connect => 1, hg => ['a'] ) } and diag $e; is_deeply( $opts, $expect, "StrList ArrayRef" ); } # 4 { my ( $opts, $e ); $e = exception { ( $opts ) = b( connect => 1, hg => 'a' ) } and diag $e; is_deeply( $opts, $expect, "StrList scalar" ); } # 5 { my ( $opts, $e ); $e = exception { ( $opts ) = c( connect => 1, hg2 => ['a'] ) } and diag $e; is_deeply( $opts, $expect2, "StrList ArrayRef - noninline" ); } # 6 { my ( $opts, $e ); $e = exception { ( $opts ) = c( connect => 1, hg2 => 'a' ) } and diag $e; is_deeply( $opts, $expect2, "StrList scalar - noninline" ); } #note compile( # { want_source => 1 }, # slurpy Dict [ # connect => Optional[Bool], # encoding => Optional[Str], # hg => Optional[Types::StrList], # ], #); done_testing; rt86233.t000664001750001750 201212422772210 16456 0ustar00taitai000000000000Type-Tiny-1.000005/t/40-regression=pod =encoding utf-8 =head1 PURPOSE Fix: "Cannot inline type constraint check" error with compile and Dict. =head1 SEE ALSO L. =head1 AUTHOR Vyacheslav Matyukhin Emmcleric@cpan.orgE. (Minor changes by Toby Inkster Etobyink@cpan.orgE.) =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Vyacheslav Matyukhin. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; use Test::Fatal; BEGIN { package Types; use Type::Library -base, -declare => qw[ Login ]; use Type::Utils; use Types::Standard qw[ Str ]; declare Login, as Str, where { /^\w+$/ }; }; use Type::Params qw[ compile ]; use Types::Standard qw[ Dict ]; my $type = Dict[login => Types::Login]; ok not( $type->can_be_inlined ); ok not( $type->coercion->can_be_inlined ); is(exception { compile($type) }, undef); done_testing; rt86239.t000664001750001750 230712422772210 16473 0ustar00taitai000000000000Type-Tiny-1.000005/t/40-regression=pod =encoding utf-8 =head1 PURPOSE Fix: Optional constraints ignored if wrapped in Dict. =head1 SEE ALSO L. =head1 AUTHOR Vyacheslav Matyukhin Emmcleric@cpan.orgE. (Minor changes by Toby Inkster Etobyink@cpan.orgE.) =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Vyacheslav Matyukhin. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; use Test::Fatal; use Type::Params qw(validate compile); use Types::Standard qw(ArrayRef Dict Optional Str); my $i = 0; sub announce { note sprintf("Test %d ########", ++$i) } sub got { note "got: " . join ", ", explain(@_) } sub f { announce(); got validate( \@_, Optional[Str], ); } is exception { f("foo") }, undef; is exception { f() }, undef; like exception { f(["abc"]) }, qr/type constraint/; sub g { announce(); got validate( \@_, Dict[foo => Optional[Str]], ); } is exception { g({ foo => "foo" }) }, undef; is exception { g({}) }, undef; like exception { g({ foo => ["abc"] }) }, qr/type constraint/; done_testing; rt90096-2.t000664001750001750 156412422772210 16632 0ustar00taitai000000000000Type-Tiny-1.000005/t/40-regression=pod =encoding utf-8 =head1 PURPOSE Additional tests related to RT#90096. Make sure that L localizes C<< $_ >>. =head1 SEE ALSO L. =head1 AUTHOR Diab Jerius Edjerius@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Diab Jerius. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; use Type::Params qw[ compile ]; use Types::Standard -all; { my $check = compile( Dict [ a => Num ] ); grep { $_->( { a => 3 } ) } $check; is( ref $check, 'CODE', "check is still code" ); } { my $check = compile( slurpy Dict [ a => Num ] ); grep { $_->( a => 3 ) } $check; is( ref $check, 'CODE', "slurpy check is still code" ); } done_testing; rt90096.t000664001750001750 135612422772210 16472 0ustar00taitai000000000000Type-Tiny-1.000005/t/40-regression=pod =encoding utf-8 =head1 PURPOSE Make sure that L localizes C<< $_ >>. =head1 SEE ALSO L. =head1 AUTHOR Samuel Kaufman Eskaufman@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Samuel Kaufman. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings FATAL=> 'all'; use Test::More tests => 3; use Type::Params qw[ compile ]; use Types::Standard qw[ slurpy Dict Bool ]; my $check = compile slurpy Dict [ with_connection => Bool ]; for (qw[ 1 2 3 ]) { # $_ is read-only in here ok $check->( with_connection => 1 ); } rt92571-2.t000664001750001750 127412422772210 16630 0ustar00taitai000000000000Type-Tiny-1.000005/t/40-regression=pod =encoding utf-8 =head1 PURPOSE Make sure that the weakening of the reference from a Type::Coercion::Union object back to its "owner" type constraint does not break functionality. =head1 SEE ALSO L. =head1 AUTHOR Diab Jerius Edjerius@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Diab Jerius. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings FATAL=> 'all'; use Test::More; use Types::Standard -all; my $sub = (Str | Str)->coercion; is( $sub->('x'), 'x', ); done_testing; rt92571.t000664001750001750 232612422772210 16470 0ustar00taitai000000000000Type-Tiny-1.000005/t/40-regression=pod =encoding utf-8 =head1 PURPOSE Make sure that the weakening of the reference from a Type::Coercion object back to its "owner" type constraint does not break functionality. =head1 SEE ALSO L. =head1 AUTHOR Diab Jerius Edjerius@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Diab Jerius. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings FATAL=> 'all'; use Test::More; use Type::Library -base, -declare => qw[ ArrayRefFromAny ]; use Types::Standard -all; use Type::Utils -all; declare_coercion ArrayRefFromAny, to_type ArrayRef, from Any, via { [$_] } ; my $x = ArrayRef->plus_coercions(ArrayRefFromAny); is_deeply( $x->coerce( ['a'] ), ['a'], ); # types hang around until after the coerce method is run is_deeply( ArrayRef->plus_coercions(ArrayRefFromAny)->coerce( ['a'] ), ['a'], ); # types go away after generation of coercion sub, breaking it my $coerce = ArrayRef->plus_coercions(ArrayRefFromAny)->coercion; is_deeply( $coerce->( ['a'] ), ['a'], ) or diag explain($coerce->( ['a'] )); done_testing; rt92591.t000664001750001750 241112422772210 16465 0ustar00taitai000000000000Type-Tiny-1.000005/t/40-regression=pod =encoding utf-8 =head1 PURPOSE Make sure that C works outside type libraries. =head1 SEE ALSO L. =head1 AUTHOR Diab Jerius Edjerius@cpan.orgE. Some additions by Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Diab Jerius. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings FATAL=> 'all'; use Test::More; { package Local::TypeLib; use Type::Library -base; use Types::Standard -all; use Type::Utils -all; my $foo = declare_coercion to_type ArrayRef, from Any, via { [$_] }; ::is( $foo->type_constraint, 'ArrayRef', "Type library, coercion target", ); ::is( $foo->type_coercion_map->[0], 'Any', "Type library, coercion type map", ); } { package Local::NotTypeLib; use Types::Standard -all; use Type::Utils -all; my $foo = declare_coercion to_type ArrayRef, from Any, via { [$_] }; ::is( $foo->type_constraint, 'ArrayRef', "Not type library, coercion target", ); ::is( $foo->type_coercion_map->[0], 'Any', "Not type library, coercion type map", ); } done_testing; rt94196.t000664001750001750 156512422772210 16501 0ustar00taitai000000000000Type-Tiny-1.000005/t/40-regression=pod =encoding utf-8 =head1 PURPOSE Problematic inlining using C<< $_ >>. =head1 SEE ALSO L. =head1 AUTHOR Diab Jerius Edjerius@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Diab Jerius. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings FATAL=> 'all'; use Test::More; use Test::Fatal; use Type::Params qw( validate ); use Types::Standard qw( -types slurpy ); { package Foo; sub new { bless {}, shift } sub send { } }; my $type = Dict[ encoder => HasMethods ['send'] ]; is( exception { my @params = ( encoder => Foo->new ); validate(\@params, slurpy($type)); }, undef, "slurpy Dict w/ HasMethods", ) or note( $type->inline_check('$_') ); done_testing; rt97684.t000664001750001750 201112422772210 16471 0ustar00taitai000000000000Type-Tiny-1.000005/t/40-regression=pod =encoding utf-8 =head1 PURPOSE The "too few arguments for type constraint check functions" error. =head1 SEE ALSO L. =head1 AUTHOR Diab Jerius Edjerius@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Diab Jerius. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; use Test::Requires 'Devel::Hide'; use Test::Requires { Mouse => '1.0000' }; use Devel::Hide qw(Type::Tiny::XS); { package Local::Class; use Mouse; } { package Local::Types; use Type::Library -base, -declare => qw( Coord ExistingCoord ); use Type::Utils -all; use Types::Standard -all; declare ExistingCoord, as Str, where { 0 }; declare Coord, as Str; } use Types::Standard -all; use Type::Params qw( validate ); validate( [], slurpy Dict[ with => Optional[Local::Types::ExistingCoord] ], ); ok 1; done_testing; rt98113.t000664001750001750 155312422772210 16467 0ustar00taitai000000000000Type-Tiny-1.000005/t/40-regression=pod =encoding utf-8 =head1 PURPOSE Test overload fallback =head1 SEE ALSO L. =head1 DEPENDENCIES Uses the bundled BiggerLib.pm type library. =head1 AUTHOR Dagfinn Ilmari Mannsåker Eilmari@ilmari.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Dagfinn Ilmari Mannsåker This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Fatal; use BiggerLib -types, -coercions; is( exception { no warnings 'numeric'; BigInteger + 42 }, undef, 'Type::Tiny overload fallback works', ); is( exception { BigInteger->coercion eq '1' }, undef, 'Type::Coercion overload fallback works', ); done_testing; ttxs-gh1.t000664001750001750 224412422772210 17111 0ustar00taitai000000000000Type-Tiny-1.000005/t/40-regression=pod =encoding utf-8 =head1 PURPOSE Test that was failing with Type::Tiny::XS prior to 0.009. =head1 AUTHOR Jed Lund Ejandrew@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Jed Lund. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; { package MyTest; use Type::Utils 0.046 -all; use Type::Library 0.046 -base, -declare => qw(TestDictionary SuperClassesList NameSpace); use Types::Standard 0.046 -types; declare NameSpace, as Str, where { $_ =~ /^[A-Za-z:]+$/ }, # inline_as { undef, "$_ =~ /^[A-Za-z:]+\$/" }, message { "-$_- does not match: " . qr/^[A-Za-z:]+$/ }; declare SuperClassesList, as ArrayRef[ ClassName ], # inline_as { undef, "\@{$_} > 0" }, where { scalar( @$_ ) > 0 }; declare TestDictionary, as Dict[ package => Optional[ NameSpace ], superclasses => Optional[ SuperClassesList ], ]; } ok( MyTest::TestDictionary->check( { package => 'My::Package' } ), "Test TestDictionary" ); #diag MyTest::TestDictionary->inline_check('$dict'); done_testing; BiggerLib.pm000664001750001750 344312422772210 15600 0ustar00taitai000000000000Type-Tiny-1.000005/t/lib=pod =encoding utf-8 =head1 PURPOSE Type library used in several test cases. Defines types C, C and C. Defines classes C and C along with correponding C and C class type constraints; defines role C and the C role type constraint. Library extends DemoLib.pm. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut package BiggerLib; use strict; use warnings; use Type::Utils qw(:all); use Type::Library -base; extends "DemoLib"; extends "Types::Standard"; declare "SmallInteger", as "Integer", where { no warnings; $_ < 10 } message { no warnings; "$_ is too big" }; declare "BigInteger", as "Integer", where { no warnings; $_ >= 10 }; { package Quux; our $VERSION = 1; } role_type "DoesQuux", { role => "Quux" }; { package Foo::Bar; sub new { my $c = shift; bless {@_}, $c } sub foo { 1 } sub bar { 2 } } class_type "FooBar", { class => "Foo::Bar" }; { package Foo::Baz; our @ISA = "Foo::Bar"; sub DOES { return 1 if $_[1] eq 'Quux'; $_[0]->isa($_[0]); } sub foo { 3 } sub baz { 4 } } class_type "Foo::Baz"; duck_type "CanFooBar", [qw/ foo bar /]; duck_type "CanFooBaz", [qw/ foo baz /]; coerce "SmallInteger", from BigInteger => via { abs($_) % 10 }, from ArrayRef => via { 1 }; coerce "BigInteger", from SmallInteger => via { abs($_) + 10 }, from ArrayRef => via { 100 }; declare_coercion "ArrayRefFromAny", to_type "ArrayRef", from "Any", q { [$_] }; declare_coercion "ArrayRefFromPiped", to_type "ArrayRef", from "Str", q { [split /\\|/] }; 1; DemoLib.pm000664001750001750 143612422772210 15265 0ustar00taitai000000000000Type-Tiny-1.000005/t/lib=pod =encoding utf-8 =head1 PURPOSE Type library used in several test cases. Defines types C, C and C. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut package DemoLib; use strict; use warnings; use Scalar::Util "looks_like_number"; use Type::Utils; use Type::Library -base; declare "String", where { not ref $_ } message { "is not a string" }; declare "Number", as "String", where { looks_like_number $_ }, message { "'$_' doesn't look like a number" }; declare "Integer", as "Number", where { $_ eq int($_) }; 1; Perl56Compat.pm000664001750001750 332012422772210 20546 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Devel/TypeTinypackage Devel::TypeTiny::Perl56Compat; use 5.006; use strict; use warnings; our $AUTHORITY = 'cpan:TOBYINK'; our $VERSION = '1.000005'; #### B doesn't provide perlstring() in 5.6. Monkey patch it. use B (); unless (exists &B::perlstring) { my $d; *B::perlstring = sub { no warnings 'uninitialized'; require Data::Dumper; $d ||= 'Data::Dumper'->new([])->Indent(0)->Purity(0)->Pad('')->Useqq(1)->Terse(1)->Freezer('')->Toaster(''); my $perlstring = $d->Values([''.shift])->Dump; ($perlstring =~ /^"/) ? $perlstring : qq["$perlstring"]; }; } push @B::EXPORT_OK, 'perlstring'; #### Done! 5.6; __END__ =pod =encoding utf-8 =for stopwords pragmas =head1 NAME Devel::TypeTiny::Perl56Compat - shims to allow Type::Tiny to run on Perl 5.6.x =head1 STATUS This module is considered part of Type-Tiny's internals. It is not covered by the L. =head1 DESCRIPTION This is not considered part of Type::Tiny's public API. Currently this module just has one job: it patches L to export a C function, as this was only added in Perl 5.8.0. =head1 BUGS Please report any bugs to L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. Perl58Compat.pm000664001750001750 272512422772210 20560 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Devel/TypeTinypackage Devel::TypeTiny::Perl58Compat; use 5.006; use strict; use warnings; our $AUTHORITY = 'cpan:TOBYINK'; our $VERSION = '1.000005'; #### re doesn't provide is_regexp in Perl < 5.10 eval 'require re'; unless (exists &re::is_regexp) { require B; *re::is_regexp = sub { eval { B::svref_2object($_[0])->MAGIC->TYPE eq 'r' }; }; } #### Done! 5.6; __END__ =pod =encoding utf-8 =for stopwords pragmas =head1 NAME Devel::TypeTiny::Perl58Compat - shims to allow Type::Tiny to run on Perl 5.8.x =head1 STATUS This module is considered part of Type-Tiny's internals. It is not covered by the L. =head1 DESCRIPTION This is not considered part of Type::Tiny's public API. Currently this module just has one job: it patches L to provide a C function, as this was only added in Perl 5.9.5. =head1 BUGS Please report any bugs to L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. Assertion.pm000664001750001750 1056612422772210 20360 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Error/TypeTinypackage Error::TypeTiny::Assertion; use 5.006001; use strict; use warnings; BEGIN { if ($] < 5.008) { require Devel::TypeTiny::Perl56Compat }; } BEGIN { $Error::TypeTiny::Assertion::AUTHORITY = 'cpan:TOBYINK'; $Error::TypeTiny::Assertion::VERSION = '1.000005'; } require Error::TypeTiny; our @ISA = 'Error::TypeTiny'; sub type { $_[0]{type} }; sub value { $_[0]{value} }; sub varname { $_[0]{varname} ||= '$_' }; sub attribute_step { $_[0]{attribute_step} }; sub attribute_name { $_[0]{attribute_name} }; sub has_type { defined $_[0]{type} }; # sic sub has_attribute_step { exists $_[0]{attribute_step} }; sub has_attribute_name { exists $_[0]{attribute_name} }; sub new { my $class = shift; my $self = $class->SUPER::new(@_); if (ref $Method::Generate::Accessor::CurrentAttribute) { require B; my %d = %{$Method::Generate::Accessor::CurrentAttribute}; $self->{attribute_name} = $d{name} if defined $d{name}; $self->{attribute_step} = $d{step} if defined $d{step}; if (defined $d{init_arg}) { $self->{varname} = sprintf('$args->{%s}', B::perlstring($d{init_arg})); } elsif (defined $d{name}) { $self->{varname} = sprintf('$self->{%s}', B::perlstring($d{name})); } } return $self; } sub message { my $e = shift; $e->varname eq '$_' ? $e->SUPER::message : sprintf('%s (in %s)', $e->SUPER::message, $e->varname); } sub _build_message { my $e = shift; $e->has_type ? sprintf('%s did not pass type constraint "%s"', Type::Tiny::_dd($e->value), $e->type) : sprintf('%s did not pass type constraint', Type::Tiny::_dd($e->value)) } *to_string = sub { my $e = shift; my $msg = $e->message; my $c = $e->context; $msg .= sprintf(" at %s line %s", $c->{file}||'file?', $c->{line}||'NaN') if $c; my $explain = $e->explain; return $msg unless @{ $explain || [] }; $msg .= "\n"; for my $line (@$explain) { $msg .= " $line\n"; } return $msg; } if $] >= 5.008; sub explain { my $e = shift; return undef unless $e->has_type; $e->type->validate_explain($e->value, $e->varname); } 1; __END__ =pod =encoding utf-8 =head1 NAME Error::TypeTiny::Assertion - exception when a value fails a type constraint =head1 STATUS This module is covered by the L. =head1 DESCRIPTION This exception is thrown when a value fails a type constraint assertion. This package inherits from L; see that for most documentation. Major differences are listed below: =head2 Attributes =over =item C The type constraint that was checked against. Weakened links are involved, so this may end up being C. =item C The value that was tested. =item C The name of the variable that was checked, if known. Defaults to C<< '$_' >>. =item C If this exception was thrown as the result of an isa check or a failed coercion for a Moo attribute, then this will tell you which attribute (if your Moo is new enough). (Hopefully one day this will support other OO frameworks.) =item C If this exception was thrown as the result of an isa check or a failed coercion for a Moo attribute, then this will contain either C<< "isa check" >> or C<< "coercion" >> to indicate which went wrong (if your Moo is new enough). (Hopefully one day this will support other OO frameworks.) =back =head2 Methods =over =item C, C, C Predicate methods. =item C Overridden to add C to the message if defined. =item C Attempts to explain why the value did not pass the type constraint. Returns an arrayref of strings providing step-by-step reasoning; or returns undef if no explanation is possible. =back =head1 BUGS Please report any bugs to L. =head1 SEE ALSO L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. Compilation.pm000664001750001750 350512422772210 20642 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Error/TypeTinypackage Error::TypeTiny::Compilation; use 5.006001; use strict; use warnings; BEGIN { $Error::TypeTiny::Compilation::AUTHORITY = 'cpan:TOBYINK'; $Error::TypeTiny::Compilation::VERSION = '1.000005'; } require Error::TypeTiny; our @ISA = 'Error::TypeTiny'; sub code { $_[0]{code} }; sub environment { $_[0]{environment} ||= {} }; sub errstr { $_[0]{errstr} }; sub _build_message { my $self = shift; sprintf("Failed to compile source because: %s", $self->errstr); } 1; __END__ =pod =encoding utf-8 =head1 NAME Error::TypeTiny::Compilation - exception for Eval::TypeTiny =head1 STATUS This module is covered by the L. =head1 DESCRIPTION Thrown when compiling a closure fails. Common causes are problems with inlined type constraints, and syntax errors when coercions are given as strings of Perl code. This package inherits from L; see that for most documentation. Major differences are listed below: =head2 Attributes =over =item C The Perl source code being compiled. =item C Hashref of variables being closed over. =item C Error message from Perl compiler. =back =head1 BUGS Please report any bugs to L. =head1 SEE ALSO L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. WrongNumberOfParameters.pm000664001750001750 503012422772210 23135 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Error/TypeTinypackage Error::TypeTiny::WrongNumberOfParameters; use 5.006001; use strict; use warnings; BEGIN { $Error::TypeTiny::WrongNumberOfParameters::AUTHORITY = 'cpan:TOBYINK'; $Error::TypeTiny::WrongNumberOfParameters::VERSION = '1.000005'; } require Error::TypeTiny; our @ISA = 'Error::TypeTiny'; sub minimum { $_[0]{minimum} }; sub maximum { $_[0]{maximum} }; sub got { $_[0]{got} }; sub has_minimum { exists $_[0]{minimum} }; sub has_maximum { exists $_[0]{maximum} }; sub _build_message { my $e = shift; if ($e->has_minimum and $e->has_maximum and $e->minimum == $e->maximum) { return sprintf( "Wrong number of parameters; got %d; expected %d", $e->got, $e->minimum, ); } elsif ($e->has_minimum and $e->has_maximum and $e->minimum < $e->maximum) { return sprintf( "Wrong number of parameters; got %d; expected %d to %d", $e->got, $e->minimum, $e->maximum, ); } elsif ($e->has_minimum) { return sprintf( "Wrong number of parameters; got %d; expected at least %d", $e->got, $e->minimum, ); } else { return sprintf( "Wrong number of parameters; got %d", $e->got, ); } } 1; __END__ =pod =encoding utf-8 =head1 NAME Error::TypeTiny::WrongNumberOfParameters - exception for Type::Params =head1 STATUS This module is covered by the L. =head1 DESCRIPTION Thrown when a Type::Params compiled check is called with the wrong number of parameters. This package inherits from L; see that for most documentation. Major differences are listed below: =head2 Attributes =over =item C The minimum expected number of parameters. =item C The maximum expected number of parameters. =item C The number of parameters actually passed to the compiled check. =back =head2 Methods =over =item C, C Predicate methods. =back =head1 BUGS Please report any bugs to L. =head1 SEE ALSO L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. TypeTiny.pm000664001750001750 366112422772210 17627 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Reply/Pluginpackage Reply::Plugin::TypeTiny; use strict; use warnings; BEGIN { $Reply::Plugin::TypeTiny::AUTHORITY = 'cpan:TOBYINK'; $Reply::Plugin::TypeTiny::VERSION = '1.000005'; }; require Reply::Plugin; our @ISA = 'Reply::Plugin'; use Scalar::Util qw(blessed); use Term::ANSIColor; sub mangle_error { my $self = shift; my ($err) = @_; if (blessed $err and $err->isa("Error::TypeTiny::Assertion")) { my $explain = $err->explain; if ($explain) { print color("cyan"); print "Error::TypeTiny::Assertion explain:\n"; $self->_explanation($explain, ""); local $| = 1; print "\n"; print color("reset"); } } return @_; } sub _explanation { my $self = shift; my ($ex, $indent) = @_; for my $line (@$ex) { if (ref($line) eq q(ARRAY)) { print "$indent * Explain:\n"; $self->_explanation($line, "$indent "); } else { print "$indent * $line\n"; } } } 1; __END__ =pod =encoding utf-8 =head1 NAME Reply::Plugin::TypeTiny - improved type constraint exceptions in Reply =head1 STATUS This module is not covered by the L. =head1 DESCRIPTION This is a small plugin to improve error messages in L. Not massively tested. =begin trustme =item mangle_error =end trustme =head1 BUGS Please report any bugs to L. =head1 SEE ALSO L, L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. FromMoose.pm000664001750001750 510112422772210 20070 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Type/Coercionpackage Type::Coercion::FromMoose; use 5.006001; use strict; use warnings; BEGIN { $Type::Coercion::FromMoose::AUTHORITY = 'cpan:TOBYINK'; $Type::Coercion::FromMoose::VERSION = '1.000005'; } use Scalar::Util qw< blessed >; use Types::TypeTiny (); sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak } require Type::Coercion; our @ISA = 'Type::Coercion'; sub type_coercion_map { my $self = shift; my @from; if ($self->type_constraint) { my $moose = $self->type_constraint->{moose_type}; @from = @{ $moose->coercion->type_coercion_map } if $moose && $moose->has_coercion; } else { _croak "The type constraint attached to this coercion has been garbage collected... PANIC"; } my @return; while (@from) { my ($type, $code) = splice(@from, 0, 2); $type = Moose::Util::TypeConstraints::find_type_constraint($type) unless ref $type; push @return, Types::TypeTiny::to_TypeTiny($type), $code; } return \@return; } sub add_type_coercions { my $self = shift; _croak "Adding coercions to Type::Coercion::FromMoose not currently supported" if @_; } sub _build_moose_coercion { my $self = shift; if ($self->type_constraint) { my $moose = $self->type_constraint->{moose_type}; return $moose->coercion if $moose && $moose->has_coercion; } $self->SUPER::_build_moose_coercion(@_); } sub can_be_inlined { 0; } 1; __END__ =pod =encoding utf-8 =head1 NAME Type::Coercion::FromMoose - a set of coercions borrowed from Moose =head1 STATUS This module is considered part of Type-Tiny's internals. It is not covered by the L. =head1 DESCRIPTION This package inherits from L; see that for most documentation. The major differences are that C always throws an exception, and the C is automatically populated from Moose. This is mostly for internal purposes. =head1 BUGS Please report any bugs to L. =head1 SEE ALSO L. L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. Union.pm000664001750001750 556412422772210 17267 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Type/Coercionpackage Type::Coercion::Union; use 5.006001; use strict; use warnings; BEGIN { $Type::Coercion::Union::AUTHORITY = 'cpan:TOBYINK'; $Type::Coercion::Union::VERSION = '1.000005'; } use Scalar::Util qw< blessed >; use Types::TypeTiny (); sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak } require Type::Coercion; our @ISA = 'Type::Coercion'; sub _preserve_type_constraint { my $self = shift; $self->{_union_of} = $self->{type_constraint}->type_constraints if $self->{type_constraint}; } sub _maybe_restore_type_constraint { my $self = shift; if ( my $union = $self->{_union_of} ) { return Type::Tiny::Union->new(type_constraints => $union); } return; } sub type_coercion_map { my $self = shift; Types::TypeTiny::TypeTiny->assert_valid(my $type = $self->type_constraint); $type->isa('Type::Tiny::Union') or _croak "Type::Coercion::Union must be used in conjunction with Type::Tiny::Union"; my @c; for my $tc (@$type) { next unless $tc->has_coercion; push @c, @{$tc->coercion->type_coercion_map}; } return \@c; } sub add_type_coercions { my $self = shift; _croak "Adding coercions to Type::Coercion::Union not currently supported" if @_; } sub _build_moose_coercion { my $self = shift; my %options = (); $options{type_constraint} = $self->type_constraint if $self->has_type_constraint; require Moose::Meta::TypeCoercion::Union; my $r = "Moose::Meta::TypeCoercion::Union"->new(%options); return $r; } sub can_be_inlined { my $self = shift; Types::TypeTiny::TypeTiny->assert_valid(my $type = $self->type_constraint); for my $tc (@$type) { next unless $tc->has_coercion; return !!0 unless $tc->coercion->can_be_inlined; } !!1; } 1; __END__ =pod =encoding utf-8 =head1 NAME Type::Coercion::Union - a set of coercions to a union type constraint =head1 STATUS This module is covered by the L. =head1 DESCRIPTION This package inherits from L; see that for most documentation. The major differences are that C always throws an exception, and the C is automatically populated from the child constraints of the union type constraint. =head1 BUGS Please report any bugs to L. =head1 SEE ALSO L. L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. Class.pm000664001750001750 1777112422772210 16451 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Type/Tinypackage Type::Tiny::Class; use 5.006001; use strict; use warnings; BEGIN { if ($] < 5.008) { require Devel::TypeTiny::Perl56Compat }; } BEGIN { $Type::Tiny::Class::AUTHORITY = 'cpan:TOBYINK'; $Type::Tiny::Class::VERSION = '1.000005'; } use Scalar::Util qw< blessed >; sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak } use Type::Tiny (); our @ISA = 'Type::Tiny'; sub new { my $proto = shift; return $proto->class->new(@_) if blessed $proto; # DWIM my %opts = (@_==1) ? %{$_[0]} : @_; _croak "Class type constraints cannot have a parent constraint passed to the constructor" if exists $opts{parent}; _croak "Class type constraints cannot have a constraint coderef passed to the constructor" if exists $opts{constraint}; _croak "Class type constraints cannot have a inlining coderef passed to the constructor" if exists $opts{inlined}; _croak "Need to supply class name" unless exists $opts{class}; if (Type::Tiny::_USE_XS) { my $xsub = Type::Tiny::XS::get_coderef_for("InstanceOf[".$opts{class}."]"); $opts{compiled_type_constraint} = $xsub if $xsub; } elsif (Type::Tiny::_USE_MOUSE) { require Mouse::Util::TypeConstraints; my $maker = "Mouse::Util::TypeConstraints"->can("generate_isa_predicate_for"); $opts{compiled_type_constraint} = $maker->($opts{class}) if $maker; } return $proto->SUPER::new(%opts); } sub class { $_[0]{class} } sub inlined { $_[0]{inlined} ||= $_[0]->_build_inlined } sub has_inlined { !!1 } sub _build_constraint { my $self = shift; my $class = $self->class; return sub { blessed($_) and $_->isa($class) }; } sub _build_inlined { my $self = shift; my $class = $self->class; if (Type::Tiny::_USE_XS) { my $xsub = Type::Tiny::XS::get_subname_for("InstanceOf[$class]"); return sub { my $var = $_[1]; "$xsub\($var\)" } if $xsub; } sub { my $var = $_[1]; qq{Scalar::Util::blessed($var) and $var->isa(q[$class])}; }; } sub _build_default_message { no warnings 'uninitialized'; my $self = shift; my $c = $self->class; return sub { sprintf '%s did not pass type constraint (not isa %s)', Type::Tiny::_dd($_[0]), $c } if $self->is_anon; my $name = "$self"; return sub { sprintf '%s did not pass type constraint "%s" (not isa %s)', Type::Tiny::_dd($_[0]), $name, $c }; } sub _instantiate_moose_type { my $self = shift; my %opts = @_; delete $opts{parent}; delete $opts{constraint}; delete $opts{inlined}; require Moose::Meta::TypeConstraint::Class; return "Moose::Meta::TypeConstraint::Class"->new(%opts, class => $self->class); } sub plus_constructors { my $self = shift; unless (@_) { require Types::Standard; push @_, Types::Standard::HashRef(), "new"; } require B; require Types::TypeTiny; my $class = B::perlstring($self->class); my @r; while (@_) { my $source = shift; Types::TypeTiny::TypeTiny->check($source) or _croak "Expected type constraint; got $source"; my $constructor = shift; Types::TypeTiny::StringLike->check($constructor) or _croak "Expected string; got $constructor"; push @r, $source, sprintf('%s->%s($_)', $class, $constructor); } return $self->plus_coercions(\@r); } sub has_parent { !!1; } sub parent { $_[0]{parent} ||= $_[0]->_build_parent; } sub _build_parent { my $self = shift; my $class = $self->class; # Some classes (I'm looking at you, Math::BigFloat) include a class in # their @ISA to inherit methods, but then override isa() to return false, # so that they don't appear to be a subclass. # # In these cases, we don't want to list the parent class as a parent # type constraint. # my @isa = grep $class->isa($_), do { no strict "refs"; no warnings; @{"$class\::ISA"} }; if (@isa == 0) { require Types::Standard; return Types::Standard::Object(); } if (@isa == 1) { return ref($self)->new(class => $isa[0]) } require Type::Tiny::Intersection; "Type::Tiny::Intersection"->new( type_constraints => [ map ref($self)->new(class => $_), @isa ], ); } *__get_linear_isa_dfs = eval { require mro } ? \&mro::get_linear_isa : sub { no strict 'refs'; my $classname = shift; my @lin = ($classname); my %stored; foreach my $parent (@{"$classname\::ISA"}) { my $plin = __get_linear_isa_dfs($parent); foreach (@$plin) { next if exists $stored{$_}; push(@lin, $_); $stored{$_} = 1; } } return \@lin; }; sub validate_explain { my $self = shift; my ($value, $varname) = @_; $varname = '$_' unless defined $varname; return undef if $self->check($value); return ["Not a blessed reference"] unless blessed($value); my @isa = @{ __get_linear_isa_dfs(ref $value) }; my $display_var = $varname eq q{$_} ? '' : sprintf(' (in %s)', $varname); require Type::Utils; return [ sprintf('"%s" requires that the reference isa %s', $self, $self->class), sprintf('The reference%s isa %s', $display_var, Type::Utils::english_list(@isa)), ]; } 1; __END__ =pod =encoding utf-8 =head1 NAME Type::Tiny::Class - type constraints based on the "isa" method =head1 STATUS This module is covered by the L. =head1 DESCRIPTION Type constraints of the general form C<< { $_->isa("Some::Class") } >>. This package inherits from L; see that for most documentation. Major differences are listed below: =head2 Constructor =over =item C When the constructor is called on an I of Type::Tiny::Class, it passes the call through to the constructor of the class for the constraint. So for example: my $type = Type::Tiny::Class->new(class => "Foo::Bar"); my $obj = $type->new(hello => "World"); say ref($obj); # prints "Foo::Bar" This little bit of DWIM was borrowed from L, but Type::Tiny doesn't take the idea quite as far. =back =head2 Attributes =over =item C The class for the constraint. =item C Unlike Type::Tiny, you I pass a constraint coderef to the constructor. Instead rely on the default. =item C Unlike Type::Tiny, you I pass an inlining coderef to the constructor. Instead rely on the default. =item C Parent is automatically calculated, and cannot be passed to the constructor. =back =head2 Methods =over =item C<< plus_constructors($source, $method_name) >> Much like C but adds coercions that go via a constructor. (In fact, this is implemented as a wrapper for C.) Example: package MyApp::Minion; use Moose; extends "MyApp::Person"; use Types::Standard qw( HashRef Str ); use Type::Utils qw( class_type ); my $Person = class_type({ class => "MyApp::Person" }); has boss => ( is => "ro", isa => $Person->plus_constructors( HashRef, "new", Str, "_new_from_name", ), coerce => 1, ); package main; MyApp::Minion->new( ..., boss => "Bob", ## via MyApp::Person->_new_from_name ); MyApp::Minion->new( ..., boss => { name => "Bob" }, ## via MyApp::Person->new ); Because coercing C via constructor is a common desire, if you call C with no arguments at all, this is the default. $classtype->plus_constructors(Types::Standard::HashRef, "new") $classtype->plus_constructors() ## identical to above This is handy for Moose/Mouse/Moo-based classes. =back =head1 BUGS Please report any bugs to L. =head1 SEE ALSO L. L. L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. Duck.pm000664001750001750 1127312422772210 16261 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Type/Tinypackage Type::Tiny::Duck; use 5.006001; use strict; use warnings; BEGIN { $Type::Tiny::Duck::AUTHORITY = 'cpan:TOBYINK'; $Type::Tiny::Duck::VERSION = '1.000005'; } use Scalar::Util qw< blessed >; sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak } use Type::Tiny (); our @ISA = 'Type::Tiny'; sub new { my $proto = shift; my %opts = (@_==1) ? %{$_[0]} : @_; _croak "Duck type constraints cannot have a parent constraint passed to the constructor" if exists $opts{parent}; _croak "Duck type constraints cannot have a constraint coderef passed to the constructor" if exists $opts{constraint}; _croak "Duck type constraints cannot have a inlining coderef passed to the constructor" if exists $opts{inlined}; _croak "Need to supply list of methods" unless exists $opts{methods}; $opts{methods} = [$opts{methods}] unless ref $opts{methods}; if (Type::Tiny::_USE_XS) { my $methods = join ",", sort(@{$opts{methods}}); my $xsub = Type::Tiny::XS::get_coderef_for("HasMethods[$methods]"); $opts{compiled_type_constraint} = $xsub if $xsub; } elsif (Type::Tiny::_USE_MOUSE) { require Mouse::Util::TypeConstraints; my $maker = "Mouse::Util::TypeConstraints"->can("generate_can_predicate_for"); $opts{compiled_type_constraint} = $maker->($opts{methods}) if $maker; } return $proto->SUPER::new(%opts); } sub methods { $_[0]{methods} } sub inlined { $_[0]{inlined} ||= $_[0]->_build_inlined } sub has_inlined { !!1 } sub _build_constraint { my $self = shift; my @methods = @{$self->methods}; return sub { blessed($_[0]) and not grep(!$_[0]->can($_), @methods) }; } sub _build_inlined { my $self = shift; my @methods = @{$self->methods}; if (Type::Tiny::_USE_XS) { my $methods = join ",", sort(@{$self->methods}); my $xsub = Type::Tiny::XS::get_subname_for("HasMethods[$methods]"); return sub { my $var = $_[1]; "$xsub\($var\)" } if $xsub; } sub { my $var = $_[1]; local $" = q{ }; # If $var is $_ or $_->{foo} or $foo{$_} or somesuch, then we # can't use it within the grep expression, so we need to save # it into a temporary variable ($tmp). ($var =~ /\$_/) ? qq{ Scalar::Util::blessed($var) and not do { my \$tmp = $var; grep(!\$tmp->can(\$_), qw/@methods/) } } : qq{ Scalar::Util::blessed($var) and not grep(!$var->can(\$_), qw/@methods/) }; }; } sub _instantiate_moose_type { my $self = shift; my %opts = @_; delete $opts{parent}; delete $opts{constraint}; delete $opts{inlined}; require Moose::Meta::TypeConstraint::DuckType; return "Moose::Meta::TypeConstraint::DuckType"->new(%opts, methods => $self->methods); } sub has_parent { !!1; } sub parent { require Types::Standard; Types::Standard::Object(); } sub validate_explain { my $self = shift; my ($value, $varname) = @_; $varname = '$_' unless defined $varname; return undef if $self->check($value); return ["Not a blessed reference"] unless blessed($value); require Type::Utils; return [ sprintf( '"%s" requires that the reference can %s', $self, Type::Utils::english_list(map qq["$_"], @{$self->methods}), ), map sprintf('The reference cannot "%s"', $_), grep !$value->can($_), @{$self->methods} ]; } 1; __END__ =pod =encoding utf-8 =head1 NAME Type::Tiny::Duck - type constraints based on the "can" method =head1 STATUS This module is covered by the L. =head1 DESCRIPTION Type constraints of the general form C<< { $_->can("method") } >>. This package inherits from L; see that for most documentation. Major differences are listed below: =head2 Attributes =over =item C An arrayref of method names. =item C Unlike Type::Tiny, you I pass a constraint coderef to the constructor. Instead rely on the default. =item C Unlike Type::Tiny, you I pass an inlining coderef to the constructor. Instead rely on the default. =item C Parent is always Types::Standard::Object, and cannot be passed to the constructor. =back =head1 BUGS Please report any bugs to L. =head1 SEE ALSO L. L. L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. Enum.pm000664001750001750 1075012422772210 16276 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Type/Tinypackage Type::Tiny::Enum; use 5.006001; use strict; use warnings; BEGIN { $Type::Tiny::Enum::AUTHORITY = 'cpan:TOBYINK'; $Type::Tiny::Enum::VERSION = '1.000005'; } sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak } use overload q[@{}] => 'values'; use Type::Tiny (); our @ISA = 'Type::Tiny'; sub new { my $proto = shift; my %opts = (@_==1) ? %{$_[0]} : @_; _croak "Enum type constraints cannot have a parent constraint passed to the constructor" if exists $opts{parent}; _croak "Enum type constraints cannot have a constraint coderef passed to the constructor" if exists $opts{constraint}; _croak "Enum type constraints cannot have a inlining coderef passed to the constructor" if exists $opts{inlined}; _croak "Need to supply list of values" unless exists $opts{values}; my %tmp = map { $_ => 1 } @{ ref $opts{values} eq "ARRAY" ? $opts{values} : [$opts{values}] }; $opts{values} = [sort keys %tmp]; if (Type::Tiny::_USE_XS and not grep /[^-\w]/, @{$opts{values}}) { my $enum = join ",", @{$opts{values}}; my $xsub = Type::Tiny::XS::get_coderef_for("Enum[$enum]"); $opts{compiled_type_constraint} = $xsub if $xsub; } return $proto->SUPER::new(%opts); } sub values { $_[0]{values} } sub constraint { $_[0]{constraint} ||= $_[0]->_build_constraint } sub _build_display_name { my $self = shift; sprintf("Enum[%s]", join q[,], @$self); } sub _build_constraint { my $self = shift; my $regexp = join "|", map quotemeta, @$self; return sub { defined and m{\A(?:$regexp)\z} }; } sub can_be_inlined { !!1; } sub inline_check { my $self = shift; if (Type::Tiny::_USE_XS) { my $enum = join ",", @{$self->values}; my $xsub = Type::Tiny::XS::get_subname_for("Enum[$enum]"); return "$xsub\($_[0]\)" if $xsub; } my $regexp = join "|", map quotemeta, @$self; $_[0] eq '$_' ? "(defined and !ref and m{\\A(?:$regexp)\\z})" : "(defined($_[0]) and !ref($_[0]) and $_[0] =~ m{\\A(?:$regexp)\\z})"; } sub _instantiate_moose_type { my $self = shift; my %opts = @_; delete $opts{parent}; delete $opts{constraint}; delete $opts{inlined}; require Moose::Meta::TypeConstraint::Enum; return "Moose::Meta::TypeConstraint::Enum"->new(%opts, values => $self->values); } sub has_parent { !!1; } sub parent { require Types::Standard; Types::Standard::Str(); } sub validate_explain { my $self = shift; my ($value, $varname) = @_; $varname = '$_' unless defined $varname; return undef if $self->check($value); require Type::Utils; !defined($value) ? [ sprintf( '"%s" requires that the value is defined', $self, ), ] : @$self < 13 ? [ sprintf( '"%s" requires that the value is equal to %s', $self, Type::Utils::english_list(\"or", map B::perlstring($_), @$self), ), ] : [ sprintf( '"%s" requires that the value is one of an enumerated list of strings', $self, ), ]; } 1; __END__ =pod =encoding utf-8 =head1 NAME Type::Tiny::Enum - string enum type constraints =head1 STATUS This module is covered by the L. =head1 DESCRIPTION Enum type constraints. This package inherits from L; see that for most documentation. Major differences are listed below: =head2 Attributes =over =item C Arrayref of allowable value strings. Non-string values (e.g. objects with overloading) will be stringified in the constructor. =item C Unlike Type::Tiny, you I pass a constraint coderef to the constructor. Instead rely on the default. =item C Unlike Type::Tiny, you I pass an inlining coderef to the constructor. Instead rely on the default. =item C Parent is always Types::Standard::Str, and cannot be passed to the constructor. =back =head2 Overloading =over =item * Arrayrefification calls C. =back =head1 BUGS Please report any bugs to L. =head1 SEE ALSO L. L. L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. Intersection.pm000664001750001750 1215012422772210 20034 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Type/Tinypackage Type::Tiny::Intersection; use 5.006001; use strict; use warnings; BEGIN { $Type::Tiny::Intersection::AUTHORITY = 'cpan:TOBYINK'; $Type::Tiny::Intersection::VERSION = '1.000005'; } use Scalar::Util qw< blessed >; use Types::TypeTiny (); sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak } use overload q[@{}] => sub { $_[0]{type_constraints} ||= [] }; use Type::Tiny (); our @ISA = 'Type::Tiny'; sub new { my $proto = shift; my %opts = (@_==1) ? %{$_[0]} : @_; _croak "Intersection type constraints cannot have a parent constraint" if exists $opts{parent}; _croak "Intersection type constraints cannot have a constraint coderef passed to the constructor" if exists $opts{constraint}; _croak "Intersection type constraints cannot have a inlining coderef passed to the constructor" if exists $opts{inlined}; _croak "Need to supply list of type constraints" unless exists $opts{type_constraints}; $opts{type_constraints} = [ map { $_->isa(__PACKAGE__) ? @$_ : $_ } map Types::TypeTiny::to_TypeTiny($_), @{ ref $opts{type_constraints} eq "ARRAY" ? $opts{type_constraints} : [$opts{type_constraints}] } ]; if (Type::Tiny::_USE_XS) { my @constraints = @{$opts{type_constraints}}; my @known = map { my $known = Type::Tiny::XS::is_known($_->compiled_check); defined($known) ? $known : (); } @constraints; if (@known == @constraints) { my $xsub = Type::Tiny::XS::get_coderef_for( sprintf "AllOf[%s]", join(',', @known) ); $opts{compiled_type_constraint} = $xsub if $xsub; } } return $proto->SUPER::new(%opts); } sub type_constraints { $_[0]{type_constraints} } sub constraint { $_[0]{constraint} ||= $_[0]->_build_constraint } sub _build_display_name { my $self = shift; join q[&], @$self; } sub _build_constraint { my @checks = map $_->compiled_check, @{+shift}; return sub { my $val = $_; $_->($val) || return for @checks; return !!1; } } sub can_be_inlined { my $self = shift; not grep !$_->can_be_inlined, @$self; } sub inline_check { my $self = shift; if (Type::Tiny::_USE_XS and !exists $self->{xs_sub}) { $self->{xs_sub} = undef; my @constraints = @{$self->type_constraints}; my @known = map { my $known = Type::Tiny::XS::is_known($_->compiled_check); defined($known) ? $known : (); } @constraints; if (@known == @constraints) { $self->{xs_sub} = Type::Tiny::XS::get_subname_for( sprintf "AllOf[%s]", join(',', @known) ); } } if (Type::Tiny::_USE_XS and $self->{xs_sub}) { return "$self->{xs_sub}\($_[0]\)"; } sprintf '(%s)', join " and ", map $_->inline_check($_[0]), @$self; } sub has_parent { !!@{ $_[0]{type_constraints} }; } sub parent { $_[0]{type_constraints}[0]; } sub validate_explain { my $self = shift; my ($value, $varname) = @_; $varname = '$_' unless defined $varname; return undef if $self->check($value); require Type::Utils; for my $type (@$self) { my $deep = $type->validate_explain($value, $varname); return [ sprintf( '"%s" requires that the value pass %s', $self, Type::Utils::english_list(map qq["$_"], @$self), ), @$deep, ] if $deep; } # This should never happen... return; # uncoverable statement } 1; __END__ =pod =encoding utf-8 =head1 NAME Type::Tiny::Intersection - intersection type constraints =head1 STATUS This module is covered by the L. =head1 DESCRIPTION Intersection type constraints. This package inherits from L; see that for most documentation. Major differences are listed below: =head2 Attributes =over =item C Arrayref of type constraints. When passed to the constructor, if any of the type constraints in the intersection is itself an intersection type constraint, this is "exploded" into the new intersection. =item C Unlike Type::Tiny, you I pass a constraint coderef to the constructor. Instead rely on the default. =item C Unlike Type::Tiny, you I pass an inlining coderef to the constructor. Instead rely on the default. =item C Unlike Type::Tiny, you I pass an inlining coderef to the constructor. A parent will instead be automatically calculated. (Technically any of the types in the intersection could be treated as a parent type; we choose the first arbitrarily.) =back =head2 Overloading =over =item * Arrayrefification calls C. =back =head1 BUGS Please report any bugs to L. =head1 SEE ALSO L. L. L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. Manual.pod000664001750001750 1426012422772210 16755 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Type/Tiny=pod =encoding utf-8 =head1 NAME Type::Tiny::Manual - an overview of Type::Tiny =head1 SYNOPSIS L is a small class for writing type constraints, inspired by L's type constraint API. It has only one non-core dependency (and even that is simply a module that was previously distributed as part of Type::Tiny but has since been spun off), and can be used with L, L and L (or none of the above). Type::Tiny is bundled with L a framework for organizing type constraints into collections. Also bundled is L, a Moose-inspired library of useful type constraints. L is also provided, to allow very fast checking and coercion of function and method parameters. =head1 SEE ALSO =over =item * L - how to build a type library with Type::Tiny, Type::Library and Type::Utils =item * L - adding coercions to type constraints =item * L - how to use Type::Tiny and Type::Library with Moose =item * L - how to use Type::Tiny and Type::Library with Mouse =item * L - how to use Type::Tiny and Type::Library with Moo =item * L - how to use Type::Tiny and Type::Library with other OO frameworks =item * Type::Tiny and friends don't need to be used within an OO framework. See L for an example that does not. =item * L - coerce and validate arguments to functions and methods. =item * Other modules using Type::Tiny in interesting ways: L, L, L, L... =item * L - squeeze the most out of your CPU. =item * L - the stability policy. =back =head1 DEPENDENCIES Type::Tiny requires at least Perl 5.6.1, though certain Unicode-related features (e.g. non-ASCII type constraint names) may work better in newer versions of Perl. Type::Tiny requires L, a module that was previously bundled in this distribution, but has since been spun off as a separate distribution. Don't worry - it's quick and easy to install. At run-time, Type::Tiny also requires the following modules: L, L, L, L, L, L, L, L and L. All of these come bundled with Perl itself. Prior to Perl 5.8, L and L do not come bundled with Perl and will need installing separately from the CPAN. Certain features require additional modules. Tying a variable to a type constraint (e.g. C<< tie my $count, Int >>) requires L; stack traces on exceptions require L. The L plugin for L requires L (obviously). L may I increase the speed of some of Type::Tiny's compiled coderefs. L is not required, but if available provides a speed boost for some type checks. (Setting the environment variable C to false, or setting C to true will suppress the use of Type::Tiny::XS, even if it is available.) The test suite additionally requires L, L and L. Test::More comes bundled with Perl, but if you are using a version of Perl older than 5.14, you will need to upgrade to at least Test::More version 0.96. Test::Requires and Test::Fatal (plus Try::Tiny which Test::Fatal depends on) are bundled with Type::Tiny in the C directory, so you do not need to install them separately. If using Type::Tiny in conjunction with L, then at least Moo 1.001000 is recommended. If using Type::Tiny with L, then at least Moose 2.0600 is recommended. If using Type::Tiny with L, then at least Mouse 1.00 is recommended. Type::Tiny is mostly untested against older versions of these packages. =head1 TYPE::TINY VERSUS X =head2 Specio Type::Tiny is similar in aim to L. The major differences are =over =item * Type::Tiny is "tiny" (Specio will eventually have fewer dependencies than it currently does, but is unlikely to ever have as few as Type::Tiny); =item * Specio has a somewhat nicer API (better method names; less duplication), and its API is likely to improve further. Type::Tiny's aims at complete compatibility with current versions of Moose and Mouse, so there is a limit to how much I can deviate from the existing APIs of (Moose|Mouse)::Meta::TypeConstraint. =back =head2 MooseX::Types Type::Tiny libraries expose a similar interface to L libraries. In most cases you should be able to rewrite a L library to use Type::Tiny pretty easily. =head2 MooX::Types::MooseLike Type::Tiny is faster and supports coercions. =head2 Scalar::Does L is somewhat of a precursor to Type::Tiny, but has now been rewritten to use Type::Tiny internally. It gives you a C<< does($value, $type) >> function that is roughly equivalent to C<< $type->check($value) >> except that C<< $type >> may be one of a list of pre-defined strings (instead of a Type::Tiny type constraint); or may be a package name in which case it will be assumed to be a role and checked with C<< $value->DOES($type) >>. =head1 BUGS Please report any bugs to L. =head1 SUPPORT B<< IRC: >> support is available through in the I<< #moops >> channel on L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. =cut Role.pm000664001750001750 1003712422772210 16271 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Type/Tinypackage Type::Tiny::Role; use 5.006001; use strict; use warnings; BEGIN { $Type::Tiny::Role::AUTHORITY = 'cpan:TOBYINK'; $Type::Tiny::Role::VERSION = '1.000005'; } use Scalar::Util qw< blessed weaken >; sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak } require Type::Tiny; our @ISA = 'Type::Tiny'; my %cache; sub new { my $proto = shift; my %opts = (@_==1) ? %{$_[0]} : @_; _croak "Role type constraints cannot have a parent constraint passed to the constructor" if exists $opts{parent}; _croak "Role type constraints cannot have a constraint coderef passed to the constructor" if exists $opts{constraint}; _croak "Role type constraints cannot have a inlining coderef passed to the constructor" if exists $opts{inlined}; _croak "Need to supply role name" unless exists $opts{role}; return $proto->SUPER::new(%opts); } sub role { $_[0]{role} } sub inlined { $_[0]{inlined} ||= $_[0]->_build_inlined } sub has_inlined { !!1 } sub _build_constraint { my $self = shift; my $role = $self->role; return sub { blessed($_) and do { my $method = $_->can('DOES')||$_->can('isa'); $_->$method($role) } }; } sub _build_inlined { my $self = shift; my $role = $self->role; sub { my $var = $_[1]; qq{Scalar::Util::blessed($var) and do { my \$method = $var->can('DOES')||$var->can('isa'); $var->\$method(q[$role]) }}; }; } sub _build_default_message { my $self = shift; my $c = $self->role; return sub { sprintf '%s did not pass type constraint (not DOES %s)', Type::Tiny::_dd($_[0]), $c } if $self->is_anon; my $name = "$self"; return sub { sprintf '%s did not pass type constraint "%s" (not DOES %s)', Type::Tiny::_dd($_[0]), $name, $c }; } sub has_parent { !!1; } sub parent { require Types::Standard; Types::Standard::Object(); } sub validate_explain { my $self = shift; my ($value, $varname) = @_; $varname = '$_' unless defined $varname; return undef if $self->check($value); return ["Not a blessed reference"] unless blessed($value); return ["Reference provides no DOES method to check roles"] unless $value->can('DOES'); my $display_var = $varname eq q{$_} ? '' : sprintf(' (in %s)', $varname); return [ sprintf('"%s" requires that the reference does %s', $self, $self->role), sprintf("The reference%s doesn't %s", $display_var, $self->role), ]; } 1; __END__ =pod =encoding utf-8 =head1 NAME Type::Tiny::Role - type constraints based on the "DOES" method =head1 STATUS This module is covered by the L. =head1 DESCRIPTION Type constraints of the general form C<< { $_->DOES("Some::Role") } >>. This package inherits from L; see that for most documentation. Major differences are listed below: =head2 Attributes =over =item C The role for the constraint. Note that this package doesn't subscribe to any particular flavour of roles (L, L, L, L, etc). It simply trusts the object's C method (see L). =item C Unlike Type::Tiny, you I pass a constraint coderef to the constructor. Instead rely on the default. =item C Unlike Type::Tiny, you I pass an inlining coderef to the constructor. Instead rely on the default. =item C Parent is always Types::Standard::Object, and cannot be passed to the constructor. =back =head1 BUGS Please report any bugs to L. =head1 SEE ALSO L. L. L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. Union.pm000664001750001750 1403712422772210 16464 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Type/Tinypackage Type::Tiny::Union; use 5.006001; use strict; use warnings; BEGIN { $Type::Tiny::Union::AUTHORITY = 'cpan:TOBYINK'; $Type::Tiny::Union::VERSION = '1.000005'; } use Scalar::Util qw< blessed >; use Types::TypeTiny (); sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak } use overload q[@{}] => sub { $_[0]{type_constraints} ||= [] }; use Type::Tiny (); our @ISA = 'Type::Tiny'; sub new { my $proto = shift; my %opts = (@_==1) ? %{$_[0]} : @_; _croak "Union type constraints cannot have a parent constraint passed to the constructor" if exists $opts{parent}; _croak "Union type constraints cannot have a constraint coderef passed to the constructor" if exists $opts{constraint}; _croak "Union type constraints cannot have a inlining coderef passed to the constructor" if exists $opts{inlined}; _croak "Need to supply list of type constraints" unless exists $opts{type_constraints}; $opts{type_constraints} = [ map { $_->isa(__PACKAGE__) ? @$_ : $_ } map Types::TypeTiny::to_TypeTiny($_), @{ ref $opts{type_constraints} eq "ARRAY" ? $opts{type_constraints} : [$opts{type_constraints}] } ]; if (Type::Tiny::_USE_XS) { my @constraints = @{$opts{type_constraints}}; my @known = map { my $known = Type::Tiny::XS::is_known($_->compiled_check); defined($known) ? $known : (); } @constraints; if (@known == @constraints) { my $xsub = Type::Tiny::XS::get_coderef_for( sprintf "AnyOf[%s]", join(',', @known) ); $opts{compiled_type_constraint} = $xsub if $xsub; } } my $self = $proto->SUPER::new(%opts); $self->coercion if grep $_->has_coercion, @$self; return $self; } sub type_constraints { $_[0]{type_constraints} } sub constraint { $_[0]{constraint} ||= $_[0]->_build_constraint } sub _build_display_name { my $self = shift; join q[|], @$self; } sub _build_coercion { require Type::Coercion::Union; my $self = shift; return "Type::Coercion::Union"->new(type_constraint => $self); } sub _build_constraint { my @checks = map $_->compiled_check, @{+shift}; return sub { my $val = $_; $_->($val) && return !!1 for @checks; return; } } sub can_be_inlined { my $self = shift; not grep !$_->can_be_inlined, @$self; } sub inline_check { my $self = shift; if (Type::Tiny::_USE_XS and !exists $self->{xs_sub}) { $self->{xs_sub} = undef; my @constraints = @{$self->type_constraints}; my @known = map { my $known = Type::Tiny::XS::is_known($_->compiled_check); defined($known) ? $known : (); } @constraints; if (@known == @constraints) { $self->{xs_sub} = Type::Tiny::XS::get_subname_for( sprintf "AnyOf[%s]", join(',', @known) ); } } if (Type::Tiny::_USE_XS and $self->{xs_sub}) { return "$self->{xs_sub}\($_[0]\)"; } sprintf '(%s)', join " or ", map $_->inline_check($_[0]), @$self; } sub _instantiate_moose_type { my $self = shift; my %opts = @_; delete $opts{parent}; delete $opts{constraint}; delete $opts{inlined}; my @tc = map $_->moose_type, @{$self->type_constraints}; require Moose::Meta::TypeConstraint::Union; return "Moose::Meta::TypeConstraint::Union"->new(%opts, type_constraints => \@tc); } sub has_parent { defined(shift->parent); } sub parent { $_[0]{parent} ||= $_[0]->_build_parent; } sub _build_parent { my $self = shift; my ($first, @rest) = @$self; for my $parent ($first, $first->parents) { return $parent unless grep !$_->is_a_type_of($parent), @rest; } return; } sub find_type_for { my @types = @{+shift}; for my $type (@types) { return $type if $type->check(@_); } return; } sub validate_explain { my $self = shift; my ($value, $varname) = @_; $varname = '$_' unless defined $varname; return undef if $self->check($value); require Type::Utils; return [ sprintf( '"%s" requires that the value pass %s', $self, Type::Utils::english_list(\"or", map qq["$_"], @$self), ), map { $_->get_message($value), map(" $_", @{ $_->validate_explain($value) || []}), } @$self ]; } 1; __END__ =pod =encoding utf-8 =head1 NAME Type::Tiny::Union - union type constraints =head1 STATUS This module is covered by the L. =head1 DESCRIPTION Union type constraints. This package inherits from L; see that for most documentation. Major differences are listed below: =head2 Attributes =over =item C Arrayref of type constraints. When passed to the constructor, if any of the type constraints in the union is itself a union type constraint, this is "exploded" into the new union. =item C Unlike Type::Tiny, you I pass a constraint coderef to the constructor. Instead rely on the default. =item C Unlike Type::Tiny, you I pass an inlining coderef to the constructor. Instead rely on the default. =item C Unlike Type::Tiny, you I pass an inlining coderef to the constructor. A parent will instead be automatically calculated. =item C You probably do not pass this to the constructor. (It's not currently disallowed, as there may be a use for it that I haven't thought of.) The auto-generated default will be a L object. =back =head2 Methods =over =item C<< find_type_for($value) >> Returns the first individual type constraint in the union which C<< $value >> passes. =back =head2 Overloading =over =item * Arrayrefification calls C. =back =head1 BUGS Please report any bugs to L. =head1 SEE ALSO L. L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. _HalfOp.pm000664001750001750 325512422772210 16664 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Type/Tinypackage Type::Tiny::_HalfOp; use 5.006001; use strict; use warnings; BEGIN { $Type::Tiny::_HalfOp::AUTHORITY = 'cpan:TOBYINK'; $Type::Tiny::_HalfOp::VERSION = '1.000005'; } use overload (); sub new { my ($class, $op, $param, $type) = @_; bless { op => $op, param => $param, type => $type, }, $class; } sub complete { my ($self, $type) = @_; my $complete_type = $type->parameterize(@{$self->{param}}); my $method = overload::Method($complete_type, $self->{op}); $complete_type->$method($self->{type}); } 1; __END__ =pod =encoding utf-8 =for stopwords pragmas =head1 NAME Type::Tiny::_HalfOp - half-completed overloaded operation =head1 STATUS This module is considered part of Type-Tiny's internals. It is not covered by the L. =head1 DESCRIPTION This is not considered part of Type::Tiny's public API. It is a class representing a half-completed overloaded operation. =head2 Constructor =over =item C<< new($operation, $param, $type) >> =back =head2 Method =over =item C<< complete($type) >> =back =head1 BUGS Please report any bugs to L. =head1 AUTHOR Graham Knop Ehaarg@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Graham Knop. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. Numeric.pm000664001750001750 1066112422772210 17465 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Types/Commonpackage Types::Common::Numeric; use 5.006001; use strict; use warnings; BEGIN { if ($] < 5.008) { require Devel::TypeTiny::Perl56Compat }; } BEGIN { $Types::Common::Numeric::AUTHORITY = 'cpan:TOBYINK'; $Types::Common::Numeric::VERSION = '1.000005'; } use Type::Library -base, -declare => qw( PositiveNum PositiveOrZeroNum PositiveInt PositiveOrZeroInt NegativeNum NegativeOrZeroNum NegativeInt NegativeOrZeroInt SingleDigit ); use Type::Tiny (); use Types::Standard qw( Num Int ); my $meta = __PACKAGE__->meta; $meta->add_type( name => 'PositiveNum', parent => Num, constraint => sub { $_ > 0 }, inlined => sub { undef, qq($_ > 0) }, message => sub { "Must be a positive number" }, ); $meta->add_type( name => 'PositiveOrZeroNum', parent => Num, constraint => sub { $_ >= 0 }, inlined => sub { undef, qq($_ >= 0) }, message => sub { "Must be a number greater than or equal to zero" }, ); my ($pos_int, $posz_int); if (Type::Tiny::_USE_XS) { $pos_int = Type::Tiny::XS::get_coderef_for('PositiveInt'); $posz_int = Type::Tiny::XS::get_coderef_for('PositiveOrZeroInt'); } $meta->add_type( name => 'PositiveInt', parent => Int, constraint => sub { $_ > 0 }, inlined => sub { if ($pos_int) { my $xsub = Type::Tiny::XS::get_subname_for($_[0]->name); return "$xsub($_[1])" if $xsub; } undef, qq($_ > 0); }, message => sub { "Must be a positive integer" }, $pos_int ? ( compiled_type_constraint => $pos_int ) : (), ); $meta->add_type( name => 'PositiveOrZeroInt', parent => Int, constraint => sub { $_ >= 0 }, inlined => sub { if ($posz_int) { my $xsub = Type::Tiny::XS::get_subname_for($_[0]->name); return "$xsub($_[1])" if $xsub; } undef, qq($_ >= 0); }, message => sub { "Must be an integer greater than or equal to zero" }, $posz_int ? ( compiled_type_constraint => $posz_int ) : (), ); $meta->add_type( name => 'NegativeNum', parent => Num, constraint => sub { $_ < 0 }, inlined => sub { undef, qq($_ < 0) }, message => sub { "Must be a negative number" }, ); $meta->add_type( name => 'NegativeOrZeroNum', parent => Num, constraint => sub { $_ <= 0 }, inlined => sub { undef, qq($_ <= 0) }, message => sub { "Must be a number less than or equal to zero" }, ); $meta->add_type( name => 'NegativeInt', parent => Int, constraint => sub { $_ < 0 }, inlined => sub { undef, qq($_ < 0) }, message => sub { "Must be a negative integer" }, ); $meta->add_type( name => 'NegativeOrZeroInt', parent => Int, constraint => sub { $_ <= 0 }, inlined => sub { undef, qq($_ <= 0) }, message => sub { "Must be an integer less than or equal to zero" }, ); $meta->add_type( name => 'SingleDigit', parent => Int, constraint => sub { $_ >= -9 and $_ <= 9 }, inlined => sub { undef, qq($_ >= -9), qq($_ <= 9) }, message => sub { "Must be a single digit" }, ); __PACKAGE__->meta->make_immutable; 1; __END__ =pod =encoding utf-8 =head1 NAME Types::Common::Numeric - drop-in replacement for MooseX::Types::Common::Numeric =head1 STATUS This module is covered by the L. =head1 DESCRIPTION A drop-in replacement for L. =head2 Types The following types are similar to those described in L. =over =item C =item C =item C =item C =item C =item C =item C =item C =item C =back C interestingly accepts the numbers -9 to -1; not just 0 to 9. =head1 BUGS Please report any bugs to L. =head1 SEE ALSO L, L. L, L, L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. String.pm000664001750001750 1232412422772210 17327 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Types/Commonpackage Types::Common::String; use 5.006001; use strict; use warnings; use utf8; BEGIN { if ($] < 5.008) { require Devel::TypeTiny::Perl56Compat }; } BEGIN { $Types::Common::String::AUTHORITY = 'cpan:TOBYINK'; $Types::Common::String::VERSION = '1.000005'; } use Type::Library -base, -declare => qw( SimpleStr NonEmptySimpleStr NumericCode LowerCaseSimpleStr UpperCaseSimpleStr Password StrongPassword NonEmptyStr LowerCaseStr UpperCaseStr ); use Type::Tiny (); use Types::Standard qw( Str ); my $meta = __PACKAGE__->meta; $meta->add_type( name => SimpleStr, parent => Str, constraint => sub { length($_) <= 255 and not /\n/ }, inlined => sub { undef, qq(length($_) <= 255), qq($_ !~ /\\n/) }, message => sub { "Must be a single line of no more than 255 chars" }, ); $meta->add_type( name => NonEmptySimpleStr, parent => SimpleStr, constraint => sub { length($_) > 0 }, inlined => sub { undef, qq(length($_) > 0) }, message => sub { "Must be a non-empty single line of no more than 255 chars" }, ); $meta->add_type( name => NumericCode, parent => NonEmptySimpleStr, constraint => sub { /^[0-9]+$/ }, inlined => sub { SimpleStr->inline_check($_), qq($_ =~ m/^[0-9]+\$/) }, message => sub { 'Must be a non-empty single line of no more than 255 chars that consists ' . 'of numeric characters only' }, ); NumericCode->coercion->add_type_coercions( NonEmptySimpleStr, q[ do { (my $code = $_) =~ s/[[:punct:]]//g; $code } ], ); $meta->add_type( name => Password, parent => NonEmptySimpleStr, constraint => sub { length($_) > 3 }, inlined => sub { SimpleStr->inline_check($_), qq(length($_) > 3) }, message => sub { "Must be between 4 and 255 chars" }, ); $meta->add_type( name => StrongPassword, parent => Password, constraint => sub { length($_) > 7 and /[^a-zA-Z]/ }, inlined => sub { SimpleStr()->inline_check($_), qq(length($_) > 7), qq($_ =~ /[^a-zA-Z]/) }, message => sub { "Must be between 8 and 255 chars, and contain a non-alpha char" }, ); my ($nestr); if (Type::Tiny::_USE_XS) { $nestr = Type::Tiny::XS::get_coderef_for('NonEmptyStr'); } $meta->add_type( name => NonEmptyStr, parent => Str, constraint => sub { length($_) > 0 }, inlined => sub { if ($nestr) { my $xsub = Type::Tiny::XS::get_subname_for($_[0]->name); return "$xsub($_[1])" if $xsub; } undef, qq(length($_) > 0); }, message => sub { "Must not be empty" }, $nestr ? ( compiled_type_constraint => $nestr ) : (), ); $meta->add_type( name => LowerCaseStr, parent => NonEmptyStr, constraint => sub { !/\p{Upper}/ms }, inlined => sub { undef, qq($_ !~ /\\p{Upper}/ms) }, message => sub { "Must not contain upper case letters" }, ); LowerCaseStr->coercion->add_type_coercions( NonEmptyStr, q[ lc($_) ], ); $meta->add_type( name => UpperCaseStr, parent => NonEmptyStr, constraint => sub { !/\p{Lower}/ms }, inlined => sub { undef, qq($_ !~ /\\p{Lower}/ms) }, message => sub { "Must not contain lower case letters" }, ); UpperCaseStr->coercion->add_type_coercions( NonEmptyStr, q[ uc($_) ], ); $meta->add_type( name => LowerCaseSimpleStr, parent => NonEmptySimpleStr, constraint => sub { !/\p{Upper}/ms }, inlined => sub { undef, qq($_ !~ /\\p{Upper}/ms) }, message => sub { "Must not contain pper case letters" }, ); LowerCaseSimpleStr->coercion->add_type_coercions( NonEmptySimpleStr, q[ lc($_) ], ); $meta->add_type( name => UpperCaseSimpleStr, parent => NonEmptySimpleStr, constraint => sub { !/\p{Lower}/ms }, inlined => sub { undef, qq($_ !~ /\\p{Lower}/ms) }, message => sub { "Must not contain lower case letters" }, ); UpperCaseSimpleStr->coercion->add_type_coercions( NonEmptySimpleStr, q[ uc($_) ], ); __PACKAGE__->meta->make_immutable; 1; __END__ =pod =encoding utf-8 =head1 NAME Types::Common::String - drop-in replacement for MooseX::Types::Common::String =head1 STATUS This module is covered by the L. =head1 DESCRIPTION A drop-in replacement for L. =head2 Types The following types are similar to those described in L. =over =item C =item C =item C =item C =item C =item C =item C =item C =item C =item C =back =head1 BUGS Please report any bugs to L. =head1 SEE ALSO L, L. L, L, L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. ArrayRef.pm000664001750001750 1046312422772210 20106 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Types/Standardpackage Types::Standard::ArrayRef; use 5.006001; use strict; use warnings; BEGIN { $Types::Standard::ArrayRef::AUTHORITY = 'cpan:TOBYINK'; $Types::Standard::ArrayRef::VERSION = '1.000005'; } use Type::Tiny (); use Types::Standard (); use Types::TypeTiny (); sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak } no warnings; sub __constraint_generator { return Types::Standard::ArrayRef unless @_; my $param = Types::TypeTiny::to_TypeTiny(shift); Types::TypeTiny::TypeTiny->check($param) or _croak("Parameter to ArrayRef[`a] expected to be a type constraint; got $param"); my $param_compiled_check = $param->compiled_check; my $xsub; if (Type::Tiny::_USE_XS) { my $paramname = Type::Tiny::XS::is_known($param_compiled_check); $xsub = Type::Tiny::XS::get_coderef_for("ArrayRef[$paramname]") if $paramname; } elsif (Type::Tiny::_USE_MOUSE and $param->_has_xsub) { require Mouse::Util::TypeConstraints; my $maker = "Mouse::Util::TypeConstraints"->can("_parameterize_ArrayRef_for"); $xsub = $maker->($param) if $maker; } return ( sub { my $array = shift; $param->check($_) || return for @$array; return !!1; }, $xsub, ); } sub __inline_generator { my $param = shift; my $param_compiled_check = $param->compiled_check; if (Type::Tiny::_USE_XS) { my $paramname = Type::Tiny::XS::is_known($param_compiled_check); my $xsubname = Type::Tiny::XS::get_subname_for("ArrayRef[$paramname]"); return sub { "$xsubname\($_[1]\)" } if $xsubname; } return unless $param->can_be_inlined; my $param_check = $param->inline_check('$i'); return sub { my $v = $_[1]; "ref($v) eq 'ARRAY' and do { " . "my \$ok = 1; " . "for my \$i (\@{$v}) { " . "(\$ok = 0, last) unless $param_check " . "}; " . "\$ok " ."}" }; } sub __deep_explanation { my ($type, $value, $varname) = @_; my $param = $type->parameters->[0]; for my $i (0 .. $#$value) { my $item = $value->[$i]; next if $param->check($item); return [ sprintf('"%s" constrains each value in the array with "%s"', $type, $param), @{ $param->validate_explain($item, sprintf('%s->[%d]', $varname, $i)) }, ] } # This should never happen... return; # uncoverable statement } sub __coercion_generator { my ($parent, $child, $param) = @_; return unless $param->has_coercion; my $coercable_item = $param->coercion->_source_type_union; my $C = "Type::Coercion"->new(type_constraint => $child); if ($param->coercion->can_be_inlined and $coercable_item->can_be_inlined) { $C->add_type_coercions($parent => Types::Standard::Stringable { my @code; push @code, 'do { my ($orig, $return_orig, @new) = ($_, 0);'; push @code, 'for (@$orig) {'; push @code, sprintf('++$return_orig && last unless (%s);', $coercable_item->inline_check('$_')); push @code, sprintf('push @new, (%s);', $param->coercion->inline_coercion('$_')); push @code, '}'; push @code, '$return_orig ? $orig : \\@new'; push @code, '}'; "@code"; }); } else { $C->add_type_coercions( $parent => sub { my $value = @_ ? $_[0] : $_; my @new; for my $item (@$value) { return $value unless $coercable_item->check($item); push @new, $param->coerce($item); } return \@new; }, ); } return $C; } 1; __END__ =pod =encoding utf-8 =head1 NAME Types::Standard::ArrayRef - internals for the Types::Standard ArrayRef type constraint =head1 STATUS This module is considered part of Type-Tiny's internals. It is not covered by the L. =head1 DESCRIPTION This file contains some of the guts for L. It will be loaded on demand. You may ignore its presence. =head1 BUGS Please report any bugs to L. =head1 SEE ALSO L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. Dict.pm000664001750001750 2174212422772210 17260 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Types/Standardpackage Types::Standard::Dict; use 5.006001; use strict; use warnings; BEGIN { $Types::Standard::Dict::AUTHORITY = 'cpan:TOBYINK'; $Types::Standard::Dict::VERSION = '1.000005'; } use Types::Standard (); use Types::TypeTiny (); sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak } my $_optional = Types::Standard::Optional; my $_hash = Types::Standard::HashRef; my $_map = Types::Standard::Map; my $_any = Types::Standard::Any; no warnings; sub __constraint_generator { my $slurpy = ref($_[-1]) eq q(HASH) ? pop(@_)->{slurpy} : undef; my %constraints = @_; my %is_optional; while (my ($k, $v) = each %constraints) { $constraints{$k} = Types::TypeTiny::to_TypeTiny($v); $is_optional{$k} = !!$constraints{$k}->is_strictly_a_type_of($_optional); Types::TypeTiny::TypeTiny->check($v) or _croak("Parameter to Dict[`a] for key '$k' expected to be a type constraint; got $v"); } return sub { my $value = $_[0]; if ($slurpy) { my %tmp = map { exists($constraints{$_}) ? () : ($_ => $value->{$_}) } keys %$value; return unless $slurpy->check(\%tmp); } else { exists($constraints{$_}) || return for sort keys %$value; } for my $k (sort keys %constraints) { exists($value->{$k}) or ($is_optional{$k} ? next : return); $constraints{$k}->check($value->{$k}) or return; } return !!1; }; } sub __inline_generator { # We can only inline a parameterized Dict if all the # constraints inside can be inlined. my $slurpy = ref($_[-1]) eq q(HASH) ? pop(@_)->{slurpy} : undef; return if $slurpy && !$slurpy->can_be_inlined; # Is slurpy a very loose type constraint? # i.e. Any, Item, Defined, Ref, or HashRef my $slurpy_is_any = $slurpy && $_hash->is_a_type_of( $slurpy ); # Is slurpy a parameterized Map, or expressable as a parameterized Map? my $slurpy_is_map = $slurpy && $slurpy->is_parameterized && (( $slurpy->parent->strictly_equals($_map) && $slurpy->parameters )||( $slurpy->parent->strictly_equals($_hash) && [ $_any, $slurpy->parameters->[0] ] )); my %constraints = @_; for my $c (values %constraints) { next if $c->can_be_inlined; return; } my $regexp = join "|", map quotemeta, sort keys %constraints; return sub { require B; my $h = $_[1]; join " and ", "ref($h) eq 'HASH'", ( $slurpy_is_any ? () : $slurpy_is_map ? do { '(not grep {' ."my \$v = ($h)->{\$_};" .sprintf( 'not((/\\A(?:%s)\\z/) or ((%s) and (%s)))', $regexp, $slurpy_is_map->[0]->inline_check('$_'), $slurpy_is_map->[1]->inline_check('$v'), ) ."} keys \%{$h})" } : $slurpy ? do { 'do {' . "my \$slurpy_tmp = +{ map /\\A(?:$regexp)\\z/ ? () : (\$_ => ($h)->{\$_}), keys \%{$h} };" . $slurpy->inline_check('$slurpy_tmp') . '}' } : "not(grep !/\\A(?:$regexp)\\z/, keys \%{$h})" ), ( map { my $k = B::perlstring($_); $constraints{$_}->is_strictly_a_type_of( $_optional ) ? sprintf('(!exists %s->{%s} or %s)', $h, $k, $constraints{$_}->inline_check("$h\->{$k}")) : ( "exists($h\->{$k})", $constraints{$_}->inline_check("$h\->{$k}") ) } sort keys %constraints ), } } sub __deep_explanation { require B; my ($type, $value, $varname) = @_; my @params = @{ $type->parameters }; my $slurpy = ref($params[-1]) eq q(HASH) ? pop(@params)->{slurpy} : undef; my %constraints = @params; for my $k (sort keys %constraints) { next if $constraints{$k}->parent == Types::Standard::Optional && !exists $value->{$k}; next if $constraints{$k}->check($value->{$k}); return [ sprintf('"%s" requires key %s to appear in hash', $type, B::perlstring($k)) ] unless exists $value->{$k}; return [ sprintf('"%s" constrains value at key %s of hash with "%s"', $type, B::perlstring($k), $constraints{$k}), @{ $constraints{$k}->validate_explain($value->{$k}, sprintf('%s->{%s}', $varname, B::perlstring($k))) }, ]; } if ($slurpy) { my %tmp = map { exists($constraints{$_}) ? () : ($_ => $value->{$_}) } keys %$value; my $explain = $slurpy->validate_explain(\%tmp, '$slurpy'); return [ sprintf('"%s" requires the hashref of additional key/value pairs to conform to "%s"', $type, $slurpy), @$explain, ] if $explain; } else { for my $k (sort keys %$value) { return [ sprintf('"%s" does not allow key %s to appear in hash', $type, B::perlstring($k)) ] unless exists $constraints{$k}; } } # This should never happen... return; # uncoverable statement } my $label_counter = 0; our ($keycheck_counter, @KEYCHECK) = -1; sub __coercion_generator { my $slurpy = ref($_[-1]) eq q(HASH) ? pop(@_)->{slurpy} : undef; my ($parent, $child, %dict) = @_; my $C = "Type::Coercion"->new(type_constraint => $child); my $all_inlinable = 1; for my $tc (values %dict) { $all_inlinable = 0 if !$tc->can_be_inlined; $all_inlinable = 0 if $tc->has_coercion && !$tc->coercion->can_be_inlined; last if!$all_inlinable; } $all_inlinable = 0 if $slurpy && !$slurpy->can_be_inlined; $all_inlinable = 0 if $slurpy && $slurpy->has_coercion && !$slurpy->coercion->can_be_inlined; if ($all_inlinable) { $C->add_type_coercions($parent => Types::Standard::Stringable { require B; my $keycheck = join "|", map quotemeta, sort { length($b) <=> length($a) or $a cmp $b } keys %dict; $keycheck = $KEYCHECK[++$keycheck_counter] = qr{^($keycheck)$}ms; # regexp for legal keys my $label = sprintf("DICTLABEL%d", ++$label_counter); my @code; push @code, 'do { my ($orig, $return_orig, $tmp, %new) = ($_, 0);'; push @code, "$label: {"; if ($slurpy) { push @code, sprintf('my $slurped = +{ map +($_=~$%s::KEYCHECK[%d])?():($_=>$orig->{$_}), keys %%$orig };', __PACKAGE__, $keycheck_counter); if ($slurpy->has_coercion) { push @code, sprintf('my $coerced = %s;', $slurpy->coercion->inline_coercion('$slurped')); push @code, sprintf('((%s)&&(%s))?(%%new=%%$coerced):(($return_orig = 1), last %s);', $_hash->inline_check('$coerced'), $slurpy->inline_check('$coerced'), $label); } else { push @code, sprintf('(%s)?(%%new=%%$slurped):(($return_orig = 1), last %s);', $slurpy->inline_check('$slurped'), $label); } } else { push @code, sprintf('($_ =~ $%s::KEYCHECK[%d])||(($return_orig = 1), last %s) for sort keys %%$orig;', __PACKAGE__, $keycheck_counter, $label); } for my $k (keys %dict) { my $ct = $dict{$k}; my $ct_coerce = $ct->has_coercion; my $ct_optional = $ct->is_a_type_of($_optional); my $K = B::perlstring($k); push @code, sprintf( 'if (exists $orig->{%s}) { $tmp = %s; (%s) ? ($new{%s}=$tmp) : ($return_orig=1 and last %s) }', $K, $ct_coerce ? $ct->coercion->inline_coercion("\$orig->{$K}") : "\$orig->{$K}", $ct->inline_check('$tmp'), $K, $label, ); } push @code, '}'; push @code, '$return_orig ? $orig : \\%new'; push @code, '}'; #warn "CODE:: @code"; "@code"; }); } else { my %is_optional = map { ; $_ => !!$dict{$_}->is_strictly_a_type_of($_optional) } sort keys %dict; $C->add_type_coercions( $parent => sub { my $value = @_ ? $_[0] : $_; my %new; if ($slurpy) { my %slurped = map exists($dict{$_}) ? () : ($_ => $value->{$_}), keys %$value; if ($slurpy->check(\%slurped)) { %new = %slurped; } elsif ($slurpy->has_coercion) { my $coerced = $slurpy->coerce(\%slurped); $slurpy->check($coerced) ? (%new = %$coerced) : (return $value); } else { return $value; } } else { for my $k (keys %$value) { return $value unless exists $dict{$k}; } } for my $k (keys %dict) { next if $is_optional{$k} and not exists $value->{$k}; my $ct = $dict{$k}; my $x = $ct->has_coercion ? $ct->coerce($value->{$k}) : $value->{$k}; return $value unless $ct->check($x); $new{$k} = $x; } return \%new; }, ); } return $C; } 1; __END__ =pod =encoding utf-8 =head1 NAME Types::Standard::Dict - internals for the Types::Standard Dict type constraint =head1 STATUS This module is considered part of Type-Tiny's internals. It is not covered by the L. =head1 DESCRIPTION This file contains some of the guts for L. It will be loaded on demand. You may ignore its presence. =head1 BUGS Please report any bugs to L. =head1 SEE ALSO L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. HashRef.pm000664001750001750 1054212422772210 17711 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Types/Standardpackage Types::Standard::HashRef; use 5.006001; use strict; use warnings; BEGIN { $Types::Standard::HashRef::AUTHORITY = 'cpan:TOBYINK'; $Types::Standard::HashRef::VERSION = '1.000005'; } use Type::Tiny (); use Types::Standard (); use Types::TypeTiny (); sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak } no warnings; sub __constraint_generator { return Types::Standard::HashRef unless @_; my $param = Types::TypeTiny::to_TypeTiny(shift); Types::TypeTiny::TypeTiny->check($param) or _croak("Parameter to HashRef[`a] expected to be a type constraint; got $param"); my $param_compiled_check = $param->compiled_check; my $xsub; if (Type::Tiny::_USE_XS) { my $paramname = Type::Tiny::XS::is_known($param_compiled_check); $xsub = Type::Tiny::XS::get_coderef_for("HashRef[$paramname]") if $paramname; } elsif (Type::Tiny::_USE_MOUSE and $param->_has_xsub) { require Mouse::Util::TypeConstraints; my $maker = "Mouse::Util::TypeConstraints"->can("_parameterize_HashRef_for"); $xsub = $maker->($param) if $maker; } return ( sub { my $hash = shift; $param->check($_) || return for values %$hash; return !!1; }, $xsub, ); } sub __inline_generator { my $param = shift; my $compiled = $param->compiled_check; if (Type::Tiny::_USE_XS) { my $paramname = Type::Tiny::XS::is_known($compiled); my $xsubname = Type::Tiny::XS::get_subname_for("HashRef[$paramname]"); return sub { "$xsubname\($_[1]\)" } if $xsubname; } return unless $param->can_be_inlined; my $param_check = $param->inline_check('$i'); return sub { my $v = $_[1]; "ref($v) eq 'HASH' and do { " . "my \$ok = 1; " . "for my \$i (values \%{$v}) { " . "(\$ok = 0, last) unless $param_check " . "}; " . "\$ok " ."}" }; } sub __deep_explanation { require B; my ($type, $value, $varname) = @_; my $param = $type->parameters->[0]; for my $k (sort keys %$value) { my $item = $value->{$k}; next if $param->check($item); return [ sprintf('"%s" constrains each value in the hash with "%s"', $type, $param), @{ $param->validate_explain($item, sprintf('%s->{%s}', $varname, B::perlstring($k))) }, ]; } # This should never happen... return; # uncoverable statement } sub __coercion_generator { my ($parent, $child, $param) = @_; return unless $param->has_coercion; my $coercable_item = $param->coercion->_source_type_union; my $C = "Type::Coercion"->new(type_constraint => $child); if ($param->coercion->can_be_inlined and $coercable_item->can_be_inlined) { $C->add_type_coercions($parent => Types::Standard::Stringable { my @code; push @code, 'do { my ($orig, $return_orig, %new) = ($_, 0);'; push @code, 'for (keys %$orig) {'; push @code, sprintf('$return_orig++ && last unless (%s);', $coercable_item->inline_check('$orig->{$_}')); push @code, sprintf('$new{$_} = (%s);', $param->coercion->inline_coercion('$orig->{$_}')); push @code, '}'; push @code, '$return_orig ? $orig : \\%new'; push @code, '}'; "@code"; }); } else { $C->add_type_coercions( $parent => sub { my $value = @_ ? $_[0] : $_; my %new; for my $k (keys %$value) { return $value unless $coercable_item->check($value->{$k}); $new{$k} = $param->coerce($value->{$k}); } return \%new; }, ); } return $C; } 1; __END__ =pod =encoding utf-8 =head1 NAME Types::Standard::HashRef - internals for the Types::Standard HashRef type constraint =head1 STATUS This module is considered part of Type-Tiny's internals. It is not covered by the L. =head1 DESCRIPTION This file contains some of the guts for L. It will be loaded on demand. You may ignore its presence. =head1 BUGS Please report any bugs to L. =head1 SEE ALSO L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. Map.pm000664001750001750 1277712422772210 17122 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Types/Standardpackage Types::Standard::Map; use 5.006001; use strict; use warnings; BEGIN { $Types::Standard::Map::AUTHORITY = 'cpan:TOBYINK'; $Types::Standard::Map::VERSION = '1.000005'; } use Type::Tiny (); use Types::Standard (); use Types::TypeTiny (); sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak } my $meta = Types::Standard->meta; no warnings; sub __constraint_generator { return $meta->get_type('Map') unless @_; my ($keys, $values) = map Types::TypeTiny::to_TypeTiny($_), @_; Types::TypeTiny::TypeTiny->check($keys) or _croak("First parameter to Map[`k,`v] expected to be a type constraint; got $keys"); Types::TypeTiny::TypeTiny->check($values) or _croak("Second parameter to Map[`k,`v] expected to be a type constraint; got $values"); my @xsub; if (Type::Tiny::_USE_XS) { my @known = map { my $known = Type::Tiny::XS::is_known($_->compiled_check); defined($known) ? $known : (); } ($keys, $values); if (@known == 2) { my $xsub = Type::Tiny::XS::get_coderef_for( sprintf "Map[%s,%s]", @known ); push @xsub, $xsub if $xsub; } } sub { my $hash = shift; $keys->check($_) || return for keys %$hash; $values->check($_) || return for values %$hash; return !!1; }, @xsub; } sub __inline_generator { my ($k, $v) = @_; return unless $k->can_be_inlined && $v->can_be_inlined; if (Type::Tiny::_USE_XS) { my @known = map { my $known = Type::Tiny::XS::is_known($_->compiled_check); defined($known) ? $known : (); } ($k, $v); if (@known == 2) { my $xsub = Type::Tiny::XS::get_subname_for( sprintf "Map[%s,%s]", @known ); return sub { my $var = $_[1]; "$xsub\($var\)" } if $xsub; } } my $k_check = $k->inline_check('$k'); my $v_check = $v->inline_check('$v'); return sub { my $h = $_[1]; "ref($h) eq 'HASH' and do { " . "my \$ok = 1; " . "for my \$v (values \%{$h}) { " . "(\$ok = 0, last) unless $v_check " . "}; " . "for my \$k (keys \%{$h}) { " . "(\$ok = 0, last) unless $k_check " . "}; " . "\$ok " ."}" }; } sub __deep_explanation { require B; my ($type, $value, $varname) = @_; my ($kparam, $vparam) = @{ $type->parameters }; for my $k (sort keys %$value) { unless ($kparam->check($k)) { return [ sprintf('"%s" constrains each key in the hash with "%s"', $type, $kparam), @{ $kparam->validate_explain($k, sprintf('key %s->{%s}', $varname, B::perlstring($k))) }, ]; } unless ($vparam->check($value->{$k})) { return [ sprintf('"%s" constrains each value in the hash with "%s"', $type, $vparam), @{ $vparam->validate_explain($value->{$k}, sprintf('%s->{%s}', $varname, B::perlstring($k))) }, ]; } } # This should never happen... return; # uncoverable statement } sub __coercion_generator { my ($parent, $child, $kparam, $vparam) = @_; return unless $kparam->has_coercion || $vparam->has_coercion; my $kcoercable_item = $kparam->has_coercion ? $kparam->coercion->_source_type_union : $kparam; my $vcoercable_item = $vparam->has_coercion ? $vparam->coercion->_source_type_union : $vparam; my $C = "Type::Coercion"->new(type_constraint => $child); if ((!$kparam->has_coercion or $kparam->coercion->can_be_inlined) and (!$vparam->has_coercion or $vparam->coercion->can_be_inlined) and $kcoercable_item->can_be_inlined and $vcoercable_item->can_be_inlined) { $C->add_type_coercions($parent => Types::Standard::Stringable { my @code; push @code, 'do { my ($orig, $return_orig, %new) = ($_, 0);'; push @code, 'for (keys %$orig) {'; push @code, sprintf('++$return_orig && last unless (%s);', $kcoercable_item->inline_check('$_')); push @code, sprintf('++$return_orig && last unless (%s);', $vcoercable_item->inline_check('$orig->{$_}')); push @code, sprintf('$new{(%s)} = (%s);', $kparam->has_coercion ? $kparam->coercion->inline_coercion('$_') : '$_', $vparam->has_coercion ? $vparam->coercion->inline_coercion('$orig->{$_}') : '$orig->{$_}', ); push @code, '}'; push @code, '$return_orig ? $orig : \\%new'; push @code, '}'; "@code"; }); } else { $C->add_type_coercions( $parent => sub { my $value = @_ ? $_[0] : $_; my %new; for my $k (keys %$value) { return $value unless $kcoercable_item->check($k) && $vcoercable_item->check($value->{$k}); $new{$kparam->has_coercion ? $kparam->coerce($k) : $k} = $vparam->has_coercion ? $vparam->coerce($value->{$k}) : $value->{$k}; } return \%new; }, ); } return $C; } 1; __END__ =pod =encoding utf-8 =head1 NAME Types::Standard::Map - internals for the Types::Standard Map type constraint =head1 STATUS This module is considered part of Type-Tiny's internals. It is not covered by the L. =head1 DESCRIPTION This file contains some of the guts for L. It will be loaded on demand. You may ignore its presence. =head1 BUGS Please report any bugs to L. =head1 SEE ALSO L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. ScalarRef.pm000664001750001750 662412422772210 20221 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Types/Standardpackage Types::Standard::ScalarRef; use 5.006001; use strict; use warnings; BEGIN { $Types::Standard::ScalarRef::AUTHORITY = 'cpan:TOBYINK'; $Types::Standard::ScalarRef::VERSION = '1.000005'; } use Types::Standard (); use Types::TypeTiny (); sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak } no warnings; sub __constraint_generator { return Types::Standard::ScalarRef unless @_; my $param = Types::TypeTiny::to_TypeTiny(shift); Types::TypeTiny::TypeTiny->check($param) or _croak("Parameter to ScalarRef[`a] expected to be a type constraint; got $param"); return sub { my $ref = shift; $param->check($$ref) || return; return !!1; }; } sub __inline_generator { my $param = shift; return unless $param->can_be_inlined; return sub { my $v = $_[1]; my $param_check = $param->inline_check("\${$v}"); "(ref($v) eq 'SCALAR' or ref($v) eq 'REF') and $param_check"; }; } sub __deep_explanation { my ($type, $value, $varname) = @_; my $param = $type->parameters->[0]; for my $item ($$value) { next if $param->check($item); return [ sprintf('"%s" constrains the referenced scalar value with "%s"', $type, $param), @{ $param->validate_explain($item, sprintf('${%s}', $varname)) }, ]; } # This should never happen... return; # uncoverable statement } sub __coercion_generator { my ($parent, $child, $param) = @_; return unless $param->has_coercion; my $coercable_item = $param->coercion->_source_type_union; my $C = "Type::Coercion"->new(type_constraint => $child); if ($param->coercion->can_be_inlined and $coercable_item->can_be_inlined) { $C->add_type_coercions($parent => Types::Standard::Stringable { my @code; push @code, 'do { my ($orig, $return_orig, $new) = ($_, 0);'; push @code, 'for ($$orig) {'; push @code, sprintf('++$return_orig && last unless (%s);', $coercable_item->inline_check('$_')); push @code, sprintf('$new = (%s);', $param->coercion->inline_coercion('$_')); push @code, '}'; push @code, '$return_orig ? $orig : \\$new'; push @code, '}'; "@code"; }); } else { $C->add_type_coercions( $parent => sub { my $value = @_ ? $_[0] : $_; my $new; for my $item ($$value) { return $value unless $coercable_item->check($item); $new = $param->coerce($item); } return \$new; }, ); } return $C; } 1; __END__ =pod =encoding utf-8 =head1 NAME Types::Standard::ScalarRef - internals for the Types::Standard ScalarRef type constraint =head1 STATUS This module is considered part of Type-Tiny's internals. It is not covered by the L. =head1 DESCRIPTION This file contains some of the guts for L. It will be loaded on demand. You may ignore its presence. =head1 BUGS Please report any bugs to L. =head1 SEE ALSO L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. Tuple.pm000664001750001750 2212612422772210 17463 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Types/Standardpackage Types::Standard::Tuple; use 5.006001; use strict; use warnings; BEGIN { $Types::Standard::Tuple::AUTHORITY = 'cpan:TOBYINK'; $Types::Standard::Tuple::VERSION = '1.000005'; } use Type::Tiny (); use Types::Standard (); use Types::TypeTiny (); sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak } my $_Optional = Types::Standard::Optional; no warnings; sub __constraint_generator { my @constraints = @_; my $slurpy; if (exists $constraints[-1] and ref $constraints[-1] eq "HASH") { $slurpy = Types::TypeTiny::to_TypeTiny(pop(@constraints)->{slurpy}); Types::TypeTiny::TypeTiny->check($slurpy) or _croak("Slurpy parameter to Tuple[...] expected to be a type constraint; got $slurpy"); } @constraints = map Types::TypeTiny::to_TypeTiny($_), @constraints; for (@constraints) { Types::TypeTiny::TypeTiny->check($_) or _croak("Parameters to Tuple[...] expected to be type constraints; got $_"); } # By god, the Type::Tiny::XS API is currently horrible my @xsub; if (Type::Tiny::_USE_XS and !$slurpy) { my @known = map { my $known; $known = Type::Tiny::XS::is_known($_->compiled_check) unless $_->is_strictly_a_type_of($_Optional); defined($known) ? $known : (); } @constraints; if (@known == @constraints) { my $xsub = Type::Tiny::XS::get_coderef_for( sprintf "Tuple[%s]", join(',', @known) ); push @xsub, $xsub if $xsub; } } my @is_optional = map !!$_->is_strictly_a_type_of($_Optional), @constraints; my $slurp_hash = $slurpy && $slurpy->is_a_type_of(Types::Standard::HashRef); my $slurp_any = $slurpy && $slurpy->equals(Types::Standard::Any); sub { my $value = $_[0]; if ($#constraints < $#$value) { return !!0 unless $slurpy; my $tmp; if ($slurp_hash) { ($#$value - $#constraints+1) % 2 or return; $tmp = +{@$value[$#constraints+1 .. $#$value]}; $slurpy->check($tmp) or return; } elsif (not $slurp_any) { $tmp = +[@$value[$#constraints+1 .. $#$value]]; $slurpy->check($tmp) or return; } } for my $i (0 .. $#constraints) { ($i > $#$value) and return !!$is_optional[$i]; $constraints[$i]->check($value->[$i]) or return !!0; } return !!1; }, @xsub; } sub __inline_generator { my @constraints = @_; my $slurpy; if (exists $constraints[-1] and ref $constraints[-1] eq "HASH") { $slurpy = pop(@constraints)->{slurpy}; } return if grep { not $_->can_be_inlined } @constraints; return if defined $slurpy && !$slurpy->can_be_inlined; if (Type::Tiny::_USE_XS and !$slurpy) { my @known = map { my $known; $known = Type::Tiny::XS::is_known($_->compiled_check) unless $_->is_strictly_a_type_of($_Optional); defined($known) ? $known : (); } @constraints; if (@known == @constraints) { my $xsub = Type::Tiny::XS::get_subname_for( sprintf "Tuple[%s]", join(',', @known) ); return sub { my $var = $_[1]; "$xsub\($var\)" } if $xsub; } } my $tmpl = "do { my \$tmp = +[\@{%s}[%d..\$#{%s}]]; %s }"; my $slurpy_any; if (defined $slurpy) { $tmpl = 'do { my ($orig, $from, $to) = (%s, %d, $#{%s});' . '($to-$from % 2) and do { my $tmp = +{@{$orig}[$from..$to]}; %s }' . '}' if $slurpy->is_a_type_of(Types::Standard::HashRef); $slurpy_any = 1 if $slurpy->equals(Types::Standard::Any); } my @is_optional = map !!$_->is_strictly_a_type_of($_Optional), @constraints; my $min = 0 + grep !$_, @is_optional; return sub { my $v = $_[1]; join " and ", "ref($v) eq 'ARRAY'", "scalar(\@{$v}) >= $min", ( $slurpy_any ? () : ( $slurpy ? sprintf($tmpl, $v, $#constraints+1, $v, $slurpy->inline_check('$tmp')) : sprintf("\@{$v} <= %d", scalar @constraints) ) ), map { my $inline = $constraints[$_]->inline_check("$v\->[$_]"); $is_optional[$_] ? sprintf('(@{%s} <= %d or %s)', $v, $_, $inline) : $inline; } 0 .. $#constraints; }; } sub __deep_explanation { my ($type, $value, $varname) = @_; my @constraints = @{ $type->parameters }; my $slurpy; if (exists $constraints[-1] and ref $constraints[-1] eq "HASH") { $slurpy = Types::TypeTiny::to_TypeTiny(pop(@constraints)->{slurpy}); } @constraints = map Types::TypeTiny::to_TypeTiny($_), @constraints; if (@constraints < @$value and not $slurpy) { return [ sprintf('"%s" expects at most %d values in the array', $type, scalar(@constraints)), sprintf('%d values found; too many', scalar(@$value)), ]; } for my $i (0 .. $#constraints) { next if $constraints[$i]->is_strictly_a_type_of( Types::Standard::Optional ) && $i > $#$value; next if $constraints[$i]->check($value->[$i]); return [ sprintf('"%s" constrains value at index %d of array with "%s"', $type, $i, $constraints[$i]), @{ $constraints[$i]->validate_explain($value->[$i], sprintf('%s->[%s]', $varname, $i)) }, ]; } if (defined($slurpy)) { my $tmp = $slurpy->is_a_type_of(Types::Standard::HashRef) ? +{@$value[$#constraints+1 .. $#$value]} : +[@$value[$#constraints+1 .. $#$value]]; $slurpy->check($tmp) or return [ sprintf( 'Array elements from index %d are slurped into a %s which is constrained with "%s"', $#constraints+1, $slurpy->is_a_type_of(Types::Standard::HashRef) ? 'hashref' : 'arrayref', $slurpy, ), @{ $slurpy->validate_explain($tmp, '$SLURPY') }, ]; } # This should never happen... return; # uncoverable statement } my $label_counter = 0; sub __coercion_generator { my ($parent, $child, @tuple) = @_; my $C = "Type::Coercion"->new(type_constraint => $child); my $slurpy; if (exists $tuple[-1] and ref $tuple[-1] eq "HASH") { $slurpy = pop(@tuple)->{slurpy}; } my $all_inlinable = 1; for my $tc (@tuple, ($slurpy ? $slurpy : ())) { $all_inlinable = 0 if !$tc->can_be_inlined; $all_inlinable = 0 if $tc->has_coercion && !$tc->coercion->can_be_inlined; last if!$all_inlinable; } if ($all_inlinable) { $C->add_type_coercions($parent => Types::Standard::Stringable { my $label = sprintf("TUPLELABEL%d", ++$label_counter); my @code; push @code, 'do { my ($orig, $return_orig, $tmp, @new) = ($_, 0);'; push @code, "$label: {"; push @code, sprintf('(($return_orig = 1), last %s) if @$orig > %d;', $label, scalar @tuple) unless $slurpy; for my $i (0 .. $#tuple) { my $ct = $tuple[$i]; my $ct_coerce = $ct->has_coercion; my $ct_optional = $ct->is_a_type_of(Types::Standard::Optional); push @code, sprintf( 'if (@$orig > %d) { $tmp = %s; (%s) ? ($new[%d]=$tmp) : ($return_orig=1 and last %s) }', $i, $ct_coerce ? $ct->coercion->inline_coercion("\$orig->[$i]") : "\$orig->[$i]", $ct->inline_check('$tmp'), $i, $label, ); } if ($slurpy) { my $size = @tuple; push @code, sprintf('if (@$orig > %d) {', $size); push @code, sprintf('my $tail = [ @{$orig}[%d .. $#$orig] ];', $size); push @code, $slurpy->has_coercion ? sprintf('$tail = %s;', $slurpy->coercion->inline_coercion('$tail')) : q(); push @code, sprintf( '(%s) ? push(@new, @$tail) : ($return_orig++);', $slurpy->inline_check('$tail'), ); push @code, '}'; } push @code, '}'; push @code, '$return_orig ? $orig : \\@new'; push @code, '}'; "@code"; }); } else { my @is_optional = map !!$_->is_strictly_a_type_of($_Optional), @tuple; $C->add_type_coercions( $parent => sub { my $value = @_ ? $_[0] : $_; if (!$slurpy and @$value > @tuple) { return $value; } my @new; for my $i (0 .. $#tuple) { return \@new if $i > $#$value and $is_optional[$i]; my $ct = $tuple[$i]; my $x = $ct->has_coercion ? $ct->coerce($value->[$i]) : $value->[$i]; return $value unless $ct->check($x); $new[$i] = $x; } if ($slurpy and @$value > @tuple) { my $tmp = $slurpy->has_coercion ? $slurpy->coerce([ @{$value}[@tuple .. $#$value] ]) : [ @{$value}[@tuple .. $#$value] ]; $slurpy->check($tmp) ? push(@new, @$tmp) : return($value); } return \@new; }, ); }; return $C; } 1; __END__ =pod =encoding utf-8 =head1 NAME Types::Standard::Tuple - internals for the Types::Standard Tuple type constraint =head1 STATUS This module is considered part of Type-Tiny's internals. It is not covered by the L. =head1 DESCRIPTION This file contains some of the guts for L. It will be loaded on demand. You may ignore its presence. =head1 BUGS Please report any bugs to L. =head1 SEE ALSO L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. basic.t000664001750001750 115112422772210 22345 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Devel-TypeTiny-Perl56Compat=pod =encoding utf-8 =head1 PURPOSE Checks C<< B::perlstring() >> works. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use B; use Test::More; use Types::Standard; is( +eval(sprintf "use strict; %s", B::perlstring("foo")), "foo", 'eval(sprintf "use strict; %s", B::perlstring("foo"))', ); done_testing; basic.t000664001750001750 116512422772210 22354 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Devel-TypeTiny-Perl58Compat=pod =encoding utf-8 =head1 PURPOSE Checks C<< re::is_regexp() >> works. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Types::Standard; ok( +re::is_regexp(qr{foo}), 're::is_regexp(qr{foo})', ); ok( +re::is_regexp(bless qr{foo}, "Foo"), 're::is_regexp(bless qr{foo}, "Foo")', ); done_testing; basic.t000664001750001750 207412422772210 20165 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Error-TypeTiny=pod =encoding utf-8 =head1 PURPOSE Tests for basic L functionality. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Fatal; use Error::TypeTiny; #line 31 "basic.t" my $e1 = exception { 'Error::TypeTiny'->throw() }; is($e1->message, 'An exception has occurred', '$e1->message (default)'); is($e1->context->{package}, 'main', '$e1->context->{main}'); is($e1->context->{line}, '31', '$e1->contex1t->{line}'); is($e1->context->{file}, 'basic.t', '$e1->context->{file}'); my $e2 = exception { 'Error::TypeTiny'->throw(message => 'oh dear') }; is($e2->message, 'oh dear', '$e2->message'); my $e3 = exception { Error::TypeTiny::croak('oh %s', 'drat') }; is($e3->message, 'oh drat', '$e3->message (set by croak)'); done_testing; stacktrace.t000664001750001750 155112422772210 21227 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Error-TypeTiny=pod =encoding utf-8 =head1 PURPOSE Tests that L is capable of providing stack traces. =head1 DEPENDENCIES Requires L; skipped otherwise. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); local $Error::TypeTiny::StackTrace; use Test::More; use Test::Fatal; use Test::Requires { "Devel::StackTrace" => 0 }; use Types::Standard slurpy => -types; sub foo { local $Error::TypeTiny::StackTrace = 1; Int->(@_); } my $e = exception { foo(undef) }; is( $e->stack_trace->frame(1)->subroutine, "main::foo", ); done_testing; basic.t000664001750001750 2473212422772210 22157 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Error-TypeTiny-Assertion=pod =encoding utf-8 =head1 PURPOSE Tests L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); local $Error::TypeTiny::LastError; use Test::More; use Test::Fatal; use Scalar::Util qw(refaddr); use Types::Standard slurpy => -types; my $supernum = Types::Standard::STRICTNUM ? "StrictNum" : "LaxNum"; my $v = []; my $e = exception { Int->create_child_type->assert_valid($v) }; isa_ok($e, "Error::TypeTiny", '$e'); is(refaddr($e), refaddr($Error::TypeTiny::LastError), '$Error::TypeTiny::LastError'); is( $e->message, q{Reference [] did not pass type constraint}, '$e->message is as expected', ); isa_ok($e, "Error::TypeTiny::Assertion", '$e'); cmp_ok( $e->type, '==', Int, '$e->type is as expected', ); is( $e->value, $v, '$e->value is as expected', ); is_deeply( $e->explain, [ '"__ANON__" is a subtype of "Int"', '"Int" is a subtype of "Num"', '"Num" is a subtype of "'.$supernum.'"', '"'.$supernum.'" is a subtype of "Str"', '"Str" is a subtype of "Value"', 'Reference [] did not pass type constraint "Value"', '"Value" is defined as: (defined($_) and not ref($_))', ], '$e->explain is as expected', ); is_deeply( (exception { (ArrayRef[Int])->([1, 2, [3]]) })->explain, [ 'Reference [1,2,[3]] did not pass type constraint "ArrayRef[Int]"', '"ArrayRef[Int]" constrains each value in the array with "Int"', '"Int" is a subtype of "Num"', '"Num" is a subtype of "'.$supernum.'"', '"'.$supernum.'" is a subtype of "Str"', '"Str" is a subtype of "Value"', 'Reference [3] did not pass type constraint "Value" (in $_->[2])', '"Value" is defined as: (defined($_) and not ref($_))', ], 'ArrayRef[Int] deep explanation, given [1, 2, [3]]', ); is_deeply( (exception { (ArrayRef[Int])->({}) })->explain, [ '"ArrayRef[Int]" is a subtype of "ArrayRef"', 'Reference {} did not pass type constraint "ArrayRef"', '"ArrayRef" is defined as: (ref($_) eq \'ARRAY\')', ], 'ArrayRef[Int] deep explanation, given {}', ); is_deeply( (exception { (Ref["ARRAY"])->({}) })->explain, [ 'Reference {} did not pass type constraint "Ref[ARRAY]"', '"Ref[ARRAY]" constrains reftype($_) to be equal to "ARRAY"', 'reftype($_) is "HASH"', ], 'Ref["ARRAY"] deep explanation, given {}', ); is_deeply( (exception { (HashRef[Maybe[Int]])->({a => undef, b => 42, c => []}) })->explain, [ 'Reference {"a" => undef,"b" => 42,"c" => []} did not pass type constraint "HashRef[Maybe[Int]]"', '"HashRef[Maybe[Int]]" constrains each value in the hash with "Maybe[Int]"', 'Reference [] did not pass type constraint "Maybe[Int]" (in $_->{"c"})', 'Reference [] is defined', '"Maybe[Int]" constrains the value with "Int" if it is defined', '"Int" is a subtype of "Num"', '"Num" is a subtype of "'.$supernum.'"', '"'.$supernum.'" is a subtype of "Str"', '"Str" is a subtype of "Value"', 'Reference [] did not pass type constraint "Value" (in $_->{"c"})', '"Value" is defined as: (defined($_) and not ref($_))', ], 'HashRef[Maybe[Int]] deep explanation, given {a => undef, b => 42, c => []}', ); my $dict = Dict[a => Int, b => Optional[ArrayRef[Str]]]; is_deeply( (exception { $dict->({a => 1, c => 1}) })->explain, [ 'Reference {"a" => 1,"c" => 1} did not pass type constraint "Dict[a=>Int,b=>Optional[ArrayRef[Str]]]"', '"Dict[a=>Int,b=>Optional[ArrayRef[Str]]]" does not allow key "c" to appear in hash', ], '$dict deep explanation, given {a => 1, c => 1}', ); is_deeply( (exception { $dict->({b => 1}) })->explain, [ 'Reference {"b" => 1} did not pass type constraint "Dict[a=>Int,b=>Optional[ArrayRef[Str]]]"', '"Dict[a=>Int,b=>Optional[ArrayRef[Str]]]" requires key "a" to appear in hash', ], '$dict deep explanation, given {b => 1}', ); is_deeply( (exception { $dict->({a => 1, b => 2}) })->explain, [ 'Reference {"a" => 1,"b" => 2} did not pass type constraint "Dict[a=>Int,b=>Optional[ArrayRef[Str]]]"', '"Dict[a=>Int,b=>Optional[ArrayRef[Str]]]" constrains value at key "b" of hash with "Optional[ArrayRef[Str]]"', 'Value "2" did not pass type constraint "Optional[ArrayRef[Str]]" (in $_->{"b"})', '$_->{"b"} exists', '"Optional[ArrayRef[Str]]" constrains $_->{"b"} with "ArrayRef[Str]" if it exists', '"ArrayRef[Str]" is a subtype of "ArrayRef"', '"ArrayRef" is a subtype of "Ref"', 'Value "2" did not pass type constraint "Ref" (in $_->{"b"})', '"Ref" is defined as: (!!ref($_))', ], '$dict deep explanation, given {a => 1, b => 2}', ); TODO: { require Data::Dumper; local $TODO = (Data::Dumper->VERSION > 2.145) ? "Data::Dumper output changed after 2.145" : (Data::Dumper->VERSION < 2.121) ? "Data::Dumper too old" : undef; is_deeply( (exception { (Map[Int,Num])->({1=>1.1,2.2=>2.3,3.3=>3.4}) })->explain, [ 'Reference {1 => "1.1","2.2" => "2.3","3.3" => "3.4"} did not pass type constraint "Map[Int,Num]"', '"Map[Int,Num]" constrains each key in the hash with "Int"', 'Value "2.2" did not pass type constraint "Int" (in key $_->{"2.2"})', '"Int" is defined as: (defined $_ and $_ =~ /\A-?[0-9]+\z/)', ], 'Map[Int,Num] deep explanation, given {1=>1.1,2.2=>2.3,3.3=>3.4}', ); } TODO: { require Data::Dumper; local $TODO = (Data::Dumper->VERSION < 2.121) ? "Data::Dumper too old" : undef; my $Ext = (StrMatch[qr/^x_/])->create_child_type(name => 'Ext'); my $dict2 = Dict[foo => ArrayRef, slurpy Map[$Ext, Int]]; ok( $dict2->({ foo => [], x_bar => 1, x_baz => 2 }), "$dict2 works ok it seems", ); my $e = exception { $dict2->({foo => [], x_bar => 1, x_baz => []}) }; is_deeply( $e->explain, [ 'Reference {"foo" => [],"x_bar" => 1,"x_baz" => []} did not pass type constraint "Dict[foo=>ArrayRef,slurpy Map[Ext,Int]]"', '"Dict[foo=>ArrayRef,slurpy Map[Ext,Int]]" requires the hashref of additional key/value pairs to conform to "Map[Ext,Int]"', 'Reference {"x_bar" => 1,"x_baz" => []} did not pass type constraint "Map[Ext,Int]" (in $slurpy)', '"Map[Ext,Int]" constrains each value in the hash with "Int"', '"Int" is a subtype of "Num"', '"Num" is a subtype of "'.$supernum.'"', '"'.$supernum.'" is a subtype of "Str"', '"Str" is a subtype of "Value"', 'Reference [] did not pass type constraint "Value" (in $slurpy->{"x_baz"})', '"Value" is defined as: (defined($_) and not ref($_))' ], "$dict2 explanation, given {foo => [], x_bar => 1, x_baz => []}", ) or diag explain($e->explain); } my $AlwaysFail = Any->create_child_type(constraint => sub { 0 }); is_deeply( (exception { $AlwaysFail->(1) })->explain, [ 'Value "1" did not pass type constraint', '"__ANON__" is defined as: sub { 0; }', ], '$AlwaysFail explanation, given 1', ); my $TupleOf1 = Tuple[ Int ]; is_deeply( (exception { $TupleOf1->([1,2]) })->explain, [ 'Reference [1,2] did not pass type constraint "Tuple[Int]"', '"Tuple[Int]" expects at most 1 values in the array', '2 values found; too many', ], '$TupleOf1 explanation, given [1,2]', ); TODO: { require Data::Dumper; local $TODO = (Data::Dumper->VERSION < 2.121) ? "Data::Dumper too old" : undef; my $SlurpyThing = Tuple[ Num, slurpy Map[Str, ArrayRef] ]; is_deeply( (exception { $SlurpyThing->(1) })->explain, [ '"Tuple[Num,slurpy Map[Str,ArrayRef]]" is a subtype of "Tuple"', '"Tuple" is a subtype of "ArrayRef"', '"ArrayRef" is a subtype of "Ref"', 'Value "1" did not pass type constraint "Ref"', '"Ref" is defined as: (!!ref($_))', ], '$SlurpyThing explanation, given 1', ); is_deeply( (exception { $SlurpyThing->([[]]) })->explain, [ 'Reference [[]] did not pass type constraint "Tuple[Num,slurpy Map[Str,ArrayRef]]"', '"Tuple[Num,slurpy Map[Str,ArrayRef]]" constrains value at index 0 of array with "Num"', '"Num" is a subtype of "'.$supernum.'"', '"'.$supernum.'" is a subtype of "Str"', '"Str" is a subtype of "Value"', 'Reference [] did not pass type constraint "Value" (in $_->[0])', '"Value" is defined as: (defined($_) and not ref($_))', ], '$SlurpyThing explanation, given [[]]', ); is_deeply( (exception { $SlurpyThing->([1.1, yeah => "Hello"]) })->explain, [ 'Reference ["1.1","yeah","Hello"] did not pass type constraint "Tuple[Num,slurpy Map[Str,ArrayRef]]"', 'Array elements from index 1 are slurped into a hashref which is constrained with "Map[Str,ArrayRef]"', 'Reference {"yeah" => "Hello"} did not pass type constraint "Map[Str,ArrayRef]" (in $SLURPY)', '"Map[Str,ArrayRef]" constrains each value in the hash with "ArrayRef"', '"ArrayRef" is a subtype of "Ref"', 'Value "Hello" did not pass type constraint "Ref" (in $SLURPY->{"yeah"})', '"Ref" is defined as: (!!ref($_))', ], '$SlurpyThing explanation, given [1.1, yeah => "Hello"]', ); } my $UndefRef = ScalarRef[Undef]; is_deeply( (exception { $UndefRef->(do { my $x = "bar"; \$x }) })->explain, [ 'Reference \\"bar" did not pass type constraint "ScalarRef[Undef]"', '"ScalarRef[Undef]" constrains the referenced scalar value with "Undef"', 'Value "bar" did not pass type constraint "Undef" (in ${$_})', '"Undef" is defined as: (!defined($_))', ], '$UndefRef explanantion, given \"bar"', ); is_deeply( (exception { $UndefRef->([]) })->explain, [ '"ScalarRef[Undef]" is a subtype of "ScalarRef"', 'Reference [] did not pass type constraint "ScalarRef"', '"ScalarRef" is defined as: (ref($_) eq \'SCALAR\' or ref($_) eq \'REF\')', ], '$UndefRef explanantion, given []', ); my $e_where = exception { #line 1 "thisfile.plx" package Monkey::Nuts; "Error::TypeTiny"->throw(message => "Test"); }; #line 230 "exceptions.t" is_deeply( $e_where->context, { package => "Monkey::Nuts", file => "thisfile.plx", line => 2, }, '$e_where->context', ); is( "$e_where", "Test at thisfile.plx line 2.\n", '"$e_where"', ); BEGIN { package MyTypes; use Type::Library -base, -declare => qw(HttpMethod); use Type::Utils -all; use Types::Standard qw(Enum); declare HttpMethod, as Enum[qw/ HEAD GET POST PUT DELETE OPTIONS PATCH /], message { "$_ is not a HttpMethod" }; }; like( exception { MyTypes::HttpMethod->("FOOL") }, qr{^FOOL is not a HttpMethod}, "correct exception from type with null constraint", ); { local $Type::Tiny::DD = sub { substr("$_[0]", 0, 5) }; like( exception { Types::Standard::Str->([]) }, qr{^ARRAY did not pass type constraint}, "local \$Type::Tiny::DD", ); } done_testing; basic.t000664001750001750 302712422772210 22440 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Error-TypeTiny-Compilation=pod =encoding utf-8 =head1 PURPOSE Tests for L, mostly by triggering compilation errors using L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Fatal; use Eval::TypeTiny; my $e = exception { no warnings qw(void); 0; 1; 2; #line 38 "basic.t" eval_closure( source => 'sub { 1 ]', environment => { '$x' => do { my $x = 42; \$x } }, ); 3; 4; 5; 6; }; isa_ok( $e, 'Error::TypeTiny::Compilation', '$e', ); like( $e, qr{^Failed to compile source because: syntax error}, 'throw exception when code does not compile', ); like( $e->message, qr{^Failed to compile source because: syntax error}, '$e->message', ); subtest '$e->context' => sub { my $ctx = $e->context; is($ctx->{package}, 'main', '$ctx->{package}'); is($ctx->{file}, 'basic.t', '$ctx->{file}'); ok($ctx->{line} >= 37, '$ctx->{line} >= 37') or diag('line is '.$ctx->{line}); ok($ctx->{line} <= 42, '$ctx->{line} <= 42') or diag('line is '.$ctx->{line}); }; like( $e->errstr, qr{^syntax error}, '$e->errstr', ); like( $e->code, qr{sub \{ 1 \]}, '$e->code', ); is_deeply( $e->environment, { '$x' => do { my $x = 42; \$x } }, '$e->environment', ); done_testing; basic.t000664001750001750 465612422772210 24751 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Error-TypeTiny-WrongNumberOfParameters=pod =encoding utf-8 =head1 PURPOSE Test L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; use Test::Fatal; use Type::Params qw(compile); use Types::Standard qw(Num Optional slurpy ArrayRef); my $check1; sub nth_root { $check1 ||= compile( Num, Num ); [ $check1->(@_) ]; } subtest "nth_root()" => sub { my $e = exception { nth_root() }; ok($e->has_minimum); is($e->minimum, 2); ok($e->has_maximum); is($e->maximum, 2); is($e->got, 0); like($e, qr{^Wrong number of parameters; got 0; expected 2}); }; subtest "nth_root(1)" => sub { my $e = exception { nth_root(1) }; ok($e->has_minimum); is($e->minimum, 2); ok($e->has_maximum); is($e->maximum, 2); is($e->got, 1); like($e, qr{^Wrong number of parameters; got 1; expected 2}); }; subtest "nth_root(1, 2, 3)" => sub { my $e = exception { nth_root(1, 2, 3) }; ok($e->has_minimum); is($e->minimum, 2); ok($e->has_maximum); is($e->maximum, 2); is($e->got, 3); like($e, qr{^Wrong number of parameters; got 3; expected 2}); }; my $check2; sub nth_root_opt { $check2 ||= compile( Num, Optional[Num] ); [ $check2->(@_) ]; } subtest "nth_root_opt()" => sub { my $e = exception { nth_root_opt() }; ok($e->has_minimum); is($e->minimum, 1); ok($e->has_maximum); is($e->maximum, 2); is($e->got, 0); like($e, qr{^Wrong number of parameters; got 0; expected 1 to 2}); }; my $check3; sub nth_root_slurp { $check3 ||= compile( Num, slurpy ArrayRef[Num] ); [ $check3->(@_) ]; } subtest "nth_root_slurp()" => sub { my $e = exception { nth_root_slurp() }; ok($e->has_minimum); is($e->minimum, 1); ok(!$e->has_maximum); is($e->maximum, undef); is($e->got, 0); like($e, qr{^Wrong number of parameters; got 0; expected at least 1}); }; my $silly = exception { Error::TypeTiny::WrongNumberOfParameters->throw( minimum => 3, maximum => 2, got => 0, ); }; like($silly, qr{^Wrong number of parameters; got 0}, 'silly exception which should never happen anyway'); my $unspecific = exception { Error::TypeTiny::WrongNumberOfParameters->throw(got => 0); }; like($unspecific, qr{^Wrong number of parameters; got 0}, 'unspecific exception'); done_testing; basic.t000664001750001750 623112422772210 17762 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Eval-TypeTiny=pod =encoding utf-8 =head1 PURPOSE Tests L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Fatal; use Eval::TypeTiny; my %env = ( '$foo' => do { my $x = "foo"; \$x }, '@bar' => [ "bar" ], '%baz' => { "baz" => "1" }, ); my $source = <<'SRC'; sub { return $foo if $_[0] eq '$foo'; return @bar if $_[0] eq '@bar'; return %baz if $_[0] eq '%baz'; return; } SRC my $closure = eval_closure(source => $source, environment => \%env); is_deeply( [ $closure->('$foo') ], [ 'foo' ], 'closure over scalar', ); is_deeply( [ $closure->('@bar') ], [ 'bar' ], 'closure over array', ); is_deeply( [ $closure->('%baz') ], [ 'baz' => 1 ], 'closure over hash', ); my $external = 40; my $closure2 = eval_closure( source => 'sub { $xxx += 2 }', environment => { '$xxx' => \$external }, alias => 1, ); $closure2->(); is($external, 42, 'closing over variables really really really works!'); { my $destroyed = 0; { package MyIndicator; sub DESTROY { $destroyed++ } } { my $number = bless \(my $foo), "MyIndicator"; $$number = 40; my $closure = eval_closure( source => 'sub { $$xxx += 2 }', environment => { '$xxx' => \$number }, alias => 1, ); $closure->(); is($$number, 42); is($destroyed, 0); } is($destroyed, 1, 'closed over variables disappear on cue'); } { my @store; { package MyTie; use Tie::Scalar (); our @ISA = 'Tie::StdScalar'; sub STORE { my $self = shift; push @store, $_[0]; $self->SUPER::STORE(@_); } sub method_of_mine { 42 } } tie(my($var), 'MyTie'); $var = 1; my $closure = eval_closure( source => 'sub { $xxx = $_[0]; tied($xxx)->method_of_mine }', environment => { '$xxx' => \$var }, alias => 1, ); is($closure->(2), 42, 'can close over tied variables ... AUTOLOAD stuff'); $closure->(3); my $nother_closure = eval_closure( source => 'sub { tied($xxx)->can(@_) }', environment => { '$xxx' => \$var }, alias => 1, ); ok( $nother_closure->('method_of_mine'), '... can'); ok(!$nother_closure->('your_method'), '... !can'); is_deeply( \@store, [ 1 .. 3], '... tie still works', ); { package OtherTie; our @ISA = 'MyTie'; sub method_of_mine { 666 } } tie($var, 'OtherTie'); is($closure->(4), 666, '... can be retied'); untie($var); my $e = exception { $closure->(5) }; like($e, qr{^Can't call method "method_of_mine" on an undefined value}, '... can be untied'); } my $c1 = eval_closure(source => 'sub { die("BANG") }', description => 'test1'); my $e1 = exception { $c1->() }; like( $e1, qr{^BANG at test1 line 1}, '"description" option works', ); my $c2 = eval_closure(source => 'sub { die("BANG") }', description => 'test2', line => 222); my $e2 = exception { $c2->() }; like( $e2, qr{^BANG at test2 line 222}, '"line" option works', ); done_testing; fallback-aliases.t000664001750001750 736112422772210 22064 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Eval-TypeTiny=pod =encoding utf-8 =head1 PURPOSE Tests L supports alias=>1 even when L is unavailable. =head1 DEPENDENCIES Requires L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; BEGIN { plan skip_all => "test currently not working (TODO)" }; use Test::Requires 'Test::Without::Module'; use Test::Without::Module 'Devel::LexAlias'; use Eval::TypeTiny; my %env = ( '$foo' => do { my $x = "foo"; \$x }, '@bar' => [ "bar" ], '%baz' => { "baz" => "1" }, ); my $source = <<'SRC'; sub { return $foo if $_[0] eq '$foo'; return @bar if $_[0] eq '@bar'; return %baz if $_[0] eq '%baz'; return; } SRC my $closure = eval_closure(source => $source, environment => \%env); is_deeply( [ $closure->('$foo') ], [ 'foo' ], 'closure over scalar', ); is_deeply( [ $closure->('@bar') ], [ 'bar' ], 'closure over array', ); is_deeply( [ $closure->('%baz') ], [ 'baz' => 1 ], 'closure over hash', ); my $external = 40; my $closure2 = eval_closure( source => 'sub { $xxx += 2 }', environment => { '$xxx' => \$external }, alias => 1, ); $closure2->(); is($external, 42, 'closing over variables really really really works!'); { my $destroyed = 0; { package MyIndicator; sub DESTROY { $destroyed++ } } { my $number = bless \(my $foo), "MyIndicator"; $$number = 40; my $closure = eval_closure( source => 'sub { $$xxx += 2 }', environment => { '$xxx' => \$number }, alias => 1, ); $closure->(); is($$number, 42); is($destroyed, 0); } is($destroyed, 1, 'closed over variables disappear on cue'); } { my @store; { package MyTie; use Tie::Scalar (); our @ISA = 'Tie::StdScalar'; sub STORE { my $self = shift; push @store, $_[0]; $self->SUPER::STORE(@_); } sub method_of_mine { 42 } } tie(my($var), 'MyTie'); $var = 1; my $closure = eval_closure( source => 'sub { $xxx = $_[0]; tied($xxx)->method_of_mine }', environment => { '$xxx' => \$var }, alias => 1, ); is($closure->(2), 42, 'can close over tied variables ... AUTOLOAD stuff'); $closure->(3); my $nother_closure = eval_closure( source => 'sub { tied($xxx)->can(@_) }', environment => { '$xxx' => \$var }, alias => 1, ); ok( $nother_closure->('method_of_mine'), '... can'); ok(!$nother_closure->('your_method'), '... !can'); is_deeply( \@store, [ 1 .. 3], '... tie still works', ); { package OtherTie; our @ISA = 'MyTie'; sub method_of_mine { 666 } } tie($var, 'OtherTie'); is($closure->(4), 666, '... can be retied'); untie($var); my $e = exception { $closure->(5) }; like($e, qr{^Can't call method "method_of_mine" on an undefined value}, '... can be untied'); } my $e = exception { eval_closure(source => 'sub { 1 ]') }; isa_ok( $e, 'Error::TypeTiny::Compilation', '$e', ); like( $e, qr{^Failed to compile source because: syntax error}, 'throw exception when code does not compile', ); like( $e->errstr, qr{^syntax error}, '$e->errstr', ); like( $e->code, qr{sub \{ 1 \]}, '$e->code', ); my $c1 = eval_closure(source => 'sub { die("BANG") }', description => 'test1'); my $e1 = exception { $c1->() }; like( $e1, qr{^BANG at test1 line 1}, '"description" option works', ); my $c2 = eval_closure(source => 'sub { die("BANG") }', description => 'test2', line => 222); my $e2 = exception { $c2->() }; like( $e2, qr{^BANG at test2 line 222}, '"line" option works', ); done_testing; lexical-subs.t000664001750001750 432312422772210 21274 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Eval-TypeTiny=pod =encoding utf-8 =head1 PURPOSE Tests L with experimental lexical subs. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Requires 'v5.18'; use Test::Fatal; use Eval::TypeTiny; my $variable; my %env = ( '$foo' => do { my $x = "foo"; \$x }, '@bar' => [ "bar" ], '%baz' => { "baz" => "1" }, '&quux' => sub { $variable }, '&quuux' => sub { $variable + 40 }, ); my $source = <<'SRC'; sub { return $foo if $_[0] eq '$foo'; return @bar if $_[0] eq '@bar'; return %baz if $_[0] eq '%baz'; return quux() if $_[0] eq '&quux'; return quuux if $_[0] eq '&quuux'; return; } SRC my $closure = eval_closure(source => $source, environment => \%env); is_deeply( [ $closure->('$foo') ], [ 'foo' ], 'closure over scalar', ); is_deeply( [ $closure->('@bar') ], [ 'bar' ], 'closure over array', ); is_deeply( [ $closure->('%baz') ], [ 'baz' => 1 ], 'closure over hash', ); is_deeply( [ $closure->('&quux') ], [ undef ], 'closure over lexical sub - undef', ); $variable = 2; is_deeply( [ $closure->('&quux') ], [ 2 ], 'closure over lexical sub - 2', ); is_deeply( [ $closure->('&quuux') ], [ 42 ], 'closure over lexical sub - 42', ); my $e = exception { eval_closure(source => 'sub { 1 ]') }; isa_ok( $e, 'Error::TypeTiny::Compilation', '$e', ); like( $e, qr{^Failed to compile source because: syntax error}, 'throw exception when code does not compile', ); like( $e->errstr, qr{^syntax error}, '$e->errstr', ); like( $e->code, qr{sub \{ 1 \]}, '$e->code', ); my $c1 = eval_closure(source => 'sub { die("BANG") }', description => 'test1'); my $e1 = exception { $c1->() }; like( $e1, qr{^BANG at test1 line 1}, '"description" option works', ); my $c2 = eval_closure(source => 'sub { die("BANG") }', description => 'test2', line => 222); my $e2 = exception { $c2->() }; like( $e2, qr{^BANG at test2 line 222}, '"line" option works', ); done_testing; basic.t000664001750001750 367212422772210 20020 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Test-TypeTiny=pod =encoding utf-8 =head1 PURPOSE Tests L (which is somewhat important because Test::TypeTiny is itself used for the majority of the type constraint tests). In particular, this tests that everything works when the C<< $EXTENDED_TESTING >> environment variable is false. =head1 DEPENDENCIES Requires L 0.109. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; BEGIN { $ENV{EXTENDED_TESTING} = 0; if (eval { require Test::Tester }) { Test::Tester->import(tests => 48); } else { require Test::More; Test::More->import(skip_all => 'requires Test::Tester'); } } use Test::TypeTiny; use Types::Standard qw( Int Num ); check_test( sub { should_pass(1, Int) }, { ok => 1, name => 'Value "1" passes type constraint Int', diag => '', type => '', }, 'successful should_pass', ); check_test( sub { should_pass([], Int) }, { ok => 0, name => 'Reference [] passes type constraint Int', diag => '', type => '', }, 'unsuccessful should_pass', ); check_test( sub { should_fail([], Int) }, { ok => 1, name => 'Reference [] fails type constraint Int', diag => '', type => '', }, 'successful (i.e. failing) should_fail', ); check_test( sub { should_fail(1, Int) }, { ok => 0, name => 'Value "1" fails type constraint Int', diag => '', type => '', }, 'unsuccessful (i.e. passing) should_fail', ); check_test( sub { ok_subtype(Num, Int) }, { ok => 1, name => 'Num subtype: Int', diag => '', type => '', }, 'successful ok_subtype', ); check_test( sub { ok_subtype(Int, Num) }, { ok => 0, name => 'Int subtype: Num', diag => '', type => '', }, 'unsuccessful ok_subtype', ); extended.t000664001750001750 226712422772210 20536 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Test-TypeTiny=pod =encoding utf-8 =head1 PURPOSE Tests L works when the C<< $EXTENDED_TESTING >> environment variable is true. Note that L appears to have issues with subtests, so currently C and C are not tested. =head1 DEPENDENCIES Requires L 0.109. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; BEGIN { $ENV{EXTENDED_TESTING} = 1; if (eval { require Test::Tester }) { Test::Tester->import(tests => 16); } else { require Test::More; Test::More->import(skip_all => 'requires Test::Tester'); } } use Test::TypeTiny; use Types::Standard qw( Int Num ); check_test( sub { ok_subtype(Num, Int) }, { ok => 1, name => 'Num subtype: Int', diag => '', type => '', }, 'successful ok_subtype', ); check_test( sub { ok_subtype(Int, Num) }, { ok => 0, name => 'Int subtype: Num', diag => '', type => '', }, 'unsuccessful ok_subtype', ); matchfor.t000664001750001750 316512422772210 20537 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Test-TypeTiny=pod =encoding utf-8 =head1 PURPOSE Tests L (which is somewhat important because Test::TypeTiny is itself used for the majority of the type constraint tests). In particular, this tests that everything works when the C<< $EXTENDED_TESTING >> environment variable is false. =head1 DEPENDENCIES Requires L 0.109. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; BEGIN { $ENV{EXTENDED_TESTING} = 0; if (eval { require Test::Tester }) { require Test::More; Test::Tester->import(tests => 24); } else { require Test::More; Test::More->import(skip_all => 'requires Test::Tester'); } } use Test::TypeTiny qw(matchfor); check_test( sub { Test::More::is( "Hello world", matchfor(qr/hello/i, qr/hiya/i, "Greeting::Global"), 'Yahoo', ); }, { ok => 1, name => 'Yahoo', diag => '', type => '', }, 'successful matchfor(qr//)', ); check_test( sub { Test::More::is( "Hiya world", matchfor(qr/hello/i, qr/hiya/i, "Greeting::Global"), 'Yahoo', ); }, { ok => 1, name => 'Yahoo', diag => '', type => '', }, 'successful matchfor(qr//)', ); check_test( sub { Test::More::is( bless({}, "Greeting::Global"), matchfor(qr/hello/i, qr/hiya/i, "Greeting::Global"), 'Yahoo', ); }, { ok => 1, name => 'Yahoo', diag => '', type => '', }, 'successful matchfor(CLASS)', ); basic.t000664001750001750 751112422772210 17772 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Coercion=pod =encoding utf-8 =head1 PURPOSE Checks Type::Coercion works. =head1 DEPENDENCIES Uses the bundled BiggerLib.pm type library. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Fatal; use BiggerLib -types, -coercions; is( BigInteger->coercion->coerce(2), 12, 'coercion works', ); is( BigInteger->coercion->(2), 12, 'coercion overloads &{}', ); ok( BigInteger->coercion->has_coercion_for_type(ArrayRef), 'BigInteger has_coercion_for_type ArrayRef', ); ok( BigInteger->coercion->has_coercion_for_type(SmallInteger), 'BigInteger has_coercion_for_type SmallInteger', ); ok( !BigInteger->coercion->has_coercion_for_type(HashRef), 'not BigInteger has_coercion_for_type SmallInteger', ); cmp_ok( BigInteger->coercion->has_coercion_for_type(BigInteger), eq => '0 but true', 'BigInteger has_coercion_for_type BigInteger eq "0 but true"' ); my $BiggerInteger = BigInteger->create_child_type( constraint => sub { $_ > 1_000_000 }, ); cmp_ok( BigInteger->coercion->has_coercion_for_type($BiggerInteger), eq => '0 but true', 'BigInteger has_coercion_for_type $BiggerInteger eq "0 but true"' ); ok( BigInteger->coercion->has_coercion_for_value([]), 'BigInteger has_coercion_for_value []', ); ok( BigInteger->coercion->has_coercion_for_value(2), 'BigInteger has_coercion_for_value 2', ); ok( !BigInteger->coercion->has_coercion_for_value({}), 'not BigInteger has_coercion_for_value {}', ); cmp_ok( BigInteger->coercion->has_coercion_for_value(200), eq => '0 but true', 'BigInteger has_coercion_for_value 200 eq "0 but true"' ); is( exception { BigInteger->coerce([]) }, undef, "coerce doesn't throw an exception if it can coerce", ); is( exception { BigInteger->coerce({}) }, undef, "coerce doesn't throw an exception if it can't coerce", ); is( exception { BigInteger->assert_coerce([]) }, undef, "assert_coerce doesn't throw an exception if it can coerce", ); like( exception { BigInteger->assert_coerce({}) }, qr{^Reference \{\} did not pass type constraint "BigInteger"}, "assert_coerce DOES throw an exception if it can't coerce", ); isa_ok( ArrayRefFromAny, 'Type::Coercion', 'ArrayRefFromAny', ); is_deeply( ArrayRefFromAny->coerce(1), [1], 'ArrayRefFromAny coercion works', ); my $sum1 = 'Type::Coercion'->add(ArrayRefFromAny, ArrayRefFromPiped); is_deeply( $sum1->coerce("foo|bar"), ["foo|bar"], "Coercion $sum1 prioritizes ArrayRefFromAny", ); my $sum2 = 'Type::Coercion'->add(ArrayRefFromPiped, ArrayRefFromAny); is_deeply( $sum2->coerce("foo|bar"), ["foo","bar"], "Coercion $sum2 prioritizes ArrayRefFromPiped", ); my $arr = ArrayRef->plus_fallback_coercions(ArrayRefFromAny); is_deeply( $arr->coerce("foo|bar"), ["foo|bar"], "Type \$arr coercion works", ); my $sum3 = $arr->plus_fallback_coercions(ArrayRefFromPiped); is_deeply( $sum3->coerce("foo|bar"), ["foo|bar"], "Type \$sum3 coercion works", ); my $sum4 = $arr->plus_coercions(ArrayRefFromPiped); is_deeply( $sum4->coerce("foo|bar"), ["foo","bar"], "Type \$sum4 coercion works", ); use Test::TypeTiny; my $arrayref_from_piped = ArrayRef->plus_coercions(ArrayRefFromPiped); my $coercibles = $arrayref_from_piped->coercibles; should_pass([], $coercibles); should_pass('1|2|3', $coercibles); should_fail({}, $coercibles); should_pass([], ArrayRef->coercibles); should_fail('1|2|3', ArrayRef->coercibles); should_fail({}, ArrayRef->coercibles); is($arrayref_from_piped->coercibles, $arrayref_from_piped->coercibles, '$arrayref_from_piped->coercibles == $arrayref_from_piped->coercibles'); done_testing; esoteric.t000664001750001750 246712422772210 20533 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Coercion=pod =encoding utf-8 =head1 PURPOSE Checks various undocumented Type::Coercion methods. The fact that these are tested here should not be construed to mean tht they are any any way a stable, supported part of the Type::Coercion API. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Fatal; use Test::TypeTiny; use Type::Coercion; use Types::Standard -types; my $type = Int->create_child_type; $type->coercion->add_type_coercions( Num, q[int($_)] ); like( exception { $type->coercion->meta }, qr/^Not really a Moose::Meta::TypeCoercion/, '$type->coercion->meta', ); $type->coercion->_compiled_type_coercion( Type::Coercion->new( type_coercion_map => [ ArrayRef, q[666] ], ), ); $type->coercion->_compiled_type_coercion( sub { 999 }, ); is($type->coerce(3.1), 3, '$type->coercion->add_type_coercions(TYPE, STR)'); is($type->coerce([]), 666, '$type->coercion->_compiled_type_coercion(OBJECT)'); is($type->coerce(undef), 999, '$type->coercion->_compiled_type_coercion(CODE)'); done_testing; frozen.t000664001750001750 324712422772210 20216 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Coercion=pod =encoding utf-8 =head1 PURPOSE Type::Coercion objects are mutable, unlike Type::Tiny objects. However, they can be frozen, making them immutable. (And Type::Tiny will freeze them occasionally, if it feels it has to.) =head1 DEPENDENCIES Uses the bundled BiggerLib.pm type library. Requires Moose 2.0000 =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::Requires { Moose => 2.0000 }; use Test::More; use Test::Fatal; use BiggerLib -types; ok(!BigInteger->coercion->frozen, 'coercions are not initially frozen'); BigInteger->coercion->add_type_coercions(Undef, sub { 777 }); ok(!BigInteger->coercion->frozen, 'coercions do not freeze because of adding code'); is(BigInteger->coerce(undef), 777, '... and they work'); BigInteger->coercion->moose_coercion; ok(BigInteger->coercion->frozen, 'coercions do freeze when forced inflation to Moose'); my $e = exception { BigInteger->coercion->add_type_coercions(Item, sub { 999 }) }; like($e, qr{Attempt to add coercion code to a Type::Coercion which has been frozen}, 'cannot add code to a frozen coercion'); BigInteger->coercion->i_really_want_to_unfreeze; ok(!BigInteger->coercion->frozen, 'i_really_want_to_unfreeze'); $e = exception { BigInteger->coercion->add_type_coercions(Item, sub { 888 }) }; is($e, undef, '... can now add coercions'); is(BigInteger->coerce(\$e), 888, '... ... which work'); done_testing; inlining.t000664001750001750 255412422772210 20522 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Coercion=pod =encoding utf-8 =head1 PURPOSE Checks Type::Coercion can be inlined. =head1 DEPENDENCIES Requires JSON::PP 2.27105. Test is skipped if this module is not present. Note that this is bundled with Perl v5.13.11 and above. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::Requires { "JSON::PP" => "2.27105" }; use Test::More; use Test::Fatal; { package T; require JSON::PP; use Type::Library -base, -declare => qw/ JsonHash JsonArray /; use Type::Utils; use Types::Standard -types; declare JsonHash, as HashRef; declare JsonArray, as ArrayRef; coerce JsonHash, from Str, 'JSON::PP::decode_json($_)'; coerce JsonArray, from Str, 'JSON::PP::decode_json($_)'; __PACKAGE__->meta->make_immutable; } my $code = T::JsonArray->coercion->inline_coercion('$::foo'); our $foo = "[3,2,1]"; is_deeply( eval $code, [3,2,1], 'inlined coercion works', ); $foo = [5,4,3]; is_deeply( eval $code, [5,4,3], 'no coercion necessary', ); $foo = {foo => "bar"}; is_deeply( eval $code, {foo => "bar"}, 'no coercion possible', ); done_testing; parameterized.t000664001750001750 1111412422772210 21557 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Coercion=pod =encoding utf-8 =head1 PURPOSE Checks the C and C parameterized coercions from L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( . ./t ../inc ./inc ); use utf8; use Test::More; use Test::Requires { "Encode" => 0 }; use Test::TypeTiny; use Encode; use Types::Standard qw( Str ArrayRef HashRef Join Split ); use Type::Utils; my $chars = "Café Paris|Garçon"; my $bytes_utf8 = Encode::encode("utf-8", $chars); my $bytes_western = Encode::encode("iso-8859-1", $chars); is(length($chars), 17, 'length $chars == 17'); is(length($bytes_utf8), 19, 'length $bytes_utf8 == 19'); is(length($bytes_western), 17, 'length $bytes_western == 17'); my $SplitSpace = (ArrayRef[Str])->plus_coercions(Split[qr/\s/]); my $SplitPipe = (ArrayRef[Str])->plus_coercions(Split[qr/\|/]); ok($SplitSpace->can_be_inlined, '$SplitSpace can be inlined'); ok($SplitPipe->can_be_inlined, '$SplitPipe can be inlined'); is_deeply( $SplitSpace->coerce($chars), [ "Café", "Paris|Garçon" ], '$SplitSpace->coerce($chars)', ); is_deeply( $SplitSpace->coerce($bytes_utf8), [ map Encode::encode("utf-8", $_), "Café", "Paris|Garçon" ], '$SplitSpace->coerce($bytes_utf8)', ); is_deeply( $SplitSpace->coerce($bytes_western), [ map Encode::encode("iso-8859-1", $_), "Café", "Paris|Garçon" ], '$SplitSpace->coerce($bytes_western)', ); should_pass($SplitSpace->coerce($chars), ArrayRef[Str]); should_pass($SplitSpace->coerce($bytes_utf8), ArrayRef[Str]); should_pass($SplitSpace->coerce($bytes_western), ArrayRef[Str]); is_deeply( my $arr_chars = $SplitPipe->coerce($chars), [ "Café Paris", "Garçon" ], '$SplitPipe->coerce($chars)', ); is_deeply( my $arr_bytes_utf8 = $SplitPipe->coerce($bytes_utf8), [ map Encode::encode("utf-8", $_), "Café Paris", "Garçon" ], '$SplitPipe->coerce($bytes_utf8)', ); is_deeply( my $arr_bytes_western = $SplitPipe->coerce($bytes_western), [ map Encode::encode("iso-8859-1", $_), "Café Paris", "Garçon" ], '$SplitPipe->coerce($bytes_western)', ); my $JoinPipe = Str->plus_coercions(Join["|"]); is( $_ = $JoinPipe->coerce($arr_chars), $chars, '$JoinPipe->coerce($arr_chars)', ); should_pass($_, Str); is( $_ = $JoinPipe->coerce($arr_bytes_utf8), $bytes_utf8, '$JoinPipe->coerce($arr_bytes_utf8)', ); should_pass($_, Str); is( $_ = $JoinPipe->coerce($arr_bytes_western), $bytes_western, '$JoinPipe->coerce($arr_bytes_western)', ); should_pass($_, Str); # Re-parameterization stuff: { # A type constraint with a useless parameter... # my $Stringy = Str->create_child_type( name => 'Stringy', parent => Str, constraint_generator => sub { sub {} }, ); ok($Stringy->is_parameterizable, '$Stringy->is_parameterizable'); # A parameterizable coercion... my $Joiny = 'Type::Coercion'->new( name => 'Joiny', type_constraint => $Stringy, type_coercion_map => [ HashRef, sub { 'hello' } ], coercion_generator => sub { my ($self, $type, $from, $to) = @_; my $joinchar = ':'; if ($type->is_a_type_of($Stringy) and $type->is_parameterized) { $joinchar = $type->type_parameter; } return ( @{ $self->type_coercion_map }, ArrayRef, sub { my @arr = @$_; join($joinchar, @arr[$from..$to]) }, ); }, ); isa_ok( $Joiny, 'Type::Coercion', 'parameterizable coercion', ); is( $Joiny->coerce({}), 'hello', '... coercion included in base definition works' ); is_deeply( $Joiny->coerce(['a'..'z']), ['a'..'z'], '... coercion generated by parameterization does not exist yet' ); my $Joiny23 = $Joiny->parameterize(2, 3); isa_ok( $Joiny23, 'Type::Coercion', 'parameterized coercion which has not yet been combined with type constraint', ); is( $Joiny23->coerce({}), 'hello', '... coercion included in base definition works' ); is( $Joiny23->coerce(['a'..'z']), 'c:d', '... coercion generated by parameterization works' ); my $StringyPipe = $Stringy->parameterize('|')->plus_coercions($Joiny23); isa_ok( $StringyPipe, 'Type::Tiny', 'type constraint consuming parameterized coercion', ); is( $StringyPipe->coerce({}), 'hello', '... coercion included in base definition works' ); is( $StringyPipe->coerce(['a'..'z']), 'c|d', '... coercion generated by parameterization works; must have been regenerated' ); } done_testing; smartmatch.t000664001750001750 146012422772210 21051 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Coercion=pod =encoding utf-8 =head1 PURPOSE Checks Type::Coercion overload of C<< ~~ >>. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; BEGIN { $] < 5.010001 ? plan(skip_all => "Perl too old") : $] >= 5.021000 ? plan(skip_all => "Perl too new") : $] >= 5.018000 ? warnings->unimport('experimental::smartmatch') : (); }; use Types::Standard qw( Num Int ); my $type = Int->plus_coercions( Num, sub{+int} ); ok ( 3.1 ~~ $type->coercion ); ok not ( [ ] ~~ $type->coercion ); done_testing; typetiny-constructor.t000664001750001750 212012422772210 23150 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Coercion=pod =encoding utf-8 =head1 PURPOSE Checks proper Type::Coercion objects are automatically created by the Type::Tiny constructor. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Fatal; use Type::Tiny; use Types::Standard qw( Int Num Any ); subtest "coercion => ARRAY" => sub { my $type = Type::Tiny->new( name => 'Test', parent => Int, coercion => [ Num, sub { int($_) } ], ); ok $type->has_coercion; is $type->coercion->type_coercion_map->[0], Num; is $type->coerce(3.2), 3; }; subtest "coercion => CODE" => sub { my $type = Type::Tiny->new( name => 'Test', parent => Int, coercion => sub { int($_) }, ); ok $type->has_coercion; is $type->coercion->type_coercion_map->[0], Any; is $type->coerce(3.2), 3; }; done_testing; basic.t000664001750001750 334212422772210 21674 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Coercion-FromMoose=pod =encoding utf-8 =head1 PURPOSE Checks the types adopted from Moose still have a coercion which works. =head1 DEPENDENCIES Moose 2.0600; otherwise skipped. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Requires { Moose => '2.0600' }; use Test::TypeTiny; use Moose::Util::TypeConstraints; my $Rounded = do { subtype 'RoundedInt', as 'Int'; coerce 'RoundedInt', from 'Num', via { int($_) }; find_type_constraint 'RoundedInt'; }; my $Array_of_Rounded = do { use Types::Standard -types; ArrayRef[$Rounded]; }; isa_ok( $Array_of_Rounded->type_parameter, 'Type::Tiny', '$Array_of_Rounded->type_parameter', ); isa_ok( $Array_of_Rounded->type_parameter->coercion, 'Type::Coercion', '$Array_of_Rounded->type_parameter->coercion', ); isa_ok( $Array_of_Rounded->type_parameter->coercion, 'Type::Coercion::FromMoose', '$Array_of_Rounded->type_parameter->coercion', ); is_deeply( $Array_of_Rounded->coerce([ 9.1, 1.1, 2.2, 3.3 ]), [ 9, 1..3 ], 'coercion works', ); # Making this work might prevent coercions from being inlined # unless the coercion has been frozen. # # See https://rt.cpan.org/Ticket/Display.html?id=93345#txn-1395097 # TODO: { local $TODO = "\$Array_of_Rounded's coercion has already been compiled"; coerce 'RoundedInt', from 'Undef', via { 0 }; is_deeply( $Array_of_Rounded->coerce([ 9.1, 1.1, undef, 3.3 ]), [ 9, 1, 0, 3 ], 'coercion can be altered later', ); }; done_testing; errors.t000664001750001750 316412422772210 22131 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Coercion-FromMoose=pod =encoding utf-8 =head1 PURPOSE Checks crazy Type::Coercion::FromMoose errors. =head1 DEPENDENCIES Moose 2.0600; otherwise skipped. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Requires { Moose => '2.0600' }; use Test::Fatal; use Types::Standard -types; use Types::TypeTiny qw( to_TypeTiny ); use Scalar::Util qw(refaddr); my $orig = do { use Moose::Util::TypeConstraints; subtype 'RoundedInt', as 'Int'; coerce 'RoundedInt', from 'Num', via { int($_) }; find_type_constraint 'RoundedInt'; }; my $type = to_TypeTiny($orig); is( refaddr($type->coercion->moose_coercion), refaddr($orig->coercion), ); is( refaddr($type->moose_type->coercion), refaddr($orig->coercion), ); TODO: { local $TODO = "Adding coercions to Type::Coercion::FromMoose not currently supported"; is( exception { $type->coercion->add_type_coercions(Any, sub {666}) }, undef, 'no exception adding coercions to a Moose-imported type constraint', ); is( $type->coerce([]), 666, '... and the coercion works' ); }; # Fake a T:C:FromMoose where the Type::Tiny object has been reaped... require Type::Coercion::FromMoose; my $dummy = Type::Coercion::FromMoose->new; like ( exception { $dummy->moose_coercion }, qr/^The type constraint attached to this coercion has been garbage collected... PANIC/, ); done_testing; basic.t000664001750001750 502612422772210 21057 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Coercion-Union=pod =encoding utf-8 =head1 PURPOSE Checks Type::Coercion::Union works. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Fatal; use Test::TypeTiny; use Types::Standard -types; use Type::Utils; my $RoundedInteger = declare RoundedInteger => as Int; $RoundedInteger->coercion->add_type_coercions(Num, 'int($_)')->freeze; should_pass("4", $RoundedInteger); should_fail("1.1", $RoundedInteger); should_fail("xyz", $RoundedInteger); my $String3 = declare String3 => as StrMatch[qr/^.{3}$/]; $String3->coercion->add_type_coercions(Str, 'substr("$_ ", 0, 3)')->freeze; should_pass("xyz", $String3); should_fail("x", $String3); should_fail("wxyz", $String3); my $Union1 = union Union1 => [$RoundedInteger, $String3]; should_pass("3.4", $Union1); should_pass("30", $Union1); should_fail("3.12", $Union1); should_fail("wxyz", $Union1); is( $RoundedInteger->coerce("3.4"), "3", "RoundedInteger coerces from Num", ); is( $RoundedInteger->coerce("xyz"), "xyz", "RoundedInteger does not coerce from Str", ); is( $String3->coerce("30"), "30 ", "String3 coerces from Str", ); my $arr = []; is( $String3->coerce($arr), $arr, "String3 does not coerce from ArrayRef", ); ok( $Union1->has_coercion, "unions automatically have a coercion if their child constraints do", ); note $Union1->coercion->inline_coercion('$X'); ok( union([Str, ArrayRef]), "unions do not automatically have a coercion if their child constraints do not", ); is( $Union1->coerce("4"), "4", "Union1 does not need to coerce an Int", ); is( $Union1->coerce("xyz"), "xyz", "Union1 does not need to coerce a String3", ); is( $Union1->coerce("3.1"), "3.1", "Union1 does not need to coerce a String3, even if it looks like a Num", ); is( $Union1->coerce("abcde"), "abc", "Union1 coerces Str -> String3", ); is( $Union1->coerce("3.123"), "3", "given the choice of two valid coercions, Union1 prefers RoundedInteger because it occurs sooner", ); is( $Union1->coerce($arr), $arr, "Union1 cannot coerce an arrayref", ); like( exception { $Union1->coercion->add_type_coercions(ArrayRef, q[ scalar(@$_) ]) }, qr/^Adding coercions to Type::Coercion::Union not currently supported/, "Cannot add to Type::Tiny::Union's coercion", ); done_testing; assert.t000664001750001750 235412422772210 20055 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Library=pod =encoding utf-8 =head1 PURPOSE Checks that the assertion functions exported by a type library work as expected. =head1 DEPENDENCIES Uses the bundled BiggerLib.pm type library. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Fatal; use BiggerLib qw( :assert ); ok assert_String("rats"), "assert_String works (value that should pass)"; like( exception { assert_String([]) }, qr{^is not a string}, "assert_String works (value that should fail)" ); ok BiggerLib::assert_String("rats"), "BiggerLib::assert_String works (value that should pass)"; like( exception { BiggerLib::assert_String([]) }, qr{^is not a string}, "BiggerLib::assert_String works (value that should fail)" ); ok assert_SmallInteger(5), "assert_SmallInteger works (value that should pass)"; like( exception { assert_SmallInteger([]) }, qr{^ARRAY\(\w+\) is too big}, "assert_SmallInteger works (value that should fail)" ); done_testing; errors.t000664001750001750 222312422772210 20063 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Library=pod =encoding utf-8 =head1 PURPOSE Tests errors thrown by L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Fatal; use Type::Library -base; use Type::Tiny; my $e1 = exception { my $m = __PACKAGE__->meta; $m->add_type(name => 'Foo'); $m->add_type(name => 'Foo'); }; like( $e1, qr/^Type Foo already exists in this library/, 'cannot add same type constraint twice', ); my $e2 = exception { my $m = __PACKAGE__->meta; $m->add_type(constraint => sub { 0 }); }; like( $e2, qr/^Cannot add anonymous type to a library/, 'cannot add an anonymous type constraint to a library', ); my $e3 = exception { my $m = __PACKAGE__->meta; $m->add_coercion(name => 'Foo'); }; like( $e3, qr/^Coercion Foo conflicts with type of same name/, 'cannot add a coercion with same name as a constraint', ); done_testing; inheritance.t000664001750001750 545312422772210 21050 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Library=pod =encoding utf-8 =head1 PURPOSE Checks that it's possible to extend existing type libraries. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( . ./t ../inc ./inc ); use utf8; use Test::More; use Test::Requires { Encode => 0 }; use Test::TypeTiny; BEGIN { package Local::Types; use Type::Library -base; use Type::Utils -all; extends 'Types::Standard'; declare "Foo", as "Str"; $INC{'Local/Types.pm'} = __FILE__; }; use Local::Types -all; use Type::Utils; my $chars = "Café Paris|Garçon"; my $bytes_utf8 = Encode::encode("utf-8", $chars); my $bytes_western = Encode::encode("iso-8859-1", $chars); is(length($chars), 17, 'length $chars == 17'); is(length($bytes_utf8), 19, 'length $bytes_utf8 == 19'); is(length($bytes_western), 17, 'length $bytes_western == 17'); my $SplitSpace = (ArrayRef[Str])->plus_coercions(Split[qr/\s/]); my $SplitPipe = (ArrayRef[Foo])->plus_coercions(Split[qr/\|/]); ok($SplitSpace->can_be_inlined, '$SplitSpace can be inlined'); ok($SplitPipe->can_be_inlined, '$SplitPipe can be inlined'); is_deeply( $SplitSpace->coerce($chars), [ "Café", "Paris|Garçon" ], '$SplitSpace->coerce($chars)', ); is_deeply( $SplitSpace->coerce($bytes_utf8), [ map Encode::encode("utf-8", $_), "Café", "Paris|Garçon" ], '$SplitSpace->coerce($bytes_utf8)', ); is_deeply( $SplitSpace->coerce($bytes_western), [ map Encode::encode("iso-8859-1", $_), "Café", "Paris|Garçon" ], '$SplitSpace->coerce($bytes_western)', ); should_pass($SplitSpace->coerce($chars), ArrayRef[Str]); should_pass($SplitSpace->coerce($bytes_utf8), ArrayRef[Str]); should_pass($SplitSpace->coerce($bytes_western), ArrayRef[Str]); is_deeply( my $arr_chars = $SplitPipe->coerce($chars), [ "Café Paris", "Garçon" ], '$SplitPipe->coerce($chars)', ); is_deeply( my $arr_bytes_utf8 = $SplitPipe->coerce($bytes_utf8), [ map Encode::encode("utf-8", $_), "Café Paris", "Garçon" ], '$SplitPipe->coerce($bytes_utf8)', ); is_deeply( my $arr_bytes_western = $SplitPipe->coerce($bytes_western), [ map Encode::encode("iso-8859-1", $_), "Café Paris", "Garçon" ], '$SplitPipe->coerce($bytes_western)', ); my $JoinPipe = Foo->plus_coercions(Join["|"]); is( $_ = $JoinPipe->coerce($arr_chars), $chars, '$JoinPipe->coerce($arr_chars)', ); should_pass($_, Str); is( $_ = $JoinPipe->coerce($arr_bytes_utf8), $bytes_utf8, '$JoinPipe->coerce($arr_bytes_utf8)', ); should_pass($_, Str); is( $_ = $JoinPipe->coerce($arr_bytes_western), $bytes_western, '$JoinPipe->coerce($arr_bytes_western)', ); should_pass($_, Str); done_testing; is.t000664001750001750 221412422772210 17162 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Library=pod =encoding utf-8 =head1 PURPOSE Checks that the check functions exported by a type library work as expected. =head1 DEPENDENCIES Uses the bundled BiggerLib.pm type library. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use BiggerLib qw( :is ); ok is_String("rats"), "is_String works (value that should pass)"; ok !is_String([]), "is_String works (value that should fail)"; ok is_Number(5.5), "is_Number works (value that should pass)"; ok !is_Number("rats"), "is_Number works (value that should fail)"; ok is_Integer(5), "is_Integer works (value that should pass)"; ok !is_Integer(5.5), "is_Integer works (value that should fail)"; ok is_SmallInteger(5), "is_SmallInteger works (value that should pass)"; ok !is_SmallInteger(12), "is_SmallInteger works (value that should fail)"; done_testing; to.t000664001750001750 164712422772210 17202 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Library=pod =encoding utf-8 =head1 PURPOSE Checks that the coercion functions exported by a type library work as expected. =head1 DEPENDENCIES Uses the bundled BiggerLib.pm type library. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Fatal qw(dies_ok); use BiggerLib qw(:to); is( to_BigInteger(8), 18, 'to_BigInteger converts a small integer OK' ); is( to_BigInteger(17), 17, 'to_BigInteger leaves an existing BigInteger OK' ); is( to_BigInteger(3.14), 3.14, 'to_BigInteger ignores something it cannot coerce' ); dies_ok { to_Str [] } "no coercion for Str - should die"; done_testing; types.t000664001750001750 453012422772210 17716 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Library=pod =encoding utf-8 =head1 PURPOSE Checks that the type functions exported by a type library work as expected. =head1 DEPENDENCIES Uses the bundled DemoLib.pm type library. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Fatal; use DemoLib -types; isa_ok String, "Type::Tiny", "String"; isa_ok Number, "Type::Tiny", "Number"; isa_ok Integer, "Type::Tiny", "Integer"; isa_ok DemoLib::String, "Type::Tiny", "DemoLib::String"; isa_ok DemoLib::Number, "Type::Tiny", "DemoLib::Number"; isa_ok DemoLib::Integer, "Type::Tiny", "DemoLib::Integer"; is(String."", "String", "String has correct stringification"); is(Number."", "Number", "Number has correct stringification"); is(Integer."", "Integer", "Integer has correct stringification"); is(DemoLib::String."", "String", "DemoLib::String has correct stringification"); is(DemoLib::Number."", "Number", "DemoLib::Number has correct stringification"); is(DemoLib::Integer."", "Integer", "DemoLib::Integer has correct stringification"); is( exception { Integer->(5) }, undef, "coderef overload (with value that should pass type constraint) does not die", ); is( Integer->(5), 5, "coderef overload returns correct value", ); like( exception { Integer->(5.5) }, qr{^Value "5\.5" did not pass type constraint "Integer"}, "coderef overload (value that should fail type constraint) dies", ); use DemoLib String => { -prefix => "foo", -as => "bar", -suffix => "baz", }; is(foobarbaz->qualified_name, "DemoLib::String", "Sub::Exporter-style export renaming"); ok( Integer eq Integer, 'eq works', ); use Types::Standard qw(ArrayRef Int); my $int = Int; my $arrayref = ArrayRef; my $arrayref_int = ArrayRef[Int]; is_deeply( [ 1, 2, Int, 3, 4 ], [ 1, 2, $int, 3, 4 ], 'type constant in list context', ); is_deeply( [ 1, 2, ArrayRef, 3, 4 ], [ 1, 2, $arrayref, 3, 4 ], 'parameterizable type constant in list context', ); is_deeply( [ 1, 2, ArrayRef[Int], 3, 4 ], [ 1, 2, $arrayref_int, 3, 4 ], 'parameterized type constant in list context', ); done_testing; badsigs.t000664001750001750 203512422772210 20003 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Params=pod =encoding utf-8 =head1 PURPOSE Check that people doing silly things with Test::Params get =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; use Test::Fatal; use Type::Params qw( compile ); use Types::Standard qw( Optional Int ArrayRef slurpy ); like( exception { compile(Optional[Int], Int) }, qr{^Non-Optional parameter following Optional parameter}, "Cannot follow an optional parameter with a required parameter", ); like( exception { compile(slurpy ArrayRef[Int], Optional[Int]) }, qr{^Parameter following slurpy parameter}, "Cannot follow a slurpy parameter with anything", ); like( exception { compile(slurpy Int) }, qr{^Slurpy parameter not of type HashRef or ArrayRef}, "Slurpy parameters must be hashrefs or arrayrefs", ); done_testing; carping.t000664001750001750 163512422772210 20017 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Params=pod =encoding utf-8 =head1 PURPOSE Test L' interaction with L: use Type::Params compile => { confess => 1 }; =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; use Test::Fatal; use Type::Params compile => { confess => 1 }; use Types::Standard qw(Int); my $check; #line 1 "testsub1.chunk" sub testsub1 { $check ||= compile(Int); [ $check->(@_) ]; } #line 1 "testsub2.chunk" sub testsub2 { testsub1(@_); } #line 52 "params-carping.t" my $e = exception { testsub2(1.1); }; isa_ok($e, 'Error::TypeTiny'); like( $e, qr{^Value "1\.1" did not pass type constraint "Int" \(in \$_\[0\]\)}, ); done_testing; coerce.t000664001750001750 302412422772210 17626 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Params=pod =encoding utf-8 =head1 PURPOSE Test L usage of types with coercions. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; use Test::Fatal; use Type::Params qw(compile); use Types::Standard -types, "slurpy"; use Type::Utils; use Scalar::Util qw(refaddr); my $RoundedInt = declare as Int; coerce $RoundedInt, from Num, q{ int($_) }; my $chk = compile(Int, $RoundedInt, Num); is_deeply( [ $chk->(1, 2, 3.3) ], [ 1, 2, 3.3 ] ); is_deeply( [ $chk->(1, 2.2, 3.3) ], [ 1, 2, 3.3 ] ); like( exception { $chk->(1.1, 2.2, 3.3) }, qr{^Value "1\.1" did not pass type constraint "Int" \(in \$_\[0\]\)}, ); my $chk2 = compile(ArrayRef[$RoundedInt]); is_deeply( [ $chk2->([1, 2, 3]) ], [ [1, 2, 3] ] ); is_deeply( [ $chk2->([1.1, 2.2, 3.3]) ], [ [1, 2, 3] ] ); is_deeply( [ $chk2->([1.1, 2, 3.3]) ], [ [1, 2, 3] ] ); my $arr = [ 1 ]; my $arr2 = [ 1.1 ]; is( refaddr( [$chk2->($arr)]->[0] ), refaddr($arr), 'if value passes type constraint; no need to clone arrayref' ); isnt( refaddr( [$chk2->($arr2)]->[0] ), refaddr($arr2), 'if value fails type constraint; need to clone arrayref' ); my $chk3 = compile($RoundedInt->no_coercions); like( exception { $chk3->(1.1) }, qr{^Value "1\.1" did not pass type constraint}, ); done_testing; methods.t000664001750001750 332612422772210 20036 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Params=pod =encoding utf-8 =head1 PURPOSE Test L usage for method calls. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; use Test::Fatal; { package Silly::String; use Type::Params qw(Invocant compile); use Types::Standard qw(ClassName Object Str Int); my %chk; sub new { $chk{new} ||= compile(ClassName, Str); my ($class, $str) = $chk{new}->(@_); bless \$str, $class; } sub repeat { $chk{repeat} ||= compile(Object, Int); my ($self, $n) = $chk{repeat}->(@_); $self->get x $n; } sub get { $chk{get} ||= compile(Object); my ($self) = $chk{get}->(@_); $$self; } sub set { $chk{set} ||= compile(Invocant, Str); my ($proto, $str) = $chk{set}->(@_); Object->check($proto) ? ($$proto = $str) : $proto->new($str); } } is( exception { my $o = Silly::String->new("X"); is($o->get, "X"); is($o->repeat(4), "XXXX"); $o->set("Y"); is($o->repeat(4), "YYYY"); my $p = Silly::String->set("Z"); is($p->repeat(4), "ZZZZ"); }, undef, 'clean operation', ); like( exception { Silly::String::new() }, qr{^Wrong number of parameters; got 0; expected 2}, 'exception calling new() with no args', ); like( exception { Silly::String->new() }, qr{^Wrong number of parameters; got 1; expected 2}, 'exception calling ->new() with no args', ); like( exception { Silly::String::set() }, qr{^Wrong number of parameters; got 0; expected 2}, 'exception calling set() with no args', ); done_testing; mixednamed.t000664001750001750 200212422772210 20474 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Params=pod =encoding utf-8 =head1 PURPOSE Test L usage with mix of positional and named parameters. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; use Test::Fatal; use Type::Params qw(compile); use Types::Standard -types, "slurpy"; my $chk = compile(ClassName, slurpy Dict[ foo => Int, bar => Str, baz => ArrayRef, ]); is_deeply( [ $chk->("Type::Tiny", foo => 1, bar => "Hello", baz => []) ], [ "Type::Tiny", { foo => 1, bar => "Hello", baz => [] } ] ); is_deeply( [ $chk->("Type::Tiny", bar => "Hello", baz => [], foo => 1) ], [ "Type::Tiny", { foo => 1, bar => "Hello", baz => [] } ] ); like( exception { $chk->("Type::Tiny", foo => 1, bar => "Hello") }, qr{did not pass type constraint "Dict}, ); done_testing; multisig.t000664001750001750 432712422772210 20232 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Params=pod =encoding utf-8 =head1 PURPOSE Test L C function. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. Portions by Diab Jerius Edjerius@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; use Test::Fatal; use Type::Params qw( multisig compile validate ); use Types::Standard qw( -types slurpy ); my $Rounded = Int->plus_coercions(Num, 'int($_)'); my $sig = multisig( [ Int, ArrayRef[$Rounded] ], [ ArrayRef[$Rounded], Int ], [ HashRef[Num] ], ); is_deeply( [ $sig->( 1, [2,3,4] ) ], [ 1, [2,3,4] ], 'first choice in multi, no coercion, should pass', ); is_deeply( [ $sig->( 1, [2.2,3.3,4.4] ) ], [ 1, [2,3,4] ], 'first choice in multi, coercion, should pass', ); like( exception { $sig->( 1.1, [2.2,3.3,4.4] ) }, qr{^Parameter validation failed}, 'first choice in multi, should fail', ); is_deeply( [ $sig->( [2,3,4], 1 ) ], [ [2,3,4], 1 ], 'second choice in multi, no coercion, should pass', ); is_deeply( [ $sig->( [2.2,3.3,4.4], 1 ) ], [ [2,3,4], 1 ], 'second choice in multi, coercion, should pass', ); like( exception { $sig->( [2.2,3.3,4.4], 1.1 ) }, qr{^Parameter validation failed}, 'second choice in multi, should fail', ); is_deeply( [ $sig->( { a => 1.1, b => 7 } ) ], [ { a => 1.1, b => 7 } ], 'third choice in multi, no coercion, should pass', ); like( exception { $sig->( { a => 1.1, b => 7, c => "Hello" } ) }, qr{^Parameter validation failed}, 'third choice in multi, should fail', ); my $a = Dict [ a => Num ]; my $b = Dict [ b => Num ]; is exception { validate( [ { a => 3 } ], $a ); validate( [ a => 3 ], slurpy $a ); }, undef; is exception { my $check = multisig( [ $a ], [ $b ] ); $check->( { a => 3 } ); $check->( { b => 3 } ); }, undef; is exception { my $check = multisig( [ slurpy $a ], [ slurpy $b ] ); $check->( a => 3 ); $check->( b => 3 ); }, undef; is exception { my $check = multisig( compile(slurpy $a), compile(slurpy $b) ); $check->( a => 3 ); $check->( b => 3 ); }, undef; done_testing; named.t000664001750001750 227612422772210 17462 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Params=pod =encoding utf-8 =head1 PURPOSE Test L usage with named parameters. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; use Test::Fatal; use Type::Params qw(compile); use Types::Standard -types, "slurpy"; my $chk = compile slurpy Dict[ foo => Int, bar => Str, baz => ArrayRef, ]; is_deeply( [ $chk->(foo => 1, bar => "Hello", baz => []) ], [ { foo => 1, bar => "Hello", baz => [] } ] ); is_deeply( [ $chk->(bar => "Hello", baz => [], foo => 1) ], [ { foo => 1, bar => "Hello", baz => [] } ] ); like( exception { $chk->(foo => 1, bar => "Hello") }, qr{did not pass type constraint "Dict}, ); my $chk2 = compile slurpy Dict[ foo => Int, bar => Str, baz => Optional[ArrayRef], ]; is_deeply( [ $chk2->(foo => 1, bar => "Hello") ], [ { foo => 1, bar => "Hello" } ] ); like( exception { $chk2->(foo => 1, bar => "Hello", zab => []) }, qr{did not pass type constraint "Dict}, ); done_testing; noninline.t000664001750001750 342612422772210 20365 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Params=pod =encoding utf-8 =head1 PURPOSE Test L with type constraints that cannot be inlined. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; use Test::Fatal; use Type::Params qw(compile); use Types::Standard qw(Num ArrayRef); use Type::Utils; my $NumX = declare NumX => as Num, where { $_ != 42 }; my $check; sub nth_root { $check ||= compile( $NumX, $NumX ); [ $check->(@_) ]; } is_deeply( nth_root(1, 2), [ 1, 2 ], '(1, 2)', ); is_deeply( nth_root("1.1", 2), [ "1.1", 2 ], '(1.1, 2)', ); { my $e = exception { nth_root() }; like($e, qr{^Wrong number of parameters; got 0; expected 2}, '()'); } { my $e = exception { nth_root(1) }; like($e, qr{^Wrong number of parameters; got 1; expected 2}, '(1)'); } { my $e = exception { nth_root(undef, 1) }; like($e, qr{^Undef did not pass type constraint "NumX" \(in \$_\[0\]\)}, '(undef, 1)'); } { my $e = exception { nth_root(41, 42) }; like($e, qr{^Value "42" did not pass type constraint "NumX" \(in \$_\[1\]\)}, '(42)'); } my $check2; sub nth_root_coerce { $check2 ||= compile( $NumX->plus_coercions( Num, sub { 21 }, # non-inline ArrayRef, q { scalar(@$_) }, # inline ), $NumX, ); [ $check2->(@_) ]; } is_deeply( nth_root_coerce(42, 11), [21, 11], '(42, 11)' ); is_deeply( nth_root_coerce([1..3], 11), [3, 11], '([1..3], 11)' ); { my $e = exception { nth_root_coerce([1..41], 42) }; like($e, qr{^Value "42" did not pass type constraint "NumX" \(in \$_\[1\]\)}, '([1..41], 42)'); } done_testing; optional.t000664001750001750 247612422772210 20225 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Params=pod =encoding utf-8 =head1 PURPOSE Test L usage with optional parameters. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; use Test::Fatal; use Type::Params qw(compile); use Types::Standard -types; my $chk = compile(Num, Optional[Int], Optional[ArrayRef], Optional[HashRef]); is_deeply( [ $chk->(1.1, 2, [], {}) ], [ 1.1, 2, [], {} ] ); is_deeply( [ $chk->(1.1, 2, []) ], [ 1.1, 2, [] ] ); is_deeply( [ $chk->(1.1, 2) ], [ 1.1, 2 ] ); is_deeply( [ $chk->(1.1) ], [ 1.1 ] ); like( exception { $chk->(1.1, 2, {}) }, qr{^Reference {} did not pass type constraint "Optional\[ArrayRef\]" \(in \$_\[2\]\)}, ); like( exception { $chk->() }, qr{^Wrong number of parameters; got 0; expected 1 to 4}, ); like( exception { $chk->(1 .. 5) }, qr{^Wrong number of parameters; got 5; expected 1 to 4}, ); my $chk2 = compile(1, 0, 0); like( exception { $chk2->() }, qr{^Wrong number of parameters; got 0; expected 1 to 3}, ); like( exception { $chk->(1, 2, undef) }, qr{^Undef did not pass type constraint}, ); done_testing; positional.t000664001750001750 252012422772210 20547 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Params=pod =encoding utf-8 =head1 PURPOSE Test L positional parameters, a la the example in the documentation: sub nth_root { state $check = compile( Num, Num ); my ($x, $n) = $check->(@_); return $x ** (1 / $n); } =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; use Test::Fatal; use Type::Params qw(compile); use Types::Standard qw(Num); my $check; sub nth_root { $check ||= compile( Num, Num ); [ $check->(@_) ]; } is_deeply( nth_root(1, 2), [ 1, 2 ], '(1, 2)', ); is_deeply( nth_root("1.1", 2), [ "1.1", 2 ], '(1.1, 2)', ); { my $e = exception { nth_root() }; like($e, qr{^Wrong number of parameters; got 0; expected 2}, '(1)'); } { my $e = exception { nth_root(1) }; like($e, qr{^Wrong number of parameters; got 1; expected 2}, '(1)'); } { my $e = exception { nth_root(undef, 1) }; like($e, qr{^Undef did not pass type constraint "Num" \(in \$_\[0\]\)}, '(undef, 1)'); } { my $e = exception { nth_root(1, 2, 3) }; like($e, qr{^Wrong number of parameters; got 3; expected 2}, '(1)'); } done_testing; slurpy.t000664001750001750 244112422772210 17726 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Params=pod =encoding utf-8 =head1 PURPOSE Test L usage with slurpy parameters. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; use Test::Fatal; use Type::Params qw(compile); use Types::Standard -types, "slurpy"; my $chk = compile(Str, slurpy HashRef[Int]); is_deeply( [ $chk->("Hello", foo => 1, bar => 2) ], [ "Hello", { foo => 1, bar => 2 } ] ); like( exception { $chk->("Hello", foo => 1, bar => 2.1) }, qr{did not pass type constraint "HashRef\[Int\]" \(in \$SLURPY\)}, ); my $chk2 = compile(Str, slurpy HashRef); is_deeply( [ $chk2->("Hello", foo => 1, bar => 2) ], [ "Hello", { foo => 1, bar => 2 } ] ); like( exception { $chk2->("Hello", foo => 1, "bar") }, qr{^Odd number of elements in HashRef}, ); my $chk3 = compile(Str, slurpy Map); like( exception { $chk3->("Hello", foo => 1, "bar") }, qr{^Odd number of elements in Map}, ); my $chk4 = compile(Str, slurpy Tuple[Str, Int, Str]); is_deeply( [ $chk4->("Hello", foo => 1, "bar") ], [ Hello => [qw/ foo 1 bar /] ], ); done_testing; basic.t000664001750001750 1620312422772210 17503 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Parser=pod =encoding utf-8 =head1 PURPOSE Checks Type::Parser works. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::TypeTiny; use Test::Fatal; use Type::Parser qw( _std_eval parse extract_type ); use Types::Standard qw( -types slurpy ); use Type::Utils; sub types_equal { my ($a, $b) = map { ref($_) ? $_ : _std_eval($_) } @_[0, 1]; my ($A, $B) = map { $_->inline_check('$X') } ($a, $b); my $msg = "$_[0] eq $_[1]"; $msg = "$msg - $_[2]" if $_[2]; @_ = ($A, $B, $msg); goto \&Test::More::is; } note "Basics"; types_equal("Int", Int); types_equal("(Int)", Int, "redundant parentheses"); types_equal("((((Int))))", Int, "many redundant parentheses"); note "Class types"; types_equal("DateTime::", InstanceOf["DateTime"]); types_equal("InstanceOf['DateTime']", InstanceOf["DateTime"]); types_equal("Tied[Foo::]", Tied["Foo"]); types_equal("Tied['Foo']", Tied["Foo"]); note "Parameterization"; types_equal("Int[]", Int, "empty parameterization against non-parameterizable type"); types_equal("Tuple[]", Tuple[], "empty parameterization against parameterizble type"); types_equal("ArrayRef[]", ArrayRef, "empty parameterization against parameterizable type"); types_equal("ArrayRef[Int]", ArrayRef[Int], "parameterized type"); types_equal("Ref['HASH']", Ref['HASH'], "string parameter (singles)"); types_equal("Ref[\"HASH\"]", Ref['HASH'], "string parameter (doubles)"); types_equal("Ref[q(HASH)]", Ref['HASH'], "string parameter (q)"); types_equal("Ref[qq(HASH)]", Ref['HASH'], "string parameter (qq)"); types_equal("StrMatch[qr{foo}]", StrMatch[qr{foo}], "regexp parameter"); note "Unions"; types_equal("Int|HashRef", Int|HashRef); types_equal("Int|HashRef|ArrayRef", Int|HashRef|ArrayRef); types_equal("ArrayRef[Int|HashRef]", ArrayRef[Int|HashRef], "union as a parameter"); types_equal("ArrayRef[Int|HashRef[Int]]", ArrayRef[Int|HashRef[Int]]); types_equal("ArrayRef[HashRef[Int]|Int]", ArrayRef[HashRef([Int]) | Int]); note "Intersections"; types_equal("Int&Num", Int & Num); types_equal("Int&Num&Defined", Int & Num & Defined); types_equal("ArrayRef[Int]&Defined", (ArrayRef[Int]) & Defined); note "Union + Intersection"; types_equal("Int&Num|ArrayRef", (Int & Num) | ArrayRef); types_equal("(Int&Num)|ArrayRef", (Int & Num) | ArrayRef); types_equal("Int&(Num|ArrayRef)", Int & (Num | ArrayRef)); types_equal("Int&Num|ArrayRef&Ref", intersection([Int, Num]) | intersection([ArrayRef, Ref])); note "Complementary types"; types_equal("~Int", ~Int); types_equal("~ArrayRef[Int]", ArrayRef([Int])->complementary_type); types_equal("~Int|CodeRef", (~Int)|CodeRef); types_equal("~(Int|CodeRef)", ~(Int|CodeRef), 'precedence of "~" versus "|"'); note "Comma"; types_equal("Map[Num,Int]", Map[Num,Int]); types_equal("Map[Int,Num]", Map[Int,Num]); types_equal("Map[Int,Int|ArrayRef[Int]]", Map[Int,Int|ArrayRef[Int]]); types_equal("Map[Int,ArrayRef[Int]|Int]", Map[Int,ArrayRef([Int])|Int]); types_equal("Dict[foo=>Int,bar=>Num]", Dict[foo=>Int,bar=>Num]); types_equal("Dict['foo'=>Int,'bar'=>Num]", Dict[foo=>Int,bar=>Num]); types_equal("Dict['foo',Int,'bar',Num]", Dict[foo=>Int,bar=>Num]); note "Slurpy"; types_equal("Dict[slurpy=>Int,bar=>Num]", Dict[slurpy=>Int,bar=>Num]); types_equal("Tuple[Str, Int, slurpy ArrayRef[Int]]", Tuple[Str, Int, slurpy ArrayRef[Int]]); types_equal("Tuple[Str, Int, slurpy(ArrayRef[Int])]", Tuple[Str, Int, slurpy ArrayRef[Int]]); note "Complexity"; types_equal( "ArrayRef[DateTime::]|HashRef[Int|DateTime::]|CodeRef", ArrayRef([InstanceOf["DateTime"]]) | HashRef([Int|InstanceOf["DateTime"]]) | CodeRef ); types_equal( "ArrayRef [DateTime::] |HashRef[ Int|\tDateTime::]|CodeRef ", ArrayRef([InstanceOf["DateTime"]]) | HashRef([Int|InstanceOf["DateTime"]]) | CodeRef, "gratuitous whitespace", ); note "Bad expressions"; like( exception { _std_eval('%hello') }, qr{^Unexpected token in primary type expression; got '%hello'}, 'weird token' ); like( exception { _std_eval('Str Int') }, qr{^Unexpected tail on type expression: Int}, 'weird stuff 1' ); like( exception { _std_eval('ArrayRef(Int)') }, qr{^Unexpected tail on type expression: .Int.}, 'weird stuff 2' ); note "Tail retention"; my ($ast, $remaining) = parse("ArrayRef [DateTime::] |HashRef[ Int|\tDateTime::]|CodeRef monkey nuts "); is($remaining, " monkey nuts ", "remainder is ok"); ($ast, $remaining) = parse("Int, Str"); is($remaining, ", Str", "comma can indicate beginning of remainder"); require Type::Registry; my $type; my $reg = Type::Registry->new; $reg->add_types( -Standard ); ($type, $remaining) = extract_type('ArrayRef [ Int ] yah', $reg); types_equal($type, ArrayRef[Int], 'extract_type works'); like($remaining, qr/\A\s?yah\z/, '... and provides proper remainder too'); note "Parsing edge cases"; is_deeply( scalar parse('Xyzzy[Foo]'), { 'type' => 'parameterized', 'base' => { 'type' => 'primary', 'token' => bless( [ 'TYPE', 'Xyzzy' ], 'Type::Parser::Token' ), }, 'params' => { 'type' => 'list', 'list' => [ { 'type' => 'primary', 'token' => bless( [ 'TYPE', 'Foo' ], 'Type::Parser::Token' ), } ], }, }, 'Xyzzy[Foo] - parameter is treated as a type constraint' ); is_deeply( scalar parse('Xyzzy["Foo"]'), { 'type' => 'parameterized', 'base' => { 'type' => 'primary', 'token' => bless( [ 'TYPE', 'Xyzzy' ], 'Type::Parser::Token' ), }, 'params' => { 'type' => 'list', 'list' => [ { 'type' => 'primary', 'token' => bless( [ 'QUOTELIKE', '"Foo"' ], 'Type::Parser::Token' ), } ], }, }, 'Xyzzy["Foo"] - parameter is treated as a string' ); is_deeply( scalar parse('Xyzzy[-100]'), { 'type' => 'parameterized', 'base' => { 'type' => 'primary', 'token' => bless( [ 'TYPE', 'Xyzzy' ], 'Type::Parser::Token' ), }, 'params' => { 'type' => 'list', 'list' => [ { 'type' => 'primary', 'token' => bless( [ 'STRING', '-100' ], 'Type::Parser::Token' ), } ], }, }, 'Xyzzy[-100] - parameter is treated as a string' ); is_deeply( scalar parse('Xyzzy[200]'), { 'type' => 'parameterized', 'base' => { 'type' => 'primary', 'token' => bless( [ 'TYPE', 'Xyzzy' ], 'Type::Parser::Token' ), }, 'params' => { 'type' => 'list', 'list' => [ { 'type' => 'primary', 'token' => bless( [ 'STRING', '200' ], 'Type::Parser::Token' ), } ], }, }, 'Xyzzy[200] - parameter is treated as a string' ); is_deeply( scalar parse('Xyzzy[+20.0]'), { 'type' => 'parameterized', 'base' => { 'type' => 'primary', 'token' => bless( [ 'TYPE', 'Xyzzy' ], 'Type::Parser::Token' ), }, 'params' => { 'type' => 'list', 'list' => [ { 'type' => 'primary', 'token' => bless( [ 'STRING', '+20.0' ], 'Type::Parser::Token' ), } ], }, }, 'Xyzzy[+20.0] - parameter is treated as a string' ); done_testing; moosextypes.t000664001750001750 151012422772210 20774 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Parser=pod =encoding utf-8 =head1 PURPOSE Checks Type::Parser can pick up MooseX::Types type constraints. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Requires { 'MooseX::Types::Common' => 0 }; use Test::TypeTiny; use Test::Fatal; use Type::Parser qw(_std_eval parse); use Types::Standard qw(-types slurpy); use Type::Utils; my $type = _std_eval("ArrayRef[MooseX::Types::Common::Numeric::PositiveInt]"); should_pass([1,2,3], $type); should_pass([], $type); should_fail([1,-2,3], $type); done_testing;automagic.t000664001750001750 144112422772210 20725 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Registry=pod =encoding utf-8 =head1 PURPOSE Checks Type::Registry->for_class is automagically populated. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Types::Common::Numeric PositiveOrZeroInt => { -as => 'NonNegativeInt' }; ok( !$INC{'Type/Registry.pm'}, 'Type::Registry is not automatically loaded', ); require Type::Registry; my $reg = Type::Registry->for_me; ok( $reg->lookup('NonNegativeInt') == NonNegativeInt, 'Type::Registry was auto-populated', ); done_testing; basic.t000664001750001750 565612422772210 20051 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Registry=pod =encoding utf-8 =head1 PURPOSE Checks Type::Registry works. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::TypeTiny; use Test::Fatal; { package Local::Pkg1; use Type::Registry "t"; ::is(t(), Type::Registry->for_me, 'Type::Registry->for_me works'); ::is(t(), Type::Registry->for_class(__PACKAGE__), 'Type::Registry->for_class works'); t->add_types(-Standard); ::like( ::exception { t->add_types(-MonkeyNutsAndChimpanzeeRaisins) }, qr{^Types::MonkeyNutsAndChimpanzeeRaisins is not a type library}, 'cannot add non-existant type library to registry', ); t->alias_type(Int => "Integer"); ::like( ::exception { t->alias_type(ChimpanzeeRaisins => "ChimpSultanas") }, qr{^Expected existing type constraint name}, 'cannot alias non-existant type in registry', ); ::ok(t->Integer == Types::Standard::Int(), 'alias works'); ::ok(t("Integer") == Types::Standard::Int(), 'alias works via simple_lookup'); ::ok(t("Integer[]") == Types::Standard::Int(), 'alias works via lookup'); } { package Local::Pkg2; use Type::Registry "t"; t->add_types(-Standard => [ -types => { -prefix => 'XYZ_' } ]); ::ok(t->XYZ_Int == Types::Standard::Int(), 'prefix works'); } ok( exception { Local::Pkg2::t->lookup("Integer") }, 'type registries are separate', ); my $r = Type::Registry->for_class("Local::Pkg1"); should_pass([1, 2, 3], $r->lookup("ArrayRef[Integer]")); should_fail([1, 2, 3.14159], $r->lookup("ArrayRef[Integer]")); like( exception { $r->lookup('%foo') }, qr{^Unexpected token in primary type expression; got '\%foo'}, 'type constraint invalid syntax', ); like( exception { $r->lookup('MonkeyNuts') }, qr{^MonkeyNuts is not a known type constraint }, 'type constraint unknown type', ); like( exception { $r->MonkeyNuts }, qr{^Can't locate object method "MonkeyNuts" via package}, 'type constraint unknown type (as method call)', ); is( $r->lookup('MonkeyNuts::')->class, 'MonkeyNuts', 'class type', ); require Type::Tiny::Enum; $r->add_type('Type::Tiny::Enum'->new(values => [qw/Monkey Nuts/]), 'MonkeyNuts'); my $mn = $r->lookup('MonkeyNuts'); should_pass('Monkey', $mn); should_pass('Nuts', $mn); should_fail('Cashews', $mn); use Type::Utils qw(dwim_type role_type class_type); is( dwim_type('MonkeyNuts')->class, 'MonkeyNuts', 'DWIM - class type', ); is( dwim_type('MonkeyNuts', does => 1)->role, 'MonkeyNuts', 'DWIM - role type', ); is( dwim_type('ArrayRef[MonkeyNuts | Foo::]', does => 1)->inline_check('$X'), Types::Standard::ArrayRef()->parameterize(role_type({role=>"MonkeyNuts"}) | class_type({class=>"Foo"}))->inline_check('$X'), 'DWIM - complex type', ); done_testing; methods.t000664001750001750 354512422772210 20426 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Registry=pod =encoding utf-8 =head1 PURPOSE Checks various newish Type::Registry method calls. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::TypeTiny; use Test::Fatal; use Type::Registry qw( t ); use Types::Standard -types; sub types_equal { my ($a, $b) = map { ref($_) ? $_ : do { require Type::Parser; Type::Parser::_std_eval($_) } } @_[0, 1]; my ($A, $B) = map { $_->inline_check('$X') } ($a, $b); my $msg = "$_[0] eq $_[1]"; $msg = "$msg - $_[2]" if $_[2]; @_ = ($A, $B, $msg); goto \&Test::More::is; } t->add_types( -Standard ); types_equal( t->make_class_type("Foo"), InstanceOf["Foo"], 't->make_class_type', ); types_equal( t->make_role_type("Foo"), ConsumerOf["Foo"], 't->make_role_type', ); types_equal( t->make_union(t->ArrayRef, t->Int), ArrayRef|Int, 't->make_union', ); types_equal( t->make_intersection(t->ArrayRef, t->Int), ArrayRef() &+ Int(), 't->make_intersection', ); my $type = t->foreign_lookup('Types::Common::Numeric::PositiveInt'); should_pass(420, $type); should_fail(-42, $type); t->add_type($type); should_pass(420, t->PositiveInt); should_fail(-42, t->PositiveInt); t->add_type($type, 'PossyWossy1'); should_pass(420, t->PossyWossy1); should_fail(-42, t->PossyWossy1); t->add_type($type->create_child_type, 'PossyWossy2'); should_pass(420, t->PossyWossy2); should_fail(-42, t->PossyWossy2); like( exception { t->add_type($type->create_child_type) }, qr/^Expected named type constraint; got anonymous type constraint/, 'cannot add an anonymous type without giving it an alias', ); done_testing; moosextypes.t000664001750001750 206312422772210 21354 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Registry=pod =encoding utf-8 =head1 PURPOSE Checks Type::Registry works with MooseX::Types. =head1 DEPENDENCIES Requires L 0.001004; skipped otherwise. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Requires { 'MooseX::Types::Common' => '0.001004' }; use Test::TypeTiny; use Test::Fatal; use Type::Registry 't'; t->add_types(-Standard); my $ucstrs = t->lookup('ArrayRef[MooseX::Types::Common::String::UpperCaseStr]'); should_pass([], $ucstrs); should_pass(['FOO', 'BAR'], $ucstrs); should_fail(['FOO', 'Bar'], $ucstrs); t->add_types('MooseX::Types::Common::Numeric'); should_pass(8, t->SingleDigit); should_pass(9, t->SingleDigit); should_fail(10, t->SingleDigit); should_pass(10, t->PositiveInt); done_testing; mousextypes.t000664001750001750 205312422772210 21361 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Registry=pod =encoding utf-8 =head1 PURPOSE Checks Type::Registry works with MouseX::Types. =head1 DEPENDENCIES Requires L 0.001000; skipped otherwise. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Requires { 'MouseX::Types::Common' => '0.001000' }; use Test::TypeTiny; use Test::Fatal; use Type::Registry 't'; t->add_types(-Standard); my $nestr = t->lookup('ArrayRef[MouseX::Types::Common::String::NonEmptyStr]'); should_pass([], $nestr); should_pass(['FOO', 'BAR'], $nestr); should_fail(['FOO', ''], $nestr); t->add_types('MouseX::Types::Common::Numeric'); should_pass(8, t->SingleDigit); should_pass(9, t->SingleDigit); should_fail(10, t->SingleDigit); should_pass(10, t->PositiveInt); done_testing; arithmetic.t000664001750001750 1126612422772210 20246 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Tiny=pod =encoding utf-8 =head1 PURPOSE Tests overloading of bitwise operators and numeric comparison operators for L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::TypeTiny; use Types::Standard -all; my $var = 123; should_fail(\$var, ~ScalarRef); should_fail([], ~ArrayRef); should_fail(+{}, ~HashRef); should_fail(sub {0}, ~CodeRef); should_fail(\*STDOUT, ~GlobRef); should_fail(\(\"Hello"), ~Ref); should_fail(\*STDOUT, ~FileHandle); should_fail(qr{x}, ~RegexpRef); should_fail(1, ~Str); should_fail(1, ~Num); should_fail(1, ~Int); should_fail(1, ~Defined); should_fail(1, ~Value); should_fail(undef, ~Undef); should_fail(undef, ~Item); should_fail(undef, ~Any); should_fail('Type::Tiny', ~ClassName); should_fail('Type::Library', ~RoleName); should_fail(undef, ~Bool); should_fail('', ~Bool); should_fail(0, ~Bool); should_fail(1, ~Bool); should_pass(7, ~Bool); should_fail(\(\"Hello"), ~ScalarRef); should_pass('Type::Tiny', ~RoleName); should_pass([], ~Str); should_pass([], ~Num); should_pass([], ~Int); should_fail("4x4", ~Str); should_pass("4x4", ~Num); should_pass("4.2", ~Int); should_pass(undef, ~Str); should_pass(undef, ~Num); should_pass(undef, ~Int); should_pass(undef, ~Defined); should_pass(undef, ~Value); { package Local::Class1; use strict; } { no warnings 'once'; $Local::Class2::VERSION = 0.001; @Local::Class3::ISA = qw(UNIVERSAL); @Local::Dummy1::FOO = qw(UNIVERSAL); } { package Local::Class4; sub XYZ () { 1 } } should_pass(undef, ~ClassName); should_pass([], ~ClassName); should_fail("Local::Class$_", ~ClassName) for 2..4; should_pass("Local::Dummy1", ~ClassName); should_fail([], ~(ArrayRef[Int])); should_fail([1,2,3], ~(ArrayRef[Int])); should_pass([1.1,2,3], ~(ArrayRef[Int])); should_pass([1,2,3.1], ~(ArrayRef[Int])); should_pass([[]], ~(ArrayRef[Int])); should_fail([[3]], ~(ArrayRef[ArrayRef[Int]])); should_pass([["A"]], ~(ArrayRef[ArrayRef[Int]])); should_fail(undef, ~(Maybe[Int])); should_fail(123, ~(Maybe[Int])); should_pass(1.3, ~(Maybe[Int])); my $even = "Type::Tiny"->new( name => "Even", parent => Int, constraint => sub { !(abs($_) % 2) }, ); my $odd = "Type::Tiny"->new( name => "Even", parent => Int, constraint => sub { !!(abs($_) % 2) }, ); my $positive = "Type::Tiny"->new( name => "Positive", parent => Int, constraint => sub { $_ > 0 }, ); my $negative = "Type::Tiny"->new( name => "Negative", parent => Int, constraint => sub { $_ < 0 }, ); should_pass(-2, $even & $negative); should_pass(-1, $odd & $negative); should_pass(0, $even & ~$negative & ~$positive); should_pass(1, $odd & $positive); should_pass(2, $even & $positive); should_pass(3, $even | $odd); should_pass(4, $even | $odd); should_pass(5, $negative | $positive); should_pass(-6, $negative | $positive); should_fail(-3, $even & $negative); should_fail(1, $odd & $negative); should_fail(1, $even & ~$negative & ~$positive); should_fail(2, $odd & $positive); should_fail(1, $even & $positive); should_fail("Str", $even | $odd); should_fail(1.1, $even | $odd); should_fail(0, $negative | $positive); should_fail("Str", $negative | $positive); is( ($even & ~$negative & ~$positive)->display_name, "Even&~Negative&~Positive", "coolio stringification", ); ok(Item > Value, "Item > Value"); ok(Value > Str, "Value > Str"); ok(Str > Num, "Str > Num"); ok(Num > Int, "Num > Int"); ok(Int > $odd, "Int > \$odd"); ok(Item >= Value, "Item >= Value"); ok(Value >= Str, "Value >= Str"); ok(Str >= Num, "Str >= Num"); ok(Num >= Int, "Num >= Int"); ok(Int >= $odd, "Int >= \$odd"); ok(Value() < Item, "Value < Item"); ok(Str() < Value, "Str < Value"); ok(Num() < Str, "Num < Str"); ok(Int() < Num, "Int < Num"); ok($even < Int, "\$even < Int"); ok(Value() <= Item, "Value <= Item"); ok(Str() <= Value, "Str <= Value"); ok(Num() <= Str, "Num <= Str"); ok(Int() <= Num, "Int <= Num"); ok($even <= Int, "\$even < Int"); ok(not(Int > Int), "not(Int > Int)"); ok(not(Int() < Int), "not(Int < Int)"); ok(Int() <= Int, "Int <= Int"); ok(Int >= Int, "Int >= Int"); ok(not((ArrayRef[Int]) > (ArrayRef[Num])), 'not(ArrayRef[Int] > ArrayRef[Num])'); ok(not((ArrayRef[Int]) == (ArrayRef[Num])), 'not(ArrayRef[Int] == ArrayRef[Num])'); ok((ArrayRef[Int]) == (ArrayRef[Int]), 'ArrayRef[Int] == ArrayRef[Int]'); ok(not(ArrayRef == ArrayRef[Int]), 'not(ArrayRef == ArrayRef[Int])'); ok(ArrayRef > ArrayRef[Int], 'ArrayRef > ArrayRef[Int]'); done_testing; basic.t000664001750001750 1124112422772210 17167 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Tiny=pod =encoding utf-8 =head1 PURPOSE Checks Type::Tiny works. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Fatal; use Test::TypeTiny; use Type::Tiny; my $Any = "Type::Tiny"->new(name => "Any"); ok(!$Any->is_anon, "Any is not anon"); is($Any->name, "Any", "Any is called Any"); ok($Any->can_be_inlined, 'Any can be inlined'); should_pass($_, $Any) for 1, 1.2, "Hello World", [], {}, undef, \*STDOUT; like( exception { $Any->create_child_type(name => "1") }, qr{^"1" is not a valid type name}, "bad type constraint name", ); my $Int = $Any->create_child_type( constraint => sub { defined($_) and !ref($_) and $_ =~ /^[+-]?[0-9]+$/sm }, ); ok($Int->is_anon, "\$Int is anon"); is($Int->name, "__ANON__", "\$Int is called __ANON__"); ok(!$Int->can_be_inlined, '$Int cannot be inlined'); should_pass($_, $Int) for 1, -1, 0, 100, 10000, 987654; should_fail($_, $Int) for 1.2, "Hello World", [], {}, undef, \*STDOUT; ok_subtype($Any, $Int); ok($Any->is_supertype_of($Int), 'Any is_supertype_of $Int'); ok($Int->is_a_type_of($Any), '$Int is_a_type_of Any'); ok($Int->is_a_type_of($Int), '$Int is_a_type_of $Int'); ok(!$Int->is_subtype_of($Int), 'not $Int is_subtype_of $Int'); my $Below = $Int->create_child_type( name => "Below", constraint_generator => sub { my $param = shift; return sub { $_ < $param }; }, ); ok($Below->is_parameterizable, 'Below is_parameterizable'); ok(!$Below->is_parameterized, 'not Below is_parameterized'); should_pass($_, $Below) for 1, -1, 0, 100, 10000, 987654; should_fail($_, $Below) for 1.2, "Hello World", [], {}, undef, \*STDOUT; my $Below5 = $Below->parameterize(5); ok($Below5->is_anon, '$Below5 is anon'); is($Below5->display_name, 'Below[5]', '... but still has a nice display name'); should_pass($_, $Below5) for 1, -1, 0; should_fail($_, $Below5) for 1.2, "Hello World", [], {}, undef, \*STDOUT, 100, 10000, 987654; ok_subtype($_, $Below5) for $Any, $Int, $Below; ok($Below5->is_parameterized, 'Below[5] is_parameterized'); ok(!$Below->has_parameters, 'has_parameters method works - negative'); ok($Below5->has_parameters, 'has_parameters method works - positive'); is_deeply($Below5->parameters, [5], 'parameters method works'); my $Ref = "Type::Tiny"->new( name => "Ref", constraint => sub { ref($_) }, inlined => sub { "ref($_)" }, ); my $ArrayRef = "Type::Tiny"->new( name => "ArrayRef", parent => $Ref, constraint => sub { ref($_) eq 'ARRAY' }, inlined => sub { undef, "ref($_) eq 'ARRAY'" }, ); is( $ArrayRef->inline_check('$xxx'), q[(((ref($xxx))) && (ref($xxx) eq 'ARRAY'))], 'inlining stuff can return a list', ); use Types::Standard (); { my $subtype_of_Num = Types::Standard::Num->create_child_type; my $subtype_of_Int = Types::Standard::Int->create_child_type; ok( $subtype_of_Int->is_subtype_of( $subtype_of_Num ), 'loose subtype comparison 1', ); ok( ! $subtype_of_Int->is_strictly_subtype_of( $subtype_of_Num ), 'strict subtype comparison 1', ); ok( $subtype_of_Num->is_supertype_of( $subtype_of_Int ), 'loose supertype comparison 1', ); ok( ! $subtype_of_Num->is_strictly_supertype_of( $subtype_of_Int ), 'strict supertype comparison 1', ); ok( Types::Standard::Int->is_subtype_of( Types::Standard::Num ), 'loose subtype comparison 2', ); ok( Types::Standard::Int->is_strictly_subtype_of( Types::Standard::Num ), 'strict subtype comparison 2', ); ok( Types::Standard::Num->is_supertype_of( Types::Standard::Int ), 'loose supertype comparison 2', ); ok( Types::Standard::Num->is_strictly_supertype_of( Types::Standard::Int ), 'strict supertype comparison 2', ); } my $t1 = Types::Standard::Int; my $t2 = $t1->create_child_type(name => 'T2'); my $t3 = $t2->create_child_type(name => 'T3'); my $t4 = $t3->create_child_type(name => 'T4'); my $t5 = $t4->create_child_type(name => 'T5'); my $t6 = $t5->create_child_type(name => 'T6'); my $found = $t6->find_parent(sub { $_->has_parent and $_->parent->name eq 'Int' }); is($found->name, 'T2', 'find_parent (scalar context)'); my ($found2, $n2) = $t6->find_parent(sub { $_->has_parent and $_->parent->name eq 'Int' }); is($found2->name, 'T2', 'find_parent (list context)'); is($n2, 4, '... includes a count'); my ($found3, $n3) = $t6->find_parent(sub { $_->name eq 'Kristoff' }); is($found3, undef, 'find_parent (null result)'); is($3, undef, '... includes an undef count'); done_testing; coercion-modifiers.t000664001750001750 375112422772210 21655 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Tiny=pod =encoding utf-8 =head1 PURPOSE Checks C, C and C methods work. =head1 DEPENDENCIES Uses the bundled BiggerLib.pm type library. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Fatal qw(dies_ok); use BiggerLib -types; my $new_type = BigInteger->plus_coercions( HashRef, "999", Undef, sub { 666 }, ); my $arr = []; my $hash = {}; ok( $new_type->coercion->has_coercion_for_type(HashRef), 'has_coercian_for_type - obvious', ); ok( $new_type->coercion->has_coercion_for_type(HashRef[Num]), 'has_coercian_for_type - subtle', ); ok( not($new_type->coercion->has_coercion_for_type(Ref["CODE"])), 'has_coercian_for_type - negative', ); is($new_type->coerce($hash), 999, 'plus_coercions - added coercion'); is($new_type->coerce(undef), 666, 'plus_coercions - added coercion'); is($new_type->coerce(-1), 11, 'plus_coercions - retained coercion'); is($new_type->coerce($arr), 100, 'plus_coercions - retained coercion'); my $newer_type = $new_type->minus_coercions(ArrayRef, Undef); is($newer_type->coerce($hash), 999, 'minus_coercions - retained coercion'); is($newer_type->coerce(undef), undef, 'minus_coercions - removed coercion'); is($newer_type->coerce(-1), 11, 'minus_coercions - retained coercion'); is($newer_type->coerce($arr), $arr, 'minus_coercions - removed coercion'); my $no_coerce = $new_type->no_coercions; dies_ok { $no_coerce->coerce($hash) } 'no_coercions - removed coercion'; dies_ok { $no_coerce->coerce(undef) } 'no_coercions - removed coercion'; dies_ok { $no_coerce->coerce(-1) } 'no_coercions - removed coercion'; dies_ok { $no_coerce->coerce($arr) } 'no_coercions - removed coercion'; done_testing; esoteric.t000664001750001750 420312422772210 17703 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Tiny=pod =encoding utf-8 =head1 PURPOSE Checks various undocumented Type::Tiny methods. The fact that these are tested here should not be construed to mean tht they are any any way a stable, supported part of the Type::Tiny API. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Fatal; use Test::TypeTiny; use Type::Tiny; use Types::Standard -types; is_deeply( Int->inline_environment, {}, '$type->inline_environment', ); my $check = Int->_inline_check('$foo'); ok( eval("my \$foo = 42; $check") && !eval("my \$foo = 4.2; $check"), '$type->_inline_check', ); ok( Int->_compiled_type_constraint->("42") && !Int->_compiled_type_constraint->("4.2"), '$type->_compiled_type_constraint', ); like( exception { Any->meta }, qr/^Not really a Moose::Meta::TypeConstraint/, '$type->meta', ); ok( Int->compile_type_constraint->("42") && !Int->compile_type_constraint->("4.2"), '$type->compile_type_constraint', ); ok( Int->_actually_compile_type_constraint->("42") && !Int->_actually_compile_type_constraint->("4.2"), '$type->_actually_compile_type_constraint', ); is( Int->hand_optimized_type_constraint, undef, '$type->hand_optimized_type_constraint', ); ok( !Int->has_hand_optimized_type_constraint, '$type->has_hand_optimized_type_constraint', ); ok( (ArrayRef[Int])->__is_parameterized && !Int->__is_parameterized, '$type->__is_parameterized', ); my $Int = Int->create_child_type; $Int->_add_type_coercions(Num, q[int($_)]); is( $Int->coerce(42.1), 42, '$type->_add_type_coercions', ); is( Int->_as_string, 'Types::Standard::Int', '$type->_as_string', ); is( $Int->_compiled_type_coercion->(6.2), 6, '$type->_compiled_type_coercion', ); ok( Int->_identity != $Int->_identity, '$type->_identity', ); my $union = Int->_unite(ArrayRef); ok( $union->equals( Int | ArrayRef ), '$type->_unite', ); done_testing; my-methods.t000664001750001750 154512422772210 20162 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Tiny=pod =encoding utf-8 =head1 PURPOSE Checks Type::Tiny's C attribute. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Types::Standard qw(Num); my $type = Num->create_child_type( name => 'Number', my_methods => { round_off => sub { int($_[1]) } } ); my $type2 = $type->create_child_type(name => 'Number2'); can_ok($_, 'my_round_off') for $type, $type2; is($_->my_round_off(42.3), 42, "$_ my_round_off works") for $type, $type2; ok(!$_->can('my_smirnoff'), "$_ cannot my_smirnoff") for $type, $type2; done_testing; parameterization.t000664001750001750 325412422772210 21451 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Tiny=pod =encoding utf-8 =head1 PURPOSE There are loads of tests for parameterization in C, C, C, C, C, C, etc. This file includes a handful of other parameterization-related tests that didn't fit anywhere else. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::TypeTiny -all; use Types::Standard -types; my $p1 = ArrayRef[Int]; my $p2 = ArrayRef[Int]; my $p3 = ArrayRef[Int->create_child_type()]; is($p1->{uniq}, $p2->{uniq}, "Avoid duplicating parameterized types"); isnt($p1->{uniq}, $p3->{uniq}, "... except when necessary!"); my $p4 = ArrayRef[sub { $_ eq "Bob" }]; my $p5 = ArrayRef[sub { $_ eq "Bob" or die "not Bob" }]; my $p6 = ArrayRef[Str & +sub { $_ eq "Bob" or die "not Bob" }]; should_pass(["Bob"], $p4); should_pass(["Bob", "Bob"], $p4); should_fail(["Bob", "Bob", "Suzie"], $p4); should_pass(["Bob"], $p5); should_pass(["Bob", "Bob"], $p5); should_fail(["Bob", "Bob", "Suzie"], $p5); should_pass(["Bob"], $p6); should_pass(["Bob", "Bob"], $p6); should_fail(["Bob", "Bob", "Suzie"], $p6); is( $p4->parameters->[0]->validate("Suzie"), 'Value "Suzie" did not pass type constraint', 'error message when a coderef returns false', ); like( $p5->parameters->[0]->validate("Suzie"), qr{^not Bob}, 'error message when a coderef dies', ); done_testing; shortcuts.t000664001750001750 144512422772210 20131 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Tiny=pod =encoding utf-8 =head1 PURPOSE Test the C<< ->of >> and C<< ->where >> shortcut methods. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::TypeTiny -all; use Types::Standard -types; my $p1 = ArrayRef->parameterize( Int ); my $p2 = ArrayRef->of( Int ); is($p1->{uniq}, $p2->{uniq}, "->of method works same as ->parameterize"); my $p3 = ArrayRef->where(sub { $_->[0] eq 'Bob' }); should_pass ['Bob', 'Alice'], $p3; should_fail ['Alice', 'Bob'], $p3; done_testing; smartmatch.t000664001750001750 222512422772210 20233 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Tiny=pod =encoding utf-8 =head1 PURPOSE Checks Type::Tiny works with the smartmatch operator. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Type::Tiny (); BEGIN { Type::Tiny::SUPPORT_SMARTMATCH or plan skip_all => 'smartmatch support not available for this version or Perl'; } use Types::Standard -all; no warnings; # !! ok( 42 ~~ Int ); ok( 42 ~~ Num ); ok not( 42 ~~ ArrayRef ); ok( 42 ~~ \&is_Int ); ok not( 42 ~~ \&is_ArrayRef ); TODO: { use feature qw(switch); given (4) { when ( \&is_RegexpRef ) { fail('regexpref') } when ( \&is_Int ) { pass('int') } default { fail('default') } } local $TODO = 'this would be nice, but probably requires changes to perl'; given (4) { when ( RegexpRef ) { fail('regexpref') } when ( Int ) { pass('int') } default { fail('default') } } }; done_testing; syntax.t000664001750001750 340712422772210 17421 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Tiny=pod =encoding utf-8 =head1 PURPOSE Checks that all this Type[Param] syntactic sugar works. In particular, the following three type constraints are expected to be equivalent to each other: use Types::Standard qw( ArrayRef Int Num Str ); use Type::Utils qw( union intersection ); my $type1 = ArrayRef[Int] | ArrayRef[Num & ~Int] | ArrayRef[Str & ~Num]; my $type2 = union [ ArrayRef[Int], ArrayRef[Num & ~Int], ArrayRef[Str & ~Num], ]; my $type3 = union([ ArrayRef->parameterize(Int), ArrayRef->parameterize( intersection([ Num, Int->complementary_type, ]), ), ArrayRef->parameterize( intersection([ Str, Num->complementary_type, ]), ), ]); =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( . ./t ../inc ./inc ); use Test::More; use Types::Standard qw( ArrayRef Int Num Str ); use Type::Utils qw( union intersection ); my $type1 = ArrayRef[Int] | ArrayRef[Num & ~Int] | ArrayRef[Str & ~Num]; my $type2 = union [ ArrayRef[Int], ArrayRef[Num & ~Int], ArrayRef[Str & ~Num], ]; my $type3 = union([ ArrayRef->parameterize(Int), ArrayRef->parameterize( intersection([ Num, Int->complementary_type, ]), ), ArrayRef->parameterize( intersection([ Str, Num->complementary_type, ]), ), ]); ok($type1==$type2, '$type1==$type2'); ok($type1==$type3, '$type1==$type3'); ok($type2==$type3, '$type2==$type3'); done_testing; to-moose.t000664001750001750 212412422772210 17630 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Tiny=pod =encoding utf-8 =head1 PURPOSE Checks Type::Tiny objects can be converted to Moose type constraint objects. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Requires { 'Moose' => '2.0600' }; use Test::TypeTiny; use Type::Tiny; my $Any = "Type::Tiny"->new(name => "Anything"); my $Int = $Any->create_child_type( name => "Integer", constraint => sub { defined($_) and !ref($_) and $_ =~ /^[+-]?[0-9]+$/sm }, ); my $mAny = $Any->moose_type; my $mInt = $Int->moose_type; isa_ok($mAny, 'Moose::Meta::TypeConstraint', '$mAny'); isa_ok($mInt, 'Moose::Meta::TypeConstraint', '$mInt'); is($mInt->parent, $mAny, 'type constraint inheritance seems right'); should_pass(42, $mAny); should_pass([], $mAny); should_pass(42, $mInt); should_fail([], $mInt); done_testing; to-mouse.t000664001750001750 212212422772210 17634 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Tiny=pod =encoding utf-8 =head1 PURPOSE Checks Type::Tiny objects can be converted to Mouse type constraint objects. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Requires { 'Mouse' => '1.00' }; use Test::TypeTiny; use Type::Tiny; my $Any = "Type::Tiny"->new(name => "Anything"); my $Int = $Any->create_child_type( name => "Integer", constraint => sub { defined($_) and !ref($_) and $_ =~ /^[+-]?[0-9]+$/sm }, ); my $mAny = $Any->mouse_type; my $mInt = $Int->mouse_type; isa_ok($mAny, 'Mouse::Meta::TypeConstraint', '$mAny'); isa_ok($mInt, 'Mouse::Meta::TypeConstraint', '$mInt'); is($mInt->parent, $mAny, 'type constraint inheritance seems right'); should_pass(42, $mAny); should_pass([], $mAny); should_pass(42, $mInt); should_fail([], $mInt); done_testing; basic.t000664001750001750 304012422772210 20210 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Tiny-Class=pod =encoding utf-8 =head1 PURPOSE Checks class type constraints work. =head1 DEPENDENCIES Uses the bundled BiggerLib.pm type library. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::TypeTiny; use BiggerLib qw( :types ); isa_ok(FooBar, "Type::Tiny", "FooBar"); isa_ok(FooBar, "Type::Tiny::Class", "FooBar"); isa_ok(FooBaz, "Type::Tiny", "FooBaz"); isa_ok(FooBaz, "Type::Tiny::Class", "FooBaz"); isa_ok(FooBar->new, "Foo::Bar", "FooBar->new"); isa_ok(FooBaz->new, "Foo::Baz", "FooBaz->new"); isa_ok(FooBar->class->new, "Foo::Bar", "FooBar->class->new"); isa_ok(FooBaz->class->new, "Foo::Baz", "FooBaz->class->new"); should_pass("Foo::Bar"->new, FooBar); should_pass("Foo::Baz"->new, FooBar); should_fail("Foo::Bar"->new, FooBaz); should_pass("Foo::Baz"->new, FooBaz); should_fail(undef, FooBar); should_fail(undef, FooBaz); should_fail({}, FooBar); should_fail({}, FooBaz); should_fail(FooBar, FooBar); should_fail(FooBar, FooBaz); should_fail(FooBaz, FooBar); should_fail(FooBaz, FooBaz); should_fail("Foo::Bar", FooBar); should_fail("Foo::Bar", FooBaz); should_fail("Foo::Baz", FooBar); should_fail("Foo::Baz", FooBaz); is( ref(FooBar->new), ref(FooBar->class->new), 'DWIM Type::Tiny::Class::new', ); done_testing; errors.t000664001750001750 270112422772210 20446 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Tiny-Class=pod =encoding utf-8 =head1 PURPOSE Checks class type constraints throw sane error messages. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Fatal; use Types::Standard qw(Int); use Type::Tiny::Class; like( exception { Type::Tiny::Class->new(parent => Int) }, qr/^Class type constraints cannot have a parent constraint/, ); like( exception { Type::Tiny::Class->new(constraint => sub { 1 }) }, qr/^Class type constraints cannot have a constraint coderef/, ); like( exception { Type::Tiny::Class->new(inlined => sub { 1 }) }, qr/^Class type constraints cannot have a inlining coderef/, ); like( exception { Type::Tiny::Class->new() }, qr/^Need to supply class name/, ); { package Quux; our @ISA = qw(); sub new { bless [], shift } } { package Quuux; our @ISA = qw(); } { package Baz; our @ISA = qw(Quuux); } { package Bar; our @ISA = qw(Baz Quux); } my $e = exception { Type::Tiny::Class ->new(name => "Elsa", class => "Foo") ->assert_valid( Bar->new ); }; is_deeply( $e->explain, [ '"Elsa" requires that the reference isa Foo', 'The reference isa Bar, Baz, Quuux, and Quux', ], ); done_testing; plus-constructors.t000664001750001750 446112422772210 22670 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Tiny-Class=pod =encoding utf-8 =head1 PURPOSE Checks the C's C method. =head1 DEPENDENCIES Requires Moose 2.00; skipped otherwise. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( . ./t ../inc ./inc ); use utf8; use Test::More; use Test::Requires { Moose => 2.00 }; use Test::TypeTiny; my ($Address, $Person); BEGIN { package Address; use Moose; use Types::Standard qw( Str ); use Type::Utils; has [qw/ line1 line2 town county postcode country /] => ( is => "ro", isa => Str, ); sub _new_from_array { my $class = shift; my @addr = ref($_[0]) ? @{$_[0]} : @_; $class->new( line1 => $addr[0], line2 => $addr[1], town => $addr[2], county => $addr[3], postcode => $addr[4], country => $addr[5], ); } $Address = class_type { class => __PACKAGE__ }; }; BEGIN { package Person; use Moose; use Types::Standard qw( Str Join Tuple HashRef ); use Type::Utils; has name => ( required => 1, coerce => 1, is => "ro", isa => Str->plus_coercions(Join[" "]), ); has addr => ( coerce => 1, is => "ro", isa => $Address->plus_constructors( (Tuple[(Str) x 6]) => "_new_from_array", (HashRef) => "new", ), ); sub _new_from_name { my $class = shift; my ($name) = @_; $class->new(name => $name); } $Person = class_type { class => __PACKAGE__ }; }; ok( "Person"->meta->get_attribute("addr")->type_constraint->is_a_type_of($Address), q["Person"->meta->get_attribute("addr")->type_constraint->is_a_type_of($Address)], ); my $me = Person->new( name => ["Toby", "Inkster"], addr => ["Flat 2, 39 Hartington Road", "West Ealing", "LONDON", "", "W13 8QL", "United Kingdom"], ); my $me2 = Person->new( name => "Toby Inkster", addr => Address->new( line1 => "Flat 2, 39 Hartington Road", line2 => "West Ealing", town => "LONDON", county => "", postcode => "W13 8QL", country => "United Kingdom", ), ); is_deeply($me, $me2, 'coercion worked'); done_testing; basic.t000664001750001750 201512422772210 20032 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Tiny-Duck=pod =encoding utf-8 =head1 PURPOSE Checks duck type constraints work. =head1 DEPENDENCIES Uses the bundled BiggerLib.pm type library. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::TypeTiny; use BiggerLib qw( :types ); isa_ok(CanFooBar, "Type::Tiny", "CanFooBar"); isa_ok(CanFooBaz, "Type::Tiny::Duck", "CanFooBar"); should_pass("Foo::Bar"->new, CanFooBar); should_fail("Foo::Bar"->new, CanFooBaz); should_pass("Foo::Baz"->new, CanFooBar); should_pass("Foo::Baz"->new, CanFooBaz); should_fail(undef, CanFooBar); should_fail({}, CanFooBar); should_fail(FooBar, CanFooBar); should_fail(FooBaz, CanFooBar); should_fail(CanFooBar, CanFooBar); should_fail("Foo::Bar", CanFooBar); done_testing; errors.t000664001750001750 261212422772210 20270 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Tiny-Duck=pod =encoding utf-8 =head1 PURPOSE Checks duck type constraints throw sane error messages. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Fatal; use Types::Standard qw(Int); use Type::Tiny::Duck; like( exception { Type::Tiny::Duck->new(parent => Int) }, qr/^Duck type constraints cannot have a parent constraint/, ); like( exception { Type::Tiny::Duck->new(constraint => sub { 1 }) }, qr/^Duck type constraints cannot have a constraint coderef/, ); like( exception { Type::Tiny::Duck->new(inlined => sub { 1 }) }, qr/^Duck type constraints cannot have a inlining coderef/, ); like( exception { Type::Tiny::Duck->new() }, qr/^Need to supply list of methods/, ); { package Bar; sub new { bless [], shift }; sub shake { fail("aquiver") }; } my $e = exception { Type::Tiny::Duck ->new(name => "Elsa", methods => [qw/ shake rattle roll /]) ->assert_valid( Bar->new ); }; is_deeply( $e->explain, [ '"Elsa" requires that the reference can "rattle", "roll", and "shake"', 'The reference cannot "rattle"', 'The reference cannot "roll"', ], ); done_testing; basic.t000664001750001750 207312422772210 20054 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Tiny-Enum=pod =encoding utf-8 =head1 PURPOSE Checks enum type constraints work. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::TypeTiny; use Type::Utils qw< enum >; use constant FBB => enum(FBB => [qw/foo bar baz/]); isa_ok(FBB, "Type::Tiny", "FBB"); isa_ok(FBB, "Type::Tiny::Enum", "FBB"); should_pass("foo", FBB); should_pass("bar", FBB); should_pass("baz", FBB); should_fail("quux", FBB); should_fail(" foo", FBB); should_fail("foo\n", FBB); should_fail("\nfoo", FBB); should_fail("\nfoo\n", FBB); should_fail("foo|", FBB); should_fail("|foo", FBB); should_fail(undef, FBB); should_fail({}, FBB); should_fail(\$_, FBB) for "foo", "bar", "baz"; is_deeply( [sort @{FBB->values}], [sort qw/foo bar baz/], 'FBB->values works', ); done_testing; errors.t000664001750001750 210712422772210 20305 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Tiny-Enum=pod =encoding utf-8 =head1 PURPOSE Checks enum type constraints throw sane error messages. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Fatal; use Types::Standard qw(Int); use Type::Tiny::Enum; like( exception { Type::Tiny::Enum->new(parent => Int) }, qr/^Enum type constraints cannot have a parent constraint/, ); like( exception { Type::Tiny::Enum->new(constraint => sub { 1 }) }, qr/^Enum type constraints cannot have a constraint coderef/, ); like( exception { Type::Tiny::Enum->new(inlined => sub { 1 }) }, qr/^Enum type constraints cannot have a inlining coderef/, ); like( exception { Type::Tiny::Enum->new() }, qr/^Need to supply list of values/, ); ok( !exception { Type::Tiny::Enum->new(values => [qw/foo bar/]) }, ); done_testing; basic.t000664001750001750 434612422772210 21623 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Tiny-Intersection=pod =encoding utf-8 =head1 PURPOSE Checks intersection type constraints work. =head1 DEPENDENCIES Uses the bundled BiggerLib.pm type library. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::TypeTiny; use BiggerLib qw( :types ); use Type::Utils qw( intersection ); { my $x; sub FooBarAndDoesQuux () { $x ||= intersection(FooBarAndDoesQuux => [FooBar, DoesQuux]) } } isa_ok( FooBarAndDoesQuux, 'Type::Tiny::Intersection', 'FooBarAndDoesQuux', ); isa_ok( FooBarAndDoesQuux->[0], 'Type::Tiny::Class', 'FooBarAndDoesQuux->[0]', ); isa_ok( FooBarAndDoesQuux->[1], 'Type::Tiny::Role', 'FooBarAndDoesQuux->[1]', ); is( FooBarAndDoesQuux."", 'FooBar&DoesQuux', 'stringification good', ); my $something = bless [] => do { package Something; sub DOES { return 1 if $_[1] eq 'Quux'; $_[0]->isa($_[0]); } __PACKAGE__; }; should_fail("Foo::Bar"->new, FooBarAndDoesQuux); should_pass("Foo::Baz"->new, FooBarAndDoesQuux); should_fail($something, FooBarAndDoesQuux); my $something_else = bless [] => do { package Something::Else; sub DOES { return 1 if $_[1] eq 'Else'; $_[0]->isa($_[0]); } __PACKAGE__; }; should_fail($something_else, FooBarAndDoesQuux); should_fail("Foo::Bar", FooBarAndDoesQuux); should_fail("Foo::Baz", FooBarAndDoesQuux); require Types::Standard; my $reftype_array = Types::Standard::Ref["ARRAY"]; { my $x; sub NotherSect () { $x ||= intersection(NotherUnion => [FooBarAndDoesQuux, $reftype_array]) } } is( scalar @{+NotherSect}, 3, "intersections don't get unnecessarily deep", ); note NotherSect->inline_check('$X'); should_pass(bless([], "Foo::Baz"), NotherSect); should_fail(bless({}, "Foo::Baz"), NotherSect); my $SmallEven = SmallInteger & sub { $_ % 2 == 0 }; isa_ok($SmallEven, "Type::Tiny::Intersection"); ok(!$SmallEven->can_be_inlined, "not ($SmallEven)->can_be_inlined"); should_pass(2, $SmallEven); should_fail(20, $SmallEven); should_fail(3, $SmallEven); done_testing; errors.t000664001750001750 273112422772210 22052 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Tiny-Intersection=pod =encoding utf-8 =head1 PURPOSE Checks intersection type constraints throw sane error messages. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Fatal; use Types::Standard qw(Int ArrayRef); use Type::Tiny::Intersection; like( exception { Type::Tiny::Intersection->new(parent => Int) }, qr/^Intersection type constraints cannot have a parent constraint/, ); like( exception { Type::Tiny::Intersection->new(constraint => sub { 1 }) }, qr/^Intersection type constraints cannot have a constraint coderef/, ); like( exception { Type::Tiny::Intersection->new(inlined => sub { 1 }) }, qr/^Intersection type constraints cannot have a inlining coderef/, ); like( exception { Type::Tiny::Intersection->new() }, qr/^Need to supply list of type constraints/, ); my $e = exception { Type::Tiny::Intersection ->new(name => "Elsa", type_constraints => [Int, Int]) ->assert_valid( 3.14159 ); }; is_deeply( $e->explain, [ '"Int&Int" requires that the value pass "Int" and "Int"', 'Value "3.14159" did not pass type constraint "Int"', '"Int" is defined as: (defined $_ and $_ =~ /\\A-?[0-9]+\\z/)', ], ) or diag explain($e->explain); done_testing; basic.t000664001750001750 165212422772210 20053 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Tiny-Role=pod =encoding utf-8 =head1 PURPOSE Checks role type constraints work. =head1 DEPENDENCIES Uses the bundled BiggerLib.pm type library. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::TypeTiny; use BiggerLib qw( :types ); isa_ok(DoesQuux, "Type::Tiny", "DoesQuux"); isa_ok(DoesQuux, "Type::Tiny::Role", "DoesQuux"); should_fail("Foo::Bar"->new, DoesQuux); should_pass("Foo::Baz"->new, DoesQuux); should_fail(undef, DoesQuux); should_fail({}, DoesQuux); should_fail(FooBar, DoesQuux); should_fail(FooBaz, DoesQuux); should_fail(DoesQuux, DoesQuux); should_fail("Quux", DoesQuux); done_testing; errors.t000664001750001750 244312422772210 20305 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Tiny-Role=pod =encoding utf-8 =head1 PURPOSE Checks role type constraints throw sane error messages. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Fatal; use Types::Standard qw(Int); use Type::Tiny::Role; like( exception { Type::Tiny::Role->new(parent => Int) }, qr/^Role type constraints cannot have a parent constraint/, ); like( exception { Type::Tiny::Role->new(constraint => sub { 1 }) }, qr/^Role type constraints cannot have a constraint coderef/, ); like( exception { Type::Tiny::Role->new(inlined => sub { 1 }) }, qr/^Role type constraints cannot have a inlining coderef/, ); like( exception { Type::Tiny::Role->new() }, qr/^Need to supply role name/, ); { package Bar; sub new { bless [], shift } sub DOES { 0 } } my $e = exception { Type::Tiny::Role ->new(name => "Elsa", role => "Foo") ->assert_valid( Bar->new ); }; is_deeply( $e->explain, [ '"Elsa" requires that the reference does Foo', "The reference doesn't Foo", ], ); done_testing; basic.t000664001750001750 566112422772210 20246 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Tiny-Union=pod =encoding utf-8 =head1 PURPOSE Checks union type constraints work. =head1 DEPENDENCIES Uses the bundled BiggerLib.pm type library. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::TypeTiny; use BiggerLib qw( :types ); use Type::Utils qw( union class_type ); { my $x; sub FooBarOrDoesQuux () { $x ||= union(FooBarOrDoesQuux => [FooBar, DoesQuux]) } } isa_ok( FooBarOrDoesQuux, 'Type::Tiny::Union', 'FooBarOrDoesQuux', ); isa_ok( FooBarOrDoesQuux->[0], 'Type::Tiny::Class', 'FooBarOrDoesQuux->[0]', ); isa_ok( FooBarOrDoesQuux->[1], 'Type::Tiny::Role', 'FooBarOrDoesQuux->[1]', ); is( FooBarOrDoesQuux."", 'FooBar|DoesQuux', 'stringification good', ); my $something = bless [] => do { package Something; sub DOES { return 1 if $_[1] eq 'Quux'; $_[0]->isa($_[0]); } __PACKAGE__; }; should_pass("Foo::Bar"->new, FooBarOrDoesQuux); should_pass("Foo::Baz"->new, FooBarOrDoesQuux); should_pass($something, FooBarOrDoesQuux); my $something_else = bless [] => do { package Something::Else; sub DOES { return 1 if $_[1] eq 'Else'; $_[0]->isa($_[0]); } __PACKAGE__; }; should_fail($something_else, FooBarOrDoesQuux); should_fail("Foo::Bar", FooBarOrDoesQuux); should_fail("Foo::Baz", FooBarOrDoesQuux); { my $x; sub NotherUnion () { $x ||= union(NotherUnion => [BigInteger, FooBarOrDoesQuux, SmallInteger]) } } is( scalar @{+NotherUnion}, 4, "unions don't get unnecessarily deep", ); { package Local::A } { package Local::B } { package Local::C } { package Local::A::A; our @ISA = qw(Local::A) } { package Local::A::B; our @ISA = qw(Local::A) } { package Local::A::AB; our @ISA = qw(Local::A::A Local::A::B) } { package Local::A::X; our @ISA = qw(Local::A) } my $c1 = union [ class_type({ class => "Local::A::AB" }), class_type({ class => "Local::A::X" }), ]; ok( $c1->parent == class_type({ class => "Local::A" }), "can climb up parents of union type constraints to find best common ancestor", ); my $c2 = union [ class_type({ class => "Local::A" }), class_type({ class => "Local::B" }), class_type({ class => "Local::C" }), ]; ok( $c2->parent == Types::Standard::Object(), "can climb up parents of union type constraints to find best common ancestor (again)", ); is( $c2->find_type_for( bless({}, 'Local::B') )->class, 'Local::B', 'Union find_type_for', ); is( $c2->find_type_for( bless({}, 'Local::A::A') )->class, 'Local::A', 'Union find_type_for (less obvious)', ); is( $c2->find_type_for( bless({}, 'Local::A::AB') )->class, 'Local::A', 'Union find_type_for (ambiguous)', ); is( $c2->find_type_for( bless({}, 'Local::D') ), undef, 'Union find_type_for (none)', ); done_testing; errors.t000664001750001750 336612422772210 20501 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Tiny-Union=pod =encoding utf-8 =head1 PURPOSE Checks union type constraints throw sane error messages. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Fatal; use Types::Standard qw(Int ArrayRef); use Type::Tiny::Union; like( exception { Type::Tiny::Union->new(parent => Int) }, qr/^Union type constraints cannot have a parent constraint/, ); like( exception { Type::Tiny::Union->new(constraint => sub { 1 }) }, qr/^Union type constraints cannot have a constraint coderef/, ); like( exception { Type::Tiny::Union->new(inlined => sub { 1 }) }, qr/^Union type constraints cannot have a inlining coderef/, ); like( exception { Type::Tiny::Union->new() }, qr/^Need to supply list of type constraints/, ); my $e = exception { Type::Tiny::Union ->new(name => "Elsa", type_constraints => [Int, ArrayRef[Int]]) ->assert_valid( 3.14159 ); }; is_deeply( $e->explain, [ '"Int|ArrayRef[Int]" requires that the value pass "ArrayRef[Int]" or "Int"', 'Value "3.14159" did not pass type constraint "Int"', ' Value "3.14159" did not pass type constraint "Int"', ' "Int" is defined as: (defined $_ and $_ =~ /\\A-?[0-9]+\\z/)', 'Value "3.14159" did not pass type constraint "ArrayRef[Int]"', ' "ArrayRef[Int]" is a subtype of "ArrayRef"', ' "ArrayRef" is a subtype of "Ref"', ' Value "3.14159" did not pass type constraint "Ref"', ' "Ref" is defined as: (!!ref($_))', ], ) or diag explain($e->explain); done_testing; overload-precedence.t000664001750001750 144612422772210 23310 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Tiny-_HalfOp=pod =encoding utf-8 =head1 PURPOSE Ensure that the following works consistently on all supported Perls: ArrayRef[Int] | HashRef[Int] =head1 AUTHOR Graham Knop Ehaarg@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Graham Knop. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings FATAL => 'all'; use Test::More; use Types::Standard -all; my $union = eval { ArrayRef[Int] | HashRef[Int] }; SKIP: { ok $union or skip 'broken type', 6; ok $union->check({welp => 1}); ok !$union->check({welp => 1.4}); ok !$union->check({welp => "guff"}); ok $union->check([1]); ok !$union->check([1.4]); ok !$union->check(["guff"]); } done_testing; classifier.t000664001750001750 213012422772210 20364 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Utils=pod =encoding utf-8 =head1 PURPOSE Test L C function. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; use Type::Utils qw( classifier ); use Types::Standard -types; my $classify = classifier(Num, Str, Int, Ref, ArrayRef, HashRef, Any, InstanceOf['Type::Tiny']); sub classified ($$) { my $got = $classify->($_[0]); my $expected = $_[1]; local $Test::Builder::Level = $Test::Builder::Level + 1; is( $got->name, $expected->name, sprintf("%s classified as %s", Type::Tiny::_dd($_[0]), $expected), ); } classified(42, Int); classified(1.1, Num); classified("Hello world", Str); classified("42", Int); classified("1.1", Num); classified((\(my $x)), Ref); classified([], ArrayRef); classified({}, HashRef); classified(undef, Any); classified(Num, InstanceOf['Type::Tiny']); done_testing; dwim-both.t000664001750001750 250412422772210 20137 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Utils=pod =encoding utf-8 =head1 PURPOSE Checks sane behaviour of C from L when both Moose and Mouse are loaded. =head1 DEPENDENCIES Mouse 1.00 and Moose 2.0600; skipped otherwise. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; { package AAA; use Test::Requires { "Mouse" => "1.00" } }; { package BBB; use Test::Requires { "Moose" => "2.0600" } }; { package Minnie; use Mouse; use Mouse::Util::TypeConstraints qw(:all); subtype "FortyFive", as "Int", where { $_ == 40 or $_ == 5 }; } { package Bulwinkle; use Moose; use Moose::Util::TypeConstraints qw(:all); subtype "FortyFive", as "Int", where { $_ == 45 }; } use Test::TypeTiny; use Type::Utils 0.015 qw(dwim_type); my $mouse = dwim_type "FortyFive", for => "Minnie"; should_fail 2, $mouse; should_pass 5, $mouse; should_pass 40, $mouse; should_fail 45, $mouse; should_fail 99, $mouse; my $moose = dwim_type "FortyFive", for => "Bulwinkle"; should_fail 2, $moose; should_fail 5, $moose; should_fail 40, $moose; should_pass 45, $moose; should_fail 99, $moose; done_testing; dwim-moose.t000664001750001750 456112422772210 20332 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Utils=pod =encoding utf-8 =head1 PURPOSE Checks Moose type constraints, and L type constraints are picked up by C from L. =head1 DEPENDENCIES Moose 2.0600 and MooseX::Types 0.35; skipped otherwise. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; use Test::Requires { "Moose" => "2.0600" }; use Test::Requires { "MooseX::Types" => "0.35" }; use Test::TypeTiny; use Moose; use Moose::Util::TypeConstraints qw(:all); use Type::Utils qw(dwim_type); # Creating a type constraint with Moose subtype "Two", as "Int", where { $_ eq 2 }; my $two = dwim_type("Two"); my $twos = dwim_type("ArrayRef[Two]"); isa_ok($two, 'Type::Tiny', '$two'); isa_ok($twos, 'Type::Tiny', '$twos'); should_pass(2, $two); should_fail(3, $two); should_pass([2, 2, 2], $twos); should_fail([2, 3, 2], $twos); # Creating a type constraint with MooseX::Types { package MyTypes; use MooseX::Types -declare => ["Three"]; use MooseX::Types::Moose "Int"; subtype Three, as Int, where { $_ eq 3 }; $INC{'MyTypes.pm'} = __FILE__; } # Note that MooseX::Types namespace-prefixes its types. my $three = dwim_type("MyTypes::Three"); my $threes = dwim_type("ArrayRef[MyTypes::Three]"); isa_ok($three, 'Type::Tiny', '$three'); isa_ok($threes, 'Type::Tiny', '$threes'); should_pass(3, $three); should_fail(4, $three); should_pass([3, 3, 3], $threes); should_fail([3, 4, 3], $threes); { my $testclass = 'Local::Some::Class'; my $fallback = dwim_type($testclass); should_pass(bless({}, $testclass), $fallback); should_fail(bless({}, 'main'), $fallback); my $fallbackp = dwim_type("ArrayRef[$testclass]"); should_pass([bless({}, $testclass)], $fallbackp); should_pass([], $fallbackp); should_fail([bless({}, 'main')], $fallbackp); } { my $testclass = 'Local::Some::Class'; my $fallback = dwim_type("$testclass\::"); should_pass(bless({}, $testclass), $fallback); should_fail(bless({}, 'main'), $fallback); my $fallbackp = dwim_type("ArrayRef[$testclass\::]"); should_pass([bless({}, $testclass)], $fallbackp); should_pass([], $fallbackp); should_fail([bless({}, 'main')], $fallbackp); } done_testing; dwim-mouse.t000664001750001750 456312422772210 20342 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Utils=pod =encoding utf-8 =head1 PURPOSE Checks Mouse type constraints, and L type constraints are picked up by C from L. =head1 DEPENDENCIES Mouse 1.00 and MouseX::Types 0.06; skipped otherwise. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; use Test::Requires { "Mouse" => "1.00" }; use Test::Requires { "MouseX::Types" => "0.06" }; use Test::TypeTiny; use Mouse; use Mouse::Util::TypeConstraints qw(:all); use Type::Utils 0.015 qw(dwim_type); # Creating a type constraint with Mouse subtype "Two", as "Int", where { $_ eq 2 }; my $two = dwim_type("Two"); my $twos = dwim_type("ArrayRef[Two]"); isa_ok($two, 'Type::Tiny', '$two'); isa_ok($twos, 'Type::Tiny', '$twos'); should_pass(2, $two); should_fail(3, $two); should_pass([2, 2, 2], $twos); should_fail([2, 3, 2], $twos); # Creating a type constraint with MouseX::Types { package MyTypes; use MouseX::Types -declare => ["Three"]; use MouseX::Types::Moose "Int"; subtype Three, as Int, where { $_ eq 3 }; $INC{'MyTypes.pm'} = __FILE__; } # Note that MouseX::Types namespace-prefixes its types. my $three = dwim_type("MyTypes::Three"); my $threes = dwim_type("ArrayRef[MyTypes::Three]"); isa_ok($three, 'Type::Tiny', '$three'); isa_ok($threes, 'Type::Tiny', '$threes'); should_pass(3, $three); should_fail(4, $three); should_pass([3, 3, 3], $threes); should_fail([3, 4, 3], $threes); { my $testclass = 'Local::Some::Class'; my $fallback = dwim_type($testclass); should_pass(bless({}, $testclass), $fallback); should_fail(bless({}, 'main'), $fallback); my $fallbackp = dwim_type("ArrayRef[$testclass]"); should_pass([bless({}, $testclass)], $fallbackp); should_pass([], $fallbackp); should_fail([bless({}, 'main')], $fallbackp); } { my $testclass = 'Local::Some::Class'; my $fallback = dwim_type("$testclass\::"); should_pass(bless({}, $testclass), $fallback); should_fail(bless({}, 'main'), $fallback); my $fallbackp = dwim_type("ArrayRef[$testclass\::]"); should_pass([bless({}, $testclass)], $fallbackp); should_pass([], $fallbackp); should_fail([bless({}, 'main')], $fallbackp); } done_testing; match-on-type.t000664001750001750 1000112422772210 20741 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Utils=pod =encoding utf-8 =head1 PURPOSE Test L C and C functions. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; use Test::Fatal; use Type::Utils qw( match_on_type compile_match_on_type ); use Types::Standard -types; sub to_json; *to_json = compile_match_on_type( HashRef() => sub { my $hash = shift; '{ ' . ( join ", " => map { '"' . $_ . '" : ' . to_json( $hash->{$_} ) } sort keys %$hash ) . ' }'; }, ArrayRef() => sub { my $array = shift; '[ ' . ( join ", " => map { to_json($_) } @$array ) . ' ]'; }, Num() => q {$_}, Str() => q { '"' . $_ . '"' }, Undef() => q {'null'}, ScalarRef() &+ sub { Bool->check($$_) } => q { $$_ ? 'true' : 'false' }, => sub { die "$_ is not acceptable json type" }, ); is( to_json({foo => 1, bar => 2, baz => [3 .. 5], quux => undef, xyzzy => \1 }), '{ "bar" : 2, "baz" : [ 3, 4, 5 ], "foo" : 1, "quux" : null, "xyzzy" : true }', 'to_json using compile_match_on_type works', ); sub to_json_2 { return match_on_type $_[0] => ( HashRef() => sub { my $hash = shift; '{ ' . ( join ", " => map { '"' . $_ . '" : ' . to_json_2( $hash->{$_} ) } sort keys %$hash ) . ' }'; }, ArrayRef() => sub { my $array = shift; '[ ' . ( join ", " => map { to_json_2($_) } @$array ) . ' ]'; }, Num() => q {$_}, Str() => q { '"' . $_ . '"' }, Undef() => q {'null'}, ScalarRef() &+ sub { Bool->check($$_) } => q { $$_ ? 'true' : 'false' }, => sub { die "$_ is not acceptable json type" }, ); } is( to_json_2({foo => 1, bar => 2, baz => [3 .. 5], quux => undef, xyzzy => \1 }), '{ "bar" : 2, "baz" : [ 3, 4, 5 ], "foo" : 1, "quux" : null, "xyzzy" : true }', 'to_json_2 using match_on_type works', ); my $compiled1 = compile_match_on_type( HashRef() => sub { 'HASH' }, ArrayRef() => sub { 'ARRAY' }, ); is(ref($compiled1), 'CODE', 'compile_match_on_type returns a coderef'); is($compiled1->({}), 'HASH', '... correct result'); is($compiled1->([]), 'ARRAY', '... correct result'); like( exception { $compiled1->(42) }, qr/^No cases matched for Value "?42"?/, '... correct exception', ); if ($ENV{EXTENDED_TESTING}) { require Benchmark; my $iters = 5_000; my $standard = Benchmark::timethis( $iters, '::to_json_2({foo => 1, bar => 2, baz => [3 .. 5], quux => undef})', 'standard', 'none', ); diag "match_on_type: " . Benchmark::timestr($standard); my $compiled = Benchmark::timethis( $iters, '::to_json({foo => 1, bar => 2, baz => [3 .. 5], quux => undef})', 'compiled', 'none', ); diag "compile_match_on_type: " . Benchmark::timestr($compiled); } like( exception { match_on_type([], Int, sub { 44 }); }, qr/^No cases matched/, 'match_on_type with no match', ); like( exception { compile_match_on_type(Int, sub { 44 })->([]); }, qr/^No cases matched/, 'coderef compiled by compile_match_on_type with no match', ); my $context; MATCH_VOID: { match_on_type([], ArrayRef, sub { $context = wantarray }); ok(!defined($context), 'match_on_type void context'); }; MATCH_SCALAR: { my $x = match_on_type([], ArrayRef, sub { $context = wantarray }); ok(defined($context) && !$context, 'match_on_type scalar context'); }; MATCH_LIST: { my @x = match_on_type([], ArrayRef, sub { $context = wantarray }); ok(defined($context) && $context, 'match_on_type list context'); }; my $compiled = compile_match_on_type(ArrayRef, sub { $context = wantarray }); COMPILE_VOID: { $compiled->([]); ok(!defined($context), 'compile_match_on_type void context'); }; COMPILE_SCALAR: { my $x = $compiled->([]); ok(defined($context) && !$context, 'compile_match_on_type scalar context'); }; COMPILE_LIST: { my @x = $compiled->([]); ok(defined($context) && $context, 'compile_match_on_type list context'); }; done_testing; warnings.t000664001750001750 165212422772210 20100 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Type-Utils=pod =encoding utf-8 =head1 PURPOSE Tests warnings raised by L. =head1 DEPENDENCIES Requires Perl 5.14 and L; skipped otherwise. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Requires '5.014'; use Test::Requires 'Test::Warnings'; use Test::Warnings qw( :no_end_test warnings ); use Type::Library -base, -declare => qw/WholeNumber/; use Type::Utils -all; use Types::Standard qw/Int/; my @warnings = warnings { declare WholeNumber as Int; }; like( $warnings[0], qr/^Possible missing comma after 'declare WholeNumber'/, 'warning for missing comma', ); done_testing; basic.t000664001750001750 632712422772210 21250 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Types-Common-Numeric=pod =encoding utf-8 =head1 PURPOSE Tests constraints for L. These tests are based on tests from L. =head1 AUTHORS =over 4 =item * Matt S Trout - mst (at) shadowcatsystems.co.uk (L) =item * K. James Cheetham =item * Guillermo Roditi =back Test cases ported to L by Toby Inkster. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Matt S Trout - mst (at) shadowcatsystems.co.uk (L). This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings FATAL => 'all'; use Test::More; use Test::TypeTiny; use Types::Common::Numeric -all; should_fail(100, SingleDigit, "SingleDigit 100"); should_fail(10, SingleDigit, "SingleDigit 10"); should_pass(9, SingleDigit, "SingleDigit 9"); should_pass(1, SingleDigit, "SingleDigit 1"); should_pass(0, SingleDigit, "SingleDigit 0"); should_pass(-1, SingleDigit, "SingleDigit -1"); should_pass(-9, SingleDigit, "SingleDigit -9"); should_fail(-10, SingleDigit, "SingleDigit -10"); should_fail(-100, PositiveInt, "PositiveInt (-100)"); should_fail(0, PositiveInt, "PositiveInt (0)"); should_fail(100.885, PositiveInt, "PositiveInt (100.885)"); should_pass(100, PositiveInt, "PositiveInt (100)"); should_fail(0, PositiveNum, "PositiveNum (0)"); should_pass(100.885, PositiveNum, "PositiveNum (100.885)"); should_fail(-100.885, PositiveNum, "PositiveNum (-100.885)"); should_pass(0.0000000001, PositiveNum, "PositiveNum (0.0000000001)"); should_fail(-100, PositiveOrZeroInt, "PositiveOrZeroInt (-100)"); should_pass(0, PositiveOrZeroInt, "PositiveOrZeroInt (0)"); should_fail(100.885, PositiveOrZeroInt, "PositiveOrZeroInt (100.885)"); should_pass(100, PositiveOrZeroInt, "PositiveOrZeroInt (100)"); should_pass(0, PositiveOrZeroNum, "PositiveOrZeroNum (0)"); should_pass(100.885, PositiveOrZeroNum, "PositiveOrZeroNum (100.885)"); should_fail(-100.885, PositiveOrZeroNum, "PositiveOrZeroNum (-100.885)"); should_pass(0.0000000001, PositiveOrZeroNum, "PositiveOrZeroNum (0.0000000001)"); should_fail(100, NegativeInt, "NegativeInt (100)"); should_fail(-100.885, NegativeInt, "NegativeInt (-100.885)"); should_pass(-100, NegativeInt, "NegativeInt (-100)"); should_fail(0, NegativeInt, "NegativeInt (0)"); should_pass(-100.885, NegativeNum, "NegativeNum (-100.885)"); should_fail(100.885, NegativeNum, "NegativeNum (100.885)"); should_fail(0, NegativeNum, "NegativeNum (0)"); should_pass(-0.0000000001, NegativeNum, "NegativeNum (-0.0000000001)"); should_fail(100, NegativeOrZeroInt, "NegativeOrZeroInt (100)"); should_fail(-100.885, NegativeOrZeroInt, "NegativeOrZeroInt (-100.885)"); should_pass(-100, NegativeOrZeroInt, "NegativeOrZeroInt (-100)"); should_pass(0, NegativeOrZeroInt, "NegativeOrZeroInt (0)"); should_pass(-100.885, NegativeOrZeroNum, "NegativeOrZeroNum (-100.885)"); should_fail(100.885, NegativeOrZeroNum, "NegativeOrZeroNum (100.885)"); should_pass(0, NegativeOrZeroNum, "NegativeOrZeroNum (0)"); should_pass(-0.0000000001, NegativeOrZeroNum, "NegativeOrZeroNum (-0.0000000001)"); done_testing; basic.t000664001750001750 541612422772210 21112 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Types-Common-String=pod =encoding utf-8 =head1 PURPOSE Tests constraints for L. These tests are based on tests from L. =head1 AUTHORS =over 4 =item * Matt S Trout - mst (at) shadowcatsystems.co.uk (L) =item * K. James Cheetham =item * Guillermo Roditi =back Test cases ported to L by Toby Inkster. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Matt S Trout - mst (at) shadowcatsystems.co.uk (L). This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings FATAL => 'all'; use Test::More; use Test::TypeTiny; use Types::Common::String -all; should_pass('', SimpleStr, "SimpleStr"); should_pass('a string', SimpleStr, "SimpleStr 2"); should_fail("another\nstring", SimpleStr, "SimpleStr 3"); should_fail(join('', ("long string" x 25)), SimpleStr, "SimpleStr 4"); should_fail('', NonEmptyStr, "NonEmptyStr"); should_pass('a string', NonEmptyStr, "NonEmptyStr 2"); should_pass("another string", NonEmptyStr, "NonEmptyStr 3"); should_pass(join('', ("long string" x 25)), NonEmptyStr, "NonEmptyStr 4"); should_pass('good str', NonEmptySimpleStr, "NonEmptySimplrStr"); should_fail('', NonEmptySimpleStr, "NonEmptyStr 2"); should_fail('no', Password, "Password"); should_pass('okay', Password, "Password 2"); should_fail('notokay', StrongPassword, "StrongPassword"); should_pass('83773r_ch01c3', StrongPassword, "StrongPassword 2"); should_fail('NOTOK', LowerCaseSimpleStr, "LowerCaseSimpleStr"); should_pass('ok', LowerCaseSimpleStr, "LowerCaseSimpleStr 2"); should_fail('NOTOK_123`"', LowerCaseSimpleStr, "LowerCaseSimpleStr 3"); should_pass('ok_123`"', LowerCaseSimpleStr, "LowerCaseSimpleStr 4"); should_fail('notok', UpperCaseSimpleStr, "UpperCaseSimpleStr"); should_pass('OK', UpperCaseSimpleStr, "UpperCaseSimpleStr 2"); should_fail('notok_123`"', UpperCaseSimpleStr, "UpperCaseSimpleStr 3"); should_pass('OK_123`"', UpperCaseSimpleStr, "UpperCaseSimpleStr 4"); should_fail('NOTOK', LowerCaseStr, "LowerCaseStr"); should_pass("ok\nok", LowerCaseStr, "LowerCaseStr 2"); should_fail('NOTOK_123`"', LowerCaseStr, "LowerCaseStr 3"); should_pass("ok\n_123`'", LowerCaseStr, "LowerCaseStr 4"); should_fail('notok', UpperCaseStr, "UpperCaseStr"); should_pass("OK\nOK", UpperCaseStr, "UpperCaseStr 2"); should_fail('notok_123`"', UpperCaseStr, "UpperCaseStr 3"); should_pass("OK\n_123`'", UpperCaseStr, "UpperCaseStr 4"); should_pass('032', NumericCode, "NumericCode lives"); should_fail('abc', NumericCode, "NumericCode dies"); should_fail('x18', NumericCode, "mixed NumericCode dies"); done_testing; coerce.t000664001750001750 225412422772210 21266 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Types-Common-String=pod =encoding utf-8 =head1 PURPOSE Tests coercions for L. These tests are based on tests from L. =head1 AUTHORS =over 4 =item * Matt S Trout - mst (at) shadowcatsystems.co.uk (L) =item * K. James Cheetham =item * Guillermo Roditi =back =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Matt S Trout - mst (at) shadowcatsystems.co.uk (L). This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings FATAL => 'all'; use Test::More; use Types::Common::String qw( +LowerCaseSimpleStr +UpperCaseSimpleStr +LowerCaseStr +UpperCaseStr +NumericCode ); is(to_UpperCaseSimpleStr('foo'), 'FOO', 'uppercase str' ); is(to_LowerCaseSimpleStr('BAR'), 'bar', 'lowercase str' ); is(to_UpperCaseStr('foo'), 'FOO', 'uppercase str' ); is(to_LowerCaseStr('BAR'), 'bar', 'lowercase str' ); is(to_NumericCode('4111-1111-1111-1111'), '4111111111111111', 'numeric code' ); done_testing; unicode.t000664001750001750 307212422772210 21453 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Types-Common-String=pod =encoding utf-8 =head1 PURPOSE Tests Unicode support for L. These tests are based on tests from L. =head1 AUTHORS =over 4 =item * Matt S Trout - mst (at) shadowcatsystems.co.uk (L) =item * K. James Cheetham =item * Guillermo Roditi =back Test cases ported to L by Toby Inkster. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Matt S Trout - mst (at) shadowcatsystems.co.uk (L). This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings FATAL => 'all'; use utf8; use Test::More; use Test::TypeTiny; use Types::Common::String -all; should_pass('CAFÉ', UpperCaseStr, "CAFÉ is uppercase"); should_fail('CAFé', UpperCaseStr, "CAFé is not (entirely) uppercase"); should_fail('ŐħĤăĩ', UpperCaseStr, "----- not entirely uppercase"); should_fail('ŐħĤăĩ', LowerCaseStr, "----- not entirely lowercase"); should_pass('café', LowerCaseStr, "café is lowercase"); should_fail('cafÉ', LowerCaseStr, "cafÉ is not (entirely) lowercase"); should_pass('CAFÉ', UpperCaseSimpleStr, "CAFÉ is uppercase"); should_fail('CAFé', UpperCaseSimpleStr, "CAFé is not (entirely) uppercase"); should_pass('café', LowerCaseSimpleStr, "café is lowercase"); should_fail('cafÉ', LowerCaseSimpleStr, "cafÉ is not (entirely) lowercase"); done_testing; basic.t000664001750001750 1066412422772210 20177 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Types-Standard=pod =encoding utf-8 =head1 PURPOSE Checks various values against the type constraints from Types::Standard. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( . ./t ../inc ./inc ); use Test::More; use Test::Fatal; use Test::TypeTiny; use Types::Standard -all; is(Num->library, "Types::Standard", "->library method"); my $var = 123; should_pass(\$var, ScalarRef); should_pass([], ArrayRef); should_pass(+{}, HashRef); should_pass(sub {0}, CodeRef); should_pass(\*STDOUT, GlobRef); should_pass(\(\"Hello"), Ref); should_pass(\*STDOUT, FileHandle); should_pass(qr{x}, RegexpRef); should_pass(1, Str); should_pass(1, Num); should_pass(1, Int); should_pass(1, Defined); should_pass(1, Value); should_pass(undef, Undef); should_pass(undef, Item); should_pass(undef, Any); should_pass('Type::Tiny', ClassName); should_pass('Type::Library', RoleName); should_pass(undef, Bool); should_pass('', Bool); should_pass(0, Bool); should_pass(1, Bool); should_fail(7, Bool); should_pass(\(\"Hello"), ScalarRef); should_fail('Type::Tiny', RoleName); should_fail([], Str); should_fail([], Num); should_fail([], Int); should_pass("4x4", Str); should_fail("4x4", Num); should_fail("4.2", Int); should_fail(undef, Str); should_fail(undef, Num); should_fail(undef, Int); should_fail(undef, Defined); should_fail(undef, Value); { package Local::Class1; use strict; } { no warnings 'once'; $Local::Class2::VERSION = 0.001; @Local::Class3::ISA = qw(UNIVERSAL); @Local::Dummy1::FOO = qw(UNIVERSAL); } { package Local::Class4; sub XYZ () { 1 } } should_fail(undef, ClassName); should_fail([], ClassName); should_pass("Local::Class$_", ClassName) for 2..4; should_fail("Local::Dummy1", ClassName); should_pass([], ArrayRef[Int]); should_pass([1,2,3], ArrayRef[Int]); should_fail([1.1,2,3], ArrayRef[Int]); should_fail([1,2,3.1], ArrayRef[Int]); should_fail([[]], ArrayRef[Int]); should_pass([[3]], ArrayRef[ArrayRef[Int]]); should_fail([["A"]], ArrayRef[ArrayRef[Int]]); my $deep = ArrayRef[HashRef[ArrayRef[HashRef[Int]]]]; ok($deep->can_be_inlined, "$deep can be inlined"); should_pass([{foo1=>[{bar=>1}]},{foo2=>[{baz=>2}]}], $deep); should_pass([{foo1=>[{bar=>1}]},{foo2=>[]}], $deep); should_fail([{foo1=>[{bar=>1}]},{foo2=>[2]}], $deep); should_pass(undef, Maybe[Int]); should_pass(123, Maybe[Int]); should_fail(1.3, Maybe[Int]); my $i = 1; my $f = 1.1; my $s = "Hello"; should_pass(\$s, ScalarRef[Str]); should_pass(\$f, ScalarRef[Str]); should_pass(\$i, ScalarRef[Str]); should_fail(\$s, ScalarRef[Num]); should_pass(\$f, ScalarRef[Num]); should_pass(\$i, ScalarRef[Num]); should_fail(\$s, ScalarRef[Int]); should_fail(\$f, ScalarRef[Int]); should_pass(\$i, ScalarRef[Int]); should_pass(bless([], "Local::Class4"), Ref["ARRAY"]); should_pass(bless({}, "Local::Class4"), Ref["HASH"]); should_pass([], Ref["ARRAY"]); should_pass({}, Ref["HASH"]); should_fail(bless([], "Local::Class4"), Ref["HASH"]); should_fail(bless({}, "Local::Class4"), Ref["ARRAY"]); should_fail([], Ref["HASH"]); should_fail({}, Ref["ARRAY"]); like( exception { ArrayRef["Int"] }, qr{^Parameter to ArrayRef\[\`a\] expected to be a type constraint; got Int}, qq{ArrayRef["Int"] is not a valid type constraint}, ); like( exception { HashRef[[]] }, qr{^Parameter to HashRef\[\`a\] expected to be a type constraint; got ARRAY}, qq{HashRef[[]] is not a valid type constraint}, ); like( exception { ScalarRef[undef] }, qr{^Parameter to ScalarRef\[\`a\] expected to be a type constraint; got}, qq{ScalarRef[undef] is not a valid type constraint}, ); like( exception { Ref[{}] }, qr{^Parameter to Ref\[\`a\] expected to be string; got HASH}, qq{Ref[{}] is not a valid type constraint}, ); SKIP: { skip "requires Perl 5.8", 3 if $] < 5.008; ok( !!Num->check("Inf") == !Types::Standard::STRICTNUM, "'Inf' passes Num unless Types::Standard::STRICTNUM", ); ok( !!Num->check("-Inf") == !Types::Standard::STRICTNUM, "'-Inf' passes Num unless Types::Standard::STRICTNUM", ); ok( !!Num->check("Nan") == !Types::Standard::STRICTNUM, "'Nan' passes Num unless Types::Standard::STRICTNUM", ); } ok( !!Num->check("0.") == !Types::Standard::STRICTNUM, "'0.' passes Num unless Types::Standard::STRICTNUM", ); ok_subtype(Any, Item); done_testing; deep-coercions.t000664001750001750 2553312422772210 22016 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Types-Standard=pod =encoding utf-8 =head1 PURPOSE If a coercion exists for type C, then Type::Tiny should be able to auto-generate a coercion for type C<< ArrayRef[Foo] >>, etc. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Types::Standard qw( -types slurpy ); use Type::Utils; NONINLINED: { my $Foo = declare Foo => as Int; coerce $Foo, from Num, via { int($_) }; my $ArrayOfFoo = declare ArrayOfFoo => as ArrayRef[$Foo], coercion => 1; ok($ArrayOfFoo->has_coercion, '$ArrayOfFoo has coercion'); my $arr1 = [1..3]; my $arr2 = [1..3, "Hello"]; is( $ArrayOfFoo->coerce($arr1), $arr1, '$ArrayOfFoo does not coerce value that needs no coercion', ); is_deeply( $ArrayOfFoo->coerce([1.1, 2.1, 3.1]), [1, 2, 3], '$ArrayOfFoo does coerce value that can be coerced', ); is( $ArrayOfFoo->coerce($arr2), $arr2, '$ArrayOfFoo does not coerce value that cannot be coerced', ); my $HashOfFoo = HashRef[$Foo]; ok($HashOfFoo->has_coercion, '$HashOfFoo has coercion'); my $hsh1 = {one => 1, two => 2, three => 3}; my $hsh2 = {one => 1, two => 2, three => 3, greeting => "Hello"}; is( $HashOfFoo->coerce($hsh1), $hsh1, '$HashOfFoo does not coerce value that needs no coercion', ); is_deeply( $HashOfFoo->coerce({one => 1.1, two => 2.2, three => 3.3}), {one => 1, two => 2, three => 3}, '$HashOfFoo does coerce value that can be coerced', ); is( $HashOfFoo->coerce($hsh2), $hsh2, '$HashOfFoo does not coerce value that cannot be coerced', ); my $RefOfFoo = ScalarRef[$Foo]; ok($RefOfFoo->has_coercion, '$RefOfFoo has coercion'); my $ref1 = do { my $x = 1; \$x }; my $ref2 = do { my $x = "xxx"; \$x }; is( $RefOfFoo->coerce($ref1), $ref1, '$RefOfFoo does not coerce value that needs no coercion', ); is_deeply( ${ $RefOfFoo->coerce(do { my $x = 1.1; \$x }) }, 1, '$RefOfFoo does coerce value that can be coerced', ); is( $RefOfFoo->coerce($ref2), $ref2, '$RefOfFoo does not coerce value that cannot be coerced', ); # This added coercion should be ignored, because undef shouldn't # need coercion! my $MaybeFoo = Maybe[$Foo->plus_coercions(Undef, 999)]; is( $MaybeFoo->coerce(undef), undef, '$MaybeFoo does not coerce undef', ); is( $MaybeFoo->coerce(42), 42, '$MaybeFoo does not coerce integer', ); is( $MaybeFoo->coerce(4.2), 4, '$MaybeFoo does coerce non-integer number', ); is( $MaybeFoo->coerce("xyz"), "xyz", '$MaybeFoo cannot coerce non-number', ); }; INLINED: { my $Bar = declare Bar => as Int; coerce $Bar, from Num, q { int($_) }; $Bar->coercion->freeze; my $ArrayOfBar = ArrayRef[$Bar]; $ArrayOfBar->coercion->freeze; ok($ArrayOfBar->has_coercion, '$ArrayOfBar has coercion'); ok($ArrayOfBar->coercion->can_be_inlined, '$ArrayOfBar coercion can be inlined'); my $arr1 = [1..3]; my $arr2 = [1..3, "Hello"]; is( $ArrayOfBar->coerce($arr1), $arr1, '$ArrayOfBar does not coerce value that needs no coercion', ); is_deeply( $ArrayOfBar->coerce([1.1, 2.1, 3.1]), [1, 2, 3], '$ArrayOfBar does coerce value that can be coerced', ); is( $ArrayOfBar->coerce($arr2), $arr2, '$ArrayOfBar does not coerce value that cannot be coerced', ); my $HashOfBar = HashRef[$Bar]; $HashOfBar->coercion->freeze; ok($HashOfBar->has_coercion, '$HashOfBar has coercion'); ok($HashOfBar->coercion->can_be_inlined, '$HashOfBar coercion can be inlined'); my $hsh1 = {one => 1, two => 2, three => 3}; my $hsh2 = {one => 1, two => 2, three => 3, greeting => "Hello"}; is( $HashOfBar->coerce($hsh1), $hsh1, '$HashOfBar does not coerce value that needs no coercion', ); is_deeply( $HashOfBar->coerce({one => 1.1, two => 2.2, three => 3.3}), {one => 1, two => 2, three => 3}, '$HashOfBar does coerce value that can be coerced', ); is( $HashOfBar->coerce($hsh2), $hsh2, '$HashOfBar does not coerce value that cannot be coerced', ); my $RefOfBar = ScalarRef[$Bar]; $RefOfBar->coercion->freeze; ok($RefOfBar->has_coercion, '$RefOfBar has coercion'); ok($RefOfBar->coercion->can_be_inlined, '$RefOfBar coercion can be inlined'); my $ref1 = do { my $x = 1; \$x }; my $ref2 = do { my $x = "xxx"; \$x }; is( $RefOfBar->coerce($ref1), $ref1, '$RefOfBar does not coerce value that needs no coercion', ); is_deeply( ${ $RefOfBar->coerce(do { my $x = 1.1; \$x }) }, 1, '$RefOfBar does coerce value that can be coerced', ); is( $RefOfBar->coerce($ref2), $ref2, '$RefOfBar does not coerce value that cannot be coerced', ); # This added coercion should be ignored, because undef shouldn't # need coercion! my $MaybeBar = Maybe[$Bar->plus_coercions(Undef, 999)]; $MaybeBar->coercion->freeze; is( $MaybeBar->coerce(undef), undef, '$MaybeBar does not coerce undef', ); is( $MaybeBar->coerce(42), 42, '$MaybeBar does not coerce integer', ); is( $MaybeBar->coerce(4.2), 4, '$MaybeBar does coerce non-integer number', ); is( $MaybeBar->coerce("xyz"), "xyz", '$MaybeBar cannot coerce non-number', ); }; MAP: { my $IntFromStr = declare IntFromStr => as Int; coerce $IntFromStr, from Str, q{ length($_) }; my $IntFromNum = declare IntFromNum => as Int; coerce $IntFromNum, from Num, q{ int($_) }; my $IntFromArray = declare IntFromArray => as Int; coerce $IntFromArray, from ArrayRef, via { scalar(@$_) }; $_->coercion->freeze for $IntFromStr, $IntFromNum, $IntFromArray; my $Map1 = Map[$IntFromNum, $IntFromStr]; ok( $Map1->has_coercion && $Map1->coercion->can_be_inlined, "$Map1 has an inlinable coercion", ); is_deeply( $Map1->coerce({ 1.1 => "Hello", 2.1 => "World", 3.1 => "Hiya" }), { 1 => 5, 2 => 5, 3 => 4 }, "Coercions to $Map1", ); is_deeply( $Map1->coerce({ 1.1 => "Hello", 2.1 => "World", 3.1 => [] }), { 1.1 => "Hello", 2.1 => "World", 3.1 => [] }, "Impossible coercion to $Map1", ); my $m = { 1 => 2 }; is( $Map1->coerce($m), $m, "Unneeded coercion to $Map1", ); my $Map2 = Map[$IntFromNum, $IntFromArray]; ok( $Map2->has_coercion && !$Map2->coercion->can_be_inlined, "$Map2 has a coercion, but it cannot be inlined", ); is_deeply( $Map2->coerce({ 1.1 => [1], 2.1 => [1,2], 3.1 => [] }), { 1 => 1, 2 => 2, 3 => 0 }, "Coercions to $Map2", ); is_deeply( $Map2->coerce({ 1.1 => [1], 2.1 => [1,2], 3.1 => {} }), { 1.1 => [1], 2.1 => [1,2], 3.1 => {} }, "Impossible coercion to $Map2", ); $m = { 1 => 2 }; is( $Map2->coerce($m), $m, "Unneeded coercion to $Map2", ); }; DICT: { my $IntFromStr = declare IntFromStr => as Int; coerce $IntFromStr, from Str, q{ length($_) }; my $IntFromNum = declare IntFromNum => as Int; coerce $IntFromNum, from Num, q{ int($_) }; my $IntFromArray = declare IntFromArray => as Int; coerce $IntFromArray, from ArrayRef, via { scalar(@$_) }; $_->coercion->freeze for $IntFromStr, $IntFromNum, $IntFromArray; my @a = (a => $IntFromStr, b => $IntFromNum, c => Optional[$IntFromNum]); my $Dict1 = Dict[ a => $IntFromStr, b => $IntFromNum, c => Optional[$IntFromNum] ]; ok( $Dict1->has_coercion && $Dict1->coercion->can_be_inlined, "$Dict1 has an inlinable coercion", ); is_deeply( $Dict1->coerce({ a => "Hello", b => 1.1, c => 2.2 }), { a => 5, b => 1, c => 2 }, "Coercion (A) to $Dict1", ); is_deeply( $Dict1->coerce({ a => "Hello", b => 1 }), { a => 5, b => 1 }, "Coercion (B) to $Dict1", ); is_deeply( $Dict1->coerce({ a => "Hello", b => 1, c => [], d => 1 }), { a => "Hello", b => 1, c => [], d => 1 }, "Coercion (C) to $Dict1 - changed in 0.003_11; the presence of an additional value cancels coercion", ); }; DICT_PLUS_SLURPY: { my $Rounded1 = Int->plus_coercions(Num, q[int($_)]); my $Dict1 = Dict[ a => $Rounded1, slurpy Map[$Rounded1, $Rounded1] ]; is_deeply( $Dict1->coerce({ a => 1.1, 2.2 => 3.3, 4.4 => 5 }), { a => 1, 2 => 3, 4 => 5 }, "Coercion to $Dict1 (inlined)", ); my $Rounded2 = Int->plus_coercions(Num, sub { int($_) }); my $Dict2 = Dict[ a => $Rounded2, slurpy Map[$Rounded2, $Rounded2] ]; is_deeply( $Dict2->coerce({ a => 1.1, 2.2 => 3.3, 4.4 => 5 }), { a => 1, 2 => 3, 4 => 5 }, "Coercion to $Dict2 (non-inlined)", ); }; DICT_PLUS_OPTIONAL: { my $IntFromStr = declare IntFromStr => as Int; coerce $IntFromStr, from Str, sub { length($_) }; $IntFromStr->coercion->freeze; my $Dict1 = Dict[ a => $IntFromStr, b => Optional[Int], c => Optional[Int] ]; ok( $Dict1->has_coercion && !$Dict1->coercion->can_be_inlined, "$Dict1 has a non-inlinable coercion", ); is_deeply( $Dict1->coerce({ a => "Hello", b => 1, c => 2 }), { a => 5, b => 1, c => 2 }, "Coercion (A) to $Dict1", ); is_deeply( $Dict1->coerce({ a => "Hello", b => 1 }), { a => 5, b => 1 }, "Coercion (B) to $Dict1", ); }; TUPLE: { my $IntFromStr = declare IntFromStr => as Int; coerce $IntFromStr, from Str, q{ length($_) }; my $IntFromNum = declare IntFromNum => as Int; coerce $IntFromNum, from Num, q{ int($_) }; my $IntFromArray = declare IntFromArray => as Int; coerce $IntFromArray, from ArrayRef, via { scalar(@$_) }; $_->coercion->freeze for $IntFromStr, $IntFromNum, $IntFromArray; my $Tuple1 = Tuple[ $IntFromNum, Optional[$IntFromStr], slurpy ArrayRef[$IntFromNum]]; ok( $Tuple1->has_coercion && $Tuple1->coercion->can_be_inlined, "$Tuple1 has an inlinable coercion", ); is_deeply( $Tuple1->coerce([qw( 1.1 1.1 )]), [1, 3], "Coercion (A) to $Tuple1", ); is_deeply( $Tuple1->coerce([qw( 1.1 1.1 2.2 2.2 33 3.3 )]), [1, 3, 2, 2, 33, 3], "Coercion (B) to $Tuple1", ); my $Tuple2 = Tuple[ $IntFromNum ]; is_deeply( $Tuple2->coerce([qw( 1.1 )]), [ 1 ], "Coercion (A) to $Tuple2", ); is_deeply( $Tuple2->coerce([qw( 1.1 2.2 )]), [ 1.1, 2.2 ], "Coercion (B) to $Tuple2 - changed in 0.003_11; the presence of an additional value cancels coercion", ); my $EvenInt = Int->create_child_type( name => 'EvenInt', constraint => sub { not $_ % 2 }, ); my $Tuple3 = Tuple[ $EvenInt->plus_coercions(Int, sub { 2 * $_ }) ]; ok( $Tuple3->check([4]) ); ok( not $Tuple3->check([3]) ); is_deeply( $Tuple3->coerce([4]), [4], "No coercion necessary to $Tuple3", ); is_deeply( $Tuple3->coerce([3]), [6], "Coercion to $Tuple3", ); my $EvenInt2 = Int->create_child_type( name => 'EvenInt2', constraint => sub { not $_ % 2 }, inlined => sub { undef, "not($_ % 2)" }, ); my $Tuple4 = Tuple[ $EvenInt2->plus_coercions(Int, q{ 2 * $_ }) ]; ok( $Tuple4->check([4]) ); ok( not $Tuple4->check([3]) ); is_deeply( $Tuple4->coerce([4]), [4], "No coercion necessary to $Tuple4", ); is_deeply( $Tuple4->coerce([3]), [6], "Coercion to $Tuple4", ); }; done_testing; lockdown.t000664001750001750 221012422772210 20702 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Types-Standard=pod =head1 PURPOSE OK, we need to bite the bullet and lock down coercions on core type constraints and parameterized type constraints. =head1 SEE ALSO L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; use Test::Fatal; use Types::Standard -types; use Types::Common::Numeric -types; my $frozen = qr/\AAttempt to add coercion code to a Type::Coercion/; like( exception { Str->coercion->add_type_coercions(ArrayRef, sub { "@$_" }); }, $frozen, 'Types::Standard core types are frozen', ); like( exception { PositiveInt->coercion->add_type_coercions(NegativeInt, sub { -$_ }); }, $frozen, 'Types::Common types are frozen', ); like( exception { InstanceOf->of("Foo")->coercion->add_type_coercions(HashRef, sub { bless $_, "Foo" }); }, $frozen, 'Parameterized types are frozen', ); done_testing; mxtmlb-alike.t000664001750001750 335612422772210 21464 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Types-Standard=pod =encoding utf-8 =head1 PURPOSE Test the following types from L which were inspired by L. =over =item C<< InstanceOf >> =item C<< ConsumerOf >> =item C<< HasMethods >> =item C<< Enum >> =back Rather than checking they work directy, we check they are equivalent to known (and well-tested) type constraints generated using L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; use Types::Standard -types; use Type::Utils; sub same_type { my ($a, $b, $msg) = @_; $msg ||= "$a == $b"; @_ = ($a->inline_check('$x'), $b->inline_check('$x'), $msg); goto \&Test::More::is; } same_type( InstanceOf[], Object, ); same_type( InstanceOf["Foo"], class_type(Foo => {class => "Foo"}), ); same_type( InstanceOf["Foo", "Bar"], union [ class_type(Foo => {class => "Foo"}), class_type(Bar => {class => "Bar"}), ], ); same_type( ConsumerOf[], Object, ); same_type( ConsumerOf["Foo"], role_type(Foo => {role => "Foo"}), ); same_type( ConsumerOf["Foo", "Bar"], intersection [ role_type(Foo => {role => "Foo"}), role_type(Bar => {role => "Bar"}), ], ); same_type( HasMethods[], Object, ); same_type( HasMethods["foo"], duck_type(CanFoo => [qw/foo/]), ); same_type( HasMethods["foo", "bar"], duck_type(CanFooBar => [qw/foo bar/]), ); same_type( Enum[], Str, ); same_type( Enum["foo"], enum(Foo => [qw/foo/]), ); same_type( Enum["foo", "bar"], enum(Foo => [qw/foo bar/]), ); done_testing; optlist.t000664001750001750 274012422772210 20570 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Types-Standard=pod =encoding utf-8 =head1 PURPOSE Checks various values against C from Types::Standard. Checks the standalone C coercion. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::TypeTiny; use Types::Standard qw( OptList MkOpt ); my $O = OptList; my $OM = OptList->plus_coercions(MkOpt); should_pass([], $O); should_pass([[foo=>undef]], $O); should_pass([[foo=>[]]], $O); should_pass([[foo=>{}]], $O); should_pass([], $OM); should_pass([[foo=>undef]], $OM); should_pass([[foo=>[]]], $OM); should_pass([[foo=>{}]], $OM); should_fail([[undef]], $O); should_fail([[[]]], $O); should_fail([[{}]], $O); should_fail([[undef]], $OM); should_fail([[[]]], $OM); should_fail([[{}]], $OM); ok(!$O->has_coercion, "not $O has coercion"); ok($OM->has_coercion, "$OM has coercion"); is_deeply( $OM->coerce(undef), [], '$OM->coerce(undef)', ); is_deeply( $OM->coerce([]), [], '$OM->coerce([])', ); is_deeply( $OM->coerce([foo => {}, bar => "baz"]), [ [foo => {}], [bar => undef], [baz => undef], ], 'simple $OM coercion test', ); is_deeply( $OM->coerce({foo => []}), [ [foo => []], ], 'another simple $OM coercion test', ); done_testing; overload.t000664001750001750 213012422772210 20676 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Types-Standard=pod =encoding utf-8 =head1 PURPOSE Checks various values against C from Types::Standard. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::TypeTiny; use Types::Standard qw( Any Item Defined Ref ArrayRef Object Overload ); my $o = bless [] => do { package Local::Class; use overload q[&] => sub { 1 }, fallback => 1; __PACKAGE__; }; should_pass($o, Any); should_pass($o, Item); should_pass($o, Defined); should_pass($o, Ref); should_pass($o, Ref["ARRAY"]); should_pass($o, Object); should_pass($o, Overload); should_pass($o, Overload["&"]); should_fail($o, Ref["HASH"]); should_fail($o, Overload["|"]); should_fail("Local::Class", Overload); should_fail([], Overload); ok_subtype($_, Overload["&"]) for Item, Defined, Ref, Object, Overload; done_testing; strmatch.t000664001750001750 334112422772210 20715 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Types-Standard=pod =encoding utf-8 =head1 PURPOSE Checks various values against C from Types::Standard. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( . ./t ../inc ./inc ); use Test::More; use Test::TypeTiny; use Types::Standard -all, "slurpy"; use Type::Utils; my $DistanceUnit = enum DistanceUnit => [qw/ mm cm m km /]; my $Distance = declare Distance => as StrMatch[ qr{^([0-9]+)\s+(.+)$}, Tuple[Int, $DistanceUnit], ]; should_pass("mm", $DistanceUnit); should_pass("cm", $DistanceUnit); should_pass("m", $DistanceUnit); should_pass("km", $DistanceUnit); should_fail("MM", $DistanceUnit); should_fail("mm ", $DistanceUnit); should_fail(" mm", $DistanceUnit); should_fail("miles", $DistanceUnit); should_pass("5 km", $Distance) or diag($Distance->inline_check('$XXX')); should_pass("5 mm", $Distance); should_fail("4 miles", $Distance); should_fail("5.5 km", $Distance); should_fail([qw/5 km/], $Distance); my $Boolean = declare Boolean => as StrMatch[qr{^(?:true|false|0|1)$}ism]; should_pass("true", $Boolean); should_pass("True", $Boolean); should_pass("TRUE", $Boolean); should_pass("false", $Boolean); should_pass("False", $Boolean); should_pass("FALSE", $Boolean); should_pass("0", $Boolean); should_pass("1", $Boolean); should_fail("True ", $Boolean); should_fail("11", $Boolean); my $SecureUrl = declare SecureUrl => as StrMatch[qr{^https://}]; should_pass("https://www.google.com/", $SecureUrl); should_fail("http://www.google.com/", $SecureUrl); done_testing; structured.t000664001750001750 3465712422772210 21332 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Types-Standard=pod =encoding utf-8 =head1 PURPOSE Checks various values against structured types from Types::Standard. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( . ./t ../inc ./inc ); use Test::More; use Test::TypeTiny; use Types::Standard -all, "slurpy"; my $struct1 = Map[Int, Num]; should_pass({1=>111,2=>222}, $struct1); should_pass({1=>1.1,2=>2.2}, $struct1); should_fail({1=>"Str",2=>222}, $struct1); should_fail({1.1=>1,2=>2.2}, $struct1); my $struct2 = Tuple[Int, Num, Optional([Int]), slurpy ArrayRef[Num]]; my $struct3 = Tuple[Int, Num, Optional[Int]]; should_pass([1, 1.1], $struct2); should_pass([1, 1.1, 2], $struct2); should_pass([1, 1.1, 2, 2.2], $struct2); should_pass([1, 1.1, 2, 2.2, 2.3], $struct2); should_pass([1, 1.1, 2, 2.2, 2.3, 2.4], $struct2); should_fail({}, $struct2); should_fail([], $struct2); should_fail([1], $struct2); should_fail([1.1, 1.1], $struct2); should_fail([1, 1.1, 2.1], $struct2); should_fail([1, 1.1, 2.1], $struct2); should_fail([1, 1.1, 2, 2.2, 2.3, 2.4, "xyz"], $struct2); should_fail([1, 1.1, undef], $struct2); should_pass([1, 1.1], $struct3); should_pass([1, 1.1, 2], $struct3); should_fail([1, 1.1, 2, 2.2], $struct3); should_fail([1, 1.1, 2, 2.2, 2.3], $struct3); should_fail([1, 1.1, 2, 2.2, 2.3, 2.4], $struct3); should_fail({}, $struct3); should_fail([], $struct3); should_fail([1], $struct3); should_fail([1.1, 1.1], $struct3); should_fail([1, 1.1, 2.1], $struct3); should_fail([1, 1.1, 2.1], $struct3); should_fail([1, 1.1, 2, 2.2, 2.3, 2.4, "xyz"], $struct3); should_fail([1, 1.1, undef], $struct3); my $struct4 = Dict[ name => Str, age => Int, height => Optional[Num] ]; should_pass({ name => "Bob", age => 40, height => 1.76 }, $struct4); should_pass({ name => "Bob", age => 40 }, $struct4); should_fail({ name => "Bob" }, $struct4); should_fail({ age => 40 }, $struct4); should_fail({ name => "Bob", age => 40.1 }, $struct4); should_fail({ name => "Bob", age => 40, weight => 80.3 }, $struct4); should_fail({ name => "Bob", age => 40, height => 1.76, weight => 80.3 }, $struct4); should_fail({ name => "Bob", age => 40, height => "xyz" }, $struct4); should_fail({ name => "Bob", age => 40, height => undef }, $struct4); should_fail({ name => "Bob", age => undef, height => 1.76 }, $struct4); my $opt1 = Optional[Int]; ok( $opt1->check(1), "$opt1 check (1)"); ok(!$opt1->check('xxx'), "$opt1 check ('xxx')"); my $slurper = Tuple[ArrayRef, slurpy Map[Num, Int]]; should_pass([ [], 1.1 => 1, 2.1 => 2 ], $slurper); should_pass([ [] ], $slurper); should_fail([ [], 1.1 => 1, xxx => 2 ], $slurper); should_fail([ [], 1.1 => 1, 2.1 => undef ], $slurper); my $struct5 = Dict[ i => Maybe[Int], b => Bool ]; should_pass({ i => 42, b => undef }, $struct5); should_pass({ i => 42, b => '' }, $struct5); should_pass({ i => 42, b => 0 }, $struct5); should_pass({ i => 42, b => 1 }, $struct5); should_pass({ i => undef, b => 1 }, $struct5); should_fail({ b => 42, i => 1 }, $struct5); should_fail({ i => 42 }, $struct5); should_fail({ b => 1 }, $struct5); should_fail({ i => 42, b => 1, a => 1 }, $struct5); should_fail({ i => 42, a => 1 }, $struct5); should_fail({ a => 42, b => 1 }, $struct5); my $anyany = Tuple[Any, Any]; should_pass([1,1], $anyany); should_pass([1,undef], $anyany); should_pass([undef,undef], $anyany); should_pass([undef,1], $anyany); should_fail([1], $anyany); should_fail([undef], $anyany); should_fail([1,1,1], $anyany); should_fail([1,1,undef], $anyany); note "Tuple[] vs Tuple"; should_pass([ ], Tuple[]); should_fail([1], Tuple[]); should_pass([ ], Tuple); should_pass([1], Tuple); note "Dict[] vs Dict"; should_pass(+{ }, Dict[]); should_fail(+{foo=>1}, Dict[]); should_pass(+{ }, Dict); should_pass(+{foo=>1}, Dict); my $gazetteer = Dict[ foo => Int, bar => Optional[Int], slurpy HashRef[Num] ]; note "Dict[ ..., slurpy ... ]"; should_pass({ foo => 42 }, $gazetteer); should_pass({ foo => 42, bar => 666 }, $gazetteer); should_fail({ foo => 4.2 }, $gazetteer); should_fail({ foo => 42, bar => 6.66 }, $gazetteer); should_fail({ foo => 4.2, bar => 6.66 }, $gazetteer); should_fail({ foo => undef }, $gazetteer); should_fail({ }, $gazetteer); should_pass({ foo => 42, baz => 999 }, $gazetteer); should_pass({ foo => 42, bar => 666, baz => 999 }, $gazetteer); should_fail({ foo => 4.2, baz => 999 }, $gazetteer); should_fail({ foo => 42, bar => 6.66, baz => 999 }, $gazetteer); should_fail({ foo => 4.2, bar => 6.66, baz => 999 }, $gazetteer); should_fail({ foo => undef, baz => 999 }, $gazetteer); should_fail({ baz => 999 }, $gazetteer); should_pass({ foo => 42, baz => 9.99 }, $gazetteer); should_pass({ foo => 42, bar => 666, baz => 9.99 }, $gazetteer); should_fail({ foo => 4.2, baz => 9.99 }, $gazetteer); should_fail({ foo => 42, bar => 6.66, baz => 9.99 }, $gazetteer); should_fail({ foo => 4.2, bar => 6.66, baz => 9.99 }, $gazetteer); should_fail({ foo => undef, baz => 9.99 }, $gazetteer); should_fail({ baz => 9.99 }, $gazetteer); should_fail({ foo => 42, baz => "x" }, $gazetteer); should_fail({ foo => 42, bar => 666, baz => "x" }, $gazetteer); should_fail({ foo => 4.2, baz => "x" }, $gazetteer); should_fail({ foo => 42, bar => 6.66, baz => "x" }, $gazetteer); should_fail({ foo => 4.2, bar => 6.66, baz => "x" }, $gazetteer); should_fail({ foo => undef, baz => "x" }, $gazetteer); should_fail({ baz => "x" }, $gazetteer); subtest my_dict_is_slurpy => sub { ok(!$struct5->my_dict_is_slurpy, 'On a non-slurpy Dict'); ok($gazetteer->my_dict_is_slurpy, 'On a slurpy Dict'); ok(!$struct5->create_child_type->my_dict_is_slurpy, 'On a child of a non-slurpy Dict'); ok($gazetteer->create_child_type->my_dict_is_slurpy, 'On a child of a slurpy Dict'); }; subtest my_hashref_allows_key => sub { ok(HashRef->my_hashref_allows_key('foo'), 'HashRef allows key "foo"'); ok(!HashRef->my_hashref_allows_key(undef), 'HashRef disallows key undef'); ok(!HashRef->my_hashref_allows_key([]), 'HashRef disallows key []'); ok((HashRef[Int])->my_hashref_allows_key('foo'), 'HashRef[Int] allows key "foo"'); ok(!(HashRef[Int])->my_hashref_allows_key(undef), 'HashRef[Int] disallows key undef'); ok(!(HashRef[Int])->my_hashref_allows_key([]), 'HashRef[Int] disallows key []'); ok(Map->my_hashref_allows_key('foo'), 'Map allows key "foo"'); ok(!Map->my_hashref_allows_key(undef), 'Map disallows key undef'); ok(!Map->my_hashref_allows_key([]), 'Map disallows key []'); ok(!(Map[Int,Int])->my_hashref_allows_key('foo'), 'Map[Int,Int] disallows key "foo"'); ok(!(Map[Int,Int])->my_hashref_allows_key(undef), 'Map[Int,Int] disallows key undef'); ok(!(Map[Int,Int])->my_hashref_allows_key([]), 'Map[Int,Int] disallows key []'); ok((Map[Int,Int])->my_hashref_allows_key('42'), 'Map[Int,Int] allows key "42"'); ok(Dict->my_hashref_allows_key('foo'), 'Dict allows key "foo"'); ok(!Dict->my_hashref_allows_key(undef), 'Dict disallows key undef'); ok(!Dict->my_hashref_allows_key([]), 'Dict disallows key []'); ok(!(Dict[])->my_hashref_allows_key('foo'), 'Dict[] disallows key "foo"'); ok(!(Dict[])->my_hashref_allows_key(undef), 'Dict[] disallows key undef'); ok(!(Dict[])->my_hashref_allows_key([]), 'Dict[] disallows key []'); ok(!(Dict[bar=>Int])->my_hashref_allows_key('foo'), 'Dict[bar=>Int] disallows key "foo"'); ok((Dict[bar=>Int])->my_hashref_allows_key('bar'), 'Dict[bar=>Int] allows key "bar"'); ok(!(Dict[bar=>Int])->my_hashref_allows_key(undef), 'Dict[bar=>Int] disallows key undef'); ok(!(Dict[bar=>Int])->my_hashref_allows_key([]), 'Dict[bar=>Int] disallows key []'); ok((Dict[bar=>Int, slurpy Any])->my_hashref_allows_key('foo'), 'Dict[bar=>Int,slurpy Any] allows key "foo"'); ok((Dict[bar=>Int, slurpy Any])->my_hashref_allows_key('bar'), 'Dict[bar=>Int,slurpy Any] allows key "bar"'); ok(!(Dict[bar=>Int, slurpy Any])->my_hashref_allows_key(undef), 'Dict[bar=>Int,slurpy Any] disallows key undef'); ok(!(Dict[bar=>Int, slurpy Any])->my_hashref_allows_key([]), 'Dict[bar=>Int,slurpy Any] disallows key []'); ok((Dict[bar=>Int, slurpy Ref])->my_hashref_allows_key('foo'), 'Dict[bar=>Int,slurpy Ref] allows key "foo"'); ok((Dict[bar=>Int, slurpy Ref])->my_hashref_allows_key('bar'), 'Dict[bar=>Int,slurpy Ref] allows key "bar"'); ok(!(Dict[bar=>Int, slurpy Ref])->my_hashref_allows_key(undef), 'Dict[bar=>Int,slurpy Ref] disallows key undef'); ok(!(Dict[bar=>Int, slurpy Ref])->my_hashref_allows_key([]), 'Dict[bar=>Int,slurpy Ref] disallows key []'); ok(!(Dict[bar=>Int, slurpy Map[Int,Int]])->my_hashref_allows_key('foo'), 'Dict[bar=>Int,slurpy Map[Int,Int]] disallows key "foo"'); ok((Dict[bar=>Int, slurpy Map[Int,Int]])->my_hashref_allows_key('bar'), 'Dict[bar=>Int,slurpy Map[Int,Int]] allows key "bar"'); ok(!(Dict[bar=>Int, slurpy Map[Int,Int]])->my_hashref_allows_key(undef), 'Dict[bar=>Int,slurpy Map[Int,Int]] disallows key undef'); ok(!(Dict[bar=>Int, slurpy Map[Int,Int]])->my_hashref_allows_key([]), 'Dict[bar=>Int,slurpy Map[Int,Int]] disallows key []'); ok((Dict[bar=>Int, slurpy Map[Int,Int]])->my_hashref_allows_key('42'), 'Dict[bar=>Int,slurpy Map[Int,Int]] allows key "42"'); ok(HashRef->create_child_type->my_hashref_allows_key('foo'), 'A child of HashRef allows key "foo"'); ok(!HashRef->create_child_type->my_hashref_allows_key(undef), 'A child of HashRef disallows key undef'); ok(!HashRef->create_child_type->my_hashref_allows_key([]), 'A child of HashRef disallows key []'); ok((HashRef[Int])->create_child_type->my_hashref_allows_key('foo'), 'A child of HashRef[Int] allows key "foo"'); ok(!(HashRef[Int])->create_child_type->my_hashref_allows_key(undef), 'A child of HashRef[Int] disallows key undef'); ok(!(HashRef[Int])->create_child_type->my_hashref_allows_key([]), 'A child of HashRef[Int] disallows key []'); ok(Map->create_child_type->my_hashref_allows_key('foo'), 'A child of Map allows key "foo"'); ok(!Map->create_child_type->my_hashref_allows_key(undef), 'A child of Map disallows key undef'); ok(!Map->create_child_type->my_hashref_allows_key([]), 'A child of Map disallows key []'); ok(!(Map[Int,Int])->create_child_type->my_hashref_allows_key('foo'), 'A child of Map[Int,Int] disallows key "foo"'); ok(!(Map[Int,Int])->create_child_type->my_hashref_allows_key(undef), 'A child of Map[Int,Int] disallows key undef'); ok(!(Map[Int,Int])->create_child_type->my_hashref_allows_key([]), 'A child of Map[Int,Int] disallows key []'); ok((Map[Int,Int])->create_child_type->my_hashref_allows_key('42'), 'A child of Map[Int,Int] allows key "42"'); ok(Dict->create_child_type->my_hashref_allows_key('foo'), 'A child of Dict allows key "foo"'); ok(!Dict->create_child_type->my_hashref_allows_key(undef), 'A child of Dict disallows key undef'); ok(!Dict->create_child_type->my_hashref_allows_key([]), 'A child of Dict disallows key []'); ok(!(Dict[])->create_child_type->my_hashref_allows_key('foo'), 'A child of Dict[] disallows key "foo"'); ok(!(Dict[])->create_child_type->my_hashref_allows_key(undef), 'A child of Dict[] disallows key undef'); ok(!(Dict[])->create_child_type->my_hashref_allows_key([]), 'A child of Dict[] disallows key []'); ok(!(Dict[bar=>Int])->create_child_type->my_hashref_allows_key('foo'), 'A child of Dict[bar=>Int] disallows key "foo"'); ok((Dict[bar=>Int])->create_child_type->my_hashref_allows_key('bar'), 'A child of Dict[bar=>Int] allows key "bar"'); ok(!(Dict[bar=>Int])->create_child_type->my_hashref_allows_key(undef), 'A child of Dict[bar=>Int] disallows key undef'); ok(!(Dict[bar=>Int])->create_child_type->my_hashref_allows_key([]), 'A child of Dict[bar=>Int] disallows key []'); ok((Dict[bar=>Int, slurpy Any])->create_child_type->my_hashref_allows_key('foo'), 'A child of Dict[bar=>Int,slurpy Any] allows key "foo"'); ok((Dict[bar=>Int, slurpy Any])->create_child_type->my_hashref_allows_key('bar'), 'A child of Dict[bar=>Int,slurpy Any] allows key "bar"'); ok(!(Dict[bar=>Int, slurpy Any])->create_child_type->my_hashref_allows_key(undef), 'A child of Dict[bar=>Int,slurpy Any] disallows key undef'); ok(!(Dict[bar=>Int, slurpy Any])->create_child_type->my_hashref_allows_key([]), 'A child of Dict[bar=>Int,slurpy Any] disallows key []'); ok((Dict[bar=>Int, slurpy Ref])->create_child_type->my_hashref_allows_key('foo'), 'A child of Dict[bar=>Int,slurpy Ref] allows key "foo"'); ok((Dict[bar=>Int, slurpy Ref])->create_child_type->my_hashref_allows_key('bar'), 'A child of Dict[bar=>Int,slurpy Ref] allows key "bar"'); ok(!(Dict[bar=>Int, slurpy Ref])->create_child_type->my_hashref_allows_key(undef), 'A child of Dict[bar=>Int,slurpy Ref] disallows key undef'); ok(!(Dict[bar=>Int, slurpy Ref])->create_child_type->my_hashref_allows_key([]), 'A child of Dict[bar=>Int,slurpy Ref] disallows key []'); ok(!(Dict[bar=>Int, slurpy Map[Int,Int]])->create_child_type->my_hashref_allows_key('foo'), 'A child of Dict[bar=>Int,slurpy Map[Int,Int]] disallows key "foo"'); ok((Dict[bar=>Int, slurpy Map[Int,Int]])->create_child_type->my_hashref_allows_key('bar'), 'A child of Dict[bar=>Int,slurpy Map[Int,Int]] allows key "bar"'); ok(!(Dict[bar=>Int, slurpy Map[Int,Int]])->create_child_type->my_hashref_allows_key(undef), 'A child of Dict[bar=>Int,slurpy Map[Int,Int]] disallows key undef'); ok(!(Dict[bar=>Int, slurpy Map[Int,Int]])->create_child_type->my_hashref_allows_key([]), 'A child of Dict[bar=>Int,slurpy Map[Int,Int]] disallows key []'); ok((Dict[bar=>Int, slurpy Map[Int,Int]])->create_child_type->my_hashref_allows_key('42'), 'A child of Dict[bar=>Int,slurpy Map[Int,Int]] allows key "42"'); }; # This could probably be expanded... subtest my_hashref_allows_value => sub { ok(HashRef->my_hashref_allows_value(foo => "bar"), 'HashRef allows key "foo" with value "bar"'); ok(HashRef->my_hashref_allows_value(foo => undef), 'HashRef allows key "foo" with value undef'); ok(!HashRef->my_hashref_allows_value(undef, "bar"), 'HashRef disallows key undef with value "bar"'); ok(!(HashRef[Int])->my_hashref_allows_value(foo => "bar"), 'HashRef[Int] disallows key "foo" with value "bar"'); ok((Dict[bar=>Int, slurpy Map[Int,Int]])->create_child_type->my_hashref_allows_value(bar => 42), 'A child of Dict[bar=>Int,slurpy Map[Int,Int]] allows key "bar" with value 42'); ok((Dict[bar=>Int, slurpy Map[Int,Int]])->create_child_type->my_hashref_allows_value(21, 42), 'A child of Dict[bar=>Int,slurpy Map[Int,Int]] allows key "21" with value 42'); ok(!(Dict[bar=>Int, slurpy Map[Int,Int]])->create_child_type->my_hashref_allows_value(baz => 42), 'A child of Dict[bar=>Int,slurpy Map[Int,Int]] disallows key "baz" with value 42'); }; done_testing; tied.t000664001750001750 437212422772210 20022 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Types-Standard=pod =encoding utf-8 =head1 PURPOSE Checks various values against C from Types::Standard. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::TypeTiny; use Types::Standard qw( Tied HashRef ); use Type::Utils qw( class_type ); my $a = do { package MyTie::Array; require Tie::Array; our @ISA = qw(Tie::StdArray); tie my(@A), __PACKAGE__; \@A; }; my $h = do { package MyTie::Hash; require Tie::Hash; our @ISA = qw(Tie::StdHash); tie my(%H), __PACKAGE__; \%H }; my $S; my $s = do { package MyTie::Scalar; require Tie::Scalar; our @ISA = qw(Tie::StdScalar); tie $S, __PACKAGE__; \$S; }; should_pass($a, Tied); should_pass($h, Tied); should_pass($s, Tied); should_fail($S, Tied); should_pass($a, Tied["MyTie::Array"]); should_fail($h, Tied["MyTie::Array"]); should_fail($s, Tied["MyTie::Array"]); should_fail($a, Tied["MyTie::Hash"]); should_pass($h, Tied["MyTie::Hash"]); should_fail($s, Tied["MyTie::Hash"]); should_fail($a, Tied["MyTie::Scalar"]); should_fail($h, Tied["MyTie::Scalar"]); should_pass($s, Tied["MyTie::Scalar"]); should_pass($a, Tied[ class_type MyTieArray => { class => "MyTie::Array" } ]); should_fail($h, Tied[ class_type MyTieArray => { class => "MyTie::Array" } ]); should_fail($s, Tied[ class_type MyTieArray => { class => "MyTie::Array" } ]); should_fail($a, Tied[ class_type MyTieHash => { class => "MyTie::Hash" } ]); should_pass($h, Tied[ class_type MyTieHash => { class => "MyTie::Hash" } ]); should_fail($s, Tied[ class_type MyTieHash => { class => "MyTie::Hash" } ]); should_fail($a, Tied[ class_type MyTieScalar => { class => "MyTie::Scalar" } ]); should_fail($h, Tied[ class_type MyTieScalar => { class => "MyTie::Scalar" } ]); should_pass($s, Tied[ class_type MyTieScalar => { class => "MyTie::Scalar" } ]); my $intersection = (Tied) & (HashRef); should_pass($h, $intersection); should_fail($a, $intersection); should_fail($s, $intersection); should_fail({foo=>2}, $intersection); done_testing; basic.t000664001750001750 563712422772210 20210 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Types-TypeTiny=pod =encoding utf-8 =head1 PURPOSE Test the L bootstrap library. (That is, type constraints used by Type::Tiny internally.) =head1 DEPENDENCIES This test requires L 2.0600 and L 1.00. Otherwise, it is skipped. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); # Test::Requires calls ->import on Moose/Mouse, so be sure # to import them into dummy packages. { package XXX; use Test::Requires { Moose => '2.0600' } }; { package YYY; use Test::Requires { Mouse => '1.00' } }; use Test::More; use Test::TypeTiny -all; use Types::TypeTiny -all; use Moose::Util::TypeConstraints qw(find_type_constraint); my $stringy = do { package Overloaded::String; use overload q[""] => sub { "Hello world" }, fallback => 1; bless {}; }; my $hashy = do { package Overloaded::HashRef; use overload q[%{}] => sub { +{} }, fallback => 1; bless []; }; my $arrayey = do { package Overloaded::ArrayRef; use overload q[@{}] => sub { [] }, fallback => 1; bless {}; }; my $codey = do { package Overloaded::CodeRef; use overload q[&{}] => sub { sub { 42 } }, fallback => 1; bless []; }; subtest "StringLike" => sub { my $type = StringLike; should_pass( "Hello", $type ); should_pass( "", $type ); should_pass( CodeLike, $type, 'Type::Tiny constraint object passes type constraint StringLike' ); should_pass( $stringy, $type ); should_fail( {}, $type ); should_fail( undef, $type ); }; subtest "ArrayLike" => sub { my $type = ArrayLike; should_pass( [], $type ); should_pass( $arrayey, $type ); should_fail( {}, $type ); should_fail( bless([], 'XXX'), $type ); should_fail( undef, $type ); }; subtest "HashLike" => sub { my $type = HashLike; should_pass( {}, $type ); should_pass( $hashy, $type ); should_fail( [], $type ); should_fail( bless({}, 'XXX'), $type ); should_fail( undef, $type ); }; subtest "CodeLike" => sub { my $type = CodeLike; should_pass( sub { 42 }, $type ); should_pass( CodeLike, $type, 'Type::Tiny constraint object passes type constraint CodeLike' ); should_pass( $codey, $type ); should_fail( {}, $type ); should_fail( bless(sub {42}, 'XXX'), $type ); should_fail( undef, $type ); }; subtest "TypeTiny" => sub { my $type = TypeTiny; should_pass( ArrayLike, $type, 'Type::Tiny constraint object passes type constraint TypeTiny' ); should_fail( {}, $type ); should_fail( sub { 42 }, $type ); should_fail( find_type_constraint("Int"), $type, 'Moose constraint object fails type constraint TypeTiny' ); should_fail( Mouse::Util::TypeConstraints::find_type_constraint("Int"), $type, 'Mouse constraint object fails type constraint TypeTiny' ); should_fail( undef, $type ); }; done_testing; coercion.t000664001750001750 627012422772210 20722 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Types-TypeTiny=pod =encoding utf-8 =head1 PURPOSE Test L pseudo-coercion. =head1 DEPENDENCIES This test requires L 2.0600, L 1.00, and L 1.000000. Otherwise, it is skipped. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); # Test::Requires calls ->import on Moose/Mouse, so be sure # to import them into dummy packages. { package XXX; use Test::Requires { Moose => '2.0600' } }; { package YYY; use Test::Requires { Mouse => '1.00' } }; { package ZZZ; use Test::Requires { Moo => '1.000000' } }; use Test::More; use Test::TypeTiny -all; use Types::TypeTiny -all; use Moose::Util::TypeConstraints qw(find_type_constraint); subtest "Coercion from Moose type constraint object" => sub { my $orig = find_type_constraint("Int"); my $type = to_TypeTiny $orig; should_pass($type, TypeTiny, 'to_TypeTiny converted a Moose type constraint to a Type::Tiny one'); is($type->name, 'Int', '... which has the correct name'); ok($type->can_be_inlined, '... and which can be inlined'); note $type->inline_check('$X'); subtest "... and it works" => sub { should_pass(123, $type); should_fail(3.3, $type); }; ## We don't do this for Moose for some reason. # # is( # $type->get_message(3.3), # $orig->get_message(3.3), # '... and provides proper message', # ); }; subtest "Coercion from Mouse type constraint object" => sub { my $orig = Mouse::Util::TypeConstraints::find_type_constraint("Int"); my $type = to_TypeTiny $orig; should_pass($type, TypeTiny, 'to_TypeTiny converted a Mouse type constraint to a Type::Tiny one'); subtest "... and it works" => sub { should_pass(123, $type); should_fail(3.3, $type); }; is( $type->get_message(3.3), $orig->get_message(3.3), '... and provides proper message', ); }; subtest "Coercion from predicate-like coderef" => sub { my $type = to_TypeTiny sub { $_[0] =~ /\A-?[0-9]+\z/ }; should_pass($type, TypeTiny, 'to_TypeTiny converted the coderef to a Type::Tiny object'); subtest "... and it works" => sub { should_pass(123, $type); should_fail(3.3, $type); }; }; subtest "Coercion from assertion-like coderef" => sub { my $type = to_TypeTiny sub { $_[0] =~ /\A-?[0-9]+\z/ or die("not an integer") }; should_pass($type, TypeTiny, 'to_TypeTiny converted the coderef to a Type::Tiny object'); subtest "... and it works" => sub { should_pass(123, $type); should_fail(3.3, $type); }; like( $type->validate(3.3), qr/\Anot an integer/, '... and provides proper message', ); }; subtest "Coercion from Sub::Quote coderef" => sub { require Sub::Quote; my $type = to_TypeTiny Sub::Quote::quote_sub(q{ $_[0] =~ /\A-?[0-9]+\z/ }); should_pass($type, TypeTiny, 'to_TypeTiny converted the coderef to a Type::Tiny object'); ok($type->can_be_inlined, '... which can be inlined'); note $type->inline_check('$X'); subtest "... and it works" => sub { should_pass(123, $type); should_fail(3.3, $type); }; }; done_testing; meta.t000664001750001750 254112422772210 20044 0ustar00taitai000000000000Type-Tiny-1.000005/t/20-unit/Types-TypeTiny=pod =encoding utf-8 =head1 PURPOSE Test the L introspection methods. Types::TypeTiny doesn't inherit from L (because bootstrapping), so provides independent re-implementations of the most important introspection stuff. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::TypeTiny -all; use Types::TypeTiny; my $meta = Types::TypeTiny->meta; is_deeply( [ sort $meta->type_names ], [ sort qw( CodeLike ArrayLike StringLike HashLike TypeTiny ) ], 'type_names', ); ok( $meta->has_type('HashLike'), 'has_type(HashLike)', ); ok( $meta->get_type('HashLike')->equals(Types::TypeTiny::HashLike()), 'get_type(HashLike)', ); ok( !$meta->has_type('MonkeyNuts'), 'has_type(MonkeyNuts)', ); ok( !defined( $meta->get_type('MonkeyNuts') ), 'get_type(MonkeyNuts)', ); is_deeply( [ sort $meta->coercion_names ], [], 'coercion_names', ); ok( !$meta->has_coercion('MonkeyNuts'), 'has_coercion(MonkeyNuts)', ); ok( !defined( $meta->get_coercion('MonkeyNuts') ), 'get_coercion(MonkeyNuts)', ); done_testing; basic.t000664001750001750 1043012422772210 21637 0ustar00taitai000000000000Type-Tiny-1.000005/t/30-integration/Class-InsideOut=pod =encoding utf-8 =head1 PURPOSE Check type constraints work with L. =head1 DEPENDENCIES Test is skipped if Class::InsideOut 1.13 is not available. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. Based on C<< t/14_accessor_hooks.t >> from the Class::InsideOut test suite, by David Golden. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by David Golden, Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::Requires { "Class::InsideOut" => 1.13 }; use Test::More; BEGIN { package Object::HookedTT; use Class::InsideOut ':std'; use Types::Standard -types; # $_ has the first argument in it for convenience public integer => my %integer, { set_hook => Int }; # first argument is also available directly public word => my %word, { set_hook => StrMatch[qr/\A\w+\z/] }; # Changing $_ changes what gets stored my $UC = (StrMatch[qr/\A[A-Z]+\z/])->plus_coercions(Str, q{uc $_}); public uppercase => my %uppercase, { set_hook => sub { $_ = $UC->coercion->($_) }, }; # Full @_ is available, but only first gets stored public list => my %list, { set_hook => sub { $_ = ArrayRef->check($_) ? $_ : [ @_ ] }, get_hook => sub { @$_ }, }; public reverser => my %reverser, { set_hook => sub { $_ = ArrayRef->check($_) ? $_ : [ @_ ] }, get_hook => sub { reverse @$_ } }; public write_only => my %only_only, { get_hook => sub { die "is write-only\n" } }; sub new { register( bless {}, shift ); } }; #--------------------------------------------------------------------------# my $class = "Object::HookedTT"; my $properties = { $class => { integer => "public", uppercase => "public", word => "public", list => "public", reverser => "public", write_only => "public", }, }; my ($o, @got, $got); #--------------------------------------------------------------------------# is_deeply( Class::InsideOut::_properties( $class ), $properties, "$class has/inherited its expected properties", ); ok( ($o = $class->new()) && $o->isa($class), "Creating a $class object", ); #--------------------------------------------------------------------------# eval { $o->integer(3.14) }; my $err = $@; like( $err, '/integer\(\) Value "3.14" did not pass type constraint "Int"/i', "integer(3.14) dies", ); eval { $o->integer(42) }; is( $@, q{}, "integer(42) lives", ); is( $o->integer, 42, "integer() == 42", ); #--------------------------------------------------------------------------# eval { $o->word("^^^^") }; like( $@, '/word\(\) value "\^\^\^\^" did not pass type constraint/i', "word(^^^^) dies", ); eval { $o->word("apple") }; is( $@, q{}, "word(apple) lives", ); is( $o->word, 'apple', "word() eq 'apple'", ); #--------------------------------------------------------------------------# eval { $o->uppercase("banana") }; is( $@, q{}, "uppercase(banana) lives", ); is( $o->uppercase, 'BANANA', "uppercase() eq 'BANANA'", ); #--------------------------------------------------------------------------# # list(@array) eval { $o->list(qw(foo bar bam)) }; is( $@, q{}, "list(qw(foo bar bam)) lives", ); is_deeply( [ $o->list ], [qw(foo bar bam)], "list() gives qw(foo bar bam)", ); # list(\@array) eval { $o->list( [qw(foo bar bam)] ) }; is( $@, q{}, "list( [qw(foo bar bam)] ) lives", ); is_deeply( [ $o->list ], [qw(foo bar bam)], "list() gives qw(foo bar bam)", ); #--------------------------------------------------------------------------# eval { $o->reverser(qw(foo bar bam)) }; is( $@, q{}, "reverser(qw(foo bar bam)) lives", ); # reverser in list context @got = $o->reverser; is_deeply( \@got, [qw(bam bar foo)], "reverser() in list context gives qw(bam bar foo)", ); # reverser in scalar context $got = $o->reverser; is( $got, 'mabraboof', "reverser() in scalar context gives mabraboof", ); #--------------------------------------------------------------------------# eval { $o->write_only( 23 ) }; is( $@, q{}, "write_only lives on write", ); eval { $got = $o->write_only() }; like( $@, '/write_only\(\) is write-only at/i', "write only dies on write (and was caught)", ); done_testing; basic.t000664001750001750 424212422772210 21406 0ustar00taitai000000000000Type-Tiny-1.000005/t/30-integration/Exporter-Tiny=pod =encoding utf-8 =head1 PURPOSE Tests L has the features Type::Tiny needs. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Fatal; require Types::Standard; is( exception { "Types::Standard"->import("Any") }, undef, q {No exception exporting a legitimate function}, ); can_ok(main => "Any"); isnt( exception { "Types::Standard"->import("kghffubbtfui") }, undef, q {Attempt to export a function which does not exist}, ); isnt( exception { "Types::Standard"->import("declare") }, undef, q {Attempt to export a function which exists but not in @EXPORT_OK}, ); { my $hash = {}; "Types::Standard"->import({ into => $hash }, qw(-types)); is_deeply( [ sort keys %$hash ], [ sort "Types::Standard"->meta->type_names ], '"-types" shortcut works', ); }; { my $hash = {}; "Types::Standard"->import({ into => $hash }, qw(-coercions)); is_deeply( [ sort keys %$hash ], [ sort "Types::Standard"->meta->coercion_names ], '"-coercions" shortcut works', ); }; { my $hash = {}; "Types::Standard"->import({ into => $hash }, Str => { }); "Types::Standard"->import({ into => $hash }, Str => { -as => "String" }); "Types::Standard"->import({ into => $hash }, -types => { -prefix => "X_" }); "Types::Standard"->import({ into => $hash }, -types => { -suffix => "_Z" }); is($hash->{Str}, $hash->{String}, 'renaming works'); is($hash->{Str}, $hash->{X_Str}, 'prefixes work'); is($hash->{Str}, $hash->{Str_Z}, 'suffixes work'); }; { my $hash = {}; "Types::Standard"->import({ into => $hash }, qw(+Str)); is_deeply( [sort keys %$hash], [sort qw/ assert_Str to_Str is_Str Str /], 'plus notation works for Type::Library', ); }; my $opthash = Exporter::Tiny::mkopt_hash([ foo => [], "bar" ]); is_deeply( $opthash, { foo => [], bar => undef }, 'mkopt_hash', ) or diag explain($opthash); done_testing; installer.t000664001750001750 155712422772210 22330 0ustar00taitai000000000000Type-Tiny-1.000005/t/30-integration/Exporter-Tiny=pod =encoding utf-8 =head1 PURPOSE Tests L libraries work with Sub::Exporter plugins. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::Requires { "Sub::Exporter::Lexical" => "0.092291" }; use Test::More; use Test::Fatal; { use Sub::Exporter::Lexical qw( lexical_installer ); use Types::Standard { installer => lexical_installer }, qw( ArrayRef ); ArrayRef->( [] ); } ok(!eval q{ ArrayRef->( [] ) }, 'the ArrayRef function was cleaned away'); ok(!__PACKAGE__->can("ArrayRef"), 'ArrayRef does not appear to be a method'); done_testing; role-conflict.t000664001750001750 231512422772210 23064 0ustar00taitai000000000000Type-Tiny-1.000005/t/30-integration/Exporter-Tiny=pod =encoding utf-8 =head1 PURPOSE Tests exporting to two roles; tries to avoid reporting conflicts. =head1 DEPENDENCIES Requires L 5.59 and L 1.000000; test skipped otherwise. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 THANKS This test case is based on a script provided by Kevin Dawson. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::Requires { "Exporter" => 5.59 }; use Test::Requires { "Role::Tiny" => 1.000000 }; use Test::More; use Test::Fatal; { package Local::Role1; use Role::Tiny; use Types::Standard "Str"; } { package Local::Role2; use Role::Tiny; use Types::Standard "Str"; } my $e = exception { package Local::Class1; use Role::Tiny::With; with qw( Local::Role1 Local::Role2 ); }; is($e, undef, 'no exception when trying to compose two roles that use type constraints'); use Scalar::Util "refaddr"; note refaddr(\&Local::Role1::Str); note refaddr(\&Local::Role2::Str); done_testing; basic.t000664001750001750 223412422772210 22542 0ustar00taitai000000000000Type-Tiny-1.000005/t/30-integration/Function-Parameters=pod =encoding utf-8 =head1 PURPOSE Check type constraints work with L. =head1 DEPENDENCIES Requires Function::Parameters 1.0103, and either Moo 1.000000 or Moose 2.0000; skipped otherwise. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Requires { "Function::Parameters" => "1.0103" }; use Test::Fatal; BEGIN { eval 'use Moo 1.000000; 1' or eval 'use Moose 2.0000; 1' or plan skip_all => "this test requires Moo 1.000000 or Moose 2.0000"; }; use Types::Standard -types; use Function::Parameters qw(:strict); fun foo ((Int) $x) { return $x; } is( foo(4), 4, 'foo(4) works', ); isnt( exception { foo(4.1) }, undef, 'foo(4.1) throws', ); my $info = Function::Parameters::info(\&foo); my ($x) = $info->positional_required; is($x->name, '$x', '$x->name'); ok($x->type == Int, '$x->type'); done_testing; basic.t000664001750001750 200512422772210 20246 0ustar00taitai000000000000Type-Tiny-1.000005/t/30-integration/Kavorka=pod =encoding utf-8 =head1 PURPOSE Checks Type::Tiny works with L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Requires 'Kavorka'; use Test::Fatal; use Kavorka; use Types::Standard qw(Int Num); fun xyz ( Int $x, (Int) $y, (Int->plus_coercions(Num, 'int($_)')) $z does coerce ) { $x * $y * $z; } is( exception { is( xyz(2,3,4), 24, 'easy sub call; all type constraints should pass', ); is( xyz(2,3,4.2), 24, 'easy sub call; all type constraints should pass or coerce', ); }, undef, '... neither raise an exception', ); isnt( exception { xyz(2.1,3,4) }, undef, 'failed type constraint with no coercion raises an exception', ); done_testing; basic.t000664001750001750 267212422772210 17414 0ustar00taitai000000000000Type-Tiny-1.000005/t/30-integration/Moo=pod =encoding utf-8 =head1 PURPOSE Check type constraints work with L. Checks values that should pass and should fail; checks error messages. =head1 DEPENDENCIES Uses the bundled BiggerLib.pm type library. Test is skipped if Moo 1.001000 is not available. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Requires { Moo => 1.001000 }; use Test::Fatal; { package Local::Class; use Moo; use BiggerLib ":all"; has small => (is => "ro", isa => SmallInteger); has big => (is => "ro", isa => BigInteger); } is( exception { "Local::Class"->new(small => 9, big => 12) }, undef, "some values that should pass their type constraint", ); isnt( exception { "Local::Class"->new(small => 100) }, undef, "direct violation of type constraint", ); isnt( exception { "Local::Class"->new(small => 5.5) }, undef, "violation of parent type constraint", ); isnt( exception { "Local::Class"->new(small => "five point five") }, undef, "violation of grandparent type constraint", ); isnt( exception { "Local::Class"->new(small => []) }, undef, "violation of great-grandparent type constraint", ); done_testing; coercion-inlining-avoidance.t000664001750001750 543612422772210 23671 0ustar00taitai000000000000Type-Tiny-1.000005/t/30-integration/Moo=pod =encoding utf-8 =head1 PURPOSE A rather complex case of defining an attribute with a type coercion in Moo; and only then adding coercion definitions to it. Does Moo pick up on the changes? It should. =head1 DEPENDENCIES Test is skipped if Moo 1.004000 is not available. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; use Test::Requires { 'Moo' => '1.004000' }; use Test::Fatal; use Types::Standard -types; my $e; my $type = Int->create_child_type( name => 'MyInt', coercion => [ Num, q[int($_)] ], ); ok( !$type->coercion->frozen, 'created a type constraint without a frozen coercion', ); ok( !$type->coercion->can_be_inlined, '... it reports that it cannot be inlined', ); { package Foo; use Moo; has foo => (is => 'ro', isa => $type, coerce => $type->coercion); } # We need to do some quick checks before adding the coercions, # partly because this is interesting to check, and partly because # we need to ensure that the is( Foo->new(foo => 3.2)->foo, 3, 'initial use of type in a Moo constructor', ); $e = exception { Foo->new(foo => [3..4])->foo }; like( $e->message, qr/did not pass type constraint/, '... and it cannot coerce from an arrayref', ); $e = exception { Foo->new(foo => { value => 42 })->foo }; like( $e->message, qr/did not pass type constraint/, '... and it cannot coerce from an hashref', ); is( exception { $type->coercion->add_type_coercions( ArrayRef, q[scalar(@$_)], HashRef, q[$_->{value}], ScalarRef, q["this is just a talisman"], ); }, undef, 'can add coercions from ArrayRef and HashRef to the type', ); ok( !$type->coercion->frozen, '... it is still not frozen', ); ok( !$type->coercion->can_be_inlined, '... it reports that it still cannot be inlined', ); is( Foo->new(foo => 3.2)->foo, 3, 'again use of type in a Moo constructor', ); is( Foo->new(foo => [3..4])->foo, 2, '... but can coerce from ArrayRef', ); is( Foo->new(foo => { value => 42 })->foo, 42, '... and can coerce from HashRef', ); is( exception { $type->coercion->freeze }, undef, 'can freeze the coercion', ); ok( $type->coercion->frozen, '... it reports that it is frozen', ); ok( $type->coercion->can_be_inlined, '... it reports that it can be inlined', ); { package Goo; use Moo; has foo => (is => 'ro', isa => $type, coerce => $type->coercion); } Goo->new; if ( $ENV{AUTHOR_TESTING} ) { require B::Deparse; my $deparsed = B::Deparse->new->coderef2text(\&Goo::new); like($deparsed, qr/talisman/i, 'Moo inlining for coercions') or diag($deparsed); } done_testing; coercion.t000664001750001750 413612422772210 20131 0ustar00taitai000000000000Type-Tiny-1.000005/t/30-integration/Moo=pod =encoding utf-8 =head1 PURPOSE Check coercions work with L. =head1 DEPENDENCIES Uses the bundled BiggerLib.pm type library. Test is skipped if Moo 1.001000 is not available. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Requires { Moo => 1.001000 }; use Test::Fatal; { package Local::Class; use Moo; use BiggerLib -all; ::isa_ok(BigInteger, "Type::Tiny"); has small => (is => "rw", isa => SmallInteger, coerce => SmallInteger->coercion); has big => (is => "rw", isa => BigInteger, coerce => BigInteger->coercion); } my ($e, $o); my $suffix = "mutable class"; for (0..1) { $e = exception { $o = "Local::Class"->new( small => 104, big => 9, ); }; is($e, undef, "no exception on coercion in constructor - $suffix"); is($o && $o->big, 19, "'big' attribute coerces in constructor - $suffix"); is($o && $o->small, 4, "'small' attribute coerces in constructor - $suffix"); $e = exception { $o = "Local::Class"->new( small => [], big => {}, ); }; ok($e, "'big' attribute throws when it cannot coerce in constructor - $suffix"); $e = exception { $o = "Local::Class"->new( small => {}, big => [], ); }; ok($e, "'small' attribute throws when it cannot coerce in constructor - $suffix"); $o = "Local::Class"->new; $e = exception { $o->big([]); $o->small([]); }; is($o && $o->big, 100, "'big' attribute coerces in accessor - $suffix"); is($o && $o->small, 1, "'small' attribute coerces in accessor - $suffix"); $e = exception { $o->big({}) }; ok($e, "'big' attribute throws when it cannot coerce in accessor - $suffix"); $e = exception { $o->small({}) }; ok($e, "'small' attribute throws when it cannot coerce in accessor - $suffix"); "Local::Class"->meta->make_immutable; $suffix = "im$suffix"; } done_testing; exceptions.t000664001750001750 412212422772210 20504 0ustar00taitai000000000000Type-Tiny-1.000005/t/30-integration/Moo=pod =encoding utf-8 =head1 PURPOSE Tests L interaction with L. =head1 DEPENDENCIES Requires Moo 1.002001 or above; skipped otherwise. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Fatal; use Test::Requires { "Moo" => "1.002001" }; BEGIN { require Method::Generate::Accessor; "Method::Generate::Accessor"->can("_SIGDIE") or "Moo"->VERSION =~ /^1\.006/ or plan skip_all => "Method::Generate::Accessor exception support seems missing!!!"; }; { package Goo; use Moo; use Types::Standard qw(Int); has number => (is => "rw", isa => Int); } my $e_constructor = exception { Goo->new(number => "too") }; isa_ok($e_constructor, 'Error::TypeTiny::Assertion', '$e_constructor'); ok($e_constructor->has_attribute_name, '$e_constructor->has_attribute_name'); is($e_constructor->attribute_name, 'number', '$e_constructor->attribute_name'); ok($e_constructor->has_attribute_step, '$e_constructor->has_attribute_step'); is($e_constructor->attribute_step, 'isa check', '$e_constructor->attribute_step'); is($e_constructor->varname, '$args->{"number"}', '$e_constructor->varname'); is($e_constructor->value, "too", '$e_constructor->value'); is($e_constructor->type, Types::Standard::Int, '$e_constructor->type'); my $e_accessor = exception { Goo->new->number("too") }; isa_ok($e_accessor, 'Error::TypeTiny::Assertion', '$e_accessor'); ok($e_accessor->has_attribute_name, '$e_accessor->has_attribute_name'); is($e_accessor->attribute_name, 'number', '$e_accessor->attribute_name'); ok($e_accessor->has_attribute_step, '$e_accessor->has_attribute_step'); is($e_accessor->attribute_step, 'isa check', '$e_accessor->attribute_step'); is($e_accessor->value, "too", '$e_accessor->value'); is($e_accessor->type, Types::Standard::Int, '$e_accessor->type'); done_testing; inflation.t000664001750001750 410612422772210 20310 0ustar00taitai000000000000Type-Tiny-1.000005/t/30-integration/Moo=pod =encoding utf-8 =head1 PURPOSE Checks that type constraints continue to work when a L class is inflated to a L class. Checks that Moo::HandleMoose correctly calls back to Type::Tiny to build Moose type constraints. =head1 DEPENDENCIES Uses the bundled BiggerLib.pm type library. Test is skipped if Moo 1.001000 is not available. Test is redundant if Moose 2.0000 is not available. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Requires { Moo => 1.001000 }; use Test::Fatal; { package Local::Class; use Moo; use BiggerLib ":all"; has small => (is => "ro", isa => SmallInteger); has big => (is => "ro", isa => BigInteger); } note explain(\%Moo::HandleMoose::TYPE_MAP); my $state = "Moose is not loaded"; for (0..1) { is( exception { "Local::Class"->new(small => 9, big => 12) }, undef, "some values that should pass their type constraint - $state", ); ok( exception { "Local::Class"->new(small => 100) }, "direct violation of type constraint - $state", ); ok( exception { "Local::Class"->new(small => 5.5) }, "violation of parent type constraint - $state", ); ok( exception { "Local::Class"->new(small => "five point five") }, "violation of grandparent type constraint - $state", ); ok( exception { "Local::Class"->new(small => []) }, "violation of great-grandparent type constraint - $state", ); eval q{ require Moose; Moose->VERSION(2.0000); "Local::Class"->meta->get_attribute("small"); "Local::Class"->meta->get_attribute("big"); $state = "Moose is loaded"; }; } $state eq 'Moose is loaded' ? is( "Local::Class"->meta->get_attribute("small")->type_constraint->name, "SmallInteger", "type constraint metaobject inflates from Moo to Moose", ) : pass("redundant test"); done_testing; inflation2.t000664001750001750 167512422772210 20402 0ustar00taitai000000000000Type-Tiny-1.000005/t/30-integration/Moo=pod =encoding utf-8 =head1 PURPOSE A test for type constraint inflation from L to L. =head1 DEPENDENCIES Requires Moo 1.003000 and Moose 2.0800; skipped otherwise. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; use Test::Fatal; use Test::Requires { 'Moo' => '1.003000' }; use Test::Requires { 'Moose' => '2.0800' }; use Types::Standard qw/Str HashRef/; my $type = HashRef[Str]; { package AAA; BEGIN { $INC{'AAA.pm'} = __FILE__ }; use Moo::Role; has foo => ( is => 'ro', isa => $type, traits => ['Hash'], ); } { package BBB; use Moose; with 'AAA'; } ok not exception { 'BBB'->new( foo => { a => 'b' } ); }; done_testing; basic.t000664001750001750 175612422772210 17761 0ustar00taitai000000000000Type-Tiny-1.000005/t/30-integration/Moops=pod =encoding utf-8 =head1 PURPOSE Check that type constraints work in L. This file is borrowed from the Moops test suite, where it is called C<< 31types.t >>. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; use Test::Requires 'Moops'; use Test::Fatal; use Moops; class Foo { has num => (is => 'rw', isa => Num); method add ( Num $addition ) { $self->num( $self->num + $addition ); } } my $foo = 'Foo'->new(num => 20); is($foo->num, 20); is($foo->num(40), 40); is($foo->num, 40); is($foo->add(2), 42); is($foo->num, 42); isnt( exception { $foo->num("Hello") }, undef, ); isnt( exception { $foo->add("Hello") }, undef, ); isnt( exception { 'Foo'->new(num => "Hello") }, undef, ); done_testing; library-keyword.t000664001750001750 211012422772210 22007 0ustar00taitai000000000000Type-Tiny-1.000005/t/30-integration/Moops=pod =encoding utf-8 =head1 PURPOSE Check that type libraries can be declared with L. This file is borrowed from the Moops test suite, where it is called C<< 71library.t >>. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; use Test::Requires { 'Moops' => '0.018' }; use Test::Fatal; use Test::TypeTiny; use Moops; library MyTypes extends Types::Standard declares RainbowColour { declare RainbowColour, as Enum[qw/ red orange yellow green blue indigo violet /]; } should_pass('indigo', MyTypes::RainbowColour); should_fail('magenta', MyTypes::RainbowColour); class MyClass types MyTypes { method capitalize_colour ( $class: RainbowColour $r ) { return uc($r); } } is('MyClass'->capitalize_colour('indigo'), 'INDIGO'); ok exception { 'MyClass'->capitalize_colour('magenta') }; done_testing; accept-moose-types.t000664001750001750 315012422772210 22374 0ustar00taitai000000000000Type-Tiny-1.000005/t/30-integration/Moose=pod =encoding utf-8 =head1 PURPOSE Check that Moose type constraints can be passed into the Type::Tiny API where a Type::Tiny constraint might usually be expected. =head1 DEPENDENCIES Uses the bundled BiggerLib.pm type library. Test is skipped if Moose 2.0000 is not available. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Requires { Moose => 2.0000 }; use Test::Fatal; # Example from the manual { package Person; use Moose; use Types::Standard qw( Str Int ); use Type::Utils qw( declare as where inline_as coerce from ); ::isa_ok( Int, 'Moose::Meta::TypeConstraint', 'Int', ); ::isa_ok( Str, 'Moose::Meta::TypeConstraint', 'Str', ); has name => ( is => "ro", isa => Str, ); my $PositiveInt = declare as Int, where { $_ > 0 }, inline_as { "$_ =~ /^0-9]\$/ and $_ > 0" }; coerce $PositiveInt, from Int, q{ abs $_ }; ::isa_ok( $PositiveInt, 'Type::Tiny', '$PositiveInt', ); ::isa_ok( $PositiveInt->parent, 'Type::Tiny', '$PositiveInt->parent', ); has age => ( is => "ro", isa => $PositiveInt, coerce => 1, writer => "_set_age", ); sub get_older { my $self = shift; my ($years) = @_; $PositiveInt->assert_valid($years); $self->_set_age($self->age + $years); } } done_testing; basic.t000664001750001750 2021212422772210 17752 0ustar00taitai000000000000Type-Tiny-1.000005/t/30-integration/Moose=pod =encoding utf-8 =head1 PURPOSE Check type constraints work with L. Checks values that should pass and should fail; checks error messages. =head1 DEPENDENCIES Uses the bundled BiggerLib.pm type library. Test is skipped if Moose 2.0000 is not available. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Requires { Moose => 2.0000 }; use Test::Fatal; use Test::TypeTiny qw( matchfor ); note "The basics"; { package Local::Class; use Moose; use BiggerLib -all; has small => (is => "ro", isa => SmallInteger); has big => (is => "ro", isa => BigInteger); } is( exception { "Local::Class"->new(small => 9, big => 12) }, undef, "some values that should pass their type constraint", ); is( exception { "Local::Class"->new(small => 100) }, matchfor( 'Moose::Exception::ValidationFailedForTypeConstraint', qr{^Attribute \(small\) does not pass the type constraint} ), "direct violation of type constraint", ); is( exception { "Local::Class"->new(small => 5.5) }, matchfor( 'Moose::Exception::ValidationFailedForTypeConstraint', qr{^Attribute \(small\) does not pass the type constraint} ), "violation of parent type constraint", ); is( exception { "Local::Class"->new(small => "five point five") }, matchfor( 'Moose::Exception::ValidationFailedForTypeConstraint', qr{^Attribute \(small\) does not pass the type constraint} ), "violation of grandparent type constraint", ); is( exception { "Local::Class"->new(small => []) }, matchfor( 'Moose::Exception::ValidationFailedForTypeConstraint', qr{^Attribute \(small\) does not pass the type constraint} ), "violation of great-grandparent type constraint", ); note "Coercion..."; my $coercion; { package TmpNS1; use Moose::Util::TypeConstraints; use Scalar::Util qw(refaddr); subtype 'MyInt', as 'Int'; coerce 'MyInt', from 'ArrayRef', via { scalar(@$_) }; my $orig = find_type_constraint('MyInt'); my $type = Types::TypeTiny::to_TypeTiny($orig); ::ok($type->has_coercion, 'types converted from Moose retain coercions'); ::is($type->coerce([qw/a b c/]), 3, '... which work'); ::is(refaddr($type->moose_type), refaddr($orig), '... refaddr matches'); ::is(refaddr($type->coercion->moose_coercion), refaddr($orig->coercion), '... coercion refaddr matches'); $coercion = $type->coercion; } note "Introspection, comparisons, conversions..."; require Types::Standard; isa_ok( Types::Standard::Int(), 'Class::MOP::Object', 'Int', ); isa_ok( Types::Standard::ArrayRef(), 'Moose::Meta::TypeConstraint', 'ArrayRef', ); isa_ok( Types::Standard::ArrayRef(), 'Moose::Meta::TypeConstraint::Parameterizable', 'ArrayRef', ); isa_ok( Types::Standard::ArrayRef()->of(Types::Standard::Int()), 'Moose::Meta::TypeConstraint', 'ArrayRef[Int]', ); isa_ok( Types::Standard::ArrayRef()->of(Types::Standard::Int()), 'Moose::Meta::TypeConstraint::Parameterized', 'ArrayRef[Int]', ); isa_ok( Types::Standard::ArrayRef() | Types::Standard::Int(), 'Moose::Meta::TypeConstraint', 'ArrayRef|Int', ); isa_ok( Types::Standard::ArrayRef() | Types::Standard::Int(), 'Moose::Meta::TypeConstraint::Union', 'ArrayRef|Int', ); isa_ok( $coercion, 'Moose::Meta::TypeCoercion', 'MyInt->coercion', ); $coercion = do { my $arrayref = Types::Standard::ArrayRef()->plus_coercions( Types::Standard::ScalarRef(), sub { [$$_] }, ); my $int = Types::Standard::Int()->plus_coercions( Types::Standard::Num(), sub { int($_) }, ); my $array_or_int = $arrayref | $int; $array_or_int->coercion; }; isa_ok( $coercion, 'Moose::Meta::TypeCoercion', '(ArrayRef|Int)->coercion', ); isa_ok( $coercion, 'Moose::Meta::TypeCoercion::Union', '(ArrayRef|Int)->coercion', ); ok( Types::Standard::ArrayRef->moose_type->equals( Moose::Util::TypeConstraints::find_type_constraint("ArrayRef") ), "equivalence between Types::Standard types and core Moose types", ); require Type::Utils; my $classtype = Type::Utils::class_type(LocalClass => { class => "Local::Class" })->moose_type; isa_ok( $classtype, "Moose::Meta::TypeConstraint::Class", '$classtype', ); is( $classtype->class, "Local::Class", "Type::Tiny::Class provides meta information to Moose::Meta::TypeConstraint::Class", ); isa_ok( $classtype->Types::TypeTiny::to_TypeTiny, 'Type::Tiny::Class', '$classtype->Types::TypeTiny::to_TypeTiny', ); my $roletype = Type::Utils::role_type(LocalRole => { class => "Local::Role" })->moose_type; isa_ok( $roletype, "Moose::Meta::TypeConstraint", '$roletype', ); ok( !$roletype->isa("Moose::Meta::TypeConstraint::Role"), "NB! Type::Tiny::Role does not inflate to Moose::Meta::TypeConstraint::Role because of differing notions as to what constitutes a role.", ); isa_ok( $roletype->Types::TypeTiny::to_TypeTiny, 'Type::Tiny::Role', '$roletype->Types::TypeTiny::to_TypeTiny', ); my $ducktype = Type::Utils::duck_type(Darkwing => [qw/ foo bar baz /])->moose_type; isa_ok( $ducktype, "Moose::Meta::TypeConstraint::DuckType", '$ducktype', ); is_deeply( [sort @{$ducktype->methods}], [sort qw/ foo bar baz /], "Type::Tiny::Duck provides meta information to Moose::Meta::TypeConstraint::DuckType", ); isa_ok( $ducktype->Types::TypeTiny::to_TypeTiny, 'Type::Tiny::Duck', '$ducktype->Types::TypeTiny::to_TypeTiny', ); my $enumtype = Type::Utils::enum(MyEnum => [qw/ foo bar baz /])->moose_type; isa_ok( $enumtype, "Moose::Meta::TypeConstraint::Enum", '$classtype', ); is_deeply( [sort @{$enumtype->values}], [sort qw/ foo bar baz /], "Type::Tiny::Enum provides meta information to Moose::Meta::TypeConstraint::Enum", ); isa_ok( $enumtype->Types::TypeTiny::to_TypeTiny, 'Type::Tiny::Enum', '$enumtype->Types::TypeTiny::to_TypeTiny', ); my $union = Type::Utils::union(ICU => [$classtype->Types::TypeTiny::to_TypeTiny, $roletype->Types::TypeTiny::to_TypeTiny])->moose_type; isa_ok( $union, "Moose::Meta::TypeConstraint::Union", '$union', ); is_deeply( [sort @{$union->type_constraints}], [sort $classtype, $roletype], "Type::Tiny::Union provides meta information to Moose::Meta::TypeConstraint::Union", ); isa_ok( $union->Types::TypeTiny::to_TypeTiny, 'Type::Tiny::Union', '$union->Types::TypeTiny::to_TypeTiny', ); is( [sort @{$union->type_constraints}]->[0]->Types::TypeTiny::to_TypeTiny->{uniq}, $classtype->Types::TypeTiny::to_TypeTiny->{uniq}, '$union->type_constraints->[$i]->Types::TypeTiny::to_TypeTiny provides access to underlying Type::Tiny objects' ); my $intersect = Type::Utils::intersection(Chuck => [$classtype->Types::TypeTiny::to_TypeTiny, $roletype->Types::TypeTiny::to_TypeTiny])->moose_type; isa_ok( $intersect, "Moose::Meta::TypeConstraint", '$intersect', ); isa_ok( $intersect->Types::TypeTiny::to_TypeTiny, 'Type::Tiny::Intersection', '$intersect->Types::TypeTiny::to_TypeTiny', ); is( Scalar::Util::refaddr( $intersect->Types::TypeTiny::to_TypeTiny ), Scalar::Util::refaddr( $intersect->Types::TypeTiny::to_TypeTiny->moose_type->Types::TypeTiny::to_TypeTiny->moose_type->Types::TypeTiny::to_TypeTiny ), 'round-tripping between ->moose_type and ->Types::TypeTiny::to_TypeTiny preserves reference address' ); note "Method pass-through"; { local *Moose::Meta::TypeConstraint::dummy_1 = sub { 42; }; local *Moose::Meta::TypeCoercion::dummy_3 = sub { 666; }; is(Types::Standard::Int()->dummy_1, 42, 'method pass-through'); like( exception { Types::Standard::Int()->dummy_2 }, qr/^Can't locate object method "dummy_2"/, '... but not non-existant method', ); ok( Types::Standard::Int()->can('dummy_1') && !Types::Standard::Int()->can('dummy_2'), '... and `can` works ok', ); my $int = Types::Standard::Int()->plus_coercions(Types::Standard::Any(),q[999]); is($int->coercion->dummy_3, 666, 'method pass-through for coercions'); like( exception { $int->coercion->dummy_4 }, qr/^Can't locate object method "dummy_4"/, '... but not non-existant method', ); ok( $int->coercion->can('dummy_3') && !$int->coercion->can('dummy_4'), '... and `can` works ok', ); } done_testing; coercion.t000664001750001750 624112422772210 20460 0ustar00taitai000000000000Type-Tiny-1.000005/t/30-integration/Moose=pod =encoding utf-8 =head1 PURPOSE Check coercions work with L; both mutable and immutable classes. =head1 DEPENDENCIES Uses the bundled BiggerLib.pm type library. Test is skipped if Moose 2.1200 is not available. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Requires { Moose => '2.1200' }; use Test::Fatal; use Test::TypeTiny qw( matchfor ); my $e; { package Local::Class; use Moose; use BiggerLib -all; ::isa_ok(BigInteger, "Moose::Meta::TypeConstraint"); has small => (is => "rw", isa => SmallInteger, coerce => 1); has big => (is => "rw", isa => BigInteger, coerce => 1); $e = ::exception { has big_nc => (is => "rw", isa => BigInteger->no_coercions, coerce => 1); }; } like( $e, qr{^You cannot coerce an attribute .?big_nc.? unless its type .?\w+.? has a coercion}, "no_coercions and friends available on Moose type constraint objects", ); undef $e; my $o; my $suffix = "mutable class"; for my $i (0..1) { $e = exception { $o = "Local::Class"->new( small => 104, big => 9, ); }; is($e, undef, "no exception on coercion in constructor - $suffix"); is($o && $o->big, 19, "'big' attribute coerces in constructor - $suffix"); is($o && $o->small, 4, "'small' attribute coerces in constructor - $suffix"); $e = exception { $o = "Local::Class"->new( small => [], big => {}, ); }; is( $e, matchfor( $i # exception class thrown by constructor is dependent on immutability ? 'Moose::Exception::ValidationFailedForInlineTypeConstraint' : 'Moose::Exception::ValidationFailedForTypeConstraint', qr{^Attribute \(big\)} ), "'big' attribute throws when it cannot coerce in constructor - $suffix", ); $e = exception { $o = "Local::Class"->new( small => {}, big => [], ); }; is( $e, matchfor( $i # exception class thrown by constructor is dependent on immutability ? 'Moose::Exception::ValidationFailedForInlineTypeConstraint' : 'Moose::Exception::ValidationFailedForTypeConstraint', qr{^Attribute \(small\)} ), "'small' attribute throws when it cannot coerce in constructor - $suffix", ); $o = "Local::Class"->new; $e = exception { $o->big([]); $o->small([]); }; is($o && $o->big, 100, "'big' attribute coerces in accessor - $suffix"); is($o && $o->small, 1, "'small' attribute coerces in accessor - $suffix"); $e = exception { $o->big({}) }; is( $e, matchfor( 'Moose::Exception::ValidationFailedForInlineTypeConstraint', qr{^Attribute \(big\)} ), "'big' attribute throws when it cannot coerce in accessor - $suffix", ); $e = exception { $o->small({}) }; is( $e, matchfor( 'Moose::Exception::ValidationFailedForInlineTypeConstraint', qr{^Attribute \(small\)} ), "'small' attribute throws when it cannot coerce in accessor - $suffix", ); "Local::Class"->meta->make_immutable; $suffix = "im$suffix"; } done_testing; inflate-then-inline.t000664001750001750 211212422772210 22502 0ustar00taitai000000000000Type-Tiny-1.000005/t/30-integration/Moose=pod =encoding utf-8 =head1 PURPOSE Check type constraint inlining works with L in strange edge cases where we need to inflate Type::Tiny constraints into full L objects. =head1 DEPENDENCIES Test is skipped if Moose 2.0600 is not available. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More 0.96; use Test::Requires { 'Moose' => '2.0600' }; use Type::Tiny; my $type1 = Type::Tiny->new; my $type2 = $type1->create_child_type( constraint => sub { !!2 }, inlined => sub { my ($self, $var) = @_; $self->parent->inline_check($var) . " && !!2"; }, ); like( $type2->inline_check('$XXX'), qr/\(\(?!!1\)? && !!2\)/, '$type2->inline_check' ); like( $type2->moose_type->_inline_check('$XXX'), qr/\(\(?!!1\)? && !!2\)/, '$type2->moose_type->_inline_check' ); done_testing; native-attribute-traits.t000664001750001750 1537412422772210 23501 0ustar00taitai000000000000Type-Tiny-1.000005/t/30-integration/Moose=pod =encoding utf-8 =head1 PURPOSE Check type constraints and coercions work with L native attibute traits. =head1 DEPENDENCIES Test is skipped if Moose 2.0600 is not available. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use Test::More; use Test::Requires { Moose => '2.0600' }; use Test::Fatal; use Test::TypeTiny qw( matchfor ); use Test::Moose qw( with_immutable ); use Types::Standard -types; # For testing Array trait { package MyCollection; use Moose; use Types::Standard qw( ArrayRef Object ); has things => ( is => 'ro', isa => ArrayRef[ Object ], traits => [ 'Array' ], handles => { add => 'push' }, ); } # for testing Hash trait my %attributes = ( hashref => HashRef, hashref_int => HashRef[Int], map => Map, map_strint => Map[Str, Int], ); { package MyHashes; use Moose; while (my ($attr, $type) = each %attributes) { has $attr => ( traits => ['Hash'], is => 'ro', isa => $type, handles => { "$attr\_get" => 'get', "$attr\_set" => 'set', "$attr\_has" => 'exists', }, default => sub { +{} }, ); } } # For testing coercions { package Mini::Milk; use Moose; use Types::Standard qw( Int InstanceOf ); has i => (is => 'ro', isa => Int); around BUILDARGS => sub { my $next = shift; my $class = shift; return { i => $_[0] } if @_==1 and not ref $_[0]; $class->$next(@_); } } my $minimilk = InstanceOf->of('Mini::Milk')->plus_constructors(Num, "new"); { package MyCollection2; use Moose; use Types::Standard qw( ArrayRef ); has things => ( is => 'ro', isa => ArrayRef[ $minimilk ], traits => [ 'Array' ], handles => { add => 'push' }, coerce => 1, ); } { package MyCollection3; use Moose; use Types::Standard qw( ArrayRef ); has things => ( is => 'ro', isa => (ArrayRef[ $minimilk ])->create_child_type(coercion => 1), traits => [ 'Array' ], handles => { add => 'push' }, coerce => 1, ); } { package MyHashes2; use Moose; use Types::Standard qw( HashRef Map Int ); has hash => ( traits => ['Hash'], is => 'ro', isa => HashRef[ $minimilk ], coerce => 1, handles => { "hash_get" => 'get', "hash_set" => 'set', }, default => sub { +{} }, ); has 'map' => ( traits => ['Hash'], is => 'ro', isa => Map[ Int, $minimilk ], coerce => 1, handles => { "map_get" => 'get', "map_set" => 'set', }, default => sub { +{} }, ); } { package MyHashes3; use Moose; use Types::Standard qw( HashRef Map Int ); has hash => ( traits => ['Hash'], is => 'ro', isa => (HashRef[ $minimilk ])->create_child_type(coercion => 1), coerce => 1, handles => { "hash_get" => 'get', "hash_set" => 'set', }, default => sub { +{} }, ); has 'map' => ( traits => ['Hash'], is => 'ro', isa => (Map[ Int, $minimilk ])->create_child_type(coercion => 1), coerce => 1, handles => { "map_get" => 'get', "map_set" => 'set', }, default => sub { +{} }, ); } WEIRD_ERROR: { my $c = MyCollection3 ->meta ->get_attribute('things') ->type_constraint ->coercion ->compiled_coercion; my $input = [ Mini::Milk->new(0), 1, 2, 3 ]; my $output = $c->($input); my $expected = [ map Mini::Milk->new($_), 0..3 ]; is_deeply($output, $expected) or diag( B::Deparse->new->coderef2text($c) ); } my $i = 0; with_immutable { note($i++ ? "MUTABLE" : "IMMUTABLE"); subtest "Array trait with type ArrayRef[Object]" => sub { my $coll = MyCollection->new(things => []); ok( !exception { $coll->add(bless {}, "Monkey") }, 'pushing ok value', ); is( exception { $coll->add({})}, matchfor( 'Moose::Exception::ValidationFailedForInlineTypeConstraint', qr{^A new member value for things does not pass its type constraint because:}, ), 'pushing not ok value', ); }; my %subtests = ( MyCollection2 => "Array trait with type ArrayRef[InstanceOf] and coercion", MyCollection3 => "Array trait with type ArrayRef[InstanceOf] and coercion and subtyping", ); for my $class (sort keys %subtests) { subtest $subtests{$class} => sub { my $coll = $class->new(things => []); is( exception { $coll->add( 'Mini::Milk'->new(i => 0) ); $coll->add(1); $coll->add(2); $coll->add(3); }, undef, 'pushing ok values', ); my $things = $coll->things; for my $i (0 .. 3) { isa_ok($things->[$i], 'Mini::Milk', "\$things->[$i]"); is($things->[$i]->i, $i, "\$things->[$i]->i == $i"); } }; } for my $attr (sort keys %attributes) { my $type = $attributes{$attr}; my $getter = "$attr\_get"; my $setter = "$attr\_set"; my $predicate = "$attr\_has"; subtest "Hash trait with type $type" => sub { my $obj = MyHashes->new; is_deeply($obj->$attr, {}, 'default empty hash'); $obj->$setter(foo => 666); $obj->$setter(bar => 999); is($obj->$getter('foo'), 666, 'getter'); is($obj->$getter('bar'), 999, 'getter'); $obj->$setter(bar => 42); is($obj->$getter('bar'), 42, 'setter'); ok($obj->$predicate('foo'), 'predicate'); ok($obj->$predicate('bar'), 'predicate'); ok(!$obj->$predicate('baz'), 'predicate - negatory'); is_deeply($obj->$attr, { foo => 666, bar => 42 }, 'correct hash'); like( exception { $obj->$setter(baz => 3.141592) }, qr/type constraint/, 'cannot add non-Int value', ) if $attr =~ /int$/; done_testing; }; } %subtests = ( MyHashes2 => "Hash trait with types HashRef[InstanceOf] and Map[Int,InstanceOf]; and coercion", MyHashes3 => "Hash trait with types HashRef[InstanceOf] and Map[Int,InstanceOf]; and coercion and subtyping", ); for my $class (sort keys %subtests) { subtest $subtests{$class} => sub { my $H = $class->new(); is( exception { $H->hash_set( 0, 'Mini::Milk'->new(i => 0) ); $H->hash_set( 1, 1 ); $H->hash_set( 2, 2 ); $H->hash_set( 3, 3 ); }, undef, 'adding ok values to HashRef', ); is( exception { $H->map_set( 4, 'Mini::Milk'->new(i => 4) ); $H->map_set( 5, 5 ); $H->map_set( 6, 6 ); $H->map_set( 7, 7 ); }, undef, 'adding ok values to Map', ); my $h = $H->hash; for my $i (0 .. 3) { isa_ok($h->{$i}, 'Mini::Milk', "\$h->{$i}"); is($h->{$i}->i, $i, "\$h->{$i}->i == .$i"); } my $m = $H->map; for my $i (4 .. 7) { isa_ok($m->{$i}, 'Mini::Milk', "\$m->{$i}"); is($m->{$i}->i, $i, "\$m->{$i}->i == .$i"); } }; } } qw( MyCollection MyCollection2 MyCollection3 MyHashes Mini::Milk ); done_testing; coercion.t000664001750001750 320512422772210 22045 0ustar00taitai000000000000Type-Tiny-1.000005/t/30-integration/MooseX-Getopt=pod =encoding utf-8 =head1 PURPOSE Check coercions work with L; both mutable and immutable classes. =head1 DEPENDENCIES Test is skipped if Moose 2.0000, MooseX::Getopt 0.63, and Types::Path::Tiny are not available. =head1 AUTHOR Alexander Hartmaier Eabraxxa@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Alexander Hartmaier. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Requires { 'Moose' => '2.0000' }; use Test::Requires { 'MooseX::Getopt' => '0.63' }; use Test::Requires { 'Types::Path::Tiny' => '0' }; use Test::Fatal; use Test::TypeTiny qw( matchfor ); my @warnings; BEGIN { package Local::Types; use Type::Library -base, -declare => qw( Files ); use Type::Utils -all; use Types::Standard -types; use Types::Path::Tiny qw( Path to_Path ); declare Files, as ArrayRef[ Path ], coercion => 1; coerce Files, from Str, via { [ to_Path($_) ] }; $INC{'Local/Types.pm'} = __FILE__; }; # note explain( Local::Types::Files->moose_type ); { package Local::Class; use Moose; use Local::Types -all; with 'MooseX::Getopt'; has files => (is => "rw", isa => Files, coerce => 1); } my ($e, $o); my $suffix = "mutable class"; for my $i (0..1) { $e = exception { $o = "Local::Class"->new_with_options( files => 'foo.bar', ); }; is($e, undef, "no exception on coercion in constructor - $suffix"); "Local::Class"->meta->make_immutable; $suffix = "im$suffix"; } done_testing; basic.t000664001750001750 334112422772210 21170 0ustar00taitai000000000000Type-Tiny-1.000005/t/30-integration/MooseX-Types=pod =encoding utf-8 =head1 PURPOSE Complex checks between Type::Tiny and L. =head1 DEPENDENCIES MooseX::Types 0.35; skipped otherwise. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; use Test::Requires { "MooseX::Types::Moose" => "0.35" }; use Test::TypeTiny; use MooseX::Types::Moose -all; use Types::Standard -all => { -prefix => "My" }; my $union1 = Int | MyArrayRef; my $union2 = MyArrayRef | Int; isa_ok($union1, "Moose::Meta::TypeConstraint"); isa_ok($union2, "Moose::Meta::TypeConstraint"); isa_ok($union2, "Type::Tiny"); should_pass([], $union1); should_pass(2, $union1); should_fail({}, $union1); should_pass([], $union2); should_pass(2, $union2); should_fail({}, $union2); my $param1 = MyArrayRef[Int]; my $param2 = ArrayRef[MyInt]; should_pass([1,2,3], $param1); should_pass([], $param1); should_fail({}, $param1); should_fail(["x"], $param1); should_pass([1,2,3], $param2); should_pass([], $param2); should_fail({}, $param2); should_fail(["x"], $param2); my $param_union = MyArrayRef[Int | ArrayRef]; should_pass([], $param_union); should_pass([1,2,3], $param_union); should_pass([[],[]], $param_union); should_pass([11,[]], $param_union); should_pass([[],11], $param_union); should_fail([1.111], $param_union); use Types::TypeTiny 'to_TypeTiny'; my $moosey = ArrayRef[HashRef[Int]]; my $tt1 = to_TypeTiny($moosey); my $tt2 = to_TypeTiny($moosey); is($tt1->{uniq}, $tt2->{uniq}, "to_TypeTiny caches results"); done_testing; extending.t000664001750001750 246312422772210 22100 0ustar00taitai000000000000Type-Tiny-1.000005/t/30-integration/MooseX-Types=pod =encoding utf-8 =head1 PURPOSE Check that L can extend an existing L type constraint library. =head1 DEPENDENCIES MooseX::Types 0.35; skipped otherwise. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; use Test::Requires { "MooseX::Types::Moose" => "0.35" }; use Test::TypeTiny; use Test::Fatal; BEGIN { package MyTypes; use Type::Library -base, -declare => qw(NonEmptyStr); use Type::Utils -all; BEGIN { extends 'MooseX::Types::Moose', 'Types::TypeTiny' }; declare NonEmptyStr, as Str, where { length($_) }; $INC{'MyTypes.pm'} = __FILE__; }; use MyTypes -types; should_pass("foo", Str); should_pass("", Str); should_pass("foo", NonEmptyStr); should_fail("", NonEmptyStr); should_pass({}, HashLike); should_fail([], HashLike); { package MyDummy; use Moose; $INC{'MyDummy.pm'} = __FILE__; package MoreTypes; use Type::Library -base; ::like( ::exception { Type::Utils::extends 'MyDummy' }, qr/not a type constraint library/, 'cannot extend non-type-library', ); } done_testing; more.t000664001750001750 327212422772210 21054 0ustar00taitai000000000000Type-Tiny-1.000005/t/30-integration/MooseX-Types=pod =encoding utf-8 =head1 PURPOSE More checks between Type::Tiny and L. This started out as an example of making a parameterized C<< Not[] >> type constraint, but worked out as a nice test case. =head1 DEPENDENCIES MooseX::Types 0.35; skipped otherwise. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; use Test::Requires { "MooseX::Types::Moose" => "0.35" }; use Test::TypeTiny; BEGIN { package MooseX::Types::Not; use Type::Library -base; use Types::TypeTiny; __PACKAGE__->add_type({ name => "Not", constraint => sub { !!0 }, inlined => sub { "!!0" }, constraint_generator => sub { Types::TypeTiny::to_TypeTiny(shift)->complementary_type }, }); $INC{"MooseX/Types/Not.pm"} = __FILE__; }; use MooseX::Types::Not qw(Not); use MooseX::Types::Moose qw(Int); isa_ok($_, "Moose::Meta::TypeConstraint", "$_") for Not, Int, Not[Int], Not[Not[Int]]; should_fail(1.1, Int); should_fail(undef, Int); should_fail([], Int); should_pass(2, Int); should_pass(1.1, Not[Int]); should_pass(undef, Not[Int]); should_pass([], Not[Int]); should_fail(2, Not[Int]); should_fail(1.1, Not[Not[Int]]); should_fail(undef, Not[Not[Int]]); should_fail([], Not[Not[Int]]); should_pass(2, Not[Not[Int]]); # 'Not' alone behaves as 'Not[Any]' should_fail(1.1, Not); should_fail(undef, Not); should_fail([], Not); should_fail(2, Not); done_testing; basic.t000664001750001750 371212422772210 17746 0ustar00taitai000000000000Type-Tiny-1.000005/t/30-integration/Mouse=pod =encoding utf-8 =head1 PURPOSE Check type constraints work with L. Checks values that should pass and should fail; checks error messages. =head1 DEPENDENCIES Uses the bundled BiggerLib.pm type library. Test is skipped if Mouse 1.00 is not available. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Requires { Mouse => 1.00 }; use Test::Fatal; { package Local::Class; use Mouse; use BiggerLib -all; has small => (is => "ro", isa => SmallInteger); has big => (is => "ro", isa => BigInteger); } is( exception { "Local::Class"->new(small => 9, big => 12) }, undef, "some values that should pass their type constraint", ); isnt( exception { "Local::Class"->new(small => 100) }, undef, "direct violation of type constraint", ); isnt( exception { "Local::Class"->new(small => 5.5) }, undef, "violation of parent type constraint", ); isnt( exception { "Local::Class"->new(small => "five point five") }, undef, "violation of grandparent type constraint", ); isnt( exception { "Local::Class"->new(small => []) }, undef, "violation of great-grandparent type constraint", ); use Mouse::Util; ok( Mouse::Util::is_a_type_constraint(BiggerLib::SmallInteger), "Mouse::Util::is_a_type_constraint accepts Type::Tiny type constraints", ); note "Coercion..."; { package TmpNS1; use Mouse::Util::TypeConstraints; subtype 'MyInt', as 'Int'; coerce 'MyInt', from 'ArrayRef', via { scalar(@$_) }; my $type = Types::TypeTiny::to_TypeTiny(find_type_constraint('MyInt')); ::ok($type->has_coercion, 'types converted from Mouse retain coercions'); ::is($type->coerce([qw/a b c/]), 3, '... which work'); } done_testing; coercion.t000664001750001750 421712422772210 20467 0ustar00taitai000000000000Type-Tiny-1.000005/t/30-integration/Mouse=pod =encoding utf-8 =head1 PURPOSE Check coercions work with L; both mutable and immutable classes. =head1 DEPENDENCIES Uses the bundled BiggerLib.pm type library. Test is skipped if Mouse 1.00 is not available. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Requires { Mouse => 1.00 }; use Test::Fatal; { package Local::Class; use Mouse; use BiggerLib -all; ::isa_ok(BigInteger, "Mouse::Meta::TypeConstraint"); has small => (is => "rw", isa => SmallInteger, coerce => 1); has big => (is => "rw", isa => BigInteger, coerce => 1); } my ($e, $o); my $suffix = "mutable class"; for (0..1) { $e = exception { $o = "Local::Class"->new( small => 104, big => 9, ); }; is($e, undef, "no exception on coercion in constructor - $suffix"); is($o && $o->big, 19, "'big' attribute coerces in constructor - $suffix"); is($o && $o->small, 4, "'small' attribute coerces in constructor - $suffix"); $e = exception { $o = "Local::Class"->new( small => [], big => {}, ); }; isnt($e, undef, "'big' attribute throws when it cannot coerce in constructor - $suffix"); $e = exception { $o = "Local::Class"->new( small => {}, big => [], ); }; isnt($e, undef, "'small' attribute throws when it cannot coerce in constructor - $suffix"); $o = "Local::Class"->new; $e = exception { $o->big([]); $o->small([]); }; is($o && $o->big, 100, "'big' attribute coerces in accessor - $suffix"); is($o && $o->small, 1, "'small' attribute coerces in accessor - $suffix"); $e = exception { $o->big({}) }; isnt($e, undef, "'big' attribute throws when it cannot coerce in accessor - $suffix"); $e = exception { $o->small({}) }; isnt($e, undef, "'small' attribute throws when it cannot coerce in accessor - $suffix"); "Local::Class"->meta->make_immutable; $suffix = "im$suffix"; } done_testing; basic.t000664001750001750 305712422772210 21202 0ustar00taitai000000000000Type-Tiny-1.000005/t/30-integration/MouseX-Types=pod =encoding utf-8 =head1 PURPOSE Complex checks between Type::Tiny and L. =head1 DEPENDENCIES MouseX::Types 0.06; skipped otherwise. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; use Test::Requires { "MouseX::Types" => "0.06" }; use Test::TypeTiny; use MouseX::Types::Moose qw(Int ArrayRef); use Types::Standard -all => { -prefix => "My" }; my $union1 = Int | MyArrayRef; my $union2 = MyArrayRef | Int; isa_ok($union1, "Mouse::Meta::TypeConstraint"); isa_ok($union1, "Mouse::Meta::TypeConstraint"); isa_ok($union2, "Type::Tiny"); should_pass([], $union1); should_pass(2, $union1); should_fail({}, $union1); should_pass([], $union2); should_pass(2, $union2); should_fail({}, $union2); note explain($union2); my $param1 = MyArrayRef[Int]; my $param2 = ArrayRef[MyInt]; should_pass([1,2,3], $param1); should_pass([], $param1); should_fail({}, $param1); should_fail(["x"], $param1); should_pass([1,2,3], $param2); should_pass([], $param2); should_fail({}, $param2); should_fail(["x"], $param2); my $param_union = MyArrayRef[Int | ArrayRef]; should_pass([], $param_union); should_pass([1,2,3], $param_union); should_pass([[],[]], $param_union); should_pass([11,[]], $param_union); should_pass([[],11], $param_union); should_fail([1.111], $param_union); done_testing; extending.t000664001750001750 245412422772210 22106 0ustar00taitai000000000000Type-Tiny-1.000005/t/30-integration/MouseX-Types=pod =encoding utf-8 =head1 PURPOSE Check that L can extend an existing L type constraint library. =head1 DEPENDENCIES MouseX::Types 0.06; skipped otherwise. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; use Test::Requires { "MouseX::Types" => "0.06" }; use Test::TypeTiny; use Test::Fatal; BEGIN { package MyTypes; use Type::Library -base, -declare => qw(NonEmptyStr); use Type::Utils -all; BEGIN { extends 'MouseX::Types::Moose', 'Types::TypeTiny' }; declare NonEmptyStr, as Str, where { length($_) }; $INC{'MyTypes.pm'} = __FILE__; }; use MyTypes -types; should_pass("foo", Str); should_pass("", Str); should_pass("foo", NonEmptyStr); should_fail("", NonEmptyStr); should_pass({}, HashLike); should_fail([], HashLike); { package MyDummy; use Mouse; $INC{'MyDummy.pm'} = __FILE__; package MoreTypes; use Type::Library -base; ::like( ::exception { Type::Utils::extends 'MyDummy' }, qr/not a type constraint library/, 'cannot extend non-type-library', ); } done_testing; basic.t000664001750001750 244212422772210 21623 0ustar00taitai000000000000Type-Tiny-1.000005/t/30-integration/Object-Accessor=pod =encoding utf-8 =head1 PURPOSE Check type constraints work with L. =head1 DEPENDENCIES Test is skipped if Object::Accessor 0.30 is not available. =head1 CAVEATS As of Perl 5.17.x, the Object::Accessor module is being de-cored, so will issue deprecation warnings. These can safely be ignored for the purposes of this test case. Object::Accessor from CPAN does not have these warnings. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); # Avoid warnings about core version of Object::Accessor in Perl 5.18 no warnings qw(deprecated); use Test::More; use Test::Requires { "Object::Accessor" => 0.30 }; use Test::Fatal; use Types::Standard "Int"; use Object::Accessor; my $obj = Object::Accessor->new; $obj->mk_accessors( { foo => Int->compiled_check }, ); $obj->foo(12); is($obj->foo, 12, 'write then read on accessor works'); my $e = exception { local $Object::Accessor::FATAL = 1; $obj->foo("Hello"); }; isnt($e, undef, 'exception thrown for bad value'); done_testing; basic.t000664001750001750 413112422772210 21050 0ustar00taitai000000000000Type-Tiny-1.000005/t/30-integration/Return-Type=pod =encoding utf-8 =head1 PURPOSE Test that this sort of thing works: sub foo :ReturnType(Int) { ...; } =head1 DEPENDENCIES Requires L 0.004; skipped otherwise. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; BEGIN { plan skip_all => "Test case fails with App::ForkProve" if exists $INC{"App/ForkProve.pm"}; }; use Test::Requires { 'Return::Type' => '0.004' }; use Types::Standard qw( HashRef Int ); use Test::Fatal; if (0) { require JSON; diag("\%ENV ".JSON->new->pretty(1)->canonical(1)->encode({%ENV})); diag("\%INC ".JSON->new->pretty(1)->canonical(1)->encode({%INC})); } sub foo :ReturnType(Int) { wantarray ? @_ : $_[0]; } subtest "simple return type constraint" => sub { subtest "scalar context" => sub { is( scalar(foo(42)), 42, ); isnt( exception { scalar(foo(4.2)) }, undef, ); done_testing; }; subtest "list context" => sub { is_deeply( [ foo(4, 2) ], [ 4, 2 ], ); isnt( exception { [ foo(4, 2, 4.2) ] }, undef, ); done_testing; }; done_testing; }; my $Even; BEGIN { $Even = Int->create_child_type( name => 'Even', constraint => sub { not($_[0] % 2) }, ); }; sub bar :ReturnType(scalar => $Even, list => HashRef[Int]) { wantarray ? @_ : scalar(@_); } subtest "more complex return type constraint" => sub { subtest "scalar context" => sub { is( scalar(bar(xxx => 1, yyy => 2)), 4, ); TODO: { local $TODO = 'this seems to fail: error in Return::Type??'; isnt( exception { scalar(bar(xxx => 1, 2)) }, undef, ); } done_testing; }; subtest "list context" => sub { is_deeply( { bar(xxx => 1, yyy => 2) }, { xxx => 1, yyy => 2 }, ); isnt( exception { [ bar(xxx => 1, 2) ] }, undef, ); done_testing; }; done_testing; }; done_testing; basic.t000664001750001750 574012422772210 20505 0ustar00taitai000000000000Type-Tiny-1.000005/t/30-integration/Sub-Quote=pod =encoding utf-8 =head1 PURPOSE Check type constraints can be made inlinable using L. =head1 DEPENDENCIES Test is skipped if Sub::Quote is not available. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Requires "Sub::Quote"; use Test::TypeTiny; use Sub::Quote; use Type::Tiny; use Types::Standard qw( ArrayRef Int ); my $Type1 = "Type::Tiny"->new( name => "Type1", constraint => quote_sub q{ $_[0] eq q(42) }, ); should_fail(41, $Type1); should_pass(42, $Type1); ok($Type1->can_be_inlined, 'constraint built using quote_sub and $_[0] can be inlined') and note $Type1->inline_check('$value'); my $Type2 = "Type::Tiny"->new( name => "Type2", constraint => quote_sub q{ $_ eq q(42) }, ); should_fail(41, $Type2); should_pass(42, $Type2); ok($Type2->can_be_inlined, 'constraint built using quote_sub and $_[0] can be inlined') and note $Type2->inline_check('$value'); my $Type3 = "Type::Tiny"->new( name => "Type3", constraint => quote_sub q{ my ($n) = @_; $n eq q(42) }, ); should_fail(41, $Type3); should_pass(42, $Type3); ok($Type3->can_be_inlined, 'constraint built using quote_sub and @_ can be inlined') and note $Type3->inline_check('$value'); my $Type4 = "Type::Tiny"->new( name => "Type4", parent => Int, constraint => quote_sub q{ $_[0] >= 42 }, ); should_fail(41, $Type4); should_pass(42, $Type4); should_pass(43, $Type4); should_fail(44.4, $Type4); ok($Type4->can_be_inlined, 'constraint built using quote_sub and parent type can be inlined') and note $Type4->inline_check('$value'); my $Type5 = "Type::Tiny"->new( name => "Type5", parent => Int, constraint => quote_sub q{ $_[0] >= $x }, { '$x' => \42 }, ); should_fail(41, $Type5); should_pass(42, $Type5); should_pass(43, $Type5); should_fail(44.4, $Type5); TODO: { local $TODO = "captures not supported yet"; ok($Type5->can_be_inlined, 'constraint built using quote_sub and captures can be inlined'); }; my $Type6 = "Type::Tiny"->new( name => "Type6", parent => Int->create_child_type(constraint => sub { 999 }), constraint => quote_sub q{ $_[0] >= 42 }, ); should_fail(41, $Type6); should_pass(42, $Type6); should_pass(43, $Type6); should_fail(44.4, $Type6); ok(!$Type6->can_be_inlined, 'constraint built using quote_sub and non-inlinable parent cannot be inlined'); my $Type7 = ArrayRef([Int]) & quote_sub q{ @$_ > 1 and @$_ < 4 }; should_pass([1,2,3], $Type7); should_fail([1,2.1,3], $Type7); should_fail([1], $Type7); should_fail([1,2,3,4], $Type7); ok($Type7->can_be_inlined, 'constraint built as an intersection of an inlinable type constraint and a quoted sub can be inlined'); note($Type7->inline_check('$VAR')); done_testing; unquote-coercions.t000664001750001750 303112422772210 23075 0ustar00taitai000000000000Type-Tiny-1.000005/t/30-integration/Sub-Quote=pod =encoding utf-8 =head1 PURPOSE Check type coercions can be unquoted L. =head1 DEPENDENCIES Test is skipped if Sub::Quote is not available. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Requires "Sub::Quote"; use Test::TypeTiny; use Sub::Quote; use Type::Tiny; use Types::Standard qw( ArrayRef Int ); use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Requires "Sub::Quote"; use Test::Fatal; use Sub::Quote; use Type::Tiny; use Types::Standard qw( Int Num ArrayRef ); my $type = Int->plus_coercions( Num, q[ int($_) ], ArrayRef, q[ scalar(@$_) ], ); my $coercion = $type->coercion; my ($name, $code, $captures, $compiled_sub) = @{ Sub::Quote::quoted_from_sub( \&$coercion ); }; ok(defined($code), 'Got back code from Sub::Quote'); my $coderef = eval "sub { $code }"; is(ref($coderef), 'CODE', '... which compiles OK'); is( $coderef->(42), 42, "... which passes through values that don't need to be coerced", ); ok( $coderef->(3.1)==3 && $coderef->([qw/foo bar/])==2, "... coerces values that can be coerced", ); is_deeply( $coderef->({foo => 666}), {foo => 666}, "... and passes through any values it can't handle", ); done_testing; unquote-constraints.t000664001750001750 211412422772210 23461 0ustar00taitai000000000000Type-Tiny-1.000005/t/30-integration/Sub-Quote=pod =encoding utf-8 =head1 PURPOSE Check type constraints can be unquoted L. =head1 DEPENDENCIES Test is skipped if Sub::Quote is not available. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Requires "Sub::Quote"; use Test::Fatal; use Sub::Quote; use Type::Tiny; use Types::Standard qw( Int ); my $type = Int; my ($name, $code, $captures, $compiled_sub) = @{ Sub::Quote::quoted_from_sub( \&$type ); }; ok(defined($code), 'Got back code from Sub::Quote'); my $coderef = eval "sub { $code }"; is(ref($coderef), 'CODE', '... which compiles OK'); ok($coderef->(42), '... and seems to work'); like( exception { $coderef->([]) }, qr/\AReference \[\] did not pass type constraint "Int"/, '... and throws exceptions properly', ); done_testing; basic.t000664001750001750 146012422772210 21002 0ustar00taitai000000000000Type-Tiny-1.000005/t/30-integration/Switcheroo=pod =encoding utf-8 =head1 PURPOSE Checks Type::Tiny works with L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Requires 'Switcheroo'; use Test::Fatal; use Types::Standard -all; use Switcheroo; sub what_is { my $var = shift; switch ($var) { case ArrayRef: 'ARRAY'; case HashRef: 'HASH'; default: undef; } } is( what_is([]), 'ARRAY', ); is( what_is({}), 'HASH', ); is( what_is(42), undef, ); is( what_is(\(42)), undef, ); done_testing; basic.t000664001750001750 242312422772210 20314 0ustar00taitai000000000000Type-Tiny-1.000005/t/30-integration/Type-Tie=pod =encoding utf-8 =head1 PURPOSE Test that this sort of thing works: tie my $var, Int; =head1 DEPENDENCIES Requires L; skipped otherwise. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use Test::More; use Test::Requires 'Type::Tie'; use Types::Standard qw( ArrayRef Int ); use Test::Fatal; subtest "tied scalar" => sub { tie my($int), Int; is( exception { $int = 42 }, undef, ); isnt( exception { $int = 4.2 }, undef, ); is($int, 42); done_testing; }; subtest "tied array" => sub { tie my(@ints), Int; is( exception { $ints[0] = 1; push @ints, 2; unshift @ints, 0; }, undef, ); isnt( exception { $ints[3] = 3.5 }, undef, ); is_deeply( \@ints, [ 0..2 ], ); done_testing; }; subtest "tied hash" => sub { tie my(%ints), Int; is( exception { $ints{one} = 1; $ints{two} = 2; }, undef, ); isnt( exception { $ints{three} = 3.5 }, undef, ); is_deeply( \%ints, { one => 1, two => 2 }, ); done_testing; }; done_testing; archaic.t000664001750001750 450312422772210 23552 0ustar00taitai000000000000Type-Tiny-1.000005/t/30-integration/Validation-Class-Simple=pod =encoding utf-8 =head1 PURPOSE Fake L 7.900017 by overriding C<< $VERSION >> variable. (There is a reason for this... C follows two different code paths depending on the version of the Validation::Class::Simple object passed to it.) =head1 DEPENDENCIES Test is skipped if Validation::Class 7.900017 is not available. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Requires { "Validation::Class" => "7.900017" }; use Test::TypeTiny; use Types::TypeTiny qw( to_TypeTiny ); use Validation::Class::Simple; BEGIN { $Validation::Class::Simple::VERSION = '7.900017' }; my $type = to_TypeTiny "Validation::Class::Simple"->new( fields => { name => { required => 1, pattern => qr{^\w+(\s\w+)*$}, filters => [qw/trim/] }, email => { required => 1 }, pass => { required => 1 }, pass2 => { required => 1, matches => 'pass' }, }, ); isa_ok($type, "Type::Tiny", 'can create a child type constraint from Validation::Class::Simple'); should_fail('Hello', $type); should_fail({}, $type); should_fail({ name => 'Toby', email => 'tobyink@cpan.org', pass => 'foo', pass2 => 'bar' }, $type); should_pass({ name => 'Toby', email => 'tobyink@cpan.org', pass => 'foo', pass2 => 'foo' }, $type); should_fail({ name => 'Toby ', email => 'tobyink@cpan.org', pass => 'foo', pass2 => 'foo' }, $type); my $msg = $type->get_message({ name => 'Toby', email => 'tobyink@cpan.org', pass => 'foo', pass2 => 'bar' }); like($msg, qr{pass2 does not match pass}, 'correct error message (A)'); my $msg2 = $type->get_message({ name => 'Toby ', email => 'tobyink@cpan.org', pass => 'foo', pass2 => 'foo' }); like($msg2, qr{name is not formatted properly}, 'correct error message (B)'); ok($type->has_coercion, 'the type has a coercion'); is_deeply( $type->coerce( { name => 'Toby ', email => 'tobyink@cpan.org', pass => 'foo', pass2 => 'foo', monkey => 'nuts' }, ), { name => 'Toby', email => 'tobyink@cpan.org', pass => 'foo', pass2 => 'foo' }, "... which works", ); done_testing; basic.t000664001750001750 414012422772210 23236 0ustar00taitai000000000000Type-Tiny-1.000005/t/30-integration/Validation-Class-Simple=pod =encoding utf-8 =head1 PURPOSE Check type constraints L objects can be used as type constraints. =head1 DEPENDENCIES Test is skipped if Validation::Class 7.900017 is not available. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Requires { "Validation::Class" => "7.900017" }; use Test::TypeTiny; use Types::TypeTiny qw( to_TypeTiny ); use Validation::Class::Simple; my $type = to_TypeTiny "Validation::Class::Simple"->new( fields => { name => { required => 1, pattern => qr{^\w+(\s\w+)*$}, filters => [qw/trim/] }, email => { required => 1 }, pass => { required => 1 }, pass2 => { required => 1, matches => 'pass' }, }, ); isa_ok($type, "Type::Tiny", 'can create a child type constraint from Validation::Class::Simple'); should_fail('Hello', $type); should_fail({}, $type); should_fail({ name => 'Toby', email => 'tobyink@cpan.org', pass => 'foo', pass2 => 'bar' }, $type); should_pass({ name => 'Toby', email => 'tobyink@cpan.org', pass => 'foo', pass2 => 'foo' }, $type); should_fail({ name => 'Toby ', email => 'tobyink@cpan.org', pass => 'foo', pass2 => 'foo' }, $type); my $msg = $type->get_message({ name => 'Toby', email => 'tobyink@cpan.org', pass => 'foo', pass2 => 'bar' }); like($msg, qr{pass2 does not match pass}, 'correct error message (A)'); my $msg2 = $type->get_message({ name => 'Toby ', email => 'tobyink@cpan.org', pass => 'foo', pass2 => 'foo' }); like($msg2, qr{name is not formatted properly}, 'correct error message (B)'); ok($type->has_coercion, 'the type has a coercion'); is_deeply( $type->coerce( { name => 'Toby ', email => 'tobyink@cpan.org', pass => 'foo', pass2 => 'foo', monkey => 'nuts' }, ), { name => 'Toby', email => 'tobyink@cpan.org', pass => 'foo', pass2 => 'foo' }, "... which works", ); done_testing; basic.t000664001750001750 130212422772210 21232 0ustar00taitai000000000000Type-Tiny-1.000005/t/30-integration/match-simple=pod =encoding utf-8 =head1 PURPOSE Checks Type::Tiny works with L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut use strict; use warnings; use lib qw( ./lib ./t/lib ../inc ./inc ); use Test::More; use Test::Requires 'match::simple'; use Test::Fatal; use Types::Standard -all; use match::simple { replace => 1 }; ok( 42 |M| Int ); ok( 42 |M| Num ); ok not( 42 |M| ArrayRef ); ok( 42 |M| \&is_Int ); ok not( 42 |M| \&is_ArrayRef ); done_testing; Coercions.pod000664001750001750 2635112422772210 20705 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Type/Tiny/Manual=pod =encoding utf-8 =for stopwords zen =head1 NAME Type::Tiny::Manual::Coercions - adding coercions to type constraints =head1 DESCRIPTION B<< Stop! Don't do it! >> OK, it's fairly common practice in L/L code to define coercions for type constraints. For example, suppose we have a type constraint: class_type PathTiny, { class => "Path::Tiny" }; We may wish to define a coercion (i.e. a conversion routine) to handle strings, and convert them into Path::Tiny objects: coerce PathTiny, from Str, via { "Path::Tiny"->new($_) }; However, there are good reasons to avoid this practice. It ties the coercion routine to the type constraint. Any people wishing to use your C type constraint need to buy in to your idea of how they should be coerced from C. With L this is unlikely to be controversial, however consider: coerce ArrayRef, from Str, via { [split /\n/] }; In one part of the application (dealing with parsing log files for instance), this could be legitimate. But another part (dealing with logins perhaps) might prefer to split on colons. Another (dealing with web services) might attempt to parse the string as a JSON array. If all these coercions have attached themselves to the C type constraint, coercing a string becomes a complicated proposition! In a large application where coercions are defined across many different files, the application can start to suffer from "spooky action at a distance". In the interests of Moose-compatibility, L and L do allow you to define coercions this way, but they also provide an alternative that you should consider: C. =head2 plus_coercions L offers a method C which constructs a new anonymous type constraint, but with additional coercions. In our earlier example, we'd define the C type constraint as before: class_type PathTiny, { class => "Path::Tiny" }; But then not define any coercions for it. Later, when using the type constraint, we can add coercions: my $ConfigFileType = PathTiny->plus_coercions( Str, sub { "Path::Tiny"->new($_) }, Undef, sub { "Path::Tiny"->new("/etc/myapp/default.conf") }, ); has config_file => ( is => "ro", isa => $ConfigFileType, coerce => 1, ); Where the C constraint is used in another part of the code, it will not see these coercions, because they were added to the new anonymous type constraint, not to the C constraint itself! =head2 Named Coercions A type library may define a named set of coercions to a particular type. For example, let's define that coercion from C to C: declare_coercion "LinesFromStr", to_type ArrayRef, from Str, q{ [split /\n/] }; Now we can import that coercion using a name, and it makes our code look a little cleaner: use Types::Standard qw(ArrayRef); use MyApp::Types qw(LinesFromStr); has lines => ( is => "ro", isa => ArrayRef->plus_coercions(LinesFromStr), coerce => 1, ); =head2 Parameterized Coercions Parameterized type constraints are familiar from Moose. For example, an arrayref of integers: ArrayRef[Int] L supports parameterized named coercions too. For example, the following type constraint has a coercion from strings that splits them into lines: use Types::Standard qw( ArrayRef Split ); my $ArrayOfLines = ArrayRef->plus_coercions( Split[ qr{\n} ] ); Viewing the source code for L should give you hints as to how they are implemented. =head2 plus_fallback_coercions, minus_coercions and no_coercions Getting back to the C method, there are some other methods that perform coercion maths. C is the same as C but the added coercions have a lower priority than any existing coercions. C can be given a list of type constraints that we wish to ignore coercions for. Imagine our C constraint already has a coercion from C, then the following creates a new anonymous type constraint without that coercion: PathTiny->minus_coercions(Str) C gives us a new type anonymous constraint without any of its parents coercions. This is useful as a way to create a blank slate for a subsequent C: PathTiny->no_coercions->plus_coercions(...) =head2 plus_constructors The C method defined in L is sugar for C. The following two are the same: PathTiny->plus_coercions(Str, q{ Path::Tiny->new($_) }) PathTiny->plus_constructors(Str, "new"); =head2 "Deep" Coercions Certain parameterized type constraints can automatically acquire coercions if their parameters have coercions. For example: ArrayRef[ Int->plus_coercions(Num, q{int($_)}) ] ... does what you mean! The parameterized type constraints that do this magic include the following ones from L: =over =item * C =item * C =item * C =item * C =item * C =item * C =item * C =item * C =back Imagine we're declaring a type library: declare Paths, as ArrayRef[PathTiny]; The C type (declared earlier in the tutorial) has a coercion from C, so C should be able to coerce from an arrayref of strings, right? B<< Wrong! >> C<< ArrayRef[PathTiny] >> can coerce from an arrayref of strings, but C is a separate type constraint which, although it inherits from C<< ArrayRef[PathTiny] >> has its own (currently empty) set of coercions. Because that is often not what you want, Type::Tiny provides a shortcut when declaring a subtype to copy the parent type constraint's coercions: declare Paths, as ArrayRef[PathTiny], coercion => 1; Now C can coerce from an arrayref of strings. =head3 Deep Caveat Currently there exists ill-defined behaviour resulting from mixing deep coercions and mutable (non-frozen) coercions. Consider the following: class_type PathTiny, { class => "Path::Tiny" }; coerce PathTiny, from Str, via { "Path::Tiny"->new($_) }; declare Paths, as ArrayRef[PathTiny], coercion => 1; coerce PathTiny, from InstanceOf["My::File"], via { $_->get_path }; An arrayref of strings can now be coerced to an arrayref of Path::Tiny objects, but is it also now possible to coerce an arrayref of My::File objects to an arrayref of Path::Tiny objects? Currently the answer is "no", but this is mostly down to implementation details. It's not clear what the best way to behave in this situation is, and it could start working at some point in the future. You should avoid falling into this trap by following the advice found under L. =head2 Chained Coercions Consider the following type library: { package Types::Geometric; use Type::Library -base, -declare => qw( VectorArray VectorArray3D Point Point3D ); use Type::Utils; use Types::Standard qw( Num Tuple InstanceOf ); declare VectorArray, as Tuple[Num, Num]; declare VectorArray3D, as Tuple[Num, Num, Num]; coerce VectorArray3D, from VectorArray, via { [ @$_, 0 ]; }; class_type Point, { class => "Point" }; coerce Point, from VectorArray, via { Point->new(x => $_->[0], y => $_->[1]); }; class_type Point3D, { class => "Point3D" }; coerce Point3D, from VectorArray3D, via { Point3D->new(x => $_->[0], y => $_->[1], z => $_->[2]); }, from Point, via { Point3D->new(x => $_->x, y => $_->y, z => 0); }; } Given an arrayref C<< [1, 1] >> you might reasonably expect it to be coercible to a C object; it matches the type constraint C so can be coerced to C and thus to C. However, L does not automatically chain coercions like this. Firstly, it would be incompatible with Moose's type coercion system which does not chain coercions. Secondly, it's ambiguous; in our example, the arrayref could be coerced along two different paths (via C or via C); in this case the end result would be the same, but in other cases it might not. Thirdly, it runs the risk of accidentally creating loops. Doing the chaining manually though is pretty simple. Firstly, we'll take note of the C method in L. This method called as C<< VectorArray3D->coercibles >> returns a type constraint meaning "anything that can be coerced to a C". So we can define the coercions for C as: coerce Point3D, from VectorArray3D->coercibles, via { my $tmp = to_VectorArray3D($_); Point3D->new(x => $tmp->[0], y => $tmp->[1], z => $tmp->[2]); }, from Point, via { Point3D->new(x => $_->x, y => $_->y, z => 0); }; ... and now coercing from C<< [1, 1] >> will work. =head2 The (Lack of) Zen of Coercions Coercions can lead to ugliness. Let's say we define a type constraint C which has a coercion from C. Now we define a class which uses that type constraint. Now in another class, we define a coercion from C to C. This kind of action at a distance is not really desirable. And in fact, things will probably subtly break - the first class may have already built a constructor inlining a bunch of code from the coercion. However, you too can achieve coercion zen by following these L: =over =item 1. If you want to define coercions for a type, do it I<< within your type constraint library >>, so the coercions are all defined before the type constraint is ever used. =item 2. At the end of your type constraint library, consider calling C<< $type->coercion->freeze >> on each type constraint that has a coercion. This makes the type's coercions immutable. If anybody wants to define any additional coercions, they'll have to create a child type to do it with. A shortcut exists for this: __PACKAGE__->meta->make_immutable; =item 3. Use C and similar methods to easily create a child type constraint of any existing type, and add more coercions to it. Don't fiddle directly with the existing type constraint which may be being used elsewhere. Note that these methods all return type constraint objects with frozen (immutable) coercions. =back That's it. =head1 SEE ALSO L, L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. =cut Libraries.pod000664001750001750 2174612422772210 20700 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Type/Tiny/Manual=pod =for stopwords smush smushed =encoding utf-8 =head1 NAME Type::Tiny::Manual::Libraries - how to build a type library with Type::Tiny, Type::Library and Type::Utils =head1 SYNOPSIS A type library is a collection of type constraints, optionally with coercions. The following is an example type library: package Example::Types; use Type::Library -base, -declare => qw( Datetime DatetimeHash EpochHash ); use Type::Utils -all; use Types::Standard -types; class_type Datetime, { class => "DateTime" }; declare DatetimeHash, as Dict[ year => Int, month => Optional[ Int ], day => Optional[ Int ], hour => Optional[ Int ], minute => Optional[ Int ], second => Optional[ Int ], nanosecond => Optional[ Int ], time_zone => Optional[ Str ], ]; declare EpochHash, as Dict[ epoch => Int ]; coerce Datetime, from Int, via { "DateTime"->from_epoch(epoch => $_) }, from Undef, via { "DateTime"->now }, from DatetimeHash, via { "DateTime"->new(%$_) }, from EpochHash, via { "DateTime"->from_epoch(%$_) }; 1; =head1 DESCRIPTION Here's a line by line description of what's going on in the type library. package Example::Types; Type libraries are packages. It is recommended that re-usable type libraries be given a name in the C<< Types::* >> namespace. For application-specific type libraries, assuming your application's namespace is C<< MyApp::* >> then name the type library C<< MyApp::Types >>, or if more than one is needed, use the C<< MyApp::Types::* >> namespace. use Type::Library -base, -declare => qw( Datetime DatetimeHash EpochHash ); The C<< -base >> part is used to establish inheritance. It makes C a child class of C. Declaring the types we're going to define ahead of their definition allows us to use them as barewords later on. (Note that in code which I our type library, the types will always be available as barewords. The declaration above just allows us to use them within the library itself.) use Type::Utils -all; Imports some utility functions from L. These will be useful for defining our types and the relationships between them. use Types::Standard -types; Here we import a standard set of type constraints from L. There is no need to do this, but it's often helpful to have a base set of types which we can define our own in terms of. Note that although we've imported the types to be able to use in our library, we haven't I the types to our library. We've imported C, but other people won't be able to re-import C from our library. If you actually want your library to I another library, do this instead: BEGIN { extends "Types::AnotherLibrary" }; (Note: if your code breaks here when you upgrade from version 0.006 or below, saying that the 'extends' keyword has not been declared, just add '-all' after use Type::Utils.) OK, now we're ready to declare a few types. class_type Datetime, { class => "DateTime" }; This creates a type constraint named "Datetime" which is all objects blessed into the L package. Because this type constraint is not anonymous (it has a name), it will be automagically installed into the type library. The next two statements declare two further types constraints, using type constraints from the Types::Standard library. Let's look at C in more detail. This is a hashref with one key called "epoch" and a value which is an integer. declare EpochHash, as Dict[ epoch => Int ]; C inherits from the C type defined in Types::Standard. It equally could have been defined as: declare EpochHash, as HashRef[Int], where { scalar(keys(%$_))==1 and exists $_->{epoch} }; Or even: declare EpochHash, where { ref($_) eq "HASH" and scalar(keys(%$_))==1 and exists $_->{epoch} }; Lastly we set up coercions. It's best to define all your types before you define any coercions. coerce Datetime, from Int, via { "DateTime"->from_epoch(epoch => $_) }, from Undef, via { "DateTime"->now }, from DatetimeHash, via { "DateTime"->new(%$_) }, from EpochHash, via { "DateTime"->from_epoch(%$_) }; These are simply coderefs that will be fired when you want a Datetime, but are given something else. For more information on coercions, see L. =head2 Using Your Library Use a custom types library just like you would L: packge MyClass; use Moose; use DateTime; use Example::Types qw( Datetime ); # import the custom type has 'sometime' => ( is => 'rw', isa => Datetime, coerce => 1, ); Type libraries defined with L are also able to export some convenience functions: use Example::Types qw( is_Datetime to_Datetime assert_Datetime ); my $dt = Foo::get_datetime; unless ( is_Datetime $dt ) { $dt = to_Datetime $dt; } assert_Datetime $dt; These functions act as shortcuts for: use Example::Types qw( Datetime ); my $dt = Foo::get_datetime; unless ( Datetime->check($dt) ) { $dt = Datetime->coerce($dt); } Datetime->assert_return($dt); Pick whichever style you think is clearer! Type::Library-based libraries provide a shortcut for importing a type constraint along with all its associated convenience functions: # Shortcut for qw( DateTime is_Datetime to_Datetime assert_Datetime ) # use Example::Types qw( +Datetime ); See L for other ways to make use of type libraries. =head1 ADVANCED TOPICS =head2 Messages It is sometimes nice to be able to emit a more useful error message than the standard: Value "Foo" did not pass type constraint "Bar" It is possible to define custom error messages for types. declare MediumInteger, as Integer, where { $_ >= 10 and $_ < 20 }, message { return Integer->get_message($_) if !Integer->check($_); return "$_ is too small!" if $_ < 10; return "$_ is so very, very big!"; }; =head2 Parameterized Constraints Parameterized type constraints are those that can generate simple child type constraints by passing parameters to their C method. For example, ArrayRef in Types::Standard: use Types::Standard; my $ArrayRef = Types::Standard::ArrayRef; my $Int = Types::Standard::Int; my $ArrayRef_of_Ints = $ArrayRef->parameterize($Int); Type libraries provide some convenient sugar for this: use Types::Standard qw( ArrayRef Int ); my $ArrayRef_of_Ints = ArrayRef[Int]; Unlike L which has separate meta classes for parameterizable, parameterized and non-parameterizable type constraints, L handles all that in one. To create a parameterizable type constraint, you'll need to pass an extra named parameter to C. Let's imagine that we want to make our earlier C constraint accept a parameter telling it the minimum size of the hash. For example C<< NonEmptyHash[4] >> would need to contain at least four key-value pairs. Here's how you'd do it: declare NonEmptyHash, as HashLike, where { scalar values %$_ }, inline_as { my ($constraint, $varname) = @_; return sprintf( '%s and scalar values %%{%s}', $constraint->parent->inline_check($varname), $varname, ); }, # Generate a new "where" coderef... constraint_generator => sub { my ($minimum) = @_; die "parameter must be positive" unless int($minimum) > 0; return sub { scalar(values(%$_)) >= int($minimum); }; }, # Generate a new "inline_as" coderef... inline_generator => sub { my ($minimum) = @_; return sub { my ($constraint, $varname) = @_; return sprintf( '%s and scalar(values(%%{%s})) >= %d', $constraint->parent->inline_check($varname), $varname, $minimum, ); }; }; =head1 SEE ALSO Some type libraries on CPAN: =over =item * L =item * L =item * L / L =item * L =item * L! =back =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. =cut Optimization.pod000664001750001750 1731412422772210 21446 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Type/Tiny/Manual=pod =for stopwords smush smushed enums =encoding utf-8 =head1 NAME Type::Tiny::Manual::Optimization - squeeze the most out of your CPU =head1 DESCRIPTION Various tips to help you squeeze the most out of your CPU. =head2 XS The simplest thing you can do to increase performance of many of the built-in type constraints is to install L, a set of ultra-fast type constraint checks implemented in C. L will attempt to load L and use its type checks. If L is not available, it will then try to use L B<< if it is already loaded >>, but Type::Tiny won't attempt to load Mouse for you. =head3 Types that can be accelerated by Type::Tiny::XS The following simple type constraints from L will be accelerated by Type::Tiny::XS: C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, and C. (Note that C and C are B on that list.) The parameterized form of C cannot be accelerated. The parameterized forms of C, C, and C can be accelerated only if their parameters are. The parameterized form of C can be accelerated if its parameters are, it has no C components, and it does not use C. Certain type constraints may benefit partially from Type::Tiny::XS. For example, C inherits from C, so part of the type check will be conducted by Type::Tiny::XS. The parameterized C, C, and C type constraints will be accelerated. So will L, L, and L objects. (But enums will only be accelerated if the list of allowed string values consist entirely of word characters and hyphens - that is: C<< not grep /[^\w-]/, @values >>.) The C and C type constraints from L will be accelerated, as will the C type constraint from L. L and L will also be accelerated if their constituent type constraints are. =head3 Types that can be accelerated by Mouse The following simple type constraints from L will be accelerated by Type::Tiny::XS: C, C, C, C, C, C, C, C, C, C, C, C, C, and C. (Note that C, C, C, C, and C are B on that list.) The parameterized form of C cannot be accelerated. The parameterized forms of C and C can be accelerated only if their parameters are. Certain type constraints may benefit partially from Mouse. For example, C inherits from C, so part of the type check will be conducted by Mouse. The parameterized C and C type constraints will be accelerated. So will L and L objects. =head2 Common Sense The C<< HashRef[ArrayRef] >> type constraint can probably be checked faster than C<< HashRef[ArrayRef[Num]] >>. If you find yourself using very complex and slow type constraints, you should consider switching to simpler and faster ones. (Though this means you have to place a little more trust in your caller to not supply you with bad data.) (A counter-intuitive exception to this: even though C is more restrictive than C, in most circumstances C checks will run faster.) =head2 Inlining Type Constraints If your type constraint can be inlined, this can not only speed up Type::Tiny's own checks and coercions, it may also allow your type constraint to be inlined into generated methods such as Moose attribute accessors. All of the constraints from C can be inlined, as can enum, class_type, role_type and duck_type constraints. Union and intersection constraints can be inlined if their sub-constraints can be. So if you can define your own types purely in terms of these types, you automatically get inlining: declare HashLike, as union [ Ref["HASH"], Overload["&{}"], ]; However, sometimes these base types are not powerful enough and you'll need to write a constraint coderef: declare NonEmptyHash, as HashLike, where { scalar values %$_ }; ... and you've suddenly sacrificed a lot of speed. Inlining to the rescue! You can define an inlining coderef which will be passed two parameters: the constraint itself and a variable name as a string. For example, the variable name might be C<< '$_' >> or C<< '$_[0]' >>. Your coderef should return a Perl expression string, interpolating that variable name. declare NonEmptyHash, as HashLike, where { scalar values %$_ }, inline_as { my ($constraint, $varname) = @_; return sprintf( '%s and scalar values %%{%s}', $constraint->parent->inline_check($varname), $varname, ); }; The Perl expression could be inlined within a function or a C clause or potentially anywhere, so it really must be an expression, not a statement. It should not C or C and probably shouldn't C. (If you need loops and so on, you can output a C block.) Note that if you're subtyping an existing type constraint, your C block is also responsible for checking the parent type's constraint. This can be done quite easily, as shown in the example above. Note that defining a type constraint in terms of a constraint coderef and an inlining coderef can be a little repetitive. L provides an alternative that reduces repetition (though the inlined code might not be as compact/good/fast). declare NonEmptyHash, as HashLike, constraint => quote_sub q{ scalar values %$_ }; Aside: it's been pointed out that "might not be as fast" above is a bit hand-wavy. When Type::Tiny does inlining from Sub::Quote coderefs, it needs to inline all the ancestor type constraints, and smush them together with C<< && >>. This may result in duplicate checks. For example, if 'MyArray' inherits from 'MyRef' which inherits from 'MyDef', the inlined code might end up as: defined($_) # check MyDef && ref($_) # check MyRef && ref($_) eq 'ARRAY' # check MyArray When just the last check would have been sufficient. A custom C allows you finer control over how the type constraint is inlined. =head2 Optimizing Coercions Coercions are often defined using coderefs: PathTiny->plus_coercions( Str, sub { "Path::Tiny"->new($_) }, Undef, sub { "Path::Tiny"->new("/etc/myapp/default.conf") }, ); But you can instead define them as strings of Perl code operating on C<< $_ >>: PathTiny->plus_coercions( Str, q{ "Path::Tiny"->new($_) }, Undef, q{ "Path::Tiny"->new("/etc/myapp/default.conf") }, ); The latter will run faster, so is preferable at least for simple coercions. This makes the most difference when used with L, which supports inlining of coercions. L does not inline coercions, but providing coercions as strings still allows Type::Tiny to optimize the coercion coderef it provides to Moose. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. =cut Params.pod000664001750001750 1176412422772210 20206 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Type/Tiny/Manual=pod =encoding utf-8 =head1 NAME Type::Tiny::Manual::Params - coerce and validate arguments to functions and methods =head1 DESCRIPTION There is a module called L available to wrap up type coercion and constraint checks into a single, simple and fast check. If you care about speed, and your sub signatures are fairly simple, then this is the way to go... use feature qw( state ); use Types::Standard qw( Str ); use Type::Utils; use Type::Params qw( compile ); my $Invocant = class_type { class => __PACKAGE__ }; sub set_name { state $check = compile($Invocant, Str); my ($self, $name) = $check->(@_); ...; } See the COOKBOOK section of L for further information. =head2 The Somewhat More Manual Way... In general, Type::Params should be sufficient to cover most needs, and will probably run faster than almost anything you could cook up yourself. However, sometimes you need to deal with unusual function signatures that it does not support. For example, imagine function C<< format_string >> takes an optional hashref of formatting instructions, followed by a required string. You might expect to be able to handle it like this: sub format_string { state $check = compile(Optional[HashRef], Str); my ($instructions, $string) = $check->(@_); ...; } However, this won't work, as Type::Params expects required parameters to always precede optional ones. So there are times you need to handle parameters more manually. In these cases, bear in mind that for any type constraint object you have several useful checking methods available: Str->check($var) # returns a boolean is_Str($var) # ditto Str->($var) # returns $var or dies assert_Str($var) # ditto Here's how you might handle the C function: sub format_string { my $instructions; $instructions = shift if HashRef->check($_[0]); my $string = Str->(shift); ...; } Alternatively, you could manipulate @_ before passing it to the compiled check: sub format_string { state $check = compile(HashRef, Str); my ($instructions, $str) = $check->(@_==1 ? ({}, @_) : @_); ...; } =head2 Signatures Don't you wish your subs could look like this? sub set_name (Object $self, Str $name) { $self->{name} = $name; } Well; here are a few solutions for sub signatures that work with L... =head3 Kavorka L is a sub signatures implementation written to natively use L' C for type constraints, and take advantage of Type::Tiny's features such as inlining, and coercions. method set_name (Str $name) { $self->{name} = $name; } Kavorka's signatures provide a lot more flexibility, and slightly more speed than Type::Params. (The speed comes from inlining almost all type checks into the body of the sub being declared.) Kavorka also includes support for type checking of the returned value. Kavorka can also be used as part of L, a larger framework for object oriented programming in Perl. =head3 Function::Parameters The following should work with L 1.0201 or above: use Type::Utils; use Function::Parameters { method => { strict => 1, reify_type => sub { Type::Utils::dwim_type($_[0]) }, }, }; method set_name (Str $name) { $self->{name} = $name; } Note that by default, Function::Parameters uses Moose's type constraints. The C option above (introduced in Function::Parameters 1.0201) allows you to "divert" type constraint lookups. Using Type::Tiny constraints will gain you about a 7% speed-up in function signature checks. An alternative way to use Function::Parameter with Type::Tiny is to provide type constraint expressions in parentheses: use Types::Standard; use Function::Parameters ':strict'; method set_name ((Str) $name) { $self->{name} = $name; } =head3 Attribute::Contract Both Kavorka and Function::Parameters require a relatively recent version of Perl. L supports older versions by using a lot less magic. You want Attribute::Contract 0.03 or above. use Attribute::Contract -types => [qw/Object Str/]; sub set_name :ContractRequires(Object, Str) { my ($self, $name) = @_; $self->{name} = $name; } Attribute::Contract also includes support for type checking of the returned value. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. =cut Policies.pod000664001750001750 657112422772210 20512 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Type/Tiny/Manual=pod =encoding utf-8 =for stopwords versioning =head1 NAME Type::Tiny::Manual::Policies - Type::Tiny policies =head1 STABILITY =head2 Type::Tiny Stability Policy Type::Tiny 1.000000 is considered stable. Any changes to the API that are big enough to I changes to the test suite will be preceded by a I<< six month >> notice period, with the following exceptions: =over =item * Any changes which are necessary to maintain compatibility with new releases of L, L, and other software that Type::Tiny needs to integrate with. =item * Changes to maintain compatibility with future versions of Perl itself. =item * Where a change fixes a contradiction between the implementation and documentation of Type::Tiny. =item * Where a feature is explicitly documented as being "experimental" or "unstable". =item * Improvements to the text of error messages. =back =head2 Experimental and Unstable Type::Tiny Features The following list is currently non-exhaustive. =over =item * L inlining subs (i.e. C) may return a list of strings (with C being allowed as the first item on the list). This is experimental. See L. =item * L's C attribute and the functionality it provides is experimental. =item * The L is subject to change. =item * The interaction of deep coercions and mutable coercions currently results in ill-defined behaviour. This could change at any time. (See L.) =item * L's ability to import L and L type libraries is experimental. =item * Integration with L. =item * These modules are considered part of Type::Tiny's internals, and not covered by the stability policy: L, L, L, L, L, L, L, L, L, L, and L. =item * L is not covered by the stability policy. =back =head2 Type::Tiny Versioning Policy As of 1.000000, this distribution follows a versioning scheme similar to L, which is based on a L-like three component version number, but with the last two components each represented by three decimal digits in the fractional part of the version number. That is, version 1.003002 of the software represents "1.3.2". Additionally, releases where the second component is an odd number will be considered unstable/trial releases. (These will also include an underscore in the version number as per the usual CPAN convention.) =head1 BUGS Please report any bugs to L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. =cut UsingWithMoo.pod000664001750001750 561112422772210 21331 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Type/Tiny/Manual=pod =encoding utf-8 =head1 NAME Type::Tiny::Manual::UsingWithMoo - how to use Type::Tiny and Type::Library with Moo =head1 SYNOPSIS { package Person; use Moo; use Types::Standard qw( Str Int ); use Type::Utils qw( declare as where inline_as coerce from ); has name => ( is => "ro", isa => Str, ); my $PositiveInt = declare as Int, where { $_ > 0 }, inline_as { "$_ =~ /^[0-9]+\$/ and $_ > 0" }; coerce $PositiveInt, from Int, q{ abs $_ }; has age => ( is => "rwp", isa => $PositiveInt, coerce => $PositiveInt->coercion, ); sub get_older { my $self = shift; my ($years) = @_; $PositiveInt->assert_valid($years); $self->_set_age($self->age + $years); } } =head1 DESCRIPTION Type::Tiny is tested with L 1.001000 and above. Type::Tiny overloads C<< &{} >>. Moo supports using objects that overload C<< &{} >> as C constraints, so Type::Tiny objects can directly be used in C. Moo doesn't support C<< coerce => 1 >> but requires a coderef as a coercion. However, again it supports using objects that overload C<< &{} >>, which Type::Coercion does, allowing C<< coerce => $Type->coercion >> to work. Type::Tiny hooks into Moo's HandleMoose interface to ensure that type constraints get inflated to Moose type constraints if and when Moo inflates your class to a full Moose class. =head2 Optimization The usual advice for optimizing type constraints applies: use type constraints which can be inlined whenever possible, and define coercions as strings rather than coderefs. Upgrading to Moo 1.002000 or above should provide a slight increase in speed for type constraints, as it allows them to be inlined into accessors and constructors. If creating your own type constraints using C<< Type::Tiny->new >>, then consider using L to quote the coderef; this allows you to take advantage of inlining without having to write your own inlining routines. See also L. =head1 SEE ALSO For examples using Type::Tiny with L see the SYNOPSIS sections of L and L, and the L in the test suite. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. =cut UsingWithMoose.pod000664001750001750 745312422772210 21667 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Type/Tiny/Manual=pod =encoding utf-8 =head1 NAME Type::Tiny::Manual::UsingWithMoose - how to use Type::Tiny and Type::Library with Moose =head1 SYNOPSIS { package Person; use Moose; use Types::Standard qw( Str Int ); use Type::Utils qw( declare as where inline_as coerce from ); has name => ( is => "ro", isa => Str, ); my $PositiveInt = declare as Int, where { $_ > 0 }, inline_as { "$_ =~ /^[0-9]+\$/ and $_ > 0" }; coerce $PositiveInt, from Int, q{ abs $_ }; has age => ( is => "ro", isa => $PositiveInt, coerce => 1, writer => "_set_age", ); sub get_older { my $self = shift; my ($years) = @_; $PositiveInt->assert_valid($years); $self->_set_age($self->age + $years); } } =head1 DESCRIPTION L type constraints have an API almost identical to that of L. It is also able to build a Moose::Meta::TypeConstraint constraint from a Type::Tiny constraint, and will do so automatically when needed. When Moose.pm is loaded, Type::Tiny will use Perl's C feature to proxy method calls through to the Moose::Meta::TypeConstraint object. In short, you can use a Type::Tiny object pretty much anywhere you'd use a Moose::Meta::TypeConstraint and you are unlikely to notice the difference. =head2 Per-Attribute Coercions Type::Tiny offers convenience methods to alter the list of coercions associated with a type constraint. Let's imagine we wish to allow our C attribute to be coerced from an arrayref of strings. has name => ( is => "ro", isa => Str->plus_coercions( ArrayRef[Str], sub { join " ", @{$_} }, ), coerce => 1, ); This coercion will apply to the C attribute only; other attributes using the C type constraint will be unaffected. See the documentation for C, C and C in L. =head2 Optimization The usual advice for optimizing type constraints applies: use type constraints which can be inlined whenever possible. Defining coercions as strings rather than coderefs won't give you as much of a boost with Moose as it does with Moo, because Moose doesn't inline coercion code. However, it should still improve performance somewhat because it allows L to do some internal inlining. See also L. =head2 Interactions with MooseX-Types Type::Tiny and MooseX::Types type constraints should "play nice". If, for example, C is taken from L (i.e. a Type::Tiny-based type library), and C is taken from L, then the following should "just work": isa => ArrayRef[ PositiveInt ] isa => PositiveInt | ArrayRef =head1 SEE ALSO For examples using Type::Tiny with L see the SYNOPSIS sections of L and L, and the L, and L in the test suite. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. =cut UsingWithMouse.pod000664001750001750 705012422772210 21666 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Type/Tiny/Manual=pod =encoding utf-8 =head1 NAME Type::Tiny::Manual::UsingWithMouse - how to use Type::Tiny and Type::Library with Mouse =head1 SYNOPSIS { package Person; use Mouse; use Types::Standard qw( Str Int ); use Type::Utils qw( declare as where inline_as coerce from ); has name => ( is => "ro", isa => Str, ); my $PositiveInt = declare as Int, where { $_ > 0 }, inline_as { "$_ =~ /^[0-9]+\$/ and $_ > 0" }; coerce $PositiveInt, from Int, q{ abs $_ }; has age => ( is => "ro", isa => $PositiveInt, coerce => 1, writer => "_set_age", ); sub get_older { my $self = shift; my ($years) = @_; $PositiveInt->assert_valid($years); $self->_set_age($self->age + $years); } } =head1 STATUS L support in Type::Tiny was somewhat of an afterthought. It should work, but is not anywhere near as well-tested as L or L support. =head1 DESCRIPTION L type constraints have an API almost identical to that of L. As a result, you can use a Type::Tiny object pretty much anywhere you'd use a Mouse::Meta::TypeConstraint and you are unlikely to notice the difference. (And Mouse is unlikely to notice the difference too!) =head2 Per-Attribute Coercions Type::Tiny offers convenience methods to alter the list of coercions associated with a type constraint. Let's imagine we wish to allow our C attribute to be coerced from an arrayref of strings. has name => ( is => "ro", isa => Str->plus_coercions( ArrayRef[Str], sub { join " ", @{$_} }, ), coerce => 1, ); This coercion will apply to the C attribute only; other attributes using the C type constraint will be unaffected. See the documentation for C, C and C in L. =head2 Optimization Mouse's built-in type constraints are implemented using XS and are stupidly fast. For many type constraints, if Type::Tiny notices Mouse is loaded early enough, Type::Tiny will borrow Mouse's XS subs. See also L. =head2 Interactions with MouseX-Types Type::Tiny and MouseX::Types type constraints should "play nice". If, for example, C is taken from L (i.e. a Type::Tiny-based type library), and C is taken from L, then the following should "just work": isa => ArrayRef[ PositiveInt ] isa => PositiveInt | ArrayRef =head1 SEE ALSO For examples using Type::Tiny with L see the SYNOPSIS sections of L and L, and the L, and L in the test suite. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. =cut UsingWithOther.pod000664001750001750 1167512422772210 21707 0ustar00taitai000000000000Type-Tiny-1.000005/lib/Type/Tiny/Manual=pod =encoding utf-8 =for stopwords inlinable =head1 NAME Type::Tiny::Manual::UsingWithOther - how to use Type::Tiny and Type::Library with other OO frameworks =head1 DESCRIPTION =head2 Class::InsideOut You want L 1.13 or above, which has support for blessed and overloaded objects (including Type::Tiny type constraints) for the C and C options. { package Person; use Class::InsideOut qw( public ); use Types::Standard qw( Str Int ); use Type::Utils qw( declare as where inline_as coerce from ); public name => my %_name, { set_hook => Str, }; my $PositiveInt = declare as Int, where { $_ > 0 }, inline_as { "$_ =~ /^[0-9]+\$/ and $_ > 0" }; coerce $PositiveInt, from Int, q{ abs $_ }; public age => my %_age, { set_hook => sub { $_ = $PositiveInt->assert_coerce($_) }, }; sub get_older { my $self = shift; my ($years) = @_; $PositiveInt->assert_valid($years); $self->_set_age($self->age + $years); } } I probably need to make coercions a little prettier. B<< See also: >> C<< t/25_accessor_hooks_typetiny.t >> and C<< t/Object/HookedTT.pm >> in the Class::InsideOut test suite; and the L in the Type::Tiny test suite. =head2 Params::Check and Object::Accessor The Params::Check C<< allow() >> function, the C option for the Params::Check C<< check() >> function, and the input validation mechanism for Object::Accessor all work in the same way, which is basically a limited pure-Perl implementation of the smart match operator. While this doesn't directly support Type::Tiny constraints, it does support coderefs. You can use Type::Tiny's C method to obtain a suitable coderef. B<< L example: >> my $tmpl = { name => { allow => Str->compiled_check }, age => { allow => Int->compiled_check }, }; check($tmpl, { name => "Bob", age => 32 }) or die Params::Check::last_error(); B<< L example: >> my $obj = Object::Accessor->new; $obj->mk_accessors( { name => Str->compiled_check }, { age => Int->compiled_check }, ); B<< Caveat: >> Object::Accessor doesn't die when a value fails to meet its type constraint; instead it outputs a warning to STDERR. This behaviour can be changed by setting C<< $Object::Accessor::FATAL = 1 >>. B<< See also: >> The L in the Type::Tiny test suite. =head2 Validation::Class::Simple You want L 7.900017 or above. The C function from L can be used to create a Type::Tiny type constraint from a Validation::Class::Simple object (and probably from Validation::Class, but this is untested). use Types::TypeTiny qw( to_TypeTiny ); use Validation::Class::Simple; my $type = to_TypeTiny Validation::Class::Simple->new( fields => { name => { required => 1, pattern => qr{^\w+(\s\w+)*$}, filters => ["trim", "strip"], }, email => { required => 1, email => 1 }, pass => { required => 1, min_length => 6 }, }, ); # true $type->check({ name => "Toby Inkster", email => "tobyink@cpan.org", pass => "foobar", }); # false $type->check({ name => "Toby Inkster ", # trailing whitespace email => "tobyink@cpan.org", pass => "foobar", }); # coercion from HashRef uses the filters defined above my $fixed = $type->coerce({ name => "Toby Inkster ", # trailing whitespace email => "tobyink@cpan.org", pass => "foobar", }); # true $type->check($fixed); Type constraints built with Validation::Class::Simple are not inlinable, so won't be as fast as C from L, but the filters are a pretty useful feature. (Note that filters are explicitly I for type constraint checking, and only come into play for coercion.) B<< See also: >> The L in the Type::Tiny test suite. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. =cut