File Coverage

blib/lib/App/RecordStream/Operation/generate.pm
Criterion Covered Total %
statement 51 61 83.6
branch 4 6 66.6
condition n/a
subroutine 11 12 91.6
pod 0 4 0.0
total 66 83 79.5


line stmt bran cond sub pod time code
1             package App::RecordStream::Operation::generate;
2              
3             our $VERSION = "4.0.24";
4              
5 2     2   1085 use strict;
  2         4  
  2         52  
6              
7 2     2   10 use base qw(App::RecordStream::Operation);
  2         4  
  2         138  
8              
9 2     2   246 use App::RecordStream::Executor::Getopt;
  2         10  
  2         45  
10 2     2   10 use App::RecordStream::Executor;
  2         3  
  2         36  
11              
12 2     2   9 use Data::Dumper;
  2         3  
  2         80  
13 2     2   266 use App::RecordStream::InputStream;
  2         7  
  2         53  
14 2     2   13 use App::RecordStream::Record;
  2         6  
  2         39  
15 2     2   9 use App::RecordStream::Executor;
  2         4  
  2         696  
16              
17             sub init {
18 2     2 0 3 my $this = shift;
19 2         5 my $args = shift;
20              
21 2         5 my $keychain = '_chain';
22 2         4 my $passthrough = 0;
23 2         20 my $executor_options = App::RecordStream::Executor::Getopt->new();
24              
25 2         13 my $spec = {
26             'keychain=s' => \$keychain,
27             'passthrough' => \$passthrough,
28             $executor_options->arguments(),
29             };
30              
31 2         16 $this->parse_options($args, $spec, ['bundling']);
32              
33 2         15 my $expression = $executor_options->get_string($args);
34 2         22 my $executor = App::RecordStream::Executor->new($expression);
35              
36 2         6 $this->{'KEYCHAIN'} = $keychain;
37 2         5 $this->{'PASSTHROUGH'} = $passthrough;
38 2         34 $this->{'EXECUTOR'} = $executor;
39             }
40              
41             sub accept_record {
42 4     4 0 8 my $this = shift;
43 4         6 my $record = shift;
44              
45 4 100       19 $this->push_record($record) if $this->{'PASSTHROUGH'};
46              
47 4         25 my $interpolated_command = $this->{'EXECUTOR'}->execute_code($record);
48              
49 4 50       15 if ($@) {
50 0         0 chomp $@;
51 0         0 warn "# $0 interpolating command threw: " . $@ . "\n";
52 0         0 return 1;
53             }
54              
55 4         11097 my $pid = open(my $pipe, "-|", $interpolated_command);
56              
57 4 50       60 if (!$pid) {
58 0         0 warn "# $0 open(..., \"$interpolated_command |\") failed: $!\n";
59 0         0 return 1;
60             }
61              
62 4         101 my $generator_stream = App::RecordStream::InputStream->new(FH => $pipe);
63              
64 4         31 while(my $generated_record = $generator_stream->get_record()) {
65 4         35 ${$generated_record->guess_key_from_spec($this->{'KEYCHAIN'})} = $record->as_hashref();
  4         39  
66 4         60 $this->push_record($generated_record);
67             }
68             # App::RecordStream::InputStream closes the file handle for us
69              
70 4         92 return 1;
71             }
72              
73             sub add_help_types {
74 2     2 0 4 my $this = shift;
75 2         10 $this->use_help_type('keyspecs');
76             }
77              
78             sub usage
79             {
80 0     0 0   my $this = shift;
81              
82 0           my $options = [
83             App::RecordStream::Executor::options_help(),
84             [ 'passthrough', 'Emit input record in addition to generated records' ],
85             [ 'keychain ', 'Use \'name\' as the chain key (default is \'_chain\') may be a key spec, see \'--help-keyspecs\' for more info' ],
86             ];
87              
88 0           my $args_string = $this->options_string($options);
89              
90 0           my $usage = <
91             Usage: recs-generate []
92             __FORMAT_TEXT__
93             Executes for each record to generate a record stream, which is
94             then output with a chain link back to the original record.
95              
96             is executed opened as a command for each record of input (or
97             records from ) with \$r set to a App::RecordStream::Record object. The output
98             lines of each command execution are interpreted as a serialized Recs records,
99             one per line. Each such line is reconstituted as a App::RecordStream::Record, and the
100             '_chain' key is added to the record before it is printed. The value of the
101             '_chain' key is the record that was originally passed to the eval expression.
102             __FORMAT_TEXT__
103              
104             For instance. If you did:
105             recs-generate "recs-fromatomfeed http://...?key=\$r->{title}..."
106              
107             with input that looked like:
108             { 'title' : 'foo' }
109             { 'title' : 'bar' }
110              
111             then recs-generate would end up executing:
112             recs-fromatomfeed http://...?key=foo...
113              
114             __FORMAT_TEXT__
115             and interpreting the result as a series of new line separated records.
116              
117             If the result from recs-fromatomfeed was something like:
118             __FORMAT_TEXT__
119             { 'title' : 'zip' }
120             { 'title' : 'zap' }
121              
122             __FORMAT_TEXT__
123             then recs-generate would add the chain link so the output would look like:
124             __FORMAT_TEXT__
125             { 'title' : 'zip', 'chain' : { 'title' : 'foo' } }
126             { 'title' : 'zap', 'chain' : { 'title' : 'foo' } }
127              
128             Arguments:
129             $args_string
130              
131             Examples:
132             Chain recs from a feed to recs from a second feed and the print the titles.
133             recs-fromatomfeed "http://..." | recs-generate "recs-fromatomfeed http://...?key=\$r->{title}" | recs-eval 'join("\t", \$r->{title}, \$r->{chain}->{title})'
134             USAGE
135              
136 0           return $usage;
137             }
138              
139             1;