When launching lib/portage/tests/dbapi/test_auxdb.py via this script that runs pytest with the multiprocessing spawn start method, it fails: > import multiprocessing > import sys > import pytest > if __name__ == "__main__": > multiprocessing.set_start_method("spawn", force=True) > sys.exit(pytest.console_main()) > ============================= test session starts ============================== > platform linux -- Python 3.12.0, pytest-7.4.2, pluggy-1.3.0 > rootdir: portage > collected 4 items > > lib/portage/tests/dbapi/test_auxdb.py FFFF > > =================================== FAILURES =================================== > __________________________ AuxdbTestCase.test_anydbm ___________________________ > > self = <portage.tests.dbapi.test_auxdb.AuxdbTestCase testMethod=test_anydbm> > > def test_anydbm(self): > try: > from portage.cache.anydbm import database > except ImportError: > self.skipTest("dbm import failed") > > self._test_mod("portage.cache.anydbm.database", multiproc=False) > > lib/portage/tests/dbapi/test_auxdb.py:16: > _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ > lib/portage/tests/dbapi/test_auxdb.py:80: in _test_mod > loop.run_until_complete(loop.run_in_executor(ForkExecutor(), test_func)) > /usr/lib/python3.12/asyncio/base_events.py:840: in run_in_executor > executor.submit(func, *args), loop=self) > lib/portage/util/futures/executor/fork.py:46: in submit > self._schedule() > lib/portage/util/futures/executor/fork.py:62: in _schedule > proc.start() > lib/_emerge/AsynchronousTask.py:34: in start > self._start() > lib/portage/util/_async/AsyncFunction.py:35: in _start > ForkProcess._start(self) > lib/portage/util/_async/ForkProcess.py:61: in _start > retval = self._spawn(self.args, fd_pipes=self.fd_pipes) > lib/portage/util/_async/ForkProcess.py:189: in _spawn > self._proc.start() > /usr/lib/python3.12/multiprocessing/process.py:121: in start > self._popen = self._Popen(self) > /usr/lib/python3.12/multiprocessing/context.py:224: in _Popen > return _default_context.get_context().Process._Popen(process_obj) > /usr/lib/python3.12/multiprocessing/context.py:289: in _Popen > return Popen(process_obj) > /usr/lib/python3.12/multiprocessing/popen_spawn_posix.py:32: in __init__ > super().__init__(process_obj) > /usr/lib/python3.12/multiprocessing/popen_fork.py:19: in __init__ > self._launch(process_obj) > /usr/lib/python3.12/multiprocessing/popen_spawn_posix.py:47: in _launch > reduction.dump(process_obj, fp) > _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ > > obj = <Process name='Process-1' parent=2281947 initial> > file = <_io.BytesIO object at 0x7f22467d6070>, protocol = None > > def dump(obj, file, protocol=None): > '''Replacement for pickle.dump() using ForkingPickler.''' > > ForkingPickler(file, protocol).dump(obj) > E AttributeError: Can't pickle local object 'AuxdbTestCase._test_mod.<locals>.test_func' > > /usr/lib/python3.12/multiprocessing/reduction.py:60: AttributeError > _______________________ AuxdbTestCase.test_flat_hash_md5 _______________________ > > self = <portage.tests.dbapi.test_auxdb.AuxdbTestCase testMethod=test_flat_hash_md5> > > def test_flat_hash_md5(self): > > self._test_mod("portage.cache.flat_hash.md5_database") > > lib/portage/tests/dbapi/test_auxdb.py:19: > _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ > lib/portage/tests/dbapi/test_auxdb.py:80: in _test_mod > loop.run_until_complete(loop.run_in_executor(ForkExecutor(), test_func)) > /usr/lib/python3.12/asyncio/base_events.py:840: in run_in_executor > executor.submit(func, *args), loop=self) > lib/portage/util/futures/executor/fork.py:46: in submit > self._schedule() > lib/portage/util/futures/executor/fork.py:62: in _schedule > proc.start() > lib/_emerge/AsynchronousTask.py:34: in start > self._start() > lib/portage/util/_async/AsyncFunction.py:35: in _start > ForkProcess._start(self) > lib/portage/util/_async/ForkProcess.py:61: in _start > retval = self._spawn(self.args, fd_pipes=self.fd_pipes) > lib/portage/util/_async/ForkProcess.py:189: in _spawn > self._proc.start() > /usr/lib/python3.12/multiprocessing/process.py:121: in start > self._popen = self._Popen(self) > /usr/lib/python3.12/multiprocessing/context.py:224: in _Popen > return _default_context.get_context().Process._Popen(process_obj) > /usr/lib/python3.12/multiprocessing/context.py:289: in _Popen > return Popen(process_obj) > /usr/lib/python3.12/multiprocessing/popen_spawn_posix.py:32: in __init__ > super().__init__(process_obj) > /usr/lib/python3.12/multiprocessing/popen_fork.py:19: in __init__ > self._launch(process_obj) > /usr/lib/python3.12/multiprocessing/popen_spawn_posix.py:47: in _launch > reduction.dump(process_obj, fp) > _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ > > obj = <Process name='Process-2' parent=2281947 initial> > file = <_io.BytesIO object at 0x7f224623f510>, protocol = None > > def dump(obj, file, protocol=None): > '''Replacement for pickle.dump() using ForkingPickler.''' > > ForkingPickler(file, protocol).dump(obj) > E AttributeError: Can't pickle local object 'AuxdbTestCase._test_mod.<locals>.test_func' > > /usr/lib/python3.12/multiprocessing/reduction.py:60: AttributeError > ___________________________ AuxdbTestCase.test_sqite ___________________________ > > self = <portage.tests.dbapi.test_auxdb.AuxdbTestCase testMethod=test_sqite> > > def test_sqite(self): > try: > import sqlite3 > except ImportError: > self.skipTest("sqlite3 import failed") > > self._test_mod("portage.cache.sqlite.database") > > lib/portage/tests/dbapi/test_auxdb.py:29: > _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ > lib/portage/tests/dbapi/test_auxdb.py:80: in _test_mod > loop.run_until_complete(loop.run_in_executor(ForkExecutor(), test_func)) > /usr/lib/python3.12/asyncio/base_events.py:840: in run_in_executor > executor.submit(func, *args), loop=self) > lib/portage/util/futures/executor/fork.py:46: in submit > self._schedule() > lib/portage/util/futures/executor/fork.py:62: in _schedule > proc.start() > lib/_emerge/AsynchronousTask.py:34: in start > self._start() > lib/portage/util/_async/AsyncFunction.py:35: in _start > ForkProcess._start(self) > lib/portage/util/_async/ForkProcess.py:61: in _start > retval = self._spawn(self.args, fd_pipes=self.fd_pipes) > lib/portage/util/_async/ForkProcess.py:189: in _spawn > self._proc.start() > /usr/lib/python3.12/multiprocessing/process.py:121: in start > self._popen = self._Popen(self) > /usr/lib/python3.12/multiprocessing/context.py:224: in _Popen > return _default_context.get_context().Process._Popen(process_obj) > /usr/lib/python3.12/multiprocessing/context.py:289: in _Popen > return Popen(process_obj) > /usr/lib/python3.12/multiprocessing/popen_spawn_posix.py:32: in __init__ > super().__init__(process_obj) > /usr/lib/python3.12/multiprocessing/popen_fork.py:19: in __init__ > self._launch(process_obj) > /usr/lib/python3.12/multiprocessing/popen_spawn_posix.py:47: in _launch > reduction.dump(process_obj, fp) > _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ > > obj = <Process name='Process-3' parent=2281947 initial> > file = <_io.BytesIO object at 0x7f224666e7f0>, protocol = None > > def dump(obj, file, protocol=None): > '''Replacement for pickle.dump() using ForkingPickler.''' > > ForkingPickler(file, protocol).dump(obj) > E AttributeError: Can't pickle local object 'AuxdbTestCase._test_mod.<locals>.test_func' > > /usr/lib/python3.12/multiprocessing/reduction.py:60: AttributeError > _________________________ AuxdbTestCase.test_volatile __________________________ > > self = <portage.tests.dbapi.test_auxdb.AuxdbTestCase testMethod=test_volatile> > > def test_volatile(self): > > self._test_mod("portage.cache.volatile.database", multiproc=False) > > lib/portage/tests/dbapi/test_auxdb.py:22: > _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ > lib/portage/tests/dbapi/test_auxdb.py:80: in _test_mod > loop.run_until_complete(loop.run_in_executor(ForkExecutor(), test_func)) > /usr/lib/python3.12/asyncio/base_events.py:840: in run_in_executor > executor.submit(func, *args), loop=self) > lib/portage/util/futures/executor/fork.py:46: in submit > self._schedule() > lib/portage/util/futures/executor/fork.py:62: in _schedule > proc.start() > lib/_emerge/AsynchronousTask.py:34: in start > self._start() > lib/portage/util/_async/AsyncFunction.py:35: in _start > ForkProcess._start(self) > lib/portage/util/_async/ForkProcess.py:61: in _start > retval = self._spawn(self.args, fd_pipes=self.fd_pipes) > lib/portage/util/_async/ForkProcess.py:189: in _spawn > self._proc.start() > /usr/lib/python3.12/multiprocessing/process.py:121: in start > self._popen = self._Popen(self) > /usr/lib/python3.12/multiprocessing/context.py:224: in _Popen > return _default_context.get_context().Process._Popen(process_obj) > /usr/lib/python3.12/multiprocessing/context.py:289: in _Popen > return Popen(process_obj) > /usr/lib/python3.12/multiprocessing/popen_spawn_posix.py:32: in __init__ > super().__init__(process_obj) > /usr/lib/python3.12/multiprocessing/popen_fork.py:19: in __init__ > self._launch(process_obj) > /usr/lib/python3.12/multiprocessing/popen_spawn_posix.py:47: in _launch > reduction.dump(process_obj, fp) > _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ > > obj = <Process name='Process-4' parent=2281947 initial> > file = <_io.BytesIO object at 0x7f224667e8e0>, protocol = None > > def dump(obj, file, protocol=None): > '''Replacement for pickle.dump() using ForkingPickler.''' > > ForkingPickler(file, protocol).dump(obj) > E AttributeError: Can't pickle local object 'AuxdbTestCase._test_mod.<locals>.test_func' > > /usr/lib/python3.12/multiprocessing/reduction.py:60: AttributeError > =========================== short test summary info ============================ > FAILED lib/portage/tests/dbapi/test_auxdb.py::AuxdbTestCase::test_anydbm - At... > FAILED lib/portage/tests/dbapi/test_auxdb.py::AuxdbTestCase::test_flat_hash_md5 > FAILED lib/portage/tests/dbapi/test_auxdb.py::AuxdbTestCase::test_sqite - Att... > FAILED lib/portage/tests/dbapi/test_auxdb.py::AuxdbTestCase::test_volatile - ... > ============================== 4 failed in 2.35s ===============================
After fixing the unpicklable local functions, there's this: FAILED lib/portage/tests/dbapi/test_auxdb.py::AuxdbTestCase::test_anydbm - TypeError: cannot pickle '_dbm.dbm' object FAILED lib/portage/tests/dbapi/test_auxdb.py::AuxdbTestCase::test_sqite - TypeError: cannot pickle 'module' object
The bug has been referenced in the following commit(s): https://gitweb.gentoo.org/proj/portage.git/commit/?id=d7e64317e3a0d789e17dfea7b451c6b3b6cdb3c0 commit d7e64317e3a0d789e17dfea7b451c6b3b6cdb3c0 Author: Zac Medico <zmedico@gentoo.org> AuthorDate: 2023-10-24 23:52:46 +0000 Commit: Zac Medico <zmedico@gentoo.org> CommitDate: 2023-10-24 23:56:15 +0000 test_auxdb: multiprocessing spawn compat Use staticmethod and functools.partial to avoid unpicklable local functions. Also, don't try to pickle anydbm or sqlite modules since they currently are not picklable. Ultimately, it might be a good idea to implement pickling for the sqlite module. Bug: https://bugs.gentoo.org/916245 Signed-off-by: Zac Medico <zmedico@gentoo.org> lib/portage/tests/dbapi/test_auxdb.py | 103 ++++++++++++++++++++++------------ 1 file changed, 66 insertions(+), 37 deletions(-)
The bug has been closed via the following commit(s): https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=2b9128b401def05cac46f9e6d66048e5a0d888b8 commit 2b9128b401def05cac46f9e6d66048e5a0d888b8 Author: Sam James <sam@gentoo.org> AuthorDate: 2023-10-25 05:48:31 +0000 Commit: Sam James <sam@gentoo.org> CommitDate: 2023-10-25 05:48:40 +0000 sys-apps/portage: add 3.0.54 Closes: https://bugs.gentoo.org/905869 Closes: https://bugs.gentoo.org/915551 Closes: https://bugs.gentoo.org/915896 Closes: https://bugs.gentoo.org/916106 Closes: https://bugs.gentoo.org/916108 Closes: https://bugs.gentoo.org/916112 Closes: https://bugs.gentoo.org/916116 Closes: https://bugs.gentoo.org/916139 Closes: https://bugs.gentoo.org/916141 Closes: https://bugs.gentoo.org/916142 Closes: https://bugs.gentoo.org/916149 Closes: https://bugs.gentoo.org/916182 Closes: https://bugs.gentoo.org/916231 Closes: https://bugs.gentoo.org/916235 Closes: https://bugs.gentoo.org/916240 Closes: https://bugs.gentoo.org/916242 Closes: https://bugs.gentoo.org/916245 Closes: https://bugs.gentoo.org/916248 Closes: https://bugs.gentoo.org/899898 Closes: https://bugs.gentoo.org/906129 Closes: https://bugs.gentoo.org/906156 Closes: https://bugs.gentoo.org/916031 Signed-off-by: Sam James <sam@gentoo.org> sys-apps/portage/Manifest | 1 + sys-apps/portage/portage-3.0.54.ebuild | 238 +++++++++++++++++++++++++++++++++ 2 files changed, 239 insertions(+)