Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package buildstream for openSUSE:Factory checked in at 2023-02-23 16:30:23 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/buildstream (Old) and /work/SRC/openSUSE:Factory/.buildstream.new.1706 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "buildstream" Thu Feb 23 16:30:23 2023 rev:25 rq:1067348 version:1.6.9 Changes: -------- --- /work/SRC/openSUSE:Factory/buildstream/buildstream.changes 2022-10-16 16:09:39.902817908 +0200 +++ /work/SRC/openSUSE:Factory/.buildstream.new.1706/buildstream.changes 2023-02-23 16:54:02.969359596 +0100 @@ -1,0 +2,6 @@ +Wed Feb 22 11:58:55 UTC 2023 - Bjørn Lie <bjorn....@gmail.com> + +- Update to version 1.6.9: + + Further Python 3.11 fixes to regex flags. + +------------------------------------------------------------------- Old: ---- buildstream-1.6.8.tar.gz New: ---- buildstream-1.6.9.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ buildstream.spec ++++++ --- /var/tmp/diff_new_pack.QgwjSO/_old 2023-02-23 16:54:04.181366624 +0100 +++ /var/tmp/diff_new_pack.QgwjSO/_new 2023-02-23 16:54:04.185366647 +0100 @@ -1,7 +1,7 @@ # # spec file for package buildstream # -# Copyright (c) 2022 SUSE LLC +# Copyright (c) 2023 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,7 +17,7 @@ Name: buildstream -Version: 1.6.8 +Version: 1.6.9 Release: 0 Summary: A framework for modelling build pipelines in YAML License: LGPL-2.1-or-later ++++++ buildstream-1.6.8.tar.gz -> buildstream-1.6.9.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/buildstream-1.6.8/.github/common.env new/buildstream-1.6.9/.github/common.env --- old/buildstream-1.6.8/.github/common.env 2022-10-12 17:13:38.000000000 +0200 +++ new/buildstream-1.6.9/.github/common.env 2023-02-21 15:31:28.000000000 +0100 @@ -1,5 +1,5 @@ # Shared common variables -CI_IMAGE_VERSION=master-533491591 -CI_TOXENV_MAIN=py36-nocover,py37-nocover,py38-nocover,py39-nocover,py310-nocover +CI_IMAGE_VERSION=master-784208155 +CI_TOXENV_MAIN=py36-nocover,py37-nocover,py38-nocover,py39-nocover,py310-nocover,py311-nocover CI_TOXENV_ALL="${CI_TOXENV_MAIN}" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/buildstream-1.6.8/.github/compose/ci.docker-compose.yml new/buildstream-1.6.9/.github/compose/ci.docker-compose.yml --- old/buildstream-1.6.8/.github/compose/ci.docker-compose.yml 2022-10-12 17:13:38.000000000 +0200 +++ new/buildstream-1.6.9/.github/compose/ci.docker-compose.yml 2023-02-21 15:31:28.000000000 +0100 @@ -1,7 +1,7 @@ version: '3.4' x-tests-template: &tests-template - image: registry.gitlab.com/buildstream/buildstream-docker-images/testsuite-fedora:35-${CI_IMAGE_VERSION:-latest} + image: registry.gitlab.com/buildstream/buildstream-docker-images/testsuite-fedora:36-${CI_IMAGE_VERSION:-latest} command: tox -vvvvv -- --color=yes --integration environment: TOXENV: ${CI_TOXENV_ALL} @@ -22,14 +22,14 @@ services: - fedora-35: - <<: *tests-template - image: registry.gitlab.com/buildstream/buildstream-docker-images/testsuite-fedora:35-${CI_IMAGE_VERSION:-latest} - fedora-36: <<: *tests-template image: registry.gitlab.com/buildstream/buildstream-docker-images/testsuite-fedora:36-${CI_IMAGE_VERSION:-latest} + fedora-37: + <<: *tests-template + image: registry.gitlab.com/buildstream/buildstream-docker-images/testsuite-fedora:37-${CI_IMAGE_VERSION:-latest} + debian-10: <<: *tests-template image: registry.gitlab.com/buildstream/buildstream-docker-images/testsuite-debian:10-${CI_IMAGE_VERSION:-latest} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/buildstream-1.6.8/.github/run-ci.sh new/buildstream-1.6.9/.github/run-ci.sh --- old/buildstream-1.6.8/.github/run-ci.sh 2022-10-12 17:13:38.000000000 +0200 +++ new/buildstream-1.6.9/.github/run-ci.sh 2023-02-21 15:31:28.000000000 +0100 @@ -67,8 +67,8 @@ if [ -z "${test_names}" ]; then runTest "lint" runTest "debian-10" - runTest "fedora-35" runTest "fedora-36" + runTest "fedora-37" else for test_name in "${test_names}"; do runTest "${test_name}" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/buildstream-1.6.8/.github/workflows/ci.yml new/buildstream-1.6.9/.github/workflows/ci.yml --- old/buildstream-1.6.8/.github/workflows/ci.yml 2022-10-12 17:13:38.000000000 +0200 +++ new/buildstream-1.6.9/.github/workflows/ci.yml 2023-02-21 15:31:28.000000000 +0100 @@ -26,8 +26,8 @@ # "../compose/ci.docker-compose.yml" test-name: - debian-10 - - fedora-35 - fedora-36 + - fedora-37 - lint steps: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/buildstream-1.6.8/NEWS new/buildstream-1.6.9/NEWS --- old/buildstream-1.6.8/NEWS 2022-10-12 17:13:38.000000000 +0200 +++ new/buildstream-1.6.9/NEWS 2023-02-21 15:31:28.000000000 +0100 @@ -1,4 +1,10 @@ ================= +buildstream 1.6.9 +================= + + o Further Python 3.11 fixes to regex flags. + +================= buildstream 1.6.8 ================= diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/buildstream-1.6.8/buildstream/_exceptions.py new/buildstream-1.6.9/buildstream/_exceptions.py --- old/buildstream-1.6.8/buildstream/_exceptions.py 2022-10-12 17:13:38.000000000 +0200 +++ new/buildstream-1.6.9/buildstream/_exceptions.py 2023-02-21 15:31:28.000000000 +0100 @@ -24,25 +24,10 @@ # pylint: disable=global-statement # The last raised exception, this is used in test cases only -_last_exception = None _last_task_error_domain = None _last_task_error_reason = None -# get_last_exception() -# -# Fetches the last exception from the main process -# -# Used by regression tests -# -def get_last_exception(): - global _last_exception - - le = _last_exception - _last_exception = None - return le - - # get_last_task_error() # # Fetches the last exception from a task @@ -102,7 +87,6 @@ class BstError(Exception): def __init__(self, message, *, detail=None, domain=None, reason=None, temporary=False): - global _last_exception super().__init__(message) @@ -126,9 +110,6 @@ self.domain = domain self.reason = reason - # Hold on to the last raised exception for testing purposes - _last_exception = self - # PluginError # diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/buildstream-1.6.8/buildstream/_frontend/app.py new/buildstream-1.6.9/buildstream/_frontend/app.py --- old/buildstream-1.6.8/buildstream/_frontend/app.py 2022-10-12 17:13:38.000000000 +0200 +++ new/buildstream-1.6.9/buildstream/_frontend/app.py 2023-02-21 15:31:28.000000000 +0100 @@ -22,9 +22,11 @@ import resource import traceback import datetime +from enum import Enum from textwrap import TextWrapper from contextlib import contextmanager +import ujson import click from click import UsageError @@ -35,7 +37,7 @@ from .._context import Context from .._platform import Platform from .._project import Project -from .._exceptions import BstError, StreamError, LoadError, LoadErrorReason, AppError +from .._exceptions import BstError, StreamError, LoadError, LoadErrorReason, AppError, get_last_task_error from .._message import Message, MessageType, unconditional_messages from .._stream import Stream from .._versions import BST_FORMAT_VERSION @@ -682,6 +684,20 @@ detail = '\n' + indent + indent.join(error.detail.splitlines(True)) click.echo("{}".format(detail), err=True) + # Record machine readable errors in a tempfile for the test harness to read back + if 'BST_TEST_ERROR_CODES' in os.environ: + task_error_domain, task_error_reason = get_last_task_error () + error_codes = ujson.dumps ({ + 'main_error_domain': error.domain.value if error.domain else None, + 'main_error_reason': error.reason.value if isinstance (error.reason, Enum) else error.reason, + 'task_error_domain': task_error_domain.value if task_error_domain else None, + 'task_error_reason': ( + task_error_reason.value if isinstance (task_error_reason, Enum) else task_error_reason + ) + }) + with open (os.environ['BST_TEST_ERROR_CODES'], "w", encoding="utf-8") as f: + f.write (error_codes) + sys.exit(-1) # diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/buildstream-1.6.8/buildstream/_version.py new/buildstream-1.6.9/buildstream/_version.py --- old/buildstream-1.6.8/buildstream/_version.py 2022-10-12 17:13:38.000000000 +0200 +++ new/buildstream-1.6.9/buildstream/_version.py 2023-02-21 15:31:28.000000000 +0100 @@ -24,9 +24,9 @@ # setup.py/versioneer.py will grep for the variable names, so they must # each be defined on a line of their own. _version.py will just call # get_keywords(). - git_refnames = " (tag: 1.6.8, bst-1)" - git_full = "0f431178ffa5a6d3e385378660ba574f5f5fb17e" - git_date = "2022-10-13 00:13:38 +0900" + git_refnames = " (tag: 1.6.9, bst-1)" + git_full = "4abd1f3e1b5e5d128bc24e45ec9a37d61723be87" + git_date = "2023-02-21 23:31:28 +0900" keywords = {"refnames": git_refnames, "full": git_full, "date": git_date} return keywords diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/buildstream-1.6.8/buildstream/element.py new/buildstream-1.6.9/buildstream/element.py --- old/buildstream-1.6.8/buildstream/element.py 2022-10-12 17:13:38.000000000 +0200 +++ new/buildstream-1.6.9/buildstream/element.py 2023-02-21 15:31:28.000000000 +0100 @@ -2311,7 +2311,9 @@ bstdata = self.get_public_data('bst') splits = bstdata.get('split-rules') self.__splits = { - domain: re.compile('^(?:' + '|'.join([utils._glob2re(r) for r in rules]) + ')$') + domain: re.compile( + "^(?:" + "|".join([utils._glob2re(r) for r in rules]) + ")$", re.MULTILINE | re.DOTALL + ) for domain, rules in self.node_items(splits) } @@ -2386,7 +2388,7 @@ for index, exp in enumerate(whitelist) ] expression = ('^(?:' + '|'.join(whitelist_expressions) + ')$') - self.__whitelist_regex = re.compile(expression) + self.__whitelist_regex = re.compile(expression, re.MULTILINE | re.DOTALL) return self.__whitelist_regex.match(path) or self.__whitelist_regex.match(os.path.join(os.sep, path)) # __extract(): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/buildstream-1.6.8/buildstream/plugins/sources/pip.py new/buildstream-1.6.9/buildstream/plugins/sources/pip.py --- old/buildstream-1.6.8/buildstream/plugins/sources/pip.py 2022-10-12 17:13:38.000000000 +0200 +++ new/buildstream-1.6.9/buildstream/plugins/sources/pip.py 2023-02-21 15:31:28.000000000 +0100 @@ -93,6 +93,7 @@ 'python3.8', 'python3.9', 'python3.10', + 'python3.11', ] # List of allowed extensions taken from diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/buildstream-1.6.8/buildstream/utils.py new/buildstream-1.6.9/buildstream/utils.py --- old/buildstream-1.6.8/buildstream/utils.py 2022-10-12 17:13:38.000000000 +0200 +++ new/buildstream-1.6.9/buildstream/utils.py 2023-02-21 15:31:28.000000000 +0100 @@ -200,7 +200,7 @@ pattern = os.sep + pattern expression = _glob2re(pattern) - regexer = re.compile(expression) + regexer = re.compile(expression, re.MULTILINE | re.DOTALL) for filename in paths: filename_try = filename @@ -1138,7 +1138,7 @@ # def _glob2re(pat): i, n = 0, len(pat) - res = '(?ms)' + res = '' while i < n: c = pat[i] i = i + 1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/buildstream-1.6.8/requirements/requirements.txt new/buildstream-1.6.9/requirements/requirements.txt --- old/buildstream-1.6.8/requirements/requirements.txt 2022-10-12 17:13:38.000000000 +0200 +++ new/buildstream-1.6.9/requirements/requirements.txt 2023-02-21 15:31:28.000000000 +0100 @@ -1,5 +1,5 @@ click==8.1.3 -grpcio==1.48.0 +grpcio==1.51.1 Jinja2==3.1.2 pluginbase==1.0.1 protobuf==4.21.4 @@ -9,5 +9,5 @@ ujson==5.4.0 ## The following requirements were added by pip freeze: MarkupSafe==2.1.1 -ruamel.yaml.clib==0.2.6 +ruamel.yaml.clib==0.2.7 six==1.16.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/buildstream-1.6.8/setup.py new/buildstream-1.6.9/setup.py --- old/buildstream-1.6.8/setup.py 2022-10-12 17:13:38.000000000 +0200 +++ new/buildstream-1.6.9/setup.py 2023-02-21 15:31:28.000000000 +0100 @@ -263,6 +263,8 @@ 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', + 'Programming Language :: Python :: 3.11', 'Topic :: Software Development :: Build Tools' ], description='A framework for modelling build pipelines in YAML', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/buildstream-1.6.8/tests/artifactcache/expiry.py new/buildstream-1.6.9/tests/artifactcache/expiry.py --- old/buildstream-1.6.8/tests/artifactcache/expiry.py 2022-10-12 17:13:38.000000000 +0200 +++ new/buildstream-1.6.9/tests/artifactcache/expiry.py 2023-02-21 15:31:28.000000000 +0100 @@ -289,6 +289,7 @@ # has 10K total disk space, and 6K of it is already in use (not # including any space used by the artifact cache). # +@pytest.mark.xfail(reason="unittest.mock() not supported when running tests in subprocesses") @pytest.mark.parametrize("quota,err_domain,err_reason", [ # Valid configurations ("1", 'success', None), diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/buildstream-1.6.8/tests/format/assertion.py new/buildstream-1.6.9/tests/format/assertion.py --- old/buildstream-1.6.8/tests/format/assertion.py 2022-10-12 17:13:38.000000000 +0200 +++ new/buildstream-1.6.9/tests/format/assertion.py 2023-02-21 15:31:28.000000000 +0100 @@ -32,4 +32,4 @@ # Assert that the assertion text provided by the user # is found in the exception text - assert assertion in str(result.exception) + assert assertion in str(result.stderr) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/buildstream-1.6.8/tests/format/optionarch.py new/buildstream-1.6.9/tests/format/optionarch.py --- old/buildstream-1.6.8/tests/format/optionarch.py 2022-10-12 17:13:38.000000000 +0200 +++ new/buildstream-1.6.9/tests/format/optionarch.py 2023-02-21 15:31:28.000000000 +0100 @@ -12,6 +12,12 @@ # Context manager to override the reported value of `os.uname()` @contextmanager def override_uname_arch(name): + + # + # Disabling this test since we now run bst in a subprocess during tests. + # + pytest.xfail("Overriding os.uname() in bst subprocess is unsupported") + orig_uname = os.uname orig_tuple = tuple(os.uname()) override_result = (orig_tuple[0], orig_tuple[1], diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/buildstream-1.6.8/tests/frontend/fetch.py new/buildstream-1.6.9/tests/frontend/fetch.py --- old/buildstream-1.6.8/tests/frontend/fetch.py 2022-10-12 17:13:38.000000000 +0200 +++ new/buildstream-1.6.9/tests/frontend/fetch.py 2023-02-21 15:31:28.000000000 +0100 @@ -71,8 +71,7 @@ # more gracefully as a BUG message. # result = cli.run(project=project, args=['fetch', 'bug.bst']) - assert result.exc is not None - assert str(result.exc) == "Something went terribly wrong" + assert "Something went terribly wrong" in result.stderr @pytest.mark.datafiles(DATA_DIR) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/buildstream-1.6.8/tests/frontend/show.py new/buildstream-1.6.9/tests/frontend/show.py --- old/buildstream-1.6.8/tests/frontend/show.py 2022-10-12 17:13:38.000000000 +0200 +++ new/buildstream-1.6.9/tests/frontend/show.py 2023-02-21 15:31:28.000000000 +0100 @@ -269,6 +269,7 @@ ############################################################### # Testing recursion depth # ############################################################### +@pytest.mark.xfail(reason="recursion errors not currently detectable") @pytest.mark.parametrize("dependency_depth", [100, 500, 1200]) def test_exceed_max_recursion_depth(cli, tmpdir, dependency_depth): project_name = "recursion-test" @@ -314,8 +315,14 @@ if dependency_depth <= recursion_limit: result.assert_success() else: - # Assert exception is thown and handled - assert not result.unhandled_exception + # XXX Assert exception is thown and handled + # + # We need to assert that the client has not thrown a stack trace for + # a recursion error, this should be done by creating a BstError instead + # of just handling it in app.py and doing sys.exit(), because we no longer + # have any way of detecting whether the client has thrown an exception + # otherwise + # assert result.exit_code == -1 shutil.rmtree(project_path) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/buildstream-1.6.8/tests/integration/symlinks.py new/buildstream-1.6.9/tests/integration/symlinks.py --- old/buildstream-1.6.8/tests/integration/symlinks.py 2022-10-12 17:13:38.000000000 +0200 +++ new/buildstream-1.6.9/tests/integration/symlinks.py 2023-02-21 15:31:28.000000000 +0100 @@ -70,5 +70,5 @@ # point outside the sandbox which BuildStream needs to detect before it # tries to actually write there. result = cli.run(project=project, args=['checkout', element_name, checkout]) - assert result.exit_code == -1 + assert result.exit_code != 0 assert "Destination path resolves to a path outside of the staging area" in result.stderr diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/buildstream-1.6.8/tests/loader/junctions.py new/buildstream-1.6.9/tests/loader/junctions.py --- old/buildstream-1.6.8/tests/loader/junctions.py 2022-10-12 17:13:38.000000000 +0200 +++ new/buildstream-1.6.9/tests/loader/junctions.py 2023-02-21 15:31:28.000000000 +0100 @@ -135,10 +135,7 @@ copy_subprojects(project, datafiles, ['foo', 'bar']) result = cli.run(project=project, args=['build', 'target.bst']) - assert result.exit_code != 0 - assert result.exception - assert isinstance(result.exception, LoadError) - assert result.exception.reason == LoadErrorReason.CONFLICTING_JUNCTION + result.assert_main_error(ErrorDomain.LOAD, LoadErrorReason.CONFLICTING_JUNCTION) @pytest.mark.datafiles(DATA_DIR) @@ -146,10 +143,7 @@ project = os.path.join(str(datafiles), 'invalid') result = cli.run(project=project, args=['build', 'missing.bst']) - assert result.exit_code != 0 - assert result.exception - assert isinstance(result.exception, LoadError) - assert result.exception.reason == LoadErrorReason.MISSING_FILE + result.assert_main_error(ErrorDomain.LOAD, LoadErrorReason.MISSING_FILE) @pytest.mark.datafiles(DATA_DIR) @@ -158,10 +152,7 @@ copy_subprojects(project, datafiles, ['base']) result = cli.run(project=project, args=['build', 'junction-with-deps.bst']) - assert result.exit_code != 0 - assert result.exception - assert isinstance(result.exception, ElementError) - assert result.exception.reason == 'element-forbidden-depends' + result.assert_main_error(ErrorDomain.ELEMENT, 'element-forbidden-depends') @pytest.mark.datafiles(DATA_DIR) @@ -170,10 +161,7 @@ copy_subprojects(project, datafiles, ['base']) result = cli.run(project=project, args=['build', 'junction-dep.bst']) - assert result.exit_code != 0 - assert result.exception - assert isinstance(result.exception, LoadError) - assert result.exception.reason == LoadErrorReason.INVALID_DATA + result.assert_main_error(ErrorDomain.LOAD, LoadErrorReason.INVALID_DATA) @pytest.mark.datafiles(DATA_DIR) @@ -248,10 +236,7 @@ # Verify that bst show does not implicitly fetch subproject result = cli.run(project=project, args=['show', 'target.bst']) - assert result.exit_code != 0 - assert result.exception - assert isinstance(result.exception, LoadError) - assert result.exception.reason == LoadErrorReason.SUBPROJECT_FETCH_NEEDED + result.assert_main_error(ErrorDomain.LOAD, LoadErrorReason.SUBPROJECT_FETCH_NEEDED) # Explicitly fetch subproject result = cli.run(project=project, args=['fetch', 'base.bst']) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/buildstream-1.6.8/tests/sources/tar.py new/buildstream-1.6.9/tests/sources/tar.py --- old/buildstream-1.6.8/tests/sources/tar.py 2022-10-12 17:13:38.000000000 +0200 +++ new/buildstream-1.6.9/tests/sources/tar.py 2023-02-21 15:31:28.000000000 +0100 @@ -348,6 +348,7 @@ # Test that BuildStream doesnt crash if HOME is unset while # the netrc module is trying to find it's ~/.netrc file. +@pytest.mark.xfail(reason="Cannot set environment variable to None when running tests in subprocesses") @pytest.mark.datafiles(os.path.join(DATA_DIR, 'fetch')) def test_homeless_environment(cli, tmpdir, datafiles): project = os.path.join(datafiles.dirname, datafiles.basename) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/buildstream-1.6.8/tests/testutils/runcli.py new/buildstream-1.6.9/tests/testutils/runcli.py --- old/buildstream-1.6.8/tests/testutils/runcli.py 2022-10-12 17:13:38.000000000 +0200 +++ new/buildstream-1.6.9/tests/testutils/runcli.py 2023-02-21 15:31:28.000000000 +0100 @@ -7,6 +7,8 @@ import traceback import subprocess from contextlib import contextmanager, ExitStack +from enum import Enum +import ujson import pytest # XXX Using pytest private internals here @@ -22,50 +24,21 @@ from buildstream._frontend import cli as bst_cli from buildstream import _yaml -# Special private exception accessor, for test case purposes -from buildstream._exceptions import BstError, get_last_exception, get_last_task_error - # Wrapper for the click.testing result class Result(): def __init__(self, exit_code=None, - exception=None, - exc_info=None, output=None, stderr=None): self.exit_code = exit_code - self.exc = exception - self.exc_info = exc_info self.output = output self.stderr = stderr - self.unhandled_exception = False - - # The last exception/error state is stored at exception - # creation time in BstError(), but this breaks down with - # recoverable errors where code blocks ignore some errors - # and fallback to alternative branches. - # - # For this reason, we just ignore the exception and errors - # in the case that the exit code reported is 0 (success). - # - if self.exit_code != 0: - - # Check if buildstream failed to handle an - # exception, topevel CLI exit should always - # be a SystemExit exception. - # - if not isinstance(exception, SystemExit): - self.unhandled_exception = True - - self.exception = get_last_exception() - self.task_error_domain, \ - self.task_error_reason = get_last_task_error() - else: - self.exception = None - self.task_error_domain = None - self.task_error_reason = None + self.main_error_domain = None + self.main_error_reason = None + self.task_error_domain = None + self.task_error_reason = None # assert_success() # @@ -79,9 +52,6 @@ # def assert_success(self, fail_message=''): assert self.exit_code == 0, fail_message - assert self.exc is None, fail_message - assert self.exception is None, fail_message - assert self.unhandled_exception is False # assert_main_error() # @@ -106,23 +76,20 @@ print( """ Exit code: {} - Exception: {} Domain: {} Reason: {} """.format( self.exit_code, - self.exception, - self.exception.domain, - self.exception.reason + self.main_error_domain, + self.main_error_reason )) - assert self.exit_code == -1, fail_message - assert self.exc is not None, fail_message - assert self.exception is not None, fail_message - assert isinstance(self.exception, BstError), fail_message - assert self.unhandled_exception is False + assert self.exit_code != 0, fail_message + + test_domain = error_domain.value if isinstance (error_domain, Enum) else error_domain + test_reason = error_reason.value if isinstance (error_reason, Enum) else error_reason - assert self.exception.domain == error_domain, fail_message - assert self.exception.reason == error_reason, fail_message + assert self.main_error_domain == test_domain, fail_message + assert self.main_error_reason == test_reason, fail_message # assert_task_error() # @@ -143,14 +110,12 @@ error_reason, fail_message=''): - assert self.exit_code == -1, fail_message - assert self.exc is not None, fail_message - assert self.exception is not None, fail_message - assert isinstance(self.exception, BstError), fail_message - assert self.unhandled_exception is False + test_domain = error_domain.value if isinstance (error_domain, Enum) else error_domain + test_reason = error_reason.value if isinstance (error_reason, Enum) else error_reason - assert self.task_error_domain == error_domain, fail_message - assert self.task_error_reason == error_reason, fail_message + assert self.exit_code != 0, fail_message + assert self.task_error_domain == test_domain, fail_message + assert self.task_error_reason == test_reason, fail_message # get_tracked_elements() # @@ -241,9 +206,21 @@ if options is None: options = [] + if env is None: + env = os.environ.copy() + else: + orig_env = os.environ.copy() + orig_env.update (env) + env = orig_env + options = self.default_options + options with ExitStack() as stack: + + # Prepare a tempfile for buildstream to record machine readable error codes + error_codes = stack.enter_context (tempfile.NamedTemporaryFile()) + env['BST_TEST_ERROR_CODES'] = error_codes.name + bst_args = ['--no-colors'] if silent: @@ -263,21 +240,34 @@ bst_args += args - if cwd is not None: - stack.enter_context(chdir(cwd)) - - if env is not None: - stack.enter_context(environment(env)) - - # Ensure we have a working stdout - required to work - # around a bug that appears to cause AIX to close - # sys.__stdout__ after setup.py - try: - sys.__stdout__.fileno() - except ValueError: - sys.__stdout__ = open('/dev/stdout', 'w') + cmd = ["bst"] + bst_args + process = subprocess.Popen( + cmd, + env=env, + cwd=cwd, + stdin=subprocess.DEVNULL, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + out, err = process.communicate() + result = Result( + exit_code=process.poll(), + output=out.decode('utf-8'), + stderr=err.decode('utf-8') + ) - result = self.invoke(bst_cli, bst_args) + # + # Collect machine readable error codes from the tmpfile + # + result_error_codes_string = error_codes.read() + result_error_codes = {} + if result_error_codes_string: + result_error_codes = ujson.loads (result_error_codes_string) + if result_error_codes: + result.main_error_domain = result_error_codes['main_error_domain'] + result.main_error_reason = result_error_codes['main_error_reason'] + result.task_error_domain = result_error_codes['task_error_domain'] + result.task_error_reason = result_error_codes['task_error_reason'] # Some informative stdout we can observe when anything fails if self.verbose: @@ -289,54 +279,8 @@ if result.stderr: print("Program stderr was:\n{}".format(result.stderr)) - if result.exc_info and result.exc_info[0] != SystemExit: - traceback.print_exception(*result.exc_info) - return result - def invoke(self, cli, args=None, color=False, **extra): - exc_info = None - exception = None - exit_code = 0 - - # Temporarily redirect sys.stdin to /dev/null to ensure that - # Popen doesn't attempt to read pytest's dummy stdin. - old_stdin = sys.stdin - with open(os.devnull) as devnull: - sys.stdin = devnull - capture = MultiCapture(out=FDCapture(1), err=FDCapture(2), in_=None) - capture.start_capturing() - - try: - cli.main(args=args or (), prog_name=cli.name, **extra) - except SystemExit as e: - if e.code != 0: - exception = e - - exc_info = sys.exc_info() - - exit_code = e.code - if not isinstance(exit_code, int): - sys.stdout.write('Program exit code was not an integer: ') - sys.stdout.write(str(exit_code)) - sys.stdout.write('\n') - exit_code = 1 - except Exception as e: - exception = e - exit_code = -1 - exc_info = sys.exc_info() - finally: - sys.stdout.flush() - - sys.stdin = old_stdin - out, err = capture.readouterr() - capture.stop_capturing() - - return Result(exit_code=exit_code, - exception=exception, - exc_info=exc_info, - output=out, - stderr=err) # Fetch an element state by name by # invoking bst show on the project with the CLI diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/buildstream-1.6.8/tox.ini new/buildstream-1.6.9/tox.ini --- old/buildstream-1.6.8/tox.ini 2022-10-12 17:13:38.000000000 +0200 +++ new/buildstream-1.6.9/tox.ini 2023-02-21 15:31:28.000000000 +0100 @@ -2,7 +2,7 @@ # Tox global configuration # [tox] -envlist = py36-nocover,py37-nocover,py38-nocover,py39-nocover,py310-nocover +envlist = py36-nocover,py37-nocover,py38-nocover,py39-nocover,py310-nocover,py311-nocover skip_missing_interpreters = true # @@ -13,16 +13,16 @@ [testenv] commands = # Running with coverage reporting enabled - py{36,37,38,39,310}-!nocover: pytest --basetemp {envtmpdir} --cov=buildstream --cov-config .coveragerc {posargs} - py{36,37,38,39,310}-!nocover: mkdir -p .coverage-reports - py{36,37,38,39,310}-!nocover: mv {envtmpdir}/.coverage {toxinidir}/.coverage-reports/.coverage.{env:COVERAGE_PREFIX:}{envname} + py{36,37,38,39,310,311}-!nocover: pytest --basetemp {envtmpdir} --cov=buildstream --cov-config .coveragerc {posargs} + py{36,37,38,39,310,311}-!nocover: mkdir -p .coverage-reports + py{36,37,38,39,310,311}-!nocover: mv {envtmpdir}/.coverage {toxinidir}/.coverage-reports/.coverage.{env:COVERAGE_PREFIX:}{envname} # Running with coverage reporting disabled - py{36,37,38,39,310}-nocover: pytest --basetemp {envtmpdir} {posargs} + py{36,37,38,39,310,311}-nocover: pytest --basetemp {envtmpdir} {posargs} deps = - py{36,37,38,39,310}: -rrequirements/requirements.txt - py{36,37,38,39,310}: -rrequirements/dev-requirements.txt - py{36,37,38,39,310}: -rrequirements/plugin-requirements.txt + py{36,37,38,39,310,311}: -rrequirements/requirements.txt + py{36,37,38,39,310,311}: -rrequirements/dev-requirements.txt + py{36,37,38,39,310,311}: -rrequirements/plugin-requirements.txt # Only require coverage and pytest-cov when using it !nocover: -rrequirements/cov-requirements.txt @@ -35,9 +35,9 @@ # These keys are not inherited by any other sections # setenv = - py{36,37,38,39,310}: COVERAGE_FILE = {envtmpdir}/.coverage + py{36,37,38,39,310,311}: COVERAGE_FILE = {envtmpdir}/.coverage whitelist_externals = - py{36,37,38,39,310}: + py{36,37,38,39,310,311}: mv mkdir