File Coverage

blib/lib/Catmandu.pm
Criterion Covered Total %
statement 103 112 91.9
branch 17 28 60.7
condition 4 6 66.6
subroutine 32 33 96.9
pod 24 24 100.0
total 180 203 88.6


line stmt bran cond sub pod time code
1              
2             use Catmandu::Sane;
3 147     147   406196  
  147         359  
  147         925  
4             our $VERSION = '1.2019';
5              
6             use Catmandu::Env;
7 147     147   55204 use Catmandu::Util qw(:is);
  147         520  
  147         7574  
8 147     147   1228 use File::Spec;
  147         268  
  147         36245  
9 147     147   1055 use namespace::clean;
  147         317  
  147         3187  
10 147     147   721 use Sub::Exporter::Util qw(curry_method);
  147         367  
  147         807  
11 147     147   143555 use Sub::Exporter -setup => {
  147         234395  
  147         709  
12 147         548 exports => [
13             config => curry_method,
14             log => curry_method,
15             store => curry_method,
16             fixer => curry_method,
17             importer => curry_method,
18             exporter => curry_method,
19             validator => curry_method,
20             export => curry_method,
21             export_to_string => curry_method,
22             import_from_string => curry_method
23             ],
24             collectors => {'-load' => \'_import_load', ':load' => \'_import_load',},
25             };
26 147     147   41714  
  147         327  
27             my ($self, $value, $data) = @_;
28             if (is_array_ref $value) {
29 0     0   0 $self->load(@$value);
30 0 0       0 }
31 0         0 else {
32             $self->load;
33             }
34 0         0 1;
35             }
36 0         0  
37             my ($class, $env) = @_;
38             state $loaded_env;
39             $loaded_env = $env if defined $env;
40 226     226   539 $loaded_env
41 226         339 ||= Catmandu::Env->new(load_paths => $class->default_load_path);
42 226 100       1333 }
43 226   66     1534  
44              
45             my ($class, $path) = @_;
46             state $default_path;
47 12     12 1 7303 $default_path = $path if defined $path;
48             $default_path //= do {
49             my $script = File::Spec->rel2abs($0);
50 68     68 1 578 my ($script_vol, $script_path, $script_name)
51 68         95 = File::Spec->splitpath($script);
52 68 100       185 my @dirs = grep length, File::Spec->splitdir($script_path);
53 68   66     240 if ($dirs[-1] eq 'bin') {
54 28         1337 pop @dirs;
55 28         532 File::Spec->catdir(File::Spec->rootdir, @dirs);
56             }
57 28         322 else {
58 28 50       135 $script_path;
59 0         0 }
60 0         0 };
61             }
62              
63 28         279 my $class = shift;
64             my $paths = [@_ ? @_ : $class->default_load_path];
65             my $env = Catmandu::Env->new(load_paths => $paths);
66             $class->_env($env);
67             $class;
68             }
69 49     49 1 102  
70 49 50       231 $_[0]->_env->roots;
71 49         1127 }
72 49         5693  
73 49         205 $_[0]->_env->root;
74             }
75              
76             my ($class, $config) = @_;
77 5     5 1 16 if ($config) {
78             my $env = Catmandu::Env->new(load_paths => $class->_env->load_paths);
79             $env->_set_config($config);
80             $class->_env($env);
81 1     1 1 1272 }
82             $class->_env->config;
83             }
84              
85 22     22 1 4403  
86 22 100       61 my $class = shift;
87 1         3 $class->_env->store(@_);
88 1         308 }
89 1         30  
90              
91 22         67 my $class = shift;
92             $class->_env->fixer(@_);
93             }
94 1     1 1 3  
95              
96              
97 27     27 1 813 my $class = shift;
98 27         93 $class->_env->importer(@_);
99             }
100              
101 1     1 1 4  
102              
103             my $class = shift;
104 9     9 1 12751 $class->_env->exporter(@_);
105 9         38 }
106              
107             my $class = shift;
108 1     1 1 4 $class->_env->validator(@_);
109             }
110 1     1 1 4  
111             my $class = shift;
112             my $data = shift;
113 33     33 1 3150 my $exporter = $class->_env->exporter(@_);
114 33         118 is_hash_ref($data) ? $exporter->add($data) : $exporter->add_many($data);
115             $exporter->commit;
116             return;
117 1     1 1 4 }
118              
119 1     1 1 4 my $class = shift;
120             my $data = shift;
121             my $name = shift;
122 45     45 1 125 my %opts = ref $_[0] ? %{$_[0]} : @_;
123 45         188 my $str = "";
124             my $exporter = $class->_env->exporter($name, %opts, file => \$str);
125             is_hash_ref($data) ? $exporter->add($data) : $exporter->add_many($data);
126             $exporter->commit;
127 1     1 1 2406 $str;
128 1         4 }
129              
130             my $class = shift;
131             my $str = shift;
132 1     1 1 21 my $name = shift;
133 1         3 my %opts = ref $_[0] ? %{$_[0]} : @_;
134 1         5 $class->_env->importer($name, %opts, file => \$str)->to_array();
135 1 50       35 }
136 1         20  
137 1         2 my $class = shift;
138             my $name = shift;
139             my $package = shift;
140             my $options = ref $_[0] ? $_[0] : {@_};
141 7     7 1 397 $class->config->{importer}{$name}
142 7         11 = {package => $package, options => $options};
143 7         9 }
144 7 50       24  
  0         0  
