| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Perinci::Sub::Property::result::table; |
|
2
|
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
our $DATE = '2015-03-10'; # DATE |
|
4
|
|
|
|
|
|
|
our $VERSION = '0.06'; # VERSION |
|
5
|
|
|
|
|
|
|
|
|
6
|
1
|
|
|
1
|
|
3008
|
use 5.010001; |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
32
|
|
|
7
|
1
|
|
|
1
|
|
3
|
use strict; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
23
|
|
|
8
|
1
|
|
|
1
|
|
3
|
use warnings; |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
29
|
|
|
9
|
|
|
|
|
|
|
#use Log::Any '$log'; |
|
10
|
|
|
|
|
|
|
|
|
11
|
1
|
|
|
1
|
|
430
|
use Locale::TextDomain::UTF8 'Perinci-Sub-Property-result-table'; |
|
|
1
|
|
|
|
|
15222
|
|
|
|
1
|
|
|
|
|
7
|
|
|
12
|
1
|
|
|
1
|
|
8984
|
use Perinci::Object::Metadata; |
|
|
1
|
|
|
|
|
1711
|
|
|
|
1
|
|
|
|
|
30
|
|
|
13
|
1
|
|
|
1
|
|
472
|
use Perinci::Sub::PropertyUtil qw(declare_property); |
|
|
1
|
|
|
|
|
647
|
|
|
|
1
|
|
|
|
|
476
|
|
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
declare_property( |
|
16
|
|
|
|
|
|
|
name => 'result/table', |
|
17
|
|
|
|
|
|
|
type => 'function', |
|
18
|
|
|
|
|
|
|
schema => ['hash*'], |
|
19
|
|
|
|
|
|
|
wrapper => { |
|
20
|
|
|
|
|
|
|
meta => { |
|
21
|
|
|
|
|
|
|
v => 2, |
|
22
|
|
|
|
|
|
|
prio => 50, |
|
23
|
|
|
|
|
|
|
}, |
|
24
|
|
|
|
|
|
|
handler => sub { |
|
25
|
2
|
|
|
2
|
|
25927
|
my ($self, %args) = @_; |
|
26
|
2
|
|
33
|
|
|
18
|
my $v = $args{new} // $args{value} // {}; |
|
|
|
|
50
|
|
|
|
|
|
27
|
2
|
|
|
|
|
4
|
my $meta = $args{meta}; |
|
28
|
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
# add format_options |
|
30
|
|
|
|
|
|
|
{ |
|
31
|
2
|
50
|
|
|
|
3
|
last if $meta->{result_naked}; |
|
|
2
|
|
|
|
|
8
|
|
|
32
|
2
|
|
|
|
|
8
|
$self->select_section('after_call_after_res_validation'); |
|
33
|
2
|
|
|
|
|
22
|
$self->push_lines('# add format_options from result/table hints'); |
|
34
|
2
|
|
|
|
|
46
|
$self->push_lines('{'); |
|
35
|
2
|
|
|
|
|
19
|
$self->indent; |
|
36
|
2
|
|
|
|
|
21
|
$self->push_lines( |
|
37
|
|
|
|
|
|
|
# we are in a local block, so no need to use _w_ prefixes |
|
38
|
|
|
|
|
|
|
# for vars or even use add_var() |
|
39
|
|
|
|
|
|
|
'last unless ref($_w_res->[2]) eq "ARRAY";', |
|
40
|
|
|
|
|
|
|
'my $firstrow = $_w_res->[2][0] or last;', # deduce type from first row |
|
41
|
|
|
|
|
|
|
'my $tablespec = '.$self->{_args}{meta_name}.'->{result}{table}{spec} or last;', |
|
42
|
|
|
|
|
|
|
'my $tct = {};', |
|
43
|
|
|
|
|
|
|
'my $tco;', |
|
44
|
|
|
|
|
|
|
'if (ref($firstrow) eq "ARRAY" && $_w_res->[3]{"table.fields"}) {', |
|
45
|
|
|
|
|
|
|
' my $field_names = $_w_res->[3]{"table.fields"};', # map column\d to field names |
|
46
|
|
|
|
|
|
|
' for (0..@$field_names-1) {', |
|
47
|
|
|
|
|
|
|
' next if defined($tct->{$_});', |
|
48
|
|
|
|
|
|
|
' my $sch = $tablespec->{fields}{$field_names->[$_]}{schema} or next;', # field is unknown in table spec |
|
49
|
|
|
|
|
|
|
' my $type = ref($sch) eq "ARRAY" ? $sch->[0] : $sch;', |
|
50
|
|
|
|
|
|
|
' $type =~ s/\\*$//;', |
|
51
|
|
|
|
|
|
|
' $tct->{"column$_"} = $type;', |
|
52
|
|
|
|
|
|
|
' }', |
|
53
|
|
|
|
|
|
|
'} elsif (ref($firstrow) eq "HASH") {', |
|
54
|
|
|
|
|
|
|
' my $fields = [keys %$firstrow];', # XXX should we check from several/all rows to collect more complete keys? |
|
55
|
|
|
|
|
|
|
' $tco = [sort {($tablespec->{fields}{$a}{pos} // $tablespec->{fields}{$a}{index} // 9999) <=> ($tablespec->{fields}{$b}{pos} // $tablespec->{fields}{$b}{index} // 9999)} @$fields];', |
|
56
|
|
|
|
|
|
|
' for (@$fields) {', |
|
57
|
|
|
|
|
|
|
' my $sch = $tablespec->{fields}{$_}{schema} or next;', # field is unknown in table spec |
|
58
|
|
|
|
|
|
|
' my $type = ref($sch) eq "ARRAY" ? $sch->[0] : $sch;', |
|
59
|
|
|
|
|
|
|
' $type =~ s/\\*$//;', |
|
60
|
|
|
|
|
|
|
' $tct->{$_} = $type;', |
|
61
|
|
|
|
|
|
|
' }', |
|
62
|
|
|
|
|
|
|
'} else {', |
|
63
|
|
|
|
|
|
|
' last;', |
|
64
|
|
|
|
|
|
|
'}', |
|
65
|
|
|
|
|
|
|
'my $rfo = {};', |
|
66
|
|
|
|
|
|
|
'$rfo->{table_column_types} = [$tct] if $tct;', |
|
67
|
|
|
|
|
|
|
'$rfo->{table_column_orders} = [$tco] if $tco;', |
|
68
|
|
|
|
|
|
|
'$_w_res->[3]{format_options} //= {};', |
|
69
|
|
|
|
|
|
|
'$_w_res->[3]{format_options}{any} //= $rfo;', |
|
70
|
|
|
|
|
|
|
); |
|
71
|
2
|
|
|
|
|
101
|
$self->unindent; |
|
72
|
2
|
|
|
|
|
15
|
$self->push_lines('}'); |
|
73
|
|
|
|
|
|
|
} |
|
74
|
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
# TODO validate table data, if requested |
|
76
|
|
|
|
|
|
|
}, |
|
77
|
|
|
|
|
|
|
}, |
|
78
|
|
|
|
|
|
|
cmdline_help => { |
|
79
|
|
|
|
|
|
|
meta => { |
|
80
|
|
|
|
|
|
|
prio => 50, |
|
81
|
|
|
|
|
|
|
}, |
|
82
|
|
|
|
|
|
|
handler => sub { |
|
83
|
0
|
|
|
0
|
|
|
my ($self, $r) = @_; |
|
84
|
0
|
|
|
|
|
|
my $meta = $r->{_help_meta}; |
|
85
|
0
|
0
|
|
|
|
|
my $table_spec = $meta->{result}{table}{spec} |
|
86
|
|
|
|
|
|
|
or return undef; |
|
87
|
0
|
|
|
|
|
|
my $text = __("Returns table data. Table fields are as follow:"); |
|
88
|
0
|
|
|
|
|
|
$text .= "\n\n"; |
|
89
|
0
|
|
|
|
|
|
my $ff = $table_spec->{fields}; |
|
90
|
|
|
|
|
|
|
# reminder: index property is for older spec, will be removed |
|
91
|
|
|
|
|
|
|
# someday |
|
92
|
0
|
|
0
|
|
|
|
for my $fn (sort {($ff->{$a}{pos}//$ff->{$a}{index}//0) <=> |
|
|
0
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
93
|
|
|
|
|
|
|
($ff->{$b}{pos}//$ff->{$b}{index}//0)} |
|
94
|
|
|
|
|
|
|
keys %$ff) { |
|
95
|
0
|
|
|
|
|
|
my $f = $ff->{$fn}; |
|
96
|
0
|
|
|
|
|
|
my $fo = Perinci::Object::Metadata->new($f); |
|
97
|
0
|
|
|
|
|
|
my $sum = $fo->langprop("summary"); |
|
98
|
0
|
|
|
|
|
|
my $type; |
|
99
|
0
|
0
|
|
|
|
|
if ($f->{schema}) { |
|
100
|
0
|
0
|
|
|
|
|
$type = ref($f->{schema}) eq 'ARRAY' ? |
|
101
|
|
|
|
|
|
|
$f->{schema}[0] : $f->{schema}; |
|
102
|
0
|
|
|
|
|
|
$type =~ s/\*$//; |
|
103
|
|
|
|
|
|
|
} |
|
104
|
|
|
|
|
|
|
$text .= |
|
105
|
0
|
0
|
|
|
|
|
join("", |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
" - *$fn*", |
|
107
|
|
|
|
|
|
|
($type ? " ($type)" : ""), |
|
108
|
|
|
|
|
|
|
$table_spec->{pk} eq $fn ? |
|
109
|
|
|
|
|
|
|
" (".__x("ID field").")":"", |
|
110
|
|
|
|
|
|
|
$sum ? ": $sum" : "", |
|
111
|
|
|
|
|
|
|
"\n\n"); |
|
112
|
0
|
|
|
|
|
|
my $desc = $fo->langprop("description"); |
|
113
|
0
|
0
|
|
|
|
|
if ($desc) { |
|
114
|
0
|
|
|
|
|
|
$desc =~ s/(\r?\n)+\z//; |
|
115
|
0
|
|
|
|
|
|
$desc =~ s/^/ /mg; |
|
116
|
0
|
|
|
|
|
|
$text .= "$desc\n\n"; |
|
117
|
|
|
|
|
|
|
} |
|
118
|
|
|
|
|
|
|
} |
|
119
|
0
|
|
|
|
|
|
$text; |
|
120
|
|
|
|
|
|
|
}, |
|
121
|
|
|
|
|
|
|
}, # cmdline_help |
|
122
|
|
|
|
|
|
|
); |
|
123
|
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
1; |
|
126
|
|
|
|
|
|
|
# ABSTRACT: Specify table data in result |
|
127
|
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
__END__ |
|
129
|
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
=pod |
|
131
|
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
=encoding UTF-8 |
|
133
|
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
=head1 NAME |
|
135
|
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
Perinci::Sub::Property::result::table - Specify table data in result |
|
137
|
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
=head1 VERSION |
|
139
|
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
This document describes version 0.06 of Perinci::Sub::Property::result::table (from Perl distribution Perinci-Sub-Property-result-table), released on 2015-03-10. |
|
141
|
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
143
|
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
In function L<Rinci> metadata: |
|
145
|
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
result => { |
|
147
|
|
|
|
|
|
|
table => { |
|
148
|
|
|
|
|
|
|
spec => { |
|
149
|
|
|
|
|
|
|
summary => "Employee's' current salary", |
|
150
|
|
|
|
|
|
|
fields => { |
|
151
|
|
|
|
|
|
|
name => { |
|
152
|
|
|
|
|
|
|
summary => "Employee's name", |
|
153
|
|
|
|
|
|
|
schema => 'str*', |
|
154
|
|
|
|
|
|
|
pos => 0, |
|
155
|
|
|
|
|
|
|
}, |
|
156
|
|
|
|
|
|
|
position => { |
|
157
|
|
|
|
|
|
|
summary => "Employee's current position", |
|
158
|
|
|
|
|
|
|
schema => 'str*', |
|
159
|
|
|
|
|
|
|
pos => 1, |
|
160
|
|
|
|
|
|
|
}, |
|
161
|
|
|
|
|
|
|
salary => { |
|
162
|
|
|
|
|
|
|
summary => "Employee's current monthly salary", |
|
163
|
|
|
|
|
|
|
schema => 'float*', |
|
164
|
|
|
|
|
|
|
pos => 2, |
|
165
|
|
|
|
|
|
|
}, |
|
166
|
|
|
|
|
|
|
}, |
|
167
|
|
|
|
|
|
|
pk => 'name', |
|
168
|
|
|
|
|
|
|
}, |
|
169
|
|
|
|
|
|
|
# allow_extra_fields => 0, |
|
170
|
|
|
|
|
|
|
# allow_underscore_fields => 0, |
|
171
|
|
|
|
|
|
|
}, |
|
172
|
|
|
|
|
|
|
... |
|
173
|
|
|
|
|
|
|
} |
|
174
|
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
176
|
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
If your function returns table data, either in the form of array (single-column |
|
178
|
|
|
|
|
|
|
rows): |
|
179
|
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
["andi", "budi", "cinta", ...] |
|
181
|
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
or array of arrays (CSV-like): |
|
183
|
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
[ |
|
185
|
|
|
|
|
|
|
["andi" , "manager", 12_000_000], |
|
186
|
|
|
|
|
|
|
["budi" , "staff", 5_000_000], |
|
187
|
|
|
|
|
|
|
["cinta", "junior manager", 7_500_000], |
|
188
|
|
|
|
|
|
|
# ... |
|
189
|
|
|
|
|
|
|
] |
|
190
|
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
or array of hashes (with field names): |
|
192
|
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
[ |
|
194
|
|
|
|
|
|
|
{name=>"andi" , position=>"manager", salary=>12_000_000}, |
|
195
|
|
|
|
|
|
|
{name=>"budi" , position=>"staff", salary=> 5_000_000}, |
|
196
|
|
|
|
|
|
|
{name=>"cinta", position=>"junior manager", salary=> 7_500_000}, |
|
197
|
|
|
|
|
|
|
# ... |
|
198
|
|
|
|
|
|
|
] |
|
199
|
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
then you might want to add a C<table> property inside your C<result> property of |
|
201
|
|
|
|
|
|
|
your function metadata. This module offers several things: |
|
202
|
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
=over |
|
204
|
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
=item * |
|
206
|
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
When your function is run under L<Perinci::CmdLine>, your tables will look |
|
208
|
|
|
|
|
|
|
prettier. This is done via adding C<format_options> property to your function |
|
209
|
|
|
|
|
|
|
result metadata, giving hints to the L<Data::Format::Pretty> formatter. |
|
210
|
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
Also when you use --help (--verbose), the table structure is described in the |
|
212
|
|
|
|
|
|
|
Result section. |
|
213
|
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
=item * |
|
215
|
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
(NOT YET IMPLEMENTED) When you generate documentation, the table specification |
|
217
|
|
|
|
|
|
|
is also included in the documentation. |
|
218
|
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
=item * |
|
220
|
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
(NOT YET IMPLEMENTED, IDEA) The user can also perhaps request the table |
|
222
|
|
|
|
|
|
|
specification, e.g. C<yourfunc --help=result-table-spec>, C<yourfunc |
|
223
|
|
|
|
|
|
|
--result-table-spec>. |
|
224
|
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
=item * |
|
226
|
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
(NOT YET IMPLEMENTED) The wrapper code can optionally validate your function |
|
228
|
|
|
|
|
|
|
result, making sure that your resulting table conforms to the table |
|
229
|
|
|
|
|
|
|
specification. |
|
230
|
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
=item * |
|
232
|
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
(NOT YET IMPLEMENTED, IDEA) The wrapper code can optionally filter, summarize, |
|
234
|
|
|
|
|
|
|
or sort the table on the fly before returning the final result to the user. |
|
235
|
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
(Alternatively, you can pipe the output to another tool like B<jq>, just like a |
|
237
|
|
|
|
|
|
|
la Unix toolbox philosophy). |
|
238
|
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
=back |
|
240
|
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
=head1 SPECIFICATION |
|
242
|
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
The value of the C<table> property should be a L<DefHash>. Known properties: |
|
244
|
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
=over |
|
246
|
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
=item * spec => DEFHASH |
|
248
|
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
Required. Table data specification, specified using L<TableDef>. |
|
250
|
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
=item * allow_extra_fields => BOOL (default: 0) |
|
252
|
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
Whether to allow the function to return extra fields other than the ones |
|
254
|
|
|
|
|
|
|
specified in C<spec>. This is only relevant when function returns array of |
|
255
|
|
|
|
|
|
|
hashes (i.e. when the field names are present). And this is only relevant when |
|
256
|
|
|
|
|
|
|
validating the table data. |
|
257
|
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
=item * allow_underscore_fields => BOOL (default: 0) |
|
259
|
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
Like C<allow_extra_fields>, but regulates whether to allow any extra fields |
|
261
|
|
|
|
|
|
|
prefixed by an underscore. Underscore-prefixed keys is the DefHash's convention |
|
262
|
|
|
|
|
|
|
of extra keys that can be ignored. |
|
263
|
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
=back |
|
265
|
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
=head1 NOTES |
|
267
|
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
If you return an array or array of arrays (i.e. no field names), you might want |
|
269
|
|
|
|
|
|
|
to add C<table.fields> result metadata so the wrapper code can know which |
|
270
|
|
|
|
|
|
|
element belongs to which field. Example: |
|
271
|
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
my $table = []; |
|
273
|
|
|
|
|
|
|
push @$table, ["andi", 1]; |
|
274
|
|
|
|
|
|
|
push @$table, ["budi", 2]; |
|
275
|
|
|
|
|
|
|
return [200, "OK", $table, {"table.fields"=>[qw/name id/]}]; |
|
276
|
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
This is not needed if you return array of hashes, since the field names are |
|
278
|
|
|
|
|
|
|
present as hash keys: |
|
279
|
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
my $table = []; |
|
281
|
|
|
|
|
|
|
push @$table, {name=>"andi", id=>1}; |
|
282
|
|
|
|
|
|
|
push @$table, {name=>"budi", id=>2}; |
|
283
|
|
|
|
|
|
|
return [200, "OK", $table]; |
|
284
|
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
=head1 RESULT METADATA |
|
286
|
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
=over |
|
288
|
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
=item * attribute: table.fields => ARRAY OF STR |
|
290
|
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
=back |
|
292
|
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
=head1 FAQ |
|
294
|
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
=head2 Why not use the C<schema> property in the C<result> property? |
|
296
|
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
That is, in your function metadata: |
|
298
|
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
result => { |
|
300
|
|
|
|
|
|
|
schema => ['array*', of => ['hash*' => keys => { |
|
301
|
|
|
|
|
|
|
name => 'str*', |
|
302
|
|
|
|
|
|
|
position => 'str', |
|
303
|
|
|
|
|
|
|
salary => ['float*', min => 0], |
|
304
|
|
|
|
|
|
|
... |
|
305
|
|
|
|
|
|
|
}]], |
|
306
|
|
|
|
|
|
|
}, |
|
307
|
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
First of all, table data can come in several forms, either a 1-dimensional |
|
309
|
|
|
|
|
|
|
array, an array of arrays, or an array of hashes. Moreover, when returning an |
|
310
|
|
|
|
|
|
|
array of arrays, the order of fields can sometimes be changed. The above schema |
|
311
|
|
|
|
|
|
|
will become more complex if it has to handle all those cases. |
|
312
|
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
With the C<table> property, the intent becomes clearer that we want to return |
|
314
|
|
|
|
|
|
|
table data. We can also specify more aspects aside from just the schema. |
|
315
|
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
=head1 HOMEPAGE |
|
317
|
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
Please visit the project's homepage at L<https://metacpan.org/release/Perinci-Sub-Property-result-table>. |
|
319
|
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
=head1 SOURCE |
|
321
|
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
Source repository is at L<https://github.com/perlancar/perl-Perinci-Sub-Property-result-table>. |
|
323
|
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
=head1 BUGS |
|
325
|
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
Please report any bugs or feature requests on the bugtracker website L<https://rt.cpan.org/Public/Dist/Display.html?Name=Perinci-Sub-Property-result-table> |
|
327
|
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
When submitting a bug or request, please include a test-file or a |
|
329
|
|
|
|
|
|
|
patch to an existing test-file that illustrates the bug or desired |
|
330
|
|
|
|
|
|
|
feature. |
|
331
|
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
=head1 AUTHOR |
|
333
|
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
perlancar <perlancar@cpan.org> |
|
335
|
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
|
337
|
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
This software is copyright (c) 2015 by perlancar@cpan.org. |
|
339
|
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
This is free software; you can redistribute it and/or modify it under |
|
341
|
|
|
|
|
|
|
the same terms as the Perl 5 programming language system itself. |
|
342
|
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
=cut |