File Coverage

blib/lib/Data/Hopen.pm
Criterion Covered Total %
statement 64 64 100.0
branch 24 24 100.0
condition 2 2 100.0
subroutine 18 18 100.0
pod 6 6 100.0
total 114 114 100.0


line stmt bran cond sub pod time code
1             #!perl
2             # lib/Data/Hopen.pm: utility routines for hopen(1). This file is also the
3             # source of the repo's README.md, which is autogenerated from this POD.
4              
5             package Data::Hopen;
6 22     22   130160 use strict;
  22         56  
  22         775  
7 22     22   573 use Data::Hopen::Base;
  22         52  
  22         139  
8              
9 22     22   4891 use parent 'Exporter';
  22         63  
  22         163  
10              
11             # TODO move more of these to a separate utility package?
12             # Probably keep hnew, hlog, $VERBOSE, and $QUIET here.
13             use vars::i {
14 22         201 '@EXPORT' => [qw(hnew hlog getparameters)],
15             '@EXPORT_OK' => [qw(loadfrom *VERBOSE *QUIET UNSPECIFIED NOTHING)],
16 22     22   9609 }; #^ * => can be localized
  22         16803  
17 22         195 use vars::i '%EXPORT_TAGS' => {
18             default => [@EXPORT],
19             v => [qw(*VERBOSE *QUIET)],
20             all => [@EXPORT, @EXPORT_OK],
21 22     22   3072 };
  22         50  
22              
23 22     22   11869 use Data::Hopen::Util::NameSet;
  22         59  
  22         695  
24 22     22   10280 use Getargs::Mixed;
  22         23117  
  22         1333  
25 22     22   16079 use Storable ();
  22         84092  
  22         1352  