145 7         14 my $class = shift;
146 7         26 my $name = shift;
147 7 100       138 my $package = shift;
148 7         119 my $options = ref $_[0] ? $_[0] : {@_};
149 7         22 $class->config->{exporter}{$name}
150             = {package => $package, options => $options};
151             }
152              
153 6     6 1 12 my $class = shift;
154 6         8 my $name = shift;
155 6         7 my $package = shift;
156 6 50       19 my $options = ref $_[0] ? $_[0] : {@_};
  0         0  
157 6         18 $class->config->{store}{$name}
158             = {package => $package, options => $options};
159             }
160              
161 1     1 1 5 my $class = shift;
162 1         5 my $name = shift;
163 1         5 my $fixes = ref $_[0] ? $_[0] : [@_];
164 1 50       11 $class->config->{fixer}{$name} = $fixes;
165 1         12 }
166              
167             1;
168              
169              
170 1     1 1 3 =pod
171 1         3  
172 1         3 =head1 NAME
173 1 50       9  
174 1         5 Catmandu - a data toolkit
175              
176             =head1 SYNOPSIS
177              
178             # From the command line
179 1     1 1 3  
180 1         3 # Convert data from one format to another
181 1         2 $ catmandu convert JSON to CSV < data.json
182 1 50       7 $ catmandu convert CSV to YAML < data.csv
183 1         5 $ catmandu convert MARC to YAML < data.mrc
184              
185             # Fix data, add, delete, change fields
186             $ catmandu convert JSON --fix 'move_field(title,my_title)' < data.json
187             $ catmandu convert JSON --fix all_my_fixes.txt < data.json
188 1     1 1 3 # Use a moustache preprocessor on the fix script
189 1         2 $ catmandu convert JSON --fix all_my_fixes.txt --var opt1=foo --var opt2=bar < data.json
190 1 50       5  
191 1         4 # Import data into a database
192             # Requires: Catmandu::MongoDB and Catmandu::ElasticSearch
193             $ catmandu import YAML to MongoDB --database_name bibliography < data.yml
194             $ catmandu import CSV to ElasticSearch --index_name mystuff < data.csv
195              
196             # Export data from a database
197             # Requires: Catmandu::MongoDB and Catmandu::ElasticSearch
198             $ catmandu export MongoDB --database_name bibliography to YAML > data.yml
199             $ catmandu export ElasticSearch --index_name mystuff to CSV > data.csv
200              
201             # Copy data from one store to another
202             $ catmandu copy MongoDB --database_name mydb to ElasticSearch --index_name mydb
203              
204             # Show the contents of catmandu.yml
205             $ catmandu config
206              
207             # Count items in a store
208             $ catmandu count test1
209              
210             # Delete items from store
211             $ catmandu delete test1 --query 'title:"My Rabbit"'
212              
213             # run a fix script
214             $ catmandu run myfixes.fix
215              
216             # or, create an executable fix script
217             $ cat myfixes.fix
218             #!/usr/local/bin/catmandu run
219             do importer(OAI,url:"http://biblio.ugent.be/oai")
220             retain(_id)
221             end
222             $ chmod 755 myfixes.fix
223             $ ./myfixes.fix
224              
225             # From Perl
226             use Catmandu;
227              
228             # If you have Catmandu::OAI and Catmandu::MongoDB installed
229             my $importer = Catmandu->importer('OAI',url => 'https://biblio.ugent.be/oai')
230             my $store = Catmandu->store('MongoDB',database_name => 'test');
231              
232             # Import all the OAI records into MongoDB
233             $store->add_many($importer);
234              
235             # Export all the MongoDB records to YAML and apply some fixes
236             # myfixes.txt:
237             # upcase(title.*)
238             # remove_field(_metadata)
239             # join_field(creator,'; ')
240             # join_field(subject,'-- ')
241             my $fixer = Catmandu->fixer('myfixes.txt');
242             my $exporter = Catmandu->exporter('YAML');
243              
244             $exporter->add_many( $fixer->fix($store) );
245             $exporter->commit;
246              
247             =head1 DESCRIPTION
248              
249             Catmandu provides a command line client and a Perl API to ease the export (E)
250             transformation (T) and loading (L) of data into databases or data file, ETL in short.
251              
252             Most of the daily work processing structured data can be done on the command line
253             executing the C<catmandu> command. With our catmandu command ETL processing is available
254             in a Perl context. Catmandu is different from other
255             ETL tools by its focus on command line processing with much support for dataformats
256             available in (academic) libraries: MARC, MODS, OAI and SRU. But, also generic formats such
257             as JSON, YAML, CVS, Excel, XML, RDF, Atom are supported.
258              
259             Read :
260              
261             =over
262              
263             =item * L<Catmandu::Introduction> for a primer on the command line capabilities of Catmandu.
264              
265             =item * L<Catmandu::Importer> for the basics of importing
266              
267             =item * L<Catmandu::Fix> for the basics of transformations
268              
269             =item * L<Catmandu::Exporter> for the basics of exporting
270              
271             =item * L<Catmandu::Store> for the basics of storing information
272              
273             =item * Or, visit our website at L<http://librecat.org/> and our blog L<https://librecatproject.wordpress.com/>
274             for many tutorials
275              
276             =back
277              
278             The documentation below describes the methods available when including Catmandu as
279             part of a Perl script. For an overview of the command line tool itself read the
280             documentation on L<catmandu>.
281              
282             =head1 USE
283              
284             To include Catmandu in a Perl script it should be loaded with a C<use> command:
285              
286             use Catmandu;
287              
288             By default no methods are imported into the Perl context. To import all or some Catmandu methods,
289             provide them as a list to the C<use> command:
290              
291             use Catmandu -all;
292             use Catmandu qw(config store exporter);
293              
294             Catmandu can load configuration options for exports, importers, fixers via configuration
295             files (see the CONFIG section below). When adding the --load option (optionally with a path) to the
296             C<use> command, these configuration files will be loaded at the start of your script.
297              
298             use Catmandu -load;
299             use Catmandu -load => ['/my/config/directory'];
300              
301             # or use all the options
302             use Catmandu -all, -load => [qw(/config/path' '/another/config/path)];
303              
304             =head1 CLASS METHODS
305              
306             =head2 log
307              
308             Return the current L<Log::Any> logger.
309              
310             use Catmandu;
311             use Log::Any::Adapter;
312             use Log::Log4perl;
313              
314             Log::Any::Adapter->set('Log4perl'); # requires Log::Any::Adapter::Log4perl
315             Log::Log4perl::init('./log4perl.conf');
316              
317             my $logger = Catmandu->log;
318             $logger->info("Starting main program");
319              
320             with log4perl.conf like:
321              
322             # Send a copy of all logging messages to STDERR
323             log4perl.rootLogger=DEBUG,STDERR
324              
325             # Logging specific for your main program
326             log4perl.category.myprog=INFO,STDERR
327              
328             # Logging specific for on part of Catmandu
329             log4perl.category.Catmandu::Fix=DEBUG,STDERR
330              
331             # Where to send the STDERR output
332             log4perl.appender.STDERR=Log::Log4perl::Appender::Screen
333             log4perl.appender.STDERR.stderr=1
334             log4perl.appender.STDERR.utf8=1
335              
336             log4perl.appender.STDERR.layout=PatternLayout
337             log4perl.appender.STDERR.layout.ConversionPattern=%d [%P] - %p %l time=%r : %m%n
338              
339             =head2 default_load_path(['/default/path'])
340              
341             Returns the default location where L<Catmandu> looks for configuration and lib
342             when called with no argument. Sets the default location if a path is given.
343             The default load path is the script directory or it's parent if the script
344             directory is C<bin>.
345              
346             =head2 load
347              
348             Load all the configuration options in the catmandu.yml configuration file.
349             See CONFIG below for extended examples of configuration options.
350              
351             =head2 load('/path', '/another/path')
352              
353             Load all the configuration options stored at alternative paths.
354              
355             A load path C<':up'> will search upwards from your program for configuration.
356              
357             See CONFIG below for extended examples of configuration options.
358              
359             =head2 roots
360              
361             Returns an ARRAYREF of paths where configuration was found. Note that this list
362             is empty before C<load>.
363              
364             =head2 root
365              
366             Returns the first path where configuration was found. Note that this is
367             C<undef> before C<load>.
368              
369             =head2 config
370              
371             Returns the current configuration as a HASHREF.
372              
373             =head2 config($config)
374              
375             Set a new configuration and reload the environment.
376              
377             =head2 default_store
378              
379             Return the name of the default store.
380              
381             =head2 store([NAME])
382              
383             Return an instance of L<Catmandu::Store>. The NAME is a name of a L<Catmandu::Store> or the
384             name of a store configured in a catmandu.yml configuration file. When no NAME is given, the
385             'default' store in the configuration file will be used.
386              
387             E.g. if the configuration file 'catmandu.yml' contains:
388              
389             store:
390             default:
391             package: ElasticSearch
392             options:
393             index_name: blog
394             test:
395             package: Mock
396              
397             then in your program:
398              
399             # This will use ElasticSearch
400             my $store = Catmandu->store('ElasticSearch', index_name => 'blog');
401              
402             # or because we have a 'default' set in the configuration file
403              
404             my $store = Catmandu->store('default');
405              
406             # or because 'default' will be used when no name was provided
407              
408             my $store = Catmandu->store;
409              
410             # This will use Mock
411             my $store = Catmandu->store('test');
412              
413             Configuration settings can be overwritten by the store command:
414              
415             my $store2 = Catmandu->store('default', index_name => 'test2');
416              
417             =head2 default_fixer
418              
419             Return the name of the default fixer.
420              
421             =head2 fixer(NAME)
422              
423             =head2 fixer(FIX,FIX)
424              
425             =head2 fixer([FIX])
426              
427             Return an instance of L<Catmandu::Fix>. NAME can be the name of a fixer section
428             in a catmandu.yml file. Or, one or more L<Catmandu::Fix>-es can be provided inline.
429              
430             E.g. if the configuration file 'catmandu.yml' contains:
431              
432             fixer:
433             default:
434             - do_this()
435             - do_that()
436              
437             then in your program al these lines below will create the same fixer:
438              
439             my $fixer = Catmandu->fixer('do_this()', 'do_that()');
440             my $fixer = Catmandu->fixer(['do_this()', 'do_that()']);
441             my $fixer = Catmandu->fixer('default');
442             my $fixer = Catmandu->fixer(); # The default name is 'default'
443              
444             FIX-es can be also written to a Fix script. E.g. if myfixes.txt contains:
445              
446             do_this()
447             do_that()
448              
449             then the above code will even be equivalent to:
450              
451             my $fixer = Catmandu->fixer('myfixes.txt');
452              
453             =head2 default_importer
454              
455             Return the name of the default importer.
456              
457             =head2 default_importer_package
458              
459             Return the name of the default importer package if no
460             package name is given in the config or as a param.
461              
462             =head2 importer(NAME)
463              
464             Return an instance of L<Catmandu::Importer>. The NAME is a name of a L<Catmandu::Importer> or the
465             name of a importer configured in a catmandu.yml configuration file. When no NAME is given, the
466             'default' importer in the configuration file will be used.
467              
468             E.g. if the configuration file 'catmandu.yml' contains:
469              
470             importer:
471             default:
472             package: OAI
473             options:
474             url: http://www.instute.org/oai/
475              
476             then in your program all these lines will be equivalent:
477              
478             my $importer = Catmandu->importer('OAI', url => 'http://www.instute.org/oai/');
479             my $importer = Catmandu->importer('default');
480             my $importer = Catmandu->importer(); # The default name is 'default'
481              
482             Configuration settings can be overwritten by the importer command:
483              
484             my $importer2 = Catmandu->importer('default', url => 'http://other.institute.org');
485              
486             =head2 default_exporter
487              
488             Return the name of the default exporter.
489              
490             =head2 default_exporter_package
491              
492             Return the name of the default exporter package if no
493             package name is given in the config or as a param.
494              
495             =head2 exporter([NAME])
496              
497             Return an instance of L<Catmandu::Exporter> with name NAME (or the default when
498             no name is given). The NAME can be in a configuration file (see 'importer').
499              
500             =head2 validator([NAME])
501              
502             Return an instance of L<Catmandu::Validator> with name NAME (or the default when
503             no name is given). The NAME can be in a configuration file (see 'importer').
504              
505             =head2 export($data,[NAME])
506              
507             Export data using a default or named exporter or exporter instance.
508              
509             Catmandu->export({ foo=>'bar'});
510              
511             my $importer = Catmandu::Importer::Mock->new;
512             Catmandu->export($importer, 'YAML', file => '/my/file');
513             Catmandu->export($importer, 'my_exporter');
514             Catmandu->export($importer, 'my_exporter', exporter_option => '...' , ...);
515             Catmantu->export($importer, Catmandu::Exporter::YAML->new);
516              
517             =head2 export_to_string
518              
519             Export data using a default or named exporter to a string.
520              
521             my $importer = Catmandu::Importer::Mock->new;
522             my $yaml = Catmandu->export_to_string($importer, 'YAML');
523             # is the same as
524             my $yaml = "";
525             Catmandu->export($importer, 'YAML', file => \$yaml);
526              
527             =head2 import_from_string
528              
529             Import data from a string using a default or named importer.
530             Return value should be an array of hashes.
531              
532             my $json = qq([{"name":"Nicolas"}]);
533             {
534             my $record = Catmandu->import_from_string( $json, "JSON" );
535             }
536             # is the same as
537             {
538             my $record = Catmandu->importer('JSON', file => \$json)->to_array()
539             }
540              
541             =head2 define_importer
542              
543             Configure a new named importer.
544              
545             Catmandu->define_importer(books => CSV => (fields => 'title,author,publisher'));
546             Catmandu->importer(books => (file => 'mybooks.csv'))->each(sub {
547             my $book = shift;
548             say $book->{title};
549             });
550              
551             # this is equivalent to
552              
553             Catmandu->config->{importer}{books} = {
554             package => 'CSV',
555             options => {
556             fields => 'title,author,publisher',
557             },
558             }
559              
560             =head2 define_exporter
561              
562             Configure a new named exporter.
563              
564             Catmandu->define_exporter('books', 'CSV', fix => 'capitalize(title)');
565             my $csv = Catmandu->export_to_string({title => 'nexus'}, 'books');
566              
567             # this is equivalent to
568              
569             Catmandu->config->{exporter}{books} = {
570             package => 'CSV',
571             options => {
572             fix => 'capitalize(title)',
573             },
574             }
575              
576             =head2 define_store
577              
578             Configure a new named store.
579              
580             Catmandu->define_store(mydb => MongoDB => (database_name => 'mydb'));
581             Catmandu->store->bag('books')->get(1234);
582              
583             # this is equivalent to
584              
585             Catmandu->config->{store}{mydb} = {
586             package => 'MongoDB',
587             options => {
588             database_name => 'mydb',
589             },
590             }
591              
592             =head2 define_fixer
593              
594             Configure a new named fixer.
595              
596             Catmandu->define_fixer('cleanup', [
597             'trim(title)',
598             'capitalize(title)',
599             'remove_field(junk)',
600             # ...
601             ]);
602             Catmandu->fixer('cleanup')->fix($record);
603              
604             =head1 EXPORTS
605              
606             =over
607              
608             =item config
609              
610             Same as C<< Catmandu->config >>.
611              
612             =item store
613              
614             Same as C<< Catmandu->store >>.
615              
616             =item importer
617              
618             Same as C<< Catmandu->importer >>.
619              
620             =item exporter
621              
622             Same as C<< Catmandu->exporter >>.
623              
624             =item validator
625              
626             Same as C<< Catmandu->validator >>.
627              
628             =item export
629              
630             Same as C<< Catmandu->export >>.
631              
632             =item export_to_string
633              
634             Same as C<< Catmandu->export_to_string >>.
635              
636             =item import_from_string
637              
638             Same as C<< Catmandu->import_from_string >>.
639              
640             =item fixer
641              
642             Same as C<< Catmandu->fixer >>.
643              
644             =item log
645              
646             Same as C<< Catmandu->log >>.
647              
648             =item -all/:all
649              
650             Import everything.
651              
652             =item -load/:load
653              
654             use Catmandu -load;
655             use Catmandu -load => [];
656             # is the same as
657             Catmandu->load;
658              
659             use Catmandu -load => ['/config/path'];
660             # is the same as
661             Catmandu->load('/config/path');
662              
663             =back
664              
665             =head1 CONFIG
666              
667             Catmandu configuration options can be stored in files in the root directory of
668             your programming project. The file can be YAML, JSON or Perl and is called
669             C<catmandu.yml>, C<catmandu.json> or C<catmandu.pl>. In this file you can set
670             the default Catmandu stores and exporters to be used. Here is an example of a
671             C<catmandu.yml> file:
672              
673             store:
674             default:
675             package: ElasticSearch
676             options:
677             index_name: myrepository
678              
679             exporter:
680             default:
681             package: YAML
682              
683             =head2 Split config
684              
685             For large configs it's more convenient to split the config into several files.
686             You can do so by having multiple config files starting with catmandu*.
687              
688             catmandu.general.yml
689             catmandu.db.yml
690             ...
691              
692             Split config files are processed and merged by L<Config::Onion>.
693              
694             =head2 Deeply nested config structures
695              
696             Config files can indicate a path under which their keys will be nested. This
697             makes your configuration more readable by keeping indentation to a minimum.
698              
699             A config file containing
700              
701             _prefix:
702             foo:
703             bar:
704             baz: 1
705              
706             will be loaded as
707              
708             foo:
709             bar:
710             baz: 1
711              
712             See L<Config::Onion> for more information on how this works.
713              
714             =head1 SEE ALSO
715              
716             =over 4
717              
718             =item documentation
719              
720             L<http://librecat.org/Catmandu/>
721              
722             =item blog
723              
724             L<https://librecatproject.wordpress.com/>
725              
726             =item step-by-step introduction from basics
727              
728             L<https://librecatproject.wordpress.com/2014/12/01/day-1-getting-catmandu/>
729              
730             =item command line client
731              
732             L<catmandu>
733              
734             =item core modules
735              
736             L<Catmandu::Importer>
737             L<Catmandu::Exporter>,
738             L<Catmandu::Store>,
739             L<Catmandu::Fix>,
740             L<Catmandu::Iterable>
741              
742             =item extended features
743              
744             L<Catmandu::Validator>
745              
746             =back
747              
748             =head1 AUTHOR
749              
750             Nicolas Steenlant, C<< <nicolas.steenlant at ugent.be> >>
751              
752             =head1 CONTRIBUTORS
753              
754             Magnus Enger, C<< magnus at enger.priv.no >>
755              
756             Nicolas Franck, C<< nicolas.franck at ugent.be >>
757              
758             Patrick Hochstenbach, C<< patrick.hochstenbach at ugent.be >>
759              
760             Vitali Peil, C<< vitali.peil at uni-bielefeld.de >>
761              
762             Christian Pietsch, C<< christian.pietsch at uni-bielefeld.de >>
763              
764             Dave Sherohman, C<< dave.sherohman at ub.lu.se >>
765              
766             Jakob Voss, C<< nichtich at cpan.org >>
767              
768             Snorri Briem, C<< snorri.briem at ub.lu.se >>
769              
770             Johann Rolschewski, C<< jorol at cpan.org >>
771              
772             Pieter De Praetere, C<< pieter.de.praetere at helptux.be >>
773              
774             Doug Bell
775              
776             Upsana, C<< me at upasana.me >>
777              
778             Stefan Weil
779              
780             Tom Hukins
781              
782             =head1 QUESTIONS, ISSUES & BUG REPORTS
783              
784             For any questions on the use of our modules please join our mailing list at:
785              
786             librecat-dev@lists.uni-bielefeld.de
787              
788             or send in your bug reports or feature requests to our issue tracker at:
789              
790             https://github.com/LibreCat/Catmandu/issues
791              
792             =head1 LICENSE AND COPYRIGHT
793              
794             This program is free software; you can redistribute it and/or modify it
795             under the terms of either: the GNU General Public License as published
796             by the Free Software Foundation; or the Artistic License.
797              
798             See L<http://dev.perl.org/licenses/> for more information.
799              
800             =cut