Stop using the deprecated Class::MOP::load_class()
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Optional / Dependencies.pm
1 package DBIx::Class::Optional::Dependencies;
2
3 use warnings;
4 use strict;
5
6 use Carp ();
7
8 # NO EXTERNAL NON-5.8.1 CORE DEPENDENCIES EVER (e.g. C::A::G)
9 # This module is to be loaded by Makefile.PM on a pristine system
10
11 # POD is generated automatically by calling _gen_pod from the
12 # Makefile.PL in $AUTHOR mode
13
14 my $json_any = {
15   'JSON::Any'                     => '1.22',
16 };
17
18 my $moose_basic = {
19   'Moose'                         => '0.98',
20   'MooseX::Types'                 => '0.21',
21   'MooseX::Types::LoadableClass'  => '0.011',
22 };
23
24 my $replicated = {
25   %$moose_basic,
26 };
27
28 my $admin_basic = {
29   %$moose_basic,
30   %$json_any,
31   'MooseX::Types::Path::Class'    => '0.05',
32   'MooseX::Types::JSON'           => '0.02',
33   'namespace::autoclean'          => '0.09',
34 };
35
36 my $admin_script = {
37   %$moose_basic,
38   %$admin_basic,
39   'Getopt::Long::Descriptive' => '0.081',
40   'Text::CSV'                 => '1.16',
41 };
42
43 my $datetime_basic = {
44   'DateTime'                      => '0.55',
45   'DateTime::Format::Strptime'    => '1.2',
46 };
47
48 my $id_shortener = {
49   'Math::BigInt'                  => '1.80',
50   'Math::Base36'                  => '0.07',
51 };
52
53 my $rdbms_sqlite = {
54   'DBD::SQLite'                   => '0',
55 };
56 my $rdbms_pg = {
57   'DBD::Pg'                       => '0',
58 };
59 my $rdbms_mssql_odbc = {
60   'DBD::ODBC'                     => '0',
61 };
62 my $rdbms_mssql_sybase = {
63   'DBD::Sybase'                   => '0',
64 };
65 my $rdbms_mssql_ado = {
66   'DBD::ADO'                      => '0',
67 };
68 my $rdbms_msaccess_odbc = {
69   'DBD::ODBC'                     => '0',
70 };
71 my $rdbms_msaccess_ado = {
72   'DBD::ADO'                      => '0',
73 };
74 my $rdbms_mysql = {
75   'DBD::mysql'                    => '0',
76 };
77 my $rdbms_oracle = {
78   'DBD::Oracle'                   => '0',
79   %$id_shortener,
80 };
81 my $rdbms_ase = {
82   'DBD::Sybase'                   => '0',
83 };
84 my $rdbms_db2 = {
85   'DBD::DB2'                      => '0',
86 };
87 my $rdbms_db2_400 = {
88   'DBD::ODBC'                     => '0',
89 };
90 my $rdbms_informix = {
91   'DBD::Informix'                 => '0',
92 };
93 my $rdbms_sqlanywhere = {
94   'DBD::SQLAnywhere'              => '0',
95 };
96 my $rdbms_sqlanywhere_odbc = {
97   'DBD::ODBC'                     => '0',
98 };
99 my $rdbms_firebird = {
100   'DBD::Firebird'                 => '0',
101 };
102 my $rdbms_firebird_interbase = {
103   'DBD::InterBase'                => '0',
104 };
105 my $rdbms_firebird_odbc = {
106   'DBD::ODBC'                     => '0',
107 };
108
109 my $reqs = {
110   replicated => {
111     req => $replicated,
112     pod => {
113       title => 'Storage::Replicated',
114       desc => 'Modules required for L<DBIx::Class::Storage::DBI::Replicated>',
115     },
116   },
117
118   test_replicated => {
119     req => {
120       %$replicated,
121       'Test::Moose'               => '0',
122     },
123   },
124
125
126   admin => {
127     req => {
128       %$admin_basic,
129     },
130     pod => {
131       title => 'DBIx::Class::Admin',
132       desc => 'Modules required for the DBIx::Class administrative library',
133     },
134   },
135
136   admin_script => {
137     req => {
138       %$admin_script,
139     },
140     pod => {
141       title => 'dbicadmin',
142       desc => 'Modules required for the CLI DBIx::Class interface dbicadmin',
143     },
144   },
145
146   deploy => {
147     req => {
148       'SQL::Translator'           => '0.11016',
149     },
150     pod => {
151       title => 'Storage::DBI::deploy()',
152       desc => 'Modules required for L<DBIx::Class::Storage::DBI/deploy> and L<DBIx::Class::Storage::DBI/deployment_statements>',
153     },
154   },
155
156   id_shortener => {
157     req => $id_shortener,
158   },
159
160   test_component_accessor => {
161     req => {
162       'Class::Unload'             => '0.07',
163     },
164   },
165
166   test_pod => {
167     req => {
168       'Test::Pod'                 => '1.42',
169     },
170   },
171
172   test_podcoverage => {
173     req => {
174       'Test::Pod::Coverage'       => '1.08',
175       'Pod::Coverage'             => '0.20',
176     },
177   },
178
179   test_whitespace => {
180     req => {
181       'Test::EOL'                 => '1.0',
182       'Test::NoTabs'              => '0.9',
183     },
184   },
185
186   test_strictures => {
187     req => {
188       'Test::Strict'              => '0.20',
189     },
190   },
191
192   test_prettydebug => {
193     req => $json_any,
194   },
195
196   test_admin_script => {
197     req => {
198       %$admin_script,
199       'JSON' => 0,
200       'JSON::XS' => 0,
201       $^O eq 'MSWin32'
202         # for t/admin/10script.t
203         ? ('Win32::ShellQuote' => 0)
204         # DWIW does not compile (./configure even) on win32
205         : ('JSON::DWIW' => 0 )
206       ,
207     }
208   },
209
210   test_leaks => {
211     req => {
212       'Test::Memory::Cycle'       => '0',
213       'Devel::Cycle'              => '1.10',
214     },
215   },
216
217   test_dt => {
218     req => $datetime_basic,
219   },
220
221   test_dt_sqlite => {
222     req => {
223       %$datetime_basic,
224       # t/36datetime.t
225       # t/60core.t
226       'DateTime::Format::SQLite'  => '0',
227     },
228   },
229
230   test_dt_mysql => {
231     req => {
232       %$datetime_basic,
233       # t/inflate/datetime_mysql.t
234       # (doesn't need Mysql itself)
235       'DateTime::Format::MySQL'   => '0',
236     },
237   },
238
239   test_dt_pg => {
240     req => {
241       %$datetime_basic,
242       # t/inflate/datetime_pg.t
243       # (doesn't need PG itself)
244       'DateTime::Format::Pg'      => '0.16004',
245     },
246   },
247
248   test_cdbicompat => {
249     req => {
250       'Class::DBI::Plugin::DeepAbstractSearch' => '0',
251       %$datetime_basic,
252       'Time::Piece::MySQL'        => '0',
253       'Date::Simple'              => '3.03',
254     },
255   },
256
257   # this is just for completeness as SQLite
258   # is a core dep of DBIC for testing
259   rdbms_sqlite => {
260     req => {
261       %$rdbms_sqlite,
262     },
263     pod => {
264       title => 'SQLite support',
265       desc => 'Modules required to connect to SQLite',
266     },
267   },
268
269   rdbms_pg => {
270     req => {
271       # when changing this list make sure to adjust xt/optional_deps.t
272       %$rdbms_pg,
273     },
274     pod => {
275       title => 'PostgreSQL support',
276       desc => 'Modules required to connect to PostgreSQL',
277     },
278   },
279
280   rdbms_mssql_odbc => {
281     req => {
282       %$rdbms_mssql_odbc,
283     },
284     pod => {
285       title => 'MSSQL support via DBD::ODBC',
286       desc => 'Modules required to connect to MSSQL via DBD::ODBC',
287     },
288   },
289
290   rdbms_mssql_sybase => {
291     req => {
292       %$rdbms_mssql_sybase,
293     },
294     pod => {
295       title => 'MSSQL support via DBD::Sybase',
296       desc => 'Modules required to connect to MSSQL via DBD::Sybase',
297     },
298   },
299
300   rdbms_mssql_ado => {
301     req => {
302       %$rdbms_mssql_ado,
303     },
304     pod => {
305       title => 'MSSQL support via DBD::ADO (Windows only)',
306       desc => 'Modules required to connect to MSSQL via DBD::ADO. This particular DBD is available on Windows only',
307     },
308   },
309
310   rdbms_msaccess_odbc => {
311     req => {
312       %$rdbms_msaccess_odbc,
313     },
314     pod => {
315       title => 'MS Access support via DBD::ODBC',
316       desc => 'Modules required to connect to MS Access via DBD::ODBC',
317     },
318   },
319
320   rdbms_msaccess_ado => {
321     req => {
322       %$rdbms_msaccess_ado,
323     },
324     pod => {
325       title => 'MS Access support via DBD::ADO (Windows only)',
326       desc => 'Modules required to connect to MS Access via DBD::ADO. This particular DBD is available on Windows only',
327     },
328   },
329
330   rdbms_mysql => {
331     req => {
332       %$rdbms_mysql,
333     },
334     pod => {
335       title => 'MySQL support',
336       desc => 'Modules required to connect to MySQL',
337     },
338   },
339
340   rdbms_oracle => {
341     req => {
342       %$rdbms_oracle,
343     },
344     pod => {
345       title => 'Oracle support',
346       desc => 'Modules required to connect to Oracle',
347     },
348   },
349
350   rdbms_ase => {
351     req => {
352       %$rdbms_ase,
353     },
354     pod => {
355       title => 'Sybase ASE support',
356       desc => 'Modules required to connect to Sybase ASE',
357     },
358   },
359
360   rdbms_db2 => {
361     req => {
362       %$rdbms_db2,
363     },
364     pod => {
365       title => 'DB2 support',
366       desc => 'Modules required to connect to DB2',
367     },
368   },
369
370   rdbms_db2_400 => {
371     req => {
372       %$rdbms_db2_400,
373     },
374     pod => {
375       title => 'DB2 on AS/400 support',
376       desc => 'Modules required to connect to DB2 on AS/400',
377     },
378   },
379
380   rdbms_informix => {
381     req => {
382       %$rdbms_informix,
383     },
384     pod => {
385       title => 'Informix support',
386       desc => 'Modules required to connect to Informix',
387     },
388   },
389
390   rdbms_sqlanywhere => {
391     req => {
392       %$rdbms_sqlanywhere,
393     },
394     pod => {
395       title => 'SQLAnywhere support',
396       desc => 'Modules required to connect to SQLAnywhere',
397     },
398   },
399
400   rdbms_sqlanywhere_odbc => {
401     req => {
402       %$rdbms_sqlanywhere_odbc,
403     },
404     pod => {
405       title => 'SQLAnywhere support via DBD::ODBC',
406       desc => 'Modules required to connect to SQLAnywhere via DBD::ODBC',
407     },
408   },
409
410   rdbms_firebird => {
411     req => {
412       %$rdbms_firebird,
413     },
414     pod => {
415       title => 'Firebird support',
416       desc => 'Modules required to connect to Firebird',
417     },
418   },
419
420   rdbms_firebird_interbase => {
421     req => {
422       %$rdbms_firebird_interbase,
423     },
424     pod => {
425       title => 'Firebird support via DBD::InterBase',
426       desc => 'Modules required to connect to Firebird via DBD::InterBase',
427     },
428   },
429
430   rdbms_firebird_odbc => {
431     req => {
432       %$rdbms_firebird_odbc,
433     },
434     pod => {
435       title => 'Firebird support via DBD::ODBC',
436       desc => 'Modules required to connect to Firebird via DBD::ODBC',
437     },
438   },
439
440 # the order does matter because the rdbms support group might require
441 # a different version that the test group
442   test_rdbms_pg => {
443     req => {
444       $ENV{DBICTEST_PG_DSN}
445         ? (
446           # when changing this list make sure to adjust xt/optional_deps.t
447           %$rdbms_pg,
448           ($^O ne 'MSWin32' ? ('Sys::SigAction' => '0') : ()),
449           'DBD::Pg'               => '2.009002',
450         ) : ()
451     },
452   },
453
454   test_rdbms_mssql_odbc => {
455     req => {
456       $ENV{DBICTEST_MSSQL_ODBC_DSN}
457         ? (
458           %$rdbms_mssql_odbc,
459         ) : ()
460     },
461   },
462
463   test_rdbms_mssql_ado => {
464     req => {
465       $ENV{DBICTEST_MSSQL_ADO_DSN}
466         ? (
467           %$rdbms_mssql_ado,
468         ) : ()
469     },
470   },
471
472   test_rdbms_mssql_sybase => {
473     req => {
474       $ENV{DBICTEST_MSSQL_DSN}
475         ? (
476           %$rdbms_mssql_sybase,
477         ) : ()
478     },
479   },
480
481   test_rdbms_msaccess_odbc => {
482     req => {
483       $ENV{DBICTEST_MSACCESS_ODBC_DSN}
484         ? (
485           %$rdbms_msaccess_odbc,
486           %$datetime_basic,
487           'Data::GUID' => '0',
488         ) : ()
489     },
490   },
491
492   test_rdbms_msaccess_ado => {
493     req => {
494       $ENV{DBICTEST_MSACCESS_ADO_DSN}
495         ? (
496           %$rdbms_msaccess_ado,
497           %$datetime_basic,
498           'Data::GUID' => 0,
499         ) : ()
500     },
501   },
502
503   test_rdbms_mysql => {
504     req => {
505       $ENV{DBICTEST_MYSQL_DSN}
506         ? (
507           %$rdbms_mysql,
508         ) : ()
509     },
510   },
511
512   test_rdbms_oracle => {
513     req => {
514       $ENV{DBICTEST_ORA_DSN}
515         ? (
516           %$rdbms_oracle,
517           'DateTime::Format::Oracle' => '0',
518           'DBD::Oracle'              => '1.24',
519         ) : ()
520     },
521   },
522
523   test_rdbms_ase => {
524     req => {
525       $ENV{DBICTEST_SYBASE_DSN}
526         ? (
527           %$rdbms_ase,
528         ) : ()
529     },
530   },
531
532   test_rdbms_db2 => {
533     req => {
534       $ENV{DBICTEST_DB2_DSN}
535         ? (
536           %$rdbms_db2,
537         ) : ()
538     },
539   },
540
541   test_rdbms_db2_400 => {
542     req => {
543       $ENV{DBICTEST_DB2_400_DSN}
544         ? (
545           %$rdbms_db2_400,
546         ) : ()
547     },
548   },
549
550   test_rdbms_informix => {
551     req => {
552       $ENV{DBICTEST_INFORMIX_DSN}
553         ? (
554           %$rdbms_informix,
555         ) : ()
556     },
557   },
558
559   test_rdbms_sqlanywhere => {
560     req => {
561       $ENV{DBICTEST_SQLANYWHERE_DSN}
562         ? (
563           %$rdbms_sqlanywhere,
564         ) : ()
565     },
566   },
567
568   test_rdbms_sqlanywhere_odbc => {
569     req => {
570       $ENV{DBICTEST_SQLANYWHERE_ODBC_DSN}
571         ? (
572           %$rdbms_sqlanywhere_odbc,
573         ) : ()
574     },
575   },
576
577   test_rdbms_firebird => {
578     req => {
579       $ENV{DBICTEST_FIREBIRD_DSN}
580         ? (
581           %$rdbms_firebird,
582         ) : ()
583     },
584   },
585
586   test_rdbms_firebird_interbase => {
587     req => {
588       $ENV{DBICTEST_FIREBIRD_INTERBASE_DSN}
589         ? (
590           %$rdbms_firebird_interbase,
591         ) : ()
592     },
593   },
594
595   test_rdbms_firebird_odbc => {
596     req => {
597       $ENV{DBICTEST_FIREBIRD_ODBC_DSN}
598         ? (
599           %$rdbms_firebird_odbc,
600         ) : ()
601     },
602   },
603
604   test_memcached => {
605     req => {
606       $ENV{DBICTEST_MEMCACHED}
607         ? (
608           'Cache::Memcached' => 0,
609         ) : ()
610     },
611   },
612
613   dist_dir => {
614     req => {
615       'ExtUtils::MakeMaker' => '6.64',
616       'Pod::Inherit'        => '0.90',
617       'Pod::Tree'           => '0',
618     }
619   },
620
621   dist_upload => {
622     req => {
623       'CPAN::Uploader' => '0.103001',
624     },
625   },
626
627 };
628
629 our %req_availability_cache;
630
631 sub req_list_for {
632   my ($class, $group) = @_;
633
634   Carp::croak "req_list_for() expects a requirement group name"
635     unless $group;
636
637   my $deps = $reqs->{$group}{req}
638     or Carp::croak "Requirement group '$group' does not exist";
639
640   return { %$deps };
641 }
642
643
644 sub die_unless_req_ok_for {
645   my ($class, $group) = @_;
646
647   Carp::croak "die_unless_req_ok_for() expects a requirement group name"
648     unless $group;
649
650   $class->_check_deps($group)->{status}
651     or die sprintf( "Required modules missing, unable to continue: %s\n", $class->_check_deps($group)->{missing} );
652 }
653
654 sub req_ok_for {
655   my ($class, $group) = @_;
656
657   Carp::croak "req_ok_for() expects a requirement group name"
658     unless $group;
659
660   return $class->_check_deps($group)->{status};
661 }
662
663 sub req_missing_for {
664   my ($class, $group) = @_;
665
666   Carp::croak "req_missing_for() expects a requirement group name"
667     unless $group;
668
669   return $class->_check_deps($group)->{missing};
670 }
671
672 sub req_errorlist_for {
673   my ($class, $group) = @_;
674
675   Carp::croak "req_errorlist_for() expects a requirement group name"
676     unless $group;
677
678   return $class->_check_deps($group)->{errorlist};
679 }
680
681 sub _check_deps {
682   my ($class, $group) = @_;
683
684   return $req_availability_cache{$group} ||= do {
685
686     my $deps = $class->req_list_for ($group);
687
688     my %errors;
689     for my $mod (keys %$deps) {
690       my $req_line = "require $mod;";
691       if (my $ver = $deps->{$mod}) {
692         $req_line .= "$mod->VERSION($ver);";
693       }
694
695       eval $req_line;
696
697       $errors{$mod} = $@ if $@;
698     }
699
700     my $res;
701
702     if (keys %errors) {
703       my $missing = join (', ', map { $deps->{$_} ? "$_ >= $deps->{$_}" : $_ } (sort keys %errors) );
704       $missing .= " (see $class for details)" if $reqs->{$group}{pod};
705       $res = {
706         status => 0,
707         errorlist => \%errors,
708         missing => $missing,
709       };
710     }
711     else {
712       $res = {
713         status => 1,
714         errorlist => {},
715         missing => '',
716       };
717     }
718
719     $res;
720   };
721 }
722
723 sub req_group_list {
724   return { map { $_ => { %{ $reqs->{$_}{req} || {} } } } (keys %$reqs) };
725 }
726
727 # This is to be called by the author only (automatically in Makefile.PL)
728 sub _gen_pod {
729   my ($class, $distver, $pod_dir) = @_;
730
731   die "No POD root dir supplied" unless $pod_dir;
732
733   $distver ||=
734     eval { require DBIx::Class; DBIx::Class->VERSION; }
735       ||
736     die
737 "\n\n---------------------------------------------------------------------\n" .
738 'Unable to load core DBIx::Class module to determine current version, '.
739 'possibly due to missing dependencies. Author-mode autodocumentation ' .
740 "halted\n\n" . $@ .
741 "\n\n---------------------------------------------------------------------\n"
742   ;
743
744   # do not ask for a recent version, use 1.x API calls
745   # this *may* execute on a smoker with old perl or whatnot
746   require File::Path;
747
748   (my $modfn = __PACKAGE__ . '.pm') =~ s|::|/|g;
749
750   (my $podfn = "$pod_dir/$modfn") =~ s/\.pm$/\.pod/;
751   (my $dir = $podfn) =~ s|/[^/]+$||;
752
753   File::Path::mkpath([$dir]);
754
755   my $sqltver = $class->req_list_for ('deploy')->{'SQL::Translator'}
756     or die "Hrmm? No sqlt dep?";
757
758   my @chunks = (
759     <<"EOC",
760 #########################################################################
761 #####################  A U T O G E N E R A T E D ########################
762 #########################################################################
763 #
764 # The contents of this POD file are auto-generated.  Any changes you make
765 # will be lost. If you need to change the generated text edit _gen_pod()
766 # at the end of $modfn
767 #
768 EOC
769     '=head1 NAME',
770     "$class - Optional module dependency specifications (for module authors)",
771     '=head1 SYNOPSIS',
772     <<"EOS",
773 Somewhere in your build-file (e.g. L<Module::Install>'s Makefile.PL):
774
775   ...
776
777   configure_requires 'DBIx::Class' => '$distver';
778
779   require $class;
780
781   my \$deploy_deps = $class->req_list_for('deploy');
782
783   for (keys %\$deploy_deps) {
784     requires \$_ => \$deploy_deps->{\$_};
785   }
786
787   ...
788
789 Note that there are some caveats regarding C<configure_requires()>, more info
790 can be found at L<Module::Install/configure_requires>
791 EOS
792     '=head1 DESCRIPTION',
793     <<'EOD',
794 Some of the less-frequently used features of L<DBIx::Class> have external
795 module dependencies on their own. In order not to burden the average user
796 with modules he will never use, these optional dependencies are not included
797 in the base Makefile.PL. Instead an exception with a descriptive message is
798 thrown when a specific feature is missing one or several modules required for
799 its operation. This module is the central holding place for  the current list
800 of such dependencies, for DBIx::Class core authors, and DBIx::Class extension
801 authors alike.
802 EOD
803     '=head1 CURRENT REQUIREMENT GROUPS',
804     <<'EOD',
805 Dependencies are organized in C<groups> and each group can list one or more
806 required modules, with an optional minimum version (or 0 for any version).
807 The group name can be used in the
808 EOD
809   );
810
811   for my $group (sort keys %$reqs) {
812     my $p = $reqs->{$group}{pod}
813       or next;
814
815     my $modlist = $reqs->{$group}{req}
816       or next;
817
818     next unless keys %$modlist;
819
820     push @chunks, (
821       "=head2 $p->{title}",
822       "$p->{desc}",
823       '=over',
824       ( map { "=item * $_" . ($modlist->{$_} ? " >= $modlist->{$_}" : '') } (sort keys %$modlist) ),
825       '=back',
826       "Requirement group: B<$group>",
827     );
828   }
829
830   push @chunks, (
831     '=head1 METHODS',
832     '=head2 req_group_list',
833     '=over',
834     '=item Arguments: none',
835     '=item Return Value: \%list_of_requirement_groups',
836     '=back',
837     <<'EOD',
838 This method should be used by DBIx::Class packagers, to get a hashref of all
839 dependencies keyed by dependency group. Each key (group name) can be supplied
840 to one of the group-specific methods below.
841 EOD
842
843     '=head2 req_list_for',
844     '=over',
845     '=item Arguments: $group_name',
846     '=item Return Value: \%list_of_module_version_pairs',
847     '=back',
848     <<'EOD',
849 This method should be used by DBIx::Class extension authors, to determine the
850 version of modules a specific feature requires in the B<current> version of
851 DBIx::Class. See the L</SYNOPSIS> for a real-world
852 example.
853 EOD
854
855     '=head2 req_ok_for',
856     '=over',
857     '=item Arguments: $group_name',
858     '=item Return Value: 1|0',
859     '=back',
860     <<'EOD',
861 Returns true or false depending on whether all modules required by
862 C<$group_name> are present on the system and loadable.
863 EOD
864
865     '=head2 req_missing_for',
866     '=over',
867     '=item Arguments: $group_name',
868     '=item Return Value: $error_message_string',
869     '=back',
870     <<"EOD",
871 Returns a single line string suitable for inclusion in larger error messages.
872 This method would normally be used by DBIx::Class core-module author, to
873 indicate to the user that he needs to install specific modules before he will
874 be able to use a specific feature.
875
876 For example if some of the requirements for C<deploy> are not available,
877 the returned string could look like:
878
879  SQL::Translator >= $sqltver (see $class for details)
880
881 The author is expected to prepend the necessary text to this message before
882 returning the actual error seen by the user.
883 EOD
884
885     '=head2 die_unless_req_ok_for',
886     '=over',
887     '=item Arguments: $group_name',
888     '=back',
889     <<'EOD',
890 Checks if L</req_ok_for> passes for the supplied C<$group_name>, and
891 in case of failure throws an exception including the information
892 from L</req_missing_for>.
893 EOD
894
895     '=head2 req_errorlist_for',
896     '=over',
897     '=item Arguments: $group_name',
898     '=item Return Value: \%list_of_loaderrors_per_module',
899     '=back',
900     <<'EOD',
901 Returns a hashref containing the actual errors that occurred while attempting
902 to load each module in the requirement group.
903 EOD
904     '=head1 AUTHOR',
905     'See L<DBIx::Class/CONTRIBUTORS>.',
906     '=head1 LICENSE',
907     'You may distribute this code under the same terms as Perl itself',
908   );
909
910   open (my $fh, '>', $podfn) or Carp::croak "Unable to write to $podfn: $!";
911   print $fh join ("\n\n", @chunks);
912   print $fh "\n";
913   close ($fh);
914 }
915
916 1;