in reply to Re^3: installing module starter
in thread installing module starter

I was hoping to see a response from bliako, as I've been nibbling away at his recent meditation git-push target for Makefile (via ExtUtils::MakeMaker). This response gets long without even trying, so more between readmore tags:

...whether I want all the functionality to go into a script or shall I create some high-level functions or even a class and store into the module.

I started with functions. I see what you did with classes, but I'm just not there yet. The scoping just doesn't make sense yet when I still don't know where things will go in this filesystem.

I have some preliminary results. This is from STDOUT and is in pre-tags:

$ ./1.my_script.pl 
ini path is /home/bob/Documents/html_template_data/3.values.ini
sub_hash is google
$VAR1 = bless( {
...
                 'google' => {
                               'api_key_1' => 'redacted'
                             },
...
                                }
               }, 'Config::Tiny' );

Would you like to see the possibilities?
y
┌───────────────────────┬───────────────────────┬───────────────────────┐
│ Afrikaans      -   af │Bahasa Indonesia-   id │ Русский        -   ru │
│ አማርኛ           -   am │ Igbo           -   ig │ يڌنس           -   sd │
│ ةيبرعلا        -   ar │ Íslenska       -   is │ සිංහල           -   si │
│ Azərbaycanca   -   az │ Italiano       -   it │ Slovenčina     -   sk │
│ башҡорт теле   -   ba │ 日本語         -   ja │ Slovenščina    -   sl │
│ беларуская     -   be │ Basa Jawa      -   jv │ Gagana Sāmoa   -   sm │
│ български      -   bg │ ქართული        -   ka │ chiShona       -   sn │
│ বাংলা          -   bn │ Қазақ тілі     -   kk │ Soomaali       -   so │
│ Bosanski       -   bs │ ភាសាខ្មែរ       -   km │ Shqip          -   sq │
│ Català         -   ca │ ಕನ್ನಡ           -   kn │ српски         -sr-Cyrl
│ Cebuano        -  ceb │ 한국어         -   ko │ srpski         -sr-Latn
│ Corsu          -   co │ Kurdî          -   ku │ Sesotho        -   st │
│ Čeština        -   cs │ Кыргызча       -   ky │ Basa Sunda     -   su │
│ Cymraeg        -   cy │ Latina         -   la │ Svenska        -   sv │
│ Dansk          -   da │ Lëtzebuergesch -   lb │ Kiswahili      -   sw │
│ Deutsch        -   de │ ລາວ            -   lo │ தமிழ்           -   ta │
│ Ελληνικά       -   el │ Lietuvių       -   lt │ తెలుగు          -   te │
│ Emoji          -  emj │ Latviešu       -   lv │ Тоҷикӣ         -   tg │
│ English        -   en │ Malagasy       -   mg │ ไทย            -   th │
│ Esperanto      -   eo │ Олык марий     -  mhr │ Tagalog        -   tl │
│ Español        -   es │ Māori          -   mi │ tlhIngan Hol   -  tlh │
│ Eesti          -   et │ Македонски     -   mk │        tlh-Qaak
│ Euskara        -   eu │ മലയാളം         -   ml │ Lea faka-Tonga -   to │
│ یسراف          -   fa │ Монгол         -   mn │ Türkçe         -   tr │
│ Suomi          -   fi │ मराठी          -   mr │ татарча        -   tt │
│ Vosa Vakaviti  -   fj │ Кырык мары     -  mrj │ Reo Tahiti     -   ty │
│ Français       -   fr │ Bahasa Melayu  -   ms │ удмурт         -  udm │
│ Frysk          -   fy │ Malti          -   mt │ Українська     -   uk │
│ Gaeilge        -   ga │ Hmoob Daw      -  mww │ وُدرُا           -   ur │
│ Gàidhlig       -   gd │ မြန်မာစာ        -   my │ Oʻzbek tili    -   uz │
│ Galego         -   gl │ नेपाली          -   ne │ Tiếng Việt     -   vi │
│ ગુજરાતી         -   gu │ Nederlands     -   nl │ isiXhosa       -   xh │
│ Hausa          -   ha │ Norsk          -   no │ שידִיי          -   yi │
│ ʻŌlelo Hawaiʻi -  haw │ Nyanja         -   ny │ Yorùbá         -   yo │
│ תיִרְבִע          -   he │ Hñąñho         -  otq │ Màaya T'àan    -  yua │
│ हिन्दी          -   hi │ ਪੰਜਾਬੀ          -   pa │ 粵語           -  yue │
│ Hmoob          -  hmn │ Papiamentu     -  pap │ 简体中文       - zh-CN│
│ Hrvatski       -   hr │ Polski         -   pl │ 正體中文       - zh-TW│
│ Kreyòl Ayisyen -   ht │ وتښپ           -   ps │ isiZulu        -   zu │
│ Magyar         -   hu │ Português      -   pt │                       │
│ Հայերեն        -   hy │ Română         -   ro │                       │
└───────────────────────┴───────────────────────┴───────────────────────┘

