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<Path::Tiny> 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<Type::Tiny> to define the following subtypes.
=head2 Path
C<Path> ensures an attribute is a L<Path::Tiny> object. Strings and
objects with overloaded stringification may be coerced.
=head2 AbsPath
C<AbsPath> is a subtype of C<Path> (above), but coerces to an absolute path.
=head2 File, AbsFile
These are just like C<Path> and C<AbsPath>, except they check C<-f> to ensure
the file actually exists on the filesystem.
=head2 Dir, AbsDir
These are just like C<Path> and C<AbsPath>, except they check C<-d> to ensure
the directory actually exists on the filesystem.
=head1 CAVEATS
=head2 Path vs File vs Dir
C<Path> just ensures you have a L<Path::Tiny> object.
C<File> and C<Dir> 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<tempfile> or C<tempdir>
constructors, which hold the reference for you.
Foo->new( filename => Path::Tiny->tempfile );
=head1 SEE ALSO
=over 4
=item *
L<Path::Tiny>
=item *
L<Moose::Manual::Types>
=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<https://github.com/dagolden/types-path-tiny/issues>.
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<https://github.com/dagolden/types-path-tiny>
git clone https://github.com/dagolden/types-path-tiny.git
=head1 AUTHOR
David Golden <dagolden@cpan.org>
=head1 CONTRIBUTORS
=for stopwords Hobbestigrou Toby Inkster
=over 4
=item *
Hobbestigrou <hobbestigrou@erakis.eu>
=item *
Hobbestigrou <natal.ngetal@novapost.fr>
=item *
Toby Inkster <tobyink@cpan.org>
=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