Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add perl test section? #790

Open
wolfv opened this issue Apr 11, 2024 · 5 comments
Open

Add perl test section? #790

wolfv opened this issue Apr 11, 2024 · 5 comments

Comments

@wolfv
Copy link
Member

wolfv commented Apr 11, 2024

Apparently conda-build has some magic that makes the test.import section also work for perl.

For example here:

{% set name = "perl-data-dumper" %}
{% set version = "2.183" %}
{% set sha256 = "e42736890b7dae1b37818d9c5efa1f1fdc52dec04f446a33a4819bf1d4ab5ad3" %}

package:
  name: {{ name }}
  version: {{ version }}

source:
  url: https://cpan.metacpan.org/authors/id/N/NW/NWCLARK/Data-Dumper-{{ version }}.tar.gz
  sha256: {{ sha256 }}

build:
  number: 0
  # nothing provides perl >=5.32.1,<6.0a0 *_perl5 needed by perl-extutils-makemaker-7.36-pl5321hd8ed1ab_0
  skip: true  # [win]
  script:
    - perl Makefile.PL INSTALLDIRS=vendor NO_PERLLOCAL=1 NO_PACKLIST=1
    - make
    - make test
    - make install VERBINST=1

requirements:
  build:
    - {{ compiler('c') }}        # [not win]
    - {{ compiler('m2w64_c') }}  # [win]
    - make
  host:
    - perl
    - perl-extutils-makemaker
  run:
    - perl

test:
  imports:
    - Data::Dumper

about:
  home: https://metacpan.org/pod/Data::Dumper
  license: GPL-1.0-or-later OR Artistic-1.0-Perl
  license_family: OTHER
  summary: 'seeds germane, yet not germinated'
  license_file:
    - {{ environ["PREFIX"] }}/man/man1/perlartistic.1
    - {{ environ["PREFIX"] }}/man/man1/perlgpl.1
@danielnachun
Copy link

That magic lives here: https://github.com/conda/conda-build/blob/3cf75b660e73babd4772d2cf65ac0026406ca558/conda_build/create_test.py, and it actually supports R and Lua as well.

I've been mass migrating all my personal recipes and feedstocks I manage in conda-forge over to rattler-build (it's worth it when it's 60x faster for some builds) and the lack of this feature is a huge blocker for migrating Perl recipes.

A couple of thoughts on this:

  • This should support Perl, R, Lua, Ruby, and should probably also work for NodeJS (though shipping libraries for that ecosystem through Conda is not as useful).
  • Eventually it might be worth linting in conda-forge and bioconda (when they support rattler-build) for using this kind of mechanism instead of the user trying to hand code basic import tests which is prone to error
  • I don't really like the auto-generated tests for Perl from conda-build because they use a brittle mechanism to check if the version of the Perl module matches what is declared in the recipe. Annoyingly a surprising number of Perl modules return a different value for Module->VERSION than what is on CPAN, which leads to test failures for something that isn't really important.

What is needed for this to be implemented? I'm not a rust expert but happy to help as I can!

@wolfv
Copy link
Member Author

wolfv commented Nov 30, 2024

Hi @danielnachun thanks for stopping by! Yes, I sorta looked through all that magic as well back in the days, but for my taste it's too much magic :)

I would propose two things:

Like python as interpreter, we can make perl (and others) as a script interpreter work, so that the following would work:

script:
  interpreter: perl
  contents: |
    use strict;
    use warnings;
    use Config;

    print "Hello World!\n";
    print "Perl prefix: $Config{prefix}\n";

That would also give an "easy" way to roll your own import tests.

When that works, we could use this to create a perl test section.

@wolfv
Copy link
Member Author

wolfv commented Nov 30, 2024

@danielnachun I started the implementation for using perl as a script interpreter in #1229

To add a perl-specific test section we should come up with a list of entries we would like, for example:

tests:
  - perl:
      imports: [ ... ]? # is imports the right word for perl?
      check_version: true/false?

And that would be just a convenience wrapper around the script with interpreter perl, essentially. Maybe you have thoughts on what an ideal perl test section would look like.

