Compare commits
4 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9358fa66bc | ||
|
|
b3c9a16a9d | ||
|
|
3903c0b861 | ||
|
|
7c561e2e11 |
14 changed files with 33 additions and 549 deletions
|
|
@ -1,48 +0,0 @@
|
||||||
"""
|
|
||||||
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:
|
contact:
|
||||||
- Petr Šplíchal <psplicha@redhat.com>
|
- Petr Šplíchal <psplicha@redhat.com>
|
||||||
- Miro Hrončok <mhroncok@redhat.com>
|
- Miro Hrončok <miro@hroncok.cz>
|
||||||
component: [python]
|
component: [python]
|
||||||
|
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
#!/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
|
|
||||||
|
|
@ -1,92 +0,0 @@
|
||||||
#!/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"
|
|
||||||
|
|
@ -1,67 +0,0 @@
|
||||||
#!/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()
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
#!/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 +0,0 @@
|
||||||
test: ./findleaks.sh
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
#!/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
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
require:
|
|
||||||
- python3-test
|
|
||||||
- python3-rpm-macros
|
|
||||||
- python3-tkinter
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
test: ./parallel.sh
|
|
||||||
duration: 30m
|
|
||||||
recommend:
|
|
||||||
- /usr/bin/dtrace
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
#!/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,21 +21,16 @@ description: |
|
||||||
* METHOD ... virtual environment creation method (venv, virtualenv)
|
* METHOD ... virtual environment creation method (venv, virtualenv)
|
||||||
* TOX ... enable or disable the tox test (true, false)
|
* TOX ... enable or disable the tox test (true, false)
|
||||||
|
|
||||||
path: /smoke
|
path: smoke
|
||||||
test: ./venv.sh
|
test: ./venv.sh
|
||||||
|
|
||||||
tier: 1
|
tier: 1
|
||||||
tag: [venv]
|
tags: [venv]
|
||||||
|
|
||||||
require+:
|
|
||||||
- gcc
|
|
||||||
- gcc-c++
|
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
VERSION: 3.7
|
VERSION: 3.7
|
||||||
METHOD: venv
|
METHOD: venv
|
||||||
TOX: true
|
TOX: true
|
||||||
TOX_REQUIRES: ""
|
|
||||||
duration: 10m
|
duration: 10m
|
||||||
component+:
|
component+:
|
||||||
- python2
|
- python2
|
||||||
|
|
|
||||||
114
smoke/venv.sh
114
smoke/venv.sh
|
|
@ -1,56 +1,24 @@
|
||||||
#!/bin/sh -eux
|
#!/bin/sh -eux
|
||||||
|
|
||||||
# set default version to %{python3_version} if available
|
# set python version
|
||||||
VERSION=${VERSION:-$(rpm --eval '%{?python3_version}')} || true
|
VERSION=${VERSION:-3.7}
|
||||||
# ...or 3.8 if that macro is not available or rpm fails for any reason
|
|
||||||
VERSION=${VERSION:-3.8}
|
|
||||||
|
|
||||||
PYTHON=${PYTHON:-python$VERSION}
|
PYTHON=${PYTHON:-python$VERSION}
|
||||||
METHOD=${METHOD:-venv}
|
METHOD=${METHOD:-venv}
|
||||||
TOX=${TOX:-true}
|
TOX=${TOX:-true}
|
||||||
TOX_REQUIRES=${TOX_REQUIRES:-}
|
|
||||||
CYTHON=${CYTHON:-true}
|
|
||||||
INSTALL_OR_SKIP=${INSTALL_OR_SKIP:-false}
|
|
||||||
|
|
||||||
# Work from a custom directory
|
# clean from possible older runs
|
||||||
workdir="$(mktemp --directory)"
|
rm -rf venv .tox __pycache__ .pytest* test_*.py *.pyx *.c *.so || :
|
||||||
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
|
# check the we can create the venv
|
||||||
if [ "$METHOD" == "venv" ]; then
|
if [ "$METHOD" == "venv" ]; then
|
||||||
$PYTHON -m venv venv
|
$PYTHON -m venv venv
|
||||||
elif [ "$METHOD" == "virtualenv" ]; then
|
elif [ "$METHOD" == "virtualenv" ]; then
|
||||||
virtualenv --python=$PYTHON venv
|
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
|
else
|
||||||
echo 'Unsupported $METHOD' $METHOD >&2
|
echo 'Unsupported $METHOD' $METHOD >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# create tests
|
|
||||||
cat > test_foo.py << EOF
|
|
||||||
def test_foo():
|
|
||||||
assert True
|
|
||||||
EOF
|
|
||||||
|
|
||||||
if [ "$METHOD" != "none" ]; then
|
|
||||||
|
|
||||||
# and activate it
|
# and activate it
|
||||||
# unset variables on 3.5, it's known
|
# unset variables on 3.5, it's known
|
||||||
|
|
@ -59,15 +27,29 @@ source venv/bin/activate
|
||||||
set -u
|
set -u
|
||||||
|
|
||||||
# run python in it
|
# run python in it
|
||||||
python -c 'import sys; print(sys.version)' | head -n1 | grep ${VERSION/t}
|
python -c 'import sys; print(sys.version)' | head -n1 | grep $VERSION
|
||||||
|
|
||||||
# install packages with pip
|
# install packages with pip
|
||||||
python -m pip install pytest
|
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
|
||||||
|
|
||||||
# run tests
|
# run tests
|
||||||
|
cat > test_foo.py << EOF
|
||||||
|
def test_foo():
|
||||||
|
assert True
|
||||||
|
EOF
|
||||||
|
|
||||||
python -m pytest -v test_foo.py
|
python -m pytest -v test_foo.py
|
||||||
|
|
||||||
if [ "$CYTHON" == "true" ]; then
|
# check that we can do extension modules
|
||||||
|
if [ "$PYTHON" != "jython" ]; then
|
||||||
cat > module.pyx << EOF
|
cat > module.pyx << EOF
|
||||||
cdef int add(int a, int b):
|
cdef int add(int a, int b):
|
||||||
return a + b
|
return a + b
|
||||||
|
|
@ -78,12 +60,6 @@ def two():
|
||||||
return add(a, b)
|
return add(a, b)
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
cat > pyproject.toml << EOF
|
|
||||||
[build-system]
|
|
||||||
requires = ["setuptools", "cython"]
|
|
||||||
build-backend = "setuptools.build_meta"
|
|
||||||
EOF
|
|
||||||
|
|
||||||
cat > setup.py << EOF
|
cat > setup.py << EOF
|
||||||
from setuptools import setup
|
from setuptools import setup
|
||||||
from Cython.Build import cythonize
|
from Cython.Build import cythonize
|
||||||
|
|
@ -91,7 +67,7 @@ from Cython.Build import cythonize
|
||||||
setup(ext_modules = cythonize('module.pyx'))
|
setup(ext_modules = cythonize('module.pyx'))
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
python -m pip install .
|
python setup.py build_ext --inplace
|
||||||
|
|
||||||
python -c 'import module; print(module.two())' | grep '^2$'
|
python -c 'import module; print(module.two())' | grep '^2$'
|
||||||
fi
|
fi
|
||||||
|
|
@ -101,50 +77,18 @@ set +u
|
||||||
deactivate
|
deactivate
|
||||||
set -u
|
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
|
# use it with tox
|
||||||
[[ "$TOX" != "true" ]] && exit 0
|
[[ "$TOX" != "true" ]] && exit 0
|
||||||
if [[ $PYTHON == python* ]]; then
|
cat > tox.ini << EOF
|
||||||
export TOXENV=py${VERSION/./}
|
[tox]
|
||||||
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
|
skipsdist = True
|
||||||
[testenv]
|
[testenv]
|
||||||
deps = pytest
|
deps = pytest
|
||||||
commands = python -m pytest -v test_foo.py
|
commands = python -m pytest -v test_foo.py
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# A more complex example with pytest
|
if [[ $PYTHON == python* ]]; then
|
||||||
tox
|
tox -e py${VERSION/./}
|
||||||
|
else
|
||||||
# Clean up if everything else went well
|
tox -e $PYTHON
|
||||||
cd -
|
fi
|
||||||
rm -rf "$workdir"
|
|
||||||
|
|
|
||||||
104
tests.yml
104
tests.yml
|
|
@ -1,104 +0,0 @@
|
||||||
---
|
|
||||||
- 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