26              
27             our $VERSION = '0.000017';
28              
29             # Docs {{{1
30              
31             =head1 NAME
32              
33             Data::Hopen - A dataflow library with first-class edges
34              
35             =head1 SYNOPSIS
36              
37             C is a dataflow library that runs actions you specify, moves data
38             between those actions, and permits transforming data as the data moves. It is
39             the underlying engine of the L cross-platform software build
40             generator, but can be used for any dataflow task that can be represented as a
41             directed acyclic graph (DAG).
42              
43             =head1 INSTALLATION
44              
45             Easiest: install C if you don't have it - see
46             L. Then run
47             C.
48              
49             Manually: clone or untar into a working directory. Then, in that directory,
50              
51             perl Makefile.PL
52             make
53             make test
54              
55             (you may need to install dependencies as well -
56             see L for resources).
57             If all the tests pass,
58              
59             make install
60              
61             If some of the tests fail, please check the issues and file a new one if
62             no one else has reported the problem yet.
63              
64             =head1 VARIABLES
65              
66             Not exported by default, except as noted.
67              
68             =head2 $VERBOSE
69              
70             Set to a positive integer to get debug output on stderr from hopen's internals.
71             The higher the value, the more output you are likely to get. See also L.
72              
73             =head2 $QUIET
74              
75             Set to truthy to suppress output. Quiet overrides L.
76              
77             =cut
78              
79             # }}}1
80              
81 22     22   737 our $VERBOSE; BEGIN { $VERBOSE = 0; }
82 22     22   18289 our $QUIET; BEGIN { $QUIET = false; }
83              
84             =head1 FUNCTIONS
85              
86             All are exported by default unless indicated.
87              
88             =head2 hnew
89              
90             Creates a new Data::Hopen instance. For example:
91              
92             hnew DAG => 'foo';
93              
94             is the same as
95              
96             Data::Hopen::G::DAG->new( name => 'foo' );
97              
98             The first parameter (C<$class>) is an abbreviated package name. It is tried
99             as the following, in order. The first one that succeeds is used.
100              
101             =over
102              
103             =item 1.
104              
105             C. This is tried only if C<$class>
106             does not include a double-colon.
107              
108             =item 2.
109              
110             C
111              
112             =item 3.
113              
114             C<$class>
115              
116             =back
117              
118             The second parameter
119             must be the name of the new instance. All other parameters are passed
120             unchanged to the relevant constructor.
121              
122             =cut
123              
124             sub hnew {
125 36 100   36 1 16322 my $class = shift or croak 'Need a class';
126 35         138 my @stems = ('Data::Hopen::G::', 'Data::Hopen::', '');
127 35 100       154 shift @stems if $class =~ /::/;
128              
129 35         87 my $found_class = false;
130              
131 35         86 foreach my $stem (@stems) {
132 37         3140 eval "require $stem$class";
133 37 100       722 next if $@;
134 34         101 $found_class = "$stem$class";
135 34         473 my $instance = "$found_class"->new('name', @_);
136             # put 'name' in front of the name parameter.
137 34 100       2635 return $instance if $instance;
138             }
139              
140 2 100       11 if($found_class) {
141 1         98 croak "Could not create instance for $found_class";
142             } else {
143 1         98 croak "Could not find class for $class";
144             }
145             } #hnew()
146              
147             =head2 hlog
148              
149             Log information if L is set. Usage:
150              
151             hlog { } [optional min verbosity level (default 1)];
152              
153             The items in the list are joined by C<' '> on output, and a C<'\n'> is added.
154             Each line is prefixed with C<'# '> for the benefit of test runs.
155              
156             The list is in C<{}> so that it won't be evaluated if logging is turned off.
157             It is a full block, so you can run arbitrary code to decide what to log.
158             If the block returns an empty list, hlog will not produce any output.
159             However, if the block returns at least one element, hlog will produce at
160             least a C<'# '>.
161              
162             The message will be output only if L is at least the given minimum
163             verbosity level (1 by default).
164              
165             If C<< $VERBOSE > 2 >>, the filename and line from which hlog was called
166             will also be printed.
167              
168             =cut
169              
170             sub hlog (&;$) {
171 440 100   440 1 20715 return if $QUIET;
172 427 100 100     1629 return unless $VERBOSE >= ($_[1] // 1);
173              
174 321         486 my @log = &{$_[0]}();
  321         741  
175 321 100       13573 return unless @log;
176              
177 320 100       1025 chomp $log[$#log] if $log[$#log];
178             # TODO add an option to number the lines of the output
179 320         2626 my $msg = (join(' ', @log)) =~ s/^/# /gmr;
180 320 100       842 if($VERBOSE>2) {
181 314         1161 my ($package, $filename, $line) = caller;
182 314         1065 $msg .= " (at $filename:$line)";
183             }
184 320         29745 say STDERR $msg;
185             } #hlog()
186              
187             =head2 getparameters
188              
189             An alias of the C function from L, but with
190             C<-undef_ok> set.
191              
192             =cut
193              
194             my $GM = Getargs::Mixed->new(-undef_ok => true);
195              
196             sub getparameters {
197 2698     2698 1 6485 unshift @_, $GM;
198 2698         7608 goto &Getargs::Mixed::parameters;
199             } #getparameters()
200              
201             =head2 loadfrom
202              
203             (Not exported by default) Load a package given a list of stems. Usage:
204              
205             my $fullname = loadfrom($name[, @stems]);
206              
207             Returns the full name of the loaded package, or falsy on failure.
208             If C<@stems> is omitted, no stem is used, i.e., C<$name> is tried as-is.
209              
210             =cut
211              
212             sub loadfrom {
213 6 100   6 1 7248 my $class = shift or croak 'Need a class';
214              
215 5         15 foreach my $stem (@_, '') {
216 5     2   32 hlog { loadfrom => "$stem$class" } 3;
  2         7  
217 5         387 eval "require $stem$class";
218 5 100       134 if($@) {
219 2     1   16 hlog { loadfrom => "$stem$class", 'load result was', $@ } 3;
  1         4  
220             } else {
221 3         15 return "$stem$class";
222             }
223             }
224              
225 2         10 return undef;
226             } #loadfrom()
227              
228             =head1 CONSTANTS
229              
230             =head2 UNSPECIFIED
231              
232             A L that matches any non-empty string.
233             Always returns the same reference, so that it can be tested with C<==>.
234              
235             =cut
236              
237             my $_UNSPECIFIED = Data::Hopen::Util::NameSet->new(qr/.(*ACCEPT)/);
238 45     45 1 4985 sub UNSPECIFIED () { $_UNSPECIFIED };
239              
240             =head2 NOTHING
241              
242             A L that never matches. Always returns the
243             same reference, so that it can be tested with C<==>.
244              
245             =cut
246              
247             my $_NOTHING = Data::Hopen::Util::NameSet->new();
248 13     13 1 3188 sub NOTHING () { $_NOTHING };
249              
250             1; # End of Data::Hopen
251             __END__