[gentoo-commits] proj/portage:master commit in: pym/portage/tests/util/futures/, pym/portage/util/futures/
commit: edba848a013e1797faeacc1911a5e6571fca3ca7 Author: Zac Medico gentoo org> AuthorDate: Thu Jul 5 04:44:42 2018 + Commit: Zac Medico gentoo org> CommitDate: Wed Jul 11 07:40:59 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=edba848a Add python2 compatible coroutine support (bug 660426) For readability, it's desirable to make asynchronous code use coroutines to avoid callbacks when possible. For python2 compatibility, generators that yield Futures can be used to implement coroutines. Add a compat_coroutine module which provides a @coroutine decorator and a coroutine_return function that can be used to return a value from a generator. The decorated function returns a Future which is done when the generator is exhausted. Usage is very similar to asyncio coroutine usage in python3.4 (see unit tests). Bug: https://bugs.gentoo.org/660426 .../tests/util/futures/test_compat_coroutine.py| 159 + pym/portage/util/futures/compat_coroutine.py | 112 +++ 2 files changed, 271 insertions(+) diff --git a/pym/portage/tests/util/futures/test_compat_coroutine.py b/pym/portage/tests/util/futures/test_compat_coroutine.py new file mode 100644 index 0..cbc070869 --- /dev/null +++ b/pym/portage/tests/util/futures/test_compat_coroutine.py @@ -0,0 +1,159 @@ +# Copyright 2018 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +from portage.util.futures import asyncio +from portage.util.futures.compat_coroutine import ( + coroutine, + coroutine_return, +) +from portage.tests import TestCase + + +class CompatCoroutineTestCase(TestCase): + + def test_returning_coroutine(self): + @coroutine + def returning_coroutine(): + yield asyncio.sleep(0) + coroutine_return('success') + + self.assertEqual('success', + asyncio.get_event_loop().run_until_complete(returning_coroutine())) + + def test_raising_coroutine(self): + + class TestException(Exception): + pass + + @coroutine + def raising_coroutine(): + yield asyncio.sleep(0) + raise TestException('exception') + + self.assertRaises(TestException, + asyncio.get_event_loop().run_until_complete, raising_coroutine()) + + def test_catching_coroutine(self): + + class TestException(Exception): + pass + + @coroutine + def catching_coroutine(loop=None): + loop = asyncio._wrap_loop(loop) + future = loop.create_future() + loop.call_soon(future.set_exception, TestException('exception')) + try: + yield future + except TestException: + self.assertTrue(True) + else: + self.assertTrue(False) + coroutine_return('success') + + loop = asyncio.get_event_loop() + self.assertEqual('success', + loop.run_until_complete(catching_coroutine(loop=loop))) + + def test_cancelled_coroutine(self): + + @coroutine + def cancelled_coroutine(loop=None): + loop = asyncio._wrap_loop(loop) + while True: + yield loop.create_future() + + loop = asyncio.get_event_loop() + future = cancelled_coroutine(loop=loop) + loop.call_soon(future.cancel) + + self.assertRaises(asyncio.CancelledError, + loop.run_until_complete, future) + + def test_cancelled_future(self): + + @coroutine + def cancelled_future_coroutine(loop=None): + loop = asyncio._wrap_loop(loop) + while True: + future = loop.create_future() + loop.call_soon(future.cancel) + yield future + + loop = asyncio.get_event_loop() + self.assertRaises(asyncio.CancelledError, + loop.run_until_complete, cancelled_future_coroutine(loop=loop)) + + def test_yield_expression_result(self): + @coroutine + def yield_expression_coroutine(): + for i in range(3): + x = yield asyncio.sleep(0, result=i) + self.assertEqual(x, i) + + asyncio.get_event_loop().run_until_complete(yield_expression_coroutine()) + + def test_method_coroutine(self): + + class Cubby(object): + +
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/sync/
commit: 82823b0c4de0a7cbb5654bb19d63aef874800afd Author: Zac Medico gentoo org> AuthorDate: Thu Jul 5 10:18:55 2018 + Commit: Zac Medico gentoo org> CommitDate: Thu Jul 5 10:19:23 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=82823b0c test_sync_local: fix GitSync coverage Fixes: 0655b4a26e37 ("test_sync_local: add test for auto-sync set to 'no'") pym/portage/tests/sync/test_sync_local.py | 15 +-- 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/pym/portage/tests/sync/test_sync_local.py b/pym/portage/tests/sync/test_sync_local.py index 010c8f887..17ff6f200 100644 --- a/pym/portage/tests/sync/test_sync_local.py +++ b/pym/portage/tests/sync/test_sync_local.py @@ -102,17 +102,20 @@ class SyncLocalTestCase(TestCase): os.unlink(os.path.join(metadata_dir, 'timestamp.chk')) sync_cmds = ( + (homedir, cmds["emerge"] + ("--sync",)), + (homedir, lambda: self.assertTrue(os.path.exists( + os.path.join(repo.location, "dev-libs", "A") + ), "dev-libs/A expected, but missing")), + (homedir, cmds["emaint"] + ("sync", "-A")), + ) + + sync_cmds_auto_sync = ( (homedir, lambda: repos_set_conf("rsync", auto_sync="no")), (homedir, cmds["emerge"] + ("--sync",)), (homedir, lambda: self.assertFalse(os.path.exists( os.path.join(repo.location, "dev-libs", "A") ), "dev-libs/A found, expected missing")), (homedir, lambda: repos_set_conf("rsync", auto_sync="yes")), - (homedir, cmds["emerge"] + ("--sync",)), - (homedir, lambda: self.assertTrue(os.path.exists( - os.path.join(repo.location, "dev-libs", "A") - ), "dev-libs/A expected, but missing")), - (homedir, cmds["emaint"] + ("sync", "-A")), ) rename_repo = ( @@ -236,7 +239,7 @@ class SyncLocalTestCase(TestCase): # triggered by python -Wd will be visible. stdout = subprocess.PIPE - for cwd, cmd in rename_repo + sync_cmds + \ + for cwd, cmd in rename_repo + sync_cmds_auto_sync + sync_cmds + \ rsync_opts_repos + rsync_opts_repos_default + \ rsync_opts_repos_default_ovr + rsync_opts_repos_default_cancel + \ delete_sync_repo + git_repo_create + sync_type_git + \
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/util/, pym/portage/util/
commit: deb87a465306d05146d7eb55d27d7d89943725c0 Author: Zac Medico gentoo org> AuthorDate: Sun Jun 24 21:42:52 2018 + Commit: Zac Medico gentoo org> CommitDate: Wed Jun 27 03:15:08 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=deb87a46 {,PKG_}INSTALL_MASK: support trailing slash (bug 658322) Fix the python INSTALL_MASK implementation so that a trailing slash matches a directory, for compatibility with the previous bash implementation. Fixes: 3416876c0ee7 ("{,PKG_}INSTALL_MASK: python implementation") Bug: https://bugs.gentoo.org/658322 pym/portage/tests/util/test_install_mask.py | 129 pym/portage/util/install_mask.py| 7 +- 2 files changed, 134 insertions(+), 2 deletions(-) diff --git a/pym/portage/tests/util/test_install_mask.py b/pym/portage/tests/util/test_install_mask.py new file mode 100644 index 0..f651eb4b7 --- /dev/null +++ b/pym/portage/tests/util/test_install_mask.py @@ -0,0 +1,129 @@ +# Copyright 2018 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +from portage.tests import TestCase +from portage.util.install_mask import InstallMask + + +class InstallMaskTestCase(TestCase): + + def testTrailingSlash(self): + """ + Test that elements with a trailing slash match a directory + but not a regular file. + """ + cases = ( + ( + '/foo/bar/ -/foo/bar/*.foo -*.baz', + ( + ( + 'foo/bar/baz', + True, + ), + ( + 'foo/bar/', + True, + ), + # /foo/bar/ does not match + ( + 'foo/bar', + False, + ), + # this is excluded + ( + 'foo/bar/baz.foo', + False, + ), + # this is excluded + ( + 'foo/bar/baz.baz', + False, + ), + ( + 'foo/bar/baz.bar', + True, + ), + ) + ), + ( + '/foo/bar -/foo/bar/*.foo -*.baz', + ( + ( + 'foo/bar/baz', + True, + ), + # /foo/bar matches both foo/bar/ and foo/bar + ( + 'foo/bar/', + True, + ), + ( + 'foo/bar', + True, + ), + # this is excluded + ( + 'foo/bar/baz.foo', + False, + ), + # this is excluded + ( + 'foo/bar/baz.baz', + False, + ), + ( + 'foo/bar/baz.bar', + True, + ), + ) + ), + ( + '/foo*', + ( + ( + 'foo', + True, + ), +
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/process/
commit: ac5b48b253add3007034f9fdad02779cd3972281 Author: Zac Medico gentoo org> AuthorDate: Sat May 26 22:38:58 2018 + Commit: Zac Medico gentoo org> CommitDate: Sat May 26 22:38:58 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=ac5b48b2 PipeReaderTestCase: wait for consumer pym/portage/tests/process/test_poll.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pym/portage/tests/process/test_poll.py b/pym/portage/tests/process/test_poll.py index d71c9b59c..f700a5585 100644 --- a/pym/portage/tests/process/test_poll.py +++ b/pym/portage/tests/process/test_poll.py @@ -78,6 +78,7 @@ class PipeReaderTestCase(TestCase): producer.start() os.close(slave_fd) producer.wait() + consumer.wait() self.assertEqual(producer.returncode, os.EX_OK) self.assertEqual(consumer.returncode, os.EX_OK)
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/process/
commit: 3b0c52b9ef364dc8e69208ec5341255ac94d41d8 Author: Zac Medico gentoo org> AuthorDate: Sat May 26 10:44:38 2018 + Commit: Zac Medico gentoo org> CommitDate: Sat May 26 10:44:38 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=3b0c52b9 PipeReaderTestCase: cover sockets and named pipes pym/portage/tests/process/test_poll.py | 74 ++ 1 file changed, 49 insertions(+), 25 deletions(-) diff --git a/pym/portage/tests/process/test_poll.py b/pym/portage/tests/process/test_poll.py index 596ea3088..d71c9b59c 100644 --- a/pym/portage/tests/process/test_poll.py +++ b/pym/portage/tests/process/test_poll.py @@ -1,11 +1,16 @@ -# Copyright 1998-2013 Gentoo Foundation +# Copyright 1998-2018 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 +import functools +import pty +import shutil +import socket +import sys import subprocess +import tempfile from portage import os from portage.tests import TestCase -from portage.util._pty import _create_pty_or_pipe from portage.util._async.PopenProcess import PopenProcess from portage.util._eventloop.global_event_loop import global_event_loop from _emerge.PipeReader import PipeReader @@ -13,28 +18,47 @@ from _emerge.PipeReader import PipeReader class PipeReaderTestCase(TestCase): _use_array = False - _use_pty = False _echo_cmd = "echo -n '%s'" - def _testPipeReader(self, test_string): + def test_pipe(self): + def make_pipes(): + return os.pipe(), None + self._do_test(make_pipes) + + def test_pty_device(self): + def make_pipes(): + try: + return pty.openpty(), None + except EnvironmentError: + self.skipTest('pty not available') + self._do_test(make_pipes) + + def test_domain_socket(self): + def make_pipes(): + if sys.version_info >= (3, 2): + read_end, write_end = socket.socketpair() + return (read_end.detach(), write_end.detach()), None + else: + self.skipTest('socket detach not supported') + self._do_test(make_pipes) + + def test_named_pipe(self): + def make_pipes(): + tempdir = tempfile.mkdtemp() + fifo_path = os.path.join(tempdir, 'fifo') + os.mkfifo(fifo_path) + return ((os.open(fifo_path, os.O_NONBLOCK|os.O_RDONLY), + os.open(fifo_path, os.O_NONBLOCK|os.O_WRONLY)), + functools.partial(shutil.rmtree, tempdir)) + self._do_test(make_pipes) + + def _testPipeReader(self, master_fd, slave_fd, test_string): """ Use a poll loop to read data from a pipe and assert that the data written to the pipe is identical to the data read from the pipe. """ - if self._use_pty: - got_pty, master_fd, slave_fd = _create_pty_or_pipe() - if not got_pty: - os.close(slave_fd) - os.close(master_fd) - skip_reason = "pty not acquired" - self.portage_skip = skip_reason - self.fail(skip_reason) - return - else: - master_fd, slave_fd = os.pipe() - # WARNING: It is very important to use unbuffered mode here, # in order to avoid issue 5380 with python3. master_file = os.fdopen(master_fd, 'rb', 0) @@ -60,15 +84,18 @@ class PipeReaderTestCase(TestCase): return consumer.getvalue().decode('ascii', 'replace') - def testPipeReader(self): + def _do_test(self, make_pipes): for x in (1, 2, 5, 6, 7, 8, 2**5, 2**10, 2**12, 2**13, 2**14): test_string = x * "a" - output = self._testPipeReader(test_string) - self.assertEqual(test_string, output, - "x = %s, len(output) = %s" % (x, len(output))) + (read_end, write_end), cleanup = make_pipes() + try: + output = self._testPipeReader(read_end, write_end, test_string) + self.assertEqual(test_string, output, + "x = %s, len(output) = %s" % (x, len(output))) + finally: + if cleanup is not None: + cleanup() -class
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/util/futures/asyncio/, pym/portage/util/_eventloop/
commit: adee194534f0b3d9762efd1e8e8713c316b93f5a Author: Zac Medico gentoo org> AuthorDate: Thu May 24 22:36:29 2018 + Commit: Zac Medico gentoo org> CommitDate: Fri May 25 02:01:27 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=adee1945 AsyncioEventLoop: suppress BlockingIOError warning (bug 655656) Override AbstractEventLoop.run_until_complete() to prevent BlockingIOError from occurring when the event loop is not running, by using signal.set_wakeup_fd(-1) to temporarily disable the wakeup fd. In order to avoid potential interference with API consumers, only modify wakeup fd when portage._interal_caller is True. Bug: https://bugs.gentoo.org/655656 .../util/futures/asyncio/test_wakeup_fd_sigchld.py | 76 ++ pym/portage/util/_eventloop/asyncio_event_loop.py | 37 +-- 2 files changed, 106 insertions(+), 7 deletions(-) diff --git a/pym/portage/tests/util/futures/asyncio/test_wakeup_fd_sigchld.py b/pym/portage/tests/util/futures/asyncio/test_wakeup_fd_sigchld.py new file mode 100644 index 0..abc67c241 --- /dev/null +++ b/pym/portage/tests/util/futures/asyncio/test_wakeup_fd_sigchld.py @@ -0,0 +1,76 @@ +# Copyright 2018 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +import os +import subprocess + +import portage +from portage.const import PORTAGE_PYM_PATH +from portage.tests import TestCase +from portage.util._eventloop.global_event_loop import _asyncio_enabled + + +class WakeupFdSigchldTestCase(TestCase): + def testWakeupFdSigchld(self): + """ + This is expected to trigger a bunch of messages like the following + unless the fix for bug 655656 works as intended: + + Exception ignored when trying to write to the signal wakeup fd: + BlockingIOError: [Errno 11] Resource temporarily unavailable + """ + if not _asyncio_enabled: + self.skipTest('asyncio not enabled') + + script = """ +import asyncio as _real_asyncio +import os +import signal +import sys + +import portage + +# In order to avoid potential interference with API consumers, wakeup +# fd handling is enabled only when portage._interal_caller is True. +portage._internal_caller = True + +from portage.util.futures import asyncio + +loop = asyncio._wrap_loop() + +# Cause the loop to register a child watcher. +proc = loop.run_until_complete(_real_asyncio.create_subprocess_exec('sleep', '0')) +loop.run_until_complete(proc.wait()) + +for i in range(8192): + os.kill(os.getpid(), signal.SIGCHLD) + +# Verify that the child watcher still works correctly +# (this will hang if it doesn't). +proc = loop.run_until_complete(_real_asyncio.create_subprocess_exec('sleep', '0')) +loop.run_until_complete(proc.wait()) +loop.close() +sys.stdout.write('success') +sys.exit(os.EX_OK) +""" + + pythonpath = os.environ.get('PYTHONPATH', '').strip().split(':') + if not pythonpath or pythonpath[0] != PORTAGE_PYM_PATH: + pythonpath = [PORTAGE_PYM_PATH] + pythonpath + pythonpath = ':'.join(filter(None, pythonpath)) + + proc = subprocess.Popen( + [portage._python_interpreter, '-c', script], + stdout=subprocess.PIPE, stderr=subprocess.STDOUT, + env=dict(os.environ, PYTHONPATH=pythonpath)) + + out, err = proc.communicate() + try: + self.assertEqual(out[:100], b'success') + except Exception: + portage.writemsg(''.join('{}\n'.format(line) + for line in out.decode(errors='replace').splitlines()[:50]), + noiselevel=-1) + raise + + self.assertEqual(proc.wait(), os.EX_OK) diff --git a/pym/portage/util/_eventloop/asyncio_event_loop.py b/pym/portage/util/_eventloop/asyncio_event_loop.py index bf5937de8..65b354544 100644 --- a/pym/portage/util/_eventloop/asyncio_event_loop.py +++ b/pym/portage/util/_eventloop/asyncio_event_loop.py @@ -1,6 +1,7 @@ # Copyright 2018 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 +import os import signal try: @@ -11,6 +12,8 @@ except ImportError: _real_asyncio = None _AbstractEventLoop = object +import portage + class AsyncioEventLoop(_AbstractEventLoop): """ @@ -26,13 +29,15 @@ class AsyncioEventLoop(_AbstractEventLoop): def __init__(self, loop=None): loop = loop or _real_asyncio.get_event_loop() self._loop = loop - self.run_until_complete = loop.run_until_complete + self.run_until_complete = (self._run_until_complete + if portage._internal_caller else loop.run_until_complete) self.call_soo
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/util/futures/asyncio/
commit: 3a55ecd1f79c31f477d7bdd0b9f0e97d8a15eb9e Author: Zac Medico gentoo org> AuthorDate: Wed May 9 14:19:11 2018 + Commit: Zac Medico gentoo org> CommitDate: Wed May 9 14:19:11 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=3a55ecd1 DefaultEventLoopPolicy: test NotImplementedError due to recursion .../asyncio/test_policy_wrapper_recursion.py | 29 ++ 1 file changed, 29 insertions(+) diff --git a/pym/portage/tests/util/futures/asyncio/test_policy_wrapper_recursion.py b/pym/portage/tests/util/futures/asyncio/test_policy_wrapper_recursion.py new file mode 100644 index 0..d3cd94b35 --- /dev/null +++ b/pym/portage/tests/util/futures/asyncio/test_policy_wrapper_recursion.py @@ -0,0 +1,29 @@ +# Copyright 2018 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +try: + import asyncio +except ImportError: + asyncio = None + +from portage.tests import TestCase +from portage.util.futures.unix_events import DefaultEventLoopPolicy + + +class PolicyWrapperRecursionTestCase(TestCase): + def testPolicyWrapperRecursion(self): + if asyncio is None: + self.skipTest('asyncio is not available') + + initial_policy = asyncio.get_event_loop_policy() + if not isinstance(initial_policy, DefaultEventLoopPolicy): + asyncio.set_event_loop_policy(DefaultEventLoopPolicy()) + + try: + with self.assertRaises(NotImplementedError): + asyncio.get_event_loop() + + with self.assertRaises(NotImplementedError): + asyncio.get_child_watcher() + finally: + asyncio.set_event_loop_policy(initial_policy)
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/util/futures/asyncio/
commit: 0c96d2d0b18036cb94d68c42783441d32af2d9d3 Author: Zac Medico gentoo org> AuthorDate: Wed May 9 07:54:26 2018 + Commit: Zac Medico gentoo org> CommitDate: Wed May 9 07:59:56 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=0c96d2d0 SubprocessExecTestCase: fix unintended skipTest The internal asyncio shim does not provide a create_subprocess_exec attribute, so access it directly from the real asyncio module. Fixes 82a3cda6f1ff ("Minimize _asyncio_wrapper usage (bug 654390)") .../util/futures/asyncio/test_subprocess_exec.py| 21 + 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/pym/portage/tests/util/futures/asyncio/test_subprocess_exec.py b/pym/portage/tests/util/futures/asyncio/test_subprocess_exec.py index 534d79c53..5a812ba6a 100644 --- a/pym/portage/tests/util/futures/asyncio/test_subprocess_exec.py +++ b/pym/portage/tests/util/futures/asyncio/test_subprocess_exec.py @@ -4,6 +4,11 @@ import os import subprocess +try: + from asyncio import create_subprocess_exec +except ImportError: + create_subprocess_exec = None + from portage.process import find_binary from portage.tests import TestCase from portage.util._eventloop.global_event_loop import global_event_loop @@ -71,7 +76,7 @@ class SubprocessExecTestCase(TestCase): self.assertFalse(global_event_loop().is_closed()) def testEcho(self): - if not hasattr(asyncio, 'create_subprocess_exec'): + if create_subprocess_exec is None: self.skipTest('create_subprocess_exec not implemented for python2') args_tuple = (b'hello', b'world') @@ -91,7 +96,7 @@ class SubprocessExecTestCase(TestCase): try: with open(os.devnull, 'rb', 0) as devnull: proc = loop.run_until_complete( - asyncio.create_subprocess_exec( + create_subprocess_exec( echo_binary, *args_tuple, stdin=devnull, stdout=stdout_pw, stderr=stdout_pw)) @@ -114,7 +119,7 @@ class SubprocessExecTestCase(TestCase): self._run_test(test) def testCat(self): - if not hasattr(asyncio, 'create_subprocess_exec'): + if create_subprocess_exec is None: self.skipTest('create_subprocess_exec not implemented for python2') stdin_data = b'hello world' @@ -138,7 +143,7 @@ class SubprocessExecTestCase(TestCase): output = None try: proc = loop.run_until_complete( - asyncio.create_subprocess_exec( + create_subprocess_exec( cat_binary, stdin=stdin_pr, stdout=stdout_pw, stderr=stdout_pw)) @@ -173,7 +178,7 @@ class SubprocessExecTestCase(TestCase): requires an AbstractEventLoop.connect_read_pipe implementation (and a ReadTransport implementation for it to return). """ - if not hasattr(asyncio, 'create_subprocess_exec'): + if create_subprocess_exec is None: self.skipTest('create_subprocess_exec not implemented for python2') args_tuple = (b'hello', b'world') @@ -184,7 +189,7 @@ class SubprocessExecTestCase(TestCase): def test(loop): with open(os.devnull, 'rb', 0) as devnull: proc = loop.run_until_complete( - asyncio.create_subprocess_exec( + create_subprocess_exec( echo_binary, *args_tuple, stdin=devnull, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) @@ -202,7 +207,7 @@ class SubprocessExecTestCase(TestCase): requires an AbstractEventLoop.connect_write_pipe implementation (and a WriteTransport implementation for it to return). """ - if not hasattr(asyncio, 'create_subprocess_exec'): + if create_subprocess_exec is None: self.skipTest('create_subprocess_exec not implemented for python2') stdin_data = b'hello world' @@ -212,7 +217,7 @@ class SubprocessExecTestCase(TestCase): def test(loop): proc = loop.run_until_complete( - asyncio.create_subprocess_exec( + create_subprocess_exec(
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/
commit: 299a9a40536209c4c2664857b5aecb018fa0a6f6 Author: Zac Medico gentoo org> AuthorDate: Sun May 6 23:40:33 2018 + Commit: Zac Medico gentoo org> CommitDate: Mon May 7 00:19:54 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=299a9a40 TestCase: handle SkipTest during setUp method pym/portage/tests/__init__.py | 20 ++-- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/pym/portage/tests/__init__.py b/pym/portage/tests/__init__.py index bf681c47e..e149b5c0c 100644 --- a/pym/portage/tests/__init__.py +++ b/pym/portage/tests/__init__.py @@ -207,18 +207,18 @@ class TestCase(unittest.TestCase): result.startTest(self) testMethod = getattr(self, self._testMethodName) try: - try: - self.setUp() - except SystemExit: - raise - except KeyboardInterrupt: - raise - except: - result.addError(self, sys.exc_info()) - return - ok = False try: + try: + self.setUp() + except KeyboardInterrupt: + raise + except SkipTest: + raise + except Exception: + result.addError(self, sys.exc_info()) + return + testMethod() ok = True except SkipTest as e:
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/util/futures/
commit: fefc6f1feb57503ce4826de1e405c12ef761c0ce Author: Zac Medico gentoo org> AuthorDate: Sun May 6 23:41:15 2018 + Commit: Zac Medico gentoo org> CommitDate: Mon May 7 00:19:54 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=fefc6f1f RetryTestCase: test ThreadPoolExecutor and ForkExecutor (bug 654390) ThreadPoolExecutor is the default asyncio event loop's default executor, so explicitly test it. Also explicitly test ForkExecutor, since it is more useful in cases where tasks may need to be forcefully cancelled. Bug: https://bugs.gentoo.org/654390 pym/portage/tests/util/futures/test_retry.py | 37 ++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/pym/portage/tests/util/futures/test_retry.py b/pym/portage/tests/util/futures/test_retry.py index baf293d56..16ecccbc7 100644 --- a/pym/portage/tests/util/futures/test_retry.py +++ b/pym/portage/tests/util/futures/test_retry.py @@ -1,16 +1,24 @@ # Copyright 2018 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 +try: + from concurrent.futures import ThreadPoolExecutor +except ImportError: + ThreadPoolExecutor = None + try: import threading except ImportError: import dummy_threading as threading +import sys + from portage.tests import TestCase from portage.util._eventloop.global_event_loop import global_event_loop from portage.util.backoff import RandomExponentialBackoff from portage.util.futures import asyncio from portage.util.futures.retry import retry +from portage.util.futures.executor.fork import ForkExecutor from portage.util.monotonic import monotonic @@ -155,13 +163,31 @@ class RetryTestCase(TestCase): self.assertTrue(isinstance(done.pop().exception().__cause__, asyncio.TimeoutError)) -class RetryExecutorTestCase(RetryTestCase): +class RetryForkExecutorTestCase(RetryTestCase): """ Wrap each coroutine function with AbstractEventLoop.run_in_executor, in order to test the event loop's default executor. The executor may use either a thread or a subprocess, and either case is automatically detected and handled. """ + def __init__(self, *pargs, **kwargs): + super(RetryForkExecutorTestCase, self).__init__(*pargs, **kwargs) + self._executor = None + + def _setUpExecutor(self): + self._executor = ForkExecutor() + + def _tearDownExecutor(self): + if self._executor is not None: + self._executor.shutdown(wait=True) + self._executor = None + + def setUp(self): + self._setUpExecutor() + + def tearDown(self): + self._tearDownExecutor() + def _wrap_coroutine_func(self, coroutine_func): parent_loop = global_event_loop() @@ -191,7 +217,7 @@ class RetryExecutorTestCase(RetryTestCase): def execute_wrapper(): kill_switch = parent_loop.create_future() parent_future = asyncio.ensure_future( - parent_loop.run_in_executor(None, wrapper, kill_switch), + parent_loop.run_in_executor(self._executor, wrapper, kill_switch), loop=parent_loop) parent_future.add_done_callback( lambda parent_future: None if kill_switch.done() @@ -199,3 +225,10 @@ class RetryExecutorTestCase(RetryTestCase): return parent_future return execute_wrapper + + +class RetryThreadExecutorTestCase(RetryForkExecutorTestCase): + def _setUpExecutor(self): + if sys.version_info.major < 3: + self.skipTest('ThreadPoolExecutor not supported for python2') + self._executor = ThreadPoolExecutor(max_workers=1)
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/util/futures/asyncio/
commit: 87aeab1a62cc6fa1d48354a42ec4fa787dbe9603 Author: Zac Medico gentoo org> AuthorDate: Sun May 6 01:19:08 2018 + Commit: Zac Medico gentoo org> CommitDate: Sun May 6 01:26:50 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=87aeab1a WriterPipeClosedTestCase: retry filling pipe This should suppress spurious writer callback observed twice for pypy in travis. See: https://travis-ci.org/gentoo/portage/jobs/375411936 See: https://travis-ci.org/gentoo/portage/jobs/373734825 .../tests/util/futures/asyncio/test_pipe_closed.py | 39 +- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/pym/portage/tests/util/futures/asyncio/test_pipe_closed.py b/pym/portage/tests/util/futures/asyncio/test_pipe_closed.py index 5398ca35c..e63829888 100644 --- a/pym/portage/tests/util/futures/asyncio/test_pipe_closed.py +++ b/pym/portage/tests/util/futures/asyncio/test_pipe_closed.py @@ -105,25 +105,32 @@ class WriterPipeClosedTestCase(_PipeClosedTestCase, TestCase): writer_callback.called = loop.create_future() _set_nonblocking(write_end.fileno()) + loop.add_writer(write_end.fileno(), writer_callback) - # Fill up the pipe, so that no writer callbacks should be - # received until the state has changed. - while True: - try: - os.write(write_end.fileno(), 512 * b'0') - except EnvironmentError as e: - if e.errno != errno.EAGAIN: - raise + # With pypy we've seen intermittent spurious writer callbacks + # here, so retry until the correct state is achieved. + tries = 10 + while tries: + tries -= 1 + + # Fill up the pipe, so that no writer callbacks should be + # received until the state has changed. + while True: + try: + os.write(write_end.fileno(), 512 * b'0') + except EnvironmentError as e: + if e.errno != errno.EAGAIN: + raise + break + + # Allow the loop to check for IO events, and assert + # that our future is still not done. + loop.run_until_complete(asyncio.sleep(0, loop=loop)) + if writer_callback.called.done(): + writer_callback.called = loop.create_future() + else: break - # We've seen at least one spurious writer callback when - # this was registered before the pipe was filled, so - # register it afterwards. - loop.add_writer(write_end.fileno(), writer_callback) - - # Allow the loop to check for IO events, and assert - # that our future is still not done. - loop.run_until_complete(asyncio.sleep(0, loop=loop)) self.assertFalse(writer_callback.called.done()) # Demonstrate that the callback is called afer the
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/util/futures/
commit: 5a5ed99cb5a6e8913df2e9ca29b4b4d5c179c20f Author: Zac Medico gentoo org> AuthorDate: Sat May 5 23:04:10 2018 + Commit: Zac Medico gentoo org> CommitDate: Sun May 6 00:35:44 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=5a5ed99c RetryTestCase: support ThreadPoolExecutor (bug 654390) In order to support the default asyncio event loop's ThreadPoolExecutor, use a threading.Event instance to support cancellation of tasks. Bug: https://bugs.gentoo.org/654390 pym/portage/tests/util/futures/test_retry.py | 96 +--- 1 file changed, 74 insertions(+), 22 deletions(-) diff --git a/pym/portage/tests/util/futures/test_retry.py b/pym/portage/tests/util/futures/test_retry.py index cdca7d294..781eac9a1 100644 --- a/pym/portage/tests/util/futures/test_retry.py +++ b/pym/portage/tests/util/futures/test_retry.py @@ -1,8 +1,6 @@ # Copyright 2018 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 -import functools - try: import threading except ImportError: @@ -28,10 +26,17 @@ class SucceedLater(object): self._succeed_time = monotonic() + duration def __call__(self): + loop = global_event_loop() + result = loop.create_future() remaining = self._succeed_time - monotonic() if remaining > 0: - raise SucceedLaterException('time until success: {} seconds'.format(remaining)) - return 'success' + loop.call_soon_threadsafe(lambda: None if result.done() else + result.set_exception(SucceedLaterException( + 'time until success: {} seconds'.format(remaining + else: + loop.call_soon_threadsafe(lambda: None if result.done() else + result.set_result('success')) + return result class SucceedNeverException(Exception): @@ -43,7 +48,11 @@ class SucceedNever(object): A callable object that never succeeds. """ def __call__(self): - raise SucceedNeverException('expected failure') + loop = global_event_loop() + result = loop.create_future() + loop.call_soon_threadsafe(lambda: None if result.done() else + result.set_exception(SucceedNeverException('expected failure'))) + return result class HangForever(object): @@ -51,14 +60,21 @@ class HangForever(object): A callable object that sleeps forever. """ def __call__(self): - threading.Event().wait() + return global_event_loop().create_future() class RetryTestCase(TestCase): + + def _wrap_coroutine_func(self, coroutine_func): + """ + Derived classes may override this method in order to implement + alternative forms of execution. + """ + return coroutine_func + def testSucceedLater(self): loop = global_event_loop() - func = SucceedLater(1) - func_coroutine = functools.partial(loop.run_in_executor, None, func) + func_coroutine = self._wrap_coroutine_func(SucceedLater(1)) decorator = retry(try_max=, delay_func=RandomExponentialBackoff(multiplier=0.1, base=2)) decorated_func = decorator(func_coroutine) @@ -67,8 +83,7 @@ class RetryTestCase(TestCase): def testSucceedNever(self): loop = global_event_loop() - func = SucceedNever() - func_coroutine = functools.partial(loop.run_in_executor, None, func) + func_coroutine = self._wrap_coroutine_func(SucceedNever()) decorator = retry(try_max=4, try_timeout=None, delay_func=RandomExponentialBackoff(multiplier=0.1, base=2)) decorated_func = decorator(func_coroutine) @@ -78,8 +93,7 @@ class RetryTestCase(TestCase): def testSucceedNeverReraise(self): loop = global_event_loop() - func = SucceedNever() - func_coroutine = functools.partial(loop.run_in_executor, None, func) + func_coroutine = self._wrap_coroutine_func(SucceedNever()) decorator = retry(reraise=True, try_max=4, try_timeout=None, delay_func=RandomExponentialBackoff(multiplier=0.1, base=2)) decorated_func = decorator(func_coroutine) @@ -89,8 +103,7 @@ class RetryTestCase(TestCase): def testHangForever(self): loop = global_event_loop() - func = HangForever() - func_coroutine = functools.partial(loop.run_in_executor, None, func) + func_coroutine = self._wrap_coroutine_func(HangForever())
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/resolver/, pym/_emerge/
commit: ce150da22e351a7ba52a6390b9cb7aa076c0c8ce Author: Zac Medico gentoo org> AuthorDate: Fri May 4 03:21:40 2018 + Commit: Zac Medico gentoo org> CommitDate: Fri May 4 17:11:07 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=ce150da2 depgraph.autounmask_breakage_detected: ignore REQUIRED_USE violations (bug 654782) When autounmask USE changes violate REQUIRED_USE, rather than recalculate with autounmask disabled, display the autounmask USE changes along with the REQUIRED_USE violation. Adjust unit tests to allow for the autounmask USE changes that were previously discarded. For the case reported in bug 654782, the output will appear as follows: The following keyword changes are necessary to proceed: (see "package.accept_keywords" in the portage(5) man page for more details) # required by =retext-7.0.1-r1 (argument) =app-editors/retext-7.0.1-r1 ~amd64 The following USE changes are necessary to proceed: (see "package.use" in the portage(5) man page for more details) # required by app-editors/retext-7.0.1-r1::gentoo # required by =retext-7.0.1-r1 (argument) >=dev-python/PyQt5-5.9.2 printsupport webengine network gui widgets !!! The ebuild selected to satisfy "dev-python/PyQt5[gui,network,printsupport,webengine,widgets,python_targets_python3_4(-)?,python_targets_python3_5(-)?,python_targets_python3_6(-)?,-python_single_target_python3_4(-),-python_single_target_python3_5(-),-python_single_target_python3_6(-)]" has unmet requirements. - dev-python/PyQt5-5.9.2::gentoo USE="-bluetooth -dbus -debug -declarative -designer -examples -gles2 -gui -help -location -multimedia -network -opengl -positioning -printsupport -sensors -serialport -sql -svg -testlib -webchannel -webengine -webkit -websockets -widgets -x11extras -xmlpatterns" PYTHON_TARGETS="python2_7 python3_4 python3_6 -python3_5" The following REQUIRED_USE flag constraints are unsatisfied: webengine? ( widgets? ( webchannel ) ) The above constraints are a subset of the following complete expression: any-of ( python_targets_python2_7 python_targets_python3_4 python_targets_python3_5 python_targets_python3_6 ) bluetooth? ( gui ) declarative? ( gui network ) designer? ( widgets ) help? ( gui widgets ) location? ( positioning ) multimedia? ( gui network ) opengl? ( gui widgets ) positioning? ( gui ) printsupport? ( gui widgets ) sensors? ( gui ) serialport? ( gui ) sql? ( widgets ) svg? ( gui widgets ) testlib? ( widgets ) webchannel? ( network ) webengine? ( network widgets? ( printsupport webchannel ) ) webkit? ( gui network printsupport widgets ) websockets? ( network ) widgets? ( gui ) xmlpatterns? ( network ) (dependency required by "app-editors/retext-7.0.1-r1::gentoo" [ebuild]) (dependency required by "=retext-7.0.1-r1" [argument]) Bug: https://bugs.gentoo.org/654782 Reviewed-by: M. J. Everitt iee.org> pym/_emerge/depgraph.py| 8 ++-- pym/portage/tests/resolver/test_autounmask.py | 48 -- pym/portage/tests/resolver/test_slot_collisions.py | 20 + 3 files changed, 61 insertions(+), 15 deletions(-) diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py index fbd16ad98..429d8871c 100644 --- a/pym/_emerge/depgraph.py +++ b/pym/_emerge/depgraph.py @@ -3009,6 +3009,10 @@ class depgraph(object): {"myparent" : dep.parent, "show_req_use" : pkg})) self._dynamic_config._required_use_unsatisfied = True self._dynamic_config._skip_restart = True + # Add pkg to digraph in order to enable autounmask messages + # for this package, which is useful when autounmask USE + # changes have violated REQUIRED_USE. + self._dynamic_config.digraph.add(pkg, dep.parent, priority=priority) return 0 if not pkg.onlydeps: @@ -9428,10 +9432,6 @@ class depgraph(object): return self._dynamic_config._need_config_reload def autounmask_breakage_detected(self): - # Check for REQUIRED_USE violations. - for changes in self._dynamic_config._needed_use_config_changes.values(): - if getattr(changes, 'required_use_satisfied', None) is False: - return True try: for pargs, kwargs in self._dynamic_config._unsatisfied_deps_for_display: self._show_unsatisfied_dep( diff --git a/pym/portage/tests/resolver/test_autounmask.py b/pym/portage/tests/resolver/test_autounmask.py index 9042349ea..809d42104 100644 --- a/pym/portage/tests/resolver/test_autounmask.py +++ b/pym/portage/tests/resolver/test_autounmask.py @@ -251,15 +251,42 @@ class AutounmaskTestCase(TestCase):
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/util/futures/asyncio/
commit: 10253819aae4cefee80f377e167ad521516d66a2 Author: Zac Medico gentoo org> AuthorDate: Thu May 3 01:18:39 2018 + Commit: Zac Medico gentoo org> CommitDate: Thu May 3 01:18:39 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=10253819 WriterPipeClosedTestCase: add_writer after pipe is filled Hopefully this supresses a spurious writer callback observed once for pypy in travis. See: https://travis-ci.org/gentoo/portage/jobs/373734825 pym/portage/tests/util/futures/asyncio/test_pipe_closed.py | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pym/portage/tests/util/futures/asyncio/test_pipe_closed.py b/pym/portage/tests/util/futures/asyncio/test_pipe_closed.py index 1ecddab78..5398ca35c 100644 --- a/pym/portage/tests/util/futures/asyncio/test_pipe_closed.py +++ b/pym/portage/tests/util/futures/asyncio/test_pipe_closed.py @@ -105,7 +105,6 @@ class WriterPipeClosedTestCase(_PipeClosedTestCase, TestCase): writer_callback.called = loop.create_future() _set_nonblocking(write_end.fileno()) - loop.add_writer(write_end.fileno(), writer_callback) # Fill up the pipe, so that no writer callbacks should be # received until the state has changed. @@ -117,6 +116,11 @@ class WriterPipeClosedTestCase(_PipeClosedTestCase, TestCase): raise break + # We've seen at least one spurious writer callback when + # this was registered before the pipe was filled, so + # register it afterwards. + loop.add_writer(write_end.fileno(), writer_callback) + # Allow the loop to check for IO events, and assert # that our future is still not done. loop.run_until_complete(asyncio.sleep(0, loop=loop))
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/emerge/, bin/
commit: 4bda6c546aab816e835f62b326db9c2215e182ac Author: Zac Medico gentoo org> AuthorDate: Tue May 1 23:37:33 2018 + Commit: Zac Medico gentoo org> CommitDate: Tue May 1 23:49:44 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=4bda6c54 Revert "phase-helpers.sh: fix best/has_version -b for cross-prefix" This reverts commit a0ac6e6727abec8d2482c95b1e84d8df24d78619, since BROOT is only supposed to be set in src_* phases. Update SimpleEmergeTestCase to call best/has_version -b only in src_install for EAPI 7. Reported-by: James Le Cuirot gentoo.org> bin/phase-helpers.sh| 2 +- pym/portage/tests/emerge/test_simple.py | 23 --- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/bin/phase-helpers.sh b/bin/phase-helpers.sh index 8b16d7d31..59c19cf67 100644 --- a/bin/phase-helpers.sh +++ b/bin/phase-helpers.sh @@ -912,7 +912,7 @@ ___best_version_and_has_version_common() { case ${root_arg} in -r) root=${EROOT} ;; -d) root=${ESYSROOT} ;; - -b) root=${BROOT:-/${PORTAGE_OVERRIDE_EPREFIX#/}} ;; + -b) root=${BROOT:-/} ;; esac else case ${root_arg} in diff --git a/pym/portage/tests/emerge/test_simple.py b/pym/portage/tests/emerge/test_simple.py index 204c23296..b1402ddd5 100644 --- a/pym/portage/tests/emerge/test_simple.py +++ b/pym/portage/tests/emerge/test_simple.py @@ -58,6 +58,8 @@ src_install() { echo "blah blah blah" > "${T}"/latin-1-$(printf "\\xa9")-regular-file || die doins "${T}"/latin-1-$(printf "\\xa9")-regular-file dosym latin-1-$(printf "\\xa9")-regular-file ${latin_1_dir}/latin-1-$(printf "\\xa9")-symlink || die + + call_has_and_best_version } pkg_config() { @@ -69,14 +71,29 @@ pkg_info() { } pkg_preinst() { + if ! ___eapi_best_version_and_has_version_support_-b_-d_-r; then + # The BROOT variable is unset during pkg_* phases for EAPI 7, + # therefore best/has_version -b is expected to fail if we attempt + # to call it for EAPI 7 here. + call_has_and_best_version + fi +} + +call_has_and_best_version() { local root_arg if ___eapi_best_version_and_has_version_support_-b_-d_-r; then root_arg="-b" else root_arg="--host-root" fi - einfo "called pkg_preinst for $CATEGORY/$PF" - + einfo "called ${EBUILD_PHASE_FUNC} for $CATEGORY/$PF" + einfo "EPREFIX=${EPREFIX}" + einfo "PORTAGE_OVERRIDE_EPREFIX=${PORTAGE_OVERRIDE_EPREFIX}" + einfo "ROOT=${ROOT}" + einfo "EROOT=${EROOT}" + einfo "SYSROOT=${SYSROOT}" + einfo "ESYSROOT=${ESYSROOT}" + einfo "BROOT=${BROOT}" # Test that has_version and best_version work correctly with # prefix (involves internal ROOT -> EROOT calculation in order # to support ROOT override via the environment with EAPIs 3 @@ -90,7 +107,7 @@ pkg_preinst() { if [[ ${EPREFIX} != ${PORTAGE_OVERRIDE_EPREFIX} ]] ; then if has_version ${root_arg} $CATEGORY/$PN:$SLOT ; then einfo "has_version ${root_arg} detects an installed instance of $CATEGORY/$PN:$SLOT" - einfo "best_version ${root_arg} reports that the installed instance is $(best_version $CATEGORY/$PN:$SLOT)" + einfo "best_version ${root_arg} reports that the installed instance is $(best_version ${root_arg} $CATEGORY/$PN:$SLOT)" else einfo "has_version ${root_arg} does not detect an installed instance of $CATEGORY/$PN:$SLOT" fi
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/emerge/, pym/portage/tests/resolver/, pym/portage/
commit: 75d6df1a2988ba440feed3db02550b62ebe0c204 Author: Zac Medico gentoo org> AuthorDate: Tue May 1 18:18:49 2018 + Commit: Zac Medico gentoo org> CommitDate: Tue May 1 18:22:45 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=75d6df1a Enable EAPI 7 (bug 654472) Bug: https://bugs.gentoo.org/654472 pym/portage/__init__.py | 2 +- pym/portage/const.py| 2 +- pym/portage/tests/emerge/test_simple.py | 6 +++--- pym/portage/tests/resolver/test_eapi.py | 2 +- pym/portage/tests/resolver/test_required_use.py | 6 +++--- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pym/portage/__init__.py b/pym/portage/__init__.py index 15c404f6f..166bfc700 100644 --- a/pym/portage/__init__.py +++ b/pym/portage/__init__.py @@ -462,7 +462,7 @@ def abssymlink(symlink, target=None): _doebuild_manifest_exempt_depend = 0 -_testing_eapis = frozenset(["4-python", "4-slot-abi", "5-progress", "5-hdepend", "7_pre1"]) +_testing_eapis = frozenset(["4-python", "4-slot-abi", "5-progress", "5-hdepend", "7_pre1", "7"]) _deprecated_eapis = frozenset(["4_pre1", "3_pre2", "3_pre1", "5_pre1", "5_pre2", "6_pre1"]) _supported_eapis = frozenset([str(x) for x in range(portage.const.EAPI + 1)] + list(_testing_eapis) + list(_deprecated_eapis)) diff --git a/pym/portage/const.py b/pym/portage/const.py index 16922a5e6..7f84bf0e9 100644 --- a/pym/portage/const.py +++ b/pym/portage/const.py @@ -204,7 +204,7 @@ SUPPORTED_FEATURES = frozenset([ "xattr", ]) -EAPI = 6 +EAPI = 7 HASHING_BLOCKSIZE= 32768 diff --git a/pym/portage/tests/emerge/test_simple.py b/pym/portage/tests/emerge/test_simple.py index 495e22297..204c23296 100644 --- a/pym/portage/tests/emerge/test_simple.py +++ b/pym/portage/tests/emerge/test_simple.py @@ -1,4 +1,4 @@ -# Copyright 2011-2015 Gentoo Foundation +# Copyright 2011-2018 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 import subprocess @@ -116,13 +116,13 @@ pkg_preinst() { "MISC_CONTENT": install_something, }, "dev-libs/C-1": { - "EAPI" : "7_pre1", + "EAPI" : "7", "KEYWORDS": "~x86", "RDEPEND": "dev-libs/D[flag]", "MISC_CONTENT": install_something, }, "dev-libs/D-1": { - "EAPI" : "7_pre1", + "EAPI" : "7", "KEYWORDS": "~x86", "IUSE" : "flag", "MISC_CONTENT": install_something, diff --git a/pym/portage/tests/resolver/test_eapi.py b/pym/portage/tests/resolver/test_eapi.py index fce05890b..50b9d90da 100644 --- a/pym/portage/tests/resolver/test_eapi.py +++ b/pym/portage/tests/resolver/test_eapi.py @@ -62,7 +62,7 @@ class EAPITestCase(TestCase): #EAPI-7: implicit || ( ) no longer satisfies deps "dev-libs/C-1": { "EAPI": "6", "IUSE": "foo", "RDEPEND": "|| ( foo? ( dev-libs/B ) )" }, - "dev-libs/C-2": { "EAPI": "7_pre1", "IUSE": "foo", "RDEPEND": "|| ( foo? ( dev-libs/B ) )" }, + "dev-libs/C-2": { "EAPI": "7", "IUSE": "foo", "RDEPEND": "|| ( foo? ( dev-libs/B ) )" }, } test_cases = ( diff --git a/pym/portage/tests/resolver/test_required_use.py b/pym/portage/tests/resolver/test_required_use.py index 7909f927f..c679ce300 100644 --- a/pym/portage/tests/resolver/test_required_use.py +++ b/pym/portage/tests/resolver/test_required_use.py @@ -51,9 +51,9 @@ class RequiredUSETestCase(TestCase): "dev-libs/E-4" : {"EAPI": "5", "IUSE": "+foo +bar", "REQUIRED_USE": "?? ( foo bar )"}, "dev-libs/E-5" : {"EAPI": "5", "IUSE": "+foo +bar", "REQUIRED_USE": "?? ( )"}, - "dev-libs/F-1" : {"EAPI": "7_pre1", "IUSE": "+foo +bar", "REQUIRED_USE": "|| ( )"}, - "dev-libs/F-2" : {"EAPI": "7_pre1", "IUSE": "+foo +bar", "REQUIRED_USE": "^^ ( )"}, - "dev-libs/F-3" : {"EAPI": "7_pre1", "IUSE": "+foo +bar", "REQUIRED_USE": "?? ( )"}, + "dev-libs/F-1" : {"EAPI": "7", "IUSE": "+foo +bar", "REQUIRED_USE": "|| ( )"}, + "dev-libs/F-2" : {"EAPI": "7", "IUSE": "+foo +bar", "REQUIRED_USE": "^^ ( )"}, + "dev-libs/F-3" : {"EAPI": "7", "IUSE": "+foo +bar", "REQUIRED_USE": "?? ( )"}, } test_cases = (
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/emerge/, bin/
commit: a0ac6e6727abec8d2482c95b1e84d8df24d78619 Author: Zac Medico gentoo org> AuthorDate: Tue May 1 18:14:07 2018 + Commit: Zac Medico gentoo org> CommitDate: Tue May 1 18:15:47 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=a0ac6e67 phase-helpers.sh: fix best/has_version -b for cross-prefix Fixes: 43b6be7423aa ("phase-helpers.sh: Implement -r|-d|-b options for best/has_version") bin/phase-helpers.sh| 2 +- pym/portage/tests/emerge/test_simple.py | 12 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/bin/phase-helpers.sh b/bin/phase-helpers.sh index 59c19cf67..8b16d7d31 100644 --- a/bin/phase-helpers.sh +++ b/bin/phase-helpers.sh @@ -912,7 +912,7 @@ ___best_version_and_has_version_common() { case ${root_arg} in -r) root=${EROOT} ;; -d) root=${ESYSROOT} ;; - -b) root=${BROOT:-/} ;; + -b) root=${BROOT:-/${PORTAGE_OVERRIDE_EPREFIX#/}} ;; esac else case ${root_arg} in diff --git a/pym/portage/tests/emerge/test_simple.py b/pym/portage/tests/emerge/test_simple.py index 17dcd548d..495e22297 100644 --- a/pym/portage/tests/emerge/test_simple.py +++ b/pym/portage/tests/emerge/test_simple.py @@ -119,11 +119,13 @@ pkg_preinst() { "EAPI" : "7_pre1", "KEYWORDS": "~x86", "RDEPEND": "dev-libs/D[flag]", + "MISC_CONTENT": install_something, }, "dev-libs/D-1": { "EAPI" : "7_pre1", "KEYWORDS": "~x86", "IUSE" : "flag", + "MISC_CONTENT": install_something, }, "virtual/foo-0": { "EAPI" : "5", @@ -326,6 +328,16 @@ pkg_preinst() { portageq_cmd + ("match", eroot, "dev-libs/D[flag]"), # Test cross-prefix usage, including chpathtool for binpkgs. + # EAPI 7 + ({"EPREFIX" : cross_prefix},) + \ + emerge_cmd + ("dev-libs/C",), + ({"EPREFIX" : cross_prefix},) + \ + portageq_cmd + ("has_version", cross_prefix, "dev-libs/C"), + ({"EPREFIX" : cross_prefix},) + \ + portageq_cmd + ("has_version", cross_prefix, "dev-libs/D"), + ({"ROOT": cross_root},) + emerge_cmd + ("dev-libs/D",), + portageq_cmd + ("has_version", cross_eroot, "dev-libs/D"), + # EAPI 5 ({"EPREFIX" : cross_prefix},) + \ emerge_cmd + ("--usepkgonly", "dev-libs/A"), ({"EPREFIX" : cross_prefix},) + \
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/emerge/
commit: 844998daa50e9db0a337bc0cf9f665d224779665 Author: Zac Medico gentoo org> AuthorDate: Tue May 1 17:49:07 2018 + Commit: Zac Medico gentoo org> CommitDate: Tue May 1 17:52:02 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=844998da SimpleEmergeTestCase: EAPI 7_pre1 has/best_version -b pym/portage/tests/emerge/test_simple.py | 18 -- 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/pym/portage/tests/emerge/test_simple.py b/pym/portage/tests/emerge/test_simple.py index f99c77927..17dcd548d 100644 --- a/pym/portage/tests/emerge/test_simple.py +++ b/pym/portage/tests/emerge/test_simple.py @@ -69,6 +69,12 @@ pkg_info() { } pkg_preinst() { + local root_arg + if ___eapi_best_version_and_has_version_support_-b_-d_-r; then + root_arg="-b" + else + root_arg="--host-root" + fi einfo "called pkg_preinst for $CATEGORY/$PF" # Test that has_version and best_version work correctly with @@ -82,11 +88,11 @@ pkg_preinst() { einfo "has_version does not detect an installed instance of $CATEGORY/$PN:$SLOT" fi if [[ ${EPREFIX} != ${PORTAGE_OVERRIDE_EPREFIX} ]] ; then - if has_version --host-root $CATEGORY/$PN:$SLOT ; then - einfo "has_version --host-root detects an installed instance of $CATEGORY/$PN:$SLOT" - einfo "best_version --host-root reports that the installed instance is $(best_version $CATEGORY/$PN:$SLOT)" + if has_version ${root_arg} $CATEGORY/$PN:$SLOT ; then + einfo "has_version ${root_arg} detects an installed instance of $CATEGORY/$PN:$SLOT" + einfo "best_version ${root_arg} reports that the installed instance is $(best_version $CATEGORY/$PN:$SLOT)" else - einfo "has_version --host-root does not detect an installed instance of $CATEGORY/$PN:$SLOT" + einfo "has_version ${root_arg} does not detect an installed instance of $CATEGORY/$PN:$SLOT" fi fi } @@ -110,12 +116,12 @@ pkg_preinst() { "MISC_CONTENT": install_something, }, "dev-libs/C-1": { - "EAPI" : "6", + "EAPI" : "7_pre1", "KEYWORDS": "~x86", "RDEPEND": "dev-libs/D[flag]", }, "dev-libs/D-1": { - "EAPI" : "6", + "EAPI" : "7_pre1", "KEYWORDS": "~x86", "IUSE" : "flag", },
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/util/futures/, pym/portage/dbapi/, pym/portage/util/futures/, ...
commit: 90d78484d6be481a9caf22c017c62ea43f8ffe33 Author: Zac Medico gentoo org> AuthorDate: Tue May 1 06:22:10 2018 + Commit: Zac Medico gentoo org> CommitDate: Tue May 1 06:46:27 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=90d78484 _PortageEventLoop: add _asyncio_* properties for internal use It's better to avoid accessing the _PortageEventLoop._loop attribute which exposes *all* EventLoop methods, therefore expose _asyncio_child_watcher and _asyncio_wrapper attributes for use by portage internals, providing minimal compatibility between _PortageEventloop and EventLoop. pym/portage/dbapi/porttree.py | 2 +- .../util/futures/asyncio/test_subprocess_exec.py | 2 +- .../tests/util/futures/test_iter_completed.py | 2 +- pym/portage/util/futures/executor/fork.py | 2 +- pym/portage/util/futures/iter_completed.py | 2 +- pym/portage/util/futures/unix_events.py| 22 ++ 6 files changed, 27 insertions(+), 5 deletions(-) diff --git a/pym/portage/dbapi/porttree.py b/pym/portage/dbapi/porttree.py index 3ce214cd7..6c38232bb 100644 --- a/pym/portage/dbapi/porttree.py +++ b/pym/portage/dbapi/porttree.py @@ -667,7 +667,7 @@ class portdbapi(dbapi): proc = EbuildMetadataPhase(cpv=mycpv, ebuild_hash=ebuild_hash, portdb=self, - repo_path=mylocation, scheduler=loop._loop, + repo_path=mylocation, scheduler=loop, settings=self.doebuild_settings) proc.addExitListener(functools.partial(self._aux_get_return, diff --git a/pym/portage/tests/util/futures/asyncio/test_subprocess_exec.py b/pym/portage/tests/util/futures/asyncio/test_subprocess_exec.py index 8c8c395ca..be103a9e0 100644 --- a/pym/portage/tests/util/futures/asyncio/test_subprocess_exec.py +++ b/pym/portage/tests/util/futures/asyncio/test_subprocess_exec.py @@ -34,7 +34,7 @@ class _Reader(object): def __init__(self, future, input_file, loop): self._future = future self._pipe_reader = PipeReader( - input_files={'input_file':input_file}, scheduler=loop._loop) + input_files={'input_file':input_file}, scheduler=loop) self._future.add_done_callback(self._cancel_callback) self._pipe_reader.addExitListener(self._eof) diff --git a/pym/portage/tests/util/futures/test_iter_completed.py b/pym/portage/tests/util/futures/test_iter_completed.py index 71343c22d..90668eb02 100644 --- a/pym/portage/tests/util/futures/test_iter_completed.py +++ b/pym/portage/tests/util/futures/test_iter_completed.py @@ -46,7 +46,7 @@ class IterCompletedTestCase(TestCase): def future_generator(): for task in tasks: task.future = loop.create_future() - task.scheduler = loop._loop + task.scheduler = loop task.start() yield task.future diff --git a/pym/portage/util/futures/executor/fork.py b/pym/portage/util/futures/executor/fork.py index 51367f934..81c292e2c 100644 --- a/pym/portage/util/futures/executor/fork.py +++ b/pym/portage/util/futures/executor/fork.py @@ -54,7 +54,7 @@ class ForkExecutor(object): future, proc = self._submit_queue.popleft() future.add_done_callback(functools.partial(self._cancel_cb, proc)) proc.addExitListener(functools.partial(self._proc_exit, future)) - proc.scheduler = self._loop._loop + proc.scheduler = self._loop proc.start() self._running_tasks[id(proc)] = proc diff --git a/pym/portage/util/futures/iter_completed.py b/pym/portage/util/futures/iter_completed.py index 1d6a9a4bd..8b0f417d9 100644 --- a/pym/portage/util/futures/iter_completed.py +++ b/pym/portage/util/futures/iter_completed.py @@ -77,7 +77,7 @@ def async_iter_completed(futures, max_jobs=None, max_load=None, loop=None): task_generator(), max_jobs=max_jobs, max_load=max_load, - event_loop=loop._loop) + event_loop=loop) def done_callback(future_done_set, wait_result): """Propagate results from wait_result to future_done_set.""" diff --git a/pym/portage/util/futures/unix_events.py b/pym/portage/util/futures/unix_events.py index 1a86ed439..00f522b61 100644 --- a/pym/portage/util/futures/unix_events.py +++ b/pym/portage/util/futures/unix_events.py @@ -72,6 +72,28 @@ class _PortageEventLoop(events.AbstractEventLoop): self.set_debug = loop.set_debug self.get_debug = loop.get_debug + @property + def _asyncio_child_watcher(self): +
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/util/futures/asyncio/, pym/portage/util/_eventloop/
commit: c77afbc31fa687cc612a6f946b324bf4d74d8175 Author: Zac Medico gentoo org> AuthorDate: Mon Apr 30 01:49:18 2018 + Commit: Zac Medico gentoo org> CommitDate: Mon Apr 30 02:14:41 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=c77afbc3 EventLoop: call add_reader/writer callbacks after pipe is closed (bug 654382) Callbacks registered via add_reader/writer methods need to be called when the other end of a pipe is closed, which does not result in a normal read or write event. Therefore, respond to other event types as well, for compatibility with the asyncio event loop implementation. The included unit tests demonstrate asyncio compatible behavior for both reader and writer callbacks. Bug: https://bugs.gentoo.org/654382 .../tests/util/futures/asyncio/test_pipe_closed.py | 133 + pym/portage/util/_eventloop/EventLoop.py | 7 +- 2 files changed, 138 insertions(+), 2 deletions(-) diff --git a/pym/portage/tests/util/futures/asyncio/test_pipe_closed.py b/pym/portage/tests/util/futures/asyncio/test_pipe_closed.py new file mode 100644 index 0..1ecddab78 --- /dev/null +++ b/pym/portage/tests/util/futures/asyncio/test_pipe_closed.py @@ -0,0 +1,133 @@ +# Copyright 2018 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +import errno +import os +import pty +import shutil +import socket +import sys +import tempfile + +from portage.tests import TestCase +from portage.util.futures import asyncio +from portage.util.futures.unix_events import ( + DefaultEventLoopPolicy, + _set_nonblocking, +) + + +class _PipeClosedTestCase(object): + + def test_pipe(self): + read_end, write_end = os.pipe() + self._do_test(read_end, write_end) + + def test_pty_device(self): + try: + read_end, write_end = pty.openpty() + except EnvironmentError: + self.skipTest('pty not available') + self._do_test(read_end, write_end) + + def test_domain_socket(self): + if sys.version_info >= (3, 2): + read_end, write_end = socket.socketpair() + else: + self.skipTest('socket detach not supported') + self._do_test(read_end.detach(), write_end.detach()) + + def test_named_pipe(self): + tempdir = tempfile.mkdtemp() + try: + fifo_path = os.path.join(tempdir, 'fifo') + os.mkfifo(fifo_path) + self._do_test(os.open(fifo_path, os.O_NONBLOCK|os.O_RDONLY), + os.open(fifo_path, os.O_NONBLOCK|os.O_WRONLY)) + finally: + shutil.rmtree(tempdir) + + +class ReaderPipeClosedTestCase(_PipeClosedTestCase, TestCase): + """ + Test that a reader callback is called after the other end of + the pipe has been closed. + """ + def _do_test(self, read_end, write_end): + initial_policy = asyncio.get_event_loop_policy() + if not isinstance(initial_policy, DefaultEventLoopPolicy): + asyncio.set_event_loop_policy(DefaultEventLoopPolicy()) + + loop = asyncio.get_event_loop() + read_end = os.fdopen(read_end, 'rb', 0) + write_end = os.fdopen(write_end, 'wb', 0) + try: + def reader_callback(): + if not reader_callback.called.done(): + reader_callback.called.set_result(None) + + reader_callback.called = loop.create_future() + loop.add_reader(read_end.fileno(), reader_callback) + + # Allow the loop to check for IO events, and assert + # that our future is still not done. + loop.run_until_complete(asyncio.sleep(0, loop=loop)) + self.assertFalse(reader_callback.called.done()) + + # Demonstrate that the callback is called afer the + # other end of the pipe has been closed. + write_end.close() + loop.run_until_complete(reader_callback.called) + finally: + loop.remove_reader(read_end.fileno()) + write_end.close() + read_end.close() + asyncio.set_event_loop_policy(initial_policy) + + +class WriterPipeClosedTestCase(_PipeClosedTestCase, TestCase): + """ + Test that a writer callback is called after the other end of + the pipe has been closed. + """ + def _do_test(self, read_end, write_end): + initial_policy = asyncio.get_event_loop_policy() + if not isinstance(initial_policy, DefaultEven
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/dbapi/, pym/portage/package/ebuild/_parallel_manifest/, ...
commit: 3e77f0199cb401acf974089fb6aa378fd45d0e90 Author: Zac Medico gentoo org> AuthorDate: Tue Apr 24 06:54:05 2018 + Commit: Zac Medico gentoo org> CommitDate: Fri Apr 27 22:56:02 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=3e77f019 ManifestScheduler: async fetchlist_dict (bug 653946) In order to avoid event loop recursion, pass fetchlist_dict to ManifestTask as a Future. Bug: https://bugs.gentoo.org/653946 pym/portage/dbapi/porttree.py | 70 ++ .../ebuild/_parallel_manifest/ManifestScheduler.py | 25 .../ebuild/_parallel_manifest/ManifestTask.py | 24 +++- pym/portage/tests/dbapi/test_portdb_cache.py | 3 +- 4 files changed, 105 insertions(+), 17 deletions(-) diff --git a/pym/portage/dbapi/porttree.py b/pym/portage/dbapi/porttree.py index 975f03d5e..3ce214cd7 100644 --- a/pym/portage/dbapi/porttree.py +++ b/pym/portage/dbapi/porttree.py @@ -37,6 +37,7 @@ from portage import _unicode_encode from portage import OrderedDict from portage.util._eventloop.EventLoop import EventLoop from portage.util._eventloop.global_event_loop import global_event_loop +from portage.util.futures.iter_completed import iter_gather from _emerge.EbuildMetadataPhase import EbuildMetadataPhase import os as _os @@ -1393,6 +1394,75 @@ class FetchlistDict(Mapping): if sys.hexversion >= 0x300: keys = __iter__ + +def _async_manifest_fetchlist(portdb, repo_config, cp, cpv_list=None, + max_jobs=None, max_load=None, loop=None): + """ + Asynchronous form of FetchlistDict, with max_jobs and max_load + parameters in order to control async_aux_get concurrency. + + @param portdb: portdbapi instance + @type portdb: portdbapi + @param repo_config: repository configuration for a Manifest + @type repo_config: RepoConfig + @param cp: cp for a Manifest + @type cp: str + @param cpv_list: list of ebuild cpv values for a Manifest + @type cpv_list: list + @param max_jobs: max number of futures to process concurrently (default + is multiprocessing.cpu_count()) + @type max_jobs: int + @param max_load: max load allowed when scheduling a new future, + otherwise schedule no more than 1 future at a time (default + is multiprocessing.cpu_count()) + @type max_load: int or float + @param loop: event loop + @type loop: EventLoop + @return: a Future resulting in a Mapping compatible with FetchlistDict + @rtype: asyncio.Future (or compatible) + """ + loop = loop or global_event_loop() + loop = getattr(loop, '_asyncio_wrapper', loop) + result = loop.create_future() + cpv_list = (portdb.cp_list(cp, mytree=repo_config.location) + if cpv_list is None else cpv_list) + + def gather_done(gather_result): + # All exceptions must be consumed from gather_result before this + # function returns, in order to avoid triggering the event loop's + # exception handler. + e = None + if not gather_result.cancelled(): + for future in gather_result.result(): + if (future.done() and not future.cancelled() and + future.exception() is not None): + e = future.exception() + + if result.cancelled(): + return + elif e is None: + result.set_result(dict((k, list(v.result())) + for k, v in zip(cpv_list, gather_result.result( + else: + result.set_exception(e) + + gather_result = iter_gather( + # Use a generator expression for lazy evaluation, so that iter_gather + # controls the number of concurrent async_fetch_map calls. + (portdb.async_fetch_map(cpv, mytree=repo_config.location, loop=loop) + for cpv in cpv_list), + max_jobs=max_jobs, + max_load=max_load, + loop=loop, + ) + + gather_result.add_done_callback(gather_done) + result.add_done_callback(lambda result: + gather_result.cancel() if result.cancelled() else None) + + return result + + def _parse_uri_map(cpv, metadata, use=None): myuris = use_reduce(metadata.get('SRC_URI', ''), diff --git a/pym/portage/package/ebuild/_parallel_manifest/ManifestScheduler.py b/pym/portage/package/ebuild/_parallel_manifest/ManifestScheduler.py index 38ac4825e..fabea9bc1 100644 --- a/pym/portage/package/ebuild/_parallel_manifest/ManifestScheduler.py +++ b/pym/portage/package/ebuild/_parallel_manifest/ManifestScheduler.py @@ -1,10 +1,10 @@ -# Copyright 2012-2013 Gentoo Foundation +# Copyright 2012-201
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/ebuild/, pym/_emerge/
commit: 71a5a82313226f7be0d966d49392a53139a96f6b Author: Zac Medico gentoo org> AuthorDate: Tue Apr 24 02:47:11 2018 + Commit: Zac Medico gentoo org> CommitDate: Thu Apr 26 03:19:22 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=71a5a823 AsynchronousTask: add async_wait() method (bug 653856) Since the AsynchronousTask.wait() method is prone to event loop recursion, deprecate it, and add an async_wait() method method to replace it. Instead of using task.wait() in order to implicitly run the event loop, now loop.run_until_complete(task.async_wait()) will be used to explicitly run the event loop. This explicit approach will make it more obvious when code will trigger event loop recursion which would not be compatible with asyncio's default event loop. Bug: https://bugs.gentoo.org/653856 pym/_emerge/AsynchronousTask.py | 23 +++ pym/portage/tests/ebuild/test_ipc_daemon.py | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/pym/_emerge/AsynchronousTask.py b/pym/_emerge/AsynchronousTask.py index e29324440..7d2e6253b 100644 --- a/pym/_emerge/AsynchronousTask.py +++ b/pym/_emerge/AsynchronousTask.py @@ -29,6 +29,26 @@ class AsynchronousTask(SlotObject): self._start_hook() self._start() + def async_wait(self): + """ + Wait for returncode asynchronously. Notification is available + via the add_done_callback method of the returned Future instance. + + @returns: Future, result is self.returncode + """ + waiter = self.scheduler.create_future() + exit_listener = lambda self: waiter.set_result(self.returncode) + self.addExitListener(exit_listener) + waiter.add_done_callback(lambda waiter: + self.removeExitListener(exit_listener) if waiter.cancelled() else None) + if self.returncode is not None: + # If the returncode is not None, it means the exit event has already + # happened, so use _async_wait() to guarantee that the exit_listener + # is called. This does not do any harm because a given exit listener + # is never called more than once. + self._async_wait() + return waiter + def _start(self): self.returncode = os.EX_OK self.wait() @@ -47,6 +67,9 @@ class AsynchronousTask(SlotObject): return self.returncode def wait(self): + """ + Deprecated. Use async_wait() instead. + """ if self.returncode is None: if not self._waiting: self._waiting = True diff --git a/pym/portage/tests/ebuild/test_ipc_daemon.py b/pym/portage/tests/ebuild/test_ipc_daemon.py index bc18cdf64..e6da51a76 100644 --- a/pym/portage/tests/ebuild/test_ipc_daemon.py +++ b/pym/portage/tests/ebuild/test_ipc_daemon.py @@ -157,6 +157,6 @@ class IpcDaemonTestCase(TestCase): try: task_scheduler.start() event_loop.run_until_complete(self._run_done) - task_scheduler.wait() + event_loop.run_until_complete(task_scheduler.async_wait()) finally: timeout_handle.cancel()
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/util/futures/asyncio/
commit: c23d093d0330a9318534a1c521fb00d6360fabc0 Author: Zac Medico gentoo org> AuthorDate: Mon Apr 23 18:20:25 2018 + Commit: Zac Medico gentoo org> CommitDate: Mon Apr 23 18:24:11 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=c23d093d tests: prove run_until_complete executes done callbacks Prove that done callbacks are executed before run_until_complete returns, which is how asyncio's default event loop behaves. This behavior was implemented in portage's internal event loop in commit 25245d7eb86ed197b7d7cfead0dbe4ce8ad4bc5b. Bug: https://bugs.gentoo.org/591760 .../futures/asyncio/test_run_until_complete.py | 29 ++ 1 file changed, 29 insertions(+) diff --git a/pym/portage/tests/util/futures/asyncio/test_run_until_complete.py b/pym/portage/tests/util/futures/asyncio/test_run_until_complete.py new file mode 100644 index 0..fc8f198ca --- /dev/null +++ b/pym/portage/tests/util/futures/asyncio/test_run_until_complete.py @@ -0,0 +1,29 @@ +# Copyright 2018 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +from portage.tests import TestCase +from portage.util.futures import asyncio +from portage.util.futures.unix_events import DefaultEventLoopPolicy + + +class RunUntilCompleteTestCase(TestCase): + def test_add_done_callback(self): + initial_policy = asyncio.get_event_loop_policy() + if not isinstance(initial_policy, DefaultEventLoopPolicy): + asyncio.set_event_loop_policy(DefaultEventLoopPolicy()) + + try: + loop = asyncio.get_event_loop() + f1 = loop.create_future() + f2 = loop.create_future() + f1.add_done_callback(f2.set_result) + loop.call_soon(lambda: f1.set_result(None)) + loop.run_until_complete(f1) + self.assertEqual(f1.done(), True) + + # This proves that done callbacks of f1 are executed before + # loop.run_until_complete(f1) returns, which is how asyncio's + # default event loop behaves. + self.assertEqual(f2.done(), True) + finally: + asyncio.set_event_loop_policy(initial_policy)
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/util/futures/
commit: a6e9c7cf429741015e26b923c8036416cc6bff7d Author: Zac Medico gentoo org> AuthorDate: Sun Apr 22 16:19:27 2018 + Commit: Zac Medico gentoo org> CommitDate: Sun Apr 22 16:24:37 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=a6e9c7cf test_iter_completed: fix SleepProcess._future_done cancel race Fixes: a9e8ebaa6979 ("Add async_iter_completed for asyncio migration (bug 591760)") pym/portage/tests/util/futures/test_iter_completed.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pym/portage/tests/util/futures/test_iter_completed.py b/pym/portage/tests/util/futures/test_iter_completed.py index 1344523c6..b07146ed3 100644 --- a/pym/portage/tests/util/futures/test_iter_completed.py +++ b/pym/portage/tests/util/futures/test_iter_completed.py @@ -19,7 +19,8 @@ class SleepProcess(ForkProcess): ForkProcess._start(self) def _future_done(self, task): - self.future.set_result(self.seconds) + if not self.future.cancelled(): + self.future.set_result(self.seconds) def _run(self): time.sleep(self.seconds)
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/util/futures/asyncio/, pym/portage/util/futures/
commit: 72914c0dbae1dfab7565a627451b616e330b8889 Author: Zac Medico gentoo org> AuthorDate: Sun Apr 15 10:11:21 2018 + Commit: Zac Medico gentoo org> CommitDate: Tue Apr 17 02:19:57 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=72914c0d Implement AbstractEventLoop.connect_write_pipe (bug 649588) In python versions that support asyncio, this allows API consumers to use subprocess.PIPE for asyncio.create_subprocess_exec() stdin parameters. Bug: https://bugs.gentoo.org/649588 .../util/futures/asyncio/test_subprocess_exec.py | 34 +++ pym/portage/util/futures/transports.py | 90 +++ pym/portage/util/futures/unix_events.py| 259 - 3 files changed, 373 insertions(+), 10 deletions(-) diff --git a/pym/portage/tests/util/futures/asyncio/test_subprocess_exec.py b/pym/portage/tests/util/futures/asyncio/test_subprocess_exec.py index 94984fc93..8c8c395ca 100644 --- a/pym/portage/tests/util/futures/asyncio/test_subprocess_exec.py +++ b/pym/portage/tests/util/futures/asyncio/test_subprocess_exec.py @@ -191,3 +191,37 @@ class SubprocessExecTestCase(TestCase): self.assertEqual(loop.run_until_complete(proc.wait()), os.EX_OK) self._run_test(test) + + def testWriteTransport(self): + """ + Test asyncio.create_subprocess_exec(stdin=subprocess.PIPE) which + requires an AbstractEventLoop.connect_write_pipe implementation + (and a WriteTransport implementation for it to return). + """ + if not hasattr(asyncio, 'create_subprocess_exec'): + self.skipTest('create_subprocess_exec not implemented for python2') + + stdin_data = b'hello world' + cat_binary = find_binary("cat") + self.assertNotEqual(cat_binary, None) + cat_binary = cat_binary.encode() + + def test(loop): + proc = loop.run_until_complete( + asyncio.create_subprocess_exec( + cat_binary, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) + + # This buffers data when necessary to avoid blocking. + proc.stdin.write(stdin_data) + # Any buffered data is written asynchronously after the + # close method is called. + proc.stdin.close() + + self.assertEqual( + loop.run_until_complete(proc.stdout.read()), + stdin_data) + self.assertEqual(loop.run_until_complete(proc.wait()), os.EX_OK) + + self._run_test(test) diff --git a/pym/portage/util/futures/transports.py b/pym/portage/util/futures/transports.py new file mode 100644 index 0..60ea93073 --- /dev/null +++ b/pym/portage/util/futures/transports.py @@ -0,0 +1,90 @@ +# Copyright 2018 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +try: + from asyncio.transports import Transport as _Transport +except ImportError: + _Transport = object + + +class _FlowControlMixin(_Transport): + """ + This is identical to the standard library's private + asyncio.transports._FlowControlMixin class. + + All the logic for (write) flow control in a mix-in base class. + + The subclass must implement get_write_buffer_size(). It must call + _maybe_pause_protocol() whenever the write buffer size increases, + and _maybe_resume_protocol() whenever it decreases. It may also + override set_write_buffer_limits() (e.g. to specify different + defaults). + + The subclass constructor must call super().__init__(extra). This + will call set_write_buffer_limits(). + + The user may call set_write_buffer_limits() and + get_write_buffer_size(), and their protocol's pause_writing() and + resume_writing() may be called. + """ + + def __init__(self, extra=None, loop=None): + super().__init__(extra) + assert loop is not None + self._loop = loop + self._protocol_paused = False + self._set_write_buffer_limits() + + def _maybe_pause_protocol(self): + size = self.get_write_buffer_size() + if size <= self._high_water: + return + if not self._protocol_paused: + self._protocol_paused = True + try: + self._protocol.pause_writing() + except Exception as exc: + self._loop.call_exception_handler({ + 'message': 'p
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/util/futures/, pym/portage/util/futures/, ...
commit: ece99145a48157b60212d511c8053f8f6c0532a9 Author: Zac Medico gentoo org> AuthorDate: Mon Apr 16 16:27:39 2018 + Commit: Zac Medico gentoo org> CommitDate: Mon Apr 16 16:42:58 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=ece99145 Use asyncio.wait from standard library when available pym/portage/tests/util/futures/test_retry.py | 46 +++--- .../futures/{_asyncio.py => _asyncio/__init__.py} | 11 ++ .../util/futures/{wait.py => _asyncio/tasks.py}| 17 ++-- pym/portage/util/futures/iter_completed.py | 5 ++- 4 files changed, 51 insertions(+), 28 deletions(-) diff --git a/pym/portage/tests/util/futures/test_retry.py b/pym/portage/tests/util/futures/test_retry.py index 7641e4e92..409f50971 100644 --- a/pym/portage/tests/util/futures/test_retry.py +++ b/pym/portage/tests/util/futures/test_retry.py @@ -11,9 +11,9 @@ except ImportError: from portage.tests import TestCase from portage.util._eventloop.global_event_loop import global_event_loop from portage.util.backoff import RandomExponentialBackoff +from portage.util.futures import asyncio from portage.util.futures.futures import TimeoutError from portage.util.futures.retry import retry -from portage.util.futures.wait import wait from portage.util.monotonic import monotonic @@ -57,7 +57,7 @@ class HangForever(object): class RetryTestCase(TestCase): def testSucceedLater(self): - loop = global_event_loop() + loop = global_event_loop()._asyncio_wrapper func = SucceedLater(1) func_coroutine = functools.partial(loop.run_in_executor, None, func) decorator = retry(try_max=, @@ -67,51 +67,51 @@ class RetryTestCase(TestCase): self.assertEqual(result, 'success') def testSucceedNever(self): - loop = global_event_loop() + loop = global_event_loop()._asyncio_wrapper func = SucceedNever() func_coroutine = functools.partial(loop.run_in_executor, None, func) decorator = retry(try_max=4, try_timeout=None, delay_func=RandomExponentialBackoff(multiplier=0.1, base=2)) decorated_func = decorator(func_coroutine) - done, pending = loop.run_until_complete(wait([decorated_func()])) + done, pending = loop.run_until_complete(asyncio.wait([decorated_func()], loop=loop)) self.assertEqual(len(done), 1) - self.assertTrue(isinstance(done[0].exception().__cause__, SucceedNeverException)) + self.assertTrue(isinstance(done.pop().exception().__cause__, SucceedNeverException)) def testSucceedNeverReraise(self): - loop = global_event_loop() + loop = global_event_loop()._asyncio_wrapper func = SucceedNever() func_coroutine = functools.partial(loop.run_in_executor, None, func) decorator = retry(reraise=True, try_max=4, try_timeout=None, delay_func=RandomExponentialBackoff(multiplier=0.1, base=2)) decorated_func = decorator(func_coroutine) - done, pending = loop.run_until_complete(wait([decorated_func()])) + done, pending = loop.run_until_complete(asyncio.wait([decorated_func()], loop=loop)) self.assertEqual(len(done), 1) - self.assertTrue(isinstance(done[0].exception(), SucceedNeverException)) + self.assertTrue(isinstance(done.pop().exception(), SucceedNeverException)) def testHangForever(self): - loop = global_event_loop() + loop = global_event_loop()._asyncio_wrapper func = HangForever() func_coroutine = functools.partial(loop.run_in_executor, None, func) decorator = retry(try_max=2, try_timeout=0.1, delay_func=RandomExponentialBackoff(multiplier=0.1, base=2)) decorated_func = decorator(func_coroutine) - done, pending = loop.run_until_complete(wait([decorated_func()])) + done, pending = loop.run_until_complete(asyncio.wait([decorated_func()], loop=loop)) self.assertEqual(len(done), 1) - self.assertTrue(isinstance(done[0].exception().__cause__, TimeoutError)) + self.assertTrue(isinstance(done.pop().exception().__cause__, TimeoutError)) def testHangForeverReraise(self): - loop = global_event_loop() + loop = global_event_loop()._asyncio_wrapper func = HangForever() func_coroutine = functools.partial(loop.run_in_executor, None, func) decorator = retry(reraise=True, try_max=2, try_timeout=0.1, delay_func=RandomExponentialBackoff(multiplier=0.1, base=2)) decora
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/resolver/, pym/_emerge/
commit: 600b329949f8770fe2962987ee97567b65393c7e Author: Zac Medico gentoo org> AuthorDate: Tue Apr 10 21:29:44 2018 + Commit: Zac Medico gentoo org> CommitDate: Thu Apr 12 02:43:47 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=600b3299 _slot_operator.._reinstalls: probe binpkg rebuild (bug 652938) If the parent is not installed, check if it needs to be rebuilt against an installed instance, since otherwise it could trigger downgrade of an installed instance. Bug: https://bugs.gentoo.org/652938 Reviewed-by: Manuel Rüger gentoo.org> pym/_emerge/depgraph.py| 10 - .../tests/resolver/test_slot_operator_rebuild.py | 45 +- 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py index 160ea5e94..67f912f5e 100644 --- a/pym/_emerge/depgraph.py +++ b/pym/_emerge/depgraph.py @@ -2571,17 +2571,23 @@ class depgraph(object): isinstance(dep.parent, Package) and dep.parent.built): continue + # If the parent is not installed, check if it needs to be + # rebuilt against an installed instance, since otherwise + # it could trigger downgrade of an installed instance as + # in bug #652938. + want_update_probe = dep.want_update or not dep.parent.installed + # Check for slot update first, since we don't want to # trigger reinstall of the child package when a newer # slot will be used instead. - if rebuild_if_new_slot and dep.want_update: + if rebuild_if_new_slot and want_update_probe: new_dep = self._slot_operator_update_probe(dep, new_child_slot=True) if new_dep is not None: self._slot_operator_update_backtrack(dep, new_child_slot=new_dep.child) - if dep.want_update: + if want_update_probe: if self._slot_operator_update_probe(dep): self._slot_operator_update_backtrack(dep) diff --git a/pym/portage/tests/resolver/test_slot_operator_rebuild.py b/pym/portage/tests/resolver/test_slot_operator_rebuild.py index 42512aad8..381683331 100644 --- a/pym/portage/tests/resolver/test_slot_operator_rebuild.py +++ b/pym/portage/tests/resolver/test_slot_operator_rebuild.py @@ -1,4 +1,4 @@ -# Copyright 2014 Gentoo Foundation +# Copyright 2014-2018 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 from portage.tests import TestCase @@ -31,6 +31,32 @@ class SlotOperatorRebuildTestCase(TestCase): "RDEPEND": "|| ( app-misc/X app-misc/A:= )" }, + "app-misc/D-1" : { + "EAPI": "6", + "RDEPEND": "app-misc/E", + }, + + "app-misc/E-1" : { + "EAPI": "6", + "RDEPEND": "app-misc/F:=", + }, + + "app-misc/F-1" : { + "EAPI": "6", + "SLOT": "0/1" + }, + + "app-misc/F-2" : { + "EAPI": "6", + "SLOT": "0/2" + }, + } + + binpkgs = { + "app-misc/E-1" : { + "EAPI": "6", + "RDEPEND": "app-misc/F:0/1=", + }, } installed = { @@ -50,6 +76,10 @@ class SlotOperatorRebuildTestCase(TestCase): "RDEPEND": "|| ( app-misc/X app-misc/A:0/1= )" }, + "app-misc/F-2" : { + "EAPI": "6", + "SLOT": "0/2" + }, } world = ["app-misc/B", "app-misc/C"] @@ -68,9 +98,20 @@ class SlotOperatorRebuildTestCase(TestCase): mergelist = ['app-misc/A-2', ('app-misc/B-0', 'app-misc/C-0')] ), + # Test bug #652938, where a binary package built against an + # older subslot triggered downgrade of an installed
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/util/futures/, pym/portage/util/futures/
commit: f2bece120b1e9bcd7c74fc782cef9016f2147555 Author: Zac Medico gentoo org> AuthorDate: Tue Apr 10 06:52:58 2018 + Commit: Zac Medico gentoo org> CommitDate: Wed Apr 11 01:44:34 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=f2bece12 iter_completed: support asyncio via _PortageEventLoopPolicy (bug 649588) Support portage's internal EventLoop as well as the _PortageEventLoop asyncio compatibility wrapper, by using the respective _loop and _asyncio_wrapper attributes where appropriate. Bug: https://bugs.gentoo.org/649588 pym/portage/tests/util/futures/test_iter_completed.py | 4 ++-- pym/portage/util/futures/iter_completed.py| 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pym/portage/tests/util/futures/test_iter_completed.py b/pym/portage/tests/util/futures/test_iter_completed.py index d0a7dbb45..9c23aefb1 100644 --- a/pym/portage/tests/util/futures/test_iter_completed.py +++ b/pym/portage/tests/util/futures/test_iter_completed.py @@ -29,7 +29,7 @@ class IterCompletedTestCase(TestCase): # load causes the tasks to finish in an unexpected order. self.todo = True - loop = global_event_loop() + loop = global_event_loop()._asyncio_wrapper tasks = [ SleepProcess(seconds=0.200), SleepProcess(seconds=0.100), @@ -41,7 +41,7 @@ class IterCompletedTestCase(TestCase): def future_generator(): for task in tasks: task.future = loop.create_future() - task.scheduler = loop + task.scheduler = loop._loop task.start() yield task.future diff --git a/pym/portage/util/futures/iter_completed.py b/pym/portage/util/futures/iter_completed.py index ad6275b49..583a20f3b 100644 --- a/pym/portage/util/futures/iter_completed.py +++ b/pym/portage/util/futures/iter_completed.py @@ -30,6 +30,7 @@ def iter_completed(futures, max_jobs=None, max_load=None, loop=None): @rtype: iterator """ loop = loop or global_event_loop() + loop = getattr(loop, '_asyncio_wrapper', loop) max_jobs = max_jobs or multiprocessing.cpu_count() max_load = max_load or multiprocessing.cpu_count() @@ -43,7 +44,7 @@ def iter_completed(futures, max_jobs=None, max_load=None, loop=None): task_generator(), max_jobs=max_jobs, max_load=max_load, - event_loop=loop) + event_loop=loop._loop) try: scheduler.start()
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/resolver/, repoman/pym/repoman/tests/
commit: 1733e574716d2e904dcd9b0338a61fbfe0a798e7 Author: Zac Medico gentoo org> AuthorDate: Sat Apr 7 00:32:43 2018 + Commit: Zac Medico gentoo org> CommitDate: Sat Apr 7 01:42:01 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=1733e574 ResolverPlayground: create ${EPREFIX}/usr/share/repoman This solves the following issue when running the tests with an installed instance of repoman like we do in travis: testSimple (repoman.tests.simple.test_simple.SimpleRepomanTestCase) ... Traceback (most recent call last): File "/usr/bin/repoman", line 44, in repoman_main(sys.argv[1:]) File "/home/travis/virtualenv/python2.7.14/lib/python2.7/site-packages/repoman/main.py", line 95, in repoman_main repoman_settings, vcs_settings, options, qadata) File "/home/travis/virtualenv/python2.7.14/lib/python2.7/site-packages/repoman/repos.py", line 56, in __init__ if not self.qadata.load_repo_config(self.masters_list, options, repoman_settings.valid_versions): File "/home/travis/virtualenv/python2.7.14/lib/python2.7/site-packages/repoman/qa_data.py", line 46, in load_repo_config repomanpaths = [os.path.join(cnfdir, _file_) for _file_ in os.listdir(cnfdir)] OSError: [Errno 2] No such file or directory: '/tmp/tmpWkrEvP/usr/share/repoman/qa_data' pym/portage/tests/resolver/ResolverPlayground.py | 10 ++ repoman/pym/repoman/tests/__init__.py| 3 +++ 2 files changed, 13 insertions(+) diff --git a/pym/portage/tests/resolver/ResolverPlayground.py b/pym/portage/tests/resolver/ResolverPlayground.py index d3a5d8092..e2e061669 100644 --- a/pym/portage/tests/resolver/ResolverPlayground.py +++ b/pym/portage/tests/resolver/ResolverPlayground.py @@ -26,6 +26,11 @@ from _emerge.create_depgraph_params import create_depgraph_params from _emerge.depgraph import backtrack_depgraph from _emerge.RootConfig import RootConfig +try: + from repoman.tests import cnf_path_repoman +except ImportError: + cnf_path_repoman = None + if sys.hexversion >= 0x300: # pylint: disable=W0622 basestring = str @@ -457,6 +462,11 @@ class ResolverPlayground(object): for line in lines: f.write("%s\n" % line) + if cnf_path_repoman is not None: + #Create /usr/share/repoman + repoman_share_dir = os.path.join(self.eroot, 'usr', 'share', 'repoman') + os.symlink(cnf_path_repoman, repoman_share_dir) + def _create_world(self, world, world_sets): #Create /var/lib/portage/world var_lib_portage = os.path.join(self.eroot, "var", "lib", "portage") diff --git a/repoman/pym/repoman/tests/__init__.py b/repoman/pym/repoman/tests/__init__.py index 3421493f4..d57ca9b10 100644 --- a/repoman/pym/repoman/tests/__init__.py +++ b/repoman/pym/repoman/tests/__init__.py @@ -33,11 +33,14 @@ from portage.const import EPREFIX, GLOBAL_CONFIG_PATH, PORTAGE_BIN_PATH if repoman._not_installed: cnf_path = os.path.join(REPOMAN_BASE_PATH, 'cnf') + cnf_path_repoman = cnf_path cnf_etc_path = cnf_path cnf_bindir = os.path.join(REPOMAN_BASE_PATH, 'bin') cnf_sbindir = cnf_bindir else: cnf_path = os.path.join(EPREFIX or '/', GLOBAL_CONFIG_PATH) + cnf_path_repoman = os.path.join(EPREFIX or '/', + sys.prefix.lstrip(os.sep), 'share', 'repoman') cnf_etc_path = os.path.join(EPREFIX or '/', 'etc') cnf_eprefix = EPREFIX cnf_bindir = os.path.join(EPREFIX or '/', 'usr', 'bin')
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/util/futures/, pym/portage/util/futures/
commit: 1aa9a71731f3ab05e10190493956c70998abf12a Author: Zac Medico gentoo org> AuthorDate: Fri Mar 16 19:37:54 2018 + Commit: Zac Medico gentoo org> CommitDate: Mon Apr 2 16:53:24 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=1aa9a717 Add retry decorator (API inspired by tenacity) This decorator will be useful for retrying asynchronous operations, such as gpg key refresh (bug 649276). The API is inspired by tenacity, but is simpler. Only asynchronous functions (like @asyncio.coroutine functions) are supported. In order to retry a synchronous function, first convert it to an asynchronous function as follows: asynchronous_func = functools.partial( loop.run_in_executor, None, synchronous_func) Bug: https://bugs.gentoo.org/649276 See: https://github.com/jd/tenacity Reviewed-by: Alec Warner gentoo.org> pym/portage/tests/util/futures/test_retry.py | 147 + pym/portage/util/futures/futures.py | 6 + pym/portage/util/futures/retry.py| 183 +++ 3 files changed, 336 insertions(+) diff --git a/pym/portage/tests/util/futures/test_retry.py b/pym/portage/tests/util/futures/test_retry.py new file mode 100644 index 0..7641e4e92 --- /dev/null +++ b/pym/portage/tests/util/futures/test_retry.py @@ -0,0 +1,147 @@ +# Copyright 2018 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +import functools + +try: + import threading +except ImportError: + import dummy_threading as threading + +from portage.tests import TestCase +from portage.util._eventloop.global_event_loop import global_event_loop +from portage.util.backoff import RandomExponentialBackoff +from portage.util.futures.futures import TimeoutError +from portage.util.futures.retry import retry +from portage.util.futures.wait import wait +from portage.util.monotonic import monotonic + + +class SucceedLaterException(Exception): + pass + + +class SucceedLater(object): + """ + A callable object that succeeds some duration of time has passed. + """ + def __init__(self, duration): + self._succeed_time = monotonic() + duration + + def __call__(self): + remaining = self._succeed_time - monotonic() + if remaining > 0: + raise SucceedLaterException('time until success: {} seconds'.format(remaining)) + return 'success' + + +class SucceedNeverException(Exception): + pass + + +class SucceedNever(object): + """ + A callable object that never succeeds. + """ + def __call__(self): + raise SucceedNeverException('expected failure') + + +class HangForever(object): + """ + A callable object that sleeps forever. + """ + def __call__(self): + threading.Event().wait() + + +class RetryTestCase(TestCase): + def testSucceedLater(self): + loop = global_event_loop() + func = SucceedLater(1) + func_coroutine = functools.partial(loop.run_in_executor, None, func) + decorator = retry(try_max=, + delay_func=RandomExponentialBackoff(multiplier=0.1, base=2)) + decorated_func = decorator(func_coroutine) + result = loop.run_until_complete(decorated_func()) + self.assertEqual(result, 'success') + + def testSucceedNever(self): + loop = global_event_loop() + func = SucceedNever() + func_coroutine = functools.partial(loop.run_in_executor, None, func) + decorator = retry(try_max=4, try_timeout=None, + delay_func=RandomExponentialBackoff(multiplier=0.1, base=2)) + decorated_func = decorator(func_coroutine) + done, pending = loop.run_until_complete(wait([decorated_func()])) + self.assertEqual(len(done), 1) + self.assertTrue(isinstance(done[0].exception().__cause__, SucceedNeverException)) + + def testSucceedNeverReraise(self): + loop = global_event_loop() + func = SucceedNever() + func_coroutine = functools.partial(loop.run_in_executor, None, func) + decorator = retry(reraise=True, try_max=4, try_timeout=None, + delay_func=RandomExponentialBackoff(multiplier=0.1, base=2)) + decorated_func = decorator(func_coroutine) + done, pending = loop.run_until_complete(wait([decorated_func()])) + self.assertEqual(len(done), 1) + self.assertTrue(isinstance(done[0].exception(), SucceedNeverException)) + + def testHangForever(self): + loop = global_event_loop() + func = HangForever() + func_coroutine = functools.partial(loop.run_in_executor, None, func) + decorator =
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/resolver/, man/, pym/_emerge/
commit: 6a810e0cdb586fb05f210a1c7ba2b5401f38c332 Author: Zac Medico gentoo org> AuthorDate: Wed Mar 21 18:50:43 2018 + Commit: Zac Medico gentoo org> CommitDate: Mon Mar 26 17:35:33 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=6a810e0c emerge: add --ignore-world [ y | n ] option (bug 608564) Ignore the @world package set and its dependencies. This may be useful if there is a desire to perform an action even though it might break the dependencies of some installed packages (it might also remove installed packages in order to solve blockers). This also alters the behavior of --complete-graph options so that only deep dependencies of packages given as arguments are included in the dependency graph. This option may be useful as an alternative to --nodeps in cases where it is desirable to account for dependencies of packages given as arguments. Bug: https://bugs.gentoo.org/608564 man/emerge.1 | 19 ++- pym/_emerge/create_depgraph_params.py | 6 +- pym/_emerge/depgraph.py | 8 ++-- pym/_emerge/main.py | 11 ++- pym/portage/tests/resolver/test_complete_graph.py | 20 +++- 5 files changed, 58 insertions(+), 6 deletions(-) diff --git a/man/emerge.1 b/man/emerge.1 index a17b65ed2..27a1193fe 100644 --- a/man/emerge.1 +++ b/man/emerge.1 @@ -1,4 +1,4 @@ -.TH "EMERGE" "1" "Jul 2016" "Portage VERSION" "Portage" +.TH "EMERGE" "1" "Mar 2018" "Portage VERSION" "Portage" .SH "NAME" emerge \- Command\-line interface to the Portage system .SH "SYNOPSIS" @@ -630,6 +630,23 @@ Therefore, \fB\-\-usepkgonly\fR (or \fB\-\-getbinpkgonly\fR) must be used in order to enable soname depedency resolution when installing packages. .TP +.BR "\-\-ignore\-world [ y | n ]" +Ignore the @world package set and its dependencies. This may be useful +if there is a desire to perform an action even though it might break +the dependencies of some installed packages (it might also remove +installed packages in order to solve blockers). This also alters the +behavior of \fB\-\-complete\-graph\fR options so that only deep +dependencies of packages given as arguments are included in the +dependency graph. This option may be useful as an alternative to +\fB\-\-nodeps\fR in cases where it is desirable to account for +dependencies of packages given as arguments. + +\fBWARNING:\fR +This option is intended to be used only with great caution, since it is +possible for it to make nonsensical changes which may lead to system +breakage. Therefore, it is advisable to use \fB\-\-ask\fR together with +this option. +.TP .BR \-j\ [JOBS] ", " \-\-jobs[=JOBS] Specifies the number of packages to build simultaneously. If this option is given without an argument, emerge will not limit the number of jobs that can diff --git a/pym/_emerge/create_depgraph_params.py b/pym/_emerge/create_depgraph_params.py index fc7fa60d7..ff18f3acc 100644 --- a/pym/_emerge/create_depgraph_params.py +++ b/pym/_emerge/create_depgraph_params.py @@ -1,4 +1,4 @@ -# Copyright 1999-2014 Gentoo Foundation +# Copyright 1999-2018 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 import logging @@ -26,6 +26,7 @@ def create_depgraph_params(myopts, myaction): # ignore_soname_deps: ignore the soname dependencies of built # packages, so that they do not trigger dependency resolution # failures, or cause packages to be rebuilt or replaced. + # ignore_world: ignore the @world package set and its dependencies # with_test_deps: pull in test deps for packages matched by arguments # changed_deps: rebuild installed packages with outdated deps # changed_deps_report: report installed packages with outdated deps @@ -56,6 +57,9 @@ def create_depgraph_params(myopts, myaction): myparams["selective"] = True return myparams + if myopts.get('--ignore-world') is True: + myparams['ignore_world'] = True + rebuild_if_new_slot = myopts.get('--rebuild-if-new-slot') if rebuild_if_new_slot is not None: myparams['rebuild_if_new_slot'] = rebuild_if_new_slot diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py index 6c728684f..f7ea27c37 100644 --- a/pym/_emerge/depgraph.py +++ b/pym/_emerge/depgraph.py @@ -163,7 +163,10 @@ class _frozen_depgraph_config(object): self.trees[myroot]["bintree"] = DummyTree( DbapiProvidesIndex(trees[myroot]["bintree"].dbapi)) - self._required_set_names = set(["world"]) + if params.get("ignore_world", False): + self._required_set_names = set() + else: + self._required_set_names = set(["world"]) atoms = ' '.join(myopts.get
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/bin/, bin/
commit: 08d405f72e85125b64f5074e49714e759d85eaf6 Author: Michał Górny gentoo org> AuthorDate: Mon Feb 19 15:38:28 2018 + Commit: Michał Górny gentoo org> CommitDate: Sun Mar 11 11:43:41 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=08d405f7 Add EAPI 7 version comparison & manipulation functions The function code is copied from eapi7-ver.eclass which has been written by Ulrich Müller and me. Bug: https://bugs.gentoo.org/482170 bin/eapi.sh | 4 + bin/eapi7-ver-funcs.sh| 191 bin/isolated-functions.sh | 4 + pym/portage/tests/bin/test_eapi7_ver_funcs.py | 240 ++ 4 files changed, 439 insertions(+) diff --git a/bin/eapi.sh b/bin/eapi.sh index fa254485c..1d5ea802d 100644 --- a/bin/eapi.sh +++ b/bin/eapi.sh @@ -100,6 +100,10 @@ ___eapi_has_in_iuse() { [[ ! ${1-${EAPI-0}} =~ ^(0|1|2|3|4|4-python|4-slot-abi|5|5-hdepend|5-progress)$ ]] } +___eapi_has_version_functions() { + [[ ! ${1-${EAPI-0}} =~ ^(0|1|2|3|4|4-python|4-slot-abi|5|5-progress|6)$ ]] +} + ___eapi_has_master_repositories() { [[ ${1-${EAPI-0}} =~ ^(5-progress)$ ]] } diff --git a/bin/eapi7-ver-funcs.sh b/bin/eapi7-ver-funcs.sh new file mode 100644 index 0..b4e98f4e7 --- /dev/null +++ b/bin/eapi7-ver-funcs.sh @@ -0,0 +1,191 @@ +#!/bin/bash +# Copyright 1999-2018 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +__eapi7_ver_parse_range() { + local range=${1} + local max=${2} + + [[ ${range} == [0-9]* ]] \ + || die "${FUNCNAME}: range must start with a number" + start=${range%-*} + [[ ${range} == *-* ]] && end=${range#*-} || end=${start} + if [[ ${end} ]]; then + [[ ${start} -le ${end} ]] \ + || die "${FUNCNAME}: end of range must be >= start" + [[ ${end} -le ${max} ]] || end=${max} + else + end=${max} + fi +} + +__eapi7_ver_split() { + local v=${1} LC_ALL=C + + comp=() + + # get separators and components + local s c + while [[ ${v} ]]; do + # cut the separator + s=${v%%[a-zA-Z0-9]*} + v=${v:${#s}} + # cut the next component; it can be either digits or letters + [[ ${v} == [0-9]* ]] && c=${v%%[^0-9]*} || c=${v%%[^a-zA-Z]*} + v=${v:${#c}} + + comp+=( "${s}" "${c}" ) + done +} + +ver_cut() { + local range=${1} + local v=${2:-${PV}} + local start end + local -a comp + + __eapi7_ver_split "${v}" + local max=$((${#comp[@]}/2)) + __eapi7_ver_parse_range "${range}" "${max}" + + local IFS= + if [[ ${start} -gt 0 ]]; then + start=$(( start*2 - 1 )) + fi + echo "${comp[*]:start:end*2-start}" +} + +ver_rs() { + local v + (( ${#} & 1 )) && v=${@: -1} || v=${PV} + local start end i + local -a comp + + __eapi7_ver_split "${v}" + local max=$((${#comp[@]}/2 - 1)) + + while [[ ${#} -ge 2 ]]; do + __eapi7_ver_parse_range "${1}" "${max}" + for (( i = start*2; i <= end*2; i+=2 )); do + [[ ${i} -eq 0 && -z ${comp[i]} ]] && continue + comp[i]=${2} + done + shift 2 + done + + local IFS= + echo "${comp[*]}" +} + +__eapi7_ver_compare_int() { + local a=$1 b=$2 d=$(( ${#1}-${#2} )) + + # Zero-pad to equal length if necessary. + if [[ ${d} -gt 0 ]]; then + printf -v b "%0${d}d%s" 0 "${b}" + elif [[ ${d} -lt 0 ]]; then + printf -v a "%0$(( -d ))d%s" 0 "${a}" + fi + + [[ ${a} > ${b} ]] && return 3 + [[ ${a} == "${b}" ]] +} + +__eapi7_ver_compare() { + local va=${1} vb=${2} a an al as ar b bn bl bs br re LC_ALL=C + + re="^([0-9]+(\.[0-9]+)*)([a-z]?)((_(alpha|beta|pre|rc|p)[0-9]*)*)(-r[0-9]+)?$" + + [[ ${va} =~ ${re} ]] || die "${FUNCNAME}: invalid version: ${va}" + an=${BASH_REMATCH[1]} + al=${BASH_REMATCH[3]} + as=${BASH_REMATCH[4]} + ar=${BASH_REMATCH[7]} + + [[ ${vb} =~ ${re} ]] || die "${FUNCNAME}: invalid version: ${vb}" + bn=${BASH_REMATCH[1]} + bl=${BASH_REMATCH[3]} + bs=${BASH_REMATCH[4]} + br=${BASH_REMATCH[7]} + + # Compare numeric components (PMS algorithm 3.2) + # First component + __eapi7_ver_compare_int "${an%%.*}" "${bn%%.*}" || return + + while [[ ${an} == *.* && ${bn} == *.* ]]; do + # Other components (PMS algorithm 3.3) + an=${an#*.} + bn=${bn#*.} + a=${an%%.*} + b=${bn%%.*} + if [[ ${a} == 0* || ${b} == 0* ]]; then + # Remove any trailing zeros +
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/resolver/
commit: ea4456cf197fd7ac8644ab0396fb629ce612ae6f Author: Michał Górny gentoo org> AuthorDate: Mon Feb 26 12:40:15 2018 + Commit: Michał Górny gentoo org> CommitDate: Sun Mar 4 21:03:52 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=ea4456cf test_required_use: Add tests for ?? operator pym/portage/tests/resolver/test_required_use.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pym/portage/tests/resolver/test_required_use.py b/pym/portage/tests/resolver/test_required_use.py index d4004..ac748ca3b 100644 --- a/pym/portage/tests/resolver/test_required_use.py +++ b/pym/portage/tests/resolver/test_required_use.py @@ -1,4 +1,4 @@ -# Copyright 2010-2011 Gentoo Foundation +# Copyright 2010-2018 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 from portage.tests import TestCase
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/resolver/, pym/portage/dep/
commit: 9ebd5865559aa17186c23c90c6a90894449dc3ac Author: Michał Górny gentoo org> AuthorDate: Mon Feb 26 13:09:32 2018 + Commit: Michał Górny gentoo org> CommitDate: Sun Mar 4 21:03:52 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=9ebd5865 Empty || *DEPEND group no longer satisfy deps in EAPI 7 Bug: https://bugs.gentoo.org/636596 pym/portage/dep/__init__.py | 3 +++ pym/portage/tests/resolver/test_eapi.py | 9 - 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/pym/portage/dep/__init__.py b/pym/portage/dep/__init__.py index 2a081f3d8..3d4bca08f 100644 --- a/pym/portage/dep/__init__.py +++ b/pym/portage/dep/__init__.py @@ -562,6 +562,9 @@ def use_reduce(depstr, uselist=[], masklist=[], matchall=False, excludeall=[], i basestring): if stack[level][-1] == "||" and not l: #Optimize: || ( ) -> . + if not eapi_attrs.empty_groups_always_true: + # in EAPI 7+, we need to fail here + l.append((token_class or _unicode)("__const__/empty-any-of")) stack[level].pop() elif stack[level][-1][-1] == "?": #The last token before the '(' that matches the current ')' diff --git a/pym/portage/tests/resolver/test_eapi.py b/pym/portage/tests/resolver/test_eapi.py index 525b58532..fce05890b 100644 --- a/pym/portage/tests/resolver/test_eapi.py +++ b/pym/portage/tests/resolver/test_eapi.py @@ -1,4 +1,4 @@ -# Copyright 2010 Gentoo Foundation +# Copyright 2010-2018 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 from portage.tests import TestCase @@ -59,6 +59,10 @@ class EAPITestCase(TestCase): "dev-libs/A-7.4": { "EAPI": "4", "IUSE": "foo +bar", "REQUIRED_USE": "|| ( foo bar )" }, "dev-libs/B-1": {"EAPI": 1, "IUSE": "+foo"}, + + #EAPI-7: implicit || ( ) no longer satisfies deps + "dev-libs/C-1": { "EAPI": "6", "IUSE": "foo", "RDEPEND": "|| ( foo? ( dev-libs/B ) )" }, + "dev-libs/C-2": { "EAPI": "7_pre1", "IUSE": "foo", "RDEPEND": "|| ( foo? ( dev-libs/B ) )" }, } test_cases = ( @@ -104,6 +108,9 @@ class EAPITestCase(TestCase): ResolverPlaygroundTestCase(["=dev-libs/A-7.2"], success = False), ResolverPlaygroundTestCase(["=dev-libs/A-7.3"], success = False), ResolverPlaygroundTestCase(["=dev-libs/A-7.4"], success = True, mergelist = ["dev-libs/A-7.4"]), + + ResolverPlaygroundTestCase(["=dev-libs/C-1"], success = True, mergelist = ["dev-libs/C-1"]), + ResolverPlaygroundTestCase(["=dev-libs/C-2"], success = False), ) playground = ResolverPlayground(ebuilds=ebuilds)
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/util/futures/, pym/portage/util/futures/, ...
commit: e43f6c583ed9205abbdcb11340c81d7dd97ccc11 Author: Zac Medico gentoo org> AuthorDate: Sun Feb 25 23:19:58 2018 + Commit: Zac Medico gentoo org> CommitDate: Wed Feb 28 17:22:20 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=e43f6c58 Add iter_completed convenience function (bug 648790) The iter_completed function is similar to asyncio.as_completed, but takes an iterator of futures as input, and includes support for max_jobs and max_load parameters. The default values for max_jobs and max_load correspond to multiprocessing.cpu_count(). Example usage for async_aux_get: import portage from portage.util.futures.iter_completed import iter_completed portdb = portage.portdb # aux_get has many inputs, and the same cpv can exist in multiple # repositories, so the caller is responsibe for mapping futures # back to their aux_get inputs future_cpv = {} def future_generator(): for cpv in portdb.cp_list('sys-apps/portage'): future = portdb.async_aux_get(cpv, portage.auxdbkeys) future_cpv[id(future)] = cpv yield future for future in iter_completed(future_generator()): cpv = future_cpv.pop(id(future)) try: result = future.result() except KeyError as e: # aux_get failed print('error:', cpv, e) else: print(cpv, result) See: https://docs.python.org/3/library/asyncio-task.html#asyncio.as_completed Bug: https://bugs.gentoo.org/648790 .../tests/util/futures/test_iter_completed.py | 50 ++ pym/portage/util/_async/AsyncTaskFuture.py | 31 +++ pym/portage/util/futures/iter_completed.py | 63 + pym/portage/util/futures/wait.py | 102 + 4 files changed, 246 insertions(+) diff --git a/pym/portage/tests/util/futures/test_iter_completed.py b/pym/portage/tests/util/futures/test_iter_completed.py new file mode 100644 index 0..d0a7dbb45 --- /dev/null +++ b/pym/portage/tests/util/futures/test_iter_completed.py @@ -0,0 +1,50 @@ +# Copyright 2018 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +import time +from portage.tests import TestCase +from portage.util._async.ForkProcess import ForkProcess +from portage.util._eventloop.global_event_loop import global_event_loop +from portage.util.futures.iter_completed import iter_completed + + +class SleepProcess(ForkProcess): + __slots__ = ('future', 'seconds') + def _start(self): + self.addExitListener(self._future_done) + ForkProcess._start(self) + + def _future_done(self, task): + self.future.set_result(self.seconds) + + def _run(self): + time.sleep(self.seconds) + + +class IterCompletedTestCase(TestCase): + + def testIterCompleted(self): + + # Mark this as todo, since we don't want to fail if heavy system + # load causes the tasks to finish in an unexpected order. + self.todo = True + + loop = global_event_loop() + tasks = [ + SleepProcess(seconds=0.200), + SleepProcess(seconds=0.100), + SleepProcess(seconds=0.001), + ] + + expected_order = sorted(task.seconds for task in tasks) + + def future_generator(): + for task in tasks: + task.future = loop.create_future() + task.scheduler = loop + task.start() + yield task.future + + for seconds, future in zip(expected_order, iter_completed(future_generator(), + max_jobs=True, max_load=None, loop=loop)): + self.assertEqual(seconds, future.result()) diff --git a/pym/portage/util/_async/AsyncTaskFuture.py b/pym/portage/util/_async/AsyncTaskFuture.py new file mode 100644 index 0..ee39183fe --- /dev/null +++ b/pym/portage/util/_async/AsyncTaskFuture.py @@ -0,0 +1,31 @@ +# Copyright 2018 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +import os +import signal + +from _emerge.AsynchronousTask import AsynchronousTask + + +class AsyncTaskFuture(AsynchronousTask): + """ + Wraps a Future in an AsynchronousTask, which is useful for + scheduling with TaskScheduler. + """ + __slots__ = ('future', 'scheduler') + def _start(self): + self.future.add_done_callback(self._done_callback) + + def _cancel(self): + if not self.future.done(): + self.future.cancel() + + def _done_callback(self, future): + if future.cancelled(): + self.cancelled = True + self.returncode = -signal.SIGINT + elif future.exception() is None: +
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/resolver/
commit: 45bdfae8b20dc24559d325db7322576855d6a582 Author: Michał Górny gentoo org> AuthorDate: Mon Feb 26 12:40:15 2018 + Commit: Michał Górny gentoo org> CommitDate: Mon Feb 26 22:07:36 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=45bdfae8 test_required_use: Add tests for ?? operator Reviewed-by: Zac Medico gentoo.org> pym/portage/tests/resolver/test_required_use.py | 12 1 file changed, 12 insertions(+) diff --git a/pym/portage/tests/resolver/test_required_use.py b/pym/portage/tests/resolver/test_required_use.py index c8810faef..d4004 100644 --- a/pym/portage/tests/resolver/test_required_use.py +++ b/pym/portage/tests/resolver/test_required_use.py @@ -44,6 +44,12 @@ class RequiredUSETestCase(TestCase): "dev-libs/D-3" : {"EAPI": "4", "IUSE": "+w +x y z", "REQUIRED_USE": "w? ( x || ( y z ) )"}, "dev-libs/D-4" : {"EAPI": "4", "IUSE": "+w x +y +z", "REQUIRED_USE": "w? ( x || ( y z ) )"}, "dev-libs/D-5" : {"EAPI": "4", "IUSE": "w x y z", "REQUIRED_USE": "w? ( x || ( y z ) )"}, + + "dev-libs/E-1" : {"EAPI": "5", "IUSE": "foo bar", "REQUIRED_USE": "?? ( foo bar )"}, + "dev-libs/E-2" : {"EAPI": "5", "IUSE": "foo +bar", "REQUIRED_USE": "?? ( foo bar )"}, + "dev-libs/E-3" : {"EAPI": "5", "IUSE": "+foo bar", "REQUIRED_USE": "?? ( foo bar )"}, + "dev-libs/E-4" : {"EAPI": "5", "IUSE": "+foo +bar", "REQUIRED_USE": "?? ( foo bar )"}, + "dev-libs/E-5" : {"EAPI": "5", "IUSE": "+foo +bar", "REQUIRED_USE": "?? ( )"}, } test_cases = ( @@ -79,6 +85,12 @@ class RequiredUSETestCase(TestCase): ResolverPlaygroundTestCase(["=dev-libs/D-3"], success = False), ResolverPlaygroundTestCase(["=dev-libs/D-4"], success = False), ResolverPlaygroundTestCase(["=dev-libs/D-5"], success = True, mergelist=["dev-libs/D-5"]), + + ResolverPlaygroundTestCase(["=dev-libs/E-1"], success = True, mergelist=["dev-libs/E-1"]), + ResolverPlaygroundTestCase(["=dev-libs/E-2"], success = True, mergelist=["dev-libs/E-2"]), + ResolverPlaygroundTestCase(["=dev-libs/E-3"], success = True, mergelist=["dev-libs/E-3"]), + ResolverPlaygroundTestCase(["=dev-libs/E-4"], success = False), + ResolverPlaygroundTestCase(["=dev-libs/E-5"], success = True, mergelist=["dev-libs/E-5"]), ) playground = ResolverPlayground(ebuilds=ebuilds)
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/ebuild/, pym/portage/util/_eventloop/
commit: 81baf80258393938152d6c8fc53d33d5f85de23c Author: Zac Medico gentoo org> AuthorDate: Sun Feb 25 06:17:40 2018 + Commit: Zac Medico gentoo org> CommitDate: Sun Feb 25 06:19:18 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=81baf802 EventLoop: implement call_later for asyncio compat (bug 591760) Bug: https://bugs.gentoo.org/591760 pym/portage/tests/ebuild/test_ipc_daemon.py | 12 ++-- pym/portage/util/_eventloop/EventLoop.py| 28 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/pym/portage/tests/ebuild/test_ipc_daemon.py b/pym/portage/tests/ebuild/test_ipc_daemon.py index fc7916541..1152f31b4 100644 --- a/pym/portage/tests/ebuild/test_ipc_daemon.py +++ b/pym/portage/tests/ebuild/test_ipc_daemon.py @@ -31,7 +31,7 @@ class SleepProcess(ForkProcess): class IpcDaemonTestCase(TestCase): - _SCHEDULE_TIMEOUT = 4 # 40 seconds + _SCHEDULE_TIMEOUT = 40 # seconds def testIpcDaemon(self): event_loop = global_event_loop() @@ -103,8 +103,8 @@ class IpcDaemonTestCase(TestCase): # Intentionally short timeout test for EventLoop/AsyncScheduler. # Use a ridiculously long sleep_time_s in case the user's # system is heavily loaded (see bug #436334). - sleep_time_s = 600 #600.000 seconds - short_timeout_ms = 10 # 0.010 seconds + sleep_time_s = 600 # seconds + short_timeout_s = 0.010 # seconds for i in range(3): exit_command = ExitCommand() @@ -123,7 +123,7 @@ class IpcDaemonTestCase(TestCase): exit_command.reply_hook = exit_command_callback start_time = time.time() - self._run(event_loop, task_scheduler, short_timeout_ms) + self._run(event_loop, task_scheduler, short_timeout_s) hardlock_cleanup(env['PORTAGE_BUILDDIR'], remove_all_locks=True) @@ -150,7 +150,7 @@ class IpcDaemonTestCase(TestCase): def _run(self, event_loop, task_scheduler, timeout): self._run_done = event_loop.create_future() - timeout_id = event_loop.timeout_add(timeout, + timeout_handle = event_loop.call_later(timeout, self._timeout_callback, task_scheduler) task_scheduler.addExitListener(self._exit_callback) @@ -159,4 +159,4 @@ class IpcDaemonTestCase(TestCase): event_loop.run_until_complete(self._run_done) task_scheduler.wait() finally: - event_loop.source_remove(timeout_id) + timeout_handle.cancel() diff --git a/pym/portage/util/_eventloop/EventLoop.py b/pym/portage/util/_eventloop/EventLoop.py index cd154005f..89ac2a3b3 100644 --- a/pym/portage/util/_eventloop/EventLoop.py +++ b/pym/portage/util/_eventloop/EventLoop.py @@ -684,6 +684,34 @@ class EventLoop(object): # The call_soon method inherits thread safety from the idle_add method. call_soon_threadsafe = call_soon + def call_later(self, delay, callback, *args): + """ + Arrange for the callback to be called after the given delay seconds + (either an int or float). + + An instance of asyncio.Handle is returned, which can be used to cancel + the callback. + + callback will be called exactly once per call to call_later(). If two + callbacks are scheduled for exactly the same time, it is undefined + which will be called first. + + The optional positional args will be passed to the callback when + it is called. If you want the callback to be called with some named + arguments, use a closure or functools.partial(). + + Use functools.partial to pass keywords to the callback. + + @type delay: int or float + @param delay: delay seconds + @type callback: callable + @param callback: a function to call + @return: a handle which can be used to cancel the callback + @rtype: asyncio.Handle (or compatible) + """ + return self._handle(self.timeout_add( + delay * 1000, self._call_soon_callback(callback, args)), self) + _can_poll_device = None
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/bin/
commit: 572861a1201ca67e18ce2ccae87480a2600b6ae2 Author: Zac Medico gentoo org> AuthorDate: Wed Feb 21 23:35:21 2018 + Commit: Zac Medico gentoo org> CommitDate: Wed Feb 21 23:36:24 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=572861a1 test_filter_bash_env.py: fix DeprecationWarning: invalid escape sequence \$ Fixes: f1367a2eeb0c ("filter-bash-environment.py: use buffered input, raw bytes (bug 647654)") pym/portage/tests/bin/test_filter_bash_env.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pym/portage/tests/bin/test_filter_bash_env.py b/pym/portage/tests/bin/test_filter_bash_env.py index 10847bb7d..d906ea793 100644 --- a/pym/portage/tests/bin/test_filter_bash_env.py +++ b/pym/portage/tests/bin/test_filter_bash_env.py @@ -16,7 +16,7 @@ class TestFilterBashEnv(TestCase): test_cases = ( ( 'RDEPEND BASH.* _EPATCH_ECLASS', - b'''declare -ir BASHPID="28997" + br'''declare -ir BASHPID="28997" declare -rx A="portage-2.3.24.tar.bz2" declare -- DESKTOP_DATABASE_DIR="/usr/share/applications" declare PDEPEND=" @@ -53,7 +53,7 @@ use_if_iuse () use $1 } ''', - b'''declare -x A="portage-2.3.24.tar.bz2" + br'''declare -x A="portage-2.3.24.tar.bz2" declare -- DESKTOP_DATABASE_DIR="/usr/share/applications" declare PDEPEND=" !build? (
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/dep/, pym/portage/dep/, pym/portage/tests/resolver/
commit: 0ddfb5802d98c618bd20742be49a520c9a54b394 Author: Zac Medico gentoo org> AuthorDate: Fri Feb 2 06:08:59 2018 + Commit: Zac Medico gentoo org> CommitDate: Fri Feb 2 12:01:25 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=0ddfb580 dep_zapdeps: sort by new_slot_count for DNF only (bug 645002) Sorting of choices by new_slot_count causes the order of choices specified in the ebuild to be discarded, and new_slot_count may have variance related to the order that packages are added to the graph. This variance can contribute to outcomes that appear to be random, like when catalyst stage1 builds sometimes pull in paludis to satisfy perl-cleaner dependencies. Meanwhile, the order specified in the ebuild has no variance, and the preferences that it specifies can serve as a crucial sources of guidance. Therefore, take advantage of the order specified in the ebuild whenever possible, and use new_slot_count only when it is needed to select optimal choices from DNF (as in bug 632026). This fixes random outcomes in the unit test for bug 645002. Previously, the unit test pulled in paludis randomly unless portage-utils was added to the arguments. With this patch, the portage-utils argument is no longer needed for the unit test to succeed consistently. The perl-cleaner dependencies do not have any overlapping || deps, so the DNF conversion and new_slot_count sorting do not apply, and the first choice is preferred regardless of the number of slots that it pulls in: || ( ( sys-apps/portage app-portage/portage-utils ) sys-apps/pkgcore sys-apps/paludis ) The _overlap_dnf function now returns the argument object when there is no overlap, so OverlapDNFTestCase has to be adjusted to account for this. Bug: https://bugs.gentoo.org/645002 Fixes: 9fdaf9bdbdf5 ("dep_check: use DNF to optimize overlapping virtual || deps (bug 632026)") pym/portage/dep/dep_check.py | 49 ++ pym/portage/tests/dep/test_overlap_dnf.py | 2 +- .../resolver/test_virtual_minimize_children.py | 12 +++--- 3 files changed, 47 insertions(+), 16 deletions(-) diff --git a/pym/portage/dep/dep_check.py b/pym/portage/dep/dep_check.py index 7e5a3186e..2896e2389 100644 --- a/pym/portage/dep/dep_check.py +++ b/pym/portage/dep/dep_check.py @@ -298,7 +298,8 @@ class _dep_choice(SlotObject): __slots__ = ('atoms', 'slot_map', 'cp_map', 'all_available', 'all_installed_slots', 'new_slot_count') -def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None): +def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None, + minimize_slots=False): """ Takes an unreduced and reduced deplist and removes satisfied dependencies. Returned deplist contains steps that must be taken to satisfy dependencies. @@ -314,7 +315,8 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None): for x, satisfied in zip(unreduced, reduced): if isinstance(x, list): unresolved += dep_zapdeps(x, satisfied, myroot, - use_binaries=use_binaries, trees=trees) + use_binaries=use_binaries, trees=trees, + minimize_slots=minimize_slots) elif not satisfied: unresolved.append(x) return unresolved @@ -386,7 +388,8 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None): for x, satisfied in zip(deps, satisfieds): if isinstance(x, list): atoms = dep_zapdeps(x, satisfied, myroot, - use_binaries=use_binaries, trees=trees) + use_binaries=use_binaries, trees=trees, + minimize_slots=minimize_slots) else: atoms = [x] if vardb is None: @@ -663,9 +666,28 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None): for choices in choice_bins: if len(choices) < 2: continue - # Prefer choices with all_installed_slots for bug #480736, and - # choices with a smaller number of new slots for bug #632026. - choices.sort(key=lambda x: (not x.all_installed_slots, x.new_slot_count)) + + sort_keys = [] + # Prefer choices with all_installed_slots for bug #480736. + sort_keys.append(lambda x: not x.all_installed_slots) + + if minimize_slots: + # Prefer choices having fewer new slots. When used with DNF form, + # this can eliminate unecessary packages that depclean would + # ultimately eliminate (see bug 632026). Only use this be
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/resolver/, pym/portage/dep/
commit: 74d0f516a346c7fb6c52a2508ca16b8949b3b65f Author: Zac Medico gentoo org> AuthorDate: Sun Jan 21 00:00:02 2018 + Commit: Zac Medico gentoo org> CommitDate: Sun Jan 21 00:09:11 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=74d0f516 dep_zapdeps: exclude virtuals from new_slot_count (bug 645190) Fix new_slot_count to exclude virtual packages, since they are considered to have zero-cost. This solves an issue where the catalyst stage1 build would unexpectedly pull in static-dev to satisfy virtual/dev-manager, but eudev is the preferred choice. Bug: https://bugs.gentoo.org/645190 Fixes: 9fdaf9bdbdf5 ("dep_check: use DNF to optimize overlapping virtual || deps (bug 632026)") Reported-by: Ben Kohler gmail.com> pym/portage/dep/dep_check.py | 3 +- .../resolver/test_virtual_minimize_children.py | 61 ++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/pym/portage/dep/dep_check.py b/pym/portage/dep/dep_check.py index 7cf338819..c56f545ec 100644 --- a/pym/portage/dep/dep_check.py +++ b/pym/portage/dep/dep_check.py @@ -499,7 +499,8 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None): cp_map[avail_pkg.cp] = avail_pkg new_slot_count = (len(slot_map) if graph_db is None else - sum(not graph_db.match_pkgs(slot_atom) for slot_atom in slot_map)) + sum(not graph_db.match_pkgs(slot_atom) for slot_atom in slot_map + if not slot_atom.cp.startswith("virtual/"))) this_choice = _dep_choice(atoms=atoms, slot_map=slot_map, cp_map=cp_map, all_available=all_available, diff --git a/pym/portage/tests/resolver/test_virtual_minimize_children.py b/pym/portage/tests/resolver/test_virtual_minimize_children.py index 6eb0409f2..287445e58 100644 --- a/pym/portage/tests/resolver/test_virtual_minimize_children.py +++ b/pym/portage/tests/resolver/test_virtual_minimize_children.py @@ -226,3 +226,64 @@ class VirtualMinimizeChildrenTestCase(TestCase): finally: playground.debug = False playground.cleanup() + + def testVirtualDevManager(self): + ebuilds = { + 'sys-fs/eudev-3.1.5': {}, + 'sys-fs/static-dev-0.1': {}, + 'sys-fs/udev-233': {}, + 'virtual/dev-manager-0': { + 'RDEPEND': ''' + || ( + virtual/udev + sys-fs/static-dev + )''' + }, + 'virtual/udev-0': { + 'RDEPEND': ''' + || ( + >=sys-fs/eudev-2.1.1 + >=sys-fs/udev-217 + )''' + }, + } + + test_cases = ( + # Test bug 645190, where static-dev was pulled in instead + # of eudev. + ResolverPlaygroundTestCase( + [ + 'virtual/dev-manager', + ], + success=True, + mergelist=( + 'sys-fs/eudev-3.1.5', + 'virtual/udev-0', + 'virtual/dev-manager-0', + ), + ), + # Test static-dev preference. + ResolverPlaygroundTestCase( + [ + 'sys-fs/static-dev', + 'virtual/dev-manager', + ], + all_permutations=True, + success=True, + mergelist=( + 'sys-fs/static-dev-0.1', + 'virtual/dev-manager-0', + ), + ), + ) + + playground = ResolverPlayground(debug=False, ebuilds=ebuilds) + + try: + for test_case in test_cases: + playground.run_TestCase(test_case) + self.assertEqual(test_case.test_success, True, + test_case.fail_msg) + finally: + playground.debug = False + playground.cleanup()
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/resolver/, pym/portage/dep/
commit: e2134e9f72a86734552bb67e9414a017cfc4ea51 Author: Zac Medico gentoo org> AuthorDate: Sat Jan 20 00:28:42 2018 + Commit: Zac Medico gentoo org> CommitDate: Sat Jan 20 23:08:42 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=e2134e9f dep_zapdeps: prefer choices with fewer new slots (bug 645002) Prefer choices with fewer new slots, rather than choices with the lowest total number of slots. This fixes a case triggered by the catalyst stage1 build, where paludis was selected to satisfy perl-cleaner dependencies because that choice happened to have a smaller number of slots: || ( ( sys-apps/portage app-portage/portage-utils ) sys-apps/pkgcore sys-apps/paludis ) Bug: https://bugs.gentoo.org/645002 Fixes: 9fdaf9bdbdf5 ("dep_check: use DNF to optimize overlapping virtual || deps (bug 632026)") Tested-by: Ben Kohler gmail.com> pym/portage/dep/dep_check.py | 14 ++-- .../resolver/test_virtual_minimize_children.py | 85 +- 2 files changed, 93 insertions(+), 6 deletions(-) diff --git a/pym/portage/dep/dep_check.py b/pym/portage/dep/dep_check.py index 291626f56..7cf338819 100644 --- a/pym/portage/dep/dep_check.py +++ b/pym/portage/dep/dep_check.py @@ -1,4 +1,4 @@ -# Copyright 2010-2015 Gentoo Foundation +# Copyright 2010-2018 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 from __future__ import unicode_literals @@ -296,7 +296,7 @@ def dep_eval(deplist): class _dep_choice(SlotObject): __slots__ = ('atoms', 'slot_map', 'cp_map', 'all_available', - 'all_installed_slots') + 'all_installed_slots', 'new_slot_count') def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None): """ @@ -498,9 +498,13 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None): if current_higher or (all_match_current and not all_match_previous): cp_map[avail_pkg.cp] = avail_pkg + new_slot_count = (len(slot_map) if graph_db is None else + sum(not graph_db.match_pkgs(slot_atom) for slot_atom in slot_map)) + this_choice = _dep_choice(atoms=atoms, slot_map=slot_map, cp_map=cp_map, all_available=all_available, - all_installed_slots=False) + all_installed_slots=False, + new_slot_count=new_slot_count) if all_available: # The "all installed" criterion is not version or slot specific. # If any version of a package is already in the graph then we @@ -655,8 +659,8 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None): if len(choices) < 2: continue # Prefer choices with all_installed_slots for bug #480736, and - # choices with a smaller number of packages for bug #632026. - choices.sort(key=lambda x: (not x.all_installed_slots, len(x.slot_map))) + # choices with a smaller number of new slots for bug #632026. + choices.sort(key=lambda x: (not x.all_installed_slots, x.new_slot_count)) for choice_1 in choices[1:]: cps = set(choice_1.cp_map) for choice_2 in choices: diff --git a/pym/portage/tests/resolver/test_virtual_minimize_children.py b/pym/portage/tests/resolver/test_virtual_minimize_children.py index 83ae34e77..6eb0409f2 100644 --- a/pym/portage/tests/resolver/test_virtual_minimize_children.py +++ b/pym/portage/tests/resolver/test_virtual_minimize_children.py @@ -1,4 +1,4 @@ -# Copyright 2017 Gentoo Foundation +# Copyright 2017-2018 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 from portage.tests import TestCase @@ -143,3 +143,86 @@ class VirtualMinimizeChildrenTestCase(TestCase): finally: playground.debug = False playground.cleanup() + + def testVirtualPackageManager(self): + ebuilds = { + 'app-admin/perl-cleaner-2.25': { + 'RDEPEND': ''' + || ( + ( sys-apps/portage app-portage/portage-utils ) + sys-apps/pkgcore + sys-apps/paludis + )''' + }, + 'app-portage/portage-utils-0.64': {}, + 'sys-apps/paludis-2.6.0': {}, + 'sys-apps/portage-2.3.19-r1': {}, + 'virtual/package-manager-0': { + 'RDEPEND': ''' +
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/resolver/, pym/portage/dep/
commit: 86ba22da7a2f34848cdb5a6f1090c22c264e577e Author: Zac Medico gentoo org> AuthorDate: Tue Jan 9 03:34:22 2018 + Commit: Zac Medico gentoo org> CommitDate: Thu Jan 11 19:23:34 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=86ba22da dep_zapdeps: install new package, allow upgrade (bug 643974) Prefer to install a new package in order to allow upgrade of an installed package. This generalizes the code from bug 635540 so that it both allows desirable upgrades and prevents unwanted downgrades. Fixes: 7c58e3737616 ("dep_zapdeps: install new package, avoid downgrade (bug 635540)") Bug: https://bugs.gentoo.org/643974 Reviewed-by: Alec Warner gentoo.org> pym/portage/dep/dep_check.py | 11 +-- .../tests/resolver/test_or_upgrade_installed.py| 101 + 2 files changed, 106 insertions(+), 6 deletions(-) diff --git a/pym/portage/dep/dep_check.py b/pym/portage/dep/dep_check.py index 2bb9dc339..291626f56 100644 --- a/pym/portage/dep/dep_check.py +++ b/pym/portage/dep/dep_check.py @@ -366,10 +366,8 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None): want_update_pkg = trees[myroot].get("want_update_pkg") downgrade_probe = trees[myroot].get("downgrade_probe") vardb = None - vardb_match_pkgs = None if "vartree" in trees[myroot]: vardb = trees[myroot]["vartree"].dbapi - vardb_match_pkgs = getattr(vardb, 'match_pkgs', None) if use_binaries: mydbapi = trees[myroot]["bintree"].dbapi else: @@ -465,10 +463,11 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None): avail_pkg = avail_pkg_use avail_slot = Atom("%s:%s" % (atom.cp, avail_pkg.slot)) - if vardb_match_pkgs is not None and downgrade_probe is not None: - inst_pkg = vardb_match_pkgs(avail_slot) - if (inst_pkg and avail_pkg < inst_pkg[-1] and - not downgrade_probe(inst_pkg[-1])): + if downgrade_probe is not None: + highest_in_slot = mydbapi_match_pkgs(avail_slot) + if (avail_pkg and highest_in_slot and + avail_pkg < highest_in_slot[-1] and + not downgrade_probe(avail_pkg)): installed_downgrade = True slot_map[avail_slot] = avail_pkg diff --git a/pym/portage/tests/resolver/test_or_upgrade_installed.py b/pym/portage/tests/resolver/test_or_upgrade_installed.py new file mode 100644 index 0..6e01d321d --- /dev/null +++ b/pym/portage/tests/resolver/test_or_upgrade_installed.py @@ -0,0 +1,101 @@ +# Copyright 2018 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +from portage.tests import TestCase +from portage.tests.resolver.ResolverPlayground import ( + ResolverPlayground, + ResolverPlaygroundTestCase, +) + +class OrUpgradeInstalledTestCase(TestCase): + + def testOrUpgradeInstalled(self): + ebuilds = { + 'net-misc/foo-1': { + 'EAPI': '6', + 'RDEPEND': '|| ( sys-libs/glibc[rpc(-)] net-libs/libtirpc )' + }, + 'net-libs/libtirpc-1': { + 'EAPI': '6', + }, + 'sys-libs/glibc-2.26': { + 'EAPI': '6', + 'IUSE': '' + }, + 'sys-libs/glibc-2.24': { + 'EAPI': '6', + 'IUSE': '+rpc' + }, + } + + installed = { + 'sys-libs/glibc-2.24': { + 'EAPI': '6', + 'IUSE': '+rpc', + 'USE': 'rpc', + }, + } + + world = ['sys-libs/glibc'] + + test_cases = ( + # Test bug 643974, where we need to install libtirpc + # in order to upgrade glibc. + ResolverPlaygroundTestCase( + ['net-misc/foo', '@world'], + options={'--update': True, '--deep': True}, + success=True, + ambiguous_merge_order=True, + mergelist=( + ( + 'net-libs/libtirpc-1', + '
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/bin/
commit: c040200175b33e637a4807278925e92cf61eb725 Author: Zac Medico gentoo org> AuthorDate: Tue Jan 9 20:28:27 2018 + Commit: Zac Medico gentoo org> CommitDate: Tue Jan 9 20:41:58 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=c0402001 testDoInsOption: fix timestamp comparison to work in travis Use integer comparison in order to avoid failures like the following: AssertionError: 1515530127.479328 != 1515530127.479327 pym/portage/tests/bin/test_doins.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pym/portage/tests/bin/test_doins.py b/pym/portage/tests/bin/test_doins.py index 9b6c55d85..e3d5153b3 100644 --- a/pym/portage/tests/bin/test_doins.py +++ b/pym/portage/tests/bin/test_doins.py @@ -45,8 +45,9 @@ class DoIns(setup_env.BinTestCase): st = os.lstat(env['D'] + '/test') if stat.S_IMODE(st.st_mode) != 0o644: raise tests.TestCase.failureException - if os.stat(os.path.join(env['S'], 'test')).st_mtime != st.st_mtime: - raise tests.TestCase.failureException + self.assertEqual( + os.stat(os.path.join(env['S'], 'test'))[stat.ST_MTIME], + st[stat.ST_MTIME]) finally: self.cleanup()
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/resolver/
commit: b47daf4d12ad54668c75f53661da4b252e665c22 Author: Zac Medico gentoo org> AuthorDate: Sat Dec 16 03:15:58 2017 + Commit: Zac Medico gentoo org> CommitDate: Sat Dec 16 03:16:30 2017 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=b47daf4d MultirepoTestCase: add missing EAPI definitions needed for slot deps pym/portage/tests/resolver/test_multirepo.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pym/portage/tests/resolver/test_multirepo.py b/pym/portage/tests/resolver/test_multirepo.py index 2b1a6d073..dabec6af9 100644 --- a/pym/portage/tests/resolver/test_multirepo.py +++ b/pym/portage/tests/resolver/test_multirepo.py @@ -42,7 +42,7 @@ class MultirepoTestCase(TestCase): } installed = { - "dev-libs/H-1": { "RDEPEND" : "|| ( dev-libs/I:2 dev-libs/I:1 )"}, + "dev-libs/H-1": { "RDEPEND" : "|| ( dev-libs/I:2 dev-libs/I:1 )", "EAPI" : "3" }, "dev-libs/I-2::repo1": {"SLOT" : "2"}, "dev-libs/K-1::repo1": { }, } @@ -277,7 +277,7 @@ class MultirepoTestCase(TestCase): } installed = { - "dev-libs/J-1": { "RDEPEND" : "|| ( dev-libs/I:2 dev-libs/I:1 )"}, + "dev-libs/J-1": { "RDEPEND" : "|| ( dev-libs/I:2 dev-libs/I:1 )", "EAPI" : "3" }, "dev-libs/I-2::repo1": {"SLOT" : "2"}, }
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/sync/, pym/portage/sync/modules/rsync/, ...
commit: 7d4612795d1d36d4284ad7bcbff5b88e3c74e993 Author: Ilya Tumaykin gmail com> AuthorDate: Mon May 23 13:43:48 2016 + Commit: Zac Medico gentoo org> CommitDate: Tue Nov 21 20:41:43 2017 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=7d461279 Fix sync_uri parsing for paths beginning with file:// Portage allows file URLs, i.e. paths beginning with 'file://', in sync_uri. According to RFC-1738 [1] a file URL must take the form 'file:///foo/bar' or 'file:///foo/bar', when is omitted (in this case localhost is assumed). Portage incorrectly parses file URLs because it leaves the second slash from the 'file://' prefix as a part of the URL. Additionally test suite incorrectly uses file URLs beginning with 'file:/' instead of 'file://'. This patch adjusts string offset so that file URLs are parsed correctly: >>> sync_uri='/foo/bar/baz' >>> ('file://' + sync_uri)[6:] '//foo/bar/baz' >>> ('file://' + sync_uri)[6:] == sync_uri False >>> ('file://' + sync_uri)[7:] '/foo/bar/baz' >>> ('file://' + sync_uri)[7:] == sync_uri True Additionally test suite is updated to use file URLs of the form 'file:///foo/bar' as required by the aforementioned RFC. [1]: https://tools.ietf.org/html/rfc1738#section-3.10 Closes: https://github.com/gentoo/portage/pull/28 pym/portage/sync/modules/git/git.py | 2 +- pym/portage/sync/modules/rsync/rsync.py | 2 +- pym/portage/tests/sync/test_sync_local.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pym/portage/sync/modules/git/git.py b/pym/portage/sync/modules/git/git.py index 8068149c7..8b4cab273 100644 --- a/pym/portage/sync/modules/git/git.py +++ b/pym/portage/sync/modules/git/git.py @@ -47,7 +47,7 @@ class GitSync(NewBase): sync_uri = self.repo.sync_uri if sync_uri.startswith("file://"): - sync_uri = sync_uri[6:] + sync_uri = sync_uri[7:] git_cmd_opts = "" if self.repo.module_specific_options.get('sync-git-env'): diff --git a/pym/portage/sync/modules/rsync/rsync.py b/pym/portage/sync/modules/rsync/rsync.py index 01e4e5924..c80641ba3 100644 --- a/pym/portage/sync/modules/rsync/rsync.py +++ b/pym/portage/sync/modules/rsync/rsync.py @@ -111,7 +111,7 @@ class RsyncSync(NewBase): if syncuri.startswith("file://"): self.proto = "file" - dosyncuri = syncuri[6:] + dosyncuri = syncuri[7:] is_synced, exitcode, updatecache_flg = self._do_rsync( dosyncuri, timestamp, opts) self._process_exitcode(exitcode, dosyncuri, out, 1) diff --git a/pym/portage/tests/sync/test_sync_local.py b/pym/portage/tests/sync/test_sync_local.py index 1d3856265..010c8f887 100644 --- a/pym/portage/tests/sync/test_sync_local.py +++ b/pym/portage/tests/sync/test_sync_local.py @@ -41,7 +41,7 @@ class SyncLocalTestCase(TestCase): [test_repo] location = %(EPREFIX)s/var/repositories/test_repo sync-type = %(sync-type)s - sync-uri = file:/%(EPREFIX)s/var/repositories/test_repo_sync + sync-uri = file://%(EPREFIX)s/var/repositories/test_repo_sync auto-sync = %(auto-sync)s %(repo_extra_keys)s """)
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/dep/, pym/portage/dep/, pym/portage/tests/resolver/
commit: 9fdaf9bdbdf500b7120aa95cb2ca421b931e6cea Author: Zac Medico gentoo org> AuthorDate: Sun Nov 5 22:21:43 2017 + Commit: Zac Medico gentoo org> CommitDate: Tue Nov 14 03:35:19 2017 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=9fdaf9bd dep_check: use DNF to optimize overlapping virtual || deps (bug 632026) Deps like these: || ( foo bar ) || ( bar baz ) Translate to disjunctive normal form (DNF): || ( ( foo bar ) ( foo baz ) ( bar bar ) ( bar baz ) ) Using DNF, if none of the packages are currently installed, then the ( bar bar ) choice will be automatically preferred since it is satisfied by the fewest number of packages. If the ( foo baz ) choice is already satisfied, then that choice will be preferred instead. Since DNF results in exponential explosion of the formula, only use DNF for the parts of the dependencies that have overlapping atoms. In order to simplify the implementation of the dnf_convert function, this patch also fixes _expand_new_virtuals to normalize results in the same way as use_reduce (with no redundant nested lists). Bug: https://bugs.gentoo.org/632026 Reviewed-by: Manuel Rüger gentoo.org> Reviewed-by: Alec Warner gentoo.org> pym/portage/dep/_dnf.py| 90 + pym/portage/dep/dep_check.py | 136 ++- pym/portage/tests/dep/test_dnf_convert.py | 48 +++ pym/portage/tests/dep/test_overlap_dnf.py | 28 .../resolver/test_virtual_minimize_children.py | 145 + 5 files changed, 440 insertions(+), 7 deletions(-) diff --git a/pym/portage/dep/_dnf.py b/pym/portage/dep/_dnf.py new file mode 100644 index 0..59657fd6a --- /dev/null +++ b/pym/portage/dep/_dnf.py @@ -0,0 +1,90 @@ +# Copyright 2017 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +from __future__ import unicode_literals + +import itertools + + +def dnf_convert(dep_struct): + """ + Convert dep_struct to disjunctive normal form (DNF), where dep_struct + is either a conjunction or disjunction of the form produced by + use_reduce(opconvert=True). + """ + # Normalize input to have a top-level conjunction. + if isinstance(dep_struct, list): + if dep_struct and dep_struct[0] == '||': + dep_struct = [dep_struct] + else: + dep_struct = [dep_struct] + + conjunction = [] + disjunctions = [] + + for x in dep_struct: + if isinstance (x, list): + assert x and x[0] == '||', \ + 'Normalization error, nested conjunction found in %s' % (dep_struct,) + if any(isinstance(element, list) for element in x): + x_dnf = ['||'] + for element in x[1:]: + if isinstance(element, list): + # Due to normalization, a disjunction must not be + # nested directly in another disjunction, so this + # must be a conjunction. + assert element, 'Normalization error, empty conjunction found in %s' % (x,) + assert element[0] != '||', \ + 'Normalization error, nested disjunction found in %s' % (x,) + element = dnf_convert(element) + if contains_disjunction(element): + assert (len(element) == 1 and + element[0] and element[0][0] == '||'), \ + 'Normalization error, expected single disjunction in %s' % (element,) + x_dnf.extend(element[0][1:]) + else: + x_dnf.append(element) + else: + x_dnf.append(element) + x = x_dnf + disjunctions.append(x) + else: + conjunction.append(x) + + if disjunctions and (conjunction or len(disjunctions) > 1): + dnf_form = ['||'] + for x in itertools.product(*[x[1:] for x in disjunctions]): + normalized = conjunction[:] + for element in x: + if isinstance(element, list): + normalized.extend(element) +
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/resolver/, pym/_emerge/
commit: 5a65670ec2b0850c278b85c6417c20d8a4ca7734 Author: Zac Medico gentoo org> AuthorDate: Fri Sep 29 07:02:27 2017 + Commit: Zac Medico gentoo org> CommitDate: Fri Sep 29 17:22:27 2017 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=5a65670e _solve_..slot_conflicts: make "forced" set recursive (bug 632210) When the slot conflict solver decides that it is "forced" to choose a particular package, recursively force the dependencies as well. Prior to this fix, substitution of @world in the arguments for SlotConflictMaskUpdateTestCase caused the test to fail because the solver removed boost-build-1.53.0 from the graph event though it had added the parent boost-1.53.0 package to the "forced" set. X-Gentoo-bug: 632210 X-Gentoo-bug-url: https://bugs.gentoo.org/632210 Acked-by: Brian Dolbec gentoo.org> pym/_emerge/depgraph.py | 13 + pym/portage/tests/resolver/test_slot_conflict_update.py | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py index 785c036b8..3b81c5c76 100644 --- a/pym/_emerge/depgraph.py +++ b/pym/_emerge/depgraph.py @@ -1457,6 +1457,19 @@ class depgraph(object): # Remove 'non_conflict_node' and or_tuples from 'forced'. forced = set(pkg for pkg in forced if isinstance(pkg, Package)) + + # Add dependendencies of forced packages. + stack = list(forced) + traversed = set() + while stack: + pkg = stack.pop() + traversed.add(pkg) + for child in conflict_graph.child_nodes(pkg): + if (isinstance(child, Package) and + child not in traversed): + forced.add(child) + stack.append(child) + non_forced = set(pkg for pkg in conflict_pkgs if pkg not in forced) if debug: diff --git a/pym/portage/tests/resolver/test_slot_conflict_update.py b/pym/portage/tests/resolver/test_slot_conflict_update.py index 331e5788b..f251d01f1 100644 --- a/pym/portage/tests/resolver/test_slot_conflict_update.py +++ b/pym/portage/tests/resolver/test_slot_conflict_update.py @@ -80,7 +80,7 @@ class SlotConflictUpdateTestCase(TestCase): # this behavior makes SlotConflictMaskUpdateTestCase # fail. ResolverPlaygroundTestCase( - world, + ['@world'], all_permutations = True, options = {"--update": True, "--deep": True}, success = True,
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/locks/, pym/_emerge/
commit: 504f66b0e25281e4465ebeceb799c3e54ff2b884 Author: Zac Medico gentoo org> AuthorDate: Mon Sep 11 21:01:39 2017 + Commit: Zac Medico gentoo org> CommitDate: Mon Sep 11 21:07:30 2017 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=504f66b0 AsynchronousLock: allow missing dummy_threading for Python 3.7 Python 3.7 does not support thread-less builds. Reported-by: Arfrever Frehtes Taifersar Arahesis Apache.Org> See: https://bugs.python.org/issue31370 X-Gentoo-bug: 630730 X-Gentoo-bug-url: https://bugs.gentoo.org/630730 pym/_emerge/AsynchronousLock.py | 6 +- pym/portage/tests/locks/test_asynchronous_lock.py | 8 +++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/pym/_emerge/AsynchronousLock.py b/pym/_emerge/AsynchronousLock.py index 6a32d2d40..fb0c2b30d 100644 --- a/pym/_emerge/AsynchronousLock.py +++ b/pym/_emerge/AsynchronousLock.py @@ -1,13 +1,17 @@ # Copyright 2010-2013 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 -import dummy_threading import fcntl import errno import logging import sys try: + import dummy_threading +except ImportError: + dummy_threading = None + +try: import threading except ImportError: threading = dummy_threading diff --git a/pym/portage/tests/locks/test_asynchronous_lock.py b/pym/portage/tests/locks/test_asynchronous_lock.py index ab67242d5..6493b6da6 100644 --- a/pym/portage/tests/locks/test_asynchronous_lock.py +++ b/pym/portage/tests/locks/test_asynchronous_lock.py @@ -5,6 +5,11 @@ import itertools import signal import tempfile +try: + import dummy_threading +except ImportError: + dummy_threading = None + from portage import os from portage import shutil from portage.tests import TestCase @@ -20,7 +25,8 @@ class AsynchronousLockTestCase(TestCase): path = os.path.join(tempdir, 'lock_me') for force_async, async_unlock in itertools.product( (True, False), repeat=2): - for force_dummy in (True, False): + for force_dummy in ((False,) if dummy_threading is None + else (True, False)): async_lock = AsynchronousLock(path=path, scheduler=scheduler, _force_async=force_async, _force_thread=True,
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/resolver/, pym/_emerge/, man/
commit: 46fac6698e5c73fda964819b508f1fe9dd341393 Author: Zac Medico gentoo org> AuthorDate: Sat Aug 12 17:16:46 2017 + Commit: Zac Medico gentoo org> CommitDate: Sat Aug 12 23:48:14 2017 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=46fac669 emerge: add --autounmask-keep-keywords option (bug 622480) The option prevents --autounmask from making changes to package.accept_keywords. This option does not imply --autounmask-keep-masks, so --autounmask is still allowed to create package.unmask changes unless the --autounmask-keep-masks is also specified. X-Gentoo-bug: 622480 X-Gentoo-bug-url: https://bugs.gentoo.org/622480 Reviewed-by: Manuel Rüger gentoo.org> man/emerge.1 | 7 +++ pym/_emerge/depgraph.py| 12 ++-- pym/_emerge/main.py| 9 +++ .../resolver/test_autounmask_keep_keywords.py | 72 ++ 4 files changed, 96 insertions(+), 4 deletions(-) diff --git a/man/emerge.1 b/man/emerge.1 index ffb453efb..12a0db166 100644 --- a/man/emerge.1 +++ b/man/emerge.1 @@ -395,6 +395,13 @@ using the \'=\' operator will be written. With this option, \'>=\' operators will be used whenever possible. USE and license changes always use the latter behavior. .TP +.BR "\-\-autounmask\-keep\-keywords [ y | n ]" +If \-\-autounmask is enabled, no package.accept_keywords changes will +be created. This leads to unsatisfied dependencies if any keyword +changes are required. This option does not imply \-\-autounmask\-keep\-masks, +so \-\-autounmask is still allowed to create package.unmask changes unless +the \-\-autounmask\-keep\-masks is also specified. +.TP .BR "\-\-autounmask\-keep\-masks [ y | n ]" If \-\-autounmask is enabled, no package.unmask or ** keyword changes will be created. This leads to unsatisfied dependencies if diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py index abe2cb1bd..b4fc5f297 100644 --- a/pym/_emerge/depgraph.py +++ b/pym/_emerge/depgraph.py @@ -5707,6 +5707,7 @@ class depgraph(object): if self._dynamic_config._autounmask is not True: return + autounmask_keep_keywords = self._frozen_config.myopts.get("--autounmask-keep-keywords", "n") != "n" autounmask_keep_masks = self._frozen_config.myopts.get("--autounmask-keep-masks", "n") != "n" autounmask_level = self._AutounmaskLevel() @@ -5716,14 +5717,16 @@ class depgraph(object): autounmask_level.allow_license_changes = True yield autounmask_level - autounmask_level.allow_unstable_keywords = True - yield autounmask_level - - if not autounmask_keep_masks: + if not autounmask_keep_keywords: + autounmask_level.allow_unstable_keywords = True + yield autounmask_level + if not (autounmask_keep_keywords or autounmask_keep_masks): + autounmask_level.allow_unstable_keywords = True autounmask_level.allow_missing_keywords = True yield autounmask_level + if not autounmask_keep_masks: # 4. USE + license + masks # Try to respect keywords while discarding # package.mask (see bug #463394). @@ -5732,6 +5735,7 @@ class depgraph(object): autounmask_level.allow_unmasks = True yield autounmask_level + if not (autounmask_keep_keywords or autounmask_keep_masks): autounmask_level.allow_unstable_keywords = True for missing_keyword, unmask in ((False, True), (True, True)): diff --git a/pym/_emerge/main.py b/pym/_emerge/main.py index 2132aa63c..d3a415b91 100644 --- a/pym/_emerge/main.py +++ b/pym/_emerge/main.py @@ -129,6 +129,7 @@ def insert_optional_args(args): '--autounmask' : y_or_n, '--autounmask-continue' : y_or_n, '--autounmask-only' : y_or_n, + '--autounmask-keep-keywords' : y_or_n, '--autounmask-keep-masks': y_or_n, '--autounmask-unrestricted-atoms' : y_or_n, '--autounmask-write' : y_or_n, @@ -348,6 +349,11 @@ def parse_opts(tmpcmdline, silent=False): "choices" : true_y_or_n }, + "--autounmask-keep-keywords": { + "help": "don't add package.accept_keywords entries", + "choices" : true_y_or_n + }, + "--autounmask-keep-masks": { "help": "don't add package.unmask entries", "choices" : true_y_or_n @@ -797,6 +803,9 @@ def parse_opts(tmpcmdline, silent=False): if myoptions.a
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/resolver/, pym/_emerge/
commit: 60af7e2696b96b47b0cd9e70caabd10546206b8b Author: Zac Medico gentoo org> AuthorDate: Mon May 29 08:22:40 2017 + Commit: Zac Medico gentoo org> CommitDate: Fri Jun 2 05:38:02 2017 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=60af7e26 depgraph: prune unnecessary rebuilds for --autounmask-continue (bug 619626) When there are autounmask USE changes, avoid unnecessary rebuilds by accepting binary packages that were rejected due to the preexisting USE configuration. This reuses the prune_rebuilds backtracker support which was added for bug 439688. X-Gentoo-bug: 619626 X-Gentoo-bug-url: https://bugs.gentoo.org/show_bug.cgi?id=619626 Acked-by: Brian Dolbec gentoo.org> pym/_emerge/depgraph.py| 96 ++ .../tests/resolver/test_autounmask_binpkg_use.py | 64 +++ 2 files changed, 142 insertions(+), 18 deletions(-) diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py index 2dc432431..abe2cb1bd 100644 --- a/pym/_emerge/depgraph.py +++ b/pym/_emerge/depgraph.py @@ -5,6 +5,7 @@ from __future__ import division, print_function, unicode_literals import collections import errno +import functools import io import logging import stat @@ -856,17 +857,11 @@ class depgraph(object): for parent in self._forced_rebuilds[root][child]: writemsg_stdout("%s\n" % (parent,), noiselevel=-1) - def _show_ignored_binaries(self): + def _eliminate_ignored_binaries(self): """ - Show binaries that have been ignored because their USE didn't - match the user's config. + Eliminate any package from self._dynamic_config.ignored_binaries + for which a more optimal alternative exists. """ - if not self._dynamic_config.ignored_binaries \ - or '--quiet' in self._frozen_config.myopts: - return - - ignored_binaries = {} - for pkg in list(self._dynamic_config.ignored_binaries): for selected_pkg in self._dynamic_config._package_tracker.match( @@ -894,10 +889,67 @@ class depgraph(object): self._dynamic_config.ignored_binaries.pop(pkg) break - else: - for reason, info in self._dynamic_config.\ - ignored_binaries[pkg].items(): - ignored_binaries.setdefault(reason, {})[pkg] = info + def _ignored_binaries_autounmask_backtrack(self): + """ + Check if there are ignored binaries that would have been + accepted with the current autounmask USE changes. + + @rtype: bool + @return: True if there are unnecessary rebuilds that + can be avoided by backtracking + """ + if not all([ + self._dynamic_config._allow_backtracking, + self._dynamic_config._needed_use_config_changes, + self._dynamic_config.ignored_binaries]): + return False + + self._eliminate_ignored_binaries() + + # _eliminate_ignored_binaries may have eliminated + # all of the ignored binaries + if not self._dynamic_config.ignored_binaries: + return False + + use_changes = collections.defaultdict( + functools.partial(collections.defaultdict, dict)) + for pkg, (new_use, changes) in self._dynamic_config._needed_use_config_changes.items(): + if pkg in self._dynamic_config.digraph: + use_changes[pkg.root][pkg.slot_atom] = (pkg, new_use) + + for pkg in self._dynamic_config.ignored_binaries: + selected_pkg, new_use = use_changes[pkg.root].get( + pkg.slot_atom, (None, None)) + if new_use is None: + continue + + if new_use != pkg.use.enabled: + continue + + if selected_pkg > pkg: + continue + + return True + + return False + + def _show_ignored_binaries(self): + """ + Show binaries that have been ignored because their USE didn't + match the user's config. + """ + if not self._dynamic_config.ignored_binaries \ + or '--quiet' in self._frozen_config.myopts: + return + + self._eliminate_ignored_binaries() + +
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/emerge/, pym/_emerge/
commit: 565ceb1bebc83ec1a5572a672e2e08ea7d91e7a8 Author: Zac Medico gentoo org> AuthorDate: Sun May 28 08:55:27 2017 + Commit: Zac Medico gentoo org> CommitDate: Tue May 30 03:30:50 2017 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=565ceb1b emerge: warn for --autounmask-continue with --autounmask=n (bug 619612) In order to avoid possible confusion when the user has specified --autounmask-continue and EMERGE_DEFAULT_OPTS contains --autounmask=n, display a warning message as follows: * --autounmask-continue has been disabled by --autounmask=n X-Gentoo-bug: 619612 X-Gentoo-bug-url: https://bugs.gentoo.org/show_bug.cgi?id=619612 Acked-by: Brian Dolbec gentoo.org> pym/_emerge/actions.py | 6 ++ pym/portage/tests/emerge/test_simple.py | 5 - 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/pym/_emerge/actions.py b/pym/_emerge/actions.py index 1bc20c3ed..c8a62fb01 100644 --- a/pym/_emerge/actions.py +++ b/pym/_emerge/actions.py @@ -2862,6 +2862,12 @@ def run_action(emerge_config): adjust_configs(emerge_config.opts, emerge_config.trees) apply_priorities(emerge_config.target_config.settings) + if ("--autounmask-continue" in emerge_config.opts and + emerge_config.opts.get("--autounmask") == "n"): + writemsg_level( + " %s --autounmask-continue has been disabled by --autounmask=n\n" % + warn("*"), level=logging.WARNING, noiselevel=-1) + for fmt in emerge_config.target_config.settings.get("PORTAGE_BINPKG_FORMAT", "").split(): if not fmt in portage.const.SUPPORTED_BINPKG_FORMATS: if "--pkg-format" in emerge_config.opts: diff --git a/pym/portage/tests/emerge/test_simple.py b/pym/portage/tests/emerge/test_simple.py index 5930f6cc8..f99c77927 100644 --- a/pym/portage/tests/emerge/test_simple.py +++ b/pym/portage/tests/emerge/test_simple.py @@ -311,7 +311,10 @@ pkg_preinst() { emerge_cmd + ("--unmerge", "--quiet", "dev-libs/A"), emerge_cmd + ("-C", "--quiet", "dev-libs/B"), - emerge_cmd + ("--autounmask-continue", "dev-libs/C",), + # If EMERGE_DEFAULT_OPTS contains --autounmask=n, then --autounmask + # must be specified with --autounmask-continue. + ({"EMERGE_DEFAULT_OPTS" : "--autounmask=n"},) + \ + emerge_cmd + ("--autounmask", "--autounmask-continue", "dev-libs/C",), # Verify that the above --autounmask-continue command caused # USE=flag to be applied correctly to dev-libs/D. portageq_cmd + ("match", eroot, "dev-libs/D[flag]"),
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/util/, pym/portage/util/
commit: c8c038fd4c201a582c420004b5ff759f28fe626b Author: Zac Medico gentoo org> AuthorDate: Wed Apr 19 04:39:31 2017 + Commit: Zac Medico gentoo org> CommitDate: Thu Apr 20 19:39:00 2017 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=c8c038fd digraph: add update and clear methods Also, optimize the add method to avoid creating a lot of duplicate priorities when called by the update method. Acked-by: Brian Dolbec gentoo.org> pym/portage/tests/util/test_digraph.py | 4 +++- pym/portage/util/digraph.py| 26 -- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/pym/portage/tests/util/test_digraph.py b/pym/portage/tests/util/test_digraph.py index f519536d3..01e075c99 100644 --- a/pym/portage/tests/util/test_digraph.py +++ b/pym/portage/tests/util/test_digraph.py @@ -88,7 +88,9 @@ class DigraphTest(TestCase): g.add("D", "A", 2) f = g.clone() - for x in g, f: + h = digraph() + h.update(f) + for x in g, f, h: self.assertEqual(bool(x), True) self.assertEqual(x.contains("A"), True) self.assertEqual(x.firstzero(), None) diff --git a/pym/portage/util/digraph.py b/pym/portage/util/digraph.py index 99b24fa1d..ba0e81c07 100644 --- a/pym/portage/util/digraph.py +++ b/pym/portage/util/digraph.py @@ -44,8 +44,10 @@ class digraph(object): priorities = [] self.nodes[node][1][parent] = priorities self.nodes[parent][0][node] = priorities - priorities.append(priority) - priorities.sort() + + if not priorities or priorities[-1] is not priority: + priorities.append(priority) + priorities.sort() def discard(self, node): """ @@ -73,6 +75,26 @@ class digraph(object): del self.nodes[node] self.order.remove(node) + def update(self, other): + """ + Add all nodes and edges from another digraph instance. + """ + for node in other.order: + children, parents, node = other.nodes[node] + if parents: + for parent, priorities in parents.items(): + for priority in priorities: + self.add(node, parent, priority=priority) + else: + self.add(node, None) + + def clear(self): + """ + Remove all nodes and edges. + """ + self.nodes.clear() + del self.order[:] + def difference_update(self, t): """ Remove all given nodes from node_set. This is more efficient
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/locks/, pym/_emerge/
commit: 916a0733c7201b7a8b22f5262bd5be8cbc8992a6 Author: Zac Medico gentoo org> AuthorDate: Sun Apr 2 20:50:09 2017 + Commit: Zac Medico gentoo org> CommitDate: Mon Apr 3 20:07:59 2017 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=916a0733 AsynchronousLock: add async_unlock method (bug 614108) Add an async_unlock method, in order to avoid event loop recursion which is incompatible with asyncio. X-Gentoo-bug: 614108 X-Gentoo-bug-url: https://bugs.gentoo.org/show_bug.cgi?id=614108 Acked-by: Brian Dolbec gentoo.org> pym/_emerge/AsynchronousLock.py | 89 +-- pym/portage/tests/locks/test_asynchronous_lock.py | 15 +++- 2 files changed, 92 insertions(+), 12 deletions(-) diff --git a/pym/_emerge/AsynchronousLock.py b/pym/_emerge/AsynchronousLock.py index c0b9b26dc..6a32d2d40 100644 --- a/pym/_emerge/AsynchronousLock.py +++ b/pym/_emerge/AsynchronousLock.py @@ -35,7 +35,7 @@ class AsynchronousLock(AsynchronousTask): __slots__ = ('path', 'scheduler',) + \ ('_imp', '_force_async', '_force_dummy', '_force_process', \ - '_force_thread') + '_force_thread', '_unlock_future') _use_process_by_default = True @@ -84,6 +84,11 @@ class AsynchronousLock(AsynchronousTask): return self.returncode def unlock(self): + """ + This method is deprecated in favor of async_unlock, since waiting + for the child process to respond can trigger event loop recursion + which is incompatible with asyncio. + """ if self._imp is None: raise AssertionError('not locked') if isinstance(self._imp, (_LockProcess, _LockThread)): @@ -92,6 +97,28 @@ class AsynchronousLock(AsynchronousTask): unlockfile(self._imp) self._imp = None + def async_unlock(self): + """ + Release the lock asynchronously. Release notification is available + via the add_done_callback method of the returned Future instance. + + @returns: Future, result is None + """ + if self._imp is None: + raise AssertionError('not locked') + if self._unlock_future is not None: + raise AssertionError("already unlocked") + if isinstance(self._imp, (_LockProcess, _LockThread)): + unlock_future = self._imp.async_unlock() + else: + unlockfile(self._imp) + unlock_future = self.scheduler.create_future() + self.scheduler.call_soon(unlock_future.set_result, None) + self._imp = None + self._unlock_future = unlock_future + return unlock_future + + class _LockThread(AbstractPollTask): """ This uses the portage.locks module to acquire a lock asynchronously, @@ -105,7 +132,7 @@ class _LockThread(AbstractPollTask): """ __slots__ = ('path',) + \ - ('_force_dummy', '_lock_obj', '_thread',) + ('_force_dummy', '_lock_obj', '_thread', '_unlock_future') def _start(self): self._registered = True @@ -132,13 +159,35 @@ class _LockThread(AbstractPollTask): pass def unlock(self): + """ + This method is deprecated in favor of async_unlock, for compatibility + with _LockProcess. + """ + self._unlock() + self._unlock_future.set_result(None) + + def _unlock(self): if self._lock_obj is None: raise AssertionError('not locked') if self.returncode is None: raise AssertionError('lock not acquired yet') + if self._unlock_future is not None: + raise AssertionError("already unlocked") + self._unlock_future = self.scheduler.create_future() unlockfile(self._lock_obj) self._lock_obj = None + def async_unlock(self): + """ + Release the lock asynchronously. Release notification is available + via the add_done_callback method of the returned Future instance. + + @returns: Future, result is None + """ + self._unlock() + self.scheduler.call_soon(self._unlock_future.set_result, None) + return self._unlock_future + def _unregister(self): self._registered = False @@ -156,7 +205,8 @@ class _LockProcess(AbstractPollTask): """ __slots__ = ('path',) + \ - ('_acquired', '_kill_test', '_proc', '_files', '_reg_id', '_unlocked') + ('_acquired', '_kil
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/resolver/, pym/_emerge/
commit: a83bb83909c5a6ac232c8eb5931b28027f4175af Author: Zac Medico gentoo org> AuthorDate: Sat Apr 1 03:53:03 2017 + Commit: Zac Medico gentoo org> CommitDate: Sat Apr 1 05:46:26 2017 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=a83bb839 depgraph: trigger slot operator rebuilds via _complete_graph (bug 614390) Fix _complete_graph to trigger rebuilds of parent packages when they pull in installed packages that had already been scheduled for rebuild by the previous calculation. X-Gentoo-bug: 614390 X-Gentoo-bug-url: https://bugs.gentoo.org/show_bug.cgi?id=614390 Acked-by: Brian Dolbec gentoo.org> pym/_emerge/depgraph.py| 15 +++ .../resolver/test_slot_operator_complete_graph.py | 141 + 2 files changed, 156 insertions(+) diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py index 04e724d8d..8a614c495 100644 --- a/pym/_emerge/depgraph.py +++ b/pym/_emerge/depgraph.py @@ -6649,6 +6649,21 @@ class depgraph(object): # will be appropriately reported as a slot collision # (possibly solvable via backtracking). pkg = matches[-1] # highest match + + if (self._dynamic_config._allow_backtracking and + not self._want_installed_pkg(pkg) and (dep.atom.soname or ( + dep.atom.package and dep.atom.slot_operator_built))): + # If pkg was already scheduled for rebuild by the previous + # calculation, then pulling in the installed instance will + # trigger a slot conflict that may go unsolved. Therefore, + # trigger a rebuild of the parent if appropriate. + dep.child = pkg + new_dep = self._slot_operator_update_probe(dep) + if new_dep is not None: + self._slot_operator_update_backtrack( + dep, new_dep=new_dep) + continue + if not self._add_pkg(pkg, dep): return 0 if not self._create_graph(allow_unsatisfied=True): diff --git a/pym/portage/tests/resolver/test_slot_operator_complete_graph.py b/pym/portage/tests/resolver/test_slot_operator_complete_graph.py new file mode 100644 index 0..1d59bcef1 --- /dev/null +++ b/pym/portage/tests/resolver/test_slot_operator_complete_graph.py @@ -0,0 +1,141 @@ +# Copyright 2017 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +from portage.tests import TestCase +from portage.tests.resolver.ResolverPlayground import ( + ResolverPlayground, + ResolverPlaygroundTestCase, +) + +class SlotOperatorCompleteGraphTestCase(TestCase): + + def testSlotOperatorCompleteGraph(self): + + ebuilds = { + "app-misc/meta-pkg-2" : { + "EAPI": "6", + "DEPEND": "=app-misc/B-2 =app-misc/C-1 =app-misc/D-1 =dev-libs/foo-2", + "RDEPEND": "=app-misc/B-2 =app-misc/C-1 =app-misc/D-1 =dev-libs/foo-2", + }, + + "app-misc/meta-pkg-1" : { + "EAPI": "6", + "DEPEND": "=app-misc/B-1 =app-misc/C-1 =app-misc/D-1 =dev-libs/foo-1", + "RDEPEND": "=app-misc/B-1 =app-misc/C-1 =app-misc/D-1 =dev-libs/foo-1", + }, + + "app-misc/B-1" : { + "EAPI": "6", + "DEPEND": "dev-libs/foo:=", + "RDEPEND": "dev-libs/foo:=", + }, + + "app-misc/B-2" : { + "EAPI": "6", + "DEPEND": "dev-libs/foo:=", + "RDEPEND": "dev-libs/foo:=", + }, + + "app-misc/C-1" : { + "EAPI": "6", + "DEPEND": "dev-libs/foo:= app-misc/B", + "RDEPEND": "dev-libs/foo:= app-misc/B", + }, + + "app-misc/C-2" : { + "EAPI": "6", + "DEPEND": "dev-libs/foo:= app-misc/B", + "RDEPEND": "dev-libs/foo:= app-misc/B", + }, + + "app-misc/D-1" : { +
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/util/eventloop/
commit: 96f0ed20ba8e079e351b2dd729d3386e59838ef3 Author: Zac Medico gentoo org> AuthorDate: Sun Mar 26 07:03:00 2017 + Commit: Zac Medico gentoo org> CommitDate: Sun Mar 26 07:03:26 2017 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=96f0ed20 tests: add missing files in util/eventloop directory Fixes: 04b1012594bf ("EventLoop: implement call_soon for asyncio compat (bug 591760)") pym/portage/tests/util/eventloop/__init__.py | 0 pym/portage/tests/util/eventloop/__test__.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/pym/portage/tests/util/eventloop/__init__.py b/pym/portage/tests/util/eventloop/__init__.py new file mode 100644 index 0..e69de29bb diff --git a/pym/portage/tests/util/eventloop/__test__.py b/pym/portage/tests/util/eventloop/__test__.py new file mode 100644 index 0..e69de29bb
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/resolver/, pym/_emerge/
commit: 82bfd91325b052a4c9250a04939641c15b3d2a20 Author: Zac Medico gentoo org> AuthorDate: Mon Mar 20 23:13:42 2017 + Commit: Zac Medico gentoo org> CommitDate: Wed Mar 22 08:58:44 2017 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=82bfd913 emerge: fix --usepkg when ebuild is not available (bug 613360) Fix emerge --usepkg to use a binary package when the corresponding ebuild is not available (and --use-ebuild-visibility is not enabled), in cases when no other package is available to satisfy the dependency. This reverts an unintended behavior change from commit e309323f156528a8a79a1f755e1326e8880346b7. Fixes: e309323f1565 ("emerge: fix --use-ebuild-visibility to reject binary packages (bug 612960)") X-Gentoo-bug: 613360 X-Gentoo-bug-url: https://bugs.gentoo.org/show_bug.cgi?id=613360 Acked-by: Brian Dolbec gentoo.org> pym/_emerge/depgraph.py| 3 ++- .../resolver/test_binary_pkg_ebuild_visibility.py | 26 ++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py index 543f4dc78..7c9130b38 100644 --- a/pym/_emerge/depgraph.py +++ b/pym/_emerge/depgraph.py @@ -6062,7 +6062,8 @@ class depgraph(object): identical_binary = True break - if not identical_binary and pkg.built: + if (not identical_binary and pkg.built and + (use_ebuild_visibility or matched_packages)): # If the ebuild no longer exists or it's # keywords have been dropped, reject built # instances (installed or binary). diff --git a/pym/portage/tests/resolver/test_binary_pkg_ebuild_visibility.py b/pym/portage/tests/resolver/test_binary_pkg_ebuild_visibility.py index ea65abded..0d01d0696 100644 --- a/pym/portage/tests/resolver/test_binary_pkg_ebuild_visibility.py +++ b/pym/portage/tests/resolver/test_binary_pkg_ebuild_visibility.py @@ -104,6 +104,32 @@ class BinaryPkgEbuildVisibilityTestCase(TestCase): '[binary]app-misc/foo-3', ], ), + + # The default behavior is to enforce ebuild visibility as + # long as a visible package is available to satisfy the + # current atom. In the following test case, ebuild visibility + # is ignored in order to satisfy the =app-misc/foo-3 atom. + ResolverPlaygroundTestCase( + ["=app-misc/foo-3"], + options = { + "--usepkg": True, + }, + success = True, + mergelist = [ + '[binary]app-misc/foo-3', + ], + ), + + # Verify that --use-ebuild-visibility works with --usepkg + # when no other visible package is available. + ResolverPlaygroundTestCase( + ["=app-misc/foo-3"], + options = { + "--use-ebuild-visibility": "y", + "--usepkg": True, + }, + success = False, + ), ) playground = ResolverPlayground(binpkgs=binpkgs, ebuilds=ebuilds,
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/resolver/, pym/_emerge/
commit: 15e67f5516e0779d2cba37704c15b42193808197 Author: Zac Medico gentoo org> AuthorDate: Wed Mar 15 21:34:37 2017 + Commit: Zac Medico gentoo org> CommitDate: Thu Mar 16 04:47:41 2017 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=15e67f55 depgraph: fix slot operator rebuild for llvm:0 to llvm:4 upgrade (bug 612772) Fix check_reverse_dependencies to ignore dependencies of parent packages that could be uninstalled in order to solve a blocker conflict. This case is similar to the one from bug 584626, except that the relevant parent package is in an older slot which is blocked by a newer slot. In this case, the _upgrade_available method returns False, because the package in the older slot is the highest version version available for its slot. Therefore, a new _in_blocker_conflict method is needed to detect parent packages that could be uninstalled. The included unit test fails without this fix. Since the _in_blocker_conflict method requires information that is collected by the _validate_blockers method, the _validate_blockers method now has to be called before the _process_slot_conflict and _slot_operator_trigger_reinstalls methods. X-Gentoo-bug: 612772 X-Gentoo-bug-url: https://bugs.gentoo.org/show_bug.cgi?id=612772 Acked-by: Brian Dolbec gentoo.org> pym/_emerge/depgraph.py| 59 --- .../resolver/test_slot_operator_exclusive_slots.py | 109 + 2 files changed, 155 insertions(+), 13 deletions(-) diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py index 1379b0563..ad94fb70f 100644 --- a/pym/_emerge/depgraph.py +++ b/pym/_emerge/depgraph.py @@ -387,7 +387,10 @@ class _dynamic_depgraph_config(object): # Contains only unsolvable Package -> Blocker edges self._unsolvable_blockers = digraph() # Contains all Blocker -> Blocked Package edges - self._blocked_pkgs = digraph() + # Do not initialize this until the depgraph _validate_blockers + # method is called, so that the _in_blocker_conflict method can + # assert that _validate_blockers has been called first. + self._blocked_pkgs = None # Contains world packages that have been protected from # uninstallation but may not have been added to the graph # if the graph is not complete yet. @@ -1466,9 +1469,22 @@ class depgraph(object): self._solve_non_slot_operator_slot_conflicts() + if not self._validate_blockers(): + # Blockers don't trigger the _skip_restart flag, since + # backtracking may solve blockers when it solves slot + # conflicts (or by blind luck). + raise self._unknown_internal_error() + + # Both _process_slot_conflict and _slot_operator_trigger_reinstalls + # can call _slot_operator_update_probe, which requires that + # self._dynamic_config._blocked_pkgs has been initialized by a + # call to the _validate_blockers method. for conflict in self._dynamic_config._package_tracker.slot_conflicts(): self._process_slot_conflict(conflict) + if self._dynamic_config._allow_backtracking: + self._slot_operator_trigger_reinstalls() + def _process_slot_conflict(self, conflict): """ Process slot conflict data to identify specific atoms which @@ -1829,9 +1845,12 @@ class depgraph(object): not self._frozen_config.excluded_pkgs. findAtomForPackage(parent, modified_use=self._pkg_use_enabled(parent)) and - self._upgrade_available(parent)): + (self._upgrade_available(parent) or + (parent.installed and self._in_blocker_conflict(parent: # This parent may be irrelevant, since an - # update is available (see bug 584626). + # update is available (see bug 584626), or + # it could be uninstalled in order to solve + # a blocker conflict (bug 612772). continue atom_set = InternalPackageSet(initial_atoms=(atom,), @@ -2125,6 +2144,24 @@ class depgraph(object): self._dynamic_config._need_restart = True + def _in_blocker_conflict(self, pkg): + """ + Check if pkg is
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/util/, pym/portage/
commit: b773fc08fe7b20b46a810b6eca85e489a69fb8ac Author: Michał Górny gentoo org> AuthorDate: Sun Mar 12 16:50:48 2017 + Commit: Michał Górny gentoo org> CommitDate: Mon Mar 13 21:46:30 2017 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=b773fc08 Support STREEBOG{256,512} hash function (from pygcrypt), #597736 pym/portage/checksum.py | 5 - pym/portage/const.py| 3 ++- pym/portage/tests/util/test_checksum.py | 18 ++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/pym/portage/checksum.py b/pym/portage/checksum.py index 92b41b133..3ee100c3f 100644 --- a/pym/portage/checksum.py +++ b/pym/portage/checksum.py @@ -137,7 +137,8 @@ if "SHA3_256" not in hashfunc_map or "SHA3_512" not in hashfunc_map: # Support pygcrypt as fallback using optimized routines from libgcrypt # (GnuPG). -gcrypt_algos = frozenset(('RMD160', 'WHIRLPOOL', 'SHA3_256', 'SHA3_512')) +gcrypt_algos = frozenset(('RMD160', 'WHIRLPOOL', 'SHA3_256', 'SHA3_512', + 'STREEBOG256', 'STREEBOG512')) if gcrypt_algos.difference(hashfunc_map): try: import binascii @@ -158,6 +159,8 @@ if gcrypt_algos.difference(hashfunc_map): 'WHIRLPOOL': 'whirlpool', 'SHA3_256': 'sha3-256', 'SHA3_512': 'sha3-512', + 'STREEBOG256': 'stribog256', + 'STREEBOG512': 'stribog512', } for local_name, gcry_name in name_mapping.items(): diff --git a/pym/portage/const.py b/pym/portage/const.py index 0cef2e8ae..7e415ba9c 100644 --- a/pym/portage/const.py +++ b/pym/portage/const.py @@ -232,7 +232,8 @@ MANIFEST1_REQUIRED_HASH = "MD5" # - Remove redundant settings from gentoo-x86/metadata/layout.conf. MANIFEST2_HASH_FUNCTIONS = ("SHA256", "SHA512", "WHIRLPOOL", - "BLAKE2B", "BLAKE2S", "SHA3_256", "SHA3_512") + "BLAKE2B", "BLAKE2S", "SHA3_256", "SHA3_512", + "STREEBOG256", "STREEBOG512") MANIFEST2_HASH_DEFAULTS = frozenset(["SHA256", "SHA512", "WHIRLPOOL"]) MANIFEST2_REQUIRED_HASH = "SHA256" diff --git a/pym/portage/tests/util/test_checksum.py b/pym/portage/tests/util/test_checksum.py index 72b8cef3f..01ac8f9d0 100644 --- a/pym/portage/tests/util/test_checksum.py +++ b/pym/portage/tests/util/test_checksum.py @@ -86,3 +86,21 @@ class ChecksumTestCase(TestCase): '6634c004dc31822fa65c2f1e2e3bbf0cfa35085653cca1ca9ca42f8f3f13c908405e0b665918146181c9fc9a9d793fc05429d669c35a55517820dfaa071425ca') except DigestException: self.skipTest('SHA3_512 implementation not available') + + def test_streebog256(self): + try: + self.assertEqual(checksum_str(b'', 'STREEBOG256'), + '3f539a213e97c802cc229d474c6aa32a825a360b2a933a949fd925208d9ce1bb') + self.assertEqual(checksum_str(self.text, 'STREEBOG256'), + '4992f1239c46f15b89e7b83ded4d83fb5966da3692788a4a1a6d118f78c08444') + except DigestException: + self.skipTest('STREEBOG256 implementation not available') + + def test_streebog512(self): + try: + self.assertEqual(checksum_str(b'', 'STREEBOG512'), + '8e945da209aa869f0455928529bcae4679e9873ab707b55315f56ceb98bef0a7362f715528356ee83cda5f2aac4c6ad2ba3a715c1bcd81cb8e9f90bf4c1c1a8a') + self.assertEqual(checksum_str(self.text, 'STREEBOG512'), + '330f5c26437f4e22c0163c72b12e93b8c27202f0750627355bdee43a0e0b253c90fbf0a27adbe5414019ff01ed84b7b240a1da1cbe10fae3adffc39c2d87a51f') + except DigestException: + self.skipTest('STREEBOG512 implementation not available')
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/util/
commit: 04c2bbaba38e766250fee019fd9bbb98ba582038 Author: Michał Górny gentoo org> AuthorDate: Sun Mar 12 15:12:48 2017 + Commit: Michał Górny gentoo org> CommitDate: Mon Mar 13 21:46:29 2017 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=04c2bbab tests: Add minimal safety checks for checksums pym/portage/tests/util/test_checksum.py | 88 + 1 file changed, 88 insertions(+) diff --git a/pym/portage/tests/util/test_checksum.py b/pym/portage/tests/util/test_checksum.py new file mode 100644 index 0..72b8cef3f --- /dev/null +++ b/pym/portage/tests/util/test_checksum.py @@ -0,0 +1,88 @@ +# Copyright 2011-2017 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +from portage.tests import TestCase + +from portage.checksum import checksum_str +from portage.exception import DigestException + +class ChecksumTestCase(TestCase): + text = b'Some test string used to check if the hash works' + + def test_md5(self): + self.assertEqual(checksum_str(b'', 'MD5'), + 'd41d8cd98f00b204e9800998ecf8427e') + self.assertEqual(checksum_str(self.text, 'MD5'), + '094c3bf4732f59b39d577e9726f1e934') + + def test_sha1(self): + self.assertEqual(checksum_str(b'', 'SHA1'), + 'da39a3ee5e6b4b0d3255bfef95601890afd80709') + self.assertEqual(checksum_str(self.text, 'SHA1'), + '5c572017d4e4d49e4aa03a2eda12dbb54a1e2e4f') + + def test_sha256(self): + self.assertEqual(checksum_str(b'', 'SHA256'), + 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855') + self.assertEqual(checksum_str(self.text, 'SHA256'), + 'e3d4a1135181fe156d61455615bb6296198e8ca5b2f20ddeb85cb4cd27f62320') + + def test_sha512(self): + self.assertEqual(checksum_str(b'', 'SHA512'), + 'cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e') + self.assertEqual(checksum_str(self.text, 'SHA512'), + 'c8eaa902d48a2c82c2185a92f1c8bab8115c63c8d7a9966a8e8e81b07abcb9762f4707a6b27075e9d720277ba9fec072a59840d6355dd2ee64681d8f39a50856') + + def test_rmd160(self): + try: + self.assertEqual(checksum_str(b'', 'RMD160'), + '9c1185a5c5e9fc54612808977ee8f548b2258d31') + self.assertEqual(checksum_str(self.text, 'RMD160'), + 'fc453174f63fc011d6f64abd2c45fb6a53c8239b') + except DigestException: + self.skipTest('RMD160 implementation not available') + + def test_whirlpool(self): + try: + self.assertEqual(checksum_str(b'', 'WHIRLPOOL'), + '19fa61d75522a4669b44e39c1d2e1726c530232130d407f89afee0964997f7a73e83be698b288febcf88e3e03c4f0757ea8964e59b63d93708b138cc42a66eb3') + self.assertEqual(checksum_str(self.text, 'WHIRLPOOL'), + '8f556a079b87057f19e0880eed6d833e40c916f4b133196f6842281a2517873074d399832470c11ee251696b4844a10197714a069ba3e3415c8a4eced8f91b48') + except DigestException: + self.skipTest('WHIRLPOOL implementation not available') + + def test_blake2b(self): + try: + self.assertEqual(checksum_str(b'', 'BLAKE2B'), + '786a02f742015903c6c6fd852552d272912f4740e15847618a86e217f71f5419d25e1031afee585313896444934eb04b903a685b1448b755d56f701afe9be2ce') + self.assertEqual(checksum_str(self.text, 'BLAKE2B'), + '84cb3c88838c7147bc9797c6525f812adcdcb40137f9c075963e3a3ed1fe06aaeeb4d2bb5589bad286864dc1aa834cfc4d66b8d7e4d4a246d91d45ce3a6eee43') + except DigestException: + self.skipTest('BLAKE2B implementation not available') + + def test_blake2s(self): + try: + self.assertEqual(checksum_str(b'', 'BLAKE2S'), + '69217a3079908094e11121d042354a7c1f55b6482ca1a51e1b250dfd1ed0eef9') + self.assertEqual(checksum_str(self.text, 'BLAKE2S'), + '823ab2429f27690450efe888b0404d092fe2ee72a9bd63d5342c251b4dbb373d') + except DigestException: + self.skipTest('BLAKE2S implementation not available') + + def test_sha3_256(self): + try: + self.assertEqual(checksum_str(b'', 'SHA3_256'), +
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/resolver/, pym/_emerge/
commit: c01f3fbd23def329eb1d1b0fc8f79959119a8a82 Author: Zac Medico gentoo org> AuthorDate: Wed Mar 8 22:25:56 2017 + Commit: Zac Medico gentoo org> CommitDate: Thu Mar 9 19:33:54 2017 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=c01f3fbd depgraph: fix runtime package mask interaction with slot operator rebuilds (bug 612094) In some cases the backtracking runtime package mask can interact badly with slot operator rebuilds, preventing a solution from being found. This patch fixes the problem, which is demonstrated by the included unit test. X-Gentoo-bug: 612094 X-Gentoo-bug-url: https://bugs.gentoo.org/show_bug.cgi?id=612094 Acked-by: Brian Dolbec gentoo.org> pym/_emerge/depgraph.py| 28 +++-- .../test_slot_operator_runtime_pkg_mask.py | 136 + 2 files changed, 152 insertions(+), 12 deletions(-) diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py index bb3e307f0..1379b0563 100644 --- a/pym/_emerge/depgraph.py +++ b/pym/_emerge/depgraph.py @@ -1597,9 +1597,6 @@ class depgraph(object): atom.package and atom.slot_operator_built): continue - if pkg not in conflict_pkgs: - continue - for other_pkg in slot_nodes: if other_pkg in conflict_pkgs: continue @@ -2569,18 +2566,25 @@ class depgraph(object): # runtime_pkg_mask, since that would trigger an # infinite backtracking loop. if self._dynamic_config._allow_backtracking: - if dep.parent in self._dynamic_config._runtime_pkg_mask: - if debug: - writemsg( - "!!! backtracking loop detected: %s %s\n" % \ - (dep.parent, - self._dynamic_config._runtime_pkg_mask[ - dep.parent]), noiselevel=-1) - elif dep.atom.package and dep.atom.slot_operator_built and \ - self._slot_operator_unsatisfied_probe(dep): + if (dep.parent not in self._dynamic_config._runtime_pkg_mask and + dep.atom.package and dep.atom.slot_operator_built and + self._slot_operator_unsatisfied_probe(dep)): self._slot_operator_unsatisfied_backtrack(dep) return 1 else: + # This is for backward-compatibility with previous + # behavior, so that installed packages with unsatisfied + # dependencies trigger an error message but do not + # cause the dependency calculation to fail. Only do + # this if the parent is already in the runtime package + # mask, since otherwise we need to backtrack. + if (dep.parent.installed and + dep.parent in self._dynamic_config._runtime_pkg_mask and + not any(self._iter_match_pkgs_any( + dep.parent.root_config, dep.atom))): + self._dynamic_config._initially_unsatisfied_deps.append(dep) + return 1 + # Do not backtrack if only USE have to be changed in # order to satisfy the dependency. Note that when # want_restart_for_use_change sets the need_restart diff --git a/pym/portage/tests/resolver/test_slot_operator_runtime_pkg_mask.py b/pym/portage/tests/resolver/test_slot_operator_runtime_pkg_mask.py new file mode 100644 index 0..0a5a7fa78 --- /dev/null +++ b/pym/portage/tests/resolver/test_slot_operator_runtime_pkg_mask.py @@ -0,0 +1,136 @@ +# Copyright 2017 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +from portage.tests import TestCase +from portage.tests.resolver.ResolverPlayground import ( + ResolverPlayground, + ResolverPlaygroundTestCase, +) + +class SlotOperatorRuntimePkgMaskTestCase(TestCase): + + def testSlotOperatorRuntimePkgMask(self): + + ebuilds = { +
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/resolver/, pym/portage/tests/resolver/soname/, pym/_emerge/
commit: 7c01a73c5a3ff969ddaa43e91730a7372a8a10c8 Author: Zac Medico gentoo org> AuthorDate: Wed Mar 8 01:30:05 2017 + Commit: Zac Medico gentoo org> CommitDate: Wed Mar 8 19:36:20 2017 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=7c01a73c depgraph: fix backtracking for slot operator rebuilds (bug 612042) Fix package selection logic to avoid pulling in undesirable rebuilds/updates during backtracking for slot operator rebuilds. The undesirable rebuilds/updates have sent some calculations off course, by triggering more and more rebuilds/updates with each backtracking run. In order to solve the problem, make various adjustments to the package selection logic so that installed packages are preferred over rebuilds/updates when appropriate. Also update unit tests to work with these adjustments. Fixes: 5842e87872fd ("Fix slot operator handling bug") X-Gentoo-bug: 612042 X-Gentoo-bug-url: https://bugs.gentoo.org/show_bug.cgi?id=612042 Acked-by: Brian Dolbec gentoo.org> pym/_emerge/depgraph.py | 11 +-- .../resolver/soname/test_slot_conflict_reinstall.py | 16 +++- pym/portage/tests/resolver/test_slot_abi.py | 12 +--- pym/portage/tests/resolver/test_slot_conflict_rebuild.py | 8 +++- 4 files changed, 36 insertions(+), 11 deletions(-) diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py index 02a32260a..bb3e307f0 100644 --- a/pym/_emerge/depgraph.py +++ b/pym/_emerge/depgraph.py @@ -2304,7 +2304,7 @@ class depgraph(object): # Check for slot update first, since we don't want to # trigger reinstall of the child package when a newer # slot will be used instead. - if rebuild_if_new_slot: + if rebuild_if_new_slot and dep.want_update: new_dep = self._slot_operator_update_probe(dep, new_child_slot=True) if new_dep is not None: @@ -6241,7 +6241,7 @@ class depgraph(object): if highest_installed is None or pkg.version > highest_installed.version: highest_installed = pkg - if highest_installed: + if highest_installed and self._want_update_pkg(parent, highest_installed): non_installed = [pkg for pkg in matched_packages \ if not pkg.installed and pkg.version > highest_installed.version] @@ -6285,11 +6285,18 @@ class depgraph(object): built_timestamp != installed_timestamp: return built_pkg, existing_node + inst_pkg = None for pkg in matched_packages: + if pkg.installed: + inst_pkg = pkg if pkg.installed and pkg.invalid: matched_packages = [x for x in \ matched_packages if x is not pkg] + if (inst_pkg is not None and parent is not None and + not self._want_update_pkg(parent, inst_pkg)): + return inst_pkg, existing_node + if avoid_update: for pkg in matched_packages: if pkg.installed and self._pkg_visibility_check(pkg, autounmask_level): diff --git a/pym/portage/tests/resolver/soname/test_slot_conflict_reinstall.py b/pym/portage/tests/resolver/soname/test_slot_conflict_reinstall.py index f4747611f..f7154442e 100644 --- a/pym/portage/tests/resolver/soname/test_slot_conflict_reinstall.py +++ b/pym/portage/tests/resolver/soname/test_slot_conflict_reinstall.py @@ -251,13 +251,27 @@ class SonameSlotConflictReinstallTestCase(TestCase): success = True, mergelist = [ '[binary]app-misc/B-2', + '[binary]app-misc/A-2', + ] + ), + ResolverPlaygroundTestCase( + ["@world"], + options = { + "--ignore-soname-deps": "n", + "--usepkgonly": True, + "--update": True, + "--d
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/resolver/, man/, pym/_emerge/
commit: 852c729bdef3d4c2e2d459a43dc21f0a05dfa2ba Author: Zac Medico gentoo org> AuthorDate: Sat Mar 4 06:24:21 2017 + Commit: Zac Medico gentoo org> CommitDate: Wed Mar 8 19:19:53 2017 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=852c729b emerge: auto-enable --with-bdeps if --usepkg is not enabled (bug 598444) It's useful to automatically enable --with-bdeps so that @world updates will update all packages that are not eligible for removal by emerge --depclean. However, many users of binary packages do not want unnecessary build time dependencies installed, therefore do not auto-enable --with-bdeps for installation actions when the --usepkg option is enabled. A new --with-bdeps-auto= option is provided, making it possible to enable or disable the program logic that causes --with-bdeps to be automatically enabled. Use --with-bdeps-auto=n to prevent --with-bdeps from being automatically enabled for installation actions. This is useful for some rare cases in which --with-bdeps triggers unsolvable dependency conflicts (and putting --with-bdeps=n in EMERGE_DEFAULT_OPTS would cause undesirable --depclean behavior). X-Gentoo-bug: 598444 X-Gentoo-bug-url: https://bugs.gentoo.org/show_bug.cgi?id=598444 Acked-by: Brian Dolbec gentoo.org> man/emerge.1 | 37 +++- pym/_emerge/create_depgraph_params.py| 5 + pym/_emerge/depgraph.py | 4 +- pym/_emerge/main.py | 5 + pym/portage/tests/resolver/ResolverPlayground.py | 5 + pym/portage/tests/resolver/test_bdeps.py | 215 +++ 6 files changed, 266 insertions(+), 5 deletions(-) diff --git a/man/emerge.1 b/man/emerge.1 index 5b6122023..7db427199 100644 --- a/man/emerge.1 +++ b/man/emerge.1 @@ -986,13 +986,44 @@ The default is set to "y" (on). .TP .BR "\-\-with\-bdeps < y | n >" In dependency calculations, pull in build time dependencies -that are not strictly required. This defaults to \'n\' for -installation actions, meaning they will not be installed, and -\'y\' for the \fB\-\-depclean\fR action, meaning they will not be removed. +that are not strictly required. This option is automatically enabled for +installation actions, meaning they will be installed, and defaults to +\(aqy\(aq for the \fB\-\-depclean\fR action, meaning they will not be +removed. In order to prevent the \fB\-\-with\-bdeps\fR option from being +automatically enabled for installation actions, specify +\fB\-\-with\-bdeps\-auto=n\fR in either the command line or +\fBEMERGE_DEFAULT_OPTS\fR. + +Since many users of binary packages do not want unnecessary build time +dependencies installed, this option is not automatically enabled for +installation actions when the \fB\-\-usepkg\fR option is enabled. In +order to pull in build time dependencies for binary packages with +\fB\-\-usepkg\fR, \fB\-\-with\-bdeps=y\fR must be specified explicitly. +This also applies to options that enable the \fB\-\-usepkg\fR option +implicitly, such as \fB\-\-getbinpkg\fR. + This setting can be added to \fBEMERGE_DEFAULT_OPTS\fR (see make.conf(5)) and later overridden via the command line. .TP +.BR "\-\-with\-bdeps\-auto < y | n >" +This option is used to enable or disable the program logic that causes +\fB\-\-with\-bdeps\fR is to be automatically enabled for installation +actions. This option is enabled by default. Use +\fB\-\-with\-bdeps\-auto=n\fR to prevent \fB\-\-with\-bdeps\fR from +being automatically enabled for installation actions. This setting can +be added to \fBEMERGE_DEFAULT_OPTS\fR (see make.conf(5)) and later +overridden via the command line. + +\fBNOTE:\fR The program logic that causes \fB\-\-with\-bdeps\fR to be +automatically enabled for installation actions does not affect removal +actions such as the \fB\-\-depclean\fR action. Therefore, when +\fB\-\-with\-bdeps\-auto=n\fR is specified in \fBEMERGE_DEFAULT_OPTS\fR, +it does not affect the default \fB\-\-with\-bdeps=y\fR setting that +applies to the \fB\-\-depclean\fR action. The default +\fB\-\-with\-bdeps=y\fR setting that applies to the \fB\-\-depclean\fR +action can be overridden only by specifying \fB\-\-with\-bdeps=n\fR. +.TP .BR "\-\-with\-test\-deps [ y | n ]" For packages matched by arguments, this option will pull in dependencies that are conditional on the "test" USE flag, even if "test" is not diff --git a/pym/_emerge/create_depgraph_params.py b/pym/_emerge/create_depgraph_params.py index 2c6492883..cdea029ba 100644 --- a/pym/_emerge/create_depgraph_params.py +++ b/pym/_emerge/create_depgraph_params.py @@ -13,6 +13,8 @@ def create_depgraph_params(myopts, myaction): # deep: go into the dependencies of already merged packages # empty: pretend nothing is merged # complete: completely account for all known dependencies + # bdeps: satisfy build time dependencies of packages that are + # already built, e
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/sync/
commit: 0655b4a26e378cf409c9a033514f41c307d01371 Author: Alexandru Elisei gmail com> AuthorDate: Sun Jan 29 18:07:34 2017 + Commit: Zac Medico gentoo org> CommitDate: Tue Jan 31 21:02:50 2017 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=0655b4a2 test_sync_local: add test for auto-sync set to 'no' pym/portage/tests/sync/test_sync_local.py | 12 ++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/pym/portage/tests/sync/test_sync_local.py b/pym/portage/tests/sync/test_sync_local.py index bec2e6a..1d38562 100644 --- a/pym/portage/tests/sync/test_sync_local.py +++ b/pym/portage/tests/sync/test_sync_local.py @@ -42,7 +42,7 @@ class SyncLocalTestCase(TestCase): location = %(EPREFIX)s/var/repositories/test_repo sync-type = %(sync-type)s sync-uri = file:/%(EPREFIX)s/var/repositories/test_repo_sync - auto-sync = yes + auto-sync = %(auto-sync)s %(repo_extra_keys)s """) @@ -87,9 +87,11 @@ class SyncLocalTestCase(TestCase): committer_name = "Gentoo Dev" committer_email = "gentoo-...@gentoo.org" - def repos_set_conf(sync_type, dflt_keys=None, xtra_keys=None): + def repos_set_conf(sync_type, dflt_keys=None, xtra_keys=None, + auto_sync="yes"): env["PORTAGE_REPOSITORIES"] = repos_conf % {\ "EPREFIX": eprefix, "sync-type": sync_type, + "auto-sync": auto_sync, "default_keys": "" if dflt_keys is None else dflt_keys, "repo_extra_keys": "" if xtra_keys is None else xtra_keys} @@ -100,6 +102,12 @@ class SyncLocalTestCase(TestCase): os.unlink(os.path.join(metadata_dir, 'timestamp.chk')) sync_cmds = ( + (homedir, lambda: repos_set_conf("rsync", auto_sync="no")), + (homedir, cmds["emerge"] + ("--sync",)), + (homedir, lambda: self.assertFalse(os.path.exists( + os.path.join(repo.location, "dev-libs", "A") + ), "dev-libs/A found, expected missing")), + (homedir, lambda: repos_set_conf("rsync", auto_sync="yes")), (homedir, cmds["emerge"] + ("--sync",)), (homedir, lambda: self.assertTrue(os.path.exists( os.path.join(repo.location, "dev-libs", "A")
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/sync/
commit: b43f542614d136f69328dbc956f902bddb3db9c2 Author: Zac Medico gentoo org> AuthorDate: Sat Jan 28 20:45:16 2017 + Commit: Zac Medico gentoo org> CommitDate: Sat Jan 28 20:55:22 2017 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=b43f5426 test_sync_local: fix emaint command path to be valid for travis pym/portage/tests/sync/test_sync_local.py | 11 +-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/pym/portage/tests/sync/test_sync_local.py b/pym/portage/tests/sync/test_sync_local.py index b57bdba..bec2e6a 100644 --- a/pym/portage/tests/sync/test_sync_local.py +++ b/pym/portage/tests/sync/test_sync_local.py @@ -71,8 +71,15 @@ class SyncLocalTestCase(TestCase): cmds = {} for cmd in ("emerge", "emaint"): - cmds[cmd] = (portage._python_interpreter, - "-b", "-Wd", os.path.join(self.bindir, cmd)) + for bindir in (self.bindir, self.sbindir): + path = os.path.join(bindir, cmd) + if os.path.exists(path): + cmds[cmd] = (portage._python_interpreter, + "-b", "-Wd", path) + break + else: + raise AssertionError('%s binary not found in %s or %s' % + (cmd, self.bindir, self.sbindir)) git_binary = find_binary("git") git_cmd = (git_binary,)
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/news/
commit: 216297a9a7e91e48b74ef796b6642fd8c15085fc Author: Mike Gilbert gentoo org> AuthorDate: Thu Sep 15 01:30:37 2016 + Commit: Zac Medico gentoo org> CommitDate: Thu Sep 15 01:43:28 2016 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=216297a9 test_NewsItem: Add News-Item-Format to template pym/portage/tests/news/test_NewsItem.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pym/portage/tests/news/test_NewsItem.py b/pym/portage/tests/news/test_NewsItem.py index a4e76f3..2f183a7 100644 --- a/pym/portage/tests/news/test_NewsItem.py +++ b/pym/portage/tests/news/test_NewsItem.py @@ -17,6 +17,7 @@ Author: Ciaran McCreesh Content-Type: text/plain Posted: 01-Nov-2005 Revision: 1 +News-Item-Format: 1.0 #Display-If-Installed: #Display-If-Profile: #Display-If-Arch:
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/ebuild/, pym/portage/util/_eventloop/
commit: 995f0f983386e2a82dbce65d4366ee7f58f59138 Author: Zac Medico gentoo org> AuthorDate: Sat Aug 20 21:59:55 2016 + Commit: Zac Medico gentoo org> CommitDate: Tue Aug 23 16:33:47 2016 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=995f0f98 EventLoop: add run_until_complete method (bug 591760) This emulates the asyncio.AbstractEventLoop.run_until_complete(future) interface, which will make it possible to reduce latency in situations where it is desirable for a loop to exit at the earliest opportunity. The most tangible benefit of this change is that it provides a migration path to asyncio, which will allow us to rely on a standard library instead of our own internal event loop implementation. In order to migrate to asyncio, more work is planned: * Migrate all internal use of the EventLoop.iteration method to the new run_until_complete(future) method, and remove the EventLoop.iteration method (or make it private as long as it's needed to implement run_until_complete for older python versions). * Implement all EventLoop methods using asyncio.AbstractEventLoop methods (but keep existing implementations for use with older python). X-Gentoo-bug: 591760 X-Gentoo-bug-url: https://bugs.gentoo.org/show_bug.cgi?id=591760 Acked-by: Alexander Berntsen gentoo.org> pym/portage/tests/ebuild/test_ipc_daemon.py | 23 ++- pym/portage/util/_eventloop/EventLoop.py| 17 - 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/pym/portage/tests/ebuild/test_ipc_daemon.py b/pym/portage/tests/ebuild/test_ipc_daemon.py index 835f51f..68f139a 100644 --- a/pym/portage/tests/ebuild/test_ipc_daemon.py +++ b/pym/portage/tests/ebuild/test_ipc_daemon.py @@ -1,4 +1,4 @@ -# Copyright 2010-2015 Gentoo Foundation +# Copyright 2010-2016 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 import tempfile @@ -16,6 +16,7 @@ from portage.util import ensure_dirs from portage.util._async.ForkProcess import ForkProcess from portage.util._async.TaskScheduler import TaskScheduler from portage.util._eventloop.global_event_loop import global_event_loop +from portage.util.futures.futures import Future from _emerge.SpawnProcess import SpawnProcess from _emerge.EbuildBuildDir import EbuildBuildDir from _emerge.EbuildIpcDaemon import EbuildIpcDaemon @@ -140,19 +141,23 @@ class IpcDaemonTestCase(TestCase): build_dir.unlock() shutil.rmtree(tmpdir) - def _timeout_callback(self): - self._timed_out = True + def _timeout_callback(self, task_scheduler): + task_scheduler.cancel() + self._exit_callback(task_scheduler) + + def _exit_callback(self, task_scheduler): + if not self._run_done.done(): + self._run_done.set_result(True) def _run(self, event_loop, task_scheduler, timeout): - self._timed_out = False - timeout_id = event_loop.timeout_add(timeout, self._timeout_callback) + self._run_done = Future() + timeout_id = event_loop.timeout_add(timeout, + self._timeout_callback, task_scheduler) + task_scheduler.addExitListener(self._exit_callback) try: task_scheduler.start() - while not self._timed_out and task_scheduler.poll() is None: - event_loop.iteration() - if self._timed_out: - task_scheduler.cancel() + event_loop.run_until_complete(self._run_done) task_scheduler.wait() finally: event_loop.source_remove(timeout_id) diff --git a/pym/portage/util/_eventloop/EventLoop.py b/pym/portage/util/_eventloop/EventLoop.py index 8095400..8f13de3 100644 --- a/pym/portage/util/_eventloop/EventLoop.py +++ b/pym/portage/util/_eventloop/EventLoop.py @@ -1,4 +1,4 @@ -# Copyright 1999-2014 Gentoo Foundation +# Copyright 1999-2016 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 from __future__ import division @@ -577,6 +577,21 @@ class EventLoop(object): del self._poll_event_handlers[f] return True + def run_until_complete(self, future): + """ + Run until the Future is done. + + @type future: asyncio.Future + @param future: a Future to wait for + @rtype: object + @return: the Future's result + @raise: the Future's exception + """ + while not future.done(): + self.iteration() + + return future.result() + _can_poll_device = None def can_poll_device():
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/resolver/, pym/_emerge/
commit: 6412205462671735f6e8b3196a780bc4b0d6a077 Author: Zac Medico gentoo org> AuthorDate: Fri Aug 5 02:15:14 2016 + Commit: Zac Medico gentoo org> CommitDate: Sun Aug 7 17:44:20 2016 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=64122054 depgraph._serialize_tasks: improve runtime cycle handling (bug 590514) Previously, it was possible for _serialize_tasks to count some dependencies of a runtime cycle as part of that cycle, leading to sub-optimal merge order for these dependencies because they got grouped together with the cycle in the overall merge order. Fix it to separate these dependencies from the cycle, and merge them earlier. X-Gentoo-Bug: 590514 X-Gentoo-Bug-url: https://bugs.gentoo.org/show_bug.cgi?id=590514 Acked-by: Brian Dolbec gentoo.org> pym/_emerge/depgraph.py| 50 +++ .../resolver/test_runtime_cycle_merge_order.py | 72 ++ 2 files changed, 98 insertions(+), 24 deletions(-) diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py index fc957f5..26037ad 100644 --- a/pym/_emerge/depgraph.py +++ b/pym/_emerge/depgraph.py @@ -7415,36 +7415,38 @@ class depgraph(object): selected_nodes = set() if gather_deps(ignore_priority, mergeable_nodes, selected_nodes, node): - # When selecting asap_nodes, we need to ensure - # that we haven't selected a large runtime cycle - # that is obviously sub-optimal. This will be - # obvious if any of the non-asap selected_nodes - # is a leaf node when medium_soft deps are - # ignored. - if prefer_asap and asap_nodes and \ - len(selected_nodes) > 1: - for node in selected_nodes.difference( - asap_nodes): - if not mygraph.child_nodes(node, - ignore_priority = - DepPriorityNormalRange.ignore_medium_soft): - selected_nodes = None - break - if selected_nodes: - if smallest_cycle is None or \ - len(selected_nodes) < len(smallest_cycle): - smallest_cycle = selected_nodes + if smallest_cycle is None or \ + len(selected_nodes) < len(smallest_cycle): + smallest_cycle = selected_nodes selected_nodes = smallest_cycle - if selected_nodes and debug: - writemsg("\nruntime cycle digraph (%s nodes):\n\n" % - (len(selected_nodes),), noiselevel=-1) + if selected_nodes is not None: cycle_digraph = mygraph.copy() cycle_digraph.difference_update([x for x in cycle_digraph if x not in selected_nodes]) - cycle_digraph.debug_print() - writemsg("\n", noiselevel=-1) + + leaves = cycle_digraph.leaf_nodes() + if leaves: + # NOTE: This case should only be triggered when + # prefer_asap is True, since otherwise these + # leaves would have been selected to merge + # before this po
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/resolver/
commit: ac6f924fa3d9296778d493a16a1d428ab54dda97 Author: Zac Medico gentoo org> AuthorDate: Thu Jun 23 06:17:17 2016 + Commit: Zac Medico gentoo org> CommitDate: Sun Jun 26 23:49:29 2016 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=ac6f924f Add a unit test which reproduces bug 584626 X-Gentoo-Bug: 584626 X-Gentoo-Bug-url: https://bugs.gentoo.org/show_bug.cgi?id=584626 .../resolver/test_slot_operator_reverse_deps.py| 109 + 1 file changed, 109 insertions(+) diff --git a/pym/portage/tests/resolver/test_slot_operator_reverse_deps.py b/pym/portage/tests/resolver/test_slot_operator_reverse_deps.py new file mode 100644 index 000..72879f8 --- /dev/null +++ b/pym/portage/tests/resolver/test_slot_operator_reverse_deps.py @@ -0,0 +1,109 @@ +# Copyright 2016 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +from portage.tests import TestCase +from portage.tests.resolver.ResolverPlayground import ( + ResolverPlayground, + ResolverPlaygroundTestCase, +) + +class SlotOperatorReverseDepsTestCase(TestCase): + + def testSlotOperatorReverseDeps(self): + + ebuilds = { + + "media-libs/mesa-11.2.2" : { + "EAPI": "6", + "SLOT": "0", + "RDEPEND": ">=sys-devel/llvm-3.6.0:=" + }, + + "sys-devel/clang-3.7.1-r100" : { + "EAPI": "6", + "SLOT": "0/3.7", + "RDEPEND": "~sys-devel/llvm-3.7.1" + }, + + "sys-devel/clang-3.8.0-r100" : { + "EAPI": "6", + "SLOT": "0/3.8", + "RDEPEND": "~sys-devel/llvm-3.8.0" + }, + + "sys-devel/llvm-3.7.1-r2" : { + "EAPI": "6", + "SLOT": "0/3.7.1", + "PDEPEND": "=sys-devel/clang-3.7.1-r100" + }, + + "sys-devel/llvm-3.8.0-r2" : { + "EAPI": "6", + "SLOT": "0/3.8.0", + "PDEPEND": "=sys-devel/clang-3.8.0-r100" + }, + + } + + installed = { + + "media-libs/mesa-11.2.2" : { + "EAPI": "6", + "SLOT": "0", + "RDEPEND": ">=sys-devel/llvm-3.6.0:0/3.7.1=" + }, + + "sys-devel/clang-3.7.1-r100" : { + "EAPI": "6", + "SLOT": "0/3.7", + "RDEPEND": "~sys-devel/llvm-3.7.1" + }, + + "sys-devel/llvm-3.7.1-r2" : { + "EAPI": "6", + "SLOT": "0/3.7.1", + "PDEPEND": "=sys-devel/clang-3.7.1-r100" + }, + + } + + world = ["media-libs/mesa"] + + test_cases = ( + + # Test bug #584626, where an llvm update is missed due to + # the check_reverse_dependencies function seeing that + # updating llvm will break a dependency of the installed + # version of clang (though a clang update is available). + ResolverPlaygroundTestCase( + ["@world"], + options = {"--update": True, "--deep": True}, + success = True, + mergelist = [], + ), + + ResolverPlaygroundTestCase( + ["@world"], + options = { + "--update": True, + "--deep": True, + "--ignore-built-slot-operator-deps": "y", + }, + success = True, + mergelist = [ + 'sys-devel/llvm-3.8.0-r2', + 'sys-devel/clang-3.8.0-r100', + ], + ), + + ) + + playground = ResolverPlayground(ebuilds=ebuilds, + installed=installed, world=world, debug=False) + try: + for test_case in test_cases: + playground.run_TestCase(test_case) + self.assertEqual(test_
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/util/, cnf/
commit: a810a92d615c904db59326188e1437fdab74e705 Author: Zac Medico gentoo org> AuthorDate: Thu May 5 17:12:13 2016 + Commit: Zac Medico gentoo org> CommitDate: Sat May 7 20:02:51 2016 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=a810a92d make.globals: Respect ssh_config port (bug 499198) Fix FETCHCOMMAND_SSH and FETCHCOMMAND_SFTP to respect ssh_config port. X-Gentoo-bug: 499198 X-Gentoo-bug-url: https://bugs.gentoo.org/show_bug.cgi?id=499198 Acked-by: Alexander Berntsen gentoo.org> cnf/make.globals | 4 ++-- pym/portage/tests/util/test_getconfig.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cnf/make.globals b/cnf/make.globals index 836bb5c..18eba94 100644 --- a/cnf/make.globals +++ b/cnf/make.globals @@ -43,11 +43,11 @@ FETCHCOMMAND_RSYNC="rsync -avP \"\${URI}\" \"\${DISTDIR}/\${FILE}\"" RESUMECOMMAND_RSYNC="rsync -avP \"\${URI}\" \"\${DISTDIR}/\${FILE}\"" # NOTE: rsync will evaluate quotes embedded inside PORTAGE_SSH_OPTS -FETCHCOMMAND_SSH="bash -c \"x=\\\${2#ssh://} ; host=\\\${x%%/*} ; port=\\\${host##*:} ; host=\\\${host%:*} ; [[ \\\${host} = \\\${port} ]] && port=22 ; exec rsync --rsh=\\\"ssh -p\\\${port} \\\${3}\\\" -avP \\\"\\\${host}:/\\\${x#*/}\\\" \\\"\\\$1\\\"\" rsync \"\${DISTDIR}/\${FILE}\" \"\${URI}\" \"\${PORTAGE_SSH_OPTS}\"" +FETCHCOMMAND_SSH="bash -c \"x=\\\${2#ssh://} ; host=\\\${x%%/*} ; port=\\\${host##*:} ; host=\\\${host%:*} ; [[ \\\${host} = \\\${port} ]] && port= ; exec rsync --rsh=\\\"ssh \\\${port:+-p\\\${port}} \\\${3}\\\" -avP \\\"\\\${host}:/\\\${x#*/}\\\" \\\"\\\$1\\\"\" rsync \"\${DISTDIR}/\${FILE}\" \"\${URI}\" \"\${PORTAGE_SSH_OPTS}\"" RESUMECOMMAND_SSH=${FETCHCOMMAND_SSH} # NOTE: bash eval is used to evaluate quotes embedded inside PORTAGE_SSH_OPTS -FETCHCOMMAND_SFTP="bash -c \"x=\\\${2#sftp://} ; host=\\\${x%%/*} ; port=\\\${host##*:} ; host=\\\${host%:*} ; [[ \\\${host} = \\\${port} ]] && port=22 ; eval \\\"declare -a ssh_opts=(\\\${3})\\\" ; exec sftp -P \\\${port} \\\"\\\${ssh_opts[@]}\\\" \\\"\\\${host}:/\\\${x#*/}\\\" \\\"\\\$1\\\"\" sftp \"\${DISTDIR}/\${FILE}\" \"\${URI}\" \"\${PORTAGE_SSH_OPTS}\"" +FETCHCOMMAND_SFTP="bash -c \"x=\\\${2#sftp://} ; host=\\\${x%%/*} ; port=\\\${host##*:} ; host=\\\${host%:*} ; [[ \\\${host} = \\\${port} ]] && port= ; eval \\\"declare -a ssh_opts=(\\\${3})\\\" ; exec sftp \\\${port:+-P \\\${port}} \\\"\\\${ssh_opts[@]}\\\" \\\"\\\${host}:/\\\${x#*/}\\\" \\\"\\\$1\\\"\" sftp \"\${DISTDIR}/\${FILE}\" \"\${URI}\" \"\${PORTAGE_SSH_OPTS}\"" # Default user options FEATURES="assume-digests binpkg-logs diff --git a/pym/portage/tests/util/test_getconfig.py b/pym/portage/tests/util/test_getconfig.py index b72bd6a..05e3147 100644 --- a/pym/portage/tests/util/test_getconfig.py +++ b/pym/portage/tests/util/test_getconfig.py @@ -20,8 +20,8 @@ class GetConfigTestCase(TestCase): _cases = { 'FETCHCOMMAND' : 'wget -t 3 -T 60 --passive-ftp -O "${DISTDIR}/${FILE}" "${URI}"', 'FETCHCOMMAND_RSYNC' : 'rsync -avP "${URI}" "${DISTDIR}/${FILE}"', - 'FETCHCOMMAND_SFTP': 'bash -c "x=\\${2#sftp://} ; host=\\${x%%/*} ; port=\\${host##*:} ; host=\\${host%:*} ; [[ \\${host} = \\${port} ]] && port=22 ; eval \\"declare -a ssh_opts=(\\${3})\\" ; exec sftp -P \\${port} \\"\\${ssh_opts[@]}\\" \\"\\${host}:/\\${x#*/}\\" \\"\\$1\\"" sftp "${DISTDIR}/${FILE}" "${URI}" "${PORTAGE_SSH_OPTS}"', - 'FETCHCOMMAND_SSH' : 'bash -c "x=\\${2#ssh://} ; host=\\${x%%/*} ; port=\\${host##*:} ; host=\\${host%:*} ; [[ \\${host} = \\${port} ]] && port=22 ; exec rsync --rsh=\\"ssh -p\\${port} \\${3}\\" -avP \\"\\${host}:/\\${x#*/}\\" \\"\\$1\\"" rsync "${DISTDIR}/${FILE}" "${URI}" "${PORTAGE_SSH_OPTS}"', + 'FETCHCOMMAND_SFTP': 'bash -c "x=\\${2#sftp://} ; host=\\${x%%/*} ; port=\\${host##*:} ; host=\\${host%:*} ; [[ \\${host} = \\${port} ]] && port= ; eval \\"declare -a ssh_opts=(\\${3})\\" ; exec sftp \\${port:+-P \\${port}} \\"\\${ssh_opts[@]}\\" \\"\\${host}:/\\${x#*/}\\" \\"\\$1\\"" sftp "${DISTDIR}/${FILE}" "${URI}" "${PORTAGE_SSH_OPTS}"', + 'FETCHCOMMAND_SSH' : 'bash -c "x=\\${2#ssh://} ; host=\\${x%%/*} ; port=\\${host##*:} ; host=\\${host%:*} ; [[ \\${host} = \\${port} ]] && port= ; exec rsync --rsh=\\"ssh \\${port:+-p\\${port}} \\${3}\\" -avP \\"\\${host}:/\\${x#*/}\\" \\"\\$1\\"" rsync "${DISTDIR}/${FILE}" "${URI}" "${PORTAGE_SSH_OPTS}"', 'PORTAGE_ELOG_MAILSUBJECT' : '[portage] ebuild log for ${PACKAGE} on ${HOST}' }
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/repoman/
commit: 4d7792fc2d633011b158780d670e57212961f933 Author: Zac Medico gentoo org> AuthorDate: Wed Feb 24 23:17:45 2016 + Commit: Zac Medico gentoo org> CommitDate: Wed Feb 24 23:19:33 2016 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=4d7792fc SimpleRepomanTestCase: suppress metadata.dtd fetch (fix travis-ci failure) pym/portage/tests/repoman/test_simple.py | 9 +++-- 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/pym/portage/tests/repoman/test_simple.py b/pym/portage/tests/repoman/test_simple.py index af6f95d..98220c4 100644 --- a/pym/portage/tests/repoman/test_simple.py +++ b/pym/portage/tests/repoman/test_simple.py @@ -7,7 +7,6 @@ import time import portage from portage import os -from portage import shutil from portage import _unicode_decode from portage.const import PORTAGE_BASE_PATH, PORTAGE_PYM_PATH from portage.process import find_binary @@ -273,11 +272,9 @@ class SimpleRepomanTestCase(TestCase): # involving canonical vs. non-canonical paths. test_repo_symlink = os.path.join(eroot, "test_repo_symlink") os.symlink(test_repo_location, test_repo_symlink) - # repoman checks metadata.dtd for recent CTIME, so copy the file in - # order to ensure that the CTIME is current - # NOTE: if we don't have the file around, let repoman try to fetch it. - if os.path.exists(metadata_dtd): - shutil.copyfile(metadata_dtd, os.path.join(distdir, "metadata.dtd")) + metadata_dtd_dest = os.path.join(test_repo_location, 'metadata/dtd/metadata.dtd') + os.makedirs(os.path.dirname(metadata_dtd_dest)) + os.symlink(metadata_dtd, metadata_dtd_dest) if debug: # The subprocess inherits both stdout and stderr, for
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/ebuild/
commit: 44aeab7fad440a289316ced8738b287d88d475d0 Author: Zac Medico gentoo org> AuthorDate: Sun Jan 17 02:52:02 2016 + Commit: Zac Medico gentoo org> CommitDate: Sun Jan 17 02:54:27 2016 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=44aeab7f DoebuildFdPipesTestCase: use extra pipe for test output Since commit 3767128cf08a0a21559eb9c41ba393dcabc6f087, this test has failed due to additional output produced by src_install. Fix it to use a separate pipe for test output. pym/portage/tests/ebuild/test_doebuild_fd_pipes.py | 36 +++--- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/pym/portage/tests/ebuild/test_doebuild_fd_pipes.py b/pym/portage/tests/ebuild/test_doebuild_fd_pipes.py index 2a65537..b894218 100644 --- a/pym/portage/tests/ebuild/test_doebuild_fd_pipes.py +++ b/pym/portage/tests/ebuild/test_doebuild_fd_pipes.py @@ -1,8 +1,6 @@ -# Copyright 2013-2015 Gentoo Foundation +# Copyright 2013-2016 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 -import textwrap - import portage from portage import os from portage.tests import TestCase @@ -10,7 +8,6 @@ from portage.tests.resolver.ResolverPlayground import ResolverPlayground from portage.package.ebuild._ipc.QueryCommand import QueryCommand from portage.util._async.ForkProcess import ForkProcess from portage.util._async.TaskScheduler import TaskScheduler -from portage.util._eventloop.global_event_loop import global_event_loop from _emerge.Package import Package from _emerge.PipeReader import PipeReader @@ -31,19 +28,16 @@ class DoebuildFdPipesTestCase(TestCase): supported for API consumers (see bug #475812). """ - ebuild_body = textwrap.dedent(""" - S=${WORKDIR} - pkg_info() { echo info ; } - pkg_nofetch() { echo nofetch ; } - pkg_pretend() { echo pretend ; } - pkg_setup() { echo setup ; } - src_unpack() { echo unpack ; } - src_prepare() { echo prepare ; } - src_configure() { echo configure ; } - src_compile() { echo compile ; } - src_test() { echo test ; } - src_install() { echo install ; } - """) + output_fd = 200 + ebuild_body = ['S=${WORKDIR}'] + for phase_func in ('pkg_info', 'pkg_nofetch', 'pkg_pretend', + 'pkg_setup', 'src_unpack', 'src_prepare', 'src_configure', + 'src_compile', 'src_test', 'src_install'): + ebuild_body.append(('%s() { echo ${EBUILD_PHASE}' + ' 1>&%s; }') % (phase_func, output_fd)) + + ebuild_body.append('') + ebuild_body = '\n'.join(ebuild_body) ebuilds = { 'app-misct/foo-1': { @@ -60,6 +54,7 @@ class DoebuildFdPipesTestCase(TestCase): self.assertEqual(true_binary is None, False, "true command not found") + dev_null = open(os.devnull, 'wb') playground = ResolverPlayground(ebuilds=ebuilds) try: QueryCommand._db = playground.trees @@ -106,7 +101,11 @@ class DoebuildFdPipesTestCase(TestCase): doebuild_kwargs={"settings" : settings, "mydbapi": portdb, "tree": "porttree", "vartree": root_config.trees["vartree"], - "fd_pipes": {1: pw, 2: pw}, + "fd_pipes": { + 1: dev_null.fileno(), + 2: dev_null.fileno(), + output_fd: pw, + }, "prev_mtimes": {}}) consumer = PipeReader( @@ -134,5 +133,6 @@ class DoebuildFdPipesTestCase(TestCase): self.assertEqual(phase, output) finally: + dev_null.close() playground.cleanup() QueryCommand._db = None
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/ebuild/, pym/portage/package/ebuild/, pym/portage/repository/
commit: 10647652ebeff52c3dbc0419ab9030ba76d46122 Author: Arfrever Frehtes Taifersar Arahesis Apache Org> AuthorDate: Tue Dec 8 06:58:36 2015 + Commit: Arfrever Frehtes Taifersar Arahesis apache org> CommitDate: Tue Dec 8 06:58:36 2015 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=10647652 portage.repository.config.RepoConfig: Delete user_location attribute and consistently use location attribute everywhere. pym/portage/package/ebuild/config.py| 4 ++-- pym/portage/repository/config.py| 21 ++--- pym/portage/tests/ebuild/test_config.py | 4 ++-- 3 files changed, 10 insertions(+), 19 deletions(-) diff --git a/pym/portage/package/ebuild/config.py b/pym/portage/package/ebuild/config.py index 7cf5a4c..b6217e7 100644 --- a/pym/portage/package/ebuild/config.py +++ b/pym/portage/package/ebuild/config.py @@ -539,13 +539,13 @@ class config(object): #filling PORTDIR and PORTDIR_OVERLAY variable for compatibility main_repo = self.repositories.mainRepo() if main_repo is not None: - self["PORTDIR"] = main_repo.user_location + self["PORTDIR"] = main_repo.location self.backup_changes("PORTDIR") expand_map["PORTDIR"] = self["PORTDIR"] # repoman controls PORTDIR_OVERLAY via the environment, so no # special cases are needed here. - portdir_overlay = list(self.repositories.repoUserLocationList()) + portdir_overlay = list(self.repositories.repoLocationList()) if portdir_overlay and portdir_overlay[0] == self["PORTDIR"]: portdir_overlay = portdir_overlay[1:] diff --git a/pym/portage/repository/config.py b/pym/portage/repository/config.py index b987b56..b792d78 100644 --- a/pym/portage/repository/config.py +++ b/pym/portage/repository/config.py @@ -91,8 +91,8 @@ class RepoConfig(object): 'profile_formats', 'sign_commit', 'sign_manifest', 'sync_depth', 'sync_hooks_only_on_change', 'sync_type', 'sync_umask', 'sync_uri', 'sync_user', 'thin_manifest', - 'update_changelog', 'user_location', '_eapis_banned', - '_eapis_deprecated', '_masters_orig', 'module_specific_options', + 'update_changelog', '_eapis_banned', '_eapis_deprecated', + '_masters_orig', 'module_specific_options', ) def __init__(self, name, repo_opts, local_config=True): @@ -189,7 +189,6 @@ class RepoConfig(object): self.format = format location = repo_opts.get('location') - self.user_location = location if location is not None and location.strip(): if os.path.isdir(location) or portage._sync_mode: location = os.path.realpath(location) @@ -410,8 +409,8 @@ class RepoConfig(object): repo_msg.append(self.name) if self.format: repo_msg.append(indent + "format: " + self.format) - if self.user_location: - repo_msg.append(indent + "location: " + self.user_location) + if self.location: + repo_msg.append(indent + "location: " + self.location) if self.sync_type: repo_msg.append(indent + "sync-type: " + self.sync_type) if self.sync_umask: @@ -527,7 +526,7 @@ class RepoConfigLoader(object): old_location == default_portdir): ignored_map.setdefault(repo.name, []).append(old_location) if old_location == portdir: - portdir = repo.user_location + portdir = repo.location if repo.priority is None: if base_priority == 0 and ov == portdir_orig: @@ -826,7 +825,7 @@ class RepoConfigLoader(object): master_repos = [] for master_name in repo.masters: if master_name not in prepos: - layout_filename = os.path.join(repo.user_location, + layout_filename = os.path.join(repo.location, "metadata", "layout.conf") writemsg_level(_("Unavailable repository '%s' " \
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/ebuild/, pym/portage/package/ebuild/_config/, ...
commit: 48c2af4538d581fb2225c0ac9620b7fcfe4eae2e Author: Arfrever Frehtes Taifersar Arahesis Apache Org> AuthorDate: Wed Dec 2 01:16:34 2015 + Commit: Arfrever Frehtes Taifersar Arahesis apache org> CommitDate: Wed Dec 2 01:16:34 2015 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=48c2af45 Respect PYTHONDONTWRITEBYTECODE in test suite. pym/portage/package/ebuild/_config/special_env_vars.py | 2 +- pym/portage/tests/dbapi/test_portdb_cache.py | 3 ++- pym/portage/tests/ebuild/test_doebuild_fd_pipes.py | 3 ++- pym/portage/tests/ebuild/test_doebuild_spawn.py| 3 ++- pym/portage/tests/ebuild/test_ipc_daemon.py| 3 ++- pym/portage/tests/emerge/test_config_protect.py| 3 ++- pym/portage/tests/emerge/test_emerge_slot_abi.py | 3 ++- pym/portage/tests/emerge/test_simple.py| 3 ++- pym/portage/tests/repoman/test_simple.py | 3 ++- pym/portage/tests/sync/test_sync_local.py | 3 ++- 10 files changed, 19 insertions(+), 10 deletions(-) diff --git a/pym/portage/package/ebuild/_config/special_env_vars.py b/pym/portage/package/ebuild/_config/special_env_vars.py index 8479cf5..9ae53c1 100644 --- a/pym/portage/package/ebuild/_config/special_env_vars.py +++ b/pym/portage/package/ebuild/_config/special_env_vars.py @@ -77,7 +77,7 @@ environ_whitelist += [ "PORTAGE_SIGPIPE_STATUS", "PORTAGE_SOCKS5_PROXY", "PORTAGE_TMPDIR", "PORTAGE_UPDATE_ENV", "PORTAGE_USERNAME", "PORTAGE_VERBOSE", "PORTAGE_WORKDIR_MODE", "PORTAGE_XATTR_EXCLUDE", - "PORTDIR", "PORTDIR_OVERLAY", "PREROOTPATH", + "PORTDIR", "PORTDIR_OVERLAY", "PREROOTPATH", "PYTHONDONTWRITEBYTECODE", "REPLACING_VERSIONS", "REPLACED_BY_VERSION", "ROOT", "ROOTPATH", "T", "TMP", "TMPDIR", "USE_EXPAND", "USE_ORDER", "WORKDIR", diff --git a/pym/portage/tests/dbapi/test_portdb_cache.py b/pym/portage/tests/dbapi/test_portdb_cache.py index 5ac9b03..bd93446 100644 --- a/pym/portage/tests/dbapi/test_portdb_cache.py +++ b/pym/portage/tests/dbapi/test_portdb_cache.py @@ -1,4 +1,4 @@ -# Copyright 2012-2014 Gentoo Foundation +# Copyright 2012-2015 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 import subprocess @@ -134,6 +134,7 @@ class PortdbCacheTestCase(TestCase): "PORTAGE_OVERRIDE_EPREFIX" : eprefix, "PORTAGE_PYTHON" : portage_python, "PORTAGE_REPOSITORIES" : settings.repositories.config_string(), + "PYTHONDONTWRITEBYTECODE" : os.environ.get("PYTHONDONTWRITEBYTECODE", ""), "PYTHONPATH" : pythonpath, } diff --git a/pym/portage/tests/ebuild/test_doebuild_fd_pipes.py b/pym/portage/tests/ebuild/test_doebuild_fd_pipes.py index 61392dd..2a65537 100644 --- a/pym/portage/tests/ebuild/test_doebuild_fd_pipes.py +++ b/pym/portage/tests/ebuild/test_doebuild_fd_pipes.py @@ -1,4 +1,4 @@ -# Copyright 2013 Gentoo Foundation +# Copyright 2013-2015 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 import textwrap @@ -75,6 +75,7 @@ class DoebuildFdPipesTestCase(TestCase): settings.features.add("test") settings['PORTAGE_PYTHON'] = portage._python_interpreter settings['PORTAGE_QUIET'] = "1" + settings['PYTHONDONTWRITEBYTECODE'] = os.environ.get("PYTHONDONTWRITEBYTECODE", "") fake_bin = os.path.join(settings["EPREFIX"], "bin") portage.util.ensure_dirs(fake_bin) diff --git a/pym/portage/tests/ebuild/test_doebuild_spawn.py b/pym/portage/tests/ebuild/test_doebuild_spawn.py index ae9a5c5..6b34465 100644 --- a/pym/portage/tests/ebuild/test_doebuild_spawn.py +++ b/pym/portage/tests/ebuild/test_doebuild_spawn.py @@ -1,4 +1,4 @@ -# Copyright 2010-2012 Gentoo Foundation +# Copyright 2010-2015 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 import textwrap @@ -65,6 +65,7 @@ class DoebuildSpawnTestCase(TestCase): settings['PORTAGE_PYTHON'] = _python_interpreter settings['PORTAGE_BUILDDIR'] = os.path.join( settings['PORTAGE_TMPDIR'], cpv) + settings['PYTHONDONTWRITEBYTECODE'] = os.environ.get('PYTHONDONTWRITEBYTECODE', '') settings['T'] = os.path.join( settings['PORTAGE_BUILDDIR'], 'temp') for x in ('PORTAGE_BUILDDIR', 'T'): diff --git a/pym/portage/tests/ebuild/test_ipc_daemon.py b/pym/portage/tests/ebuild/test_ipc_daemon.py index a871076..835f51f 100644 --- a/pym/portage/tests/ebuild/test_ipc_daemon.py +++ b/pym/portage/tests/ebuild/test_ipc_daemon.py @@ -1,4 +1,4 @@ -# Copyright 2010-2012 Gentoo Foundation +# Copyright 2010-2015 Gento
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/resolver/, pym/_emerge/
commit: 0c00530c92ecca3499c7d98fedae41a9ab559d17 Author: Zac Medico gentoo org> AuthorDate: Tue Nov 24 09:14:41 2015 + Commit: Zac Medico gentoo org> CommitDate: Tue Nov 24 16:43:58 2015 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=0c00530c depgraph: autounmask for conditional USE deps (bug 566704) For parents with unsatisfied conditional dependencies, translate USE change suggestions into autounmask changes. X-Gentoo-Bug: 566704 X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=566704 Acked-by: Alexander Berntsen gentoo.org> pym/_emerge/depgraph.py| 35 +- .../tests/resolver/test_autounmask_parent.py | 43 ++ 2 files changed, 77 insertions(+), 1 deletion(-) diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py index 57040ab..f659b0a 100644 --- a/pym/_emerge/depgraph.py +++ b/pym/_emerge/depgraph.py @@ -4075,6 +4075,7 @@ class depgraph(object): # Now that the root packages have been added to the graph, # process the dependencies. if not self._create_graph(): + self._apply_parent_use_changes() return 0, myfavorites try: @@ -4162,6 +4163,24 @@ class depgraph(object): # We're true here unless we are missing binaries. return (True, myfavorites) + def _apply_parent_use_changes(self): + """ + For parents with unsatisfied conditional dependencies, translate + USE change suggestions into autounmask changes. + """ + if (self._dynamic_config._unsatisfied_deps_for_display and + self._dynamic_config._autounmask): + remaining_items = [] + for item in self._dynamic_config._unsatisfied_deps_for_display: + pargs, kwargs = item + kwargs = kwargs.copy() + kwargs['collect_use_changes'] = True + if not self._show_unsatisfied_dep(*pargs, + **portage._native_kwargs(kwargs)): + remaining_items.append(item) + if len(remaining_items) != len(self._dynamic_config._unsatisfied_deps_for_display): + self._dynamic_config._unsatisfied_deps_for_display = remaining_items + def _set_args(self, args): """ Create the "__non_set_args__" package set from atoms and packages given as @@ -4718,7 +4737,8 @@ class depgraph(object): def _show_unsatisfied_dep(self, root, atom, myparent=None, arg=None, - check_backtrack=False, check_autounmask_breakage=False, show_req_use=None): + check_backtrack=False, check_autounmask_breakage=False, show_req_use=None, + collect_use_changes=False): """ When check_backtrack=True, no output is produced and the method either returns or raises _backtrack_mask if @@ -4962,15 +4982,28 @@ class depgraph(object): "defined by %s: '%s'" % (myparent.cpv, \ human_readable_required_use(required_use)) + target_use = {} for flag in involved_flags: if flag in self._pkg_use_enabled(myparent): + target_use[flag] = False changes.append(colorize("blue", "-" + flag)) else: + target_use[flag] = True changes.append(colorize("red", "+" + flag)) + + if collect_use_changes and not required_use_warning: + previous_changes = self._dynamic_config._needed_use_config_changes.get(myparent) + self._pkg_use_enabled(myparent, target_use=target_use) + if previous_changes is not self._dynamic_config._needed_use_config_changes.get(myparent): + return True + mreasons.append("Change USE: %s" % " ".join(changes) + required_use_warning) if (myparent, mreasons) not in missing_use_reasons: missing_use_reasons.append((myparent, mreasons)) + if
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/sync/, pym/portage/util/_async/, ...
commit: 496ff326dc18890889d1ea5d2aec590394635960 Author: Zac Medico gentoo org> AuthorDate: Mon Aug 10 07:42:51 2015 + Commit: Zac Medico gentoo org> CommitDate: Thu Aug 13 19:49:39 2015 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=496ff326 sync repositories in parallel (bug 557426) Repos will now be synced in parallel (including their post-sync hooks), but a given repo will only be synced after its master(s) have synced (in case that matters for hooks). Output of concurrent processes will be mixed (irrelevant with --quiet). Support for FEATURES=metadata-transfer will be handled in the main process, which may be required for some backends (such as sqlite). X-Gentoo-Bug: 557426 X-Gentoo-Bug-url: https://bugs.gentoo.org/show_bug.cgi?id=557426 Acked-by: Brian Dolbec gentoo.org> pym/portage/emaint/modules/sync/sync.py | 129 -- pym/portage/sync/controller.py| 31 +-- pym/portage/tests/sync/test_sync_local.py | 6 +- pym/portage/util/_async/AsyncFunction.py | 67 4 files changed, 219 insertions(+), 14 deletions(-) diff --git a/pym/portage/emaint/modules/sync/sync.py b/pym/portage/emaint/modules/sync/sync.py index b463073..879d0f0 100644 --- a/pym/portage/emaint/modules/sync/sync.py +++ b/pym/portage/emaint/modules/sync/sync.py @@ -13,6 +13,10 @@ from portage.output import bold, red, create_color_func from portage._global_updates import _global_updates from portage.sync.controller import SyncManager from portage.util import writemsg_level +from portage.util.digraph import digraph +from portage.util._async.AsyncScheduler import AsyncScheduler +from portage.util._eventloop.global_event_loop import global_event_loop +from portage.util._eventloop.EventLoop import EventLoop import _emerge from _emerge.emergelog import emergelog @@ -201,6 +205,7 @@ class SyncRepos(object): k = "--" + k.replace("_", "-") self.emerge_config.opts[k] = v + selected_repos = [repo for repo in selected_repos if repo.sync_type is not None] msgs = [] if not selected_repos: msgs.append("Emaint sync, nothing to sync... returning") @@ -213,13 +218,20 @@ class SyncRepos(object): sync_manager = SyncManager( self.emerge_config.target_config.settings, emergelog) - retvals = [] - for repo in selected_repos: - if repo.sync_type is not None: - returncode, message = sync_manager.sync(self.emerge_config, repo) - retvals.append((repo.name, returncode)) - if message: - msgs.append(message) + + max_jobs = (self.emerge_config.opts.get('--jobs', 1) + if 'parallel-fetch' in self.emerge_config. + target_config.settings.features else 1) + sync_scheduler = SyncScheduler(emerge_config=self.emerge_config, + selected_repos=selected_repos, sync_manager=sync_manager, + max_jobs=max_jobs, + event_loop=global_event_loop() if portage._internal_caller else + EventLoop(main=False)) + + sync_scheduler.start() + sync_scheduler.wait() + retvals = sync_scheduler.retvals + msgs.extend(sync_scheduler.msgs) # Reload the whole config. portage._sync_mode = False @@ -287,3 +299,106 @@ class SyncRepos(object): messages.append("Action: %s for repo: %s, returned code = %s" % (action, rval[0], rval[1])) return messages + + +class SyncScheduler(AsyncScheduler): + ''' + Sync repos in parallel, but don't sync a given repo until all + of its masters have synced. + ''' + def __init__(self, **kwargs): + ''' + @param emerge_config: an emerge_config instance + @param selected_repos: list of RepoConfig instances + @param sync_manager: a SyncManger instance + ''' + self._emerge_config = kwargs.pop('emerge_config') + self._selected_repos = kwargs.pop('selected_repos') + self._sync_manager = kwargs.pop('sync_manager') + AsyncScheduler.__init__(self, **kwargs) + self._init_graph() + self.retvals = [] + self.msgs = [] + + def _init_graph(self): + ''' + Graph relationships between repos and their masters. + ''' + self._sync_graph = digraph() + self._leaf_nodes = [] + self._repo_map = {} +
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/resolver/, pym/portage/tests/resolver/binpkg_multi_instance/
commit: 6d4eb498e59ff6477b4290047bee78c77bd28676 Author: Zac Medico gentoo org> AuthorDate: Tue Feb 17 22:56:47 2015 + Commit: Zac Medico gentoo org> CommitDate: Wed Mar 4 21:32:07 2015 + URL: http://sources.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=6d4eb498 binpkg-multi-instance 4 of 7 Add a test case to verify that emerge --rebuilt-binaries works with binpkg-multi-instance. This relies on the fact that binary packages of the same version are ordered by BUILD_TIME, so that the latest builds are preferred when appropriate. pym/portage/tests/resolver/ResolverPlayground.py | 25 - .../resolver/binpkg_multi_instance/__init__.py | 2 + .../resolver/binpkg_multi_instance/__test__.py | 2 + .../binpkg_multi_instance/test_rebuilt_binaries.py | 101 + 4 files changed, 126 insertions(+), 4 deletions(-) diff --git a/pym/portage/tests/resolver/ResolverPlayground.py b/pym/portage/tests/resolver/ResolverPlayground.py index 84ad17c..6bdf2c7 100644 --- a/pym/portage/tests/resolver/ResolverPlayground.py +++ b/pym/portage/tests/resolver/ResolverPlayground.py @@ -39,6 +39,7 @@ class ResolverPlayground(object): config_files = frozenset(("eapi", "layout.conf", "make.conf", "package.accept_keywords", "package.keywords", "package.license", "package.mask", "package.properties", + "package.provided", "packages", "package.unmask", "package.use", "package.use.aliases", "package.use.stable.mask", "soname.provided", "unpack_dependencies", "use.aliases", "use.force", "use.mask", "layout.conf")) @@ -208,12 +209,18 @@ class ResolverPlayground(object): raise AssertionError('digest creation failed for %s' % ebuild_path) def _create_binpkgs(self, binpkgs): - for cpv, metadata in binpkgs.items(): + # When using BUILD_ID, there can be mutiple instances for the + # same cpv. Therefore, binpkgs may be an iterable instead of + # a dict. + items = getattr(binpkgs, 'items', None) + items = items() if items is not None else binpkgs + for cpv, metadata in items: a = Atom("=" + cpv, allow_repo=True) repo = a.repo if repo is None: repo = "test_repo" + pn = catsplit(a.cp)[1] cat, pf = catsplit(a.cpv) metadata = metadata.copy() metadata.setdefault("SLOT", "0") @@ -225,8 +232,13 @@ class ResolverPlayground(object): repo_dir = self.pkgdir category_dir = os.path.join(repo_dir, cat) - binpkg_path = os.path.join(category_dir, pf + ".tbz2") - ensure_dirs(category_dir) + if "BUILD_ID" in metadata: + binpkg_path = os.path.join(category_dir, pn, + "%s-%s.xpak"% (pf, metadata["BUILD_ID"])) + else: + binpkg_path = os.path.join(category_dir, pf + ".tbz2") + + ensure_dirs(os.path.dirname(binpkg_path)) t = portage.xpak.tbz2(binpkg_path) t.recompose_mem(portage.xpak.xpak_mem(metadata)) @@ -252,6 +264,7 @@ class ResolverPlayground(object): unknown_keys = set(metadata).difference( portage.dbapi.dbapi._known_keys) unknown_keys.discard("BUILD_TIME") + unknown_keys.discard("BUILD_ID") unknown_keys.discard("COUNTER") unknown_keys.discard("repository") unknown_keys.discard("USE") @@ -749,7 +762,11 @@ class ResolverPlaygroundResult(object): repo_str = "" if x.repo != "test_repo": repo_str = _repo_separator + x.repo - mergelist_str = x.cpv + repo_str + build_id_str = "" + if (x.type_name == "binary" and + x.cpv.build_id is not None): + build_id_str = "-%s" % x.cpv.build_id + mergelist_str = x.cpv + build_id_str + repo_str if x.built: if x.operation == "merge": desc = x.type_name diff --git a/pym/portage/tests/resolver/binpkg_multi_instance/__init__.py b/pym/portage/tests/resolver/bi
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/lint/
commit: 70a41bd4404502a3eacf6335c8d2c9503129 Author: Michał Górny gentoo org> AuthorDate: Fri Jan 30 22:53:50 2015 + Commit: Michał Górny gentoo org> CommitDate: Sun Feb 1 09:06:41 2015 + URL: http://sources.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=70a41bd4 test_compile_modules: skip files that require newer Python version Support skipping Python modules and scripts that require newer Python version than currently used during compile tests. Add a metadata db that can be used to store additional information about Python files, and store the required language version there. --- pym/portage/tests/lint/metadata.py | 11 +++ pym/portage/tests/lint/test_compile_modules.py | 13 + 2 files changed, 24 insertions(+) diff --git a/pym/portage/tests/lint/metadata.py b/pym/portage/tests/lint/metadata.py new file mode 100644 index 000..e3f90cb --- /dev/null +++ b/pym/portage/tests/lint/metadata.py @@ -0,0 +1,11 @@ +# Copyright 2015 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +module_metadata = { +} + +script_metadata = { + 'socks5-server.py': { + 'required_python': '3.3', + }, +} diff --git a/pym/portage/tests/lint/test_compile_modules.py b/pym/portage/tests/lint/test_compile_modules.py index 4826cad..51eb8cd 100644 --- a/pym/portage/tests/lint/test_compile_modules.py +++ b/pym/portage/tests/lint/test_compile_modules.py @@ -4,9 +4,11 @@ import errno import itertools import stat +import sys from portage.const import PORTAGE_BIN_PATH, PORTAGE_PYM_PATH, PORTAGE_PYM_PACKAGES from portage.tests import TestCase +from portage.tests.lint.metadata import module_metadata, script_metadata from portage import os from portage import _encodings from portage import _unicode_decode, _unicode_encode @@ -30,6 +32,17 @@ class CompileModulesTestCase(TestCase): st = os.lstat(x) if not stat.S_ISREG(st.st_mode): continue + + bin_path = os.path.relpath(x, PORTAGE_BIN_PATH) + mod_path = os.path.relpath(x, PORTAGE_PYM_PATH) + + meta = module_metadata.get(mod_path) or script_metadata.get(bin_path) + if meta: + req_py = tuple(int(x) for x + in meta.get('required_python', '0.0').split('.')) + if sys.version_info < req_py: + continue + do_compile = False if x[-3:] == '.py': do_compile = True
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/resolver/, pym/_emerge/, man/
commit: 1891388ea0ae0dd58903a71a3adc779731523601 Author: Zac Medico gentoo org> AuthorDate: Sat Jan 17 22:56:47 2015 + Commit: Zac Medico gentoo org> CommitDate: Sun Jan 18 18:54:24 2015 + URL: http://sources.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=1891388e emerge: default --backtrack=3 (bug #536926) The previous default emerge --backtrack=10 setting could lead to lots of wasted cpu time in cases where it will ultimately fail to find a valid solution anyway. Therefore, reduce the default to --backtrack=3. In order for the BacktrackingTestCase.testBacktrackNoWrongRebuilds to succeed, the test now needs to specify --backtrack=6. This is a rather obscure case though, so it does not seem worthwhile to increase the default because of it. X-Gentoo-Bug: 536926 X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=536926 Acked-by: Brian Dolbec gentoo.org> --- man/emerge.1| 2 +- pym/_emerge/depgraph.py | 2 +- pym/portage/tests/resolver/test_backtracking.py | 9 +++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/man/emerge.1 b/man/emerge.1 index aea7cae..fd9140f 100644 --- a/man/emerge.1 +++ b/man/emerge.1 @@ -384,7 +384,7 @@ precedence over existing changes. This option is automatically enabled with .BR \-\-backtrack=COUNT Specifies an integer number of times to backtrack if dependency calculation fails due to a conflict or an -unsatisfied dependency (default: \'10\'). +unsatisfied dependency (default: \'3\'). .TP .BR "\-\-binpkg\-changed\-deps [ y | n ]" Tells emerge to ignore binary packages for which the corresponding diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py index 3e9bfdd..1184dd6 100644 --- a/pym/_emerge/depgraph.py +++ b/pym/_emerge/depgraph.py @@ -8950,7 +8950,7 @@ def _backtrack_depgraph(settings, trees, myopts, myparams, myaction, myfiles, sp debug = "--debug" in myopts mydepgraph = None - max_retries = myopts.get('--backtrack', 10) + max_retries = myopts.get('--backtrack', 3) max_depth = max(1, (max_retries + 1) // 2) allow_backtracking = max_retries > 0 backtracker = Backtracker(max_depth) diff --git a/pym/portage/tests/resolver/test_backtracking.py b/pym/portage/tests/resolver/test_backtracking.py index 3b69eda..6567153 100644 --- a/pym/portage/tests/resolver/test_backtracking.py +++ b/pym/portage/tests/resolver/test_backtracking.py @@ -1,4 +1,4 @@ -# Copyright 2010-2014 Gentoo Foundation +# Copyright 2010-2015 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 from portage.tests import TestCase @@ -154,7 +154,12 @@ class BacktrackingTestCase(TestCase): world = ["dev-libs/B", "dev-libs/C"] - options = {'--update' : True, '--deep' : True, '--selective' : True} + options = { + '--backtrack': 6, + '--deep' : True, + '--selective' : True, + '--update' : True, + } test_cases = ( ResolverPlaygroundTestCase(
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/dbapi/, pym/portage/tests/resolver/
commit: a9aea5f9a055e6a38acfbaa1b6190d0c627cb299 Author: Zac Medico gentoo org> AuthorDate: Sat Dec 20 21:08:35 2014 + Commit: Zac Medico gentoo org> CommitDate: Sun Jan 18 18:39:12 2015 + URL: http://sources.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=a9aea5f9 TestFakedbapi: override EPREFIX for bug #492932 For tests, override portage.const.EPREFIX in order to avoid unwanted access to /etc/portage. This override may seem evil, but it is a convenient way to simulate a prefix install, and it is reasonable to do this because tests should be self-contained such that the "real" value of portage.const.EPREFIX is entirely irrelevant. X-Gentoo-Bug: 492932 X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=492932 Acked-by: Brian Dolbec gentoo.org> --- pym/portage/tests/dbapi/test_fakedbapi.py| 11 ++- pym/portage/tests/resolver/ResolverPlayground.py | 8 +++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/pym/portage/tests/dbapi/test_fakedbapi.py b/pym/portage/tests/dbapi/test_fakedbapi.py index 7713563..e4f5dd7 100644 --- a/pym/portage/tests/dbapi/test_fakedbapi.py +++ b/pym/portage/tests/dbapi/test_fakedbapi.py @@ -1,8 +1,9 @@ -# Copyright 2011-2013 Gentoo Foundation +# Copyright 2011-2015 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 import tempfile +import portage from portage import os from portage import shutil from portage.dbapi.virtual import fakedbapi @@ -49,6 +50,14 @@ class TestFakedbapi(TestCase): env = { "PORTAGE_REPOSITORIES": "[DEFAULT]\nmain-repo = test_repo\n[test_repo]\nlocation = %s" % test_repo } + + # Tests may override portage.const.EPREFIX in order to + # simulate a prefix installation. It's reasonable to do + # this because tests should be self-contained such that + # the "real" value of portage.const.EPREFIX is entirely + # irrelevant (see bug #492932). + portage.const.EPREFIX = tempdir + fakedb = fakedbapi(settings=config(config_profile_path="", env=env, eprefix=tempdir)) for cpv, metadata in packages: diff --git a/pym/portage/tests/resolver/ResolverPlayground.py b/pym/portage/tests/resolver/ResolverPlayground.py index 0be5d81..b5c0446 100644 --- a/pym/portage/tests/resolver/ResolverPlayground.py +++ b/pym/portage/tests/resolver/ResolverPlayground.py @@ -1,4 +1,4 @@ -# Copyright 2010-2014 Gentoo Foundation +# Copyright 2010-2015 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 from itertools import permutations @@ -72,6 +72,12 @@ class ResolverPlayground(object): self.eprefix = normalize_path(tempfile.mkdtemp()) else: self.eprefix = normalize_path(eprefix) + + # Tests may override portage.const.EPREFIX in order to + # simulate a prefix installation. It's reasonable to do + # this because tests should be self-contained such that + # the "real" value of portage.const.EPREFIX is entirely + # irrelevant (see bug #492932). portage.const.EPREFIX = self.eprefix.rstrip(os.sep) self.eroot = self.eprefix + os.sep
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/resolver/, pym/_emerge/, pym/portage/dep/
commit: a9064d08ef4c92a5d0d1bfb3dc8a01b7850812b0 Author: Zac Medico gentoo org> AuthorDate: Sun Dec 21 04:11:30 2014 + Commit: Zac Medico gentoo org> CommitDate: Mon Jan 5 19:43:59 2015 + URL: http://sources.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=a9064d08 Solve more slot-operator conflicts (531656) Add some heuristics to handle slot conflicts triggered by interaction of slot-operator dependencies with dependencies like those of labgl: ocaml:= || ( labltk https://bugs.gentoo.org/show_bug.cgi?id=531656 Acked-by: Alexander Berntsen gentoo.org> --- pym/_emerge/depgraph.py | 32 ++- pym/portage/dep/dep_check.py | 16 +- pym/portage/tests/resolver/test_or_choices.py | 80 ++- 3 files changed, 124 insertions(+), 4 deletions(-) diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py index 28abea4..6266c79 100644 --- a/pym/_emerge/depgraph.py +++ b/pym/_emerge/depgraph.py @@ -1,4 +1,4 @@ -# Copyright 1999-2014 Gentoo Foundation +# Copyright 1999-2015 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 from __future__ import division, print_function, unicode_literals @@ -451,6 +451,7 @@ class _dynamic_depgraph_config(object): self._graph_trees[myroot]["graph_db"] = graph_tree.dbapi self._graph_trees[myroot]["graph"] = self.digraph self._graph_trees[myroot]["want_update_pkg"] = depgraph._want_update_pkg + self._graph_trees[myroot]["downgrade_probe"] = depgraph._downgrade_probe def filtered_tree(): pass filtered_tree.dbapi = _dep_check_composite_db(depgraph, myroot) @@ -478,6 +479,7 @@ class _dynamic_depgraph_config(object): self._filtered_trees[myroot]["vartree"] = \ depgraph._frozen_config.trees[myroot]["vartree"] self._filtered_trees[myroot]["want_update_pkg"] = depgraph._want_update_pkg + self._filtered_trees[myroot]["downgrade_probe"] = depgraph._downgrade_probe dbs = [] # (db, pkg_type, built, installed, db_keys) @@ -1144,7 +1146,13 @@ class depgraph(object): writemsg_level(" pkg: %s\n" % pkg, level=logging.DEBUG, noiselevel=-1) all_parent_atoms = set() + highest_pkg = None + inst_pkg = None for pkg in conflict: + if pkg.installed: + inst_pkg = pkg + if highest_pkg is None or highest_pkg < pkg: + highest_pkg = pkg all_parent_atoms.update( self._dynamic_config._parent_atoms.get(pkg, [])) @@ -1167,6 +1175,15 @@ class depgraph(object): matched = [] for pkg in conflict: + if (pkg is highest_pkg and + not highest_pkg.installed and + inst_pkg is not None and + inst_pkg.sub_slot != highest_pkg.sub_slot and + not self._downgrade_probe(highest_pkg)): + # If an upgrade is desired, force the highest + # version into the graph (bug #531656). + non_matching_forced.add(highest_pkg) + if atom_set.findAtomForPackage(pkg, \ modified_use=self._pkg_use_enabled(pkg)) and \ not (is_arg_parent and pkg.installed): @@ -1220,14 +1237,20 @@ class depgraph(object): # the packages in the tuple. This way we don't have # to choose one. unexplored_tuples = set() + explored_nodes = set() while unexplored: # Handle all unexplored packages. while unexplored: node = unexplored.pop() for child in conflict_graph.child_nodes(node): - if child in forced: + # Don't explore a node more than once, in order + # to avoid infinite recursion. The forced set + # cannot be used for this pu
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/dbapi/
commit: c953151486b3cf92d931affc7fd3bb0b4fbe1a43 Author: Arfrever Frehtes Taifersar Arahesis Apache Org> AuthorDate: Mon Dec 15 16:26:23 2014 + Commit: Arfrever Frehtes Taifersar Arahesis apache org> CommitDate: Mon Dec 15 16:26:23 2014 + URL: http://sources.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=c9531514 portage.tests.dbapi.test_portdb_cache: Delete deprecated code. 9 calls to deprecated portage.repository.config.RepoConfigLoader.mainRepoLocation() function have been deleted. --- pym/portage/tests/dbapi/test_portdb_cache.py | 18 +- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/pym/portage/tests/dbapi/test_portdb_cache.py b/pym/portage/tests/dbapi/test_portdb_cache.py index f08d0f8..5ac9b03 100644 --- a/pym/portage/tests/dbapi/test_portdb_cache.py +++ b/pym/portage/tests/dbapi/test_portdb_cache.py @@ -47,7 +47,7 @@ class PortdbCacheTestCase(TestCase): (lambda: not os.path.exists(md5_cache_dir),), python_cmd + (textwrap.dedent(""" import os, sys, portage - if portage.portdb.repositories.mainRepoLocation() in portage.portdb._pregen_auxdb: + if portage.portdb.repositories['test_repo'].location in portage.portdb._pregen_auxdb: sys.exit(1) """),), @@ -56,13 +56,13 @@ class PortdbCacheTestCase(TestCase): (lambda: os.path.exists(md5_cache_dir),), python_cmd + (textwrap.dedent(""" import os, sys, portage - if portage.portdb.repositories.mainRepoLocation() not in portage.portdb._pregen_auxdb: + if portage.portdb.repositories['test_repo'].location not in portage.portdb._pregen_auxdb: sys.exit(1) """),), python_cmd + (textwrap.dedent(""" import os, sys, portage from portage.cache.flat_hash import md5_database - if not isinstance(portage.portdb._pregen_auxdb[portage.portdb.repositories.mainRepoLocation()], md5_database): + if not isinstance(portage.portdb._pregen_auxdb[portage.portdb.repositories['test_repo'].location], md5_database): sys.exit(1) """),), @@ -73,13 +73,13 @@ class PortdbCacheTestCase(TestCase): (lambda: os.path.exists(md5_cache_dir),), python_cmd + (textwrap.dedent(""" import os, sys, portage - if portage.portdb.repositories.mainRepoLocation() not in portage.portdb._pregen_auxdb: + if portage.portdb.repositories['test_repo'].location not in portage.portdb._pregen_auxdb: sys.exit(1) """),), python_cmd + (textwrap.dedent(""" import os, sys, portage from portage.cache.flat_hash import md5_database - if not isinstance(portage.portdb._pregen_auxdb[portage.portdb.repositories.mainRepoLocation()], md5_database): + if not isinstance(portage.portdb._pregen_auxdb[portage.portdb.repositories['test_repo'].location], md5_database): sys.exit(1) """),), @@ -90,13 +90,13 @@ class PortdbCacheTestCase(TestCase): ("cache-formats = pms md5-dict", layout_conf_path,, (portage_python, "-b", "-Wd", "-Wi::DeprecationWarning", "-c") + (textwrap.dedent(""" import os, sys, portage - if portage.portdb.repositories.mainRepoLocation() not in portage.portdb._pregen_auxdb: + if portage.portdb.repositories['test_repo'].location not in portage.portdb._pregen_auxdb: sys.exit(1) """),), (portage_python, "-b", "-Wd", "-Wi::DeprecationWarning", "-c") + (textwrap.dedent(""" import os, sys, portage from portage.cache.metadata import database as pms_database - if not isinstance(portage.portdb._pregen_auxdb[portage.portdb.repositories.mainRepoLocation()], pms_database): + if not isinstance(portage.portdb._pregen_auxdb[portage.portdb.repositories['test_repo'].location], pms_database): sys.exit(1)
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/glsa/
commit: cd0ca6c558cbe6bdada311f4302f28c2dbec1f0f Author: Arfrever Frehtes Taifersar Arahesis Apache Org> AuthorDate: Mon Dec 15 16:27:13 2014 + Commit: Arfrever Frehtes Taifersar Arahesis apache org> CommitDate: Mon Dec 15 16:27:13 2014 + URL: http://sources.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=cd0ca6c5 portage.tests.glsa.test_security_set: Delete deprecated code. 1 call to deprecated portage.repository.config.RepoConfigLoader.mainRepoLocation() function has been deleted. --- pym/portage/tests/glsa/test_security_set.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pym/portage/tests/glsa/test_security_set.py b/pym/portage/tests/glsa/test_security_set.py index bf1f82b..e73deab 100644 --- a/pym/portage/tests/glsa/test_security_set.py +++ b/pym/portage/tests/glsa/test_security_set.py @@ -1,4 +1,4 @@ -# Copyright 2013 Gentoo Foundation +# Copyright 2013-2014 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 from __future__ import unicode_literals @@ -129,8 +129,7 @@ class SecuritySetTestCase(TestCase): try: portdb = playground.trees[playground.eroot]["porttree"].dbapi - glsa_dir = os.path.join( - portdb.repositories.mainRepoLocation(), 'metadata', 'glsa') + glsa_dir = os.path.join(portdb.repositories['test_repo'].location, 'metadata', 'glsa') portage.util.ensure_dirs(glsa_dir) for glsa in glsas: with io.open(os.path.join(glsa_dir,
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/, /
commit: 8c6d7eb2b77c82b904c16ad812a794acb9731d66 Author: Michał Górny gentoo org> AuthorDate: Sat Nov 29 22:28:06 2014 + Commit: Michał Górny gentoo org> CommitDate: Tue Dec 2 23:05:39 2014 + URL: http://sources.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=8c6d7eb2 Restore sbindir install support Restore the ability to install sbin-tools into sbindir since it works fine with pure distutils. The issue is python-exec/eclass-specific and therefore all the relevant workarounds belong in the ebuild. --- pym/portage/tests/__init__.py | 4 +--- setup.py | 23 +++ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/pym/portage/tests/__init__.py b/pym/portage/tests/__init__.py index afa57e3..708dd59 100644 --- a/pym/portage/tests/__init__.py +++ b/pym/portage/tests/__init__.py @@ -197,9 +197,7 @@ class TestCase(unittest.TestCase): self.cnf_path = cnf_path self.cnf_etc_path = cnf_etc_path self.bindir = cnf_bindir - # sbin scripts are installed by setup.py to the bindir - # they are relocated to /usr/sbin dir by the ebuild later - self.sbindir = self.bindir + self.sbindir = cnf_sbindir def defaultTestResult(self): return TextTestResult() diff --git a/setup.py b/setup.py index dba8539..8231c0a 100755 --- a/setup.py +++ b/setup.py @@ -30,10 +30,12 @@ import sys x_scripts = { 'bin': [ - 'bin/archive-conf', 'bin/dispatch-conf', 'bin/ebuild', 'bin/egencache', - 'bin/emaint', 'bin/emerge', 'bin/emerge-webrsync', 'bin/emirrordist', - 'bin/env-update', 'bin/etc-update', 'bin/fixpackages', 'bin/portageq', - 'bin/quickpkg', 'bin/regenworld', 'bin/repoman', + 'bin/ebuild', 'bin/egencache', 'bin/emerge', 'bin/emerge-webrsync', + 'bin/emirrordist', 'bin/portageq', 'bin/quickpkg', 'bin/repoman' + ], + 'sbin': [ + 'bin/archive-conf', 'bin/dispatch-conf', 'bin/emaint', 'bin/env-update', + 'bin/etc-update', 'bin/fixpackages', 'bin/regenworld' ], } @@ -224,6 +226,10 @@ class x_build_scripts_bin(x_build_scripts_custom): dir_name = 'bin' +class x_build_scripts_sbin(x_build_scripts_custom): + dir_name = 'sbin' + + class x_build_scripts_portagebin(x_build_scripts_custom): dir_name = 'portage' @@ -238,6 +244,7 @@ class x_build_scripts(build_scripts): def run(self): self.run_command('build_scripts_bin') self.run_command('build_scripts_portagebin') + self.run_command('build_scripts_sbin') class x_clean(clean): @@ -473,6 +480,11 @@ class x_install_scripts_bin(x_install_scripts_custom): var_name = 'bindir' +class x_install_scripts_sbin(x_install_scripts_custom): + dir_name = 'sbin' + var_name = 'sbindir' + + class x_install_scripts_portagebin(x_install_scripts_custom): dir_name = 'portage' var_name = 'portage_bindir' @@ -488,6 +500,7 @@ class x_install_scripts(install_scripts): def run(self): self.run_command('install_scripts_bin') self.run_command('install_scripts_portagebin') + self.run_command('install_scripts_sbin') class x_sdist(sdist): @@ -624,6 +637,7 @@ setup( 'build_scripts': x_build_scripts, 'build_scripts_bin': x_build_scripts_bin, 'build_scripts_portagebin': x_build_scripts_portagebin, + 'build_scripts_sbin': x_build_scripts_sbin, 'build_tests': build_tests, 'clean': x_clean, 'docbook': docbook, @@ -636,6 +650,7 @@ setup( 'install_scripts': x_install_scripts, 'install_scripts_bin': x_install_scripts_bin, 'install_scripts_portagebin': x_install_scripts_portagebin, + 'install_scripts_sbin': x_install_scripts_sbin, 'sdist': x_sdist, 'test': test, },
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/ebuild/, pym/portage/tests/resolver/, ...
commit: b9c06a6a2dd4ccc875f8b9dd3139ea582e1e5621 Author: Zac Medico gentoo org> AuthorDate: Sun Nov 23 21:03:21 2014 + Commit: Zac Medico gentoo org> CommitDate: Thu Nov 27 08:45:40 2014 + URL: http://sources.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=b9c06a6a make.defaults: negative incrementals in USE_EXPAND (530222) Previously, USE_EXPAND variable settings in profile make.defaults only supported positive incremental settings. This patch adds support for negative settings like PYTHON_TARGETS="-python3_3", which brings behavior into alignment with PMS. Notably, this patch does not change behavior for settings in make.conf. In make.conf, settings to USE_EXPAND variables remain entirely non-incremental. PMS does not govern make.conf behavior. X-Gentoo-Bug: 530222 X-Gentoo-Url: https://bugs.gentoo.org/show_bug.cgi?id=530222 Acked-by: Brian Dolbec gentoo.org> --- pym/portage/package/ebuild/config.py | 18 +-- .../tests/ebuild/test_use_expand_incremental.py| 132 + pym/portage/tests/resolver/ResolverPlayground.py | 10 ++ 3 files changed, 151 insertions(+), 9 deletions(-) diff --git a/pym/portage/package/ebuild/config.py b/pym/portage/package/ebuild/config.py index bf39487..aca27f2 100644 --- a/pym/portage/package/ebuild/config.py +++ b/pym/portage/package/ebuild/config.py @@ -2332,22 +2332,22 @@ class config(object): if v is None: continue prefix = k.lower() + '_' - if k in myincrementals: - for x in v.split(): - if x[:1] == '-': - expand_use.append('-' + prefix + x[1:]) - else: - expand_use.append(prefix + x) - else: - for x in v.split(): + for x in v.split(): + if x[:1] == '-': + expand_use.append('-' + prefix + x[1:]) + else: expand_use.append(prefix + x) + if expand_use: expand_use.append(use) use = ' '.join(expand_use) self.make_defaults_use.append(use) self.make_defaults_use = tuple(self.make_defaults_use) + # Preserve both positive and negative flags here, since + # negative flags may later interact with other flags pulled + # in via USE_ORDER. configdict_defaults['USE'] = ' '.join( - stack_lists([x.split() for x in self.make_defaults_use])) + filter(None, self.make_defaults_use)) # Set to None so this code only runs once. self._make_defaults = None diff --git a/pym/portage/tests/ebuild/test_use_expand_incremental.py b/pym/portage/tests/ebuild/test_use_expand_incremental.py new file mode 100644 index 000..a58f08c --- /dev/null +++ b/pym/portage/tests/ebuild/test_use_expand_incremental.py @@ -0,0 +1,132 @@ +# Copyright 2014 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +from __future__ import unicode_literals + +import io + +from portage import os, _encodings +from portage.dep import Atom +from portage.package.ebuild.config import config +from portage.tests import TestCase +from portage.tests.resolver.ResolverPlayground import ResolverPlayground +from portage.util import ensure_dirs + +class UseExpandIncrementalTestCase(TestCase): + + def testUseExpandIncremental(self): + + profiles = ( + ( + 'base', + { + "eapi": ("5",), + "parent": ("..",), + "make.defaults": ( + "INPUT_DEVICES=\"keyboard mouse\"", + "PYTHON_TARGETS=\"python2_7 python3_3\"", + ("USE_EXPAND=\"INPUT_DEVICES PYTHON_TARGETS " + "VIDEO_CARDS\""), + ) + } + ), + ( +
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/resolver/, pym/portage/package/ebuild/, ...
commit: 10f991041672f36b05a42752c81ffc6ede0c3326 Author: Zac Medico gentoo org> AuthorDate: Sun Nov 23 21:03:21 2014 + Commit: Zac Medico gentoo org> CommitDate: Thu Nov 27 08:15:33 2014 + URL: http://sources.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=10f99104 make.defaults: negative incrementals in USE_EXPAND (530222) Previously, USE_EXPAND variable settings in profile make.defaults only supported positive incremental settings. This patch adds support for negative settings like PYTHON_TARGETS="-python3_3", which brings behavior into alignment with PMS. Notably, this patch does not change behavior for settings in make.conf. In make.conf, settings to USE_EXPAND variables remain entirely non-incremental. PMS does not govern make.conf behavior. X-Gentoo-Bug: 530222 X-Gentoo-Url: https://bugs.gentoo.org/show_bug.cgi?id=530222 Acked-by: Brian Dolbec gentoo.org> --- pym/portage/package/ebuild/config.py | 23 ++-- .../tests/ebuild/test_use_expand_incremental.py| 132 + pym/portage/tests/resolver/ResolverPlayground.py | 10 ++ 3 files changed, 155 insertions(+), 10 deletions(-) diff --git a/pym/portage/package/ebuild/config.py b/pym/portage/package/ebuild/config.py index bf39487..c7ac486 100644 --- a/pym/portage/package/ebuild/config.py +++ b/pym/portage/package/ebuild/config.py @@ -2314,6 +2314,7 @@ class config(object): # equivalent USE flags so that useful incremental behavior # is enabled (for sub-profiles). configdict_defaults = self.configdict['defaults'] + defaults_use = [] if self._make_defaults is not None: for i, cfg in enumerate(self._make_defaults): if not cfg: @@ -2332,22 +2333,24 @@ class config(object): if v is None: continue prefix = k.lower() + '_' - if k in myincrementals: - for x in v.split(): - if x[:1] == '-': - expand_use.append('-' + prefix + x[1:]) - else: - expand_use.append(prefix + x) - else: - for x in v.split(): + for x in v.split(): + if x[:1] == '-': + expand_use.append('-' + prefix + x[1:]) + else: expand_use.append(prefix + x) + + defaults_use.extend(expand_use) + defaults_use.extend(use.split()) + if expand_use: expand_use.append(use) use = ' '.join(expand_use) self.make_defaults_use.append(use) self.make_defaults_use = tuple(self.make_defaults_use) - configdict_defaults['USE'] = ' '.join( - stack_lists([x.split() for x in self.make_defaults_use])) + # Preserve both positive and negative flags here, since + # negative flags may later interact with other flags pulled + # in via USE_ORDER. + configdict_defaults['USE'] = ' '.join(defaults_use) # Set to None so this code only runs once. self._make_defaults = None diff --git a/pym/portage/tests/ebuild/test_use_expand_incremental.py b/pym/portage/tests/ebuild/test_use_expand_incremental.py new file mode 100644 index 000..a58f08c --- /dev/null +++ b/pym/portage/tests/ebuild/test_use_expand_incremental.py @@ -0,0 +1,132 @@ +# Copyright 2014 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +from __future__ import unicode_literals + +import io + +from portage import os, _encodings +from portage.dep import Atom +from portage.package.ebuild.config import config +from portage.tests import TestCase +from portage.tests.resolver.ResolverPlayground import ResolverPlayground +from portage.util import ensure_dirs + +class UseExpandIncrementalTestCase(TestCase): + + def testUseExpandIncremental(self): + + profiles = ( + ( + 'base', + { + "eapi": ("5",), +
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/ebuild/, pym/portage/package/ebuild/, ...
commit: ffbc3416f535752e50a60adfaf0d64486c50a035 Author: Zac Medico gentoo org> AuthorDate: Sun Nov 23 21:03:21 2014 + Commit: Zac Medico gentoo org> CommitDate: Thu Nov 27 08:02:00 2014 + URL: http://sources.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=ffbc3416 make.defaults: negative incrementals in USE_EXPAND (530222) Previously, USE_EXPAND variable settings in profile make.defaults only supported positive incremental settings. This patch adds support for negative settings like PYTHON_TARGETS="-python3_3", which brings behavior into alignment with PMS. Notably, this patch does not change behavior for settings in make.conf. In make.conf, settings to USE_EXPAND variables remain entirely non-incremental. PMS does not govern make.conf behavior. X-Gentoo-Bug: 530222 X-Gentoo-Url: https://bugs.gentoo.org/show_bug.cgi?id=530222 Acked-by: Brian Dolbec gentoo.org> --- pym/portage/package/ebuild/config.py | 19 ++- .../tests/ebuild/test_use_expand_incremental.py| 132 + pym/portage/tests/resolver/ResolverPlayground.py | 10 ++ 3 files changed, 151 insertions(+), 10 deletions(-) diff --git a/pym/portage/package/ebuild/config.py b/pym/portage/package/ebuild/config.py index bf39487..01876cd 100644 --- a/pym/portage/package/ebuild/config.py +++ b/pym/portage/package/ebuild/config.py @@ -2332,22 +2332,21 @@ class config(object): if v is None: continue prefix = k.lower() + '_' - if k in myincrementals: - for x in v.split(): - if x[:1] == '-': - expand_use.append('-' + prefix + x[1:]) - else: - expand_use.append(prefix + x) - else: - for x in v.split(): + for x in v.split(): + if x[:1] == '-': + expand_use.append('-' + prefix + x[1:]) + else: expand_use.append(prefix + x) + if expand_use: expand_use.append(use) use = ' '.join(expand_use) self.make_defaults_use.append(use) self.make_defaults_use = tuple(self.make_defaults_use) - configdict_defaults['USE'] = ' '.join( - stack_lists([x.split() for x in self.make_defaults_use])) + # Preserve both positive and negative flags here, since + # negative flags may later interact with other flags pulled + # in via USE_ORDER. + configdict_defaults['USE'] = ' '.join(self.make_defaults_use) # Set to None so this code only runs once. self._make_defaults = None diff --git a/pym/portage/tests/ebuild/test_use_expand_incremental.py b/pym/portage/tests/ebuild/test_use_expand_incremental.py new file mode 100644 index 000..a58f08c --- /dev/null +++ b/pym/portage/tests/ebuild/test_use_expand_incremental.py @@ -0,0 +1,132 @@ +# Copyright 2014 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +from __future__ import unicode_literals + +import io + +from portage import os, _encodings +from portage.dep import Atom +from portage.package.ebuild.config import config +from portage.tests import TestCase +from portage.tests.resolver.ResolverPlayground import ResolverPlayground +from portage.util import ensure_dirs + +class UseExpandIncrementalTestCase(TestCase): + + def testUseExpandIncremental(self): + + profiles = ( + ( + 'base', + { + "eapi": ("5",), + "parent": ("..",), + "make.defaults": ( + "INPUT_DEVICES=\"keyboard mouse\"", + "PYTHON_TARGETS=\"python2_7 python3_3\"", + ("USE_EXPAND=\"INPUT_DEVICES PYTHON_TARGETS " + "VIDEO_CARDS\""), + ) + } + ), +
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/resolver/, pym/_emerge/
commit: 390f90c2bee92ee5c845cdd765824b48ed6718ad Author: Zac Medico gentoo org> AuthorDate: Sun Nov 16 04:32:43 2014 + Commit: Zac Medico gentoo org> CommitDate: Sun Nov 16 08:58:53 2014 + URL: http://sources.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=390f90c2 _slot_operator_update_probe: fix bug #528610 This fixes a case inside _slot_operator_update_probe where it would select an inappropriate replacement_parent of a lower version than desired. The problem is solved by rejecting replacement_parent if its version is lower than the existing parent, and a downgrade is not desired. X-Gentoo-Bug: 528610 X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=528610 Acked-by: Brian Dolbec gentoo.org> --- pym/_emerge/depgraph.py| 8 +++ ..._slot_operator_update_probe_parent_downgrade.py | 68 ++ 2 files changed, 76 insertions(+) diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py index 94eaed8..2a839d0 100644 --- a/pym/_emerge/depgraph.py +++ b/pym/_emerge/depgraph.py @@ -1659,6 +1659,7 @@ class depgraph(object): debug = "--debug" in self._frozen_config.myopts selective = "selective" in self._dynamic_config.myparams want_downgrade = None + want_downgrade_parent = None def check_reverse_dependencies(existing_pkg, candidate_pkg, replacement_parent=None): @@ -1706,6 +1707,13 @@ class depgraph(object): for replacement_parent in self._iter_similar_available(dep.parent, dep.parent.slot_atom, autounmask_level=autounmask_level): + if replacement_parent < dep.parent: + if want_downgrade_parent is None: + want_downgrade_parent = self._downgrade_probe( + dep.parent) + if not want_downgrade_parent: + continue + if not check_reverse_dependencies(dep.parent, replacement_parent): continue diff --git a/pym/portage/tests/resolver/test_slot_operator_update_probe_parent_downgrade.py b/pym/portage/tests/resolver/test_slot_operator_update_probe_parent_downgrade.py new file mode 100644 index 000..2ec15b6 --- /dev/null +++ b/pym/portage/tests/resolver/test_slot_operator_update_probe_parent_downgrade.py @@ -0,0 +1,68 @@ +# Copyright 2014 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +from portage.tests import TestCase +from portage.tests.resolver.ResolverPlayground import \ + ResolverPlayground, ResolverPlaygroundTestCase + +class SlotOperatorUpdateProbeParentDowngradeTestCase(TestCase): + + def testSlotOperatorUpdateProbeParentDowngrade(self): + + ebuilds = { + "net-nds/openldap-2.4.40-r3": { + "EAPI": "5", + "RDEPEND": "
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/emerge/, bin/
commit: 3b08575233ecf1d3e6f31f959741a4826aeac4a9 Author: Zac Medico gentoo org> AuthorDate: Fri Nov 14 06:57:45 2014 + Commit: Zac Medico gentoo org> CommitDate: Fri Nov 14 17:28:19 2014 + URL: http://sources.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=3b085752 portageq: fix eroot parameter (bug #529200) The portageq eroot parameter has been broken since commit c9f6aa9f0151adb3c86706eaef1914cdbdcf2b6d, due to premature instantiation of portage.settings (before the ROOT variable was set). Premature access to the portage.settings attribute must be avoided by using other available means to determine the EPREFIX. Fixes: c9f6aa9f0151 ("Add cross-prefix support") X-Gentoo-Bug: 529200 X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=529200 Acked-by: Alexander Berntsen gentoo.org> --- bin/portageq| 9 - pym/portage/tests/emerge/test_simple.py | 10 -- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/bin/portageq b/bin/portageq index 009f116..ef565d1 100755 --- a/bin/portageq +++ b/bin/portageq @@ -1392,7 +1392,14 @@ def main(argv): sys.stderr.write("Run portageq with --help for info\n") sys.stderr.flush() sys.exit(os.EX_USAGE) - eprefix = portage.settings["EPREFIX"] + # Calculate EPREFIX and ROOT that will be used to construct + # portage.settings later. It's tempting to use + # portage.settings["EPREFIX"] here, but that would force + # instantiation of portage.settings, which we don't want to do + # until after we've calculated ROOT (see bug #529200). + eprefix = os.environ.get("EPREFIX", portage.const.EPREFIX) + if eprefix: + eprefix = portage.util.normalize_path(eprefix) eroot = portage.util.normalize_path(argv[2]) if eprefix: diff --git a/pym/portage/tests/emerge/test_simple.py b/pym/portage/tests/emerge/test_simple.py index 6c20a07..0101362 100644 --- a/pym/portage/tests/emerge/test_simple.py +++ b/pym/portage/tests/emerge/test_simple.py @@ -217,6 +217,8 @@ pkg_preinst() { self.assertFalse(test_ebuild is None) cross_prefix = os.path.join(eprefix, "cross_prefix") + cross_root = os.path.join(eprefix, "cross_root") + cross_eroot = os.path.join(cross_root, eprefix.lstrip(os.sep)) test_commands = ( env_update_cmd, @@ -318,6 +320,10 @@ pkg_preinst() { portageq_cmd + ("has_version", cross_prefix, "dev-libs/A"), ({"EPREFIX" : cross_prefix},) + \ portageq_cmd + ("has_version", cross_prefix, "dev-libs/B"), + + # Test ROOT support + ({"ROOT": cross_root},) + emerge_cmd + ("dev-libs/B",), + portageq_cmd + ("has_version", cross_eroot, "dev-libs/B"), ) distdir = playground.distdir @@ -372,8 +378,8 @@ pkg_preinst() { os.environ["__PORTAGE_TEST_HARDLINK_LOCKS"] updates_dir = os.path.join(test_repo_location, "profiles", "updates") - dirs = [cachedir, cachedir_pregen, cross_prefix, distdir, fake_bin, - portage_tmpdir, updates_dir, + dirs = [cachedir, cachedir_pregen, cross_eroot, cross_prefix, + distdir, fake_bin, portage_tmpdir, updates_dir, user_config_dir, var_cache_edb] etc_symlinks = ("dispatch-conf.conf", "etc-update.conf") # Override things that may be unavailable, or may have portability
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/resolver/, pym/_emerge/
commit: d3be49fe6827aa1974856dffe6d5a1aca80a7bed Author: Zac Medico gentoo org> AuthorDate: Mon Oct 27 00:32:36 2014 + Commit: Zac Medico gentoo org> CommitDate: Mon Oct 27 09:21:06 2014 + URL: http://sources.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=d3be49fe depgraph: fix bug #526160 This fixes _dep_check_composite_db to mask packages that aren't the highest visible match, but only if an update is desirable. This causes desirable updates to get pulled in for cases like bug #526160. The included unit test simulates the virtual/pypy update that triggered the bug. X-Gentoo-Bug: 526160 X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=526160 Acked-by: Alexander Berntsen gentoo.org> --- pym/_emerge/depgraph.py | 24 + pym/portage/tests/resolver/test_virtual_slot.py | 66 + 2 files changed, 90 insertions(+) diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py index 5180db5..78b9236 100644 --- a/pym/_emerge/depgraph.py +++ b/pym/_emerge/depgraph.py @@ -527,6 +527,8 @@ class depgraph(object): self._event_loop = (portage._internal_caller and global_event_loop() or EventLoop(main=False)) + self._select_atoms_parent = None + self.query = UserQuery(myopts).query def _load_vdb(self): @@ -4062,11 +4064,13 @@ class depgraph(object): self._dynamic_config._autounmask = False # backup state for restoration, in case of recursive # calls to this method + backup_parent = self._select_atoms_parent backup_state = mytrees.copy() try: # clear state from previous call, in case this # call is recursive (we have a backup, that we # will use to restore it later) + self._select_atoms_parent = None mytrees.pop("pkg_use_enabled", None) mytrees.pop("parent", None) mytrees.pop("atom_graph", None) @@ -4074,6 +4078,7 @@ class depgraph(object): mytrees["pkg_use_enabled"] = self._pkg_use_enabled if parent is not None: + self._select_atoms_parent = parent mytrees["parent"] = parent mytrees["atom_graph"] = atom_graph if priority is not None: @@ -4085,6 +4090,7 @@ class depgraph(object): finally: # restore state self._dynamic_config._autounmask = _autounmask_backup + self._select_atoms_parent = backup_parent mytrees.pop("pkg_use_enabled", None) mytrees.pop("parent", None) mytrees.pop("atom_graph", None) @@ -8529,6 +8535,24 @@ class _dep_check_composite_db(dbapi): elif not self._depgraph._equiv_ebuild_visible(pkg): return False + if pkg.cp.startswith("virtual/"): + # Force virtual updates to be pulled in when appropriate + # for bug #526160. + want_update = False + if self._depgraph._select_atoms_parent is not None: + want_update = \ + self._depgraph._want_update_pkg( + self._depgraph._select_atoms_parent, pkg) + + if want_update: + for new_child in self._depgraph._iter_similar_available( + pkg, next(iter(atom_set))): + if not self._depgraph._virt_deps_visible( + new_child, ignore_use=True): + continue + if pkg < new_child: + return False + in_graph = next(self._depgraph._dynamic_config._package_tracker.match( self._root, pkg.slot_atom, installed=False), None) diff --git a/pym/portage/tests/resolver/test_virtual_slot.py b/pym/portage/tests/resolver/test_virtual_slot.py index 1b19d77..2e5ca7f 100644 --- a/pym/portage/tests/resolver/test_virtual_slot.py +++ b/pym/portage/tests/resolver/test_virtual_slot.py @@ -92,6 +92,72 @@ class VirtualSlotResolverTestCase(TestCase): finally: playground.cleanup() +
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/emerge/, pym/portage/package/ebuild/, pym/portage/
commit: 1364fcd89384c9f60e6d72d7057dc00d8caba175 Author: Zac Medico gentoo org> AuthorDate: Mon Sep 29 18:18:42 2014 + Commit: Zac Medico gentoo org> CommitDate: Wed Oct 22 23:11:58 2014 + URL: http://sources.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=1364fcd8 Support unprivileged mode for bug #433453. This takes the existing unprivileged prefix support and enables it to work when EPREFIX is empty. This "unprivileged" mode is automatically enabled if the current user is not root, but has write access to the EROOT directory (not due to the 0002 bit). For use in conditional logic (for example, see doebuild.py diff), "unprivileged" is automatically added to the FEATURES variable. X-Gentoo-Bug: 433453 X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=433453 --- pym/portage/const.py| 1 + pym/portage/data.py | 95 ++--- pym/portage/package/ebuild/config.py| 21 +--- pym/portage/package/ebuild/doebuild.py | 4 +- pym/portage/tests/emerge/test_simple.py | 2 +- 5 files changed, 83 insertions(+), 40 deletions(-) diff --git a/pym/portage/const.py b/pym/portage/const.py index acb90f9..d472075 100644 --- a/pym/portage/const.py +++ b/pym/portage/const.py @@ -189,6 +189,7 @@ SUPPORTED_FEATURES = frozenset([ "unmerge-backup", "unmerge-logs", "unmerge-orphans", + "unprivileged", "userfetch", "userpriv", "usersandbox", diff --git a/pym/portage/data.py b/pym/portage/data.py index 54e3a8d..3d91e48 100644 --- a/pym/portage/data.py +++ b/pym/portage/data.py @@ -59,6 +59,15 @@ def portage_group_warning(): # If the "wheel" group does not exist then wheelgid falls back to 0. # If the "portage" group does not exist then portage_uid falls back to wheelgid. +# If the current user is not root, but has write access to the +# EROOT directory (not due to the 0002 bit), then use "unprivileged" +# mode which sets secpass = 2 and uses the UID and GID of the EROOT +# directory to generate default PORTAGE_INST_GID, PORTAGE_INST_UID, +# PORTAGE_USERNAME, and PORTAGE_GRPNAME settings. +def _unprivileged_mode(eroot, eroot_st): + return os.getuid() != 0 and os.access(eroot, os.W_OK) and \ + not eroot_st.st_mode & 0o0002 + uid = os.getuid() wheelgid = 0 try: @@ -77,13 +86,33 @@ def _get_global(k): if k in _initialized_globals: return globals()[k] - if k in ('portage_gid', 'portage_uid', 'secpass'): - global portage_gid, portage_uid, secpass - secpass = 0 + if k == 'secpass': + + unprivileged = False + if hasattr(portage, 'settings'): + unprivileged = "unprivileged" in portage.settings.features + else: + # The config class has equivalent code, but we also need to + # do it here if _disable_legacy_globals() has been called. + eroot = os.path.join(os.environ.get('ROOT', os.sep), + portage.const.EPREFIX.lstrip(os.sep)) + try: + eroot_st = os.stat(eroot) + except OSError: + pass + else: + unprivileged = _unprivileged_mode(eroot, eroot_st) + + v = 0 if uid == 0: - secpass = 2 - elif portage.const.EPREFIX: - secpass = 2 + v = 2 + elif unprivileged: + v = 2 + elif portage_gid in os.getgroups(): + v = 1 + + elif k in ('portage_gid', 'portage_uid'): + #Discover the uid and gid of the portage user/group keyerror = False try: @@ -98,9 +127,6 @@ def _get_global(k): keyerror = True portage_gid = 0 - if secpass < 1 and portage_gid in os.getgroups(): - secpass = 1 - # Suppress this error message if both PORTAGE_GRPNAME and # PORTAGE_USERNAME are set to "root", for things like # Android (see bug #454060). @@ -118,16 +144,15 @@ def _get_global(k): noiselevel=-1) portage_group_warning() + globals()['portage_gid'] = portage_gid _initialized_globals.add('portage_gid') + globals()['portage_uid'] = portage_uid _initialized_globals.add('portage_uid') - _initialized_globals.add('secpass') if k == 'portage_gid': return portage_gid elif k == 'portage_uid': return portage_uid - elif k == 'se
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/emerge/, pym/portage/dbapi/
commit: 5f7b4865ecafe4f04a92c5e1158f657b0dcd41d6 Author: Zac Medico gentoo org> AuthorDate: Fri Sep 26 03:02:41 2014 + Commit: Zac Medico gentoo org> CommitDate: Sun Oct 19 17:23:07 2014 + URL: http://sources.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=5f7b4865 dblink.mergeme: implement bug #523684 If a CONFIG_PROTECTed file was installed but no longer exists in the file system, then it may have been deleted or renamed by the admin. Therefore, force the file to be merged with a ._cfg name, so that the admin will be prompted for this update. X-Gentoo-Bug: 523684 X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=523684 --- pym/portage/dbapi/vartree.py| 32 pym/portage/tests/emerge/test_simple.py | 19 +-- 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py index b46ba0b..11384bf 100644 --- a/pym/portage/dbapi/vartree.py +++ b/pym/portage/dbapi/vartree.py @@ -4687,10 +4687,7 @@ class dblink(object): zing = "!!!" mymtime = None protected = self.isprotected(mydest) - if mydmode != None: - # destination file exists - - if stat.S_ISDIR(mydmode): + if mydmode is not None and stat.S_ISDIR(mydmode): # install of destination is blocked by an existing directory with the same name newdest = self._new_backup_path(mydest) msg = [] @@ -4703,12 +4700,15 @@ class dblink(object): self._eerror("preinst", msg) mydest = newdest - elif stat.S_ISREG(mydmode) or (stat.S_ISLNK(mydmode) and os.path.exists(mydest) and stat.S_ISREG(os.stat(mydest)[stat.ST_MODE])): + elif mydmode is None or stat.S_ISREG(mydmode) or \ + (stat.S_ISLNK(mydmode) and os.path.exists(mydest) + and stat.S_ISREG(os.stat(mydest)[stat.ST_MODE])): # install of destination is blocked by an existing regular file, # or by a symlink to an existing regular file; # now, config file management may come into play. # we only need to tweak mydest if cfg file management is in play. - if protected: + destmd5 = None + if protected and mydmode is not None: destmd5 = perform_md5(mydest, calc_prelink=calc_prelink) if protect_if_modified: contents_key = \ @@ -4721,7 +4721,21 @@ class dblink(object): if protected: # we have a protection path; enable config file management. cfgprot = 0 - if mymd5 == destmd5: + cfgprot_force = False + if mydmode is None: + if self._installed_instance is not None and \ + self._installed_instance._match_contents( + myrealdest) is not False: + # If the file doesn't exist, then it may + # have been deleted or renamed by the + # admin. Therefore, force the file to be + # merged with a ._cfg name, so that the + # admin will be prompted for this update + # (see bug #523684). + cfgprot_force = True +
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/
commit: 02ed485976fbf88a548c7b83978e23e3b50f41a2 Author: Brian Dolbec gentoo org> AuthorDate: Mon Sep 29 21:48:20 2014 + Commit: Brian Dolbec gmail com> CommitDate: Mon Sep 29 22:26:35 2014 + URL: http://sources.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=02ed4859 Fix travis test failures due to setup.py installing future sbin scripts in bindir --- pym/portage/tests/__init__.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pym/portage/tests/__init__.py b/pym/portage/tests/__init__.py index 708dd59..afa57e3 100644 --- a/pym/portage/tests/__init__.py +++ b/pym/portage/tests/__init__.py @@ -197,7 +197,9 @@ class TestCase(unittest.TestCase): self.cnf_path = cnf_path self.cnf_etc_path = cnf_etc_path self.bindir = cnf_bindir - self.sbindir = cnf_sbindir + # sbin scripts are installed by setup.py to the bindir + # they are relocated to /usr/sbin dir by the ebuild later + self.sbindir = self.bindir def defaultTestResult(self): return TextTestResult()
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/resolver/, pym/_emerge/
commit: c81f3f4586b7b6164f5038ac778098911fef9404 Author: Zac Medico gentoo org> AuthorDate: Fri Sep 19 09:24:58 2014 + Commit: Zac Medico gentoo org> CommitDate: Fri Sep 19 09:26:15 2014 + URL: http://sources.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=c81f3f45 _solve_..slot_conflicts: fix bug #522084 Fix _solve_non_slot_operator_slot_conflicts to add all parents to the conflict_graph, even for parents where the atom matches all relevant nodes. Otherwise, we risk removing all of the matched nodes from the graph, which would cause a missed update. X-Gentoo-Bug: 522084 X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=522084 Reviewed-by: Alexander Berntsen gentoo.org> --- pym/_emerge/depgraph.py| 14 ++-- .../test_solve_non_slot_operator_slot_conflicts.py | 75 ++ 2 files changed, 82 insertions(+), 7 deletions(-) diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py index e7ae720..f4e5a1b 100644 --- a/pym/_emerge/depgraph.py +++ b/pym/_emerge/depgraph.py @@ -1172,12 +1172,15 @@ class depgraph(object): for match in matched: writemsg_level(" match: %s\n" % match, level=logging.DEBUG, noiselevel=-1) - if len(matched) == len(conflict): - # All packages match. - continue + if len(matched) > 1: + # Even if all packages match, this parent must still + # be added to the conflict_graph. Otherwise, we risk + # removing all of these packages from the depgraph, + # which could cause a missed update (bug #522084). + conflict_graph.add(or_tuple(matched), parent) elif len(matched) == 1: conflict_graph.add(matched[0], parent) - elif len(matched) == 0: + else: # This typically means that autounmask broke a # USE-dep, but it could also be due to the slot # not matching due to multislot (bug #220341). @@ -1189,9 +1192,6 @@ class depgraph(object): for pkg in conflict: writemsg_level(" non-match: %s\n" % pkg, level=logging.DEBUG, noiselevel=-1) - else: - # More than one packages matched, but not all. - conflict_graph.add(or_tuple(matched), parent) for pkg in indirect_conflict_pkgs: for parent, atom in self._dynamic_config._parent_atoms.get(pkg, []): diff --git a/pym/portage/tests/resolver/test_solve_non_slot_operator_slot_conflicts.py b/pym/portage/tests/resolver/test_solve_non_slot_operator_slot_conflicts.py new file mode 100644 index 000..c6024f4 --- /dev/null +++ b/pym/portage/tests/resolver/test_solve_non_slot_operator_slot_conflicts.py @@ -0,0 +1,75 @@ +# Copyright 2014 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +from portage.tests import TestCase +from portage.tests.resolver.ResolverPlayground import (ResolverPlayground, + ResolverPlaygroundTestCase) + +class SolveNonSlotOperatorSlotConflictsTestCase(TestCase): + + def testSolveNonSlotOperatorSlotConflicts(self): + + ebuilds = { + + "app-misc/A-1" : { + "EAPI": "5", + "SLOT": "0/1", + "PDEPEND": "app-misc/B" + }, + + "app-misc/A-2" : { + "EAPI": "5", + "SLOT": "0/2", + "PDEPEND": "app-misc/B" + }, + + "app-misc/B-0" : { + "EAPI": "5", + "RDEPEND": "app-misc/A:=" + }, + + } + + installed = { + + "app-misc/A-1" : { + "EAPI": "5", + "SLOT": "0/1", + "PDEPEND": "app-misc/B" + }, + + "app-misc/B-0" : { + "EAPI": "5", + "RDEPEND": "app-misc/A:0/1=" + }, + + } +
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/resolver/, pym/_emerge/
commit: beecd610f21497609679a08f867fd88090c71fb7 Author: Zac Medico gentoo org> AuthorDate: Fri Sep 19 09:16:32 2014 + Commit: Zac Medico gentoo org> CommitDate: Fri Sep 19 09:16:32 2014 + URL: http://sources.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=beecd610 _backtrack_depgraph: fix bug #523048 This fixes _backtrack_depgraph to immediately report necessary REQUIRED_USE changes instead of discarding the graph. This is accomplished by replacing the depgraph.success_without_autounmask method with a new need_config_change method that accounts for both autounmask and REQUIRED_USE changes. X-Gentoo-Bug: 523048 X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=523048 Acked-by: Brian Dolbec gentoo.org> Acked-by: Alexander Berntsen gentoo.org> --- pym/_emerge/depgraph.py| 11 ++-- pym/portage/tests/resolver/ResolverPlayground.py | 19 +- .../resolver/test_slot_operator_required_use.py| 72 ++ 3 files changed, 95 insertions(+), 7 deletions(-) diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py index 6332733..e7ae720 100644 --- a/pym/_emerge/depgraph.py +++ b/pym/_emerge/depgraph.py @@ -421,6 +421,7 @@ class _dynamic_depgraph_config(object): self._buildpkgonly_deps_unsatisfied = False self._autounmask = depgraph._frozen_config.myopts.get('--autounmask') != 'n' self._success_without_autounmask = False + self._required_use_unsatisfied = False self._traverse_ignored_deps = False self._complete_mode = False self._slot_operator_deps = {} @@ -2461,6 +2462,7 @@ class depgraph(object): self._dynamic_config._unsatisfied_deps_for_display.append( ((pkg.root, atom), {"myparent" : dep.parent, "show_req_use" : pkg})) + self._dynamic_config._required_use_unsatisfied = True self._dynamic_config._skip_restart = True return 0 @@ -8390,8 +8392,9 @@ class depgraph(object): return self._dynamic_config._need_restart and \ not self._dynamic_config._skip_restart - def success_without_autounmask(self): - return self._dynamic_config._success_without_autounmask + def need_config_change(self): + return self._dynamic_config._success_without_autounmask or \ + self._dynamic_config._required_use_unsatisfied def autounmask_breakage_detected(self): try: @@ -8665,7 +8668,7 @@ def _backtrack_depgraph(settings, trees, myopts, myparams, myaction, myfiles, sp backtrack_parameters=backtrack_parameters) success, favorites = mydepgraph.select_files(myfiles) - if success or mydepgraph.success_without_autounmask(): + if success or mydepgraph.need_config_change(): break elif not allow_backtracking: break @@ -8677,7 +8680,7 @@ def _backtrack_depgraph(settings, trees, myopts, myparams, myaction, myfiles, sp else: break - if not (success or mydepgraph.success_without_autounmask()) and backtracked: + if not (success or mydepgraph.need_config_change()) and backtracked: if debug: writemsg_level( diff --git a/pym/portage/tests/resolver/ResolverPlayground.py b/pym/portage/tests/resolver/ResolverPlayground.py index d74a410..2d16251 100644 --- a/pym/portage/tests/resolver/ResolverPlayground.py +++ b/pym/portage/tests/resolver/ResolverPlayground.py @@ -674,7 +674,8 @@ class ResolverPlaygroundTestCase(object): expected = x break elif key in ("unstable_keywords", "needed_p_mask_changes", - "unsatisfied_deps") and expected is not None: + "unsatisfied_deps", "required_use_unsatisfied") and \ + expected is not None: expected = set(expected) elif key == "forced_rebuilds" and expected is not None: @@ -692,11 +693,14 @@ class ResolverPlaygroundTestCase(object): class ResolverPlaygroundResult(object): checks = ( - "success", "mergelist", "use_changes", "license_changes", "unstable_keywords", "slot_collision_solutions", - "circular_dependency_solutions", "needed_p_mask_changes", "unsatisfied_deps", "forced_rebuilds" + "success", "mergelist", "use_changes", "license_changes", + "unstable_keywords", "slot_collision_solutions", + "circular_de
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/resolver/
commit: 52970a73754160a203e34684e7000ba6f8a47667 Author: Zac Medico gentoo org> AuthorDate: Fri Sep 19 08:47:59 2014 + Commit: Zac Medico gentoo org> CommitDate: Fri Sep 19 08:47:59 2014 + URL: http://sources.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=52970a73 ResolverPlayground: inline _iter_forced_rebuilds Use an inline generator expression rather than a function, since the function was only used once. --- pym/portage/tests/resolver/ResolverPlayground.py | 10 -- 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/pym/portage/tests/resolver/ResolverPlayground.py b/pym/portage/tests/resolver/ResolverPlayground.py index 646987d..d74a410 100644 --- a/pym/portage/tests/resolver/ResolverPlayground.py +++ b/pym/portage/tests/resolver/ResolverPlayground.py @@ -778,12 +778,10 @@ class ResolverPlaygroundResult(object): for dep_info in self.depgraph._dynamic_config._unsatisfied_deps_for_display) if self.depgraph._forced_rebuilds: - self.forced_rebuilds = dict(self._iter_forced_rebuilds()) - - def _iter_forced_rebuilds(self): - for child_dict in self.depgraph._forced_rebuilds.values(): - for child, parents in child_dict.items(): - yield child.cpv, set(parent.cpv for parent in parents) + self.forced_rebuilds = dict( + (child.cpv, set(parent.cpv for parent in parents)) + for child_dict in self.depgraph._forced_rebuilds.values() + for child, parents in child_dict.items()) class ResolverPlaygroundDepcleanResult(object):
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/resolver/, pym/_emerge/
commit: 3f0799054b4e5ef88feb59d20d262668ca79df33 Author: Zac Medico gentoo org> AuthorDate: Fri Sep 12 07:07:13 2014 + Commit: Zac Medico gentoo org> CommitDate: Wed Sep 17 16:29:07 2014 + URL: http://sources.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=3f079905 _compute_abi_rebuild_info: fix bug #521990 Since self._dynamic_config._slot_operator_deps only contains deps for packages added to the graph, it doesn't contain potentially relevant deps of installed packages that have not been added to the graph. Therefore, generate pseudo-deps for such installed packages, and use those to generate the rebuild info. X-Gentoo-Bug: 521990 X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=521990 --- pym/_emerge/depgraph.py| 100 + pym/portage/tests/resolver/ResolverPlayground.py | 15 +++- .../resolver/test_slot_conflict_force_rebuild.py | 84 + 3 files changed, 183 insertions(+), 16 deletions(-) diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py index d85494a..6332733 100644 --- a/pym/_emerge/depgraph.py +++ b/pym/_emerge/depgraph.py @@ -647,26 +647,96 @@ class depgraph(object): # Go through all slot operator deps and check if one of these deps # has a parent that is matched by one of the atoms from above. forced_rebuilds = {} - for (root, slot_atom), deps in self._dynamic_config._slot_operator_deps.items(): - rebuild_atoms = atoms.get(root, set()) - for dep in deps: - if not isinstance(dep.parent, Package): - continue + for root, rebuild_atoms in atoms.items(): - if dep.parent.installed or dep.child.installed or \ - dep.parent.slot_atom not in rebuild_atoms: - continue + for slot_atom in rebuild_atoms: + + inst_pkg, reinst_pkg = \ + self._select_pkg_from_installed(root, slot_atom) - # Make sure the child's slot/subslot has changed. If it hasn't, - # then another child has forced this rebuild. - installed_pkg = self._select_pkg_from_installed(root, dep.child.slot_atom)[0] - if installed_pkg and installed_pkg.slot == dep.child.slot and \ - installed_pkg.sub_slot == dep.child.sub_slot: + if inst_pkg is reinst_pkg or reinst_pkg is None: continue - # The child has forced a rebuild of the parent - forced_rebuilds.setdefault(root, {}).setdefault(dep.child, set()).add(dep.parent) + # Generate pseudo-deps for any slot-operator deps of + # inst_pkg. Its deps aren't in _slot_operator_deps + # because it hasn't been added to the graph, but we + # are interested in any rebuilds that it triggered. + built_slot_op_atoms = [] + if inst_pkg is not None: + selected_atoms = self._select_atoms_probe( + inst_pkg.root, inst_pkg) + for atom in selected_atoms: + if atom.slot_operator_built: + built_slot_op_atoms.append(atom) + + if not built_slot_op_atoms: + continue + + # Use a cloned list, since we may append to it below. + deps = self._dynamic_config._slot_operator_deps.get( + (root, slot_atom), [])[:] + + if built_slot_op_atoms and reinst_pkg is not None: + for child in self._dynamic_config.digraph.child_nodes( + reinst_pkg): + + if child.installed: + continue + + for atom in built_slot_op_atoms: + # NOTE: Since atom comes from inst_pkg, and + # reinst_pkg is the replacement parent, there's + # no guarantee that atom will complet
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/resolver/, pym/_emerge/
commit: 38d9d0d3aa260c29b0a49ad0933e425e8e729b07 Author: Zac Medico gentoo org> AuthorDate: Tue Sep 16 17:57:49 2014 + Commit: Brian Dolbec gmail com> CommitDate: Tue Sep 16 20:25:13 2014 + URL: http://sources.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=38d9d0d3 _solve_..slot_conflicts: fix bug #510270 This fixes an IndexError in _solve_non_slot_operator_slot_conflicts which occurs when none of the conflict packages matched a particular atom. This typically means that autounmask broke a USE-dep, but it could also be due to the slot not matching due to multislot (bug #220341). Either way, don't try to solve this conflict. Instead, force all of the associated conflict nodes into the graph so that they are protected from removal by the conflict solver. X-Gentoo-Bug: 510270 X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=510270 --- pym/_emerge/depgraph.py| 14 + pym/portage/tests/resolver/ResolverPlayground.py | 9 .../tests/resolver/test_autounmask_use_breakage.py | 63 ++ 3 files changed, 86 insertions(+) diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py index cc87d9f..d85494a 100644 --- a/pym/_emerge/depgraph.py +++ b/pym/_emerge/depgraph.py @@ -1059,6 +1059,7 @@ class depgraph(object): def __str__(self): return "(%s)" % ",".join(str(pkg) for pkg in self) + non_matching_forced = set() for conflict in conflicts: if debug: writemsg_level(" conflict:\n", level=logging.DEBUG, noiselevel=-1) @@ -1105,6 +1106,18 @@ class depgraph(object): continue elif len(matched) == 1: conflict_graph.add(matched[0], parent) + elif len(matched) == 0: + # This typically means that autounmask broke a + # USE-dep, but it could also be due to the slot + # not matching due to multislot (bug #220341). + # Either way, don't try to solve this conflict. + # Instead, force them all into the graph so that + # they are protected from removal. + non_matching_forced.update(conflict) + if debug: + for pkg in conflict: + writemsg_level(" non-match: %s\n" % pkg, + level=logging.DEBUG, noiselevel=-1) else: # More than one packages matched, but not all. conflict_graph.add(or_tuple(matched), parent) @@ -1125,6 +1138,7 @@ class depgraph(object): # Now select required packages. Collect them in the # 'forced' set. forced = set([non_conflict_node]) + forced.update(non_matching_forced) unexplored = set([non_conflict_node]) # or_tuples get special handling. We first explore # all packages in the hope of having forced one of diff --git a/pym/portage/tests/resolver/ResolverPlayground.py b/pym/portage/tests/resolver/ResolverPlayground.py index 77a5b5c..b1974d7 100644 --- a/pym/portage/tests/resolver/ResolverPlayground.py +++ b/pym/portage/tests/resolver/ResolverPlayground.py @@ -549,6 +549,7 @@ class ResolverPlaygroundTestCase(object): self.all_permutations = kwargs.pop("all_permutations", False) self.ignore_mergelist_order = kwargs.pop("ignore_mergelist_order", False) self.ambiguous_merge_order = kwargs.pop("ambiguous_merge_order", False) + self.ambiguous_slot_collision_solutions = kwargs.pop("ambiguous_slot_collision_solutions", False) self.check_repo_names = kwargs.pop("check_repo_names", False) self.merge_order_assertions = kwargs.pop("merge_order_assertions", False) @@ -664,6 +665,14 @@ class ResolverPlaygroundTestCase(object): str((node1, node2))) + \ ", got: " + str(got)) + elif key == "slot_collision_solutions" and \ + self.ambiguous_slot_collision_solutions: + # Tests that use all_permutations can have multiple + # outcomes here. + for x in expected: +
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/resolver/
commit: 4fcf4fa56c0033d726eb0755e3ca67b3337ad944 Author: Zac Medico gentoo org> AuthorDate: Sat Sep 13 00:41:00 2014 + Commit: Brian Dolbec gmail com> CommitDate: Tue Sep 16 03:29:41 2014 + URL: http://sources.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=4fcf4fa5 Add test for bug #522652 with slot-operator This test case uses || ( bar foo:= ) syntax that is forbidden by PMS. --- .../tests/resolver/test_slot_operator_rebuild.py | 80 ++ 1 file changed, 80 insertions(+) diff --git a/pym/portage/tests/resolver/test_slot_operator_rebuild.py b/pym/portage/tests/resolver/test_slot_operator_rebuild.py new file mode 100644 index 000..42512aa --- /dev/null +++ b/pym/portage/tests/resolver/test_slot_operator_rebuild.py @@ -0,0 +1,80 @@ +# Copyright 2014 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +from portage.tests import TestCase +from portage.tests.resolver.ResolverPlayground import (ResolverPlayground, + ResolverPlaygroundTestCase) + +class SlotOperatorRebuildTestCase(TestCase): + + def testSlotOperatorRebuild(self): + + ebuilds = { + + "app-misc/A-1" : { + "EAPI": "5", + "SLOT": "0/1" + }, + + "app-misc/A-2" : { + "EAPI": "5", + "SLOT": "0/2" + }, + + "app-misc/B-0" : { + "EAPI": "5", + "RDEPEND": "app-misc/A:=" + }, + + "app-misc/C-0" : { + "EAPI": "5", + "RDEPEND": "|| ( app-misc/X app-misc/A:= )" + }, + + } + + installed = { + + "app-misc/A-1" : { + "EAPI": "5", + "SLOT": "0/1" + }, + + "app-misc/B-0" : { + "EAPI": "5", + "RDEPEND": "app-misc/A:0/1=" + }, + + "app-misc/C-0" : { + "EAPI": "5", + "RDEPEND": "|| ( app-misc/X app-misc/A:0/1= )" + }, + + } + + world = ["app-misc/B", "app-misc/C"] + + test_cases = ( + + # Test bug #522652, where the unsatisfiable app-misc/X + # atom is selected, and the dependency is placed into + # _initially_unsatisfied_deps where it is ignored, causing + # the app-misc/C-0 rebuild to be missed. + ResolverPlaygroundTestCase( + ["app-misc/A"], + options = {"--dynamic-deps": "n"}, + success = True, + ambiguous_merge_order = True, + mergelist = ['app-misc/A-2', ('app-misc/B-0', 'app-misc/C-0')] + ), + + ) + + playground = ResolverPlayground(ebuilds=ebuilds, + installed=installed, world=world, debug=False) + try: + for test_case in test_cases: + playground.run_TestCase(test_case) + self.assertEqual(test_case.test_success, True, test_case.fail_msg) + finally: + playground.cleanup()
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/resolver/, pym/portage/dep/
commit: d1e8d3468d0cee24480f6cbe16b2ca82ec7dc9fa Author: Zac Medico gentoo org> AuthorDate: Sat Sep 13 00:32:53 2014 + Commit: Brian Dolbec gmail com> CommitDate: Mon Sep 15 04:00:15 2014 + URL: http://sources.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=d1e8d346 dep_zapdeps: fix bug #522652 For cases such as || ( X
[gentoo-commits] proj/portage:master commit in: pym/portage/tests/, pym/portage/tests/resolver/, pym/portage/tests/dbapi/, ...
commit: 529b6985cb3f65d52d6f54bb251c446d317b6508 Author: Michał Górny gentoo org> AuthorDate: Sat Aug 9 10:17:59 2014 + Commit: Brian Dolbec gmail com> CommitDate: Thu Sep 11 23:44:25 2014 + URL: http://sources.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=529b6985 tests: Fix running on installed copy of Portage --- pym/portage/tests/__init__.py| 20 ++ pym/portage/tests/dbapi/test_portdb_cache.py | 5 ++--- pym/portage/tests/emerge/test_emerge_slot_abi.py | 7 +++ pym/portage/tests/emerge/test_simple.py | 26 pym/portage/tests/lint/test_compile_modules.py | 10 + pym/portage/tests/lint/test_import_modules.py| 8 ++-- pym/portage/tests/repoman/test_simple.py | 8 +--- pym/portage/tests/resolver/ResolverPlayground.py | 8 +--- pym/portage/tests/util/test_getconfig.py | 4 +--- 9 files changed, 61 insertions(+), 35 deletions(-) diff --git a/pym/portage/tests/__init__.py b/pym/portage/tests/__init__.py index 697b800..708dd59 100644 --- a/pym/portage/tests/__init__.py +++ b/pym/portage/tests/__init__.py @@ -25,8 +25,24 @@ import portage from portage import os from portage import _encodings from portage import _unicode_decode +from portage.const import (EPREFIX, GLOBAL_CONFIG_PATH, PORTAGE_BASE_PATH, + PORTAGE_BIN_PATH) from portage.util._argparse import ArgumentParser + +if portage._not_installed: + cnf_path = os.path.join(PORTAGE_BASE_PATH, 'cnf') + cnf_etc_path = cnf_path + cnf_bindir = PORTAGE_BIN_PATH + cnf_sbindir = cnf_bindir +else: + cnf_path = os.path.join(EPREFIX or '/', GLOBAL_CONFIG_PATH) + cnf_etc_path = os.path.join(EPREFIX or '/', 'etc') + cnf_eprefix = EPREFIX + cnf_bindir = os.path.join(EPREFIX or '/', 'usr', 'bin') + cnf_sbindir = os.path.join(EPREFIX or '/', 'usr', 'sbin') + + def main(): suite = unittest.TestSuite() basedir = os.path.dirname(os.path.realpath(__file__)) @@ -178,6 +194,10 @@ class TestCase(unittest.TestCase): unittest.TestCase.__init__(self, *pargs, **kwargs) self.todo = False self.portage_skip = None + self.cnf_path = cnf_path + self.cnf_etc_path = cnf_etc_path + self.bindir = cnf_bindir + self.sbindir = cnf_sbindir def defaultTestResult(self): return TextTestResult() diff --git a/pym/portage/tests/dbapi/test_portdb_cache.py b/pym/portage/tests/dbapi/test_portdb_cache.py index 3c77ed3..f08d0f8 100644 --- a/pym/portage/tests/dbapi/test_portdb_cache.py +++ b/pym/portage/tests/dbapi/test_portdb_cache.py @@ -8,8 +8,7 @@ import textwrap import portage from portage import os from portage import _unicode_decode -from portage.const import (BASH_BINARY, PORTAGE_BIN_PATH, - PORTAGE_PYM_PATH, USER_CONFIG_PATH) +from portage.const import (BASH_BINARY, PORTAGE_PYM_PATH, USER_CONFIG_PATH) from portage.tests import TestCase from portage.tests.resolver.ResolverPlayground import ResolverPlayground from portage.util import ensure_dirs @@ -38,7 +37,7 @@ class PortdbCacheTestCase(TestCase): portage_python = portage._python_interpreter egencache_cmd = (portage_python, "-b", "-Wd", - os.path.join(PORTAGE_BIN_PATH, "egencache"), + os.path.join(self.bindir, "egencache"), "--repo", "test_repo", "--repositories-configuration", settings.repositories.config_string()) python_cmd = (portage_python, "-b", "-Wd", "-c") diff --git a/pym/portage/tests/emerge/test_emerge_slot_abi.py b/pym/portage/tests/emerge/test_emerge_slot_abi.py index fd7ec0e..d1f2d92 100644 --- a/pym/portage/tests/emerge/test_emerge_slot_abi.py +++ b/pym/portage/tests/emerge/test_emerge_slot_abi.py @@ -7,8 +7,7 @@ import sys import portage from portage import os from portage import _unicode_decode -from portage.const import (BASH_BINARY, PORTAGE_BIN_PATH, - PORTAGE_PYM_PATH, USER_CONFIG_PATH) +from portage.const import (BASH_BINARY, PORTAGE_PYM_PATH, USER_CONFIG_PATH) from portage.process import find_binary from portage.tests import TestCase from portage.tests.resolver.ResolverPlayground import ResolverPlayground @@ -70,9 +69,9 @@ class SlotAbiEmergeTestCase(TestCase): portage_python = portage._python_interpreter ebuild_cmd = (portage_python, "-b", "-Wd", - os.path.join(PORTAGE_BIN_PATH, "ebuild")) + os.path.join(self.bindir, "ebuild")) emerge_cmd = (portage_python, "-b", "-Wd", - os.path.join(PORTAGE_BIN_PATH, "emerge")) + os.path.join(self.bindir, "emerge")) test_ebuild = portdb.findname("dev-libs/dbus-glib-0.98") self.assertFal