Compare commits
72 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a83a4480c0 | ||
|
|
3bc0535c27 | ||
|
|
533e84657e | ||
|
|
b4af9ca880 | ||
|
|
dfd41a9acf | ||
|
|
018063867c | ||
|
|
5a345b59d6 | ||
|
|
223296d711 | ||
|
|
085416c781 | ||
|
|
5c46fa4679 | ||
|
|
5ffff08833 | ||
|
|
1ad7f0cc25 | ||
|
|
a0a96e2721 | ||
|
|
800608da2e | ||
|
|
b8d9e52c94 | ||
|
|
6f4fdf29c4 | ||
|
|
548de9fc09 | ||
|
|
3ff6bdd8ba | ||
|
|
b9eebf1c79 | ||
|
|
dc4e662e56 | ||
|
|
6be8056917 | ||
|
|
9a18358399 | ||
|
|
6f4c0d0815 | ||
|
|
f022884999 | ||
|
|
b9dc63ad15 | ||
|
|
51c24d51d1 | ||
|
|
4c3ed6ec49 | ||
|
|
df6c0cef6e | ||
|
|
18de9ca2b3 | ||
|
|
fd113d4cf8 | ||
|
|
db335e1e44 | ||
|
|
19a49e8637 | ||
|
|
362f438cc6 | ||
|
|
bc948d6e50 | ||
|
|
c2466c2de5 | ||
|
|
beb705f0d0 | ||
|
|
1adc399e3d | ||
|
|
2fc6fc00bc | ||
|
|
853a1f50a3 | ||
|
|
98ad8d0232 | ||
|
|
1b6575d5a5 | ||
|
|
59f2079f68 | ||
|
|
6cc91d52a7 | ||
|
|
86842acd1b | ||
|
|
b4fd40e6ca | ||
|
|
261dfe65e1 | ||
|
|
c26b64823b | ||
|
|
0ec11f1f64 | ||
|
|
450364614f | ||
|
|
6a9ffe6cb2 | ||
|
|
562c77a483 | ||
|
|
38d9a441ce | ||
|
|
74239cac5d | ||
|
|
606e77a1ba | ||
|
|
754dc5a573 | ||
|
|
96fbcc5c42 | ||
|
|
11b7e874ef | ||
|
|
30e8067df5 | ||
|
|
d37bcbfd9a | ||
|
|
d72c62fe79 | ||
|
|
f5948a878c | ||
|
|
8f563a8e11 | ||
|
|
bd3ec9505c | ||
|
|
0ae2425874 | ||
|
|
bb40c2a2a8 | ||
|
|
ca464dcb60 | ||
|
|
8dbc369a49 | ||
|
|
ead01d15f0 | ||
|
|
97db1f97bb | ||
|
|
81d0de13aa | ||
|
|
11bfd62cc1 | ||
|
|
8ddab88d43 |
14 changed files with 549 additions and 33 deletions
48
flags/assertflags.py
Normal file
48
flags/assertflags.py
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
"""
|
||||
This script asserts that Python config vars with compiler options including
|
||||
one or more -O flags have the last specified -O flag equal to the script's
|
||||
first argument.
|
||||
|
||||
We use it to check that the debug build (as well as extension modules) was
|
||||
built with a desired optimization level (usually -Og or -O0).
|
||||
|
||||
About -O flags: https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
|
||||
"If you use multiple -O options, with or without level numbers,
|
||||
the last such option is the one that is effective."
|
||||
"""
|
||||
|
||||
import sys
|
||||
import sysconfig
|
||||
|
||||
# We will check all flags if none were requested
|
||||
KEYS_TO_CHECK = sys.argv[2:] or list(sysconfig.get_config_vars().keys())
|
||||
# For backwards compatibility, if no flags were provided, we assume flags without -O are to be skipped
|
||||
# But when we provide explicit list of flags, we assert they get the options,
|
||||
# so we can assert things like "CFLAGS has -O3" vs. "CFLAGS has no -O at all"
|
||||
NO_FLAG_FAILS = bool(sys.argv[2:])
|
||||
|
||||
# The flags that currently don't have the -Og flag on the debug build
|
||||
# and we consider it OK, because we don't know any better :)
|
||||
SKIP = [
|
||||
'CONFIGURE_CFLAGS',
|
||||
'CONFIGURE_CFLAGS_NODIST',
|
||||
'CONFIG_ARGS',
|
||||
'OPT',
|
||||
]
|
||||
|
||||
print('Expecting that {} is the last -O flag:\n'.format(sys.argv[1]))
|
||||
ret = 0
|
||||
|
||||
for key in KEYS_TO_CHECK:
|
||||
if key in SKIP:
|
||||
continue
|
||||
flags = sysconfig.get_config_vars()[key]
|
||||
if isinstance(flags, str):
|
||||
oflags = [f for f in flags.split(' ') if f.startswith('-O')]
|
||||
if (oflags and oflags[-1] != sys.argv[1]) or (not oflags and NO_FLAG_FAILS):
|
||||
print('Problem in {} -O flags: {}'.format(key, ' '.join(oflags) or '<empty>'))
|
||||
ret = 1
|
||||
elif oflags:
|
||||
print('{} are OK'.format(key))
|
||||
|
||||
sys.exit(ret)
|
||||
2
main.fmf
2
main.fmf
|
|
@ -1,4 +1,4 @@
|
|||
contact:
|
||||
- Petr Šplíchal <psplicha@redhat.com>
|
||||
- Miro Hrončok <miro@hroncok.cz>
|
||||
- Miro Hrončok <mhroncok@redhat.com>
|
||||
component: [python]
|
||||
|
|
|
|||
32
marshalparser/test_marshalparser_compatibility.sh
Executable file
32
marshalparser/test_marshalparser_compatibility.sh
Executable file
|
|
@ -0,0 +1,32 @@
|
|||
#!/bin/sh -eux
|
||||
|
||||
# Marshalparser helps us to uniform byte-compiled Python files
|
||||
# so it has to be able to also parse pyc files from
|
||||
# the main python packages.
|
||||
# Moreover, it has its own database of magic numbers so this test
|
||||
# checks that the parser is compatible with the latest python before
|
||||
# we ship it.
|
||||
|
||||
# Test the latest version by default because that's the place
|
||||
# where magic number incompatibility might happen with
|
||||
# the largest probability
|
||||
VERSION=${VERSION:-3.9}
|
||||
|
||||
# How many randomly-selected pyc files to check?
|
||||
SAMPLE=${SAMPLE:-50}
|
||||
|
||||
# This allows us to test marshalparser optionally: on Fedora 33+ only
|
||||
INSTALL_OR_SKIP=${INSTALL_OR_SKIP:-false}
|
||||
if [ "$INSTALL_OR_SKIP" == "true" ] && [ ! -f "/usr/bin/marshalparser" ]; then
|
||||
dnf -y install marshalparser || :
|
||||
if [ ! -f "/usr/bin/marshalparser" ]; then
|
||||
echo "marshalparser not installable, skipping this test"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
path="/usr/lib*/python$VERSION/"
|
||||
|
||||
for file in `find $path -name "*.pyc" | shuf | head -n $SAMPLE`; do
|
||||
marshalparser $file || exit 1
|
||||
done
|
||||
92
required-symbols/check.sh
Executable file
92
required-symbols/check.sh
Executable file
|
|
@ -0,0 +1,92 @@
|
|||
#!/bin/bash
|
||||
# Compare required external symbols of compiled Python extension modules between
|
||||
# the PR build (pre-installed by Testing Farm) and the latest stable version
|
||||
# available in the distribution repositories.
|
||||
#
|
||||
# The PR build is already installed before this test runs (via the Testing Farm
|
||||
# artifact mechanism). We save its .so files, downgrade to the stable repo version,
|
||||
# collect symbols from both, and compare.
|
||||
#
|
||||
# Output:
|
||||
# + [module] symbol — PR build adds a new required symbol (potential issue possibly requiring update of Requires)
|
||||
# - [module] symbol — PR build drops a previously required symbol (generally OK)
|
||||
#
|
||||
# Exit codes:
|
||||
# 0 — no changes, or no stable version available to compare against (skipped)
|
||||
# 1 — symbol differences detected between PR build and stable release
|
||||
set -eo pipefail
|
||||
|
||||
PYVER=${VERSION}
|
||||
SCRIPT_DIR="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"
|
||||
|
||||
WORK_DIR=""
|
||||
PKGS_MODIFIED=false
|
||||
|
||||
cleanup() {
|
||||
if [[ "$PKGS_MODIFIED" == true ]]; then
|
||||
echo ""
|
||||
echo "=== Reverting package changes ==="
|
||||
dnf history undo last -y 2>&1 || echo "WARNING: dnf history undo failed" >&2
|
||||
fi
|
||||
[[ -n "$WORK_DIR" ]] && rm -rf "$WORK_DIR"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
# Directories containing compiled extension modules
|
||||
SCAN_DIRS=()
|
||||
for d in "/usr/lib64/python${PYVER}" "/usr/lib64/python${PYVER}t"; do
|
||||
[ -d "$d" ] && SCAN_DIRS+=("$d")
|
||||
done
|
||||
|
||||
if [ ${#SCAN_DIRS[@]} -eq 0 ]; then
|
||||
echo "ERROR: No Python extension directories found for python${PYVER}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SCAN_ARGS=("${SCAN_DIRS[@]}")
|
||||
for f in /usr/lib64/libpython${PYVER}*.so.*; do
|
||||
[[ -f "$f" && ! -L "$f" ]] && SCAN_ARGS+=("$f")
|
||||
done
|
||||
|
||||
WORK_DIR=$(mktemp -d)
|
||||
|
||||
echo "=== Collecting PR build symbols ==="
|
||||
python${PYVER} "$SCRIPT_DIR/collect_symbols.py" "${SCAN_ARGS[@]}" > "$WORK_DIR/new.json"
|
||||
|
||||
echo ""
|
||||
echo "=== Available repos ==="
|
||||
dnf repolist --all
|
||||
|
||||
# Discover packages dynamically from the installed source RPM so we don't need
|
||||
# to hardcode subpackage names — works regardless of which subpackages were built.
|
||||
readarray -t PKGS < <(
|
||||
rpm -qa --qf '%{SOURCERPM} %{NAME}\n' |
|
||||
awk -v src="python${PYVER}" '$1 ~ "^" src "-[0-9]" { print $2 }' |
|
||||
sort -u
|
||||
)
|
||||
echo "Packages to install from stable repos: ${PKGS[*]}"
|
||||
|
||||
# Install the stable version from distribution repos, excluding the artifact repo
|
||||
# that carries the PR build, so we always compare against what is publicly available.
|
||||
#
|
||||
# Strategy:
|
||||
# 1. dnf reinstall — works when the PR did not bump NVR (same version in stable repos)
|
||||
# 2. dnf distro-sync — fallback when the PR bumped NVR; installs the latest stable NVR
|
||||
echo ""
|
||||
echo "=== Installing stable version from repos ==="
|
||||
if ! dnf reinstall -y --disablerepo=test-artifacts "${PKGS[@]}" 2>&1; then
|
||||
echo "INFO: reinstall failed (NVR not in stable repos), falling back to distro-sync" >&2
|
||||
if ! dnf distro-sync -y --disablerepo=test-artifacts "${PKGS[@]}" 2>&1; then
|
||||
echo "INFO: distro-sync failed; no stable version available, skipping comparison." >&2
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
PKGS_MODIFIED=true
|
||||
|
||||
echo ""
|
||||
echo "=== Collecting stable version symbols ==="
|
||||
python${PYVER} "$SCRIPT_DIR/collect_symbols.py" "${SCAN_ARGS[@]}" > "$WORK_DIR/old.json"
|
||||
|
||||
echo ""
|
||||
echo "=== Comparing PR build against stable ==="
|
||||
python${PYVER} "$SCRIPT_DIR/compare_symbols.py" "$WORK_DIR/old.json" "$WORK_DIR/new.json"
|
||||
67
required-symbols/collect_symbols.py
Executable file
67
required-symbols/collect_symbols.py
Executable file
|
|
@ -0,0 +1,67 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Collect undefined non-boring external symbols from compiled Python extension modules
|
||||
and libpython shared libraries.
|
||||
|
||||
Usage: collect_symbols.py <path> [<path>...]
|
||||
|
||||
Each path may be a directory (scanned recursively for *.cpython-*.so) or a file
|
||||
(scanned directly; intended for libpython*.so.* passed explicitly from the caller).
|
||||
Symbols are unioned across all variants of each module (regular/debug/freethreading),
|
||||
and the result is printed as JSON to stdout.
|
||||
"""
|
||||
|
||||
import json
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
BORING = re.compile(
|
||||
r"@GLIBC_" # glibc versioned symbols (stable by definition)
|
||||
r"|@GCC_" # GCC built-ins
|
||||
r"|^_?Py[A-Za-z_]" # Python C API (resolved from libpython at runtime)
|
||||
r"|^__" # C runtime internals
|
||||
r"|^_ITM_" # Intel transactional memory
|
||||
)
|
||||
|
||||
|
||||
def module_name(so: Path) -> str:
|
||||
# _ssl.cpython-314td-x86_64-linux-gnu.so → _ssl
|
||||
if m := re.match(r"(.+?)\.cpython-", so.name):
|
||||
return m.group(1)
|
||||
# libpython3.14.so.1.0 → libpython3.14
|
||||
return re.sub(r"\.so.*$", "", so.name)
|
||||
|
||||
|
||||
def external_symbols(so: Path) -> list[str]:
|
||||
result = subprocess.run(["nm", "-D", str(so)], capture_output=True, text=True)
|
||||
return sorted(
|
||||
parts[-1]
|
||||
for line in result.stdout.splitlines()
|
||||
if len(parts := line.split()) >= 2
|
||||
and parts[-2] == "U"
|
||||
and not BORING.search(parts[-1])
|
||||
)
|
||||
|
||||
|
||||
modules: dict[str, set[str]] = {}
|
||||
for path_arg in sys.argv[1:]:
|
||||
p = Path(path_arg)
|
||||
if p.is_file():
|
||||
print(f"Scanning: {p.name}", file=sys.stderr)
|
||||
if syms := external_symbols(p):
|
||||
modules.setdefault(module_name(p), set()).update(syms)
|
||||
else:
|
||||
print(f"Scanning: {path_arg}", file=sys.stderr)
|
||||
for so in sorted(p.rglob("*.cpython-*.so")):
|
||||
if so.is_symlink():
|
||||
continue
|
||||
if syms := external_symbols(so):
|
||||
modules.setdefault(module_name(so), set()).update(syms)
|
||||
|
||||
total_symbols = sum(len(v) for v in modules.values())
|
||||
print(f"Found {len(modules)} modules, {total_symbols} tracked symbols", file=sys.stderr)
|
||||
|
||||
json.dump({k: sorted(v) for k, v in sorted(modules.items())}, sys.stdout, indent=2)
|
||||
print()
|
||||
41
required-symbols/compare_symbols.py
Executable file
41
required-symbols/compare_symbols.py
Executable file
|
|
@ -0,0 +1,41 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Compare two symbol JSON files produced by collect_symbols.py.
|
||||
|
||||
Usage: compare_symbols.py <old.json> <new.json>
|
||||
|
||||
Output:
|
||||
+ [module] symbol — new build adds a required symbol the old build did not have
|
||||
- [module] symbol — new build drops a required symbol the old build had
|
||||
|
||||
Exit codes:
|
||||
0 — no differences
|
||||
1 — differences found
|
||||
"""
|
||||
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
old = json.loads(Path(sys.argv[1]).read_text())
|
||||
new = json.loads(Path(sys.argv[2]).read_text())
|
||||
|
||||
all_mods = sorted(set(old) | set(new))
|
||||
changes = []
|
||||
for mod in all_mods:
|
||||
added = sorted(set(new.get(mod, [])) - set(old.get(mod, [])))
|
||||
removed = sorted(set(old.get(mod, [])) - set(new.get(mod, [])))
|
||||
if added or removed:
|
||||
changes.append((mod, added, removed))
|
||||
|
||||
if not changes:
|
||||
print("OK: no symbol changes between stable and PR build")
|
||||
sys.exit(0)
|
||||
|
||||
print("Symbol changes detected (+ new requirement in PR build, - dropped by PR build):")
|
||||
for mod, added, removed in changes:
|
||||
for sym in added:
|
||||
print(f" + [{mod}] {sym}")
|
||||
for sym in removed:
|
||||
print(f" - [{mod}] {sym}")
|
||||
sys.exit(1)
|
||||
1
selftest/findleaks.fmf
Normal file
1
selftest/findleaks.fmf
Normal file
|
|
@ -0,0 +1 @@
|
|||
test: ./findleaks.sh
|
||||
21
selftest/findleaks.sh
Executable file
21
selftest/findleaks.sh
Executable file
|
|
@ -0,0 +1,21 @@
|
|||
#!/bin/sh -eux
|
||||
|
||||
# set python version
|
||||
VERSION=${VERSION:-3.7}
|
||||
PYTHON=${PYTHON:-python${VERSION}dm}
|
||||
|
||||
# what to skip
|
||||
# test_socket swaps and kills the machine https://bugs.python.org/issue34587
|
||||
X=${X:-"-x test_socket"}
|
||||
|
||||
# Fedora sets explicit minimum/maximum TLS versions.
|
||||
# Python's test suite assumes that the minimum/maximum version is set to
|
||||
# a magic marker. We workaround the test problem by setting:
|
||||
export OPENSSL_CONF=/non-existing-file
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=1618753
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=1778357
|
||||
# https://bugs.python.org/issue35045
|
||||
# https://bugs.python.org/issue38815
|
||||
|
||||
$PYTHON -m test.pythoninfo
|
||||
$PYTHON -m test -wW --findleaks $X
|
||||
4
selftest/main.fmf
Normal file
4
selftest/main.fmf
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
require:
|
||||
- python3-test
|
||||
- python3-rpm-macros
|
||||
- python3-tkinter
|
||||
4
selftest/parallel.fmf
Normal file
4
selftest/parallel.fmf
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
test: ./parallel.sh
|
||||
duration: 30m
|
||||
recommend:
|
||||
- /usr/bin/dtrace
|
||||
41
selftest/parallel.sh
Executable file
41
selftest/parallel.sh
Executable file
|
|
@ -0,0 +1,41 @@
|
|||
#!/bin/sh -eux
|
||||
|
||||
# set default version to %{python3_version} if available
|
||||
VERSION=${VERSION:-$(rpm --eval '%{?python3_version}')} || true
|
||||
# ...or 3.8 if that macro is not available or rpm fails for any reason
|
||||
VERSION=${VERSION:-3.8}
|
||||
|
||||
PYTHON=${PYTHON:-python$VERSION}
|
||||
|
||||
# what to skip
|
||||
# test_socket swaps and kills the machine https://bugs.python.org/issue34587
|
||||
X=${X:-"-x test_socket"}
|
||||
|
||||
TIMEOUT=${TIMEOUT:-1800}
|
||||
|
||||
# parallel jobs, 0 lets Python decide what's best
|
||||
JOBS=${JOBS:-0}
|
||||
|
||||
# Fedora sets explicit minimum/maximum TLS versions.
|
||||
# Python's test suite assumes that the minimum/maximum version is set to
|
||||
# a magic marker. We workaround the test problem by setting:
|
||||
export OPENSSL_CONF=/non-existing-file
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=1618753
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=1778357
|
||||
# https://bugs.python.org/issue35045
|
||||
# https://bugs.python.org/issue38815
|
||||
|
||||
# setuptools 60+ uses its own copy of distutils by default
|
||||
# this setting must be overriden with the environment variable for
|
||||
# Python tests to use the standard library's distutils
|
||||
# We only do this if stdlib distutils actually exists
|
||||
$PYTHON -c 'import distutils' 2>/dev/null && export SETUPTOOLS_USE_DISTUTILS=stdlib || true
|
||||
|
||||
$PYTHON -m test.pythoninfo
|
||||
$PYTHON -m test -wW -j$JOBS --timeout=$TIMEOUT $X && e=0 || e=$?
|
||||
# https://tmt.readthedocs.io/en/stable/spec/tests.html#framework says only exit code 1 is failure, rest is error
|
||||
# https://github.com/python/cpython/blob/v3.14.0/Lib/test/libregrtest/results.py#L18 says a bad test exits with 2
|
||||
if [ $e -eq 2 ]; then
|
||||
exit 1
|
||||
fi
|
||||
exit $e
|
||||
|
|
@ -21,16 +21,21 @@ description: |
|
|||
* METHOD ... virtual environment creation method (venv, virtualenv)
|
||||
* TOX ... enable or disable the tox test (true, false)
|
||||
|
||||
path: smoke
|
||||
path: /smoke
|
||||
test: ./venv.sh
|
||||
|
||||
tier: 1
|
||||
tags: [venv]
|
||||
tag: [venv]
|
||||
|
||||
require+:
|
||||
- gcc
|
||||
- gcc-c++
|
||||
|
||||
environment:
|
||||
VERSION: 3.7
|
||||
METHOD: venv
|
||||
TOX: true
|
||||
TOX_REQUIRES: ""
|
||||
duration: 10m
|
||||
component+:
|
||||
- python2
|
||||
|
|
|
|||
114
smoke/venv.sh
114
smoke/venv.sh
|
|
@ -1,24 +1,56 @@
|
|||
#!/bin/sh -eux
|
||||
|
||||
# set python version
|
||||
VERSION=${VERSION:-3.7}
|
||||
# set default version to %{python3_version} if available
|
||||
VERSION=${VERSION:-$(rpm --eval '%{?python3_version}')} || true
|
||||
# ...or 3.8 if that macro is not available or rpm fails for any reason
|
||||
VERSION=${VERSION:-3.8}
|
||||
|
||||
PYTHON=${PYTHON:-python$VERSION}
|
||||
METHOD=${METHOD:-venv}
|
||||
TOX=${TOX:-true}
|
||||
TOX_REQUIRES=${TOX_REQUIRES:-}
|
||||
CYTHON=${CYTHON:-true}
|
||||
INSTALL_OR_SKIP=${INSTALL_OR_SKIP:-false}
|
||||
|
||||
# clean from possible older runs
|
||||
rm -rf venv .tox __pycache__ .pytest* test_*.py *.pyx *.c *.so || :
|
||||
# Work from a custom directory
|
||||
workdir="$(mktemp --directory)"
|
||||
cd "$workdir"
|
||||
|
||||
if [ "$INSTALL_OR_SKIP" == "true" ]; then
|
||||
[ ! -f "/usr/bin/$PYTHON" ] && dnf -y install "/usr/bin/$PYTHON" || :
|
||||
[ ! -f "/usr/bin/${PYTHON}-config" ] && dnf -y install "/usr/bin/${PYTHON}-config" || :
|
||||
dnf -y install "$PYTHON-devel" || :
|
||||
if [ ! -f "/usr/bin/$PYTHON" ]; then
|
||||
echo "/usr/bin/$PYTHON not installable, skipping this test"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# check the we can create the venv
|
||||
if [ "$METHOD" == "venv" ]; then
|
||||
$PYTHON -m venv venv
|
||||
elif [ "$METHOD" == "virtualenv" ]; then
|
||||
virtualenv --python=$PYTHON venv
|
||||
elif [ "$METHOD" == "virtualenv-download" ]; then
|
||||
virtualenv --download --python=$PYTHON venv
|
||||
elif [ "$METHOD" == "virtualenv-no-download" ]; then
|
||||
virtualenv --no-download --python=$PYTHON venv
|
||||
elif [ "$METHOD" == "virtualenv-seeder-pip" ]; then
|
||||
virtualenv --seeder pip --python=$PYTHON venv
|
||||
elif [ "$METHOD" == "none" ]; then
|
||||
echo 'Skipping plain virtual environment tests' >&2
|
||||
else
|
||||
echo 'Unsupported $METHOD' $METHOD >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# create tests
|
||||
cat > test_foo.py << EOF
|
||||
def test_foo():
|
||||
assert True
|
||||
EOF
|
||||
|
||||
if [ "$METHOD" != "none" ]; then
|
||||
|
||||
# and activate it
|
||||
# unset variables on 3.5, it's known
|
||||
|
|
@ -27,29 +59,15 @@ source venv/bin/activate
|
|||
set -u
|
||||
|
||||
# run python in it
|
||||
python -c 'import sys; print(sys.version)' | head -n1 | grep $VERSION
|
||||
python -c 'import sys; print(sys.version)' | head -n1 | grep ${VERSION/t}
|
||||
|
||||
# install packages with pip
|
||||
if [ "$VERSION" == "2.6" ]; then
|
||||
pip install pytest
|
||||
pip install Cython --install-option="--no-cython-compile"
|
||||
else
|
||||
python -m pip install pytest
|
||||
if [ "$PYTHON" != "jython" ]; then
|
||||
python -m pip install Cython
|
||||
fi
|
||||
fi
|
||||
python -m pip install pytest
|
||||
|
||||
# run tests
|
||||
cat > test_foo.py << EOF
|
||||
def test_foo():
|
||||
assert True
|
||||
EOF
|
||||
|
||||
python -m pytest -v test_foo.py
|
||||
|
||||
# check that we can do extension modules
|
||||
if [ "$PYTHON" != "jython" ]; then
|
||||
if [ "$CYTHON" == "true" ]; then
|
||||
cat > module.pyx << EOF
|
||||
cdef int add(int a, int b):
|
||||
return a + b
|
||||
|
|
@ -60,6 +78,12 @@ def two():
|
|||
return add(a, b)
|
||||
EOF
|
||||
|
||||
cat > pyproject.toml << EOF
|
||||
[build-system]
|
||||
requires = ["setuptools", "cython"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
EOF
|
||||
|
||||
cat > setup.py << EOF
|
||||
from setuptools import setup
|
||||
from Cython.Build import cythonize
|
||||
|
|
@ -67,7 +91,7 @@ from Cython.Build import cythonize
|
|||
setup(ext_modules = cythonize('module.pyx'))
|
||||
EOF
|
||||
|
||||
python setup.py build_ext --inplace
|
||||
python -m pip install .
|
||||
|
||||
python -c 'import module; print(module.two())' | grep '^2$'
|
||||
fi
|
||||
|
|
@ -77,18 +101,50 @@ set +u
|
|||
deactivate
|
||||
set -u
|
||||
|
||||
fi # METHOD != none
|
||||
|
||||
# ensurepip test (when testing virtualenv, this was not covered)
|
||||
# with the main Python, this will say "Requirement already satisfied", but that's OK
|
||||
$PYTHON -m ensurepip --root ensurepiptestroot
|
||||
|
||||
# use it with tox
|
||||
[[ "$TOX" != "true" ]] && exit 0
|
||||
cat > tox.ini << EOF
|
||||
[tox]
|
||||
if [[ $PYTHON == python* ]]; then
|
||||
export TOXENV=py${VERSION/./}
|
||||
elif [[ $PYTHON == pypy* ]]; then
|
||||
export TOXENV=pypy${VERSION/./}
|
||||
else
|
||||
export TOXENV=$PYTHON
|
||||
fi
|
||||
|
||||
echo '[tox]' > tox.ini
|
||||
if [ -n "$TOX_REQUIRES" ]; then
|
||||
echo 'requires = '"$TOX_REQUIRES" >> tox.ini
|
||||
fi
|
||||
cat >> tox.ini << EOF
|
||||
skipsdist = True
|
||||
[testenv]
|
||||
commands = python -c 'import sys; print(sys.version)'
|
||||
EOF
|
||||
|
||||
# Tests that the Python version used in tox is really the Python version we want
|
||||
tox | tee toxlog
|
||||
grep "^${VERSION/t}\.[0-9]" toxlog
|
||||
|
||||
echo '[tox]' > tox.ini
|
||||
if [ -n "$TOX_REQUIRES" ]; then
|
||||
echo 'requires = '"$TOX_REQUIRES" >> tox.ini
|
||||
fi
|
||||
cat >> tox.ini << EOF
|
||||
skipsdist = True
|
||||
[testenv]
|
||||
deps = pytest
|
||||
commands = python -m pytest -v test_foo.py
|
||||
EOF
|
||||
|
||||
if [[ $PYTHON == python* ]]; then
|
||||
tox -e py${VERSION/./}
|
||||
else
|
||||
tox -e $PYTHON
|
||||
fi
|
||||
# A more complex example with pytest
|
||||
tox
|
||||
|
||||
# Clean up if everything else went well
|
||||
cd -
|
||||
rm -rf "$workdir"
|
||||
|
|
|
|||
104
tests.yml
Normal file
104
tests.yml
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
---
|
||||
- hosts: localhost
|
||||
tags:
|
||||
- classic
|
||||
tasks:
|
||||
- dnf:
|
||||
name: "*"
|
||||
state: latest
|
||||
- ansible.builtin.user:
|
||||
name: testuser
|
||||
|
||||
- hosts: localhost
|
||||
roles:
|
||||
- role: standard-test-basic
|
||||
tags:
|
||||
- classic
|
||||
tests:
|
||||
- smoke_default:
|
||||
dir: smoke
|
||||
run: runuser testuser -c './venv.sh'
|
||||
- smoke27:
|
||||
dir: smoke
|
||||
run: VERSION=2.7 INSTALL_OR_SKIP=true METHOD=virtualenv TOX_REQUIRES="virtualenv<20.22.0" ./venv.sh
|
||||
- smoke27_seeder_pip:
|
||||
dir: smoke
|
||||
run: VERSION=2.7 INSTALL_OR_SKIP=true METHOD=virtualenv-seeder-pip TOX=false ./venv.sh
|
||||
- smoke36:
|
||||
dir: smoke
|
||||
run: runuser testuser -c 'VERSION=3.6 METHOD=venv TOX_REQUIRES="virtualenv<20.22.0" ./venv.sh'
|
||||
- smoke37:
|
||||
dir: smoke
|
||||
run: VERSION=3.7 METHOD=venv INSTALL_OR_SKIP=true ./venv.sh
|
||||
- smoke38:
|
||||
dir: smoke
|
||||
run: VERSION=3.8 METHOD=venv INSTALL_OR_SKIP=true ./venv.sh
|
||||
- smoke39:
|
||||
dir: smoke
|
||||
run: runuser testuser -c 'VERSION=3.9 METHOD=venv ./venv.sh'
|
||||
- smoke311:
|
||||
dir: smoke
|
||||
run: runuser testuser -c 'VERSION=3.11 METHOD=venv CYTHON=false ./venv.sh'
|
||||
- smoke312:
|
||||
dir: smoke
|
||||
run: runuser testuser -c 'VERSION=3.12 METHOD=venv ./venv.sh'
|
||||
- smoke314t_optional:
|
||||
dir: smoke
|
||||
run: VERSION=3.14t METHOD=venv INSTALL_OR_SKIP=true ./venv.sh
|
||||
- smoke39_seeder_pip:
|
||||
dir: smoke
|
||||
run: runuser testuser -c 'VERSION=3.9 METHOD=virtualenv-seeder-pip ./venv.sh'
|
||||
- smoke34_optional:
|
||||
dir: smoke
|
||||
run: VERSION=3.4 METHOD=venv INSTALL_OR_SKIP=true ./venv.sh
|
||||
- smoke310_optional:
|
||||
dir: smoke
|
||||
run: VERSION=3.10 METHOD=venv TOX=false INSTALL_OR_SKIP=true ./venv.sh
|
||||
- smoke311_virtualenv_download:
|
||||
dir: smoke
|
||||
run: VERSION=3.10 METHOD=virtualenv-download TOX=false ./venv.sh
|
||||
- smokepypy:
|
||||
dir: smoke
|
||||
run: runuser testuser -c 'VERSION=2.7 METHOD=none PYTHON=pypy TOX_REQUIRES="virtualenv<20.22.0" ./venv.sh'
|
||||
- smokepypy310:
|
||||
dir: smoke
|
||||
run: runuser testuser -c 'VERSION=3.10 METHOD=venv PYTHON=pypy3.10 ./venv.sh'
|
||||
- selftest39:
|
||||
dir: selftest
|
||||
run: runuser testuser -c 'VERSION=3.9 X="-x test_socket -x test_asyncgen -x test_asyncio -x test_compile -x test_concurrent_futures -x test_itertools -x test_multiprocessing_fork -x test_multiprocessing_forkserver -x test_shutil -x test_time -x test_multiprocessing_spawn -x test_threading -x test_wsgiref" ./parallel.sh'
|
||||
- debugtest310:
|
||||
dir: selftest
|
||||
run: runuser testuser -c 'VERSION=3.10 PYTHON="python3.10d" X="test_ssl" ./parallel.sh'
|
||||
- debugflags:
|
||||
dir: flags
|
||||
run: runuser testuser -c 'python3-debug ./assertflags.py -O0'
|
||||
- debugflags_some:
|
||||
dir: flags
|
||||
run: runuser testuser -c 'python3-debug ./assertflags.py -O0 PY_STDMODULE_CFLAGS'
|
||||
- optflags_o3:
|
||||
dir: flags
|
||||
run: runuser testuser -c 'python3 ./assertflags.py -O3 CFLAGS'
|
||||
- marshalparser_compatibility:
|
||||
dir: marshalparser
|
||||
run: runuser testuser -c 'SAMPLE=10 test_marshalparser_compatibility.sh'
|
||||
required_packages:
|
||||
- util-linux # for runuser
|
||||
- dnf
|
||||
- gcc
|
||||
- gcc-c++
|
||||
- virtualenv
|
||||
- python3.6
|
||||
- python3.9
|
||||
- python3.11
|
||||
- python3.12
|
||||
- pypy
|
||||
- pypy3.10-devel
|
||||
- python3-devel
|
||||
- pypy-devel
|
||||
- python3-tox
|
||||
- python3-tkinter
|
||||
- python3-test
|
||||
- python3-debug
|
||||
- python3.10-debug
|
||||
- python3-rpm-macros
|
||||
- marshalparser
|
||||
Loading…
Add table
Add a link
Reference in a new issue