1 package DBIx::Class::Optional::Dependencies;
3 ### This may look crazy, but it in fact tangibly ( by 50(!)% ) shortens
4 # the skip-test time when everything requested is unavailable
5 use if $ENV{RELEASE_TESTING} => 'warnings';
6 use if $ENV{RELEASE_TESTING} => 'strict';
14 # NO EXTERNAL NON-5.8.1 CORE DEPENDENCIES EVER (e.g. C::A::G)
15 # This module is to be loaded by Makefile.PM on a pristine system
17 # POD is generated automatically by calling _gen_pod from the
18 # Makefile.PL in $AUTHOR mode
20 # *DELIBERATELY* not making a group for these - they must disappear
21 # forever as optdeps in the first place
24 'MooseX::Types' => '0.21',
25 'MooseX::Types::LoadableClass' => '0.011',
30 # NOTE: the rationale for 2 JSON::Any versions is that
31 # we need the newer only to work around JSON::XS, which
32 # itself is an optional dep
35 'JSON::Any' => '1.23',
39 _json_xs_compatible_json_any => {
41 'JSON::Any' => '1.31',
45 # a common placeholder for engines with IC::DT support based off DT::F::S
46 _icdt_strptime_based => {
50 'DateTime::Format::Strptime' => '1.2',
56 _rdbms_generic_odbc => {
62 _rdbms_generic_ado => {
71 title => 'Storage::Replicated',
72 desc => 'Modules required for L<DBIx::Class::Storage::DBI::Replicated>',
77 include => 'replicated',
84 include => '_json_any',
87 'MooseX::Types::Path::Class' => '0.05',
88 'MooseX::Types::JSON' => '0.02',
91 title => 'DBIx::Class::Admin',
92 desc => 'Modules required for the DBIx::Class administrative library',
99 'Getopt::Long::Descriptive' => '0.081',
100 'Text::CSV' => '1.16',
103 title => 'dbicadmin',
104 desc => 'Modules required for the CLI DBIx::Class interface dbicadmin',
110 'SQL::Translator' => '0.11018',
113 title => 'Storage::DBI::deploy()',
114 desc => 'Modules required for L<DBIx::Class::Storage::DBI/deployment_statements> and L<DBIx::Class::Schema/deploy>',
120 'DateTime' => '0.55',
123 title => 'InflateColumn::DateTime support',
125 'Modules required for L<DBIx::Class::InflateColumn::DateTime>. '
126 . 'Note that this group does not require much on its own, but '
127 . 'instead is augmented by various RDBMS-specific groups. See the '
128 . 'documentation of each C<rbms_*> group for details',
134 'Math::BigInt' => '1.80',
135 'Math::Base36' => '0.07',
139 test_component_accessor => {
141 'Class::Unload' => '0.07',
147 'Test::Pod' => '1.42',
149 release_testing_mandatory => 1,
152 test_podcoverage => {
154 'Test::Pod::Coverage' => '1.08',
155 'Pod::Coverage' => '0.20',
157 release_testing_mandatory => 1,
162 'Test::EOL' => '1.0',
163 'Test::NoTabs' => '0.9',
165 release_testing_mandatory => 1,
170 'Test::Strict' => '0.20',
172 release_testing_mandatory => 1,
175 test_prettydebug => {
176 include => '_json_any',
179 test_admin_script => {
180 include => [qw( admin_script _json_xs_compatible_json_any )],
184 'Cpanel::JSON::XS' => 0,
187 # for t/admin/10script.t
188 ? ('Win32::ShellQuote' => 0)
189 # DWIW does not compile (./configure even) on win32
190 : ('JSON::DWIW' => 0 )
195 test_leaks_heavy => {
197 'Class::MethodCache' => '0.02',
198 'PadWalker' => '1.06',
205 'Class::DBI::Plugin::DeepAbstractSearch' => '0',
206 'Time::Piece::MySQL' => '0',
207 'Date::Simple' => '3.03',
211 # this is just for completeness as SQLite
212 # is a core dep of DBIC for testing
218 title => 'SQLite support',
219 desc => 'Modules required to connect to SQLite',
224 'DateTime::Format::SQLite' => '0',
230 # centralize the specification, as we have ICDT tests which can
231 # test the full behavior of RDBMS-specific ICDT on top of bare SQLite
232 # not _-prefixed so that it will show up under req_group_list
237 'DateTime::Format::Pg' => '0.16004',
244 include => 'icdt_pg',
246 # when changing this list make sure to adjust xt/optional_deps.t
250 title => 'PostgreSQL support',
251 desc => 'Modules required to connect to PostgreSQL',
255 _rdbms_mssql_common => {
256 include => '_icdt_strptime_based',
259 rdbms_mssql_odbc => {
260 include => [qw( _rdbms_generic_odbc _rdbms_mssql_common )],
262 title => 'MSSQL support via DBD::ODBC',
263 desc => 'Modules required to connect to MSSQL via DBD::ODBC',
267 rdbms_mssql_sybase => {
268 include => '_rdbms_mssql_common',
273 title => 'MSSQL support via DBD::Sybase',
274 desc => 'Modules required to connect to MSSQL via DBD::Sybase',
279 include => [qw( _rdbms_generic_ado _rdbms_mssql_common )],
281 title => 'MSSQL support via DBD::ADO (Windows only)',
282 desc => 'Modules required to connect to MSSQL via DBD::ADO. This particular DBD is available on Windows only',
286 _rdbms_msaccess_common => {
287 include => '_icdt_strptime_based',
290 rdbms_msaccess_odbc => {
291 include => [qw( _rdbms_generic_odbc _rdbms_msaccess_common )],
293 title => 'MS Access support via DBD::ODBC',
294 desc => 'Modules required to connect to MS Access via DBD::ODBC',
298 rdbms_msaccess_ado => {
299 include => [qw( _rdbms_generic_ado _rdbms_msaccess_common )],
301 title => 'MS Access support via DBD::ADO (Windows only)',
302 desc => 'Modules required to connect to MS Access via DBD::ADO. This particular DBD is available on Windows only',
306 # centralize the specification, as we have ICDT tests which can
307 # test the full behavior of RDBMS-specific ICDT on top of bare SQLite
308 # not _-prefixed so that it will show up under req_group_list
313 'DateTime::Format::MySQL' => '0',
320 include => 'icdt_mysql',
325 title => 'MySQL support',
326 desc => 'Modules required to connect to MySQL',
331 include => 'id_shortener',
336 title => 'Oracle support',
337 desc => 'Modules required to connect to Oracle',
342 'DateTime::Format::Oracle' => '0',
349 include => '_icdt_strptime_based',
354 title => 'Sybase ASE support',
355 desc => 'Modules required to connect to Sybase ASE',
359 _rdbms_db2_common => {
363 'DateTime::Format::DB2' => '0',
370 include => '_rdbms_db2_common',
375 title => 'DB2 support',
376 desc => 'Modules required to connect to DB2',
381 include => [qw( _rdbms_generic_odbc _rdbms_db2_common )],
383 title => 'DB2 on AS/400 support',
384 desc => 'Modules required to connect to DB2 on AS/400',
389 include => '_icdt_strptime_based',
391 'DBD::Informix' => 0,
394 title => 'Informix support',
395 desc => 'Modules required to connect to Informix',
399 _rdbms_sqlanywhere_common => {
400 inclide => '_icdt_strptime_based',
403 rdbms_sqlanywhere => {
404 include => '_rdbms_sqlanywhere_common',
406 'DBD::SQLAnywhere' => 0,
409 title => 'SQLAnywhere support',
410 desc => 'Modules required to connect to SQLAnywhere',
414 rdbms_sqlanywhere_odbc => {
415 include => [qw( _rdbms_generic_odbc _rdbms_sqlanywhere_common )],
417 title => 'SQLAnywhere support via DBD::ODBC',
418 desc => 'Modules required to connect to SQLAnywhere via DBD::ODBC',
422 _rdbms_firebird_common => {
423 include => '_icdt_strptime_based',
427 include => '_rdbms_firebird_common',
429 'DBD::Firebird' => 0,
432 title => 'Firebird support',
433 desc => 'Modules required to connect to Firebird',
437 rdbms_firebird_interbase => {
438 include => '_rdbms_firebird_common',
440 'DBD::InterBase' => 0,
443 title => 'Firebird support via DBD::InterBase',
444 desc => 'Modules required to connect to Firebird via DBD::InterBase',
448 rdbms_firebird_odbc => {
449 include => [qw( _rdbms_generic_odbc _rdbms_firebird_common )],
451 title => 'Firebird support via DBD::ODBC',
452 desc => 'Modules required to connect to Firebird via DBD::ODBC',
456 test_rdbms_sqlite => {
457 include => 'rdbms_sqlite',
460 ### IMPORTANT - do not raise this dependency
461 ### even though many bugfixes are present in newer versions, the general DBIC
462 ### rule is to bend over backwards for available DBDs (given upgrading them is
463 ### often *not* easy or even possible)
465 'DBD::SQLite' => '1.29',
470 include => 'rdbms_pg',
472 DBICTEST_PG_DSN => 1,
473 DBICTEST_PG_USER => 0,
474 DBICTEST_PG_PASS => 0,
477 # the order does matter because the rdbms support group might require
478 # a different version that the test group
480 # when changing this list make sure to adjust xt/optional_deps.t
481 'DBD::Pg' => '2.009002', # specific version to test bytea
485 test_rdbms_mssql_odbc => {
486 include => 'rdbms_mssql_odbc',
488 DBICTEST_MSSQL_ODBC_DSN => 1,
489 DBICTEST_MSSQL_ODBC_USER => 0,
490 DBICTEST_MSSQL_ODBC_PASS => 0,
494 test_rdbms_mssql_ado => {
495 include => 'rdbms_mssql_ado',
497 DBICTEST_MSSQL_ADO_DSN => 1,
498 DBICTEST_MSSQL_ADO_USER => 0,
499 DBICTEST_MSSQL_ADO_PASS => 0,
503 test_rdbms_mssql_sybase => {
504 include => 'rdbms_mssql_sybase',
506 DBICTEST_MSSQL_DSN => 1,
507 DBICTEST_MSSQL_USER => 0,
508 DBICTEST_MSSQL_PASS => 0,
512 test_rdbms_msaccess_odbc => {
513 include => 'rdbms_msaccess_odbc',
515 DBICTEST_MSACCESS_ODBC_DSN => 1,
516 DBICTEST_MSACCESS_ODBC_USER => 0,
517 DBICTEST_MSACCESS_ODBC_PASS => 0,
524 test_rdbms_msaccess_ado => {
525 include => 'rdbms_msaccess_ado',
527 DBICTEST_MSACCESS_ADO_DSN => 1,
528 DBICTEST_MSACCESS_ADO_USER => 0,
529 DBICTEST_MSACCESS_ADO_PASS => 0,
536 test_rdbms_mysql => {
537 include => 'rdbms_mysql',
539 DBICTEST_MYSQL_DSN => 1,
540 DBICTEST_MYSQL_USER => 0,
541 DBICTEST_MYSQL_PASS => 0,
545 test_rdbms_oracle => {
546 include => 'rdbms_oracle',
548 DBICTEST_ORA_DSN => 1,
549 DBICTEST_ORA_USER => 0,
550 DBICTEST_ORA_PASS => 0,
553 'DBD::Oracle' => '1.24',
558 include => 'rdbms_ase',
560 DBICTEST_SYBASE_DSN => 1,
561 DBICTEST_SYBASE_USER => 0,
562 DBICTEST_SYBASE_PASS => 0,
567 include => 'rdbms_db2',
569 DBICTEST_DB2_DSN => 1,
570 DBICTEST_DB2_USER => 0,
571 DBICTEST_DB2_PASS => 0,
575 test_rdbms_db2_400 => {
576 include => 'rdbms_db2_400',
578 DBICTEST_DB2_400_DSN => 1,
579 DBICTEST_DB2_400_USER => 0,
580 DBICTEST_DB2_400_PASS => 0,
584 test_rdbms_informix => {
585 include => 'rdbms_informix',
587 DBICTEST_INFORMIX_DSN => 1,
588 DBICTEST_INFORMIX_USER => 0,
589 DBICTEST_INFORMIX_PASS => 0,
593 test_rdbms_sqlanywhere => {
594 include => 'rdbms_sqlanywhere',
596 DBICTEST_SQLANYWHERE_DSN => 1,
597 DBICTEST_SQLANYWHERE_USER => 0,
598 DBICTEST_SQLANYWHERE_PASS => 0,
602 test_rdbms_sqlanywhere_odbc => {
603 include => 'rdbms_sqlanywhere_odbc',
605 DBICTEST_SQLANYWHERE_ODBC_DSN => 1,
606 DBICTEST_SQLANYWHERE_ODBC_USER => 0,
607 DBICTEST_SQLANYWHERE_ODBC_PASS => 0,
611 test_rdbms_firebird => {
612 include => 'rdbms_firebird',
614 DBICTEST_FIREBIRD_DSN => 1,
615 DBICTEST_FIREBIRD_USER => 0,
616 DBICTEST_FIREBIRD_PASS => 0,
620 test_rdbms_firebird_interbase => {
621 include => 'rdbms_firebird_interbase',
623 DBICTEST_FIREBIRD_INTERBASE_DSN => 1,
624 DBICTEST_FIREBIRD_INTERBASE_USER => 0,
625 DBICTEST_FIREBIRD_INTERBASE_PASS => 0,
629 test_rdbms_firebird_odbc => {
630 include => 'rdbms_firebird_odbc',
632 DBICTEST_FIREBIRD_ODBC_DSN => 1,
633 DBICTEST_FIREBIRD_ODBC_USER => 0,
634 DBICTEST_FIREBIRD_ODBC_PASS => 0,
640 DBICTEST_MEMCACHED => 1,
643 'Cache::Memcached' => 0,
648 # we need to run the dbicadmin so we can self-generate its POD
649 # also we do not want surprises in case JSON::XS is in the path
650 # so make sure we get an always-working JSON::Any
651 include => [qw( admin_script _json_xs_compatible_json_any )],
653 'ExtUtils::MakeMaker' => '6.64',
654 'Pod::Inherit' => '0.91',
660 'CPAN::Uploader' => '0.103001',
676 if ($action eq '-die_without') {
680 eval { $class->die_unless_req_ok_for(\@_); 1 }
683 die "\n$err\n" if $err;
685 elsif ($action eq '-list_missing') {
686 print $class->modreq_missing_for(\@_);
690 elsif ($action eq '-skip_all_without') {
692 # sanity check - make sure ->current_test is 0 and no plan has been declared
696 Test::Builder->new->current_test
698 Test::Builder->new->has_plan
700 } and croak("Unable to invoke -skip_all_without after testing has started");
702 if ( my $missing = $class->req_missing_for(\@_) ) {
704 die ("\nMandatory requirements not satisfied during release-testing: $missing\n\n")
705 if $ENV{RELEASE_TESTING} and $class->_groups_to_reqs(\@_)->{release_testing_mandatory};
707 print "1..0 # SKIP requirements not satisfied: $missing\n";
711 elsif ($action =~ /^-/) {
712 croak "Unknown import-time action '$action'";
715 croak "$class is not an exporter, unable to import '$action'";
723 croak( __PACKAGE__ . " does not implement unimport" );
726 # OO for (mistakenly considered) ease of extensibility, not due to any need to
727 # carry state of any sort. This API is currently used outside, so leave as-is.
728 # FIXME - make sure to not propagate this further if module is extracted as a
729 # standalone library - keep the stupidity to a DBIC-secific shim!
732 shift->_groups_to_reqs(shift)->{effective_modreqs};
735 sub modreq_list_for {
736 shift->_groups_to_reqs(shift)->{modreqs};
741 { $_ => $_[0]->_groups_to_reqs($_) }
742 grep { $_ !~ /^_/ } keys %$dbic_reqs
746 sub req_errorlist_for { shift->modreq_errorlist_for(shift) } # deprecated
747 sub modreq_errorlist_for {
748 my ($self, $groups) = @_;
749 $self->_errorlist_for_modreqs( $self->_groups_to_reqs($groups)->{modreqs} );
753 shift->req_missing_for(shift) ? 0 : 1;
756 sub req_missing_for {
757 my ($self, $groups) = @_;
759 my $reqs = $self->_groups_to_reqs($groups);
760 my $mods_missing = $self->modreq_missing_for($groups);
765 ! $reqs->{missing_envvars}
768 my @res = $mods_missing || ();
770 push @res, 'the following group(s) of environment variables: ' . join ' and ', sort map
771 { __envvar_group_desc($_) }
772 @{$reqs->{missing_envvars}}
773 if $reqs->{missing_envvars};
776 ( join ' as well as ', @res )
778 ( $reqs->{modreqs_fully_documented} ? " (see @{[ ref $self || $self ]} documentation for details)" : '' ),
782 sub modreq_missing_for {
783 my ($self, $groups) = @_;
785 my $reqs = $self->_groups_to_reqs($groups);
786 my $modreq_errors = $self->_errorlist_for_modreqs($reqs->{modreqs})
790 { $reqs->{modreqs}{$_} ? qq("$_~>=$reqs->{modreqs}{$_}") : $_ }
791 sort { lc($a) cmp lc($b) } keys %$modreq_errors
795 sub die_unless_req_ok_for {
796 if (my $err = shift->req_missing_for(shift) ) {
797 die "Unable to continue due to missing requirements: $err\n";
803 ### Private functions
805 # potentially shorten group desc
806 sub __envvar_group_desc {
809 my (@res, $last_prefix);
810 while (my $ev = shift @envs) {
811 my ($pref, $sep, $suff) = split / ([\_\-]) (?= [^\_\-]+ \z )/x, $ev;
813 if ( defined $sep and ($last_prefix||'') eq $pref ) {
814 push @res, "...${sep}${suff}"
820 $last_prefix = $pref if $sep;
826 # Expand includes from a random group in a specific order:
827 # nonvariable groups first, then their includes, then the variable groups,
828 # then their includes.
829 # This allows reliably marking the rest of the mod reqs as variable (this is
830 # also why variable includes are currently not allowed)
831 sub __expand_includes {
832 my ($groups, $seen) = @_;
834 # !! DIFFERENT !! behavior and return depending on invocation mode
835 # (easier to recurse this way)
836 my $is_toplevel = $seen
841 my ($res_per_type, $missing_envvars);
843 # breadth-first evaluation, with non-variable includes on top
844 for my $g (@$groups) {
846 croak "Invalid requirement group name '$g': only ascii alphanumerics and _ are allowed"
847 if $g !~ /\A [A-Z_a-z][0-9A-Z_a-z]* \z/x;
849 my $r = $dbic_reqs->{$g}
850 or croak "Requirement group '$g' is not defined";
852 # always do this check *before* the $seen check
853 croak "Group '$g' with variable effective_modreqs can not be specified as an 'include'"
854 if ( $r->{env} and ! $is_toplevel );
856 next if $seen->{$g}++;
858 my $req_type = 'static';
860 if ( my @e = @{$r->{env}||[]} ) {
862 croak "Unexpected 'env' attribute under group '$g' (only allowed in test_* groups)"
863 unless $g =~ /^test_/;
865 croak "Unexpected *odd* list in 'env' under group '$g'"
868 # deconstruct the whole thing
869 my (@group_envnames_list, $some_envs_required, $some_required_missing);
871 push @group_envnames_list, my $envname = shift @e;
873 # env required or not
874 next unless shift @e;
876 $some_envs_required ||= 1;
878 $some_required_missing ||= (
879 ! defined $ENV{$envname}
881 ! length $ENV{$envname}
885 croak "None of the envvars in group '$g' declared as required, making the requirement moot"
886 unless $some_envs_required;
888 if ($some_required_missing) {
889 push @{$missing_envvars->{$g}}, \@group_envnames_list;
890 $req_type = 'variable';
894 push @{$res_per_type->{"base_${req_type}"}}, $g;
896 if (my $i = $dbic_reqs->{$g}{include}) {
897 $i = [ $i ] unless ref $i eq 'ARRAY';
899 croak "Malformed 'include' for group '$g': must be another existing group name or arrayref of existing group names"
902 push @{$res_per_type->{"incs_${req_type}"}}, @$i;
907 @{ $res_per_type->{"base_${_}"} || [] },
908 ( $res_per_type->{"incs_${_}"} ? __expand_includes( $res_per_type->{"incs_${_}"}, $seen ) : () ),
909 } qw(static variable);
911 return ! $is_toplevel ? @ret : do {
914 idx => 1 + keys %$rv,
915 missing_envvars => $missing_envvars->{$_},
917 $rv->{$_}{user_requested} = 1 for @$groups;
923 our %req_unavailability_cache;
925 # this method is just a lister and envvar/metadata checker - it does not try to load anything
926 sub _groups_to_reqs {
927 my ($self, $groups) = @_;
929 $groups = [ $groups || () ]
930 unless ref $groups eq 'ARRAY';
932 croak "@{[ (caller(1))[3] ]}() expects a requirement group name or arrayref of group names"
937 modreqs_fully_documented => 1,
940 my $all_groups = __expand_includes($groups);
942 # pre-assemble list of augmentations, perform basic sanity checks
943 # Note that below we *DO NOT* respect the source/target reationship, but
944 # instead always default to augment the "later" group
945 # This is done so that the "stable/variable" boundary keeps working as
948 for my $requesting_group (keys %$all_groups) {
949 if (my $ag = $dbic_reqs->{$requesting_group}{augment}) {
950 for my $target_group (keys %$ag) {
952 croak "Group '$requesting_group' claims to augment a non-existent group '$target_group'"
953 unless $dbic_reqs->{$target_group};
955 croak "Augmentation combined with variable effective_modreqs currently unsupported for group '$requesting_group'"
956 if $dbic_reqs->{$requesting_group}{env};
958 croak "Augmentation of group '$target_group' with variable effective_modreqs unsupported (requested by '$requesting_group')"
959 if $dbic_reqs->{$target_group}{env};
961 if (my @foreign = grep { $_ ne 'req' } keys %{$ag->{$target_group}} ) {
962 croak "Only 'req' augmentations are currently supported (group '$requesting_group' attempts to alter '$foreign[0]' of group '$target_group'";
965 $ret->{augments}{$target_group} = 1;
967 # no augmentation for stuff that hasn't been selected
968 if ( $all_groups->{$target_group} and my $ar = $ag->{$target_group}{req} ) {
969 push @{$augmentations->{
970 ( $all_groups->{$requesting_group}{idx} < $all_groups->{$target_group}{idx} )
979 for my $group (sort { $all_groups->{$a}{idx} <=> $all_groups->{$b}{idx} } keys %$all_groups ) {
981 my $group_reqs = $dbic_reqs->{$group}{req};
984 for my $req_bag ($group_reqs, @{ $augmentations->{$group} || [] } ) {
985 for (keys %$req_bag) {
987 $_ =~ /\A [A-Z_a-z][0-9A-Z_a-z]* (?:::[0-9A-Z_a-z]+)* \z /x
988 or croak "Requirement '$_' in group '$group' is not a valid module name";
990 # !!!DO NOT CHANGE!!!
991 # remember - version.pm may not be available on the system
992 croak "Requirement '$_' in group '$group' specifies an invalid version '$req_bag->{$_}' (only plain non-underscored floating point decimals are supported)"
993 if ( ($req_bag->{$_}||0) !~ / \A [0-9]+ (?: \. [0-9]+ )? \z /x );
997 if (my $e = $all_groups->{$group}{missing_envvars}) {
998 push @{$ret->{missing_envvars}}, @$e;
1001 # assemble into the final ret
1004 ( $ret->{missing_envvars} ? () : 'effective_modreqs' ),
1006 for my $req_bag ($group_reqs, @{ $augmentations->{$group} || [] } ) {
1007 for my $mod (keys %$req_bag) {
1009 $ret->{$type}{$mod} = $req_bag->{$mod}||0 if (
1011 ! exists $ret->{$type}{$mod}
1013 # we sanitized the version to be numeric above - we can just -gt it
1014 ($req_bag->{$mod}||0) > $ret->{$type}{$mod}
1021 $ret->{modreqs_fully_documented} &&= !!$dbic_reqs->{$group}{pod}
1022 if $all_groups->{$group}{user_requested};
1024 $ret->{release_testing_mandatory} ||= !!$dbic_reqs->{$group}{release_testing_mandatory};
1031 # this method tries to load specified modreqs and returns a hashref of
1032 # module/loaderror pairs for anything that failed
1033 sub _errorlist_for_modreqs {
1034 # args supposedly already went through _groups_to_reqs and are therefore sanitized
1035 # safe to eval at will
1036 my ($self, $reqs) = @_;
1040 for my $m ( keys %$reqs ) {
1041 my $v = $reqs->{$m};
1043 if (! exists $req_unavailability_cache{$m}{$v} ) {
1045 eval( "require $m;" . ( $v ? "$m->VERSION(q($v))" : '' ) );
1046 $req_unavailability_cache{$m}{$v} = $@;
1049 $ret->{$m} = $req_unavailability_cache{$m}{$v}
1050 if $req_unavailability_cache{$m}{$v};
1057 # This is to be called by the author only (automatically in Makefile.PL)
1059 my ($class, $distver, $pod_dir) = @_;
1061 die "No POD root dir supplied" unless $pod_dir;
1064 eval { require DBIx::Class; DBIx::Class->VERSION; }
1067 "\n\n---------------------------------------------------------------------\n" .
1068 'Unable to load core DBIx::Class module to determine current version, '.
1069 'possibly due to missing dependencies. Author-mode autodocumentation ' .
1071 "\n\n---------------------------------------------------------------------\n"
1074 # do not ask for a recent version, use 1.x API calls
1075 # this *may* execute on a smoker with old perl or whatnot
1078 (my $modfn = __PACKAGE__ . '.pm') =~ s|::|/|g;
1080 (my $podfn = "$pod_dir/$modfn") =~ s/\.pm$/\.pod/;
1081 (my $dir = $podfn) =~ s|/[^/]+$||;
1083 File::Path::mkpath([$dir]);
1085 my $sqltver = $class->req_list_for('deploy')->{'SQL::Translator'}
1086 or die "Hrmm? No sqlt dep?";
1094 push @chunks, <<"EOC";
1095 #########################################################################
1096 ##################### A U T O G E N E R A T E D ########################
1097 #########################################################################
1099 # The contents of this POD file are auto-generated. Any changes you make
1100 # will be lost. If you need to change the generated text edit _gen_pod()
1101 # at the end of $modfn
1106 $class - Optional module dependency specifications (for module authors)
1111 #@@ SYNOPSIS HEADING
1113 push @chunks, <<"EOC";
1116 Somewhere in your build-file (e.g. L<ExtUtils::MakeMaker>'s F<Makefile.PL>):
1120 \$EUMM_ARGS{CONFIGURE_REQUIRES} = {
1121 \%{ \$EUMM_ARGS{CONFIGURE_REQUIRES} || {} },
1122 'DBIx::Class' => '$distver',
1127 my %DBIC_DEPLOY_AND_ORACLE_DEPS = %{ eval {
1129 $class->req_list_for([qw( deploy rdbms_oracle icdt )]);
1132 \$EUMM_ARGS{PREREQ_PM} = {
1133 \%DBIC_DEPLOY_AND_ORACLE_DEPS,
1134 \%{ \$EUMM_ARGS{PREREQ_PM} || {} },
1139 ExtUtils::MakeMaker::WriteMakefile(\%EUMM_ARGS);
1141 B<Note>: The C<eval> protection within the example is due to support for
1142 requirements during L<the C<configure> build phase|CPAN::Meta::Spec/Phases>
1143 not being available on a sufficient portion of production installations of
1144 Perl. Robust support for such dependency requirements is available in the
1145 L<CPAN> installer only since version C<1.94_56> first made available for
1146 production with perl version C<5.12>. It is the belief of the current
1147 maintainer that support for requirements during the C<configure> build phase
1148 will not be sufficiently ubiquitous until the B<year 2020> at the earliest,
1149 hence the extra care demonstrated above. It should also be noted that some
1150 3rd party installers (e.g. L<cpanminus|App::cpanminus>) do the right thing
1151 with configure requirements independent from the versions of perl and CPAN
1157 #@@ DESCRIPTION HEADING
1159 push @chunks, <<'EOC';
1162 Some of the less-frequently used features of L<DBIx::Class> have external
1163 module dependencies on their own. In order not to burden the average user
1164 with modules they will never use, these optional dependencies are not included
1165 in the base Makefile.PL. Instead an exception with a descriptive message is
1166 thrown when a specific feature can't find one or several modules required for
1167 its operation. This module is the central holding place for the current list
1168 of such dependencies, for DBIx::Class core authors, and DBIx::Class extension
1171 Dependencies are organized in L<groups|/CURRENT REQUIREMENT GROUPS> where each
1172 group can list one or more required modules, with an optional minimum version
1173 (or 0 for any version). In addition groups prefixed with C<test_> can specify
1174 a set of environment variables, some (or all) of which are marked as required
1175 for the group to be considered by L</req_list_for>
1177 Each group name (or a combination thereof) can be used in the
1178 L<public methods|/METHODS> as described below.
1183 #@@ REQUIREMENT GROUPLIST HEADING
1185 push @chunks, '=head1 CURRENT REQUIREMENT GROUPS';
1187 my $standalone_info;
1189 for my $group (sort keys %$dbic_reqs) {
1191 my $info = $standalone_info->{$group} ||= $class->_groups_to_reqs($group);
1194 $info->{modreqs_fully_documented}
1196 ( $info->{augments} or $info->{modreqs} )
1199 my $p = $dbic_reqs->{$group}{pod};
1202 "=head2 $p->{title}",
1208 if ( keys %{ $info->{modreqs}||{} } ) {
1210 { "=item * $_" . ($info->{modreqs}{$_} ? " >= $info->{modreqs}{$_}" : '') }
1211 ( sort keys %{ $info->{modreqs} } )
1215 push @chunks, '=item * No standalone requirements',
1218 push @chunks, '=back';
1220 for my $ag ( sort keys %{ $info->{augments} || {} } ) {
1221 my $ag_info = $standalone_info->{$ag} ||= $class->_groups_to_reqs($ag);
1223 my $newreqs = $class->modreq_list_for([ $group, $ag ]);
1224 for (keys %$newreqs) {
1225 delete $newreqs->{$_} if (
1226 ( defined $info->{modreqs}{$_} and $info->{modreqs}{$_} == $newreqs->{$_} )
1228 ( defined $ag_info->{modreqs}{$_} and $ag_info->{modreqs}{$_} == $newreqs->{$_} )
1232 if (keys %$newreqs) {
1234 "Combined with L</$ag> additionally requires:",
1237 { "=item * $_" . ($newreqs->{$_} ? " >= $newreqs->{$_}" : '') }
1238 ( sort keys %$newreqs )
1248 #@@ API DOCUMENTATION HEADING
1250 push @chunks, <<'EOC';
1252 =head1 IMPORT-LIKE ACTIONS
1254 Even though this module is not an L<Exporter>, it recognizes several C<actions>
1255 supplied to its C<import> method.
1257 =head2 -skip_all_without
1261 =item Arguments: @group_names
1265 A convenience wrapper for use during testing:
1268 push @chunks, " use $class -skip_all_without => qw(admin test_rdbms_mysql);";
1270 push @chunks, 'Roughly equivalent to the following code:';
1272 push @chunks, sprintf <<'EOS', ($class) x 2;
1276 if ( my $missing = %s->req_missing_for(\@group_names_) ) {
1277 print "1..0 # SKIP requirements not satisfied: $missing\n";
1283 push @chunks, <<'EOC';
1285 It also takes into account the C<RELEASE_TESTING> environment variable and
1286 behaves like L</-die_without> for any requirement groups marked as
1287 C<release_testing_mandatory>.
1293 =item Arguments: @group_names
1297 A convenience wrapper around L</die_unless_req_ok_for>:
1300 push @chunks, " use $class -die_without => qw(deploy admin);";
1302 push @chunks, <<'EOC';
1304 =head2 -list_missing
1308 =item Arguments: @group_names
1312 A convenience wrapper around L</modreq_missing_for>:
1314 perl -Ilib -MDBIx::Class::Optional::Dependencies=-list_missing,deploy,admin | cpanm
1318 =head2 req_group_list
1322 =item Arguments: none
1324 =item Return Value: \%list_of_requirement_groups
1328 This method should be used by DBIx::Class packagers, to get a hashref of all
1329 dependencies B<keyed> by dependency group. Each key (group name), or a combination
1330 thereof (as an arrayref) can be supplied to the methods below.
1331 The B<values> of the returned hash are currently a set of options B<without a
1332 well defined structure>. If you have use for any of the contents - contact the
1333 maintainers, instead of treating this as public (left alone stable) API.
1339 =item Arguments: $group_name | \@group_names
1341 =item Return Value: \%set_of_module_version_pairs
1345 This method should be used by DBIx::Class extension authors, to determine the
1346 version of modules a specific set of features requires for this version of
1347 DBIx::Class (regardless of their availability on the system).
1348 See the L</SYNOPSIS> for a real-world example.
1350 When handling C<test_*> groups this method behaves B<differently> from
1351 L</modreq_list_for> below (and is the only such inconsistency among the
1352 C<req_*> methods). If a particular group declares as requirements some
1353 C<environment variables> and these requirements are not satisfied (the envvars
1354 are unset) - then the C<module requirements> of this group are not included in
1357 =head2 modreq_list_for
1361 =item Arguments: $group_name | \@group_names
1363 =item Return Value: \%set_of_module_version_pairs
1367 Same as L</req_list_for> but does not take into consideration any
1368 C<environment variable requirements> - returns just the list of required
1375 =item Arguments: $group_name | \@group_names
1377 =item Return Value: 1|0
1381 Returns true or false depending on whether all modules/envvars required by
1382 the group(s) are loadable/set on the system.
1384 =head2 req_missing_for
1388 =item Arguments: $group_name | \@group_names
1390 =item Return Value: $error_message_string
1394 Returns a single-line string suitable for inclusion in larger error messages.
1395 This method would normally be used by DBIx::Class core features, to indicate to
1396 the user that they need to install specific modules and/or set specific
1397 environment variables before being able to use a specific feature set.
1399 For example if some of the requirements for C<deploy> are not available,
1400 the returned string could look like:
1403 push @chunks, qq{ "SQL::Translator~>=$sqltver" (see $class documentation for details)};
1405 push @chunks, <<'EOC';
1406 The author is expected to prepend the necessary text to this message before
1407 returning the actual error seen by the user. See also L</modreq_missing_for>
1409 =head2 modreq_missing_for
1413 =item Arguments: $group_name | \@group_names
1415 =item Return Value: $error_message_string
1419 Same as L</req_missing_for> except that the error string is guaranteed to be
1420 either empty, or contain a set of module requirement specifications suitable
1421 for piping to e.g. L<cpanminus|App::cpanminus>. The method explicitly does not
1422 attempt to validate the state of required environment variables (if any).
1424 For instance if some of the requirements for C<deploy> are not available,
1425 the returned string could look like:
1428 push @chunks, qq{ "SQL::Translator~>=$sqltver"};
1430 push @chunks, <<'EOC';
1432 See also L</-list_missing>.
1434 =head2 die_unless_req_ok_for
1438 =item Arguments: $group_name | \@group_names
1442 Checks if L</req_ok_for> passes for the supplied group(s), and
1443 in case of failure throws an exception including the information
1444 from L</req_missing_for>. See also L</-die_without>.
1446 =head2 modreq_errorlist_for
1450 =item Arguments: $group_name | \@group_names
1452 =item Return Value: \%set_of_loaderrors_per_module
1456 Returns a hashref containing the actual errors that occurred while attempting
1457 to load each module in the requirement group(s).
1459 =head2 req_errorlist_for
1461 Deprecated method name, equivalent (via proxy) to L</modreq_errorlist_for>.
1468 push @chunks, <<'EOC';
1469 =head1 FURTHER QUESTIONS?
1471 Check the list of L<additional DBIC resources|DBIx::Class/GETTING HELP/SUPPORT>.
1473 =head1 COPYRIGHT AND LICENSE
1475 This module is free software L<copyright|DBIx::Class/COPYRIGHT AND LICENSE>
1476 by the L<DBIx::Class (DBIC) authors|DBIx::Class/AUTHORS>. You can
1477 redistribute it and/or modify it under the same terms as the
1478 L<DBIx::Class library|DBIx::Class/COPYRIGHT AND LICENSE>.
1482 open (my $fh, '>', $podfn) or die;
1483 print $fh join ("\n\n", @chunks) or die;
1484 print $fh "\n" or die;
1486 } or croak( "Unable to write $podfn: " . ( $! || $@ || 'unknown error') );