Turn blank seperated text into a CSV
Wrap all urls in a text into a HTML link
Print version of installed Perl modules
Convert images with Image::Magick
CPAN modules - the good and the bad
Test whether result is one of multiple values
Provide useful information with diag
Net::SSLeay, Crypt::OpenSSL::Random, Crypt::OpenSSL::X509, ...
It is a best practice to use
namespace::clean
in your class or your role
after
use ...
statements. Otherwise imported functions
double as methods for your class, which can have unexpected side effects which
are really hard to track down.
We can recommend to use Type::Tiny instead of MooX::Types::Mooselike. The latter is not Moose-friendly, while Type::Tiny types get inflated to full Moose types if you happen to play with them in Moose. Also they are faster and we get better coercion in Moo for free.
One thing you may not have spotted for Type::Tiny which is useful... it overloads | and & for use in isa - very tidy.
use Moo; use Types::Standard qw/ArrayRef HashRef InstanceOf/; has fields => ( is => 'ro', isa => ArrayRef [ InstanceOf ['Template::Flute::Form::Field'] ], );
has config_files => ( is => 'ro', isa => ArrayRef, default => sub { [] }, );
Sometimes it makes sense to allow undef
as a value, e.g. if the builder isn't able to produce the promised type:
has config => ( is => 'ro', isa => Maybe[HashRef], lazy => 1, builder => '_build_config', );
Ensure that me use UTF-8 encoding for the standard input/output streams:
use open ':std', ':encoding(utf-8)';
APIs often using JSON as output. A JSON date looks like that:
DateTime->now->strftime('%Y-%m-%d');
This function determines the first day of the week for a given year:
sub first_day_of_week { my ($year, $week) = @_; # Week 1 is defined as the one containing January 4: DateTime ->new( year => $year, month => 1, day => 4 ) ->add( weeks => ($week - 1) ) ->truncate( to => 'week' ); }
Split text into an array of lines:
my @lines = split /\r?\n/, $content; my %email_headers; for my $line (@lines) { if ($line =~ /^(From|To):\s(.*)/) { $email_headers{lc($1)} = $2; } }
The simplest way to parse a list of arguments separated by whitespace is the split function:
my $arglist = 'foo bar baz'; my @args = split (/\s+/, $arglist));
This doesn't work with a list of files when it includes filenames with whitespaces:
'foo bar'
'baz'
You can use the shellwords function from the Text::ParseWords module in this case:
use Text::ParseWords; my $arglist = '"foo bar" baz'; my @args = shellwords($arglist);
perl -pe 's/\p{Blank}+/;/g' dns2.txt > dns.csv
$text =~s#(https?://\S+?)(\.*[\s\<,])#<a href="$1">$1</a>$2#igs;
There is a very useful module called V for printing out version information about installed Perl modules:
perl -MV=Dancer2 Dancer2 /home/racke/perl5/perlbrew/perls/perl-5.24.0/lib/site_perl/5.24.1/Dancer2.pm: 0.205000 /home/racke/perl5/perlbrew/perls/perl-5.24.0/lib/site_perl/5.24.0/Dancer2.pm: 0.204001
$ convert mypic.jpg -resize 25% mypicsmall.jpg
$ convert -size 1000x1000 xc:transparent any-square.png
File::Slurp
is deprecated, use for example Path::Tiny
instead.
Always use Test::Warnings to capture unexpected warnings in your tests:
use Test::Warnings;
use Test::Deep; my $status = $mws->GetServiceStatus; cmp_deeply $status, any(qw/GREEN GREEN_I YELLOW RED/), "Test response of GetServiceStatus API method";
Often tests are using an optional module or external resources. In that case we just skip these tests if we haven't all pieces in the right place.
For example, if an environment variable isn't set properly:
if ($ENV{SOLR_URL}) { $solr_url = $ENV{SOLR_URL}; } else { plan skip_all => "Please set environment variable SOLR_URL."; }
diag
Even if you think your tests won't fail, they might. In this case it is very helpful to provide additional information to trace down the source of the problem:
# check output my @matches = $out =~ /Blue ball/g; ok (@matches == 2, 'Test replacement in both lists') || diag "Matches: ", scalar(@matches), "Output: $out";
A good alternative is to use is
instead of ok
, which
automatically provides diagnostics:
# check output my @matches = $out =~ /Blue ball/g; is (scalar(@matches), 2, 'Test replacement in both lists');
Also other test functions like isa_ok
print further information.
Devel::Cover makes test coverage easy in your distribution:
cpanm Devel::Cover perl Makefile.PL make cover -test
You can find more information in the blog post from Neil Bower.
You can install Perl modules from Git repositories, e.g.
cpanm git@github.com:interchange/Amazon-MWS.git@topic/amazon-pay-2020-01-28
The part after the @ is a branch, tag or hashsum.
Here we show you which libraries you need to install for binary Perl modules (Debian and Ubuntu).
This works for MySQL and MariaDB:
$ apt install libmysqlclient-dev
$ apt install unixodbc-dev
$ apt install libpq-dev
$ apt install libmagic-dev
You need to install a number of development packages for the different image types before installing Imager, e.g. on Debian:
$ apt install libjpeg-dev libpng-dev libgif-dev libtiff-dev libfreetype6-dev
$ apt install libidn2-dev
$ apt install libssl-dev
$ apt install zlib1g-dev
$ apt install libexpat1-dev
$ apt install libxml2-dev
For more speed, install recommended modules as well:
cpanm --installdeps --with-recommends Dancer2
These are XS modules replacing pure Perl modules, e.g. HTTP::XSHeaders or Type::Tiny::XS.
If you want to make a patch for a CPAN module which doesn't provide a Git repository, Git::CPAN::Patch comes in very handy:
% git-cpan clone WebService::Xero creating WebService-Xero created tag 'v0.10' (7dbe0fdd5c54307ce6ea6d6943ddf529e1a7ab8c) created tag 'v0.11' (082ce463c0dec679710d0eecfbbaf47262526bff)
Create a branch for your patch:
% git checkout -b topic/enable-put-method
After done with patching, you can submit the changes as follows:
add your changes and commit
push patch to CPAN
For example:
% git add -u % git commit -m "Enable PUT method in Xero agent." [topic/enable-put-method 76c60c1] Enable PUT method in Xero agent. %
Please add resources for meta::cpan to your Makefile.PL, e.g.
META_MERGE => { resources => { repository => 'https://github.com/interchange/interchange6-schema.git', bugtracker => 'https://github.com/interchange/interchange6-schema/issues', IRC => 'irc://irc.freenode.net/#interchange', }, },
if you use noneof
if you use InstanceOf
Before you commit and push your .travis.yml
file,
make sure that file is valid:
travis lint .travis.yml
The lastest Perl version supported by Travis is 5.30
as of September 2020.
language: perl perl: - "5.10" - "5.12" - "5.14" - "5.16" - "5.18" - "5.20" - "5.22" - "5.24" - "5.28" - "dev" # installs latest developer release of perl - "blead" # builds perl from git matrix: include: - perl: 5.28 env: COVERAGE=1 # enables coverage+coveralls reporting allow_failures: - perl: blead # ignore failures for blead perl sudo: false # faster builds as long as you don't need sudo access before_install: - eval $(curl https://travis-perl.github.io/init) --auto
Please see Travis helpers for complete reference.
Add missing columns with default values to CSV file:
$ perl -i -pe 's/$/;0;/' data.csv
This one-liner removes carriage returns in a file:
$ perl -i -pe 's/\r//g' data.csv
Turn file with multiples lines into a comma separated list:
$ cat myfile.txt FOO BAR BAZ
$ perl -pe 's/\r?\n/,/g' myfile.txt FOO,BAR,BAZ