wolfi-dev / os

Main package repository for production Wolfi images
Other
794 stars 213 forks source link

testing python is too hard / cannot use 'python3' / python transition will cause problems #26818

Open smoser opened 3 weeks ago

smoser commented 3 weeks ago

Because we have multiple pythons and we want them to be co-installable, we have packages like:

  1. python-3.12-base
  2. python-3.12
  3. python-3.11-base
  4. python-3.11

The -base package provides basically everything and the python-3.11 package provides a symlink making 'python3' default to python 3.11 (/usr/bin/python3 -> python3.11)

When we build packages, melange correctly identifies that a package that installs python files into /usr/lib/python3.12/site-packages/ depends on python-3.12-base. It does not depend on python-3.12 (it never uses that symlink. even the installed scripts have /usr/bin/python3.12).

The pipeline 'python/imports' pipeline takes a 'python' input, but if it is not provided it will use a shell snippet to find the right one (if there is only one installed).

That works well for the imports pipeline.

The problem is that anything that wants to run 'python3' in a test has to have a similar snippet of code.

Consider py3-async-generator.yaml.

It looks like this:

package:
  name: py3-async-generator
  version: 1.10
  epoch: 1
  description: Async generators and context managers for Python 3.5+
  copyright:
    - license: MIT OR Apache-2.0
  dependencies:
    runtime:
      - python-3
...
test:
  environment:
    contents:
      packages:
        - python-3
  pipeline:
    - runs: |
        python -c "import async_generator; print(async_generator.__version__)"

Two things to call out there

  1. It has 'python-3' as a runtime dep. The package built today will have the python-3.12 dep written by melange but will also have python-3 dep. In the future, when python-3.13 exists, python-3.13 will also provide python-3 and will be preferred to python-3.12. So installation of this package would install 2 python versions. Yikes.
  2. It includes python-3 in the test environment in order to get a python program to execute. But similarly to 1, that will install the wrong python in the future, and the test will begin to fail (it works today, but as soon as there is a python-3 package it will fail).

So, how should that test look? Do we have to copy a shell snippet like this:

python=$(m=/usr/bin/python3.*; set +x; set -- $m
    [ $# -eq 1 -a -x "$1" ] && echo "$1" && exit 0
    echo "found $# matches to $m"; exit 1;)
$python -c '...'
smoser commented 3 weeks ago

Here is one thought, in py3-pendelum.yaml. Similar to the multi-version building, we use a var and manually have to change that. Things to note:

package:
  name: py3-pendulum
  version: 3.0.0
  epoch: 1
  description: Python datetimes made easy
  copyright:
    - license: MIT
  dependencies:
    runtime:
      - py${{vars.pyver}}-dateutil
      - py${{vars.pyver}}-tzdata
      - py3-typing
    provides:
      - py${{vars.pyver}}-pendulum

vars:
  pyver: "3.12"

environment:
  contents:
    packages:
      - build-base
      - busybox
      - ca-certificates-bundle
      - py${{vars.pyver}}-maturin-bin
      - py${{vars.pyver}}-pip
      - py${{vars.pyver}}-wheel
      - python-${{vars.pyver}}
      - python-${{vars.pyver}}-dev
      - rust
      - wolfi-base

pipeline:
  - uses: git-checkout
    with:
      repository: https://github.com/sdispater/pendulum
      tag: ${{package.version}}
      expected-commit: 0fcd10217af0469b3edda072f2b152d5273f3d58

  - uses: py/pip-build-install

test:
  pipeline:
    - uses: python/import
      with:
        imports: |
          import pendulum
    - runs: |
        # test verifies that timezone data is present.
        python${{vars.pyver}} -c '
        from pendulum import datetime
        tor = datetime(2012, 1, 1, tz="America/Toronto")
        van = datetime(2012, 1, 1, tz="America/Vancouver")
        assert 3 == van.diff(tor).in_hours()
        print("PASS: time zones check out")
        '