COPYRIGHT000664001750001750 2471113116235715 13722 0ustar00taitai000000000000Type-Tiny-1.002001Format: 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/benchmarking/benchmark-coercions.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, 2017 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, 2017 by Toby Inkster. License: GPL-1.0+ or Artistic-1.0 Files: CREDITS Changes LICENSE META.json META.yml Makefile.PL NEWS README TODO doap.ttl examples/benchmarking/benchmark-constraints.pl examples/benchmarking/benchmark-named-param-validation.pl examples/benchmarking/benchmark-param-validation.pl examples/benchmarking/versus-scalar-validation.pl examples/datetime-coercions.pl examples/nonempty.pl examples/page-numbers.pl Copyright: Copyright 2017 Toby Inkster. License: GPL-1.0+ or Artistic-1.0 Files: lib/Types/Standard/CycleTuple.pm t/20-unit/Type-Tiny-_HalfOp/double-union.t t/20-unit/Type-Tiny/constraint-strings.t t/20-unit/Types-Standard/cycletuple.t t/40-regression/gh14.t Copyright: This software is copyright (c) 2017 by 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, 2017 by Diab Jerius. License: GPL-1.0+ or Artistic-1.0 Files: INSTALL t/README t/TODO t/mk-test-manifest.pl t/not-covered.pl Copyright: Unknown License: Unknown 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, 2017 by Graham Knop. 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, 2017 by Matt S Trout - mst (at) shadowcatsystems.co.uk (L). License: GPL-1.0+ or Artistic-1.0 Files: t/20-unit/Type-Params/compile-named.t t/20-unit/Type-Params/hashorder.t t/30-integration/Moose/coercion-more.t Copyright: This software is copyright (c) 2013-2014 by Toby Inkster. 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, 2017 by Diab Jerius. License: GPL-1.0+ or Artistic-1.0 Files: t/40-regression/rt86233.t t/40-regression/rt86239.t Copyright: This software is copyright (c) 2013-2014, 2017 by Vyacheslav Matyukhin. License: GPL-1.0+ or Artistic-1.0 Files: COPYRIGHT SIGNATURE Copyright: None License: public-domain Files: t/30-integration/MooseX-Getopt/coercion.t Copyright: This software is copyright (c) 2014, 2017 by Alexander Hartmaier. License: GPL-1.0+ or Artistic-1.0 Files: t/40-regression/ttxs-gh1.t Copyright: This software is copyright (c) 2014, 2017 by Jed Lund. License: GPL-1.0+ or Artistic-1.0 Files: t/30-integration/Class-InsideOut/basic.t Copyright: This software is copyright (c) 2013-2014, 2017 by David Golden, Toby Inkster. License: GPL-1.0+ or Artistic-1.0 Files: t/40-regression/gh1.t Copyright: This software is copyright (c) 2013-2014, 2017 by Richard Simões. 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/rt90096.t Copyright: This software is copyright (c) 2013-2014, 2017 by Samuel Kaufman. 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: t/40-regression/rt98113.t Copyright: This software is copyright (c) 2014, 2017 by Dagfinn Ilmari MannsÃ¥ker. License: GPL-1.0+ or Artistic-1.0 Files: t/99-moose-std-types-test.t Copyright: This software is copyright (c) 2013-2014, 2017 by Infinity Interactive, Inc.. License: GPL-1.0+ or Artistic-1.0 Files: dist.ini Copyright: Copyright 2014 Toby Inkster. 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 License: Artistic-1.0 This software is Copyright (c) 2017 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) 2017 by the copyright holder(s). This is free software, licensed under: The GNU General Public License, Version 1, February 1989 CREDITS000664001750001750 317313116235465 13430 0ustar00taitai000000000000Type-Tiny-1.002001Maintainer: - Toby Inkster (TOBYINK) Contributor: - Alexander Hartmaier (ABRAXXA) - Alexandr Ciornii - Dagfinn Ilmari Mannsåker (ILMARI) - David Steinbrunner - Denis Ibaev - Diab Jerius (DJERIUS) - Gianni Ceccarelli (DAKKAR) - Graham Knop (HAARG) - Karen Etheridge (ETHER) - Lucas Buchala - Mark Stosberg (MARKSTOS) - Peter Flanigan (PJFL) - Peter Karman (KARMAN) - Peter Valdemar Mørch - Pierre Masci - Samuel Kaufman (SKAUFMAN) - Thomas Sibley (TSIBLEY) - Vyacheslav Matyukhin (MMCLERIC) - Zoffix Znet Thanks: - André Walker - Aran Clary Deltac (BLUEFEET) - 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 20546613116235465 13754 0ustar00taitai000000000000Type-Tiny-1.002001Type-Tiny ========= Created: 2013-03-23 Home page: Bug tracker: Maintainer: Toby Inkster (TOBYINK) 1.002001 2017-06-08 [ Test Suite ] - Skip t/30-integration/Moose/native-attribute-traits.t on older Moose because Test::Moose is broken. [ Packaging ] - Ref::Util::XS 0.100 should be recommended, not 0.200 (which doesn't exist yet). Fixes RT#121981. 1.002000 2017-06-01 [ Packaging ] - Stable version number. 1.001_016 2017-05-30 [ Documentation ] - Include page-numbers.pl example 1.001_015 2017-05-20 [ Bug Fixes ] - Fix HashRef[Str]|Undef|Str parsing on Perl < 5.14. Fixes RT#121764. Aran Clary Deltac++ Graham Knop++ 1.001_014 2017-05-19 - Include trailing line break at the end of stringified version of some exceptions. Peter Valdemar Mørch++ 1.001_013 2017-05-18 Kittiversary [ Bug Fixes ] - Fixed crazy amount of UTF-8 warnings from Type::Params on Perl 5.6.x and Perl 5.8.x. Fixes RT#101582. André Walker++ - StrMatch changes in previous release broke the ability to check type equality between two parameterized StrMatch types under some circumstances. Changed how the hash key for stashing regexp references gets built — is now closer to the old way. This doesn't revert the change in 1.001_012 where regexp checks can be inlined better, but only applies to those regexp references that can't easily be inlined. 1.001_012 2017-05-17 [ BACK COMPAT ] - RegexpRef now accepts blessed objects if $object->isa('Regexp') returns true. [ Other ] - StrMatch will use Regexp::Util (if available) to inline regular expressions more sensibly. 1.001_011 2017-05-17 [ Bug Fixes ] - Type constraints like Tuple[Int] shouldn't report they have a coercion if Int doesn't have a coercion. [ Other ] - Added: Types::Standard now has a CycleTuple type. 1.001_010 2017-05-16 Puppiversary [ Test Suite ] - t/00-begin.t will now work around ANDK's apparently broken XS testing environment. 1.001_009 2017-05-13 - Rewrite some benchmarking scripts to use Benchmark::Featureset::ParamCheck. - Use Ref::Util::XS (if it's installed) to speed up certain type checks. 1.001_008 2017-05-10 [ Bug Fixes ] - Type::Params should make sure Type::Utils is loaded before calling english_list(). [ Documentation ] - Rearrange the examples directory in the distribution. [ Other ] - Added: Named parameter validation benchmarking script. - Added: Reduce scope of local $SIG{__DIE__} in Type::Registry. Graham Knop++ 1.001_007 2017-05-04 May the fourth be with you [ Documentation ] - Comparison of Type::Params with new(ish) CPAN module Params::ValidationCompiler. - Show example of how to set defaults for parameters with Type::Params. [ Other ] - Added: Type::Params' `multisig` function now sets a variable `${^TYPE_PARAMS_MULTISIG}` to indicate which signature succeeded. - Optimization of Type::Params positional parameter checking for simple cases with no slurpy parameter and no coercions. - Optimizations for Tuple and StrMatch type constraints from Types::Standard. 1.001_006 2017-04-30 - Allow Type::Tiny's `constraint` parameter to be a string of Perl code. - Localize $SIG{__DIE__} in Type::Registry. Fixes RT#100780. 1.001_005 2017-04-19 [ Bug Fixes ] - 02-api.t should check version of Moose available. - 20-unit/Type-Utils/warnings.t should check version of Test::Warnings. Alexandr Ciornii++ - Fix minor typos in documentation for Types::Standard. Zoffix Znet++ - Fix variable name typo in documentation for Type::Params. Lucas Buchala++ [ Documentation ] - Include projected release date for Type::Tiny 1.002000 in NEWS. [ Test Suite ] - Bundle a test case for GH issue 14. [ Other ] - Improved error location reporting for Moo Peter Valdemar Mørch++ - Updated: NumericCode now coerces from strings with whitespace in them, like MooseX::Types::Common::Numeric. Denis Ibaev++ 1.001_004 2017-02-06 - Attempting ArrayRef[Int, Int] or similar now throws an exception. Fixes RT#105299. Thomas Sibley++ 1.001_003 2017-02-02 - Updated: Merge fixes from stable Type-Tiny 1.000006. 1.001_002 2014-10-25 [ Bug Fixes ] - Fix short-circuiting optimizations for parameterized HashRef, ArrayRef, ScalarRef, and Map type constraints. Fixes RT#99312. Marcel Timmerman++ - Inlined version of Types::Standard::Int should check that the value is not a reference. [ Test Suite ] - Fix annoying warning message in test suite with recent versions of Exporter::Tiny. [ Other ] - Make equals/is_a_type_of/is_subtype_of/is_supertype_of in Type::Tiny::Union work more like Moose::Meta::TypeConstraint::Union. 1.001_001 2014-09-19 - Lazy-load Text::Balanced in Type::Parser. (Many parses don't even need it.) - Lazy-load Type::Tiny::Union in Type::Params. - Updated: Prefer Sub::Util over Sub::Name. (The former is smaller.) 1.001_000 2014-09-07 [ 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++ [ Documentation ] - Updated NEWS file. - Updated TODO file. - Updates to Type::Tiny::Manual::UsingWithMoose, Type::Tiny::Manual::UsingWithMoo, and Type::Tiny::Manual::UsingWithMouse. [ Test Suite ] - Make some of the test case skip_all bits more ambitious; test older versions of Moose and Moo than we were testing before. [ Other ] - Added: Type::Params now provides `compile_named` and `validate_named` functions which do the same thing as `compile` and `validate` but are better for named arguments. - Updated: If Sub::Name is unavailable, but the shiny new core Sub::Util is available, then use it instead. - Updated: Want Type::Tiny::XS 0.011. - `Type::Utils::dwim_type` now allows more control over fallback behaviours. 1.000006 2017-01-30 [ Bug Fixes ] - Fix escaping within q{...} in a test case. Fixes RT#114386. Karen Etheridge++ 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 165313116235453 13437 0ustar00taitai000000000000Type-Tiny-1.002001 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 4365513116235454 13444 0ustar00taitai000000000000Type-Tiny-1.002001This software is copyright (c) 2017 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) 2017 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) 2017 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 1646413116235715 13566 0ustar00taitai000000000000Type-Tiny-1.002001COPYRIGHT CREDITS Changes INSTALL LICENSE MANIFEST META.json META.yml Makefile.PL NEWS README SIGNATURE TODO dist.ini doap.ttl examples/benchmarking/benchmark-coercions.pl examples/benchmarking/benchmark-constraints.pl examples/benchmarking/benchmark-named-param-validation.pl examples/benchmarking/benchmark-param-validation.pl examples/benchmarking/versus-scalar-validation.pl examples/datetime-coercions.pl examples/nonempty.pl examples/page-numbers.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/CycleTuple.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/compile-named.t t/20-unit/Type-Params/hashorder.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/double-union.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/constraint-strings.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/cycletuple.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-more.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/gh14.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 1774513116235714 14060 0ustar00taitai000000000000Type-Tiny-1.002001{ "abstract" : "tiny, yet Moo(se)-compatible type constraint", "author" : [ "Toby Inkster (TOBYINK) " ], "dynamic_config" : 1, "generated_by" : "Dist::Inkt::Profile::TOBYINK version 0.024, CPAN::Meta::Converter version 2.150005", "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", "Ref::Util::XS" : "0.100", "Regexp::Util" : "0.003", "Sub::Util" : "0", "Type::Tie" : "0", "Type::Tiny::XS" : "0.011", "perl" : "5.010001" }, "requires" : { "Exporter::Tiny" : "0.026", "perl" : "5.006001" }, "suggests" : { "Moo" : "1.000000", "Moose" : "2.0000", "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.002001" }, "Devel::TypeTiny::Perl58Compat" : { "file" : "lib/Devel/TypeTiny/Perl58Compat.pm", "version" : "1.002001" }, "Error::TypeTiny" : { "file" : "lib/Error/TypeTiny.pm", "version" : "1.002001" }, "Error::TypeTiny::Assertion" : { "file" : "lib/Error/TypeTiny/Assertion.pm", "version" : "1.002001" }, "Error::TypeTiny::Compilation" : { "file" : "lib/Error/TypeTiny/Compilation.pm", "version" : "1.002001" }, "Error::TypeTiny::WrongNumberOfParameters" : { "file" : "lib/Error/TypeTiny/WrongNumberOfParameters.pm", "version" : "1.002001" }, "Eval::TypeTiny" : { "file" : "lib/Eval/TypeTiny.pm", "version" : "1.002001" }, "Reply::Plugin::TypeTiny" : { "file" : "lib/Reply/Plugin/TypeTiny.pm", "version" : "1.002001" }, "Test::TypeTiny" : { "file" : "lib/Test/TypeTiny.pm", "version" : "1.002001" }, "Type::Coercion" : { "file" : "lib/Type/Coercion.pm", "version" : "1.002001" }, "Type::Coercion::FromMoose" : { "file" : "lib/Type/Coercion/FromMoose.pm", "version" : "1.002001" }, "Type::Coercion::Union" : { "file" : "lib/Type/Coercion/Union.pm", "version" : "1.002001" }, "Type::Library" : { "file" : "lib/Type/Library.pm", "version" : "1.002001" }, "Type::Params" : { "file" : "lib/Type/Params.pm", "version" : "1.002001" }, "Type::Parser" : { "file" : "lib/Type/Parser.pm", "version" : "1.002001" }, "Type::Registry" : { "file" : "lib/Type/Registry.pm", "version" : "1.002001" }, "Type::Tiny" : { "file" : "lib/Type/Tiny.pm", "version" : "1.002001" }, "Type::Tiny::Class" : { "file" : "lib/Type/Tiny/Class.pm", "version" : "1.002001" }, "Type::Tiny::Duck" : { "file" : "lib/Type/Tiny/Duck.pm", "version" : "1.002001" }, "Type::Tiny::Enum" : { "file" : "lib/Type/Tiny/Enum.pm", "version" : "1.002001" }, "Type::Tiny::Intersection" : { "file" : "lib/Type/Tiny/Intersection.pm", "version" : "1.002001" }, "Type::Tiny::Role" : { "file" : "lib/Type/Tiny/Role.pm", "version" : "1.002001" }, "Type::Tiny::Union" : { "file" : "lib/Type/Tiny/Union.pm", "version" : "1.002001" }, "Type::Utils" : { "file" : "lib/Type/Utils.pm", "version" : "1.002001" }, "Types::Common::Numeric" : { "file" : "lib/Types/Common/Numeric.pm", "version" : "1.002001" }, "Types::Common::String" : { "file" : "lib/Types/Common/String.pm", "version" : "1.002001" }, "Types::Standard" : { "file" : "lib/Types/Standard.pm", "version" : "1.002001" }, "Types::Standard::ArrayRef" : { "file" : "lib/Types/Standard/ArrayRef.pm", "version" : "1.002001" }, "Types::Standard::CycleTuple" : { "file" : "lib/Types/Standard/CycleTuple.pm", "version" : "1.002001" }, "Types::Standard::Dict" : { "file" : "lib/Types/Standard/Dict.pm", "version" : "1.002001" }, "Types::Standard::HashRef" : { "file" : "lib/Types/Standard/HashRef.pm", "version" : "1.002001" }, "Types::Standard::Map" : { "file" : "lib/Types/Standard/Map.pm", "version" : "1.002001" }, "Types::Standard::ScalarRef" : { "file" : "lib/Types/Standard/ScalarRef.pm", "version" : "1.002001" }, "Types::Standard::Tuple" : { "file" : "lib/Types/Standard/Tuple.pm", "version" : "1.002001" }, "Types::TypeTiny" : { "file" : "lib/Types/TypeTiny.pm", "version" : "1.002001" } }, "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_IRC" : "irc://irc.perl.org/#moops", "x_identifier" : "http://purl.org/NET/cpan-uri/dist/Type-Tiny/project" }, "version" : "1.002001", "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) ", "Karen Etheridge (ETHER) ", "Thomas Sibley (TSIBLEY) ", "Peter Valdemar Mørch ", "Zoffix Znet ", "Denis Ibaev ", "Lucas Buchala ", "Alexandr Ciornii " ], "x_serialization_backend" : "JSON::PP version 2.27300_01" } META.yml000664001750001750 1241313116235714 13673 0ustar00taitai000000000000Type-Tiny-1.002001--- 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.024, CPAN::Meta::Converter version 2.150005' 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.002001' Devel::TypeTiny::Perl58Compat: file: lib/Devel/TypeTiny/Perl58Compat.pm version: '1.002001' Error::TypeTiny: file: lib/Error/TypeTiny.pm version: '1.002001' Error::TypeTiny::Assertion: file: lib/Error/TypeTiny/Assertion.pm version: '1.002001' Error::TypeTiny::Compilation: file: lib/Error/TypeTiny/Compilation.pm version: '1.002001' Error::TypeTiny::WrongNumberOfParameters: file: lib/Error/TypeTiny/WrongNumberOfParameters.pm version: '1.002001' Eval::TypeTiny: file: lib/Eval/TypeTiny.pm version: '1.002001' Reply::Plugin::TypeTiny: file: lib/Reply/Plugin/TypeTiny.pm version: '1.002001' Test::TypeTiny: file: lib/Test/TypeTiny.pm version: '1.002001' Type::Coercion: file: lib/Type/Coercion.pm version: '1.002001' Type::Coercion::FromMoose: file: lib/Type/Coercion/FromMoose.pm version: '1.002001' Type::Coercion::Union: file: lib/Type/Coercion/Union.pm version: '1.002001' Type::Library: file: lib/Type/Library.pm version: '1.002001' Type::Params: file: lib/Type/Params.pm version: '1.002001' Type::Parser: file: lib/Type/Parser.pm version: '1.002001' Type::Registry: file: lib/Type/Registry.pm version: '1.002001' Type::Tiny: file: lib/Type/Tiny.pm version: '1.002001' Type::Tiny::Class: file: lib/Type/Tiny/Class.pm version: '1.002001' Type::Tiny::Duck: file: lib/Type/Tiny/Duck.pm version: '1.002001' Type::Tiny::Enum: file: lib/Type/Tiny/Enum.pm version: '1.002001' Type::Tiny::Intersection: file: lib/Type/Tiny/Intersection.pm version: '1.002001' Type::Tiny::Role: file: lib/Type/Tiny/Role.pm version: '1.002001' Type::Tiny::Union: file: lib/Type/Tiny/Union.pm version: '1.002001' Type::Utils: file: lib/Type/Utils.pm version: '1.002001' Types::Common::Numeric: file: lib/Types/Common/Numeric.pm version: '1.002001' Types::Common::String: file: lib/Types/Common/String.pm version: '1.002001' Types::Standard: file: lib/Types/Standard.pm version: '1.002001' Types::Standard::ArrayRef: file: lib/Types/Standard/ArrayRef.pm version: '1.002001' Types::Standard::CycleTuple: file: lib/Types/Standard/CycleTuple.pm version: '1.002001' Types::Standard::Dict: file: lib/Types/Standard/Dict.pm version: '1.002001' Types::Standard::HashRef: file: lib/Types/Standard/HashRef.pm version: '1.002001' Types::Standard::Map: file: lib/Types/Standard/Map.pm version: '1.002001' Types::Standard::ScalarRef: file: lib/Types/Standard/ScalarRef.pm version: '1.002001' Types::Standard::Tuple: file: lib/Types/Standard/Tuple.pm version: '1.002001' Types::TypeTiny: file: lib/Types/TypeTiny.pm version: '1.002001' recommends: Devel::LexAlias: '0.05' Devel::StackTrace: '0' Ref::Util::XS: '0.100' Regexp::Util: '0.003' Sub::Util: '0' Type::Tie: '0' Type::Tiny::XS: '0.011' perl: '5.010001' requires: Exporter::Tiny: '0.026' perl: '5.006001' resources: IRC: irc://irc.perl.org/#moops 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.002001' 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) ' - 'Karen Etheridge (ETHER) ' - 'Thomas Sibley (TSIBLEY) ' - 'Peter Valdemar Mørch ' - 'Zoffix Znet ' - 'Denis Ibaev ' - 'Lucas Buchala ' - 'Alexandr Ciornii ' x_serialization_backend: 'CPAN::Meta::YAML version 0.018' Makefile.PL000664001750001750 3670513116235714 14406 0ustar00taitai000000000000Type-Tiny-1.002001use 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.024, CPAN::Meta::Converter version 2.150005", "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, "Ref::Util::XS" => "0.100", "Regexp::Util" => 0.003, "Sub::Util" => 0, "Type::Tie" => 0, "Type::Tiny::XS" => 0.011, }, requires => { "Exporter::Tiny" => 0.026, "perl" => 5.006001 }, suggests => { Moo => "1.000000", Moose => "2.0000", 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.002001 }, "Devel::TypeTiny::Perl58Compat" => { file => "lib/Devel/TypeTiny/Perl58Compat.pm", version => 1.002001 }, "Error::TypeTiny" => { file => "lib/Error/TypeTiny.pm", version => 1.002001 }, "Error::TypeTiny::Assertion" => { file => "lib/Error/TypeTiny/Assertion.pm", version => 1.002001 }, "Error::TypeTiny::Compilation" => { file => "lib/Error/TypeTiny/Compilation.pm", version => 1.002001 }, "Error::TypeTiny::WrongNumberOfParameters" => { file => "lib/Error/TypeTiny/WrongNumberOfParameters.pm", version => 1.002001, }, "Eval::TypeTiny" => { file => "lib/Eval/TypeTiny.pm", version => 1.002001 }, "Reply::Plugin::TypeTiny" => { file => "lib/Reply/Plugin/TypeTiny.pm", version => 1.002001 }, "Test::TypeTiny" => { file => "lib/Test/TypeTiny.pm", version => 1.002001 }, "Type::Coercion" => { file => "lib/Type/Coercion.pm", version => 1.002001 }, "Type::Coercion::FromMoose" => { file => "lib/Type/Coercion/FromMoose.pm", version => 1.002001 }, "Type::Coercion::Union" => { file => "lib/Type/Coercion/Union.pm", version => 1.002001 }, "Type::Library" => { file => "lib/Type/Library.pm", version => 1.002001 }, "Type::Params" => { file => "lib/Type/Params.pm", version => 1.002001 }, "Type::Parser" => { file => "lib/Type/Parser.pm", version => 1.002001 }, "Type::Registry" => { file => "lib/Type/Registry.pm", version => 1.002001 }, "Type::Tiny" => { file => "lib/Type/Tiny.pm", version => 1.002001 }, "Type::Tiny::Class" => { file => "lib/Type/Tiny/Class.pm", version => 1.002001 }, "Type::Tiny::Duck" => { file => "lib/Type/Tiny/Duck.pm", version => 1.002001 }, "Type::Tiny::Enum" => { file => "lib/Type/Tiny/Enum.pm", version => 1.002001 }, "Type::Tiny::Intersection" => { file => "lib/Type/Tiny/Intersection.pm", version => 1.002001 }, "Type::Tiny::Role" => { file => "lib/Type/Tiny/Role.pm", version => 1.002001 }, "Type::Tiny::Union" => { file => "lib/Type/Tiny/Union.pm", version => 1.002001 }, "Type::Utils" => { file => "lib/Type/Utils.pm", version => 1.002001 }, "Types::Common::Numeric" => { file => "lib/Types/Common/Numeric.pm", version => 1.002001 }, "Types::Common::String" => { file => "lib/Types/Common/String.pm", version => 1.002001 }, "Types::Standard" => { file => "lib/Types/Standard.pm", version => 1.002001 }, "Types::Standard::ArrayRef" => { file => "lib/Types/Standard/ArrayRef.pm", version => 1.002001 }, "Types::Standard::CycleTuple" => { file => "lib/Types/Standard/CycleTuple.pm", version => 1.002001 }, "Types::Standard::Dict" => { file => "lib/Types/Standard/Dict.pm", version => 1.002001 }, "Types::Standard::HashRef" => { file => "lib/Types/Standard/HashRef.pm", version => 1.002001 }, "Types::Standard::Map" => { file => "lib/Types/Standard/Map.pm", version => 1.002001 }, "Types::Standard::ScalarRef" => { file => "lib/Types/Standard/ScalarRef.pm", version => 1.002001 }, "Types::Standard::Tuple" => { file => "lib/Types/Standard/Tuple.pm", version => 1.002001 }, "Types::TypeTiny" => { file => "lib/Types/TypeTiny.pm", version => 1.002001 }, }, "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", x_IRC => "irc://irc.perl.org/#moops", }, "version" => 1.002001, "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) ", "Karen Etheridge (ETHER) ", "Thomas Sibley (TSIBLEY) ", "Peter Valdemar M\xF8rch ", "Zoffix Znet ", "Denis Ibaev ", "Lucas Buchala ", "Alexandr Ciornii ", ], }; 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 254513116235452 13105 0ustar00taitai000000000000Type-Tiny-1.002001======================================================================= 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-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. 2017-06-01 Type-Tiny version 1.002000 released! - Type::Params now has `compile_named` and `validate_named`. - Type::Tiny's `constraint` parameter may be a string of code. - Types::Standard::CycleTuple added. - Types::Standard::RegexpRef now accepts blessed objects where $object->isa('Regexp'). This plays better with re::engine::* pragmas. - Fixed bug where Types::Standard::Int would *sometimes* accept an overloaded object. (It never should.) - Various performance enhancements and bug fixes. README000664001750001750 1357313116235454 13313 0ustar00taitai000000000000Type-Tiny-1.002001NAME 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.000000 is recommended. If using Type::Tiny with Moose, then at least Moose 2.0000 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, 2017 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 4513513116235716 13717 0ustar00taitai000000000000Type-Tiny-1.002001This file contains message digests of all files listed in MANIFEST, signed via the Module::Signature module, version 0.81. 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 43f3035111305813d6c5aae01a2c36a54d9e6b53 COPYRIGHT SHA1 e962230fa8f7cacbad9041ed11986ef8f904748e CREDITS SHA1 684deaea38ccde9aa6475867d78fa65f289aa9e2 Changes SHA1 ad40a11542937daa751b38225d43868322a073cc INSTALL SHA1 c4c1e6c578edcfd14d13eadebc8f56dd9ca46821 LICENSE SHA1 38cdd49ddac430003837f92a80500eeaa6d03a13 MANIFEST SHA1 c23604e99be1d978112e5d536b2c3e00d7b31329 META.json SHA1 303045039f8e516a9aea36b50450ec3cca6f0297 META.yml SHA1 56fb9384fcd722364b16a57c7992550d63eefe36 Makefile.PL SHA1 1c3f46a6123d633060192dad3eb925634a2c6824 NEWS SHA1 ede3b434b7e4bbe7305a6b3a6c9889b4a3f703bc README SHA1 1bdfc3ee53c5fa5a44b1040c9a395342097f79a6 TODO SHA1 eeed84a123dd7a29ae3be4700cd6d1daeb6c1c68 dist.ini SHA1 3f6502f7f961571426f93a5bad5f0c4347d44c5d doap.ttl SHA1 f6a5ed85dc02d9af3f31ea901639f0a65fa4bdd5 examples/benchmarking/benchmark-coercions.pl SHA1 b041788e5c5bf1074370d629b0464e5cf8c9a6cf examples/benchmarking/benchmark-constraints.pl SHA1 da374658c1f1c58c1373803c291c47746eb35ebf examples/benchmarking/benchmark-named-param-validation.pl SHA1 64c425643408fe5311575bef3625f82a514a281f examples/benchmarking/benchmark-param-validation.pl SHA1 2aacb4150fc74604496079f9ac21968325ac5f3b examples/benchmarking/versus-scalar-validation.pl SHA1 f25058eef51dac107e9aa72ec62272aec62f7e94 examples/datetime-coercions.pl SHA1 6ed5c7a93aa23cf9c5c71004d6f9216826f6f3fa examples/nonempty.pl SHA1 55e7ca7fc7520290472eea6e252b25cc77049c1e examples/page-numbers.pl SHA1 8b3c5d366a0a716096617c9e14a100c1948fd159 inc/Test/Fatal.pm SHA1 95d4da14025622f3a45f5e9b75b7b6860148f415 inc/Test/Requires.pm SHA1 e7088f7483bdffb64be359be205927c3d6639ffe inc/Try/Tiny.pm SHA1 75980a8641e17d40930aac03c6d41abbee35683f lib/Devel/TypeTiny/Perl56Compat.pm SHA1 d2cf8f597938fa6138d083cfccac0cb108b90380 lib/Devel/TypeTiny/Perl58Compat.pm SHA1 acd36e37d1b801217700287ea94fa3fa1e58f90a lib/Error/TypeTiny.pm SHA1 be322238ac57c4cd023c1d6eb4fcb8804b4086f9 lib/Error/TypeTiny/Assertion.pm SHA1 ca973dce2f3fe34897db6a0620f8806bd1d9aeae lib/Error/TypeTiny/Compilation.pm SHA1 09b95ea782dc09d6d229b27fbf82459a9c8b61cd lib/Error/TypeTiny/WrongNumberOfParameters.pm SHA1 5cfaedab8558fed0b1baf49c898eef35e0912b1b lib/Eval/TypeTiny.pm SHA1 4c4a6031649491ed5a6918b2b25383be4f118cd9 lib/Reply/Plugin/TypeTiny.pm SHA1 ff71ebc840390448aee34629fba181cddfa21f49 lib/Test/TypeTiny.pm SHA1 7debe88e939f17d8da4a52d0b77a0cc6ae78eb5c lib/Type/Coercion.pm SHA1 c60c03f8f234e01e8d9ad9e35507ad763fc9200a lib/Type/Coercion/FromMoose.pm SHA1 0f3af91b391e27b8af44c9278c7b424f2fe41e5a lib/Type/Coercion/Union.pm SHA1 3ee2b10df83e82762071b2049b0b2d8a7d8717e8 lib/Type/Library.pm SHA1 f0770011f7263bcfd59b95b06c524e1518536857 lib/Type/Params.pm SHA1 ac2d833334767f016597826351c6e0e34115e37d lib/Type/Parser.pm SHA1 7ab51056ab4a88887be50e3c0b36da18afbb8378 lib/Type/Registry.pm SHA1 4d19e7b6fd7bba3dfb900dc7a736edd79cbbd2cf lib/Type/Tiny.pm SHA1 600a32179d66ffaee115ca19636fae2e6512b4f9 lib/Type/Tiny/Class.pm SHA1 6f4d664b84eadad4d5a75998eb831da986a7c222 lib/Type/Tiny/Duck.pm SHA1 f791f448f9f39dd1364bebf955d9242f3baa7e2c lib/Type/Tiny/Enum.pm SHA1 2f6ba1c90fbbf55b9c3fbb9947a11225fa0afa82 lib/Type/Tiny/Intersection.pm SHA1 05e56e880fca0deaf1bef4a46b14f8cf4d163581 lib/Type/Tiny/Manual.pod SHA1 2b67e924aa0809bdf7a10b61c86f57dfc056ee47 lib/Type/Tiny/Manual/Coercions.pod SHA1 0ef000b7e9d7a20f2044a01d76c9bd9fa569a7b1 lib/Type/Tiny/Manual/Libraries.pod SHA1 9fcc800a62763c891556d8246fd0a43072f50276 lib/Type/Tiny/Manual/Optimization.pod SHA1 65224c09a5b132f557acf45198a00fab86854deb lib/Type/Tiny/Manual/Params.pod SHA1 bd060a36edfd9ca7a6740f6a6a1c896c6a546d31 lib/Type/Tiny/Manual/Policies.pod SHA1 184056e24852adbcbb3e14068da4a4f1e04a6a17 lib/Type/Tiny/Manual/UsingWithMoo.pod SHA1 2fa4c4064de0c556c9d8226019c8cfc183695459 lib/Type/Tiny/Manual/UsingWithMoose.pod SHA1 8fe837cddd94856235ab6fca5068e55b4841d8ad lib/Type/Tiny/Manual/UsingWithMouse.pod SHA1 83b18347b56696345232fe5094564545a77f5048 lib/Type/Tiny/Manual/UsingWithOther.pod SHA1 fa1fcfba5f20f0befb196e2a7cd75f6ad57b033b lib/Type/Tiny/Role.pm SHA1 3750f1dee8f247b558d8a96bc9be6e2acd16e2dd lib/Type/Tiny/Union.pm SHA1 f0d098493833497f08c5f9df3b9e8eb1d685763a lib/Type/Tiny/_HalfOp.pm SHA1 6ae90d6c40dc0ead09b790f2d98e3b4aefec6e6d lib/Type/Utils.pm SHA1 fc04e27a7459dff7ce9dff0956aef09b8ab008e9 lib/Types/Common/Numeric.pm SHA1 ff53bd0e52ee18e15063bd1cac56d7181d6ccf3c lib/Types/Common/String.pm SHA1 99b0ad24bea080b8cd70af22c7e1be9c415b5275 lib/Types/Standard.pm SHA1 c641ab2ffffe48470c751f0eefa7926c09099da2 lib/Types/Standard/ArrayRef.pm SHA1 57f7b76ec2eddc3d95b9df04e8028a8e1bfc70a4 lib/Types/Standard/CycleTuple.pm SHA1 b10192a4b971db4bd19cbad8618fc43af1ce8c51 lib/Types/Standard/Dict.pm SHA1 d37126316fbda6ca6c46e11c7340667b8647d7c5 lib/Types/Standard/HashRef.pm SHA1 582ded1449e41165b530114e9d6cbf50adb1c9fb lib/Types/Standard/Map.pm SHA1 69f05d9380ae1e6f593380a2c903e740b6125362 lib/Types/Standard/ScalarRef.pm SHA1 71bf647e07a4ead9c89603ee9933496a6aa05cc6 lib/Types/Standard/Tuple.pm SHA1 5d762ad5d1d892870a947b9b42e678aa50948b20 lib/Types/TypeTiny.pm SHA1 fcbd8bb8803959349f3a768d34f31ef84bee466c t/00-begin.t SHA1 088b352634ef159700fb113335211a79179c7153 t/01-compile.t SHA1 11a99d9dd8b8026eba860ddb415e49e1937e0c23 t/02-api.t SHA1 942d039ee8a9484812ee961631eaa22cdf2c8340 t/03-leak.t SHA1 deb8551b9098ad0098a372a453ba395d62c81c74 t/20-unit/Devel-TypeTiny-Perl56Compat/basic.t SHA1 9dc1d9b55394e405540cde709fce9f718cce0651 t/20-unit/Devel-TypeTiny-Perl58Compat/basic.t SHA1 32c4eec0ac3e7cb09e3455c0bc75b92816c586fa t/20-unit/Error-TypeTiny-Assertion/basic.t SHA1 84923f01be2ffc040c9e74ae0dff252e487122be t/20-unit/Error-TypeTiny-Compilation/basic.t SHA1 88c02880d1d81f3725d86c9d0c37fe2fe27a2cd6 t/20-unit/Error-TypeTiny-WrongNumberOfParameters/basic.t SHA1 860aa0dcf2537f02367e35838194a20697003d7e t/20-unit/Error-TypeTiny/basic.t SHA1 db4a42bc7edacaf071fbda74faeac47f8b3152bb t/20-unit/Error-TypeTiny/stacktrace.t SHA1 a4f59c3acda7b5c90cf0e5dcc066c98e9838c96f t/20-unit/Eval-TypeTiny/basic.t SHA1 8f14beadc74f3b760c61a7c88df1941f91d1614f t/20-unit/Eval-TypeTiny/fallback-aliases.t SHA1 681e804ad87bb4d9676f6729db1ef4ad2e56e717 t/20-unit/Eval-TypeTiny/lexical-subs.t SHA1 549eb9a118c031977740d1012400af1845375d97 t/20-unit/Test-TypeTiny/basic.t SHA1 9786a265867f9043400418fea81ce5b1f50237a9 t/20-unit/Test-TypeTiny/extended.t SHA1 e10dbd60b9da6659a553b1b2f1f53fa81db28f98 t/20-unit/Test-TypeTiny/matchfor.t SHA1 2efebc5b869d9c16ea2d74d6fa97277ff0edae3c t/20-unit/Type-Coercion-FromMoose/basic.t SHA1 039d59fb1145e40f0e5a2cf7ff01edbfac70e1a5 t/20-unit/Type-Coercion-FromMoose/errors.t SHA1 9a55bdf88590b1f1c6a2d64c5aac13a8fd8a7114 t/20-unit/Type-Coercion-Union/basic.t SHA1 3cad2c52303c6fdf77bfba2ec01456873bf0d494 t/20-unit/Type-Coercion/basic.t SHA1 359e7a8c48322022b24147a546d8a2ae4abf6df1 t/20-unit/Type-Coercion/esoteric.t SHA1 2fe671bdd2f1b4a341ee4d4b96dac3ea77c78098 t/20-unit/Type-Coercion/frozen.t SHA1 fe459d4c4b282e1667a5cbb8c2cc9204322ef76e t/20-unit/Type-Coercion/inlining.t SHA1 39031d45a22a2f3f7ae5eb616e46419e23101005 t/20-unit/Type-Coercion/parameterized.t SHA1 f0e1fd91d62b92a462768e9555edacf0d332fd03 t/20-unit/Type-Coercion/smartmatch.t SHA1 bc7c029731a9e4296760a6de68066cd2facb6b79 t/20-unit/Type-Coercion/typetiny-constructor.t SHA1 5c2607992c378e00df8b9d715f8e87ac7570d895 t/20-unit/Type-Library/assert.t SHA1 3163b2d331b79388bd554267389d584d1a7f2966 t/20-unit/Type-Library/errors.t SHA1 9233cc81fb8dd81d213150a4947cb1d1d4ee2ce3 t/20-unit/Type-Library/inheritance.t SHA1 15a991e5866a4891fe2fce24a697b57fccafc4b4 t/20-unit/Type-Library/is.t SHA1 bca3204f88d3ced4172f2586eb025936d84abe81 t/20-unit/Type-Library/to.t SHA1 1e40f33a9273f56fef4037fb83fffec015ed6cb7 t/20-unit/Type-Library/types.t SHA1 5b4557bbf9b8e159de3dcf980641437e2ec33f42 t/20-unit/Type-Params/badsigs.t SHA1 b8390317ff84edcd45691e0b862d43689339c04d t/20-unit/Type-Params/carping.t SHA1 e3915c354e90d9743fecce8a7c75e153928f07de t/20-unit/Type-Params/coerce.t SHA1 95e71519f2d83af05d95f9fccb06ae81e92d9099 t/20-unit/Type-Params/compile-named.t SHA1 a4d26033ecb493564ffe13fa9ec8ae83daff23bc t/20-unit/Type-Params/hashorder.t SHA1 94c7724f5c7057c7b9f3228d38a3e430620a7d0c t/20-unit/Type-Params/methods.t SHA1 7206515761cfe08d0cf64600e452eddb8acf138b t/20-unit/Type-Params/mixednamed.t SHA1 16055e4bda1971f446f80c422f4a816ad9505b2b t/20-unit/Type-Params/multisig.t SHA1 7b4f07f90df4afc6ff1a3ad7f70fe06405770488 t/20-unit/Type-Params/named.t SHA1 a85bdab1cf4c343f768c43b4664f21461a1c6550 t/20-unit/Type-Params/noninline.t SHA1 4400e5a6af2cbe2964e440f98eb2c97b07b9b3d9 t/20-unit/Type-Params/optional.t SHA1 1e7b890cbc30f7d749a82002e276d978df20824b t/20-unit/Type-Params/positional.t SHA1 1f5b7b40469fa682ee2600319d3f8b3f4d224d27 t/20-unit/Type-Params/slurpy.t SHA1 f2740ba627bead27eaa5020a8691d0e99b9c554e t/20-unit/Type-Parser/basic.t SHA1 aa4c2f9d045890d2a8be552c0d528137dd13ea43 t/20-unit/Type-Parser/moosextypes.t SHA1 c0139f97ecfffa853c47d92f2d1287dbf8cf696e t/20-unit/Type-Registry/automagic.t SHA1 b1ca2c587a5e1ad4c945347144981f80db166a5d t/20-unit/Type-Registry/basic.t SHA1 574ca5fc6c025cdd747deac7eaba745de169ef40 t/20-unit/Type-Registry/methods.t SHA1 48b0b6dacf6fe6e21efad7616dd45391af517763 t/20-unit/Type-Registry/moosextypes.t SHA1 4dfb724f15d18fa50a33a57f2a96cf40ad2066e5 t/20-unit/Type-Registry/mousextypes.t SHA1 a4fe869cd2c864a7cef9b99a871ad96c49765097 t/20-unit/Type-Tiny-Class/basic.t SHA1 12c41fca5d8e742de8da30f4bf4633cd88b7f786 t/20-unit/Type-Tiny-Class/errors.t SHA1 e6a917cc17089264004387e7ea18575d04e31c92 t/20-unit/Type-Tiny-Class/plus-constructors.t SHA1 2d0fb4f2428ec740e45d4c199e19d388bf91a4e3 t/20-unit/Type-Tiny-Duck/basic.t SHA1 e6ba27d65c108fb6764d33e531cb736f3beae917 t/20-unit/Type-Tiny-Duck/errors.t SHA1 26ad2118ae48c3a6029e97c618e868b5d9f44a86 t/20-unit/Type-Tiny-Enum/basic.t SHA1 7ce42af55682af497f3bf16000f423cbe437b65f t/20-unit/Type-Tiny-Enum/errors.t SHA1 83ba71b81b70b2359c8870a4a24b8886a3f1dc53 t/20-unit/Type-Tiny-Intersection/basic.t SHA1 baf8f968e9003e54c292357a08ad988a38646d81 t/20-unit/Type-Tiny-Intersection/errors.t SHA1 c962c48b0407aa68c4178cdf66044d70b9099369 t/20-unit/Type-Tiny-Role/basic.t SHA1 0f668f419eb4ecf75fd0dec613da658b003075e3 t/20-unit/Type-Tiny-Role/errors.t SHA1 ffba8d8b3bda1ec7dc16a41bcdd7f2445d4d213b t/20-unit/Type-Tiny-Union/basic.t SHA1 230e3d84627e0a68d2ec9036a3caeff2a466a2b8 t/20-unit/Type-Tiny-Union/errors.t SHA1 a474d12f370e5d9579037e2469b78a4edc1ec0e2 t/20-unit/Type-Tiny-_HalfOp/double-union.t SHA1 6a63835fa1db2609b508db2362860e82d0a41023 t/20-unit/Type-Tiny-_HalfOp/overload-precedence.t SHA1 96d1cc1c6193974918c80c6d813c7ae9bf7e6c8e t/20-unit/Type-Tiny/arithmetic.t SHA1 8314b4f8f13fb6128b6565d1e91e30cb10242524 t/20-unit/Type-Tiny/basic.t SHA1 596e94112bb67dd8f024380728dd445261bbbd04 t/20-unit/Type-Tiny/coercion-modifiers.t SHA1 2f43e4216b98f9693ce521f1fd610e05318fadfc t/20-unit/Type-Tiny/constraint-strings.t SHA1 c017a23122c8538b9b3b5da9be2c466f4ed3cd07 t/20-unit/Type-Tiny/esoteric.t SHA1 39e50f942a94082461979221915c62383144736c t/20-unit/Type-Tiny/my-methods.t SHA1 b0a5f4d5902883e6b5f55572ca095f6f81cc6bc9 t/20-unit/Type-Tiny/parameterization.t SHA1 c7e8a4ff1094404ccf059026d4a9550f16d28226 t/20-unit/Type-Tiny/shortcuts.t SHA1 570a184a8bb6bcfc79990e1d9ce6d819657b0342 t/20-unit/Type-Tiny/smartmatch.t SHA1 673ae8ee5f0d12673f9e14d0bade6f995b76900c t/20-unit/Type-Tiny/syntax.t SHA1 4656a864b6b5c1c6997f93d4ee4e0a20b87dadee t/20-unit/Type-Tiny/to-moose.t SHA1 e271b1a40eda56bd6e2e4dcbf8918c735fc414e9 t/20-unit/Type-Tiny/to-mouse.t SHA1 470ae7fd95dede94da1c81b9d5aff49ff08e2f2a t/20-unit/Type-Utils/classifier.t SHA1 4313544b381cc9ec6192fd08f7de3508a827c7d1 t/20-unit/Type-Utils/dwim-both.t SHA1 72d8becb0612d6045bb8e88a25f90a15e55f3337 t/20-unit/Type-Utils/dwim-moose.t SHA1 b380f4a562c6d93866c31f27ba8f9bc328fd0f80 t/20-unit/Type-Utils/dwim-mouse.t SHA1 a98a6db6b8973bcbe3478f5b6dd559cb1bfe1bef t/20-unit/Type-Utils/match-on-type.t SHA1 4388b81d4f4901f9a8785cef4b1126e339a09464 t/20-unit/Type-Utils/warnings.t SHA1 e21c47d117ca084f0f3a77d378c8363afbc4f427 t/20-unit/Types-Common-Numeric/basic.t SHA1 3a1b140b23eb2da7df7ba28e66743cabbde2757f t/20-unit/Types-Common-String/basic.t SHA1 dc3e4d49883b384042c90d4cacc70b3c5029622d t/20-unit/Types-Common-String/coerce.t SHA1 0ef063de8a3ccc2c7508b07fee87edc914d18622 t/20-unit/Types-Common-String/unicode.t SHA1 fdcda91c002cad88c158236a074005323049c06d t/20-unit/Types-Standard/basic.t SHA1 4a951f7d4d149a70a6b8b6c8c8d259bdda2733fe t/20-unit/Types-Standard/cycletuple.t SHA1 1b339ad0ef2ded541a5ff14a83f2e2e1d7a0baa3 t/20-unit/Types-Standard/deep-coercions.t SHA1 ee55afb82db5a13eea02aaa0a65b3766fc0537df t/20-unit/Types-Standard/lockdown.t SHA1 08534c5ed3c759c7224033681b62df3744ecc1a0 t/20-unit/Types-Standard/mxtmlb-alike.t SHA1 0ce0ffd559e577aa7be9c99e349338d51341f86d t/20-unit/Types-Standard/optlist.t SHA1 6bb89d985b555f75b6329176ca4eb3d99eff6466 t/20-unit/Types-Standard/overload.t SHA1 f01b41686908125f684cb770ad61cf19ece0e3ef t/20-unit/Types-Standard/strmatch.t SHA1 b10fcfd1f32dff76b005c690d48cee42fd95acfe t/20-unit/Types-Standard/structured.t SHA1 1334790b0f772a5084eb9680fe744ce900458a2a t/20-unit/Types-Standard/tied.t SHA1 8e4d9b70f24cba19f36a901c8dd18645ab06d236 t/20-unit/Types-TypeTiny/basic.t SHA1 b49a299ffee3a0ccac641e0367ccd48e73f98e1e t/20-unit/Types-TypeTiny/coercion.t SHA1 6109d0372ba9a0e7394ff8aebcea446681410d72 t/20-unit/Types-TypeTiny/meta.t SHA1 2dcf7a442f486d3ec8fef2fdaca9c2479ad26fac t/30-integration/Class-InsideOut/basic.t SHA1 ea41e92d94304eb036c78513e0bb4cc0ada7a158 t/30-integration/Exporter-Tiny/basic.t SHA1 5ce618a88675c26ede3d75959fe284a60a4459cf t/30-integration/Exporter-Tiny/installer.t SHA1 c6fbd75c51b02e0f97a841bf81408574530733d9 t/30-integration/Exporter-Tiny/role-conflict.t SHA1 d8c4413b530f7f0a7a194b2553253211a1e115e4 t/30-integration/Function-Parameters/basic.t SHA1 0b22dabbe027cc0d6e0fe3477677ebc33a301f29 t/30-integration/Kavorka/basic.t SHA1 dfbf1ec5c5f68ecd8b6b4f81cbbcc0625b7dee1f t/30-integration/Moo/basic.t SHA1 64129e0dd285baf3d2a7ef1da82d269bed58373a t/30-integration/Moo/coercion-inlining-avoidance.t SHA1 b552639a413ae840276e4b0958e0da519e6edbe6 t/30-integration/Moo/coercion.t SHA1 4442ff84b3cedc8d2f1aa1f4df5de0d108317a50 t/30-integration/Moo/exceptions.t SHA1 8b0bf43680e86a0993c86ab45e5ce6e09db4f77e t/30-integration/Moo/inflation.t SHA1 35721971431900c03ff1ed50ab6e14c2df6c1b28 t/30-integration/Moo/inflation2.t SHA1 ce832c00487b3839b0547de8156a2ea402018577 t/30-integration/Moops/basic.t SHA1 2f676788e11ad97cad710c08f5c0a40858dd856b t/30-integration/Moops/library-keyword.t SHA1 603a146d01efb5cf652ffc8fc24355224c3df011 t/30-integration/Moose/accept-moose-types.t SHA1 3314e21c4f42bdb1c9583eb3cccfedea111454d3 t/30-integration/Moose/basic.t SHA1 f9faf1d6c037f9fcea2437c934bec47c60e1c144 t/30-integration/Moose/coercion-more.t SHA1 035a79c4f50e36812917517759bb79d1cf45b00b t/30-integration/Moose/coercion.t SHA1 2275e6cb73071edafafca4f3ba55958006998296 t/30-integration/Moose/inflate-then-inline.t SHA1 6ea8e33674ed2033158a284ee52a66308a8b3241 t/30-integration/Moose/native-attribute-traits.t SHA1 a478d51706bbb7e3408240f2beacc9db7b98befc t/30-integration/MooseX-Getopt/coercion.t SHA1 83c7d5943ce038e55bd5fd9a91660b1899b87ed9 t/30-integration/MooseX-Types/basic.t SHA1 8a61ccbf2ebe94c0ad90f94a4b3c7a6255a06ead t/30-integration/MooseX-Types/extending.t SHA1 233be82ed6b12ae6d7864096d030fe16e6e08349 t/30-integration/MooseX-Types/more.t SHA1 51b97790bb80a089b281fb872dc81e19f65cad49 t/30-integration/Mouse/basic.t SHA1 17052679602e83c6cf4b2860cfaa295c9d38adff t/30-integration/Mouse/coercion.t SHA1 a69f190ade8ffd0ae576c33da907fdafd6230376 t/30-integration/MouseX-Types/basic.t SHA1 5a9ba3b6d85d4be1444852cd205d784686b58275 t/30-integration/MouseX-Types/extending.t SHA1 17510f8f0e2491aa8666ff64c9f08d8232e62d7b t/30-integration/Object-Accessor/basic.t SHA1 cf365dacd282ae48865eec869011500f563d60be t/30-integration/Return-Type/basic.t SHA1 5f88261bc1446ebb084072a8a2f405ff6294e88a t/30-integration/Sub-Quote/basic.t SHA1 954612e885c3684954c89f8ca1f9cd5b0f280983 t/30-integration/Sub-Quote/unquote-coercions.t SHA1 9c3784b75f197135876e9bb1c30a9875ea530a13 t/30-integration/Sub-Quote/unquote-constraints.t SHA1 97383ebd5d5b4c72e350e1238c5d4757ebd0579b t/30-integration/Switcheroo/basic.t SHA1 2e52a080e65502ff2f33a42d291e1713007db344 t/30-integration/Type-Tie/basic.t SHA1 708334d74c472aec16dcb5b0405c2f8fe13ea1a6 t/30-integration/Validation-Class-Simple/archaic.t SHA1 529c741c1bd64e034edb40db79459ef8180c5be3 t/30-integration/Validation-Class-Simple/basic.t SHA1 da0bcfaf797a50b7aa769e9e883085b6faea673d t/30-integration/match-simple/basic.t SHA1 a01847d36d518853e8d6c8ab035de5e3dbc902bd t/40-regression/73f51e2d.pl SHA1 7da69658767ec7707de793d6c337f82e133a317e t/40-regression/73f51e2d.t SHA1 1023ea8345bcfdccf5de347f16ad5e89061d65df t/40-regression/gh1.t SHA1 0b2b862c124a8fd4bfb5dd515496fe2b8d495410 t/40-regression/gh14.t SHA1 bd89f7b4accdc2be6c714aa0be2c7f3b7b87942d t/40-regression/rt85911.t SHA1 217b8eff5067ca1db714c05b3324879077a647de t/40-regression/rt86004.t SHA1 22df371f9b24407b912b5360323ef385a4499883 t/40-regression/rt86233.t SHA1 ef4aa628cddc64ab28d1241cd853513fef1cb110 t/40-regression/rt86239.t SHA1 1a8e9ca148b44f06924c6bffaf369737db747926 t/40-regression/rt90096-2.t SHA1 9d0f59bca63d6a651ca2091559e9498529dd89e1 t/40-regression/rt90096.t SHA1 7e51dd0a8d3334cb5332ab0b90858dae4bc0bdaf t/40-regression/rt92571-2.t SHA1 260cc0f1d2fc65cccc1166cc65cfeeddb2884bc5 t/40-regression/rt92571.t SHA1 93226c8e490eabab36c26da28146e0f4ad0679a5 t/40-regression/rt92591.t SHA1 0a4ec28dad687e3a43133eeba4a84e24a2e1f716 t/40-regression/rt94196.t SHA1 60a5be6dd22530cfa5870ab2842dee57e5eb1bc7 t/40-regression/rt97684.t SHA1 3baa1253cfb0988bab6674906032b09eb80eed89 t/40-regression/rt98113.t SHA1 61d9a55bf7678b298fad93f8413580783d133b32 t/40-regression/ttxs-gh1.t SHA1 d358dc633a1c15c5f0aa5db23d0e286d411e5992 t/99-moose-std-types-test.t SHA1 f765f14abcbe280da09d0d3aacca0337760b0683 t/README SHA1 83c445cac3ab13ffe427ec7bf21287ef2824ff8f t/TODO SHA1 05f6d0a8e1baba614a7442e51e47cf1bd66e425a t/lib/BiggerLib.pm SHA1 c99da21d6c6c95b956b8edf2f15d92ffb52d8e4b t/lib/DemoLib.pm SHA1 3eb4a7ac4357ce37ee83611ecccd32dab0a6d5a1 t/mk-test-manifest.pl SHA1 f846fa57aa90c0c55aeee735368cb9dd4015b77a t/not-covered.pl -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iEYEARECAAYFAlk5O84ACgkQzr+BKGoqfTlhjQCcDzMDcRQyr34aA+SI71VCsSa9 gwIAnR2osdkEh6DggABoq0Ux3NslO6NB =75Rw -----END PGP SIGNATURE----- TODO000664001750001750 230213116235452 13065 0ustar00taitai000000000000Type-Tiny-1.002001Type-Tiny 1.002xxx or 1.004000 ============================== * Resolve RT#102457. Error::TypeTiny::Assertion needs a better way of identifying which stack frame to report the error at, or Type::Params needs to mark its compiled subs more clearly. * Resolve RT#121763. Need to figure out the circumstances under which this happens and fix. Type-Tiny 1.004000 ================== * December 2017 release date. * Rewrite Type::Tiny::Manual. * Resolve RT#120226 if HAARG will help me flesh out an API. * Loosen the definition of FileHandle so that it accepts any references where Scalar::Util::openhandle($_) is true, not just unblessed GLOB references. (It also currently accepts blessed references where $_->isa('IO::Handle'). This will not change.) THIS CHANGE IS BACKWARDS INCOMPATIBLE AND DIFFERS FROM MOOSE'S IMPLEMENTATION OF THE SAME-NAMED TYPE CONSTRAINT. YOU ARE HEREBY WARNED! Long-Term ========= * Try to make inlining for ClassName, RoleName, StrMatch, etc more suitable for things like Mite. Perhaps add a separate method to type constraints for generating a string of Perl code that can be compiled and executed without the presence of Type::Tiny and the type library. dist.ini000664001750001750 16213116235452 14023 0ustar00taitai000000000000Type-Tiny-1.002001;; class = 'Dist::Inkt::Profile::TOBYINK' ;; name = 'Type-Tiny' ;; source_for_readme = 'lib/Type/Tiny/Manual.pod' doap.ttl000664001750001750 115346113116235714 14144 0ustar00taitai000000000000Type-Tiny-1.002001@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; cpan-uri:x_IRC ; 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 "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: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.011"^^doap-deps:CpanId; rdfs:comment "Make stuff faster."@en; ], [ doap-deps:on "Ref::Util::XS 0.100"^^doap-deps:CpanId; rdfs:comment "Make stuff faster."@en; ], [ doap-deps:on "Regexp::Util 0.003"^^doap-deps:CpanId; rdfs:comment "Saner serialization of StrMatch type constraints."@en; ], [ doap-deps:on "Sub::Util"^^doap-deps:CpanId; rdfs:comment "This allows Type::Library to name subs nicely."@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.0000"^^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 doap:Version; dc:identifier "Type-Tiny-1.000006"^^xsd:string; dc:issued "2017-01-30"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix, doap-changeset:Tests, doap-changeset:Update; rdfs:label "Fix escaping within q{...} in a test case."; doap-changeset:blame ; doap-changeset:fixes ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "1.000006"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-1.001_000"^^xsd:string; dc:issued "2014-09-07"^^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:Update; rdfs:label "Want Type::Tiny::XS 0.011."; ], [ 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 ; ], [ a doap-changeset:Tests; rdfs:label "Make some of the test case skip_all bits more ambitious; test older versions of Moose and Moo than we were testing before."; ], [ a doap-changeset:Bugfix; rdfs:label "Fix for Type::Registry::DWIM."; doap-changeset:fixes ; doap-changeset:thanks ; ], [ a doap-changeset:Update; rdfs:label "If Sub::Name is unavailable, but the shiny new core Sub::Util is available, then use it instead."; ], [ a doap-changeset:Addition; rdfs:label "Type::Params now provides `compile_named` and `validate_named` functions which do the same thing as `compile` and `validate` but are better for named arguments."; rdfs:comment "Several people have requested this."; ], [ a doap-changeset:Change; rdfs:label "`Type::Utils::dwim_type` now allows more control over fallback behaviours."; ], [ a doap-changeset:Documentation; rdfs:label "Updates to Type::Tiny::Manual::UsingWithMoose, Type::Tiny::Manual::UsingWithMoo, and Type::Tiny::Manual::UsingWithMouse."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "1.001_000"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-1.001_001"^^xsd:string; dc:issued "2014-09-19"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Update; rdfs:label "Prefer Sub::Util over Sub::Name. (The former is smaller.)"; ], [ a doap-changeset:Change; rdfs:label "Lazy-load Text::Balanced in Type::Parser. (Many parses don't even need it.)"; ], [ a doap-changeset:Change; rdfs:label "Lazy-load Type::Tiny::Union in Type::Params."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "1.001_001"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-1.001_002"^^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."; ], [ a doap-changeset:Bugfix; rdfs:label "Inlined version of Types::Standard::Int should check that the value is not a reference."; ], [ a doap-changeset:Change; rdfs:label "Make equals/is_a_type_of/is_subtype_of/is_supertype_of in Type::Tiny::Union work more like Moose::Meta::TypeConstraint::Union."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "1.001_002"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-1.001_003"^^xsd:string; dc:issued "2017-02-02"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Update; rdfs:label "Merge fixes from stable Type-Tiny 1.000006."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "1.001_003"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-1.001_004"^^xsd:string; dc:issued "2017-02-06"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Attempting ArrayRef[Int, Int] or similar now throws an exception."; doap-changeset:blame ; doap-changeset:fixes ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "1.001_004"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-1.001_005"^^xsd:string; dc:issued "2017-04-19"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Tests; rdfs:label "Bundle a test case for GH issue 14."; rdfs:seeAlso ; ], [ a doap-changeset:Change; rdfs:label "Improved error location reporting for Moo"; doap-changeset:blame ; rdfs:seeAlso ; ], [ a doap-changeset:Bugfix, doap-changeset:Tests; rdfs:label "02-api.t should check version of Moose available."; rdfs:seeAlso ; ], [ a doap-changeset:Bugfix, doap-changeset:Documentation; rdfs:label "Fix minor typos in documentation for Types::Standard."; doap-changeset:blame ; rdfs:seeAlso ; ], [ a doap-changeset:Update; rdfs:label "NumericCode now coerces from strings with whitespace in them, like MooseX::Types::Common::Numeric."; doap-changeset:blame ; rdfs:seeAlso ; ], [ a doap-changeset:Bugfix, doap-changeset:Documentation; rdfs:label "Fix variable name typo in documentation for Type::Params."; doap-changeset:blame ; rdfs:seeAlso ; ], [ a doap-changeset:Bugfix, doap-changeset:Tests; rdfs:label "20-unit/Type-Utils/warnings.t should check version of Test::Warnings."; doap-changeset:blame ; rdfs:seeAlso ; ], [ a doap-changeset:Documentation; rdfs:label "Include projected release date for Type::Tiny 1.002000 in NEWS."; rdfs:comment "It's my birthday!"; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "1.001_005"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-1.001_006"^^xsd:string; dc:issued "2017-04-30"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Localize $SIG{__DIE__} in Type::Registry."; doap-changeset:fixes ; ], [ a doap-changeset:Change; rdfs:label "Allow Type::Tiny's `constraint` parameter to be a string of Perl code."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "1.001_006"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; rdfs:label "May the fourth be with you"; dc:identifier "Type-Tiny-1.001_007"^^xsd:string; dc:issued "2017-05-04"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Optimizations for Tuple and StrMatch type constraints from Types::Standard."; ], [ a doap-changeset:Change; rdfs:label "Optimization of Type::Params positional parameter checking for simple cases with no slurpy parameter and no coercions."; ], [ a doap-changeset:Addition; rdfs:label "Type::Params' `multisig` function now sets a variable `${^TYPE_PARAMS_MULTISIG}` to indicate which signature succeeded."; ], [ a doap-changeset:Documentation; rdfs:label "Comparison of Type::Params with new(ish) CPAN module Params::ValidationCompiler."; ], [ a doap-changeset:Documentation; rdfs:label "Show example of how to set defaults for parameters with Type::Params."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "1.001_007"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-1.001_008"^^xsd:string; dc:issued "2017-05-10"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Rearrange the examples directory in the distribution."; ], [ a doap-changeset:Addition; rdfs:label "Named parameter validation benchmarking script."; ], [ a doap-changeset:Addition; rdfs:label "Reduce scope of local $SIG{__DIE__} in Type::Registry."; doap-changeset:thanks ; ], [ a doap-changeset:Bugfix; rdfs:label "Type::Params should make sure Type::Utils is loaded before calling english_list()."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "1.001_008"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-1.001_009"^^xsd:string; dc:issued "2017-05-13"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Use Ref::Util::XS (if it's installed) to speed up certain type checks."; ], [ a doap-changeset:Change; rdfs:label "Rewrite some benchmarking scripts to use Benchmark::Featureset::ParamCheck."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "1.001_009"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; rdfs:label "Puppiversary"; dc:identifier "Type-Tiny-1.001_010"^^xsd:string; dc:issued "2017-05-16"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Tests; rdfs:label "t/00-begin.t will now work around ANDK's apparently broken XS testing environment."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "1.001_010"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-1.001_011"^^xsd:string; dc:issued "2017-05-17"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "Type constraints like Tuple[Int] shouldn't report they have a coercion if Int doesn't have a coercion."; ], [ a doap-changeset:Addition; rdfs:label "Types::Standard now has a CycleTuple type."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "1.001_011"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-1.001_012"^^xsd:string; dc:issued "2017-05-17"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:BackCompat, doap-changeset:Change; rdfs:label "RegexpRef now accepts blessed objects if $object->isa('Regexp') returns true."; rdfs:comment "For compatibility with re::engine::RE2 and similar modules."; ], [ a doap-changeset:Change; rdfs:label "StrMatch will use Regexp::Util (if available) to inline regular expressions more sensibly."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "1.001_012"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; rdfs:label "Kittiversary"; dc:identifier "Type-Tiny-1.001_013"^^xsd:string; dc:issued "2017-05-18"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "StrMatch changes in previous release broke the ability to check type equality between two parameterized StrMatch types under some circumstances. Changed how the hash key for stashing regexp references gets built — is now closer to the old way. This doesn't revert the change in 1.001_012 where regexp checks can be inlined better, but only applies to those regexp references that can't easily be inlined."; ], [ a doap-changeset:Bugfix; rdfs:label "Fixed crazy amount of UTF-8 warnings from Type::Params on Perl 5.6.x and Perl 5.8.x."; doap-changeset:fixes ; doap-changeset:thanks ; rdfs:seeAlso ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "1.001_013"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-1.001_014"^^xsd:string; dc:issued "2017-05-19"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Change; rdfs:label "Include trailing line break at the end of stringified version of some exceptions."; doap-changeset:thanks ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "1.001_014"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-1.001_015"^^xsd:string; dc:issued "2017-05-20"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Bugfix; rdfs:label "Fix HashRef[Str]|Undef|Str parsing on Perl < 5.14."; doap-changeset:fixes ; doap-changeset:thanks , ; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "1.001_015"^^xsd:string. a cpan-uri:DeveloperRelease, doap:Version; dc:identifier "Type-Tiny-1.001_016"^^xsd:string; dc:issued "2017-05-30"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Documentation; rdfs:label "Include page-numbers.pl example"; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "1.001_016"^^xsd:string. a doap:Version; dc:identifier "Type-Tiny-1.002000"^^xsd:string; dc:issued "2017-06-01"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Packaging; rdfs:label "Stable version number."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "1.002000"^^xsd:string. a doap:Version; dc:identifier "Type-Tiny-1.002001"^^xsd:string; dc:issued "2017-06-08"^^xsd:date; doap-changeset:changeset [ doap-changeset:item [ a doap-changeset:Packaging; rdfs:label "Ref::Util::XS 0.100 should be recommended, not 0.200 (which doesn't exist yet)."; doap-changeset:fixes ; ], [ a doap-changeset:Tests; rdfs:label "Skip t/30-integration/Moose/native-attribute-traits.t on older Moose because Test::Moose is broken."; ]; doap-changeset:versus ; ]; doap-changeset:released-by ; doap:file-release ; doap:revision "1.002001"^^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 "Aran Clary Deltac"; foaf:nick "BLUEFEET"; 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 "Karen Etheridge"; foaf:nick "ETHER"; foaf:page . a foaf:Person; foaf:name "Graham Knop"; foaf:nick "HAARG"; foaf:page . a foaf:Person; foaf:name "Dagfinn Ilmari Mannsåker"; foaf:nick "ILMARI"; foaf:page . a foaf:Person; foaf:name "Ingy döt 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 Simões"; 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 "Thomas Sibley"; foaf:nick "TSIBLEY"; foaf:page , . a foaf:Person; foaf:name "Caleb Cushing"; foaf:nick "XENO"; foaf:page . a doap-bugs:Issue; doap-bugs:id "100780"^^xsd:string; doap-bugs:page . a doap-bugs:Issue; doap-bugs:id "101582"^^xsd:string; doap-bugs:page . a doap-bugs:Issue; doap-bugs:id "105299"^^xsd:string; doap-bugs:page . a doap-bugs:Issue; doap-bugs:id "114386"^^xsd:string; doap-bugs:page . a doap-bugs:Issue; doap-bugs:id "121764"^^xsd:string; doap-bugs:page . a doap-bugs:Issue; doap-bugs:id "121981"^^xsd:string; doap-bugs: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 ; doap-tests:regression_test [ a doap-tests:RegressionTest; doap-tests:purpose "The \"too few arguments for type constraint check functions\" error."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/40-regression/rt97684.t"; ]; ]. a doap-bugs:Issue; doap-bugs:id "98113"^^xsd:string; doap-bugs:page ; doap-tests:regression_test [ a doap-tests:RegressionTest; doap-tests:purpose "Test overload fallback"; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/40-regression/rt98113.t"; ]; ]. 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". foaf:mbox ; foaf:name "Peter Valdemar Mørch". foaf:homepage ; foaf:name "André Walker"; foaf:page . foaf:mbox ; foaf:name "Alexandr Ciornii"; foaf:page . foaf:mbox ; foaf:name "Zoffix Znet". foaf:mbox ; foaf:name "Denis Ibaev"; foaf:page . foaf:mbox ; foaf:name "Lucas Buchala"; foaf:page . _: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/Error-TypeTiny/stacktrace.t". [] 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". [] 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". _:B9 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/02-api.t". _:B10 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/03-leak.t". _:B11 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/99-moose-std-types-test.t". [] 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 "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 "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 _:B8; ]; nfo:fileName "lib/Error/TypeTiny.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". [] 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". [] 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". [] 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' brand spanking new 'compile_named' function."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Params/compile-named.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 "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->for_class is automagically populated."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Registry/automagic.t"; ]; ], [ 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 various newish Type::Registry method calls."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Registry/methods.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 Type::Tiny works accepts strings of Perl code as constraints."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Tiny/constraint-strings.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 "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 "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 sane behaviour of 'dwim_type' from Type::Utils when both Moose and Mouse are loaded."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Utils/dwim-both.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 [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Utils/dwim-moose.t"; ]; ], [ 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 [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Utils/dwim-mouse.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Test Type::Utils 'match_on_type' and 'compile_match_on_type' functions."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Utils/match-on-type.t"; ]; ], [ a doap-tests:UnitTest; doap-tests:purpose "Tests warnings raised by Type::Utils."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Type-Utils/warnings.t"; ]; ]; nfo:fileName "lib/Type/Utils.pm"; nfo:programmingLanguage "Perl". [] 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". [] 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 "OK, we need to bite the bullet and lock down coercions on core type constraints and parameterized type constraints."; doap-tests:test_script [ a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/20-unit/Types-Standard/lockdown.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 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"; ]; ], [ 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"; ]; ]; nfo:fileName "lib/Types/TypeTiny.pm"; nfo:programmingLanguage "Perl". _:B12 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Class-InsideOut/basic.t". _:B13 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Exporter-Tiny/basic.t". _:B14 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Exporter-Tiny/installer.t". _:B15 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Exporter-Tiny/role-conflict.t". _:B16 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Function-Parameters/basic.t". _:B17 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Kavorka/basic.t". _:B18 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Moo/basic.t". _:B19 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Moo/coercion-inlining-avoidance.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-more.t". _:B29 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Moose/coercion.t". _:B30 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Moose/inflate-then-inline.t". _:B31 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Moose/native-attribute-traits.t". _:B32 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/MooseX-Getopt/coercion.t". _:B33 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/MooseX-Types/basic.t". _:B34 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/MooseX-Types/extending.t". _:B35 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/MooseX-Types/more.t". _:B36 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Mouse/basic.t". _:B37 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Mouse/coercion.t". _:B38 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/MouseX-Types/basic.t". _:B39 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/MouseX-Types/extending.t". _:B40 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Object-Accessor/basic.t". _:B41 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Return-Type/basic.t". _:B42 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Sub-Quote/basic.t". _:B43 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Sub-Quote/unquote-coercions.t". _:B44 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Sub-Quote/unquote-constraints.t". _:B45 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Switcheroo/basic.t". _:B46 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Type-Tie/basic.t". _:B47 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Validation-Class-Simple/archaic.t". _:B48 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/Validation-Class-Simple/basic.t". _:B49 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/30-integration/match-simple/basic.t". _:B50 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/40-regression/73f51e2d.t". _:B51 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/40-regression/gh1.t". _:B52 a nfo:FileDataObject, nfo:SourceCode; nfo:fileName "t/40-regression/gh14.t". _:B53 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/benchmarking/benchmark-coercion.pl"; nfo:programmingLanguage "Perl". [] a nfo:FileDataObject, nfo:SourceCode; dc:license ; dc:rightsHolder ; nfo:fileName "examples/benchmarking/benchmark-constraints.pl"; nfo:programmingLanguage "Perl". [] a nfo:FileDataObject, nfo:SourceCode; dc:license ; dc:rightsHolder ; nfo:fileName "examples/benchmarking/benchmark-param-validation.pl"; nfo:programmingLanguage "Perl". [] a nfo:FileDataObject, nfo:SourceCode; dc:license ; dc:rightsHolder ; nfo:fileName "examples/benchmarking/benchmark-named-param-validation.pl"; nfo:programmingLanguage "Perl". [] a nfo:FileDataObject, nfo:SourceCode; dc:license ; dc:rightsHolder ; nfo:fileName "examples/benchmarking/versus-scalar-validation.pl"; nfo:programmingLanguage "Perl". [] a nfo:FileDataObject, nfo:SourceCode; dc:license ; dc:rightsHolder ; nfo:fileName "examples/nonempty.pl"; nfo:programmingLanguage "Perl". [] a nfo:FileDataObject, nfo:SourceCode; dc:license ; dc:rightsHolder ; nfo:fileName "examples/page-numbers.pl"; nfo:programmingLanguage "Perl". [] a nfo:FileDataObject, nfo:SourceCode; dc:license ; dc:rightsHolder ; nfo:fileName "examples/datetime-coercions.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 "Check type constraints work with Class::InsideOut."; doap-tests:test_script _:B12. [] a doap-tests:IntegrationTest; doap-tests:purpose "Tests Exporter::Tiny has the features Type::Tiny needs."; doap-tests:test_script _:B13. [] a doap-tests:IntegrationTest; doap-tests:purpose "Tests Type::Library libraries work with Sub::Exporter plugins."; doap-tests:test_script _:B14. [] a doap-tests:IntegrationTest; doap-tests:purpose "Tests exporting to two roles; tries to avoid reporting conflicts."; doap-tests:test_script _:B15. [] a doap-tests:IntegrationTest; doap-tests:purpose "Check type constraints work with Function::Parameters."; doap-tests:test_script _:B16. [] a doap-tests:IntegrationTest; doap-tests:purpose "Checks Type::Tiny works with Kavorka."; doap-tests:test_script _:B17. [] 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 _:B18. [] a doap-tests:IntegrationTest; doap-tests: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."; 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 "Test for the good old \"You cannot coerce an attribute unless its type has a coercion\" error."; doap-tests:test_script _:B28. [] a doap-tests:IntegrationTest; doap-tests:purpose "Check coercions work with Moose; both mutable and immutable classes."; doap-tests:test_script _:B29. [] 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 _:B30. [] a doap-tests:IntegrationTest; doap-tests:purpose "Check type constraints and coercions work with Moose native attibute traits."; doap-tests:test_script _:B31. [] a doap-tests:IntegrationTest; doap-tests:purpose "Check coercions work with MooseX::Getopt; both mutable and immutable classes."; doap-tests:test_script _:B32. [] a doap-tests:IntegrationTest; doap-tests:purpose "Complex checks between Type::Tiny and MooseX::Types."; doap-tests:test_script _:B33. [] a doap-tests:IntegrationTest; doap-tests:purpose "Check that Type::Library can extend an existing MooseX::Types type constraint library."; doap-tests:test_script _:B34. [] 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 _:B35. [] 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 _:B36. [] a doap-tests:IntegrationTest; doap-tests:purpose "Check coercions work with Mouse; both mutable and immutable classes."; doap-tests:test_script _:B37. [] a doap-tests:IntegrationTest; doap-tests:purpose "Complex checks between Type::Tiny and MouseX::Types."; doap-tests:test_script _:B38. [] a doap-tests:IntegrationTest; doap-tests:purpose "Check that Type::Library can extend an existing MooseX::Types type constraint library."; doap-tests:test_script _:B39. [] a doap-tests:IntegrationTest; doap-tests:purpose "Check type constraints work with Object::Accessor."; doap-tests:test_script _:B40. [] a doap-tests:IntegrationTest; doap-tests:purpose "Test that this sort of thing works: sub foo :ReturnType(Int) { ...; }"; doap-tests:test_script _:B41. [] a doap-tests:IntegrationTest; doap-tests:purpose "Check type constraints can be made inlinable using Sub::Quote."; doap-tests:test_script _:B42. [] a doap-tests:IntegrationTest; doap-tests:purpose "Check type coercions can be unquoted Sub::Quote."; doap-tests:test_script _:B43. [] a doap-tests:IntegrationTest; doap-tests:purpose "Check type constraints can be unquoted Sub::Quote."; doap-tests:test_script _:B44. [] a doap-tests:IntegrationTest; doap-tests:purpose "Checks Type::Tiny works with Switcheroo."; doap-tests:test_script _:B45. [] a doap-tests:IntegrationTest; doap-tests:purpose "Test that this sort of thing works: tie my $var, Int;"; doap-tests:test_script _:B46. [] 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 _:B47. [] a doap-tests:IntegrationTest; doap-tests:purpose "Check type constraints Validation::Class::Simple objects can be used as type constraints."; doap-tests:test_script _:B48. [] a doap-tests:IntegrationTest; doap-tests:purpose "Checks Type::Tiny works with match::simple."; doap-tests:test_script _:B49. [] a doap-tests:RegressionTest; doap-tests:purpose "Possible issue causing segfaults on threaded Perl 5.18.x."; doap-tests:test_script _:B50. [] a doap-tests:RegressionTest; doap-tests:purpose "Test that subtypes of Type::Tiny::Class work."; doap-tests:test_script _:B51. [] a doap-tests:RegressionTest; doap-tests:purpose "Test for non-inlined coercions in Moo. The issue that prompted this test was actually invalid, caused by a typo in the bug reporter's code. But I wrote the test case, so I might as well include it."; doap-tests:test_script _:B52. [] a doap-tests:RegressionTest; doap-tests:purpose "Test that was failing with Type::Tiny::XS prior to 0.009."; doap-tests:test_script _:B53. [] a doap-tests:Test; doap-tests:purpose "Test that Type::Tiny and Type::Coercion provide a Moose/Mouse-compatible API."; doap-tests:test_script _:B9. [] 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 _:B10. [] a doap-tests:Test; doap-tests:purpose "Type constraint tests pilfered from the Moose test suite."; doap-tests:test_script _:B11. datetime-coercions.pl000664001750001750 525113116235452 20334 0ustar00taitai000000000000Type-Tiny-1.002001/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); nonempty.pl000664001750001750 205013116235452 16421 0ustar00taitai000000000000Type-Tiny-1.002001/examplesuse v5.14; use strict; use warnings; package Example1 { use Moo; use Sub::Quote 'quote_sub'; use Types::Standard -types; has my_string => ( is => 'ro', isa => Str->where( 'length($_) > 0' ), ); has my_array => ( is => 'ro', isa => ArrayRef->where( '@$_ > 0' ), ); has my_hash => ( is => 'ro', isa => HashRef->where( 'keys(%$_) > 0' ), ); } use Test::More; use Test::Fatal; is( exception { Example1::->new( my_string => 'u' ) }, undef, 'non-empty string, okay', ); isa_ok( exception { Example1::->new( my_string => '' ) }, 'Error::TypeTiny', 'result of empty string', ); is( exception { Example1::->new( my_array => [undef] ) }, undef, 'non-empty arrayref, okay', ); isa_ok( exception { Example1::->new( my_array => [] ) }, 'Error::TypeTiny', 'result of empty arrayref', ); is( exception { Example1::->new( my_hash => { '' => undef } ) }, undef, 'non-empty hashref, okay', ); isa_ok( exception { Example1::->new( my_hash => +{} ) }, 'Error::TypeTiny', 'result of empty hashref', ); done_testing; page-numbers.pl000664001750001750 342313116235453 17143 0ustar00taitai000000000000Type-Tiny-1.002001/examplesuse strict; use warnings; # Type constraint library… BEGIN { package Types::Bookish; $INC{'Types/Bookish.pm'} = __FILE__; use Type::Library -base, -declare => qw( PageNumber PageRangeArray PageRange PageSeriesArray PageSeries ); use Types::Standard qw( Str StrMatch Tuple ArrayRef ); use Types::Common::Numeric qw( PositiveInt ); use Type::Utils -all; declare PageNumber, as PositiveInt, ; declare PageRangeArray, as Tuple[ PageNumber, PageNumber ], constraint => '$_->[0] < $_->[1]', ; declare PageRange, as StrMatch[ qr/\A([0-9]+)-([0-9]+)\z/, PageRangeArray ], ; coerce PageRangeArray from PageRange, q{ [ split /-/, $_ ] }, ; coerce PageRange from PageRangeArray, q{ join q/-/, @$_ }, ; declare PageSeriesArray, as ArrayRef[ PageNumber | PageRange ], constraint => ( # This constraint prevents page series arrays from being in # the wrong order, like [ 20, '4-16', 12 ]. 'my $J = join q/-/, @$_; '. 'my $S = join q/-/, sort { $a <=> $b } split /-/, $J; '. '$S eq $J' ), ; declare PageSeries, as Str, constraint => ( 'my $tmp = [split /\s*,\s*/]; '. PageSeriesArray->inline_check('$tmp') ), ; coerce PageSeriesArray from PageSeries, q{ [ split /\s*,\s*/, $_ ] }, from PageRange, q{ [ $_ ] }, from PageNumber, q{ [ $_ ] }, ; coerce PageSeries from PageSeriesArray, q{ join q[,], @$_ }, ; __PACKAGE__->meta->make_immutable; } use Types::Bookish -types; use Perl::Tidy; PageNumber->assert_valid('4'); PageRangeArray->assert_valid([4, 16]); PageRange->assert_valid('4-16'); PageSeriesArray->assert_valid([ '4-16', 18, 20 ]); PageSeries->assert_valid('4-16, 18, 20'); Perl::Tidy::perltidy( source => \( PageSeries->inline_check('$DATA') ), destination => \( my $tidied ), ); print $tidied; 00-begin.t000664001750001750 365013116235453 14336 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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) = @_; if ($module eq 'Type::Tiny::XS' and $ENV{AUTOMATED_TESTING} and $ENV{PATH} =~ m{\A/home/sand/bin:}) { diag "**** ANDK BROKEN TESTING ENVIRONMENT DETECTED"; diag "**** SKIPPING REPORTING VERSION OF $module"; diag "**** EVERYTHING ELSE SHOULD BE OKAY"; return; } $version = eval "require $module; $module->VERSION" unless defined $version; return diag sprintf(' %-30s undef', $module) unless defined $version; my ($major, $rest) = split /\./, $version; $major =~ s/^v//; 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 216113116235453 14677 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 472713116235453 14033 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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; Moose->VERSION('2.000'); 1; # return true }; my @MOOSE_WANTS = qw( _actually_compile_type_constraint _collect_all_parents _compile_subtype _compile_type _compiled_type_constraint _default_message _has_compiled_type_constraint _inline_check _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 417013116235453 14167 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 4667113116235453 17357 0ustar00taitai000000000000Type-Tiny-1.002001/t=pod =encoding utf-8 =head1 PURPOSE Type constraint tests pilfered from the L test suite. =head1 DEPENDENCIES Test is skipped if Moose 2.0000 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, 2017 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.0000' }; 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, $FAKE_REGEX, ], 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, ], }, 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 124413116235453 13525 0ustar00taitai000000000000Type-Tiny-1.002001/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 6513116235453 13275 0ustar00taitai000000000000Type-Tiny-1.002001/t- full module coverage (according to not-covered.pl) mk-test-manifest.pl000664001750001750 515413116235453 16376 0ustar00taitai000000000000Type-Tiny-1.002001/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 113013116235453 15421 0ustar00taitai000000000000Type-Tiny-1.002001/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; } benchmark-coercions.pl000664001750001750 674013116235453 23127 0ustar00taitai000000000000Type-Tiny-1.002001/examples/benchmarking=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, 2017 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 1144613116235453 23531 0ustar00taitai000000000000Type-Tiny-1.002001/examples/benchmarking=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, 2017 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-named-param-validation.pl000664001750001750 776113116235453 25461 0ustar00taitai000000000000Type-Tiny-1.002001/examples/benchmarking=pod =encoding utf-8 =head1 DESCRIPTION Let's use L to see how fast L is compared with other modules for validating named parameters. (Hint: very fast.) =head1 RESULTS The results of running the script on a fairly low-powered laptop. Each parameter checking implementation is called 250,000 times. The table below displays the average time taken for each call in nanoseconds. =head2 With Type::Tiny::XS Type::Params .................................... 5079 ns (196850/s) Params::ValidateCompiler with Type::Tiny ........ 6599 ns (151515/s) Pure Perl Implementation with Ref::Util::XS ..... 7000 ns (142857/s) Naive Pure Perl Implementation .................. 7560 ns (132275/s) Data::Validator with Mouse ...................... 8440 ns (118483/s) Data::Validator with Type::Tiny ................. 9840 ns (101626/s) Params::ValidateCompiler with Moose ............. 11279 ns (88652/s) Params::ValidateCompiler with Specio ............ 11320 ns (88339/s) Data::Validator with Moose ...................... 18319 ns (54585/s) Params::Check with Type::Tiny ................... 21639 ns (46210/s) Params::Check with coderefs ..................... 28079 ns (35612/s) MooseX::Params::Validate with Moose ............. 48559 ns (20593/s) MooseX::Params::Validate with Type::Tiny ........ 54079 ns (18491/s) =head2 Without Type::Tiny::XS Pure Perl Implementation with Ref::Util::XS ..... 7120 ns (140449/s) Naive Pure Perl Implementation .................. 7520 ns (132978/s) Type::Params .................................... 7960 ns (125628/s) Data::Validator with Mouse ...................... 9000 ns (111111/s) Params::ValidateCompiler with Type::Tiny ........ 9159 ns (109170/s) Params::ValidateCompiler with Moose ............. 10159 ns (98425/s) Params::ValidateCompiler with Specio ............ 11240 ns (88967/s) Data::Validator with Type::Tiny ................. 14240 ns (70224/s) Data::Validator with Moose ...................... 18159 ns (55066/s) Params::Check with Type::Tiny ................... 22039 ns (45372/s) Params::Check with coderefs ..................... 22479 ns (44483/s) MooseX::Params::Validate with Moose ............. 42920 ns (23299/s) MooseX::Params::Validate with Type::Tiny ........ 43360 ns (23062/s) =head1 ANALYSIS Type::Params (using Type::Tiny type constraints) provides the fastest way of checking named parameters for a function, whether or not Type::Tiny::XS is available. Params::ValidationCompiler (also using Type::Tiny type constraints) is very nearly as fast. Params::ValidationCompiler using other type constraints is also quite fast, and when Type::Tiny::XS is not available, Moose and Specio constraints run almost as fast as Type::Tiny constraints. Data::Validator is acceptably fast. Params::Check is fairly slow, and MooseX::Params::Validate very slow. Type::Tiny::XS seems to slow down MooseX::Params::Validate for some strange reason. =head1 DEPENDENCIES To run this script, you will need: L, L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2017 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 v5.12; use strict; use warnings; use Benchmark qw(:hireswallclock timeit); use Benchmark::Featureset::ParamCheck 0.002; use Module::Runtime qw(use_module); my $data = 'Benchmark::Featureset::ParamCheck'->trivial_named_data; my @impl = 'Benchmark::Featureset::ParamCheck'->implementations; my $iter = 250_000; say for map { sprintf( '%s %s %6d ns (%d/s)', $_->[0]->long_name, '.' x (48 - length($_->[0]->long_name)), 1_000_000_000 * $_->[1]->cpu_a / $iter, $iter / $_->[1]->cpu_a, ); } sort { $a->[1]->cpu_a <=> $b->[1]->cpu_a; } map { my $pkg = use_module($_); [ $pkg, timeit 1, sub { $pkg->run_named_check($iter, $data) } ]; } @impl; benchmark-param-validation.pl000664001750001750 750613116235453 24374 0ustar00taitai000000000000Type-Tiny-1.002001/examples/benchmarking=pod =encoding utf-8 =head1 DESCRIPTION Let's use L to see how fast L is compared with other modules for validating positional parameters. (Hint: very fast.) =head1 RESULTS The results of running the script on a fairly low-powered laptop. Each parameter checking implementation is called 250,000 times. The table below displays the average time taken for each call in nanoseconds. =head2 With Type::Tiny::XS Type::Params .................................... 2640 ns (378787/s) Params::ValidateCompiler with Type::Tiny ........ 3120 ns (320512/s) Pure Perl Implementation with Ref::Util::XS ..... 3639 ns (274725/s) Naive Pure Perl Implementation .................. 4600 ns (217391/s) Params::ValidateCompiler with Specio ............ 11719 ns (85324/s) Params::ValidateCompiler with Moose ............. 12079 ns (82781/s) Data::Validator with Mouse ...................... 51760 ns (19319/s) Data::Validator with Type::Tiny ................. 51920 ns (19260/s) Data::Validator with Moose ...................... 52120 ns (19186/s) MooseX::Params::Validate with Moose ............. 83080 ns (12036/s) MooseX::Params::Validate with Type::Tiny ........ 84839 ns (11786/s) =head2 Without Type::Tiny::XS Pure Perl Implementation with Ref::Util::XS ..... 3560 ns (280898/s) Naive Pure Perl Implementation .................. 4479 ns (223214/s) Type::Params .................................... 7879 ns (126903/s) Params::ValidateCompiler with Type::Tiny ........ 8319 ns (120192/s) Params::ValidateCompiler with Specio ............ 11800 ns (84745/s) Params::ValidateCompiler with Moose ............. 12159 ns (82236/s) Data::Validator with Type::Tiny ................. 51039 ns (19592/s) Data::Validator with Moose ...................... 51559 ns (19394/s) Data::Validator with Mouse ...................... 51760 ns (19319/s) MooseX::Params::Validate with Type::Tiny ........ 82800 ns (12077/s) MooseX::Params::Validate with Moose ............. 93160 ns (10734/s) =head1 ANALYSIS Type::Params (using Type::Tiny type constraints) provides the fastest convenient way of checking positional parameters for a function, whether or not Type::Tiny::XS is available. The only way to beat it is to write your own type checking in longhand, but if Type::Tiny::XS is installed, you probably still won't be able to match Type::Params' speed. Params::ValidationCompiler (also using Type::Tiny type constraints) is very nearly as fast. Params::ValidationCompiler using other type constraints is also quite fast, and when Type::Tiny::XS is not available, Moose and Specio constraints run almost as fast as Type::Tiny constraints. Data::Validator and MooseX::Params::Validate are far slower. =head1 DEPENDENCIES To run this script, you will need: L, L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014, 2017 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 v5.12; use strict; use warnings; use Benchmark qw(:hireswallclock timeit); use Benchmark::Featureset::ParamCheck 0.002; use Module::Runtime qw(use_module); my $data = 'Benchmark::Featureset::ParamCheck'->trivial_positional_data; my @impl = 'Benchmark::Featureset::ParamCheck'->implementations; my $iter = 250_000; say for map { sprintf( '%s %s %6d ns (%d/s)', $_->[0]->long_name, '.' x (48 - length($_->[0]->long_name)), 1_000_000_000 * $_->[1]->cpu_a / $iter, $iter / $_->[1]->cpu_a, ); } sort { $a->[1]->cpu_a <=> $b->[1]->cpu_a; } map { my $pkg = use_module($_); $pkg->accept_array ? [ $pkg, timeit 1, sub { $pkg->run_positional_check($iter, @$data) } ] : () } @impl; versus-scalar-validation.pl000664001750001750 400313116235453 24123 0ustar00taitai000000000000Type-Tiny-1.002001/examples/benchmarkinguse 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 Fatal.pm000664001750001750 245513116235453 15464 0ustar00taitai000000000000Type-Tiny-1.002001/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 343313116235453 16231 0ustar00taitai000000000000Type-Tiny-1.002001/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 4332513116235453 15240 0ustar00taitai000000000000Type-Tiny-1.002001/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 1272513116235453 16412 0ustar00taitai000000000000Type-Tiny-1.002001/lib/Errorpackage Error::TypeTiny; use 5.006001; use strict; use warnings; BEGIN { $Error::TypeTiny::AUTHORITY = 'cpan:TOBYINK'; $Error::TypeTiny::VERSION = '1.002001'; } 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||""); } # Moo's Method::Generate::Constructor puts an eval in the stack trace, # that is useless for debugging, so show the stack frame one above. $level++ if ( (caller($level))[1] =~ /^\(eval \d+\)$/ and (caller($level))[3] eq '(eval)' # (caller())[3] is $subroutine ); @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, 2017 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 2034113116235453 16201 0ustar00taitai000000000000Type-Tiny-1.002001/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.002001'; 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, 2017 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 1261513116235453 16236 0ustar00taitai000000000000Type-Tiny-1.002001/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.002001'; 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, 2017 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 5326513116235453 16222 0ustar00taitai000000000000Type-Tiny-1.002001/lib/Typepackage Type::Coercion; use 5.006001; use strict; use warnings; BEGIN { $Type::Coercion::AUTHORITY = 'cpan:TOBYINK'; $Type::Coercion::VERSION = '1.002001'; } 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, 2017 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 3330113116235453 16052 0ustar00taitai000000000000Type-Tiny-1.002001/lib/Typepackage Type::Library; use 5.006001; use strict; use warnings; BEGIN { $Type::Library::AUTHORITY = 'cpan:TOBYINK'; $Type::Library::VERSION = '1.002001'; } 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 $subname; my %already; # prevent renaming established functions sub _subname ($$) { $subname = eval { require Sub::Util } ? \&Sub::Util::set_subname : eval { require Sub::Name } ? \&Sub::Name::subname : 0 if not defined $subname; !$already{refaddr($_[1])}++ and return($subname->(@_)) if $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, 2017 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 6322513116235453 15701 0ustar00taitai000000000000Type-Tiny-1.002001/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.002001'; } use B qw(); use Eval::TypeTiny; use Scalar::Util qw(refaddr); use Error::TypeTiny; use Error::TypeTiny::Assertion; use Error::TypeTiny::WrongNumberOfParameters; use Types::Standard -types; use Types::TypeTiny qw(CodeLike ArrayLike to_TypeTiny); require Exporter::Tiny; our @ISA = 'Exporter::Tiny'; our @EXPORT = qw( compile compile_named ); our @EXPORT_OK = qw( multisig validate validate_named Invocant ); sub english_list { require Type::Utils; goto \&Type::Utils::english_list; } my $QUOTE = ($^V < 5.010 && exists(&B::cstring)) ? \&B::cstring : \&B::perlstring; # is buggy on Perl 5.8 { my $Invocant; sub Invocant () { $Invocant ||= do { require Type::Tiny::Union; require Types::Standard; 'Type::Tiny::Union'->new( name => 'Invocant', type_constraints => [ Types::Standard::Object(), Types::Standard::ClassName(), ], ); }; } } 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, $QUOTE->("$tc"), $i, ); } sub compile { my (@code, %env); push @code, '#placeholder', '#placeholder'; # @code[0,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; my $return_default_list = !!1; $code[0] = 'my (%tmp, $tmp);'; PARAM: for my $param (@_) { if (HashRef->check($param)) { $code[0] = 'my (@R, %tmp, $tmp);'; $return_default_list = !!0; last PARAM; } elsif (not Bool->check($param)) { if ($param->has_coercion) { $code[0] = 'my (@R, %tmp, $tmp);'; $return_default_list = !!0; last PARAM; } } } 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} or Error::TypeTiny::croak("Slurpy parameter malformed") ); 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 %s if $#_ < %d;', $return_default_list ? '@_' : '@R', $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}, $QUOTE->($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}, $QUOTE->($constraint), $varname, $is_slurpy ? 'q{$SLURPY}' : sprintf('q{$_[%d]}', $arg), ); } unless ($return_default_list) { 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, ); } if ($return_default_list) { push @code, '@_;'; } else { 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; } sub compile_named { 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 $had_slurpy; push @code, 'my %in = ((@_==1) && ref($_[0]) eq "HASH") ? %{$_[0]} : (@_ % 2) ? "Error::TypeTiny::WrongNumberOfParameters"->throw(message => "Odd number of elements in hash") : @_;'; while (@_) { ++$arg; my ($name, $constraint) = splice(@_, 0, 2); 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}); ++$is_slurpy; ++$had_slurpy; } else { $is_optional = grep $_->{uniq} == Optional->{uniq}, $constraint->parents; $really_optional = $is_optional && $constraint->parent->{uniq} eq Optional->{uniq} && $constraint->type_parameter; $constraint = $constraint->type_parameter if $really_optional; } unless ($is_optional or $is_slurpy) { push @code, sprintf( 'exists($in{%s}) or "Error::TypeTiny::WrongNumberOfParameters"->throw(message => sprintf "Missing required parameter: %%s", %s);', $QUOTE->($name), $QUOTE->($name), ); } my $need_to_close_if = 0; if ($is_slurpy) { $varname = '\\%in'; } elsif ($is_optional) { push @code, sprintf('if (exists($in{%s})) {', $QUOTE->($name)); push @code, sprintf('$tmp = delete($in{%s});', $QUOTE->($name)); $varname = '$tmp'; ++$need_to_close_if; } else { push @code, sprintf('$tmp = delete($in{%s});', $QUOTE->($name)); $varname = '$tmp'; } if ($constraint->has_coercion) { if ($constraint->coercion->can_be_inlined) { push @code, sprintf( '$tmp = %s;', $constraint->coercion->inline_coercion($varname) ); } else { $env{'@coerce'}[$arg] = $constraint->coercion->compiled_coercion; push @code, sprintf( '$tmp = $coerce[%d]->(%s);', $arg, $varname, ); } $varname = '$tmp'; } if ($constraint->can_be_inlined) { push @code, sprintf( '(%s) or Type::Tiny::_failed_check(%d, %s, %s, varname => %s);', $constraint->inline_check($varname), $constraint->{uniq}, $QUOTE->($constraint), $varname, $is_slurpy ? 'q{$SLURPY}' : sprintf('q{$_{%s}}', $QUOTE->($name)), ); } else { $env{'@check'}[$arg] = $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}, $QUOTE->($constraint), $varname, $is_slurpy ? 'q{$SLURPY}' : sprintf('q{$_{%s}}', $QUOTE->($name)), ); } push @code, sprintf('$R{%s} = %s;', $QUOTE->($name), $varname); push @code, '}' if $need_to_close_if; } if (!$had_slurpy) { push @code, 'keys(%in) and "Error::TypeTiny"->throw(message => sprintf "Unrecognized parameter%s: %s", keys(%in)>1?"s":"", Type::Params::english_list(sort keys %in));' } 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 => undef, # always going to be 1 or 0 max_args => undef, # should be possible to figure out if no slurpy param 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; } my %compiled_named; sub validate_named { my $arr = shift; my $sub = ( $compiled_named{ join ":", map(ref($_)?($_->{uniq}||"\@$_->{slurpy}"):$QUOTE->($_), @_) } ||= compile_named({ 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 $flag = sprintf('${^TYPE_PARAMS_MULTISIG} = %d', $i); 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}; if (defined $sig->{max_args} and defined $sig->{min_args}) { @cond = sprintf('@_ == %s', $sig->{min_args}) if $sig->{max_args} == $sig->{min_args}; } push @code, sprintf('if (%s){', join(' and ', @cond)) if @cond; push @code, sprintf('eval { $r = [ $multi[%d]{closure}->(@_) ]; %s };', $i, $flag); 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 invocant =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) = $deposit_monies_check->(@_); ...; } Not quite as neat, but not awful either. There's a shortcut reducing it to one step: use Type::Params qw( validate validate_named ); 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 compile_named =item validate_named =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; } Of course, some people like to use C for the invocant: sub dump { my $self = shift; state $check = compile( Int ); my ($limit) = $check->(@_); local $Data::Dumper::Maxdepth = $limit; print Data::Dumper::Dumper($self); } =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. Having a slurpy parameter will slightly slow down your checks. =head2 Named Parameters You can use C to accept a hash of named parameters use Type::Params qw(compile_named); use Types::Standard qw( slurpy Dict Ref Optional Int ); sub dump { state $check = compile_named( 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 (hashref) dump( var => $foo, limit => 1 ); # ok (hash) dump( var => $foo ); # ok (no optional parameter) dump( limit => 1 ); # dies Prior to Type::Tiny 1.002000, the recommendation was to use a slurpy C. This still works, though the error messages you get might not be quite so nice, and you don't get the automatic detection of hash versus hashref in the input C<< @_ >>. Oh, and it's usually slower. use Type::Params qw(compile); 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 (hash) dump( var => $foo ); # ok (no optional parameter) dump( limit => 1 ); # dies =head2 Mixed Positional and Named Parameters For this, you can still use the C<< slurpy Dict >> hack... 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<< $_ >>. Having any coercions will slightly slow down your checks. =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. The magic global C<< ${^TYPE_PARAMS_MULTISIG} >> is set to the index of the first signature which 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 ], compile_named( needle => Value, haystack => Ref ), ); 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->(@_); for (${^TYPE_PARAMS_MULTISIG) { return $haystack->[$needle] if $_ == 0; return $haystack->{$needle} if $_ == 1; return $haystack->$needle if $_ == 2; } } get_from(0, \@array); # returns $array[0] get_from('foo', \%hash); # returns $hash{foo} get_from('foo', $obj); # returns $obj->foo =head2 Defaults Type::Params does not currently offer a built-in way to set defaults for a parameter. Setting defaults manually is not especially difficult. sub print_coloured { state $check = compile( Str, Optional[Str] ); my ($text, $colour) = $check->(@_); $colour //= "black"; ...; } I occasionally get requests for this to work: sub print_coloured { state $check = compile( Str, Default[Str, "black"] ); my ($text, $colour) = $check->(@_); ...; } But honestly, I don't find that any clearer. =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 * 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 COMPARISON WITH PARAMS::VALIDATIONCOMPILER L does basically the same thing as L. =over =item * Params::ValidationCompiler and Type::Params are likely to perform fairly similarly. In most cases, recent versions of Type::Params seem to be I faster, but except in very trivial cases, you're unlikely to notice the speed difference. Speed probably shouldn't be a factor when choosing between them. =item * Type::Params's syntax is more compact: state $check = compile(Object, Optional[Int], slurpy ArrayRef); Versus: state $check = validation_for( params => [ { type => Object }, { type => Int, optional => 1 }, { type => ArrayRef, slurpy => 1 }, ], ); =item * L offers defaults. =item * L probably has slightly better exceptions. =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, 2017 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 3230013116235453 15700 0ustar00taitai000000000000Type-Tiny-1.002001/lib/Typepackage Type::Parser; use strict; use warnings; sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak } our $AUTHORITY = 'cpan:TOBYINK'; our $VERSION = '1.002001'; # 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); 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 ($self->{remaining} =~ /\A\s*[q'"]/sm) { require Text::Balanced; if (my $quotelike = Text::Balanced::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, 2017 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 2572613116235453 16272 0ustar00taitai000000000000Type-Tiny-1.002001/lib/Typepackage Type::Registry; use 5.006001; use strict; use warnings; BEGIN { $Type::Registry::AUTHORITY = 'cpan:TOBYINK'; $Type::Registry::VERSION = '1.002001'; } 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 ($library, $types) = @_; $library =~ s/^-/Types::/; { local $SIG{__DIE__} = sub {}; eval "require $library"; }; my %hash; if ($library->isa("Type::Library") or $library eq 'Types::TypeTiny') { $types ||= [qw/-types/]; ArrayLike->check($types) or _croak("Expected arrayref following '%s'; got %s", $library, $types); $library->import({into => \%hash}, @$types); $hash{$_} = &{$hash{$_}}() for keys %hash; } elsif ($library->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", $library); require Moose::Util::TypeConstraints; my $moosextypes = $library->type_storage; for my $name (sort keys %$moosextypes) { my $tt = to_TypeTiny( Moose::Util::TypeConstraints::find_type_constraint($moosextypes->{$name}) ); $hash{$name} = $tt; } } elsif ($library->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", $library); require Mouse::Util::TypeConstraints; my $moosextypes = $library->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", $library); } 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; { local $SIG{__DIE__} = sub {}; 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, 2017 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 13726513116235453 15427 0ustar00taitai000000000000Type-Tiny-1.002001/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.002001'; $Type::Tiny::XS_VERSION = '0.011'; } 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 }; }; sub __warn__ { my ($msg, $thing) = @_==2 ? @_ : (Thing => @_); my $string = do { blessed($thing) && $thing->isa('Type::Tiny::Union') ? sprintf('Union[%s]', join q{, }, map $_->name, @{$thing->type_constraints}) : blessed($thing) && $thing->isa('Type::Tiny') ? $thing->name : blessed($thing) && $thing->isa('Type::Tiny::_HalfOp') ? sprintf('HalfOp[ q{%s}, %s, %s ]', $thing->{op}, $thing->{type}->name, $thing->{param}) : !defined($thing) ? 'NIL' : "$thing" }; warn "$msg => $string\n"; $thing; } 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 && $_[2]) { if (blessed $tc[0]) { if (blessed $tc[0] eq "Type::Tiny::_HalfOp") { my $type = $tc[0]->{type}; my $param = $tc[0]->{param}; my $op = $tc[0]->{op}; require Type::Tiny::Union; return "Type::Tiny::_HalfOp"->new( $op, $param, "Type::Tiny::Union"->new(type_constraints => [$type, $tc[1]]), ); } } elsif (ref $tc[0] eq 'ARRAY') { require Type::Tiny::_HalfOp; return "Type::Tiny::_HalfOp"->new('|', @tc); } } require Type::Tiny::Union; return "Type::Tiny::Union"->new(type_constraints => \@tc) }, q(&) => sub { my @tc = _swap @_; if (!_FIXED_PRECEDENCE && $_[2]) { if (blessed $tc[0]) { if (blessed $tc[0] eq "Type::Tiny::_HalfOp") { my $type = $tc[0]->{type}; my $param = $tc[0]->{param}; my $op = $tc[0]->{op}; require Type::Tiny::Intersection; return "Type::Tiny::_HalfOp"->new( $op, $param, "Type::Tiny::Intersection"->new(type_constraints => [$type, $tc[1]]), ); } } elsif (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 { not $_[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; my $subname; sub new { my $class = shift; my %params = (@_==1) ? %{$_[0]} : @_; if (exists $params{constraint} and not ref $params{constraint} and not exists $params{constraint_generator} and not exists $params{inline_generator}) { my $code = $params{constraint}; $params{constraint} = Eval::TypeTiny::eval_closure( source => sprintf('sub ($) { %s }', $code), description => "anonymous check", ); $params{inlined} ||= sub { my ($type) = @_; my $inlined = $_ eq '$_' ? "do { $code }" : "do { local \$_ = $_; $code }"; $type->has_parent ? (undef, $inlined) : $inlined; }; } 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}) { $subname = eval { require Sub::Util } ? \&Sub::Util::set_subname : eval { require Sub::Name } ? \&Sub::Name::subname : 0 if not defined $subname; if ($subname) { $subname->( sprintf("%s::my_%s", $self->qualified_name, $_), $params{my_methods}{$_}, ) for keys %{$params{my_methods}}; } } 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). Alternatively, a string of Perl code checking C<< $_ >> can be passed as a parameter to the constructor, and will be converted to a coderef. 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. If C (above) is a string, it will be able to. =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}) } Like the C<< constraint >> attribute, this will accept a string of Perl code: HashRef->where('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, 2017 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 6370313116235453 15557 0ustar00taitai000000000000Type-Tiny-1.002001/lib/Typepackage Type::Utils; use 5.006001; use strict; use warnings; BEGIN { $Type::Utils::AUTHORITY = 'cpan:TOBYINK'; $Type::Utils::VERSION = '1.002001'; } 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 (my $assume = $self->{"~~assume"} and $_[0] =~ /[A-Z_a-z][0-9A-Z_a-z]*(?:::[0-9A-Z_a-z]+)*/) { my @methods = ref($assume) ? @$assume : $assume; for my $method (@methods) { $r = $self->$method(@_); return $r if $r; } } return; } sub lookup_via_moose { my $self = shift; if ($INC{'Moose.pm'}) { require Moose::Util::TypeConstraints; require Types::TypeTiny; my $r = Moose::Util::TypeConstraints::find_type_constraint($_[0]); return Types::TypeTiny::to_TypeTiny($r) if defined $r; } return; } sub lookup_via_mouse { my $self = shift; if ($INC{'Mouse.pm'}) { require Mouse::Util::TypeConstraints; require Types::TypeTiny; my $r = Mouse::Util::TypeConstraints::find_type_constraint($_[0]); return Types::TypeTiny::to_TypeTiny($r) if defined $r; } 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 $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')) { $r = $self->lookup_via_moose(@_); return $r if $r; } elsif ($meta and $meta->isa('Mouse::Meta::Module')) { $r = $self->lookup_via_mouse(@_); return $r if $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{fallback} || [ qw/ lookup_via_moose lookup_via_mouse /, $opts{does} ? 'make_role_type' : 'make_class_type', ]; local $@ = undef; my $type; unless (eval { $type = $dwimmer->lookup($string); 1 }) { my $e = $@; die($e) unless $e =~ /not a known type constraint/; } $type; } 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 standard type constraint names. If none of the above yields a type constraint, and the caller class is a Moose-based class, then C attempts to look the type constraint up in the Moose type registry. If it's a Mouse-based class, then the Mouse type registry is used instead. If no type constraint can be found via these normal methods, several fallbacks are available: =over =item C Lookup in Moose registry even if caller is non-Moose class. =item C Lookup in Mouse registry even if caller is non-Mouse class. =item C Create a new Type::Tiny::Class constraint. =item C Create a new Type::Tiny::Role constraint. =back You can alter which should be attempted, and in which order, by passing an option to C: my $type = Type::Utils::dwim_type( "ArrayRef[Int]", fallback => [ "lookup_via_mouse" , "make_role_type" ], ); For historical reasons, by default the fallbacks attempted are: lookup_via_moose, lookup_via_mouse, make_class_type You may set C to an empty arrayref to avoid using any of these fallbacks. You can specify an alternative for the caller using the C option. my $type = dwim_type("ArrayRef", for => "Moose::Object"); 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, 2017 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 11756713116235453 16432 0ustar00taitai000000000000Type-Tiny-1.002001/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.002001'; } 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 $HAS_RUXS = eval { require Ref::Util::XS; Ref::Util::XS::->VERSION(0.100); 1; }; 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 !ref($_[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 => $HAS_RUXS ? sub { "Ref::Util::XS::is_plain_coderef($_[1])" } : sub { "ref($_[1]) eq 'CODE'" }, }); my $_regexp = $meta->$add_core_type({ name => "RegexpRef", parent => $_ref, constraint => sub { ref($_) && !!re::is_regexp($_) or blessed($_) && $_->isa('Regexp') }, inlined => sub { my $v = $_[1]; "ref($v) && !!re::is_regexp($v) or Scalar::Util::blessed($v) && $v\->isa('Regexp')" }, }); $meta->$add_core_type({ name => "GlobRef", parent => $_ref, constraint => sub { ref $_ eq "GLOB" }, inlined => $HAS_RUXS ? sub { "Ref::Util::XS::is_plain_globref($_[1])" } : 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 => $HAS_RUXS ? sub { "Ref::Util::XS::is_plain_arrayref($_[1])" } : 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 => $HAS_RUXS ? sub { "Ref::Util::XS::is_plain_hashref($_[1])" } : 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 => $HAS_RUXS ? sub { "Ref::Util::XS::is_blessed_ref($_[1])" } : 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 => "CycleTuple", parent => $_arr, name_generator => sub { my ($s, @a) = @_; sprintf('%s[%s]', $s, join q[,], @a); }, constraint_generator => LazyLoad(CycleTuple => 'constraint_generator'), inline_generator => LazyLoad(CycleTuple => 'inline_generator'), deep_explanation => LazyLoad(CycleTuple => 'deep_explanation'), coercion_generator => LazyLoad(CycleTuple => '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; my $has_regexp_util; my $serialize_regexp = sub { $has_regexp_util = eval { require Regexp::Util; Regexp::Util->VERSION('0.003'); 1; } || 0 unless defined $has_regexp_util; my $re = shift; my $serialized; if ($has_regexp_util) { $serialized = eval { Regexp::Util::serialize_regexp($re) }; } if (!$serialized) { my $key = sprintf('%s|%s', ref($re), $re); $_StrMatch{$key} = $re; $serialized = sprintf('$Types::Standard::_StrMatch{%s}', B::perlstring($key)); } return $serialized; }; $meta->add_type({ name => "StrMatch", parent => $_str, constraint_generator => sub { return $meta->get_type('StrMatch') unless @_; my ($regexp, $checker) = @_; $_regexp->check($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) = @_; if ($checker) { return unless $checker->can_be_inlined; my $serialized_re = $regexp->$serialize_regexp; return sub { my $v = $_[1]; sprintf "!ref($v) and do { my \$m = [$v =~ %s]; %s }", $serialized_re, $checker->inline_check('$m'), ; }; } else { my $regexp_string = "$regexp"; if ($regexp_string =~ /\A\(\?\^u?:(\.+)\)\z/) { my $length = length $1; return sub { "!ref($_) and length($_)>=$length" }; } if ($regexp_string =~ /\A\(\?\^u?:\\A(\.+)\\z\)\z/) { my $length = length $1; return sub { "!ref($_) and length($_)==$length" }; } my $serialized_re = $regexp->$serialize_regexp; return sub { my $v = $_[1]; "!ref($v) and $v =~ $serialized_re"; }; } }, }); $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 reference where C<< re::is_regexp($value) >> is true, or a blessed reference where C<< $value->isa("Regexp") >> is true. =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 a 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 a 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. Although the following are essentially equivalent checks, the former should run a lot faster: Tuple[Int, slurpy Any] Tuple[Int, slurpy ArrayRef] =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 /]), ], ]; On certain versions of Perl, type constraints of the forms C<< StrMatch[qr/../ >> and C<< StrMatch[qr/\A..\z/ >> with any number of intervening dots can be optimized to simple length checks. =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". =item C<< CycleTuple[`a] >> Similar to Tuple, but cyclical. CycleTuple[Int, HashRef] will allow C<< [1,{}] >> and C<< [1,{},2,{}] >> but disallow C<< [1,{},2] >> and C<< [1,{},2,[]] >>. I think you understand CycleTuples already. Currently C and C parameters are forbidden. There are fairly limited use cases for them, and it's not exactly clear what they should mean. The following is an efficient way of checking for an even-sized arrayref: CycleTuple[Any, Any] The following is an arrayref which would be suitable for coercing to a hashref: CycleTuple[Str, Any] All the examples so far have used two parameters, but the following is also a possible CycleTuple: CycleTuple[Str, Int, HashRef] This will be an arrayref where the 0th, 3rd, 6th, etc values are strings, the 1st, 4th, 7th, etc values are integers, and the 2nd, 5th, 8th, etc values are hashrefs. =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, 2017 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 2500213116235453 16415 0ustar00taitai000000000000Type-Tiny-1.002001/lib/Typespackage Types::TypeTiny; use strict; use warnings; our $AUTHORITY = 'cpan:TOBYINK'; our $VERSION = '1.002001'; 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("can_be_inlined") && $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, 2017 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 115613116235453 16745 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 125013116235453 16570 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 154213116235453 16113 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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; gh14.t000664001750001750 266113116235453 16202 0ustar00taitai000000000000Type-Tiny-1.002001/t/40-regression=pod =encoding utf-8 =head1 PURPOSE Test for non-inlined coercions in Moo. The issue that prompted this test was actually invalid, caused by a typo in the bug reporter's code. But I wrote the test case, so I might as well include it. =head1 SEE ALSO L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2017 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.006' }; { package FinancialTypes; use Type::Library -base; use Type::Utils -all; BEGIN { extends "Types::Standard" }; declare 'BankAccountNo', as Str, where { /^\d{26}$/ or /^[A-Z]{2}\d{18,26}$/ or /^\d{8}-\d+(-\d+)+$/ }, message { "Bad account: $_"}; coerce 'BankAccountNo', from Str, via { $_ =~ s{\s+}{}g; $_; }; } { package BankAccount; use Moo; has account_number => ( is => 'ro', required => !!1, isa => FinancialTypes::BankAccountNo(), coerce => FinancialTypes::BankAccountNo()->coercion, ); } my $x; my $e = exception { $x = BankAccount::->new( account_number => "10 2030 4050 1111 2222 3333 4444" ); }; is($e, undef); is($x->account_number, "10203040501111222233334444"); done_testing(); rt85911.t000664001750001750 220713116235453 16470 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 512213116235453 16461 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 202013116235453 16457 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 231513116235453 16474 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 157213116235453 16633 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 136413116235453 16473 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 130213116235453 16622 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 233413116235453 16471 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 241713116235453 16475 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 157313116235453 16502 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 201713116235453 16501 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 156113116235453 16470 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 225213116235453 17112 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 345113116235453 15601 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 144413116235453 15266 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 344313116235453 20556 0ustar00taitai000000000000Type-Tiny-1.002001/lib/Devel/TypeTinypackage Devel::TypeTiny::Perl56Compat; use 5.006; use strict; use warnings; our $AUTHORITY = 'cpan:TOBYINK'; our $VERSION = '1.002001'; #### 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"]; }; } unless (exists &B::cstring) { *B::cstring = \&B::perlstring; } push @B::EXPORT_OK, qw( perlstring cstring ); #### 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, 2017 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 273313116235453 20561 0ustar00taitai000000000000Type-Tiny-1.002001/lib/Devel/TypeTinypackage Devel::TypeTiny::Perl58Compat; use 5.006; use strict; use warnings; our $AUTHORITY = 'cpan:TOBYINK'; our $VERSION = '1.002001'; #### 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, 2017 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 1060013116235453 20347 0ustar00taitai000000000000Type-Tiny-1.002001/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.002001'; } 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\n" 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, 2017 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 351313116235453 20643 0ustar00taitai000000000000Type-Tiny-1.002001/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.002001'; } 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, 2017 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 503613116235453 23145 0ustar00taitai000000000000Type-Tiny-1.002001/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.002001'; } 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, 2017 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 366713116235453 17637 0ustar00taitai000000000000Type-Tiny-1.002001/lib/Reply/Pluginpackage Reply::Plugin::TypeTiny; use strict; use warnings; BEGIN { $Reply::Plugin::TypeTiny::AUTHORITY = 'cpan:TOBYINK'; $Reply::Plugin::TypeTiny::VERSION = '1.002001'; }; 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, 2017 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 510713116235453 20100 0ustar00taitai000000000000Type-Tiny-1.002001/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.002001'; } 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, 2017 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 557213116235453 17270 0ustar00taitai000000000000Type-Tiny-1.002001/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.002001'; } 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, 2017 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 1777713116235453 16461 0ustar00taitai000000000000Type-Tiny-1.002001/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.002001'; } 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, 2017 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 1130113116235453 16253 0ustar00taitai000000000000Type-Tiny-1.002001/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.002001'; } 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, 2017 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 1075613116235453 16306 0ustar00taitai000000000000Type-Tiny-1.002001/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.002001'; } 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, 2017 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 1215613116235453 20044 0ustar00taitai000000000000Type-Tiny-1.002001/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.002001'; } 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, 2017 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 1426613116235453 16765 0ustar00taitai000000000000Type-Tiny-1.002001/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.000000 is recommended. If using Type::Tiny with L, then at least Moose 2.0000 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, 2017 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 1004513116235453 16272 0ustar00taitai000000000000Type-Tiny-1.002001/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.002001'; } 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, 2017 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 1756213116235453 16474 0ustar00taitai000000000000Type-Tiny-1.002001/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.002001'; } 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 ]; } sub equals { my ($self, $other) = Type::Tiny::_loose_to_TypeTiny(@_); return unless blessed($self) && $self->isa("Type::Tiny"); return unless blessed($other) && $other->isa("Type::Tiny"); return !!1 if $self->SUPER::equals($other); return !!0 unless $other->isa(__PACKAGE__); my @self_constraints = @{ $self->type_constraints }; my @other_constraints = @{ $other->type_constraints }; return !!0 unless @self_constraints == @other_constraints; constraint: foreach my $constraint ( @self_constraints ) { for ( my $i = 0; $i < @other_constraints; $i++ ) { if ( $constraint->equals($other_constraints[$i]) ) { splice @other_constraints, $i, 1; next constraint; } } } @other_constraints == 0; } sub is_a_type_of { my ($self, $other) = Type::Tiny::_loose_to_TypeTiny(@_); return unless blessed($self) && $self->isa("Type::Tiny"); return unless blessed($other) && $other->isa("Type::Tiny"); return !!1 if $self->SUPER::is_a_type_of($other); for my $tc (@{ $self->type_constraints }) { return !!0 unless $tc->is_a_type_of($other); } return !!1; } sub is_subtype_of { my ($self, $other) = Type::Tiny::_loose_to_TypeTiny(@_); return unless blessed($self) && $self->isa("Type::Tiny"); return unless blessed($other) && $other->isa("Type::Tiny"); return !!1 if $self->SUPER::is_subtype_of($other); for my $tc (@{ $self->type_constraints }) { return !!0 unless $tc->is_subtype_of($other); } return !!1; } sub is_supertype_of { my ($self, $other) = Type::Tiny::_loose_to_TypeTiny(@_); return unless blessed($self) && $self->isa("Type::Tiny"); return unless blessed($other) && $other->isa("Type::Tiny"); return !!1 if $self->SUPER::is_supertype_of($other); for my $tc (@{ $self->type_constraints }) { return !!1 if $tc->equals($other); return !!1 if $tc->is_supertype_of($other); } return !!0; } 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, 2017 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 326313116235453 16665 0ustar00taitai000000000000Type-Tiny-1.002001/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.002001'; } 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, 2017 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 1066713116235453 17475 0ustar00taitai000000000000Type-Tiny-1.002001/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.002001'; } 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, 2017 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 1234313116235453 17332 0ustar00taitai000000000000Type-Tiny-1.002001/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.002001'; } 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:][:space:]]//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, 2017 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 1072513116235453 20111 0ustar00taitai000000000000Type-Tiny-1.002001/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.002001'; } 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"); _croak("Only one parameter to ArrayRef[`a] expected; got @{[ 1 + @_ ]}. Did you mean to use Tuple[`a]?") if @_; 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]; my $p = Types::Standard::ArrayRef->inline_check($v); "$p 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, 2017 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. CycleTuple.pm000664001750001750 1422213116235453 20443 0ustar00taitai000000000000Type-Tiny-1.002001/lib/Types/Standardpackage Types::Standard::CycleTuple; use 5.006001; use strict; use warnings; BEGIN { $Types::Standard::CycleTuple::AUTHORITY = 'cpan:TOBYINK'; $Types::Standard::CycleTuple::VERSION = '1.002001'; } use Type::Tiny (); use Types::Standard (); use Types::TypeTiny (); sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak } my $_Optional = Types::Standard::Optional; my $_arr = Types::Standard::ArrayRef; no warnings; my $cycleuniq = 0; sub __constraint_generator { my @params = map { ref($_) eq 'HASH' and exists($_->{slurpy}) and _croak("Parameters to CycleTuple[`a] cannot be slurpy"); my $param = Types::TypeTiny::to_TypeTiny($_); Types::TypeTiny::TypeTiny->check($param) or _croak("Parameter to CycleTuple[`a] expected to be a type constraint; got $param"); $param; } @_; my $count = @params; my $tuple = Types::Standard::Tuple()->of(@params); _croak("Parameters to CycleTuple[`a] cannot be optional") if grep !!$_->is_strictly_a_type_of($_Optional), @params; sub { my $value = shift; return unless $_arr->check($value); return if @$value % $count; my $i = 0; while ($i < $#$value) { my $tmp = [@$value[ $i .. $i+$count-1 ]]; return unless $tuple->check($tmp); $i += $count; } !!1; } } sub __inline_generator { my @params = map { my $param = Types::TypeTiny::to_TypeTiny($_); Types::TypeTiny::TypeTiny->check($param) or _croak("Parameter to CycleTuple[`a] expected to be a type constraint; got $param"); $param; } @_; my $count = @params; my $tuple = Types::Standard::Tuple()->of(@params); return unless $tuple->can_be_inlined; sub { $cycleuniq++; my $v = $_[1]; my @checks = $_arr->inline_check($v); push @checks, sprintf( 'not(@%s %% %d)', ($v=~/\A\$[a-z0-9_]+\z/i ? $v : "{$v}"), $count, ); push @checks, sprintf( 'do { my $cyclecount%d = 0; my $cycleok%d = 1; while ($cyclecount%d < $#{%s}) { my $cycletmp%d = [@{%s}[$cyclecount%d .. $cyclecount%d+%d]]; unless (%s) { $cycleok%d = 0; last; }; $cyclecount%d += %d; }; $cycleok%d; }', $cycleuniq, $cycleuniq, $cycleuniq, $v, $cycleuniq, $v, $cycleuniq, $cycleuniq, $count - 1, $tuple->inline_check("\$cycletmp$cycleuniq"), $cycleuniq, $cycleuniq, $count, $cycleuniq, ) if grep { $_->inline_check('$xyz') ne '(!!1)' } @params; join(' && ', @checks); } } sub __deep_explanation { my ($type, $value, $varname) = @_; my @constraints = map Types::TypeTiny::to_TypeTiny($_), @{ $type->parameters }; if (@$value % @constraints) { return [ sprintf('"%s" expects a multiple of %d values in the array', $type, scalar(@constraints)), sprintf('%d values found', scalar(@$value)), ]; } for my $i (0 .. $#$value) { my $constraint = $constraints[$i % @constraints]; next if $constraint->check($value->[$i]); return [ sprintf('"%s" constrains value at index %d of array with "%s"', $type, $i, $constraint), @{ $constraint->validate_explain($value->[$i], sprintf('%s->[%s]', $varname, $i)) }, ]; } # This should never happen... return; # uncoverable statement } my $label_counter = 0; sub __coercion_generator { my ($parent, $child, @tuple) = @_; my $child_coercions_exist = 0; my $all_inlinable = 1; for my $tc (@tuple) { $all_inlinable = 0 if !$tc->can_be_inlined; $all_inlinable = 0 if $tc->has_coercion && !$tc->coercion->can_be_inlined; $child_coercions_exist++ if $tc->has_coercion; } return unless $child_coercions_exist; my $C = "Type::Coercion"->new(type_constraint => $child); if ($all_inlinable) { $C->add_type_coercions($parent => Types::Standard::Stringable { my $label = sprintf("CTUPLELABEL%d", ++$label_counter); my $label2 = sprintf("CTUPLEINNER%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 scalar(@$orig) %% %d != 0;', $label, scalar @tuple); push @code, sprintf('my $%s = 0; while ($%s < @$orig) {', $label2, $label2); for my $i (0 .. $#tuple) { my $ct = $tuple[$i]; my $ct_coerce = $ct->has_coercion; push @code, sprintf( 'do { $tmp = %s; (%s) ? ($new[$%s + %d]=$tmp) : (($return_orig=1), last %s) };', $ct_coerce ? $ct->coercion->inline_coercion("\$orig->[\$$label2 + $i]") : "\$orig->[\$$label2 + $i]", $ct->inline_check('$tmp'), $label2, $i, $label, ); } push @code, sprintf('$%s += %d;', $label2, scalar(@tuple)); push @code, '}'; push @code, '}'; push @code, '$return_orig ? $orig : \\@new'; push @code, '}'; "@code"; }); } else { $C->add_type_coercions( $parent => sub { my $value = @_ ? $_[0] : $_; if (scalar(@$value) % scalar(@tuple) != 0) { return $value; } my @new; for my $i (0 .. $#$value) { my $ct = $tuple[$i % @tuple]; my $x = $ct->has_coercion ? $ct->coerce($value->[$i]) : $value->[$i]; return $value unless $ct->check($x); $new[$i] = $x; } return \@new; }, ); }; return $C; } 1; __END__ =pod =encoding utf-8 =head1 NAME Types::Standard::CycleTuple - internals for the Types::Standard CycleTuple 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) 2017 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 2223313116235453 17256 0ustar00taitai000000000000Type-Tiny-1.002001/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.002001'; } 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 ", Types::Standard::HashRef->inline_check($h), ( $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; my $child_coercions_exist = 0; 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; $child_coercions_exist++ if $tc->has_coercion; } $all_inlinable = 0 if $slurpy && !$slurpy->can_be_inlined; $all_inlinable = 0 if $slurpy && $slurpy->has_coercion && !$slurpy->coercion->can_be_inlined; $child_coercions_exist++ if $slurpy && $slurpy->has_coercion; return unless $child_coercions_exist; 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), 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, 2017 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 1061713116235453 17716 0ustar00taitai000000000000Type-Tiny-1.002001/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.002001'; } 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]; my $p = Types::Standard::HashRef->inline_check($v); "$p 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, 2017 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 1305413116235453 17111 0ustar00taitai000000000000Type-Tiny-1.002001/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.002001'; } 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]; my $p = Types::Standard::HashRef->inline_check($h); "$p 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, 2017 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 663213116235453 20222 0ustar00taitai000000000000Type-Tiny-1.002001/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.002001'; } 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, 2017 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 2260213116235453 17464 0ustar00taitai000000000000Type-Tiny-1.002001/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.002001'; } 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 ", Types::Standard::ArrayRef->inline_check($v), ( (scalar @constraints == $min and not $slurpy) ? "\@{$v} == $min" : ( "\@{$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\->[$_]"); $inline eq '(!!1)' ? () : ( $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 $slurpy; if (exists $tuple[-1] and ref $tuple[-1] eq "HASH") { $slurpy = pop(@tuple)->{slurpy}; } my $child_coercions_exist = 0; 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; $child_coercions_exist++ if $tc->has_coercion; } return unless $child_coercions_exist; my $C = "Type::Coercion"->new(type_constraint => $child); 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), 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, 2017 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 115713116235453 22355 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 117313116235453 22355 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 210213116235453 20157 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 155713116235453 21237 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 2477613116235453 22171 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 }[0..1] ], [ '"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 !ref($_) 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 303513116235453 22441 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 466413116235453 24752 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 623713116235453 17772 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 736713116235453 22074 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 433113116235453 21275 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 370013116235453 20012 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 227513116235453 20537 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 317313116235453 20540 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 751713116235453 20002 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 247513116235453 20534 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 325513116235453 20217 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 256213116235453 20523 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 1112213116235453 21560 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 146613116235453 21061 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 212613116235453 23160 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 335013116235453 21675 0ustar00taitai000000000000Type-Tiny-1.002001/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.0000; otherwise skipped. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014, 2017 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::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 317213116235453 22132 0ustar00taitai000000000000Type-Tiny-1.002001/t/20-unit/Type-Coercion-FromMoose=pod =encoding utf-8 =head1 PURPOSE Checks crazy Type::Coercion::FromMoose errors. =head1 DEPENDENCIES Moose 2.0000; otherwise skipped. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014, 2017 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 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 503413116235453 21060 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 236213116235453 20056 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 223113116235453 20064 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 546113116235453 21051 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 222213116235453 17163 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 165513116235453 17203 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 453613116235453 17726 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 204313116235453 20004 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 164313116235453 20020 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 303213116235453 17627 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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; compile-named.t000664001750001750 1654613116235453 21137 0ustar00taitai000000000000Type-Tiny-1.002001/t/20-unit/Type-Params=pod =encoding utf-8 =head1 PURPOSE Test L' brand spanking new C function. =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_named validate_named); use Types::Standard -types, "slurpy"; use Type::Utils; use Scalar::Util qw(refaddr); sub simple_test { my ($name, @spec) = @_; local $Test::Builder::Level = $Test::Builder::Level + 1; subtest $name => sub { _simple_test( validate_named => sub { validate_named(\@_, @spec) } ); _simple_test( compile_named => compile_named(@spec) ); }; } sub slurpy_test { my ($name, @spec) = @_; local $Test::Builder::Level = $Test::Builder::Level + 1; subtest $name => sub { _slurpy_test( validate_named => sub { validate_named(\@_, @spec) } ); _slurpy_test( compile_named => compile_named(@spec) ); }; } sub _simple_test { my ($name, $check) = @_; local $Test::Builder::Level = $Test::Builder::Level + 1; subtest $name, sub { is_deeply( $check->( foo => 3, bar => 42 ), { foo => 3, bar => 42 }, 'accept a hash', ); is_deeply( $check->( foo => 3, bar => 42, baz => [1..3] ), { foo => 3, bar => 42, baz => [1..3] }, 'accept a hash, with optional parameter', ); is_deeply( $check->( foo => 3.1, bar => 42 ), { foo => 3, bar => 42 }, 'accept a hash, and coerce', ); is_deeply( $check->( foo => 3.1, bar => 42, baz => [1..3, 4.2] ), { foo => 3, bar => 42, baz => [1..4] }, 'accept a hash, with optional parameter, and coerce', ); is_deeply( $check->({ foo => 3, bar => 42 }), { foo => 3, bar => 42 }, 'accept a hashref', ); is_deeply( $check->({ foo => 3, bar => 42, baz => [1..3] }), { foo => 3, bar => 42, baz => [1..3] }, 'accept a hashref, with optional parameter', ); is_deeply( $check->({ foo => 3.1, bar => 42 }), { foo => 3, bar => 42 }, 'accept a hashref, and coerce', ); is_deeply( $check->({ foo => 3.1, bar => 42, baz => [1..3, 4.2] }), { foo => 3, bar => 42, baz => [1..4] }, 'accept a hashref, with optional parameter, and coerce', ); like( exception { $check->({ foo => [], bar => 42 }) }, qr/^Reference \[\] did not pass type constraint/, 'bad "foo" parameter', ); like( exception { $check->({ foo => 3, bar => [] }) }, qr/^Reference \[\] did not pass type constraint/, 'bad "bar" parameter', ); like( exception { $check->({ foo => {}, bar => [] }) }, qr/^Reference \{\} did not pass type constraint/, 'two bad parameters; "foo" throws before "bar" gets a chance', ); like( exception { $check->({ foo => 3, bar => 42, baz => {} }) }, qr/^Reference \{\} did not pass type constraint/, 'bad optional "baz" parameter', ); like( exception { $check->({ foo => 3, bar => 42, xxx => 1 }) }, qr/^Unrecognized parameter: xxx/, 'additional parameter', ); like( exception { $check->({ foo => 3, bar => 42, xxx => 1, yyy => 2, zzz => 3 }) }, qr/^Unrecognized parameters: xxx, yyy, and zzz/, 'additional parameters', ); like( exception { $check->({ }) }, qr/^Missing required parameter: foo/, 'missing parameter', ); }; } sub _slurpy_test { my ($name, $check) = @_; local $Test::Builder::Level = $Test::Builder::Level + 1; subtest $name, sub { is_deeply( $check->( foo => 3, bar => 42 ), { XXX => {}, foo => 3, bar => 42 }, 'accept a hash', ); is_deeply( $check->( foo => 3, bar => 42, baz => [1..3] ), { XXX => {}, foo => 3, bar => 42, baz => [1..3] }, 'accept a hash, with optional parameter', ); is_deeply( $check->( foo => 3.1, bar => 42 ), { XXX => {}, foo => 3, bar => 42 }, 'accept a hash, and coerce', ); is_deeply( $check->( foo => 3.1, bar => 42, baz => [1..3, 4.2] ), { XXX => {}, foo => 3, bar => 42, baz => [1..4] }, 'accept a hash, with optional parameter, and coerce', ); is_deeply( $check->({ foo => 3, bar => 42 }), { XXX => {}, foo => 3, bar => 42 }, 'accept a hashref', ); is_deeply( $check->({ foo => 3, bar => 42, baz => [1..3] }), { XXX => {}, foo => 3, bar => 42, baz => [1..3] }, 'accept a hashref, with optional parameter', ); is_deeply( $check->({ foo => 3.1, bar => 42 }), { XXX => {}, foo => 3, bar => 42 }, 'accept a hashref, and coerce', ); is_deeply( $check->({ foo => 3.1, bar => 42, baz => [1..3, 4.2] }), { XXX => {}, foo => 3, bar => 42, baz => [1..4] }, 'accept a hashref, with optional parameter, and coerce', ); like( exception { $check->({ foo => [], bar => 42 }) }, qr/^Reference \[\] did not pass type constraint/, 'bad "foo" parameter', ); like( exception { $check->({ foo => 3, bar => [] }) }, qr/^Reference \[\] did not pass type constraint/, 'bad "bar" parameter', ); like( exception { $check->({ foo => {}, bar => [] }) }, qr/^Reference \{\} did not pass type constraint/, 'two bad parameters; "foo" throws before "bar" gets a chance', ); like( exception { $check->({ foo => 3, bar => 42, baz => {} }) }, qr/^Reference \{\} did not pass type constraint/, 'bad optional "baz" parameter', ); is_deeply( $check->({ foo => 3, bar => 42, xxx => 1 }), { XXX => { xxx => 1 }, foo => 3, bar => 42 }, 'additional parameter', ); is_deeply( $check->({ foo => 3, bar => 42, xxx => 1, yyy => 2, zzz => 3 }), { XXX => { xxx => 1, yyy => 2, zzz => 3 }, foo => 3, bar => 42 }, 'additional parameters', ); is_deeply( $check->({ foo => 3, bar => 42, xxx => 1.1, yyy => 2.2, zzz => 3 }), { XXX => { xxx => 1, yyy => 2, zzz => 3 }, foo => 3, bar => 42 }, 'coercion of additional parameters', ); like( exception { $check->({ }) }, qr/^Missing required parameter: foo/, 'missing parameter', ); }; } my $Rounded; $Rounded = Int->plus_coercions(Num, q{ int($_) }); simple_test( "simple test with everything inlineable", foo => $Rounded, bar => Int, baz => Optional[ArrayRef->of($Rounded)], ); $Rounded = Int->plus_coercions(Num, sub { int($_) }); simple_test( "simple test with inlineable types, but non-inlineable coercion", foo => $Rounded, bar => Int, baz => Optional[ArrayRef->of($Rounded)], ); $Rounded = Int->where(sub { !!1 })->plus_coercions(Num, sub { int($_) }); simple_test( "simple test with everything non-inlineable", foo => $Rounded, bar => Int->where(sub { !!1 }), baz => Optional[ArrayRef->of($Rounded)], ); $Rounded = Int->plus_coercions(Num, q{ int($_) }); slurpy_test( "slurpy test with everything inlineable", foo => $Rounded, bar => Int, baz => Optional[ArrayRef->of($Rounded)], XXX => slurpy HashRef[$Rounded], ); $Rounded = Int->plus_coercions(Num, sub { int($_) }); slurpy_test( "slurpy test with inlineable types, but non-inlineable coercion", foo => $Rounded, bar => Int, baz => Optional[ArrayRef->of($Rounded)], XXX => slurpy HashRef[$Rounded], ); $Rounded = Int->where(sub { !!1 })->plus_coercions(Num, sub { int($_) }); slurpy_test( "slurpy test with everything non-inlineable", foo => $Rounded, bar => Int->where(sub { !!1 }), baz => Optional[ArrayRef->of($Rounded)], XXX => slurpy HashRef[$Rounded], ); done_testing; hashorder.t000664001750001750 317113116235453 20352 0ustar00taitai000000000000Type-Tiny-1.002001/t/20-unit/Type-Params=pod =encoding utf-8 =head1 PURPOSE Test L' brand spanking new C function. =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_named); use Types::Standard qw(Int); subtest "predictable error message when problems with two parameters" => sub { for my $i (1..20) { my $check1 = compile_named( a => Int, b => Int ); my $check2 = compile_named( b => Int, a => Int ); like( exception { $check1->() }, qr/Missing required parameter: a/, "Iteration $i, check 1, missing parameters", ); like( exception { $check1->(a => [], b => {}) }, qr/Reference \[\] did not pass type constraint "Int"/, "Iteration $i, check 1, invalid values", ); like( exception { $check1->(a => 1, b => 2, c => '3PO', r2d => 2) }, qr/Unrecognized parameters: c and r2d/, "Iteration $i, check 1, extra values", ); like( exception { $check2->() }, qr/Missing required parameter: b/, "Iteration $i, check 2, missing parameters", ); like( exception { $check2->(a => [], b => {}) }, qr/Reference \{\} did not pass type constraint "Int"/, "Iteration $i, check 2, invalid values", ); like( exception { $check2->(a => 1, b => 2, c => '3PO', r2d => 2) }, qr/Unrecognized parameters: c and r2d/, "Iteration $i, check 2, extra values", ); } }; done_testing; methods.t000664001750001750 333413116235453 20037 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 201013116235453 20475 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 510013116235453 20222 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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( ${^TYPE_PARAMS_MULTISIG}, 0, '...${^TYPE_PARAMS_MULTISIG}', ); is_deeply( [ $sig->( 1, [2.2,3.3,4.4] ) ], [ 1, [2,3,4] ], 'first choice in multi, coercion, should pass', ); is( ${^TYPE_PARAMS_MULTISIG}, 0, '...${^TYPE_PARAMS_MULTISIG}', ); 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( ${^TYPE_PARAMS_MULTISIG}, 1, '...${^TYPE_PARAMS_MULTISIG}', ); is_deeply( [ $sig->( [2.2,3.3,4.4], 1 ) ], [ [2,3,4], 1 ], 'second choice in multi, coercion, should pass', ); is( ${^TYPE_PARAMS_MULTISIG}, 1, '...${^TYPE_PARAMS_MULTISIG}', ); 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', ); is( ${^TYPE_PARAMS_MULTISIG}, 2, '...${^TYPE_PARAMS_MULTISIG}', ); 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 230413116235453 17454 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 343413116235453 20366 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 250613116235453 20221 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 252613116235453 20557 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 244713116235453 17736 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 1621113116235453 17504 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 175513116235453 21011 0ustar00taitai000000000000Type-Tiny-1.002001/t/20-unit/Type-Parser=pod =encoding utf-8 =head1 PURPOSE Checks Type::Parser can pick up MooseX::Types type constraints. =head1 DEPENDENCIES Requires L 2.0201 and L 0.001004; skipped otherwise. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014, 2017 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.0201' }; use Test::Requires { 'MooseX::Types::Common' => '0.001004' }; 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 144713116235453 20735 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 566413116235453 20052 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 355313116235453 20427 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 217113116235453 21356 0ustar00taitai000000000000Type-Tiny-1.002001/t/20-unit/Type-Registry=pod =encoding utf-8 =head1 PURPOSE Checks Type::Registry works with MooseX::Types. =head1 DEPENDENCIES Requires L 2.0201 and L 0.001004; kipped otherwise. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014, 2017 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.0201' }; 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 206113116235453 21362 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 1127413116235453 20247 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 1124713116235453 17177 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 375713116235453 21665 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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; constraint-strings.t000664001750001750 226713116235453 21753 0ustar00taitai000000000000Type-Tiny-1.002001/t/20-unit/Type-Tiny=pod =encoding utf-8 =head1 PURPOSE Checks Type::Tiny works accepts strings of Perl code as constraints. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2017 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 Types::Standard -types; my $Str = Str->where( 'length($_) > 0' ); my $Arr = ArrayRef->where( '@$_ > 0' ); my $Hash = HashRef->where( 'keys(%$_) > 0' ); use Test::More; use Test::Fatal; is( exception { $Str->assert_valid( 'u' ) }, undef, 'non-empty string, okay', ); isa_ok( exception { $Str->assert_valid( '' ) }, 'Error::TypeTiny', 'result of empty string', ); is( exception { $Arr->assert_valid( [undef] ) }, undef, 'non-empty arrayref, okay', ); isa_ok( exception { $Arr->assert_valid( [] ) }, 'Error::TypeTiny', 'result of empty arrayref', ); is( exception { $Hash->assert_valid( { '' => undef } ) }, undef, 'non-empty hashref, okay', ); isa_ok( exception { $Hash->assert_valid( +{} ) }, 'Error::TypeTiny', 'result of empty hashref', ); done_testing; esoteric.t000664001750001750 421113116235453 17704 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 155313116235453 20163 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 355213116235453 21454 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 Test::Fatal; 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', ); like( exception { ArrayRef[Int, Int] }, qr/^\QOnly one parameter to ArrayRef[`a] expected; got 2/, 'error message when ArrayRef[`a] passed multiple parameters' ); done_testing; shortcuts.t000664001750001750 145313116235453 20132 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 223313116235453 20234 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 341513116235453 17422 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 223213116235453 17632 0ustar00taitai000000000000Type-Tiny-1.002001/t/20-unit/Type-Tiny=pod =encoding utf-8 =head1 PURPOSE Checks Type::Tiny objects can be converted to Moose type constraint objects. =head1 DEPENDENCIES Requires Moose 2.0000; skipped otherwise. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014, 2017 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::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 213013116235453 17635 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 304613116235453 20220 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 270713116235453 20456 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 446713116235453 22700 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 202313116235453 20033 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 262013116235453 20271 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 210113116235453 20046 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 211513116235453 20306 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 435413116235453 21624 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 275513116235453 22062 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 !ref($_) and $_ =~ /\\A-?[0-9]+\\z/)', ], ) or diag explain($e->explain); done_testing; basic.t000664001750001750 166013116235453 20054 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 245113116235453 20306 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 610113116235453 20236 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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)', ); ok( (FooBar|DoesQuux)==(DoesQuux|FooBar), 'Union equals', ); ok( (FooBar|DoesQuux)!=(DoesQuux|SmallInteger), 'Union not equals', ); done_testing; errors.t000664001750001750 341213116235453 20473 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 !ref($_) 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; double-union.t000664001750001750 135313116235453 22001 0ustar00taitai000000000000Type-Tiny-1.002001/t/20-unit/Type-Tiny-_HalfOp=pod =encoding utf-8 =head1 PURPOSE Ensure that the following works: ArrayRef[Str] | Undef | Str =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2017 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 FATAL => 'all'; use Test::More; use Types::Standard -all; my $union = eval { ArrayRef[Str] | Undef | Str }; SKIP: { ok $union or skip 'broken type', 6; ok $union->check([qw/ a b /]); ok !$union->check([[]]); ok $union->check(undef); ok $union->check("a"); ok !$union->check([undef]); ok !$union->check({}); } done_testing; overload-precedence.t000664001750001750 145413116235453 23311 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 213613116235453 20374 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 251213116235453 20140 0ustar00taitai000000000000Type-Tiny-1.002001/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.0000; skipped otherwise. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014, 2017 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.0000" } }; { 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 472513116235453 20336 0ustar00taitai000000000000Type-Tiny-1.002001/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.0201 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, 2017 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.0201" }; 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 $fallbacku = dwim_type("ArrayRef[$testclass]", fallback => []); is($fallbacku, undef); } { 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 473113116235453 20341 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 $fallbacku = dwim_type("ArrayRef[$testclass]", fallback => []); is($fallbacku, undef); } { 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 1000713116235453 20751 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 173513116235453 20104 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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' => 0.005 }; #warnings added in this version 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 633513116235453 21251 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 542413116235453 21113 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 237413116235453 21273 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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' ); is(to_NumericCode('+1 (800) 555-01-23'), '18005550123', 'numeric code' ); done_testing; unicode.t000664001750001750 310013116235453 21445 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 1067213116235453 20200 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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; cycletuple.t000664001750001750 313013116235453 21237 0ustar00taitai000000000000Type-Tiny-1.002001/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) 2017 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 qw(exception); use Types::Standard qw( CycleTuple Num Int HashRef ArrayRef Any Optional slurpy ); use Type::Utils qw( class_type ); my $type = CycleTuple[ Int->plus_coercions(Num, 'int($_)'), HashRef, ArrayRef, ]; should_fail(undef, $type); should_fail({}, $type); should_pass([], $type); should_fail([{}], $type); should_fail([1], $type); should_fail([1,{}], $type); should_pass([1,{}, []], $type); should_fail([1,{}, [], undef], $type); should_fail([1,{}, [], 2], $type); should_pass([1,{}, [], 2, {}, [1]], $type); is_deeply( $type->coerce([1.1, {}, [], 2.2, {}, [3.3]]), [1, {}, [], 2, {}, [3.3]], 'automagic coercion', ); #diag $type->inline_check('$THING'); #diag CycleTuple->of(Any, Any)->inline_check('$BLAH'); like( exception { CycleTuple[Any, Optional[Any]] }, qr/cannot be optional/i, 'cannot make CycleTuples with optional slots', ); like( exception { CycleTuple[Any, slurpy ArrayRef] }, qr/cannot be slurpy/i, 'cannot make CycleTuples with slurpy slots', ); # should probably write a test case for this. #diag exception { $type->assert_return([1,{},[],[],[],[]]) }; done_testing; deep-coercions.t000664001750001750 2676113116235453 22024 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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; ok( ! Dict->of(x => Int)->has_coercion, "Dict of type without coercion shouldn't have coercion", ); ok( Dict->of(x => Int->plus_coercions(Any, 1))->has_coercion, "Dict of type with coercion should have coercion", ); ok( ! Tuple->of(Int)->has_coercion, "Tuple of type without coercion shouldn't have coercion", ); ok( Tuple->of(Int->plus_coercions(Any, 1))->has_coercion, "Tuple of type with coercion should have coercion", ); ok( ! Map->of(Str, Int)->has_coercion, "Map of type without coercion shouldn't have coercion", ); ok( Map->of(Str, Int->plus_coercions(Any, 1))->has_coercion, "Map of type with coercion should have coercion", ); 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 221613116235453 20712 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 336413116235453 21465 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 274613116235453 20600 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 213613116235453 20706 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 334713116235453 20725 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 3466513116235453 21333 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 440013116235453 20014 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 564513116235453 20211 0ustar00taitai000000000000Type-Tiny-1.002001/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.0000 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, 2017 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.0000' } }; { 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 627613116235453 20732 0ustar00taitai000000000000Type-Tiny-1.002001/t/20-unit/Types-TypeTiny=pod =encoding utf-8 =head1 PURPOSE Test L pseudo-coercion. =head1 DEPENDENCIES This test requires L 2.0000, 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, 2017 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.0000' } }; { 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 254713116235453 20054 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 1043613116235453 21647 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 425013116235453 21407 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 156513116235453 22331 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 232313116235453 23065 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 224213116235453 22543 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 201313116235453 20247 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 270013116235453 17406 0ustar00taitai000000000000Type-Tiny-1.002001/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.000000 is not available. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014, 2017 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.000000 }; 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 544413116235453 23672 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 414413116235453 20132 0ustar00taitai000000000000Type-Tiny-1.002001/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.000000 is not available. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014, 2017 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.000000 }; 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 433413116235453 20513 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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'); # Expect the error message to contain this file, 'exceptions.t' like($e_constructor, qr/exceptions\.t/, '$e_constructor location'); 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 411413116235453 20311 0ustar00taitai000000000000Type-Tiny-1.002001/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.000000 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, 2017 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.000000 }; 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 170313116235453 20374 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 176413116235453 17762 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 211613116235453 22017 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 315613116235453 22404 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 2024613116235453 17763 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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; no warnings qw(once); 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-more.t000664001750001750 235613116235453 21425 0ustar00taitai000000000000Type-Tiny-1.002001/t/30-integration/Moose=pod =encoding utf-8 =head1 PURPOSE Test for the good old "You cannot coerce an attribute unless its type has a coercion" error. =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", ); done_testing; coercion.t000664001750001750 572413116235453 20467 0ustar00taitai000000000000Type-Tiny-1.002001/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.0000 is not available. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014, 2017 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 ); my $e; my $o; { 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); has big_nc => (is => "rw", isa => BigInteger->no_coercions, coerce => 0); } 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 212013116235453 22503 0ustar00taitai000000000000Type-Tiny-1.002001/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.1210 is not available. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2014, 2017 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.1210' }; 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 1561213116235453 23476 0ustar00taitai000000000000Type-Tiny-1.002001/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.1210 is not available. (The feature should work in older versions of Moose, but older versions of Test::Moose conflict with newer versions of Test::Builder.) =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE This software is copyright (c) 2013-2014, 2017 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.1210' }; 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 321313116235453 22046 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 334713116235453 21200 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 247113116235453 22101 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 330013116235453 21046 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 372013116235453 17747 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 422513116235453 20470 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 306513116235453 21203 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 246213116235453 22107 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 245013116235453 21624 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 413713116235453 21060 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 574613116235453 20515 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 303713116235453 23105 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 212213116235453 23462 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 146613116235453 21012 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 243113116235453 20315 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 451113116235453 23553 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 414613116235453 23246 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 131013116235453 21233 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 2635713116235453 20715 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 2175413116235453 20701 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 1732213116235453 21447 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 1177213116235453 20207 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 657713116235453 20522 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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 577613116235453 21347 0ustar00taitai000000000000Type-Tiny-1.002001/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 1.006000; use Sub::Quote qw( quote_sub ); use Types::Standard qw( Str Int ); has name => ( is => "ro", isa => Str, ); my $PositiveInt = Int -> where( quote_sub '$_ > 0' ) -> plus_coercions( Int, sub { abs $_ } ); has age => ( is => "rwp", isa => $PositiveInt, coerce => 1, ); 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 prior to 1.006000 doesn't support C<< coerce => 1 >>, instead requiring a coderef to use as a coercion. However, Type::Tiny can provide you with a suitable coderef to use (actually an object that overloads C<< &{} >>). Just use: has age => ( is => "rwp", isa => $PositiveInt, coerce => $PositiveInt->coercion, ); If you can upgrade to the latest Moo, and use C<< coerce => 1 >> you'll have a lot more fun though. :-) 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, 2017 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 731513116235453 21666 0ustar00taitai000000000000Type-Tiny-1.002001/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 ); has name => ( is => "ro", isa => Str, ); my $PositiveInt = Int -> where( sub { $_ > 0 } ) -> plus_coercions( Int, sub { 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 Type::Tiny is tested with L 2.0007 and above. 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, 2017 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 671013116235453 21672 0ustar00taitai000000000000Type-Tiny-1.002001/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 ); has name => ( is => "ro", isa => Str, ); my $PositiveInt = Int -> where( sub { $_ > 0 } ) -> plus_coercions( Int, sub { 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 Type::Tiny is tested with L 1.00 and above. 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, 2017 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 1170313116235453 21701 0ustar00taitai000000000000Type-Tiny-1.002001/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, 2017 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