Alien-Selenium

 view release on metacpan or  search on metacpan

inc/My/Module/Build.pm  view on Meta::CPAN

=head1 SYNOPSIS

This module works mostly like L<Module::Build> with a few differences
highlighted below. Put this in Build.PL:

=for My::Tests::Below "synopsis" begin

  use strict;
  use warnings;

  ## Replace
  # use Module::Build;
  ## with
  use FindBin; use lib "$FindBin::Bin/inc";
  use My::Module::Build;

  ## Replace
  # my $builder = Module::Build->new(
  ## With
  my $builder = My::Module::Build->new(
     ## ... Use ordinary Module::Build arguments here ...
     build_requires =>    {
           'Acme::Pony'    => 0,
           My::Module::Build->requires_for_build(),
     },
     add_to_no_index => { namespace => [ "My::Private::Stuff" ] },
  );

  ## The remainder of the script works like with stock Module::Build

=for My::Tests::Below "synopsis" end

=head1 DESCRIPTION

DOMQ is a guy who releases CPAN packages from time to time - you are
probably frobbing into one of them right now.

This module is a subclass to L<Module::Build> by Ken Williams, and a
helper that supports DOMQ's coding style for Perl modules so as to
facilitate relasing my code to the world.

=head2 How to use My::Module::Build for a new CPAN package

This part of the documentation is probably only useful to myself,
but hey, you never know - Feel free to share and enjoy!

=over

=item 1.

If not already done, prepare a skeletal CPAN module that uses
L<Module::Build> as its build support class. L<Module::Starter> and
its companion command C<module-starter(1)> is B<highly> recommended
for this purpose, e.g.

   module-starter --mb --module=Main::Screen::Turn::On \
     --author='Dominique Quatravaux' --email='domq@cpan.org' --force

=item 2.

create an C<inc/> subdirectory at the CPAN module's top level and drop
this file there. (While you are there, you could put the rest of the
My:: stuff along with it, and the t/maintainer/ test cases - see L<SEE
ALSO>.)

=item 3.

Amend the Build.PL as highlighted in the L</SYNOPSIS>.

=item 4.

B<VERY IMPORTANT!> Arrange for My::Module::Build and friends to
B<not> be indexed on the CPAN, lest the Perl deities' wrath fall upon
you. This is done by adding the following lines to the META.yml file:

=for My::Tests::Below "META.yml excerpt" begin

 no_index:
   directory:
     - examples
     - inc
     - t

=for My::Tests::Below "META.yml excerpt" end

(indentation is meaningful - "no_index:" must start at the very first
column and the indenting quantum is exactly 2 spaces, B<no tabs
allowed>)

If you prefer the META.yml file to be built automatically, do a

=for My::Tests::Below "distmeta" begin

   ./Build manifest
   ./Build distmeta

=for My::Tests::Below "distmeta" end

and the aforementioned no_index exclusions will be set up
automatically (but B<please double-check nevertheless>).

=back

=head2 Coding Style and Practices supported by this module

No, I don't want to go into silly regulations regarding whether I
should start a new line before the opening bracket in a sub
declaration. This would be coding syntax, or coding grammar. The stuff
here is about style, and only the subset thereof that is somehow under
control of the CPAN build process.

=head3 Unit tests

A large fraction of the unit tests are written as perlmodlib-style
__END__ documents attached directly to the module to test. See
L<My::Tests::Below> for details. My::Module::Build removes the test
footer at build time so as not to waste any resources on the install
target platform.

=head3 Extended C<test> action

inc/My/Module/Build.pm  view on Meta::CPAN


=cut

sub process_pm_files {
    no warnings "once";
    local *copy_if_modified = \*process_pm_file_if_modified;
    my $self = shift;
    return $self->SUPER::process_pm_files(@_);
}

=item I<process_pm_file_if_modified(%args)>

Does the same as L<copy_file_if_modified> (which it actually replaces
while L<process_pm_files> runs), except that the L</new_pm_filter> is
applied instead of performing a vanilla copy as L<Module::Build> does.

=cut

sub process_pm_file_if_modified {
    my ($self, %args) = @_;
    my ($from, $to) = @args{qw(from to)};
    return if $self->up_to_date($from, $to); # Already fresh

    mkpath(dirname($to), 0, 0777);

    # Do a filtering copy
    print "$from -> $to\n" if $args{verbose};
    die "Cannot open $from for reading: $!\n" unless
        (my $fromfd = new IO::File($from, "r"));
    die "Cannot open $to for writing: $!\n" unless
        (my $tofd = new IO::File($to, "w"));

    my $filter = $self->new_pm_filter;
    while(my $line = <$fromfd>) {
        my $moretext = $filter->filter($line);
        if (defined($moretext) && length($moretext)) {
            $tofd->print($moretext) or
                die "Cannot write to $to: $!\n";
        }
        last if $filter->eof_reached();
    }
    $tofd->close() or die "Cannot close to $to: $!\n";
}

=item I<new_pm_filter>

Creates and returns a fresh filter object (see
L</My::Module::Build::PmFilter Ancillary Class>) that will be used by
L</process_pm_file_if_modified> to process the text of the .pm files.
Subclasses may find it convenient to overload I<new_pm_filter> in
order to provide a different filter.  The filter object should obey
the API set forth in L</My::Module::Build::PmFilter Ancillary Class>,
although it need not inherit from same.

=cut

sub new_pm_filter { My::Module::Build::PmFilter->new }

=item I<find_test_files()>

Overloaded from parent class to treat all .pm files in C<lib/> and
C<t/lib/> as unit tests if they use L<My::Tests::Below>, to look for
C<.t> files in C<examples/>, and to retain C<.t> test files in
C<t/maintainer> if and only if L</maintainer_mode_enabled> is true.

=cut

sub find_test_files {
    my $self = shift;

    # Short-cut activated by L</ACTION_test>:
    return $self->{FORCE_find_test_files_result} if
        (defined $self->{FORCE_find_test_files_result});

    my @tests = @{$self->SUPER::find_test_files(@_)};
    # Short-cut activated by putting a 'test_files' key in the constructor
    # arguments:
    return @tests if $self->{test_files};

    @tests = grep { ! m/^t.maintainer/ } @tests unless
        ($self->maintainer_mode_enabled());

    File::Find::find
        ({no_chdir => 1, wanted => sub {
              push(@tests, $_) if $self->find_test_files_predicate();
          }}, $self->find_test_files_in_directories);

    return \@tests;
}

=item I<find_test_files_predicate()>

=item I<find_test_files_in_directories()>

Those two methods are used as callbacks by L</find_test_files>;
subclasses of I<My::Module::Build> may therefore find it convenient to
overload them.  I<find_test_files_in_directories> should return a list
of the directories in which to search for test files.
I<find_test_files_predicate> gets passed the name of each file found
in these directories in the same way as a L<File::Find> C<wanted> sub
would (that is, using $_ and B<not> the argument list); it should
return a true value iff this file is a test file.

=cut

sub find_test_files_predicate {
    my ($self) = @_;
    return 1 if m/My.Tests.Below\.pm$/;
    return if m/\b[_.]svn\b/; # Subversion metadata
    return 1 if m/\.t$/;
    my $module = catfile($self->base_dir, $_);
    local *MODULE;
    unless (open(MODULE, "<", $module)) {
        warn "Cannot open $module: $!";
        return;
    }
    return 1 if grep {
        m/^require\s+My::Tests::Below\s+unless\s+caller/
    } (<MODULE>);
    return;
}

sub find_test_files_in_directories {



( run in 1.732 second using v1.01-cache-2.11-cpan-df04353d9ac )