use 5.008001; use strict; use warnings; package Types::Path::Tiny; # ABSTRACT: Path::Tiny types and coercions for Moose and Moo our $VERSION = '0.006'; use Path::Tiny qw(); use Type::Library 0.008 -base, -declare => qw( Path AbsPath File AbsFile Dir AbsDir ); use Type::Utils; use Types::Standard qw( Str ArrayRef ); use Types::TypeTiny 0.004 StringLike => { -as => "Stringable" }; #<<< class_type Path, { class => "Path::Tiny" }; declare AbsPath, as Path, where { $_->is_absolute }, inline_as { $_[0]->parent->inline_check($_) . "&& ${_}->is_absolute" }, message { is_Path($_) ? "Path '$_' is not absolute" : Path->get_message($_); }; declare File, as Path, where { $_->is_file }, inline_as { $_[0]->parent->inline_check($_) . "&& (-f $_)" }, message { is_Path($_) ? "File '$_' does not exist" : Path->get_message($_); }; declare Dir, as Path, where { $_->is_dir }, inline_as { $_[0]->parent->inline_check($_) . "&& (-d $_)" }, message { is_Path($_) ? "Directory '$_' does not exist" : Path->get_message($_); }; declare AbsFile, as intersection([AbsPath, File]), message { is_AbsPath($_) ? File->get_message($_) : AbsPath->get_message($_); }; declare AbsDir, as intersection([AbsPath, Dir]), message { is_AbsPath($_) ? Dir->get_message($_) : AbsPath->get_message($_); }; #>>> for my $type ( Path, File, Dir ) { coerce( $type, from Str() => q{ Path::Tiny::path($_) }, from Stringable() => q{ Path::Tiny::path($_) }, from ArrayRef() => q{ Path::Tiny::path(@$_) }, ); } for my $type ( AbsPath, AbsFile, AbsDir ) { coerce( $type, from Path => q{ $_->absolute }, from Str() => q{ Path::Tiny::path($_)->absolute }, from Stringable() => q{ Path::Tiny::path($_)->absolute }, from ArrayRef() => q{ Path::Tiny::path(@$_)->absolute }, ); } ### optionally add Getopt option type (adapted from MooseX::Types:Path::Class ##eval { require MooseX::Getopt; }; ##if ( !$@ ) { ## MooseX::Getopt::OptionTypeMap->add_option_type_to_map( $_, '=s', ) ## for ( 'Path::Tiny', Path ); ##} 1; # vim: ts=4 sts=4 sw=4 et: __END__ =pod =encoding UTF-8 =head1 NAME Types::Path::Tiny - Path::Tiny types and coercions for Moose and Moo =head1 VERSION version 0.006 =head1 SYNOPSIS Example with Moose: ### specification of type constraint with coercion package Foo; use Moose; use Types::Path::Tiny qw/Path AbsPath/; has filename => ( is => 'ro', isa => Path, coerce => 1, ); has directory => ( is => 'ro', isa => AbsPath, coerce => 1, ); ### usage in code Foo->new( filename => 'foo.txt' ); # coerced to Path::Tiny Foo->new( directory => '.' ); # coerced to path('.')->absolute Example with Moo: ### specification of type constraint with coercion package Foo; use Moo; use Types::Path::Tiny qw/Path AbsPath/; has 'directory' => ( is => 'rw', isa => AbsPath, required => 1, coerce => AbsPath->coercion, ); ### usage in code Foo->new( directory => '.' ); # coerced to path('.')->absolute =head1 DESCRIPTION This module provides L types for Moose, Moo, etc. It handles two important types of coercion: =over 4 =item * coercing objects with overloaded stringification =item * coercing to absolute paths =back It also can check to ensure that files or directories exist. =for Pod::Coverage method_names_here =head1 SUBTYPES This module uses L to define the following subtypes. =head2 Path C ensures an attribute is a L object. Strings and objects with overloaded stringification may be coerced. =head2 AbsPath C is a subtype of C (above), but coerces to an absolute path. =head2 File, AbsFile These are just like C and C, except they check C<-f> to ensure the file actually exists on the filesystem. =head2 Dir, AbsDir These are just like C and C, except they check C<-d> to ensure the directory actually exists on the filesystem. =head1 CAVEATS =head2 Path vs File vs Dir C just ensures you have a L object. C and C check the filesystem. Don't use them unless that's really what you want. =head2 Usage with File::Temp Be careful if you pass in a File::Temp object. Because the argument is stringified during coercion into a Path::Tiny object, no reference to the original File::Temp argument is held. Be sure to hold an external reference to it to avoid immediate cleanup of the temporary file or directory at the end of the enclosing scope. A better approach is to use Path::Tiny's own C or C constructors, which hold the reference for you. Foo->new( filename => Path::Tiny->tempfile ); =head1 SEE ALSO =over 4 =item * L =item * L =back =for :stopwords cpan testmatrix url annocpan anno bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan =head1 SUPPORT =head2 Bugs / Feature Requests Please report any bugs or feature requests through the issue tracker at L. You will be notified automatically of any progress on your issue. =head2 Source Code This is open source software. The code repository is available for public review and contribution under the terms of the license. L git clone https://github.com/dagolden/types-path-tiny.git =head1 AUTHOR David Golden =head1 CONTRIBUTORS =for stopwords Hobbestigrou Toby Inkster =over 4 =item * Hobbestigrou =item * Hobbestigrou =item * Toby Inkster =back =head1 COPYRIGHT AND LICENSE This software is Copyright (c) 2013 by David Golden. This is free software, licensed under: The Apache License, Version 2.0, January 2004 =cut