@danielnachun
Copy link

Hi @danielnachun thanks for stopping by! Yes, I sorta looked through all that magic as well back in the days, but for my taste it's too much magic :)

Indeed upon examining that code in conda-build, it seems that since the old recipe format didn't have a way to explicitly specify the language being used for the import, conda-build tried to guess the language based on the recipe name. I can imagine quite a few ways in which that could break very easily, so the new approach of explicitly specifying the language should be much more robust.

I would propose two things:

Like python as interpreter, we can make perl (and others) as a script interpreter work, so that the following would work:

script:
interpreter: perl
contents: |
use strict;
use warnings;
use Config;

print "Hello World!\n";
print "Perl prefix: $Config{prefix}\n";

That would also give an "easy" way to roll your own import tests.

When that works, we could use this to create a perl test section.

This is a great idea, and I'll write up below potential specifications for how this can be done with R, Ruby, Lua and NodeJS.

@danielnachun I started the implementation for using perl as a script interpreter in #1229

To add a perl-specific test section we should come up with a list of entries we would like, for example:

tests:

  • perl:
    imports: [ ... ]? # is imports the right word for perl?
    check_version: true/false?
    And that would be just a convenience wrapper around the script with interpreter perl, essentially. Maybe you have thoughts on what an ideal perl test section would look like.

This is exactly what I had in mind. I'll write out specifications below for what I think make sense for the different languages.

@danielnachun
Copy link

These are my current thoughts on how we could call various scripting languages as interpreters and what language-specific test sections could look like. One overall decision that probably needs to be made is whether we would want to consolidate all the "import" tests to a single script, or to use single command invocations for each test. I don't feel strongly about this either way - maybe we should just go by what is easiest to implement and maintain.

Perl

Perl scripts can be invoked simply by call perl script.pl, while single commands can be issued with perl -e. The equivalent to import for Perl is use, so test syntax could look like this:

perl:
  uses:
    - Module::Submodule

I'm not sure yet if the version check is actually worth adding. The situation is even more complex than I first mentioned above because in modules specified by multiple files, the author may not keep the versions across these files in sync. This has resulted in partial test failures where some module/submodules did have the right version and others did not. It may be possible to have a syntax that allows the user to explicitly enable/disable the version check, but given that version checking isn't even done for other languages, I'm not sure it's important to do here.

R

R scripts can be invoked with Rscript, while single commands can be issued with R -e (note that these are different executables!). The equivalent to import for R is library(library_name) (no quotes needed), so test syntax could look like this:

R:
  libraries:
    - library_name

Ruby

Ruby scripts can be invoked with ruby, while single commands can be issued with ruby -e. Unlike in most other languages, Ruby can also use ruby -r to directly test import of a gem, though a -e command must still be issue (usually exit 0). It's probably simpler though to use a script or -e calls to be more consistent with other languages. The equivalent to import for Ruby is require 'gem_name' (note the quotes), so test syntax could look like this:

ruby:
  requires:
    - gem_name

Lua

Lua scripts can be invoked with lua, while single commands can be issued with lua -e. The equivalent to import for Lua is also require 'library_name' (note the quotes), so test syntax could look like this:

lua:
  requires:
    - library_name

NodeJS

NodeJS scripts can be invoked with node, while single commands can be issue with node -e. The equivalent to import for NodeJS is also require, but it is invoked in the form const library_name = require("library_name"), so test syntax syntax could look like this:

node:
  requires:
    - library_name

I'll note here that as I mentioned above, there isn't a lot of value in bundling standalone NodeJS libraries, as the standard NodeJS practice is to bundle all the libraries together. Most NodeJS recipes are CLI executables that can just be tested with a shell command, but the one scenario where it can be useful to package libraries is when they include native code to avoid vendoring pre-compiled native code in other packages that depend on that library. I'm happy to explain this in more detail if needed.

Sorry for the huge info dump here, but I figured that all of these could probably end up being implemented more or less the same way aside from the minor syntactic differences

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants