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   129641 use strict;
  22         46  
  22         709  
7 22     22   542 use Data::Hopen::Base;
  22         39  
  22         129  
8              
9 22     22   4862 use parent 'Exporter';
  22         48  
  22         139  
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         196 '@EXPORT' => [qw(hnew hlog getparameters)],
15             '@EXPORT_OK' => [qw(loadfrom *VERBOSE *QUIET UNSPECIFIED NOTHING)],
16 22     22   9408 }; #^ * => can be localized
  22         16611  
17 22         217 use vars::i '%EXPORT_TAGS' => {
18             default => [@EXPORT],
19             v => [qw(*VERBOSE *QUIET)],
20             all => [@EXPORT, @EXPORT_OK],
21 22     22   2963 };
  22         60  
22              
23 22     22   11437 use Data::Hopen::Util::NameSet;
  22         58  
  22         672  
24 22     22   10372 use Getargs::Mixed;
  22         22912  
  22         1300  
25 22     22   15887 use Storable ();
  22         80847  
  22         1349  
26              
27             our $VERSION = '0.000018';
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   741 our $VERBOSE; BEGIN { $VERBOSE = 0; }
82 22     22   17892 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 15618 my $class = shift or croak 'Need a class';
126 35         128 my @stems = ('Data::Hopen::G::', 'Data::Hopen::', '');
127 35 100       169 shift @stems if $class =~ /::/;
128              
129 35         84 my $found_class = false;
130              
131 35         99 foreach my $stem (@stems) {
132 37         3296 eval "require $stem$class";
133 37 100       822 next if $@;
134 34         97 $found_class = "$stem$class";
135 34         461 my $instance = "$found_class"->new('name', @_);
136             # put 'name' in front of the name parameter.
137 34 100       2413 return $instance if $instance;
138             }
139              
140 2 100       6 if($found_class) {
141 1         89 croak "Could not create instance for $found_class";
142             } else {
143 1         105 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 18470 return if $QUIET;
172 427 100 100     1573 return unless $VERBOSE >= ($_[1] // 1);
173              
174 321         450 my @log = &{$_[0]}();
  321         714  
175 321 100       12800 return unless @log;
176              
177 320 100       987 chomp $log[$#log] if $log[$#log];
178             # TODO add an option to number the lines of the output
179 320         2507 my $msg = (join(' ', @log)) =~ s/^/# /gmr;
180 320 100       861 if($VERBOSE>2) {
181 314         1029 my ($package, $filename, $line) = caller;
182 314         1083 $msg .= " (at $filename:$line)";
183             }
184 320         17213 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 6514 unshift @_, $GM;
198 2698         7667 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 7010 my $class = shift or croak 'Need a class';
214              
215 5         13 foreach my $stem (@_, '') {
216 5     2   30 hlog { loadfrom => "$stem$class" } 3;
  2         8  
217 5         348 eval "require $stem$class";
218 5 100       99 if($@) {
219 2     1   11 hlog { loadfrom => "$stem$class", 'load result was', $@ } 3;
  1         4  
220             } else {
221 3         13 return "$stem$class";
222             }
223             }
224              
225 2         8 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 4731 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 3320 sub NOTHING () { $_NOTHING };
249              
250             1; # End of Data::Hopen
251             __END__