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
6 if ( $ENV{RELEASE_TESTING} ) {
7 require warnings and warnings->import;
8 require strict and strict->import;
18 # NO EXTERNAL NON-5.8.1 CORE DEPENDENCIES EVER (e.g. C::A::G)
19 # This module is to be loaded by Makefile.PM on a pristine system
21 # POD is generated automatically by calling _gen_pod from the
22 # Makefile.PL in $AUTHOR mode
24 # *DELIBERATELY* not making a group for these - they must disappear
25 # forever as optdeps in the first place
28 'MooseX::Types' => '0.21',
29 'MooseX::Types::LoadableClass' => '0.011',
34 # NOTE: the rationale for 2 JSON::Any versions is that
35 # we need the newer only to work around JSON::XS, which
36 # itself is an optional dep
39 'JSON::Any' => '1.23',
43 _json_xs_compatible_json_any => {
45 'JSON::Any' => '1.31',
49 # a common placeholder for engines with IC::DT support based off DT::F::S
50 _ic_dt_strptime_based => {
54 'DateTime::Format::Strptime' => '1.2',
60 _rdbms_generic_odbc => {
66 _rdbms_generic_ado => {
72 # must list any dep used by adhoc testing
73 # this prevents the "skips due to forgotten deps" issue
76 'Class::DBI::Plugin::DeepAbstractSearch' => '0',
77 'Class::DBI' => '3.000005',
78 'Date::Simple' => '3.03',
80 'Class::Unload' => '0.07',
82 'Time::Piece::MySQL' => '0',
89 title => 'Storage::Replicated',
90 desc => 'Modules required for L<DBIx::Class::Storage::DBI::Replicated>',
95 include => 'replicated',
101 config_file_reader => {
103 title => 'Generic config reader',
104 desc => 'Modules required for generic config file parsing, currently Config::Any (rarely used at runtime)',
107 'Config::Any' => '0.20',
112 include => [qw( _json_any config_file_reader )],
115 'MooseX::Types::Path::Class' => '0.05',
116 'MooseX::Types::JSON' => '0.02',
119 title => 'DBIx::Class::Admin',
120 desc => 'Modules required for the DBIx::Class administrative library',
127 'Getopt::Long::Descriptive' => '0.081',
128 'Text::CSV' => '1.16',
131 title => 'dbicadmin',
132 desc => 'Modules required for the CLI DBIx::Class interface dbicadmin',
138 'SQL::Translator' => '0.11018',
141 title => 'Storage::DBI::deploy()',
142 desc => 'Modules required for L<DBIx::Class::Storage::DBI/deployment_statements> and L<DBIx::Class::Schema/deploy>',
148 'DateTime' => '0.55',
149 'DateTime::TimeZone::OlsonDB' => 0,
152 title => 'InflateColumn::DateTime support',
154 'Modules required for L<DBIx::Class::InflateColumn::DateTime>. '
155 . 'Note that this group does not require much on its own, but '
156 . 'instead is augmented by various RDBMS-specific groups. See the '
157 . 'documentation of each C<rbms_*> group for details',
163 'Math::BigInt' => '1.80',
164 'Math::Base36' => '0.07',
170 'Class::Data::Inheritable' => '0',
171 'Class::Trigger' => '0',
172 'DBIx::ContextualFetch' => '0',
176 title => 'DBIx::Class::CDBICompat support',
177 desc => 'Modules required for L<DBIx::Class::CDBICompat>'
183 'Test::Pod' => '1.42',
185 release_testing_mandatory => 1,
188 test_podcoverage => {
190 'Test::Pod::Coverage' => '1.08',
191 'Pod::Coverage' => '0.20',
193 release_testing_mandatory => 1,
198 'Test::EOL' => '1.0',
199 'Test::NoTabs' => '0.9',
201 release_testing_mandatory => 1,
206 'Test::Strict' => '0.20',
208 release_testing_mandatory => 1,
211 test_prettydebug => {
212 include => '_json_any',
215 test_admin_script => {
216 include => [qw( admin_script _json_xs_compatible_json_any )],
220 'Cpanel::JSON::XS' => 0,
223 # for t/admin/10script.t
224 ? ('Win32::ShellQuote' => 0)
225 # DWIW does not compile (./configure even) on win32
226 : ('JSON::DWIW' => 0 )
231 test_leaks_heavy => {
233 'Class::MethodCache' => '0.02',
234 'PadWalker' => '1.06',
239 # this is just for completeness as SQLite
240 # is a core dep of DBIC for testing
246 title => 'SQLite support',
247 desc => 'Modules required to connect to SQLite',
252 'DateTime::Format::SQLite' => '0',
258 # centralize the specification, as we have ICDT tests which can
259 # test the full behavior of RDBMS-specific ICDT on top of bare SQLite
264 'DateTime::Format::Pg' => '0.16004',
271 include => [qw( ic_dt _ic_dt_pg_base )],
275 include => '_ic_dt_pg_base',
277 # when changing this list make sure to adjust xt/optional_deps.t
281 title => 'PostgreSQL support',
282 desc => 'Modules required to connect to PostgreSQL',
286 _rdbms_mssql_common => {
287 include => '_ic_dt_strptime_based',
290 rdbms_mssql_odbc => {
291 include => [qw( _rdbms_generic_odbc _rdbms_mssql_common )],
293 title => 'MSSQL support via DBD::ODBC',
294 desc => 'Modules required to connect to MSSQL via DBD::ODBC',
298 rdbms_mssql_sybase => {
299 include => '_rdbms_mssql_common',
304 title => 'MSSQL support via DBD::Sybase',
305 desc => 'Modules required to connect to MSSQL via DBD::Sybase',
310 include => [qw( _rdbms_generic_ado _rdbms_mssql_common )],
312 title => 'MSSQL support via DBD::ADO (Windows only)',
313 desc => 'Modules required to connect to MSSQL via DBD::ADO. This particular DBD is available on Windows only',
317 _rdbms_msaccess_common => {
318 include => '_ic_dt_strptime_based',
321 rdbms_msaccess_odbc => {
322 include => [qw( _rdbms_generic_odbc _rdbms_msaccess_common )],
324 title => 'MS Access support via DBD::ODBC',
325 desc => 'Modules required to connect to MS Access via DBD::ODBC',
329 rdbms_msaccess_ado => {
330 include => [qw( _rdbms_generic_ado _rdbms_msaccess_common )],
332 title => 'MS Access support via DBD::ADO (Windows only)',
333 desc => 'Modules required to connect to MS Access via DBD::ADO. This particular DBD is available on Windows only',
337 # centralize the specification, as we have ICDT tests which can
338 # test the full behavior of RDBMS-specific ICDT on top of bare SQLite
339 _ic_dt_mysql_base => {
343 'DateTime::Format::MySQL' => '0',
350 include => [qw( ic_dt _ic_dt_mysql_base )],
354 include => '_ic_dt_mysql_base',
359 title => 'MySQL support',
360 desc => 'Modules required to connect to MySQL',
365 include => 'id_shortener',
370 title => 'Oracle support',
371 desc => 'Modules required to connect to Oracle',
376 'DateTime::Format::Oracle' => '0',
383 include => '_ic_dt_strptime_based',
388 title => 'Sybase ASE support',
389 desc => 'Modules required to connect to Sybase ASE',
393 _rdbms_db2_common => {
397 'DateTime::Format::DB2' => '0',
404 include => '_rdbms_db2_common',
409 title => 'DB2 support',
410 desc => 'Modules required to connect to DB2',
415 include => [qw( _rdbms_generic_odbc _rdbms_db2_common )],
417 title => 'DB2 on AS/400 support',
418 desc => 'Modules required to connect to DB2 on AS/400',
423 include => '_ic_dt_strptime_based',
425 'DBD::Informix' => 0,
428 title => 'Informix support',
429 desc => 'Modules required to connect to Informix',
433 _rdbms_sqlanywhere_common => {
434 include => '_ic_dt_strptime_based',
437 rdbms_sqlanywhere => {
438 include => '_rdbms_sqlanywhere_common',
440 'DBD::SQLAnywhere' => 0,
443 title => 'SQLAnywhere support',
444 desc => 'Modules required to connect to SQLAnywhere',
448 rdbms_sqlanywhere_odbc => {
449 include => [qw( _rdbms_generic_odbc _rdbms_sqlanywhere_common )],
451 title => 'SQLAnywhere support via DBD::ODBC',
452 desc => 'Modules required to connect to SQLAnywhere via DBD::ODBC',
456 _rdbms_firebird_common => {
457 include => '_ic_dt_strptime_based',
461 include => '_rdbms_firebird_common',
463 'DBD::Firebird' => 0,
466 title => 'Firebird support',
467 desc => 'Modules required to connect to Firebird',
471 rdbms_firebird_interbase => {
472 include => '_rdbms_firebird_common',
474 'DBD::InterBase' => 0,
477 title => 'Firebird support via DBD::InterBase',
478 desc => 'Modules required to connect to Firebird via DBD::InterBase',
482 rdbms_firebird_odbc => {
483 include => [qw( _rdbms_generic_odbc _rdbms_firebird_common )],
485 title => 'Firebird support via DBD::ODBC',
486 desc => 'Modules required to connect to Firebird via DBD::ODBC',
490 test_rdbms_sqlite => {
491 include => 'rdbms_sqlite',
494 ### IMPORTANT - do not raise this dependency
495 ### even though many bugfixes are present in newer versions, the general DBIC
496 ### rule is to bend over backwards for available DBDs (given upgrading them is
497 ### often *not* easy or even possible)
499 'DBD::SQLite' => '1.29',
504 include => 'rdbms_pg',
506 DBICTEST_PG_DSN => 1,
507 DBICTEST_PG_USER => 0,
508 DBICTEST_PG_PASS => 0,
511 # the order does matter because the rdbms support group might require
512 # a different version that the test group
514 # when changing this list make sure to adjust xt/optional_deps.t
515 'DBD::Pg' => '2.009002', # specific version to test bytea
519 test_rdbms_mssql_odbc => {
520 include => 'rdbms_mssql_odbc',
522 DBICTEST_MSSQL_ODBC_DSN => 1,
523 DBICTEST_MSSQL_ODBC_USER => 0,
524 DBICTEST_MSSQL_ODBC_PASS => 0,
528 test_rdbms_mssql_ado => {
529 include => 'rdbms_mssql_ado',
531 DBICTEST_MSSQL_ADO_DSN => 1,
532 DBICTEST_MSSQL_ADO_USER => 0,
533 DBICTEST_MSSQL_ADO_PASS => 0,
537 test_rdbms_mssql_sybase => {
538 include => 'rdbms_mssql_sybase',
540 DBICTEST_MSSQL_DSN => 1,
541 DBICTEST_MSSQL_USER => 0,
542 DBICTEST_MSSQL_PASS => 0,
546 test_rdbms_msaccess_odbc => {
547 include => 'rdbms_msaccess_odbc',
549 DBICTEST_MSACCESS_ODBC_DSN => 1,
550 DBICTEST_MSACCESS_ODBC_USER => 0,
551 DBICTEST_MSACCESS_ODBC_PASS => 0,
558 test_rdbms_msaccess_ado => {
559 include => 'rdbms_msaccess_ado',
561 DBICTEST_MSACCESS_ADO_DSN => 1,
562 DBICTEST_MSACCESS_ADO_USER => 0,
563 DBICTEST_MSACCESS_ADO_PASS => 0,
570 test_rdbms_mysql => {
571 include => 'rdbms_mysql',
573 DBICTEST_MYSQL_DSN => 1,
574 DBICTEST_MYSQL_USER => 0,
575 DBICTEST_MYSQL_PASS => 0,
579 test_rdbms_oracle => {
580 include => 'rdbms_oracle',
582 DBICTEST_ORA_DSN => 1,
583 DBICTEST_ORA_USER => 0,
584 DBICTEST_ORA_PASS => 0,
587 'DBD::Oracle' => '1.24',
592 include => 'rdbms_ase',
594 DBICTEST_SYBASE_DSN => 1,
595 DBICTEST_SYBASE_USER => 0,
596 DBICTEST_SYBASE_PASS => 0,
601 include => 'rdbms_db2',
603 DBICTEST_DB2_DSN => 1,
604 DBICTEST_DB2_USER => 0,
605 DBICTEST_DB2_PASS => 0,
609 test_rdbms_db2_400 => {
610 include => 'rdbms_db2_400',
612 DBICTEST_DB2_400_DSN => 1,
613 DBICTEST_DB2_400_USER => 0,
614 DBICTEST_DB2_400_PASS => 0,
618 test_rdbms_informix => {
619 include => 'rdbms_informix',
621 DBICTEST_INFORMIX_DSN => 1,
622 DBICTEST_INFORMIX_USER => 0,
623 DBICTEST_INFORMIX_PASS => 0,
627 test_rdbms_sqlanywhere => {
628 include => 'rdbms_sqlanywhere',
630 DBICTEST_SQLANYWHERE_DSN => 1,
631 DBICTEST_SQLANYWHERE_USER => 0,
632 DBICTEST_SQLANYWHERE_PASS => 0,
636 test_rdbms_sqlanywhere_odbc => {
637 include => 'rdbms_sqlanywhere_odbc',
639 DBICTEST_SQLANYWHERE_ODBC_DSN => 1,
640 DBICTEST_SQLANYWHERE_ODBC_USER => 0,
641 DBICTEST_SQLANYWHERE_ODBC_PASS => 0,
645 test_rdbms_firebird => {
646 include => 'rdbms_firebird',
648 DBICTEST_FIREBIRD_DSN => 1,
649 DBICTEST_FIREBIRD_USER => 0,
650 DBICTEST_FIREBIRD_PASS => 0,
654 test_rdbms_firebird_interbase => {
655 include => 'rdbms_firebird_interbase',
657 DBICTEST_FIREBIRD_INTERBASE_DSN => 1,
658 DBICTEST_FIREBIRD_INTERBASE_USER => 0,
659 DBICTEST_FIREBIRD_INTERBASE_PASS => 0,
663 test_rdbms_firebird_odbc => {
664 include => 'rdbms_firebird_odbc',
666 DBICTEST_FIREBIRD_ODBC_DSN => 1,
667 DBICTEST_FIREBIRD_ODBC_USER => 0,
668 DBICTEST_FIREBIRD_ODBC_PASS => 0,
674 DBICTEST_MEMCACHED => 1,
677 'Cache::Memcached' => 0,
682 # we need to run the dbicadmin so we can self-generate its POD
683 # also we do not want surprises in case JSON::XS is in the path
684 # so make sure we get an always-working JSON::Any
687 _json_xs_compatible_json_any
696 'ExtUtils::MakeMaker' => '6.64',
697 'Module::Install' => '1.06',
698 'Pod::Inherit' => '0.91',
704 'CPAN::Uploader' => '0.103001',
720 if ($action eq '-die_without') {
724 eval { $class->die_unless_req_ok_for(\@_); 1 }
727 die "\n$err\n" if $err;
729 elsif ($action eq '-list_missing') {
730 print $class->modreq_missing_for(\@_);
734 elsif ($action eq '-skip_all_without') {
736 # sanity check - make sure ->current_test is 0 and no plan has been declared
740 Test::Builder->new->current_test
742 Test::Builder->new->has_plan
744 } and croak("Unable to invoke -skip_all_without after testing has started");
746 if ( my $missing = $class->req_missing_for(\@_) ) {
748 die ("\nMandatory requirements not satisfied during release-testing: $missing\n\n")
749 if $ENV{RELEASE_TESTING} and $class->_groups_to_reqs(\@_)->{release_testing_mandatory};
751 print "1..0 # SKIP requirements not satisfied: $missing\n";
755 elsif ($action =~ /^-/) {
756 croak "Unknown import-time action '$action'";
759 croak "$class is not an exporter, unable to import '$action'";
767 croak( __PACKAGE__ . " does not implement unimport" );
770 # OO for (mistakenly considered) ease of extensibility, not due to any need to
771 # carry state of any sort. This API is currently used outside, so leave as-is.
772 # FIXME - make sure to not propagate this further if module is extracted as a
773 # standalone library - keep the stupidity to a DBIC-secific shim!
776 shift->_groups_to_reqs(shift)->{effective_modreqs};
779 sub modreq_list_for {
780 shift->_groups_to_reqs(shift)->{modreqs};
785 { $_ => $_[0]->_groups_to_reqs($_) }
786 grep { $_ !~ /^_/ } keys %$dbic_reqs
790 sub req_errorlist_for { shift->modreq_errorlist_for(shift) } # deprecated
791 sub modreq_errorlist_for {
792 my ($self, $groups) = @_;
793 $self->_errorlist_for_modreqs( $self->_groups_to_reqs($groups)->{modreqs} );
797 shift->req_missing_for(shift) ? 0 : 1;
800 sub req_missing_for {
801 my ($self, $groups) = @_;
803 my $reqs = $self->_groups_to_reqs($groups);
805 my $mods_missing = $reqs->{missing_envvars}
806 ? $self->_list_physically_missing_modules( $reqs->{modreqs} )
807 : $self->modreq_missing_for($groups)
813 ! $reqs->{missing_envvars}
816 my @res = $mods_missing || ();
818 push @res, 'the following group(s) of environment variables: ' . join ' and ', sort map
819 { __envvar_group_desc($_) }
820 @{$reqs->{missing_envvars}}
821 if $reqs->{missing_envvars};
824 ( join ' as well as ', @res )
826 ( $reqs->{modreqs_fully_documented} ? " (see @{[ ref $self || $self ]} documentation for details)" : '' ),
830 sub modreq_missing_for {
831 my ($self, $groups) = @_;
833 my $reqs = $self->_groups_to_reqs($groups);
834 my $modreq_errors = $self->_errorlist_for_modreqs($reqs->{modreqs})
838 { $reqs->{modreqs}{$_} ? "$_~$reqs->{modreqs}{$_}" : $_ }
839 sort { lc($a) cmp lc($b) } keys %$modreq_errors
845 my ($self, $groups) = @_;
847 $tb ||= do { local $@; eval { Test::Builder->new } }
848 or croak "Calling skip_without() before loading Test::Builder makes no sense";
850 if ( my $err = $self->req_missing_for($groups) ) {
851 my ($fn, $ln) = (caller(0))[1,2];
852 $tb->skip("block in $fn around line $ln requires $err");
860 sub die_unless_req_ok_for {
861 if (my $err = shift->req_missing_for(shift) ) {
862 die "Unable to continue due to missing requirements: $err\n";
868 ### Private functions
870 # potentially shorten group desc
871 sub __envvar_group_desc {
874 my (@res, $last_prefix);
875 while (my $ev = shift @envs) {
876 my ($pref, $sep, $suff) = split / ([\_\-]) (?= [^\_\-]+ \z )/x, $ev;
878 if ( defined $sep and ($last_prefix||'') eq $pref ) {
879 push @res, "...${sep}${suff}"
885 $last_prefix = $pref if $sep;
891 my $groupname_re = qr/ [a-z_] [0-9_a-z]* /x;
892 my $modname_re = qr/ [A-Z_a-z] [0-9A-Z_a-z]* (?:::[0-9A-Z_a-z]+)* /x;
893 my $modver_re = qr/ [0-9]+ (?: \. [0-9]+ )? /x;
895 # Expand includes from a random group in a specific order:
896 # nonvariable groups first, then their includes, then the variable groups,
897 # then their includes.
898 # This allows reliably marking the rest of the mod reqs as variable (this is
899 # also why variable includes are currently not allowed)
900 sub __expand_includes {
901 my ($groups, $seen) = @_;
903 # !! DIFFERENT !! behavior and return depending on invocation mode
904 # (easier to recurse this way)
905 my $is_toplevel = $seen
910 my ($res_per_type, $missing_envvars);
912 # breadth-first evaluation, with non-variable includes on top
913 for my $g (@$groups) {
915 croak "Invalid requirement group name '$g': only ascii alphanumerics and _ are allowed"
916 if $g !~ qr/ \A $groupname_re \z/x;
918 my $r = $dbic_reqs->{$g}
919 or croak "Requirement group '$g' is not defined";
921 # always do this check *before* the $seen check
922 croak "Group '$g' with variable effective_modreqs can not be specified as an 'include'"
923 if ( $r->{env} and ! $is_toplevel );
925 next if $seen->{$g}++;
927 my $req_type = 'static';
929 if ( my @e = @{$r->{env}||[]} ) {
931 croak "Unexpected 'env' attribute under group '$g' (only allowed in test_* groups)"
932 unless $g =~ /^test_/;
934 croak "Unexpected *odd* list in 'env' under group '$g'"
937 # deconstruct the whole thing
938 my (@group_envnames_list, $some_envs_required, $some_required_missing);
940 push @group_envnames_list, my $envname = shift @e;
942 # env required or not
943 next unless shift @e;
945 $some_envs_required ||= 1;
947 $some_required_missing ||= (
948 ! defined $ENV{$envname}
950 ! length $ENV{$envname}
954 croak "None of the envvars in group '$g' declared as required, making the requirement moot"
955 unless $some_envs_required;
957 if ($some_required_missing) {
958 push @{$missing_envvars->{$g}}, \@group_envnames_list;
959 $req_type = 'variable';
963 push @{$res_per_type->{"base_${req_type}"}}, $g;
965 if (my $i = $dbic_reqs->{$g}{include}) {
966 $i = [ $i ] unless ref $i eq 'ARRAY';
968 croak "Malformed 'include' for group '$g': must be another existing group name or arrayref of existing group names"
971 push @{$res_per_type->{"incs_${req_type}"}}, @$i;
976 @{ $res_per_type->{"base_${_}"} || [] },
977 ( $res_per_type->{"incs_${_}"} ? __expand_includes( $res_per_type->{"incs_${_}"}, $seen ) : () ),
978 } qw(static variable);
980 return ! $is_toplevel ? @ret : do {
983 idx => 1 + keys %$rv,
984 missing_envvars => $missing_envvars->{$_},
986 $rv->{$_}{user_requested} = 1 for @$groups;
992 our %req_unavailability_cache;
994 # this method is just a lister and envvar/metadata checker - it does not try to load anything
995 sub _groups_to_reqs {
996 my ($self, $want) = @_;
998 $want = [ $want || () ]
999 unless ref $want eq 'ARRAY';
1001 croak "@{[ (caller(1))[3] ]}() expects a requirement group name or arrayref of group names"
1006 modreqs_fully_documented => 1,
1010 for my $piece (@$want) {
1011 if ($piece =~ qr/ \A $groupname_re \z /x) {
1012 push @$groups, $piece;
1014 elsif ( my ($mod, $ver) = $piece =~ qr/ \A ($modname_re) \>\= ($modver_re) \z /x ) {
1015 croak "Ad hoc module specification lists '$mod' twice"
1016 if exists $ret->{modreqs}{$mod};
1018 croak "Ad hoc module specification '${mod} >= $ver' (or greater) not listed in the test_adhoc optdep group" if (
1019 ! defined $dbic_reqs->{test_adhoc}{req}{$mod}
1021 $dbic_reqs->{test_adhoc}{req}{$mod} < $ver
1024 $ret->{modreqs}{$mod} = $ver;
1025 $ret->{modreqs_fully_documented} = 0;
1028 croak "Unsupported argument '$piece' supplied to @{[ (caller(1))[3] ]}()"
1032 my $all_groups = __expand_includes($groups);
1034 # pre-assemble list of augmentations, perform basic sanity checks
1035 # Note that below we *DO NOT* respect the source/target reationship, but
1036 # instead always default to augment the "later" group
1037 # This is done so that the "stable/variable" boundary keeps working as
1040 for my $requesting_group (keys %$all_groups) {
1041 if (my $ag = $dbic_reqs->{$requesting_group}{augment}) {
1042 for my $target_group (keys %$ag) {
1044 croak "Group '$requesting_group' claims to augment a non-existent group '$target_group'"
1045 unless $dbic_reqs->{$target_group};
1047 croak "Augmentation combined with variable effective_modreqs currently unsupported for group '$requesting_group'"
1048 if $dbic_reqs->{$requesting_group}{env};
1050 croak "Augmentation of group '$target_group' with variable effective_modreqs unsupported (requested by '$requesting_group')"
1051 if $dbic_reqs->{$target_group}{env};
1053 if (my @foreign = grep { $_ ne 'req' } keys %{$ag->{$target_group}} ) {
1054 croak "Only 'req' augmentations are currently supported (group '$requesting_group' attempts to alter '$foreign[0]' of group '$target_group'";
1057 $ret->{augments}{$target_group} = 1;
1059 # no augmentation for stuff that hasn't been selected
1060 if ( $all_groups->{$target_group} and my $ar = $ag->{$target_group}{req} ) {
1061 push @{$augmentations->{
1062 ( $all_groups->{$requesting_group}{idx} < $all_groups->{$target_group}{idx} )
1071 for my $group (sort { $all_groups->{$a}{idx} <=> $all_groups->{$b}{idx} } keys %$all_groups ) {
1073 my $group_reqs = $dbic_reqs->{$group}{req};
1076 for my $req_bag ($group_reqs, @{ $augmentations->{$group} || [] } ) {
1077 for (keys %$req_bag) {
1079 $_ =~ / \A $modname_re \z /x
1080 or croak "Requirement '$_' in group '$group' is not a valid module name";
1082 # !!!DO NOT CHANGE!!!
1083 # remember - version.pm may not be available on the system
1084 croak "Requirement '$_' in group '$group' specifies an invalid version '$req_bag->{$_}' (only plain non-underscored floating point decimals are supported)"
1085 if ( ($req_bag->{$_}||0) !~ qr/ \A $modver_re \z /x );
1089 if (my $e = $all_groups->{$group}{missing_envvars}) {
1090 push @{$ret->{missing_envvars}}, @$e;
1093 # assemble into the final ret
1096 ( $ret->{missing_envvars} ? () : 'effective_modreqs' ),
1098 for my $req_bag ($group_reqs, @{ $augmentations->{$group} || [] } ) {
1099 for my $mod (keys %$req_bag) {
1101 $ret->{$type}{$mod} = $req_bag->{$mod}||0 if (
1103 ! exists $ret->{$type}{$mod}
1105 # we sanitized the version to be numeric above - we can just -gt it
1106 ($req_bag->{$mod}||0) > $ret->{$type}{$mod}
1113 $ret->{modreqs_fully_documented} &&= !!$dbic_reqs->{$group}{pod}
1114 if $all_groups->{$group}{user_requested};
1116 $ret->{release_testing_mandatory} ||= !!$dbic_reqs->{$group}{release_testing_mandatory};
1123 # this method tries to find/load specified modreqs and returns a hashref of
1124 # module/loaderror pairs for anything that failed
1125 sub _errorlist_for_modreqs {
1126 # args supposedly already went through _groups_to_reqs and are therefore sanitized
1127 # safe to eval at will
1128 my ($self, $reqs) = @_;
1132 for my $m ( keys %$reqs ) {
1133 my $v = $reqs->{$m};
1135 if (! exists $req_unavailability_cache{$m}{$v} ) {
1137 eval( "require $m;" . ( $v ? "$m->VERSION(q($v))" : '' ) );
1138 $req_unavailability_cache{$m}{$v} = $@;
1141 $ret->{$m} = $req_unavailability_cache{$m}{$v}
1142 if $req_unavailability_cache{$m}{$v};
1148 # Unlike the above DO NOT try to load anything
1149 # This is executed when some needed envvars are not available
1150 # which in turn means a module load will never be reached anyway
1151 # This is important because some modules (especially DBDs) can be
1152 # *really* fickle when a require() is attempted, with pretty confusing
1153 # side-effects (especially on windows)
1154 sub _list_physically_missing_modules {
1155 my ($self, $modreqs) = @_;
1157 # in case there is a coderef in @INC there is nothing we can definitively prove
1158 # so short circuit directly
1159 return '' if grep { length ref $_ } @INC;
1161 my @definitely_missing;
1162 for my $mod (keys %$modreqs) {
1163 (my $fn = $mod . '.pm') =~ s|::|/|g;
1165 push @definitely_missing, $mod unless grep
1166 # this should work on any combination of slashes
1167 { $_ and -d $_ and -f "$_/$fn" and -r "$_/$fn" }
1173 { $modreqs->{$_} ? "$_~$modreqs->{$_}" : $_ }
1174 sort { lc($a) cmp lc($b) } @definitely_missing
1179 # This is to be called by the author only (automatically in Makefile.PL)
1181 my ($class, $distver, $pod_dir) = @_;
1183 die "No POD root dir supplied" unless $pod_dir;
1186 eval { require DBIx::Class; DBIx::Class->VERSION; }
1189 "\n\n---------------------------------------------------------------------\n" .
1190 'Unable to load core DBIx::Class module to determine current version, '.
1191 'possibly due to missing dependencies. Author-mode autodocumentation ' .
1193 "\n\n---------------------------------------------------------------------\n"
1196 # do not ask for a recent version, use 1.x API calls
1197 # this *may* execute on a smoker with old perl or whatnot
1200 (my $modfn = __PACKAGE__ . '.pm') =~ s|::|/|g;
1202 (my $podfn = "$pod_dir/$modfn") =~ s/\.pm$/\.pod/;
1203 (my $dir = $podfn) =~ s|/[^/]+$||;
1205 File::Path::mkpath([$dir]);
1207 my $sqltver = $class->req_list_for('deploy')->{'SQL::Translator'}
1208 or die "Hrmm? No sqlt dep?";
1216 push @chunks, <<"EOC";
1217 #########################################################################
1218 ##################### A U T O G E N E R A T E D ########################
1219 #########################################################################
1221 # The contents of this POD file are auto-generated. Any changes you make
1222 # will be lost. If you need to change the generated text edit _gen_pod()
1223 # at the end of $modfn
1228 $class - Optional module dependency specifications (for module authors)
1233 #@@ SYNOPSIS HEADING
1235 push @chunks, <<"EOC";
1238 Somewhere in your build-file (e.g. L<ExtUtils::MakeMaker>'s F<Makefile.PL>):
1242 \$EUMM_ARGS{CONFIGURE_REQUIRES} = {
1243 \%{ \$EUMM_ARGS{CONFIGURE_REQUIRES} || {} },
1244 'DBIx::Class' => '$distver',
1249 my %DBIC_DEPLOY_AND_ORACLE_DEPS = %{ eval {
1251 $class->req_list_for([qw( deploy rdbms_oracle ic_dt )]);
1254 \$EUMM_ARGS{PREREQ_PM} = {
1255 \%DBIC_DEPLOY_AND_ORACLE_DEPS,
1256 \%{ \$EUMM_ARGS{PREREQ_PM} || {} },
1261 ExtUtils::MakeMaker::WriteMakefile(\%EUMM_ARGS);
1263 B<Note>: The C<eval> protection within the example is due to support for
1264 requirements during L<the C<configure> build phase|CPAN::Meta::Spec/Phases>
1265 not being available on a sufficient portion of production installations of
1266 Perl. Robust support for such dependency requirements is available in the
1267 L<CPAN> installer only since version C<1.94_56> first made available for
1268 production with perl version C<5.12>. It is the belief of the current
1269 maintainer that support for requirements during the C<configure> build phase
1270 will not be sufficiently ubiquitous until the B<year 2020> at the earliest,
1271 hence the extra care demonstrated above. It should also be noted that some
1272 3rd party installers (e.g. L<cpanminus|App::cpanminus>) do the right thing
1273 with configure requirements independent from the versions of perl and CPAN
1279 #@@ DESCRIPTION HEADING
1281 push @chunks, <<'EOC';
1284 Some of the less-frequently used features of L<DBIx::Class> have external
1285 module dependencies on their own. In order not to burden the average user
1286 with modules they will never use, these optional dependencies are not included
1287 in the base Makefile.PL. Instead an exception with a descriptive message is
1288 thrown when a specific feature can't find one or several modules required for
1289 its operation. This module is the central holding place for the current list
1290 of such dependencies, for DBIx::Class core authors, and DBIx::Class extension
1293 Dependencies are organized in L<groups|/CURRENT REQUIREMENT GROUPS> where each
1294 group can list one or more required modules, with an optional minimum version
1295 (or 0 for any version). In addition groups prefixed with C<test_> can specify
1296 a set of environment variables, some (or all) of which are marked as required
1297 for the group to be considered by L</req_list_for>
1299 Each group name (or a combination thereof) can be used in the
1300 L<public methods|/METHODS> as described below.
1305 #@@ REQUIREMENT GROUPLIST HEADING
1307 push @chunks, '=head1 CURRENT REQUIREMENT GROUPS';
1309 my $standalone_info;
1311 for my $group (sort keys %$dbic_reqs) {
1313 my $info = $standalone_info->{$group} ||= $class->_groups_to_reqs($group);
1316 $info->{modreqs_fully_documented}
1318 ( $info->{augments} or $info->{modreqs} )
1321 my $p = $dbic_reqs->{$group}{pod};
1324 "=head2 $p->{title}",
1330 if ( keys %{ $info->{modreqs}||{} } ) {
1332 { "=item * $_" . ($info->{modreqs}{$_} ? " >= $info->{modreqs}{$_}" : '') }
1333 ( sort keys %{ $info->{modreqs} } )
1337 push @chunks, '=item * No standalone requirements',
1340 push @chunks, '=back';
1342 for my $ag ( sort keys %{ $info->{augments} || {} } ) {
1343 my $ag_info = $standalone_info->{$ag} ||= $class->_groups_to_reqs($ag);
1345 my $newreqs = $class->modreq_list_for([ $group, $ag ]);
1346 for (keys %$newreqs) {
1347 delete $newreqs->{$_} if (
1348 ( defined $info->{modreqs}{$_} and $info->{modreqs}{$_} == $newreqs->{$_} )
1350 ( defined $ag_info->{modreqs}{$_} and $ag_info->{modreqs}{$_} == $newreqs->{$_} )
1354 if (keys %$newreqs) {
1356 "Combined with L</$ag> additionally requires:",
1359 { "=item * $_" . ($newreqs->{$_} ? " >= $newreqs->{$_}" : '') }
1360 ( sort keys %$newreqs )
1370 #@@ API DOCUMENTATION HEADING
1372 push @chunks, <<'EOC';
1374 =head1 IMPORT-LIKE ACTIONS
1376 Even though this module is not an L<Exporter>, it recognizes several C<actions>
1377 supplied to its C<import> method.
1379 =head2 -skip_all_without
1383 =item Arguments: @group_names
1387 A convenience wrapper for use during testing:
1390 push @chunks, " use $class -skip_all_without => qw(admin test_rdbms_mysql);";
1392 push @chunks, 'Roughly equivalent to the following code:';
1394 push @chunks, sprintf <<'EOS', ($class) x 2;
1398 if ( my $missing = %s->req_missing_for(\@group_names_) ) {
1399 print "1..0 # SKIP requirements not satisfied: $missing\n";
1405 push @chunks, <<'EOC';
1407 It also takes into account the C<RELEASE_TESTING> environment variable and
1408 behaves like L</-die_without> for any requirement groups marked as
1409 C<release_testing_mandatory>.
1415 =item Arguments: @group_names
1419 A convenience wrapper around L</die_unless_req_ok_for>:
1422 push @chunks, " use $class -die_without => qw(deploy admin);";
1424 push @chunks, <<'EOC';
1426 =head2 -list_missing
1430 =item Arguments: @group_names
1434 A convenience wrapper around L</modreq_missing_for>:
1436 perl -Ilib -MDBIx::Class::Optional::Dependencies=-list_missing,deploy,admin | cpanm
1440 =head2 req_group_list
1444 =item Arguments: none
1446 =item Return Value: \%list_of_requirement_groups
1450 This method should be used by DBIx::Class packagers, to get a hashref of all
1451 dependencies B<keyed> by dependency group. Each key (group name), or a combination
1452 thereof (as an arrayref) can be supplied to the methods below.
1453 The B<values> of the returned hash are currently a set of options B<without a
1454 well defined structure>. If you have use for any of the contents - contact the
1455 maintainers, instead of treating this as public (left alone stable) API.
1461 =item Arguments: $group_name | \@group_names
1463 =item Return Value: \%set_of_module_version_pairs
1467 This method should be used by DBIx::Class extension authors, to determine the
1468 version of modules a specific set of features requires for this version of
1469 DBIx::Class (regardless of their availability on the system).
1470 See the L</SYNOPSIS> for a real-world example.
1472 When handling C<test_*> groups this method behaves B<differently> from
1473 L</modreq_list_for> below (and is the only such inconsistency among the
1474 C<req_*> methods). If a particular group declares as requirements some
1475 C<environment variables> and these requirements are not satisfied (the envvars
1476 are unset) - then the C<module requirements> of this group are not included in
1479 =head2 modreq_list_for
1483 =item Arguments: $group_name | \@group_names
1485 =item Return Value: \%set_of_module_version_pairs
1489 Same as L</req_list_for> but does not take into consideration any
1490 C<environment variable requirements> - returns just the list of required
1497 =item Arguments: $group_name | \@group_names
1499 =item Return Value: 1|0
1503 Returns true or false depending on whether all modules/envvars required by
1504 the group(s) are loadable/set on the system.
1506 =head2 req_missing_for
1510 =item Arguments: $group_name | \@group_names
1512 =item Return Value: $error_message_string
1516 Returns a single-line string suitable for inclusion in larger error messages.
1517 This method would normally be used by DBIx::Class core features, to indicate to
1518 the user that they need to install specific modules and/or set specific
1519 environment variables before being able to use a specific feature set.
1521 For example if some of the requirements for C<deploy> are not available,
1522 the returned string could look like:
1525 push @chunks, qq{ "SQL::Translator~$sqltver" (see $class documentation for details)};
1527 push @chunks, <<'EOC';
1528 The author is expected to prepend the necessary text to this message before
1529 returning the actual error seen by the user. See also L</modreq_missing_for>
1531 =head2 modreq_missing_for
1535 =item Arguments: $group_name | \@group_names
1537 =item Return Value: $error_message_string
1541 Same as L</req_missing_for> except that the error string is guaranteed to be
1542 either empty, or contain a set of module requirement specifications suitable
1543 for piping to e.g. L<cpanminus|App::cpanminus>. The method explicitly does not
1544 attempt to validate the state of required environment variables (if any).
1546 For instance if some of the requirements for C<deploy> are not available,
1547 the returned string could look like:
1550 push @chunks, qq{ "SQL::Translator~$sqltver"};
1552 push @chunks, <<'EOC';
1554 See also L</-list_missing>.
1560 =item Arguments: $group_name | \@group_names
1564 A convenience wrapper around L<skip|Test::More/SKIP>. It does not take neither
1565 a reason (it is generated by L</req_missing_for>) nor an amount of skipped tests
1566 (it is always C<1>, thus mandating unconditional use of
1567 L<done_testing|Test::More/done_testing>). Most useful in combination with ad hoc
1568 requirement specifications:
1571 push @chunks, <<EOC;
1573 $class->skip_without([ deploy YAML>=0.90 ]);
1579 push @chunks, <<'EOC';
1581 =head2 die_unless_req_ok_for
1585 =item Arguments: $group_name | \@group_names
1589 Checks if L</req_ok_for> passes for the supplied group(s), and
1590 in case of failure throws an exception including the information
1591 from L</req_missing_for>. See also L</-die_without>.
1593 =head2 modreq_errorlist_for
1597 =item Arguments: $group_name | \@group_names
1599 =item Return Value: \%set_of_loaderrors_per_module
1603 Returns a hashref containing the actual errors that occurred while attempting
1604 to load each module in the requirement group(s).
1606 =head2 req_errorlist_for
1608 Deprecated method name, equivalent (via proxy) to L</modreq_errorlist_for>.
1615 push @chunks, <<'EOC';
1616 =head1 FURTHER QUESTIONS?
1618 Check the list of L<additional DBIC resources|DBIx::Class/GETTING HELP/SUPPORT>.
1620 =head1 COPYRIGHT AND LICENSE
1622 This module is free software L<copyright|DBIx::Class/COPYRIGHT AND LICENSE>
1623 by the L<DBIx::Class (DBIC) authors|DBIx::Class/AUTHORS>. You can
1624 redistribute it and/or modify it under the same terms as the
1625 L<DBIx::Class library|DBIx::Class/COPYRIGHT AND LICENSE>.
1629 open (my $fh, '>', $podfn) or die;
1630 print $fh join ("\n\n", @chunks) or die;
1631 print $fh "\n" or die;
1633 } or croak( "Unable to write $podfn: " . ( $! || $@ || 'unknown error') );