basic tests working
David Golden
11 years ago
2 | 2 | use warnings; |
3 | 3 | |
4 | 4 | package MooseX::Types::Path::Tiny; |
5 | # ABSTRACT: No abstract given for MooseX::Types::Path::Tiny | |
5 | # ABSTRACT: Path::Tiny types and coercions for Moose | |
6 | 6 | # VERSION |
7 | 7 | |
8 | # Dependencies | |
9 | use autodie 2.00; | |
8 | use Moose; | |
9 | use MooseX::Types::Stringlike qw/Stringable/; | |
10 | use Path::Tiny (); | |
11 | use MooseX::Types -declare => [qw( Path AbsPath )]; | |
12 | use MooseX::Types::Moose qw/Str ArrayRef/; | |
13 | ||
14 | subtype Path, as 'Path::Tiny'; | |
15 | ||
16 | for my $type ( 'Path::Tiny', Path ) { | |
17 | coerce( | |
18 | $type, | |
19 | from Str() => via { Path::Tiny::path($_) }, | |
20 | from Stringable() => via { Path::Tiny::path($_) }, | |
21 | from ArrayRef() => via { Path::Tiny::path(@$_) }, | |
22 | ); | |
23 | } | |
24 | ||
25 | subtype AbsPath, as Path, where { $_->is_absolute }; | |
26 | ||
27 | coerce( AbsPath, | |
28 | from Str() => via { Path::Tiny::path($_)->absolute }, | |
29 | from Stringable() => via { Path::Tiny::path($_)->absolute }, | |
30 | from ArrayRef() => via { Path::Tiny::path(@$_)->absolute }, | |
31 | ); | |
32 | ||
33 | # optionally add Getopt option type (adapted from MooseX::Types:Path::Class | |
34 | eval { require MooseX::Getopt; }; | |
35 | if ( !$@ ) { | |
36 | MooseX::Getopt::OptionTypeMap->add_option_type_to_map( $_, '=s', ) | |
37 | for ( 'Path::Tiny', Path ); | |
38 | } | |
10 | 39 | |
11 | 40 | 1; |
12 | 41 | |
14 | 43 | |
15 | 44 | =head1 SYNOPSIS |
16 | 45 | |
17 | use MooseX::Types::Path::Tiny; | |
46 | ### specification of type constraint with coercion | |
47 | ||
48 | package Foo; | |
49 | ||
50 | use Moose; | |
51 | use MooseX::Types::Path::Tiny qw/Path AbsPath/; | |
52 | ||
53 | has filename => ( | |
54 | is => 'ro', | |
55 | isa => Path, | |
56 | coerce => 1, | |
57 | ); | |
58 | ||
59 | has directory => ( | |
60 | is => 'ro', | |
61 | isa => AbsPath, | |
62 | coerce => 1, | |
63 | ); | |
64 | ||
65 | ### usage in code | |
66 | ||
67 | Foo->new( filename => 'foo.txt' ); # coerced to Path::Tiny | |
68 | Foo->new( directory => '.' ); # coerced to path('.')->absolute | |
18 | 69 | |
19 | 70 | =head1 DESCRIPTION |
20 | 71 | |
21 | This module might be cool, but you'd never know it from the lack | |
22 | of documentation. | |
72 | This module provides L<Path::Tiny> types for Moose. It handles | |
73 | two important types of coercion: | |
23 | 74 | |
24 | =head1 USAGE | |
75 | =for :list | |
76 | * coercing objects with overloaded stringification | |
77 | * coercing to absolute paths | |
25 | 78 | |
26 | Good luck! | |
79 | =head1 SUBTYPES | |
80 | ||
81 | This module uses L<MooseX::Types> to define the following subtypes. | |
82 | ||
83 | =head2 Path | |
84 | ||
85 | C<Path> ensures an attribute is a L<Path::Tiny> object. Strings and | |
86 | objects with overloaded stringification may be coerced. | |
87 | ||
88 | =head2 AbsPath | |
89 | ||
90 | C<AbsPath> is a subtype of C<Path> (above), but coerces to an absolute path. | |
91 | ||
92 | =head1 CAVEATS | |
93 | ||
94 | =head2 Usage with File::Temp | |
95 | ||
96 | Be careful if you pass in a File::Temp object. Because the argument is | |
97 | stringified during coercion into a Path::Tiny object, no reference to the | |
98 | original File::Temp argument is held. Be sure to hold an external reference to | |
99 | it to avoid immediate cleanup of the temporary file or diretory at the end of | |
100 | the enclosing scope. | |
101 | ||
102 | A better approach is to use Path::Tiny's own C<tempfile> or C<tempdir> | |
103 | constructors, which hold the reference for you. | |
104 | ||
105 | Foo->new( filename => Path::Tiny->tempfile ); | |
27 | 106 | |
28 | 107 | =head1 SEE ALSO |
29 | 108 | |
30 | Maybe other modules do related things. | |
109 | =for :list | |
110 | * L<Path::Tiny> | |
111 | * L<Moose::Manual::Types> | |
31 | 112 | |
32 | 113 | =cut |
33 | 114 |
0 | use 5.006; | |
1 | use strict; | |
2 | use warnings; | |
3 | use Test::More 0.96; | |
4 | use File::Temp; | |
5 | use File::pushd qw/tempd/; | |
6 | use Path::Tiny; | |
7 | ||
8 | { | |
9 | package Foo; | |
10 | use Moose; | |
11 | use MooseX::Types::Path::Tiny qw/Path/; | |
12 | ||
13 | has temp_file => ( is => 'ro', isa => Path, coerce => 1 ); | |
14 | } | |
15 | ||
16 | { | |
17 | package AbsFoo; | |
18 | use Moose; | |
19 | use MooseX::Types::Path::Tiny qw/AbsPath/; | |
20 | ||
21 | has temp_file => ( is => 'ro', isa => AbsPath, coerce => 1 ); | |
22 | } | |
23 | ||
24 | my $tf = File::Temp->new; | |
25 | ||
26 | subtest "coerce stringable objects" => sub { | |
27 | my $obj = eval { | |
28 | Foo->new( | |
29 | temp_file => $tf, | |
30 | ) | |
31 | }; | |
32 | ||
33 | is( $@, '', "object created without exception" ); | |
34 | isa_ok( $obj->temp_file, "Path::Tiny", "temp_file" ); | |
35 | is( $obj->temp_file, $tf, "temp_file set correctly" ); | |
36 | }; | |
37 | ||
38 | subtest "coerce strings" => sub { | |
39 | my $wd = tempd; | |
40 | my $obj = eval { | |
41 | Foo->new( | |
42 | temp_file => "./foo", | |
43 | ) | |
44 | }; | |
45 | is( $@, '', "object created using strings without exception" ); | |
46 | isa_ok( $obj->temp_file, "Path::Tiny", "temp_file" ); | |
47 | is( $obj->temp_file, path("./foo"), "temp_file set correctly" ); | |
48 | }; | |
49 | ||
50 | subtest "coerce arrayref" => sub { | |
51 | my $wd = tempd; | |
52 | my $obj = eval { | |
53 | Foo->new( | |
54 | temp_file => [qw/foo bar/] | |
55 | ) | |
56 | }; | |
57 | is( $@, '', "object created using arrayref without exception" ); | |
58 | isa_ok( $obj->temp_file, "Path::Tiny", "temp_file" ); | |
59 | is( $obj->temp_file, path(qw/foo bar/), "temp_file set correctly" ); | |
60 | }; | |
61 | ||
62 | subtest "coerce to absolute from strings" => sub { | |
63 | my $wd = tempd; | |
64 | my $obj = eval { | |
65 | AbsFoo->new( | |
66 | temp_file => "./foo", | |
67 | ) | |
68 | }; | |
69 | is( $@, '', "absolute path object created" ); | |
70 | isa_ok( $obj->temp_file, "Path::Tiny", "temp_file" ); | |
71 | is( $obj->temp_file, path("./foo")->absolute, "temp_file set correctly as absolute" ); | |
72 | }; | |
73 | ||
74 | subtest "coerce to absolute from arrayref" => sub { | |
75 | my $wd = tempd; | |
76 | my $obj = eval { | |
77 | AbsFoo->new( | |
78 | temp_file => [qw/foo bar/] | |
79 | ) | |
80 | }; | |
81 | is( $@, '', "object created using arrayref without exception" ); | |
82 | isa_ok( $obj->temp_file, "Path::Tiny", "temp_file" ); | |
83 | is( $obj->temp_file, path(qw/foo bar/)->absolute, "temp_file set correctly" ); | |
84 | }; | |
85 | ||
86 | subtest "coerce to absolute from stringables" => sub { | |
87 | my $obj = eval { | |
88 | AbsFoo->new( | |
89 | temp_file => $tf, | |
90 | ) | |
91 | }; | |
92 | is( $@, '', "absolute path object created" ); | |
93 | isa_ok( $obj->temp_file, "Path::Tiny", "temp_file" ); | |
94 | is( $obj->temp_file, $tf, "temp_file set correctly" ); | |
95 | }; | |
96 | ||
97 | subtest "coerce to absolute from Path::Tiny" => sub { | |
98 | my $wd = tempd; | |
99 | my $obj = eval { | |
100 | AbsFoo->new( | |
101 | temp_file => path("./foo"), | |
102 | ) | |
103 | }; | |
104 | is( $@, '', "absolute path object created" ); | |
105 | isa_ok( $obj->temp_file, "Path::Tiny", "temp_file" ); | |
106 | is( $obj->temp_file, path("./foo")->absolute, "temp_file set correctly as absolute" ); | |
107 | }; | |
108 | ||
109 | done_testing; | |
110 | # COPYRIGHT |