Usage: tw-upstream-pytest --name NAME --stage build --destdir DIR [OPTIONS] Runs a Python project's upstream test suite against the installed build, with the network guard, import pinning, origin check, destdir snapshot and hard-gate rules of stereo's upstream-tests/pytest pipelines, and prints the UPSTREAM-TESTS summary lines. Exits 0 when the gate passes, 1 otherwise. Options (each takes --opt VALUE or --opt=VALUE; one per pipeline input): --name NAME (sub)package name in the summary (context.name) --stage build|test build: test the destdir (test: not yet supported) --caller NAME prefix of messages (default: tw-upstream-pytest) --destdir DIR install root under test (stage build) --workspace DIR melange workspace (default: current directory) --python PY interpreter (default DEFAULT: python3, or the single /usr/bin/python3.X) --dir DIR project directory, relative to the workspace (.) --paths 'P ...' test paths or node ids (default: testpaths) --args 'ARGS' extra pytest (or unittest discover) arguments, parsed once by the shell (quotes work) --markers EXPR -m expression --ignore 'ID ...' node ids to deselect; an entry also covers ids that continue with '::' or '[' (a file's or class's tests, parametrized cases), but not test_x_regression for test_x. An entry that matches no collected test fails the gate (contract 4; a directory matches nothing: use --ignore-files), unless its module was not collected (skipped at collection, or a collection error). For an id that exists only on some builds (a test under a sys.version_info check, a parametrized case per importable backend, a platform-gated class), use --args "--deselect ID": pytest skips it silently where it is absent, but matches any prefix (test_x also drops test_x_regression), and the tests it drops get no IGNORE line and are not in ignored= --ignore-files 'P ...' paths not to collect (--ignore) --import-mode MODE auto (append), append, prepend, importlib --clear-addopts BOOL true drops the project's addopts --jobs N|auto xdist workers (1: serial) --timeout SECS per-test timeout (0: off; default 600); not 0 needs pytest-timeout for that python --overall-timeout SECS wall-clock limit (default 3600) --runner pytest|unittest unittest: python -m unittest discover, which has no way to honour --ignore, --ignore-files, --markers, --jobs or --timeout (rejected unless left at their defaults); use --paths and --args --extensions auto|required|none --min-run-percent N fail when fewer than N% of the selected tests ran (default 5); a module skipped at collection (pytest.importorskip, allow_module_level skip) counts as one skipped test (contract 4) --envpkgs TEXT where callers add test requirements, named in messages (default: by stage) --origin NAME origin package (package.name); the test stage's default test tree is named after it Reserved for the test stage and newer gates (only the defaults work in contract 4): --package, --test-tree, --import-from installed, --isolate true. --version print the interface version and exit -h, --help show this help and exit Summary: UPSTREAM-TESTS NAME: pass=N fail=N skip=N [xfail=N] [ignored=N] [modskip=N]; modskip (contract 4) counts modules skipped at collection, whose tests are not in skip. When pytest-asyncio 0.24 or later is importable, not disabled with -p no:asyncio, and neither the project's pytest config (the key or addopts, in the file pytest 9 reads: pytest.toml, .pytest.toml, pytest.ini, .pytest.ini, pyproject.toml, tox.ini or setup.cfg) nor --args nor PYTEST_ADDOPTS sets asyncio_default_fixture_loop_scope, the tool ignores the plugin's "is unset" deprecation warning with -W (contract 4): under filterwarnings = error it is an INTERNALERROR. The option stays unset, so each async fixture's event loop keeps its caching scope. The network guard is always on. On Python 3.10 child interpreters started by the tests (python -c 'import pkg' from the source tree) can import the source copy instead of the build: PYTHONSAFEPATH needs 3.11 or later, and the import pin and origin check cover only the pytest process and its xdist workers.