Would you like to change the from language?
n
Would you like to see the possibilities?
n
Would you like to change the from language?
n
Я машу своими личными частями в твоих тетушек, ты, паршивая подержанная электрическая пила с ослиным дном.
then insert an EXE_FILES => 'bin/myscript.pl' into Makefile.PL

Is this the bin directory where 1.myscript.pl should end up?

$ pwd /home/bob/Documents/meditations/castaways/translate/blib $ ls arch bin lib man1 man3 script $

I did this:

my %WriteMakefileArgs = ( NAME => 'translate', AUTHOR => q{professor <prof@island.coconut>}, VERSION_FROM => 'lib/translate.pm', ABSTRACT_FROM => 'lib/translate.pm', LICENSE => 'artistic_2', MIN_PERL_VERSION => '5.006', CONFIGURE_REQUIRES => { 'ExtUtils::MakeMaker' => '0', }, TEST_REQUIRES => { 'Test::More' => '0', }, PREREQ_PM => { #'ABC' => '1.6', #'Foo::Bar::Module' => '5.0401', }, EXE_FILES => ['lib/1.my_script.pl'], dist => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', }, clean => { FILES => 'translate-*' }, );

I executed the make commands:

$ pwd /home/bob/Documents/meditations/castaways/translate/lib $ cd .. $ ls Changes ignore.txt lib Makefile.PL MANIFEST README t xt $ perl Makefile.PL Checking if your kit is complete... Looks good WARNING: Setting ABSTRACT via file 'lib/translate.pm' failed at /usr/local/share/perl/5.26.1/ExtUtils/MakeMaker.pm line 753. Generating a Unix-style Makefile Writing Makefile for translate Writing MYMETA.yml and MYMETA.json $ make cp lib/translate.pm.bak blib/lib/translate.pm.bak cp lib/translate.pm blib/lib/translate.pm cp lib/my_data/lang_data/1.langlist.txt blib/lib/my_data/lang_data/1.l +anglist.txt cp lib/1.my_script.pl blib/lib/1.my_script.pl cp lib/1.my_script.pl blib/script/1.my_script.pl "/usr/bin/perl" -MExtUtils::MY -e 'MY->fixin(shift)' -- blib/script/1. +my_script.pl Manifying 1 pod document $ make test PERL_DL_NONLAZY=1 "/usr/bin/perl" "-MExtUtils::Command::MM" "-MTest::H +arness" "-e" "undef *Test::Harness::Switches; test_harness(0, 'blib/l +ib', 'blib/arch')" t/*.t t/00-load.t ....... 1/? # Testing translate 0.01, Perl 5.026001, /usr/ +bin/perl t/00-load.t ....... ok t/manifest.t ...... skipped: Author tests not required for installatio +n t/pod-coverage.t .. skipped: Author tests not required for installatio +n t/pod.t ........... skipped: Author tests not required for installatio +n All tests successful. Files=4, Tests=1, 1 wallclock secs ( 0.05 usr 0.01 sys + 0.41 cusr + 0.08 csys = 0.55 CPU) Result: PASS $ make install Manifying 1 pod document Installing /home/bob/perl5/lib/perl5/translate.pm Installing /home/bob/perl5/lib/perl5/1.my_script.pl Installing /home/bob/perl5/lib/perl5/translate.pm.bak Installing /home/bob/perl5/lib/perl5/my_data/lang_data/1.langlist.txt Installing /home/bob/perl5/man/man3/translate.3pm Installing /home/bob/perl5/bin/1.my_script.pl Appending installation info to /home/bob/perl5/lib/perl5/x86_64-linux- +gnu-thread-multi/perllocal.pod $ ls blib ignore.txt Makefile MANIFEST MYMETA.yml README xt Changes lib Makefile.PL MYMETA.json pm_to_blib t $

This is what the package looks like now:

package translate; use 5.006; use strict; use warnings; require Exporter; our @ISA = qw(Exporter); our @EXPORT = qw( get_config get_trans get_from_lang get_to_lang reverse_trans); our $VERSION = '0.01'; =head1 SYNOPSIS use translate; my $config = get_config('path-to-ini-file', $sub_hash); my $from = get_from_lang(); my $to = get_to_lang(); my $trans_output_file = get_trans($input_file, $from, $to, $config); my $reverse = reverse_trans($trans_output_file, $to, $from, $config) +; =cut sub get_config { use Config::Tiny; use Data::Dumper; use open OUT => ':encoding(UTF-8)'; use Path::Tiny; use 5.011; my ( $ini_path, $sub_hash ) = @_; say "ini path is $ini_path"; say "sub_hash is $sub_hash"; my $Config = Config::Tiny->new; $Config = Config::Tiny->read( $ini_path, 'utf8' ); say Dumper $Config; my $key = $Config->{$sub_hash}{'api_key_1'}; return $key; } sub get_from_lang { use Path::Tiny; use 5.011; my $von = 'en'; # put your default here say "Would you like to see the possibilities?"; my $prompt1 = <STDIN>; chomp $prompt1; if ( $prompt1 eq ( "y" | "Y" ) ) { my $path_to_langs = path( "my_data", "lang_data", "1.langlist.txt" + ); my $data = $path_to_langs->slurp_utf8; say "$data"; } my $prompt2; say "Would you like to change the from language?"; $prompt1 = <STDIN>; chomp $prompt1; if ( $prompt1 eq ( "y" | "Y" ) ) { say "enter new lang: "; $prompt2 = <STDIN>; chomp $prompt2; $von = $prompt2; } return $von; } sub get_to_lang { use Path::Tiny; use 5.011; my $zu = 'ru'; # put your default here say "Would you like to see the possibilities?"; my $prompt1 = <STDIN>; chomp $prompt1; if ( $prompt1 eq ( "y" | "Y" ) ) { my $path_to_langs = path( "my_data", "lang_data", "1.langlist.txt" + ); my $data = $path_to_langs->slurp_utf8; say "$data"; } my $prompt2; say "Would you like to change the from language?"; $prompt1 = <STDIN>; chomp $prompt1; if ( $prompt1 eq ( "y" | "Y" ) ) { say "enter new lang: "; $prompt2 = <STDIN>; chomp $prompt2; $zu = $prompt2; } return $zu; } 1; # End of translate

and this is what 1.myscript.pl looks like:

#!/usr/bin/perl -w use 5.011; use WWW::Google::Translate; use Data::Dumper; use open OUT => ':utf8'; use Path::Tiny; use lib "."; use translate; binmode STDOUT, 'utf8'; my $ini_path = qw( /home/bob/Documents/html_template_data/3.values.ini + ); my $sub_hash = "google"; my $key = get_config($ini_path, $sub_hash); my $von = get_from_lang(); my $zu = get_to_lang(); my $wgt = WWW::Google::Translate->new( { key => $key, default_source => $von, default_target => $zu, } ); my $r = $wgt->translate( { q => 'I wave my private parts at your aunti +es, you cheesy lot of second hand electric donkey-bottom biters.' } ) +; my $result = ""; for my $trans_rh ( @{ $r->{data}->{translations} } ) { $result = $trans_rh->{translatedText}; print $trans_rh->{translatedText}, "\n"; }

My first question is whether I had to use

require Exporter; our @ISA = qw(Exporter); our @EXPORT = qw( get_config get_trans get_from_lang get_to_lang reverse_trans);

as I have done in previous modules. Page 183 of _Intermediate Perl_ seems to suggest that I could name them in an export section. Is that only for documentation?

My other general question is where files should go. What does the t directory do? How about xt?

When do you start with git?

Thanks for your comments,

Replies are listed 'Best First'.
Re^5: installing module starter
by bliako (Abbot) on Jun 09, 2019 at 11:14 UTC
    then insert an EXE_FILES => 'bin/myscript.pl' into Makefile.PL
    
    Is this the bin directory where 1.myscript.pl should end up?

    This is the path where each of the scripts you want installed system-wide (or user-dir-wide) LIVE NOW, in your module file structure. Their destination/installed dir is decided by the maker - you do not need to worry about that right now. Beware, I said EXE_FILES => ['bin/myscript.pl'], i.e. one or more scripts go into an array-ref (you need to enclose yours within square brackets). It's correct in your Makefile.PL but you cited it slightly wrong that's all.

    WARNING: Setting ABSTRACT via file 'lib/translate.pm' failed

    see What does this ABSTRACT warning from MakeMaker mean?

    My first question is whether I had to use require Exporter; our @ISA = qw(Exporter); our @EXPORT = qw( get_config get_trans get_from_lang get_to_lang reverse_trans);

    No you didn't have to but it is considered good practice not to "pollute the namespace of your module's users". Without exporting something, its access can be done via its full qualifier e.g. translate::get_from_lang();. You can not call that sub by using the shorter: get_from_lang(). Because it is not exported to the namespace of your module's users, unless you did so explicitly via the our @EXPORT mechanism. See also Selecting What to Export.

    Directory t/ contains all the test files run when you do make test. A few have already been created automatically by ExtUtils::MakeMaker and check for example if loading the module succeeds. In t/ you can add your own test files. For example there could be a test file which checks the functionality of get_config. I would call that test file t/01-get_config.t and could have something like this inside it:

    # t/01-get_config.t use strict; use warnings; use lib 'blib/lib'; use Test::More; use translate; my $num_tests = 0; my $ini_path = qw( /home/bob/Documents/html_template_data/3.values.ini + ); my $sub_hash = "google"; my $key = get_config($ini_path, $sub_hash); ok(defined $key, "get_config() : key defined"); $num_tests++; ok($key eq 'blahblah', "get_config() : key has correct value"); $num_t +ests++; # END done_testing($num_tests);

    After a user downloads your module, they should make test prior to installing it in order to make sure that the module works fine on their system (as opposed to working fine on author's system). So you must include as many test files as necessary to cover every aspect of your module's functionality. Perhaps as a minimum you should test the functionality of all your functions (exported/public or private). The more the better but not necessarily. Test files also help you to make sure that it works after you make a small change here or there: make a change, then run the tests. does it work? then your change *seems* not to have broken something. *seems*: always in relation to how well and comprehensive your test files are.

    Also, your module accesses a remote website. Testing this on a user's machine may not be a good idea, not without their permission perhaps. It will also fail without network access. I do not know what's considered a good practice in this situation.

    Directory xt/ should contain all the test files meant to be for author's use only. That is, the module user should not be concerned with running those. Only the author would find running them useful. You may have no author tests at all.

    There are many approaches and opinions about Testing. Perhaps you will find this useful I am most likely to install a new module from CPAN if:.

    Use git (github or your own server) to host your code for collaboration and as a version control system, i.e. to register incrementally your changes to your code so that you can rollback at any time.

    Disclaimer: please note that my knowledge of the above is at most average and seriously lacking commercial experience. It has been gained from doing my own projects, without peer-review from colleagues or supervisors as others here working for companies do every day. I am saying this not because of you doing something wrong on my advice (@&%^% that) but because there are battle-hardened veteran monks who are real experts and i think you should ask them too, or they should intervene if i am dispensing wrong or rubbish advice.

    bw, bliako