Massive cleanup of DateTime test dependencies, other interim
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Optional / Dependencies.pm
CommitLineData
8057ed01 1package DBIx::Class::Optional::Dependencies;
2
3use warnings;
4use strict;
5
fb39747c 6use Carp;
7
8# NO EXTERNAL NON-5.8.1 CORE DEPENDENCIES EVER (e.g. C::A::G)
8057ed01 9# This module is to be loaded by Makefile.PM on a pristine system
10
f6b26571 11# POD is generated automatically by calling _gen_pod from the
12# Makefile.PL in $AUTHOR mode
13
2b48ebff 14my $moose_basic = {
68de9438 15 'Moose' => '0.98',
16 'MooseX::Types' => '0.21',
17};
18
19my $replicated = {
20 %$moose_basic,
21 'Hash::Merge' => '0.12',
2b48ebff 22};
23
ebcd0e4f 24my $admin_basic = {
25 %$moose_basic,
68de9438 26 'MooseX::Types::Path::Class' => '0.05',
27 'MooseX::Types::JSON' => '0.02',
28 'JSON::Any' => '1.22',
29 'namespace::autoclean' => '0.09',
30};
31
32my $datetime_basic = {
33 'DateTime' => '0.55',
34 'DateTime::Format::Strptime' => '1.2',
ebcd0e4f 35};
36
8057ed01 37my $reqs = {
38 dist => {
39 #'Module::Install::Pod::Inherit' => '0.01',
40 },
41
42 replicated => {
68de9438 43 req => $replicated,
f6b26571 44 pod => {
45 title => 'Storage::Replicated',
46 desc => 'Modules required for L<DBIx::Class::Storage::DBI::Replicated>',
47 },
8057ed01 48 },
49
68de9438 50 test_replicated => {
51 req => {
52 %$replicated,
53 'Test::Moose' => '0',
54 },
55 },
56
57
8057ed01 58 admin => {
2b48ebff 59 req => {
ebcd0e4f 60 %$admin_basic,
61 },
62 pod => {
63 title => 'DBIx::Class::Admin',
64 desc => 'Modules required for the DBIx::Class administrative library',
65 },
66 },
67
a4a02f15 68 admin_script => {
ebcd0e4f 69 req => {
2b48ebff 70 %$moose_basic,
ebcd0e4f 71 %$admin_basic,
2b48ebff 72 'Getopt::Long::Descriptive' => '0.081',
2b48ebff 73 'Text::CSV' => '1.16',
74 },
e144415f 75 pod => {
76 title => 'dbicadmin',
77 desc => 'Modules required for the CLI DBIx::Class interface dbicadmin',
78 },
8057ed01 79 },
80
81 deploy => {
f6b26571 82 req => {
9e34d554 83 'SQL::Translator' => '0.11006',
f6b26571 84 },
85 pod => {
86 title => 'Storage::DBI::deploy()',
87 desc => 'Modules required for L<DBIx::Class::Storage::DBI/deploy> and L<DBIx::Class::Storage::DBI/deploymen_statements>',
88 },
8057ed01 89 },
90
a109c954 91
92 test_pod => {
f6b26571 93 req => {
14d17d71 94 'Test::Pod' => '1.41',
a109c954 95 },
96 },
97
98 test_podcoverage => {
99 req => {
f6b26571 100 'Test::Pod::Coverage' => '1.08',
101 'Pod::Coverage' => '0.20',
a109c954 102 },
103 },
104
105 test_notabs => {
106 req => {
d146b340 107 'Test::NoTabs' => '0.9',
a109c954 108 },
109 },
110
111 test_eol => {
112 req => {
d146b340 113 'Test::EOL' => '0.6',
f6b26571 114 },
8057ed01 115 },
116
a109c954 117 test_cycle => {
f6b26571 118 req => {
f6b26571 119 'Test::Memory::Cycle' => '0',
120 'Devel::Cycle' => '1.10',
a109c954 121 },
122 },
f6b26571 123
68de9438 124 test_dt => {
125 req => $datetime_basic,
126 },
127
128 test_dt_sqlite => {
a109c954 129 req => {
68de9438 130 %$datetime_basic,
f6b26571 131 # t/36datetime.t
132 # t/60core.t
133 'DateTime::Format::SQLite' => '0',
68de9438 134 },
135 },
f6b26571 136
68de9438 137 test_dt_mysql => {
138 req => {
139 %$datetime_basic,
9c92bb1c 140 # t/inflate/datetime_mysql.t
141 # (doesn't need Mysql itself)
68de9438 142 'DateTime::Format::MySQL' => '0',
143 },
144 },
9c92bb1c 145
68de9438 146 test_dt_pg => {
147 req => {
148 %$datetime_basic,
9c92bb1c 149 # t/inflate/datetime_pg.t
150 # (doesn't need PG itself)
68de9438 151 'DateTime::Format::Pg' => '0',
f6b26571 152 },
8057ed01 153 },
154
68de9438 155 test_cdbicompat => {
f6b26571 156 req => {
157 'DBIx::ContextualFetch' => '0',
158 'Class::DBI::Plugin::DeepAbstractSearch' => '0',
159 'Class::Trigger' => '0',
160 'Time::Piece::MySQL' => '0',
161 'Clone' => '0',
162 'Date::Simple' => '3.03',
163 },
8057ed01 164 },
165
68de9438 166 test_rdbms_pg => {
f6b26571 167 req => {
168 $ENV{DBICTEST_PG_DSN}
169 ? (
170 'Sys::SigAction' => '0',
171 'DBD::Pg' => '2.009002',
f6b26571 172 ) : ()
173 },
8057ed01 174 },
175
68de9438 176 test_rdbms_mysql => {
f6b26571 177 req => {
178 $ENV{DBICTEST_MYSQL_DSN}
179 ? (
f6b26571 180 'DBD::mysql' => '0',
181 ) : ()
182 },
8057ed01 183 },
184
68de9438 185 test_rdbms_oracle => {
f6b26571 186 req => {
187 $ENV{DBICTEST_ORA_DSN}
188 ? (
189 'DateTime::Format::Oracle' => '0',
e1b7e9b4 190 'DBD::Oracle' => '1.24',
f6b26571 191 ) : ()
192 },
8057ed01 193 },
194
68de9438 195 test_rdbms_ase => {
f6b26571 196 req => {
197 $ENV{DBICTEST_SYBASE_DSN}
198 ? (
199 'DateTime::Format::Sybase' => 0,
200 ) : ()
201 },
8057ed01 202 },
203
68de9438 204 test_rdbms_db2 => {
f58a165c 205 req => {
206 $ENV{DBICTEST_DB2_DSN}
207 ? (
208 'DBD::DB2' => 0,
209 ) : ()
210 },
211 },
212
8057ed01 213};
214
f6b26571 215
fb39747c 216sub req_list_for {
217 my ($class, $group) = @_;
218
f6b26571 219 croak "req_list_for() expects a requirement group name"
fb39747c 220 unless $group;
221
f6b26571 222 my $deps = $reqs->{$group}{req}
223 or croak "Requirement group '$group' does not exist";
fb39747c 224
225 return { %$deps };
226}
227
228
229our %req_availability_cache;
230sub req_ok_for {
231 my ($class, $group) = @_;
232
233 croak "req_ok_for() expects a requirement group name"
234 unless $group;
235
d8799bab 236 return $class->_check_deps($group)->{status};
fb39747c 237}
238
239sub req_missing_for {
240 my ($class, $group) = @_;
241
242 croak "req_missing_for() expects a requirement group name"
243 unless $group;
244
d8799bab 245 return $class->_check_deps($group)->{missing};
fb39747c 246}
247
248sub req_errorlist_for {
249 my ($class, $group) = @_;
250
251 croak "req_errorlist_for() expects a requirement group name"
252 unless $group;
253
d8799bab 254 return $class->_check_deps($group)->{errorlist};
fb39747c 255}
256
257sub _check_deps {
258 my ($class, $group) = @_;
259
d8799bab 260 return $req_availability_cache{$group} ||= do {
261
262 my $deps = $class->req_list_for ($group);
263
264 my %errors;
265 for my $mod (keys %$deps) {
266 my $req_line = "require $mod;";
267 if (my $ver = $deps->{$mod}) {
268 $req_line .= "$mod->VERSION($ver);";
269 }
270
271 eval $req_line;
272
273 $errors{$mod} = $@ if $@;
274 }
275
276 my $res;
fb39747c 277
d8799bab 278 if (keys %errors) {
279 my $missing = join (', ', map { $deps->{$_} ? "$_ >= $deps->{$_}" : $_ } (sort keys %errors) );
280 $missing .= " (see $class for details)" if $reqs->{$group}{pod};
281 $res = {
282 status => 0,
283 errorlist => \%errors,
284 missing => $missing,
285 };
fb39747c 286 }
287 else {
d8799bab 288 $res = {
289 status => 1,
290 errorlist => {},
291 missing => '',
292 };
fb39747c 293 }
294
d8799bab 295 $res;
296 };
fb39747c 297}
298
e3fc11e1 299sub req_group_list {
300 return { map { $_ => { %{ $reqs->{$_}{req} || {} } } } (keys %$reqs) };
301}
302
303# This is to be called by the author only (automatically in Makefile.PL)
f6b26571 304sub _gen_pod {
31fa1764 305
f6b26571 306 my $class = shift;
af4ac504 307 my $modfn = __PACKAGE__ . '.pm';
308 $modfn =~ s/\:\:/\//g;
f6b26571 309
31fa1764 310 my $podfn = __FILE__;
311 $podfn =~ s/\.pm$/\.pod/;
312
313 my $distver =
314 eval { require DBIx::Class; DBIx::Class->VERSION; }
315 ||
316 do {
317 warn
318"\n\n---------------------------------------------------------------------\n" .
319'Unable to load core DBIx::Class module to determine current version, '.
320'possibly due to missing dependencies. Author-mode autodocumentation ' .
321"halted\n\n" . $@ .
322"\n\n---------------------------------------------------------------------\n"
323 ;
324 '*UNKNOWN*'; # rv
325 }
326 ;
327
e3fc11e1 328 my $sqltver = $class->req_list_for ('deploy')->{'SQL::Translator'}
329 or die "Hrmm? No sqlt dep?";
7e3dc46f 330
f6b26571 331 my @chunks = (
d8799bab 332 <<'EOC',
af4ac504 333#########################################################################
334##################### A U T O G E N E R A T E D ########################
335#########################################################################
336#
337# The contents of this POD file are auto-generated. Any changes you make
338# will be lost. If you need to change the generated text edit _gen_pod()
339# at the end of $modfn
340#
341EOC
f6b26571 342 '=head1 NAME',
7e3dc46f 343 "$class - Optional module dependency specifications (for module authors)",
e3fc11e1 344 '=head1 SYNOPSIS',
d8799bab 345 <<"EOS",
7e3dc46f 346Somewhere in your build-file (e.g. L<Module::Install>'s Makefile.PL):
347
348 ...
349
350 configure_requires 'DBIx::Class' => '$distver';
351
352 require $class;
353
354 my \$deploy_deps = $class->req_list_for ('deploy');
355
356 for (keys %\$deploy_deps) {
357 requires \$_ => \$deploy_deps->{\$_};
358 }
359
360 ...
361
362Note that there are some caveats regarding C<configure_requires()>, more info
363can be found at L<Module::Install/configure_requires>
364EOS
f6b26571 365 '=head1 DESCRIPTION',
366 <<'EOD',
367Some of the less-frequently used features of L<DBIx::Class> have external
368module dependencies on their own. In order not to burden the average user
369with modules he will never use, these optional dependencies are not included
370in the base Makefile.PL. Instead an exception with a descriptive message is
371thrown when a specific feature is missing one or several modules required for
372its operation. This module is the central holding place for the current list
7e3dc46f 373of such dependencies, for DBIx::Class core authors, and DBIx::Class extension
374authors alike.
f6b26571 375EOD
376 '=head1 CURRENT REQUIREMENT GROUPS',
377 <<'EOD',
378Dependencies are organized in C<groups> and each group can list one or more
379required modules, with an optional minimum version (or 0 for any version).
ecb68746 380The group name can be used in the
f6b26571 381EOD
382 );
383
384 for my $group (sort keys %$reqs) {
385 my $p = $reqs->{$group}{pod}
386 or next;
387
388 my $modlist = $reqs->{$group}{req}
389 or next;
390
391 next unless keys %$modlist;
392
393 push @chunks, (
394 "=head2 $p->{title}",
395 "$p->{desc}",
396 '=over',
397 ( map { "=item * $_" . ($modlist->{$_} ? " >= $modlist->{$_}" : '') } (sort keys %$modlist) ),
398 '=back',
399 "Requirement group: B<$group>",
400 );
401 }
402
403 push @chunks, (
404 '=head1 METHODS',
e3fc11e1 405 '=head2 req_group_list',
406 '=over',
d8799bab 407 '=item Arguments: none',
e3fc11e1 408 '=item Returns: \%list_of_requirement_groups',
409 '=back',
d8799bab 410 <<'EOD',
e3fc11e1 411This method should be used by DBIx::Class packagers, to get a hashref of all
412dependencies keyed by dependency group. Each key (group name) can be supplied
413to one of the group-specific methods below.
414EOD
415
f6b26571 416 '=head2 req_list_for',
417 '=over',
418 '=item Arguments: $group_name',
419 '=item Returns: \%list_of_module_version_pairs',
420 '=back',
d8799bab 421 <<'EOD',
f6b26571 422This method should be used by DBIx::Class extension authors, to determine the
7e3dc46f 423version of modules a specific feature requires in the B<current> version of
e3fc11e1 424DBIx::Class. See the L</SYNOPSIS> for a real-world
7e3dc46f 425example.
f6b26571 426EOD
427
428 '=head2 req_ok_for',
429 '=over',
430 '=item Arguments: $group_name',
431 '=item Returns: 1|0',
432 '=back',
d8799bab 433 <<'EOD',
434Returns true or false depending on whether all modules required by
435C<$group_name> are present on the system and loadable.
436EOD
f6b26571 437
438 '=head2 req_missing_for',
439 '=over',
440 '=item Arguments: $group_name',
441 '=item Returns: $error_message_string',
442 '=back',
d8799bab 443 <<"EOD",
f6b26571 444Returns a single line string suitable for inclusion in larger error messages.
445This method would normally be used by DBIx::Class core-module author, to
446indicate to the user that he needs to install specific modules before he will
447be able to use a specific feature.
448
e3fc11e1 449For example if some of the requirements for C<deploy> are not available,
450the returned string could look like:
f6b26571 451
e3fc11e1 452 SQL::Translator >= $sqltver (see $class for details)
f6b26571 453
454The author is expected to prepend the necessary text to this message before
455returning the actual error seen by the user.
456EOD
457
458 '=head2 req_errorlist_for',
459 '=over',
460 '=item Arguments: $group_name',
461 '=item Returns: \%list_of_loaderrors_per_module',
462 '=back',
463 <<'EOD',
464Returns a hashref containing the actual errors that occured while attempting
465to load each module in the requirement group.
466EOD
fb8ae353 467 '=head1 AUTHOR',
468 'See L<DBIx::Class/CONTRIBUTORS>.',
469 '=head1 LICENSE',
470 'You may distribute this code under the same terms as Perl itself',
f6b26571 471 );
472
31fa1764 473 open (my $fh, '>', $podfn) or croak "Unable to write to $podfn: $!";
f6b26571 474 print $fh join ("\n\n", @chunks);
475 close ($fh);
476}
477
8057ed01 4781;